forked from Mirrors/openclonk
127 lines
3.1 KiB
C
127 lines
3.1 KiB
C
/**
|
|
Earthquake
|
|
Trembles the earth.
|
|
|
|
@author Maikel
|
|
*/
|
|
|
|
|
|
/*-- Disaster Control --*/
|
|
|
|
public func SetChance(num chance)
|
|
{
|
|
if (this != Earthquake)
|
|
return;
|
|
var effect = GetEffect("IntEarthquakeControl");
|
|
if (!effect)
|
|
effect = AddEffect("IntEarthquakeControl", nil, 100, 20, nil, Earthquake);
|
|
effect.chance = chance;
|
|
return;
|
|
}
|
|
|
|
public func GetChance()
|
|
{
|
|
if (this != Earthquake)
|
|
return;
|
|
var effect = GetEffect("IntEarthquakeControl");
|
|
if (effect)
|
|
return effect.chance;
|
|
return;
|
|
}
|
|
|
|
protected func FxIntEarthquakeControlTimer(object target, proplist effect, int time)
|
|
{
|
|
if (Random(100) < effect.chance && !Random(10))
|
|
LaunchEarthquake(Random(LandscapeWidth()), Random(LandscapeHeight()), Random(40) + 35);
|
|
return FX_OK;
|
|
}
|
|
|
|
// Launches an earthquake with epicenter (x,y).
|
|
global func LaunchEarthquake(int x, int y, int strength)
|
|
{
|
|
// Earthquake should start in solid.
|
|
if (!GBackSemiSolid(x, y))
|
|
return false;
|
|
// Minimum strength is 15, maximum strength is 100.
|
|
strength = BoundBy(strength, 15, 100);
|
|
// The earthquake is handled by a global effect.
|
|
var effect = AddEffect("IntEarthquake", nil, 100, 1, nil, Earthquake);
|
|
effect.x = x; // Epicentre x coordinate.
|
|
effect.y = y; // Epicentre y coordinate.
|
|
effect.strength = strength / 3; // Earthquake strength.
|
|
effect.length = 3 * strength / 2; // Earthquake length.
|
|
return true;
|
|
}
|
|
|
|
/*-- Earthquake --*/
|
|
|
|
protected func FxIntEarthquakeStart(object target, effect)
|
|
{
|
|
// Start sound at quake local coordinates.
|
|
// < Maikel> Global until someone implements non-object local sounds
|
|
Sound("Earthquake", true, 100, nil, 1);
|
|
return FX_OK;
|
|
}
|
|
|
|
protected func FxIntEarthquakeStop(object target, effect)
|
|
{
|
|
// Stop sound.
|
|
Sound("Earthquake", true, 100, nil, -1);
|
|
return FX_OK;
|
|
}
|
|
|
|
protected func FxIntEarthquakeTimer(object target, effect, int time)
|
|
{
|
|
// Time is up?
|
|
if (time > effect.length)
|
|
return FX_Execute_Kill;
|
|
// Some randomness.
|
|
if (Random(3))
|
|
return FX_OK;
|
|
// Get strength.
|
|
var str = effect.strength;
|
|
// Get quake coordinates.
|
|
var x = effect.x;
|
|
var y = effect.y;
|
|
var l = 4 * str;
|
|
// Shake viewport.
|
|
if (!Random(10))
|
|
ShakeViewPort(str, x, y);
|
|
// Shake ground & objects.
|
|
ShakeFree(x, y, Random(str / 2) + str / 5 + 5);
|
|
for (var obj in FindObjects(Find_NoContainer(), Find_OCF(OCF_Alive), Find_InRect(x - l, y - l, l, l)))
|
|
{
|
|
if (Random(3)) continue;
|
|
if (!obj->GetAction()) continue;
|
|
var act = obj.ActMap[obj->GetAction()];
|
|
if (act.Attach || (act.Procedure
|
|
&& act.Procedure != DFA_FLIGHT
|
|
&& act.Procedure != DFA_LIFT
|
|
&& act.Procedure != DFA_FLOAT
|
|
&& act.Procedure != DFA_ATTACH
|
|
&& act.Procedure != DFA_CONNECT))
|
|
//if (!MatVehicle(obj->Shape.AttachMat))
|
|
obj->Fling(Random(3)-1);
|
|
}
|
|
// Move the quake around a little.
|
|
var dx, dy, cnt = 0;
|
|
do
|
|
{ // Try ten times to find a nearby in material location.
|
|
dx = Random(str * 4 + 1) - str * 2;
|
|
dy = Random(str * 4 + 1) - str * 2;
|
|
cnt++;
|
|
} while (!GBackSemiSolid(x + dx, y + dy) && cnt < 10)
|
|
// No continuation.
|
|
if (cnt >= 10)
|
|
return FX_Execute_Kill;
|
|
// Set new position.
|
|
effect.x += dx;
|
|
effect.y += dy;
|
|
// Done.
|
|
return FX_OK;
|
|
}
|
|
|
|
/*-- Proplist --*/
|
|
|
|
local Name = "$Name$";
|