openclonk/planet/Objects.ocd/Environment.ocd/Meteor.ocd/Script.c

138 lines
3.2 KiB
C

/**
Meteor
A burning rock falling from the sky, explodes on impact.
@author Maikel
*/
/*-- Disaster Control --*/
public func SetChance(num chance)
{
if (this != Meteor)
return;
var effect = GetEffect("IntMeteorControl");
if (!effect)
effect = AddEffect("IntMeteorControl", nil, 100, 20, nil, Meteor);
effect.chance = chance;
return;
}
public func GetChance()
{
if (this != Meteor)
return;
var effect = GetEffect("IntMeteorControl");
if (effect)
return effect.chance;
return;
}
protected func FxIntMeteorControlTimer(object target, proplist effect, int time)
{
if (Random(100) < effect.chance && !Random(10))
{
// Launch a meteor.
var meteor = CreateObject(Meteor);
var x = Random(LandscapeWidth());
var y = 0;
var size = RandomX(60, 90);
var xdir = RandomX(-22, 22);
var ydir = RandomX(28, 36);
meteor->Launch(x, y, size, xdir, ydir);
}
return FX_OK;
}
global func LaunchMeteor(float x, float y, num size, float xdir, float ydir)
{
var meteor = CreateObject(Meteor);
return meteor->Launch(x, y, size, xdir, ydir);
}
/*-- Meteor --*/
public func Launch(float x, float y, num size, float xdir, float ydir)
{
// Launch from indicated position.
SetPosition(x, y);
// Set the meteor's size.
SetCon(BoundBy(size, 20, 100));
// Set the initial velocity.
SetXDir(xdir);
SetYDir(ydir);
// Set random rotation.
SetR(Random(360));
SetRDir(RandomX(-10, 10));
// Safety check.
if (!IsLaunchable())
return false;
// Set right action.
AddEffect("IntMeteor", this, 100, 1, this);
return true;
}
private func IsLaunchable()
{
if (GBackSemiSolid() || Stuck())
{
RemoveObject();
return false;
}
return true;
}
protected func FxIntMeteorTimer()
{
var size = GetCon();
// Air drag.
var ydir = GetYDir(100);
ydir -= size * ydir ** 2 / 11552000; // Magic number.
SetYDir(ydir, 100);
// Smoke trail.
CreateParticle("ExploSmoke", Random(5)-2, Random(5)-2, Random(3)-1, Random(3)-1, size + RandomX(-20,20), RGBa(130,130,130,90));
CreateParticle("FireballSmoke", 0, 0, Random(3)-1, Random(3)-1, RandomX(120,180), RGBa(100,100,100,70));
// Fire trail.
CreateParticle("MagicSpark", 0, 0, Sin(Random(360),RandomX(15,33)), Cos(Random(360), RandomX(15,33)), RandomX(30,70), RGB(255,255,255));
for (var i = 0; i < 6; i++)
{
var theta = RandomX(-45, 45);
var x = Sin(theta, size / 8);
var y = Cos(theta, size / 8);
CreateParticle("MagicFire", x, y, Random(3)-1, Random(3)-1 ,RandomX(50, 90), HSL(Random(50), 200+Random(25), Random(100)));
}
// Sound.
// Burning and friction decrease size.
if (!Random(5))
DoCon(-1);
// Removal if size < 10.
if (size < 10)
RemoveObject();
return 1;
}
protected func Hit(float xdir, float ydir)
{
var size = 10 + GetCon();
var speed2 = 20 + (xdir ** 2 + ydir ** 2) / 10000;
// Some fire sparks.
for (var i = 0; i < 6; i++)
{
var theta = RandomX(135, 225);
var x = Sin(theta, size / 8);
var y = Cos(theta, size / 8);
CreateParticle("MagicFire", x, y, Random(3)-1, Random(3)-1 ,RandomX(50, 90), HSL(Random(50), 200+Random(25), Random(100)));
}
// Explode meteor, explode size scales with the energy of the meteor.
var dam = size * speed2 / 750;
dam = BoundBy(dam, 5, 30);
Explode(dam);
return;
}
/*-- Proplist --*/
local Name = "$Name$";