openclonk/planet/Objects.ocd/Helpers.ocd/ItemSpark.ocd/Script.c

226 lines
5.0 KiB
C

/*-- Item Spark --*/
/*
global func StartItemSparks(int rate, bool mirror)
starts the spawning of sparks.
rate is the average frequency and ranges from 0 to 1000.
if mirror is true, the sparks are mirrored along LandscapeWidth()/2
global func StopItemSparks()
self-explanatory
scenario callbacks:
func GetSparkItem(int x, int y)
returns the item ID one spark should spawn.
called at the creation of the sparks (x=nil, y=nil) for mirrored sparks and on Hit() again, if it returned nil before
func GetSparkRange()
returns the area where the sparks spawn as an array, standard equals return [0, LandscapeWidth()]
func SetupSparkItem(object obj)
called after an item is spawned. Can be used to put arrows into bows, for example
*/
local Plane = 300;
local toSpawn;
static ItemSpark_particle;
static ItemSpark_particle_additive;
global func StartItemSparks(int rate, bool mirror)
{
AddEffect("GlobalItemSparks", nil, 1, 5, nil, nil, rate, mirror);
}
global func StopItemSparks()
{
RemoveEffect("GlobalItemSparks");
}
global func FxGlobalItemSparksStart(_, effect, temp, rate, mir)
{
if(temp) return;
effect.rate=rate;
effect.mirror=mir;
}
global func FxGlobalItemSparksTimer(_, effect, time)
{
if(Random(1000) >= effect.rate) return;
var range=GameCall("GetSparkRange");
var max, start;
if(range != nil)
{
start=range[0];
max=range[1]-start;
if(effect.mirror) if(max>LandscapeWidth()) max=LandscapeWidth();
}
else
{
max=LandscapeWidth();
start=0;
}
if(effect.mirror){ max/=2; if(Random(2)) start=LandscapeWidth()/2;}
var x=Random(max)+start;
var failsafe=0;
while(failsafe++ < 100 && GBackSolid(x, 1)) x=Random(max)+start;
if(failsafe >= 100) return;
// mirrors requires free sky
var what=GameCall("GetSparkItem", nil, nil);
var count=0;
if(effect.mirror)
{
if(x > LandscapeWidth()/2)
{
x-=LandscapeWidth()/2;
x=LandscapeWidth()/2-x;
}
count=2;
var s=CreateObjectAbove(ItemSpark, LandscapeWidth()-x, 1, NO_OWNER);
s.toSpawn=what;
}
var s=CreateObjectAbove(ItemSpark, x, 1, NO_OWNER);
s.toSpawn=what;
}
global func FxGlobalItemSparksSaveScen(_, effect, props)
{
props->Add("Sparks", "StartItemSparks(%d, %v)", effect.rate, effect.mirror);
return true;
}
protected func Initialize()
{
if (!ItemSpark_particle)
{
ItemSpark_particle =
{
Size = PV_Linear(15, 0),
Rotation = PV_Step(1, PV_Random(0, 90)),
Alpha = PV_Linear(0, 255),
R = PV_Random(0, 50),
G = PV_Random(0, 50),
B = PV_Random(200, 255),
Attach = ATTACH_Back,
CollisionVertex = 500,
OnCollision = PC_Die()
};
ItemSpark_particle_additive =
{
Prototype = ItemSpark_particle,
BlitMode = GFX_BLIT_Additive,
Attach = ATTACH_Front
};
}
AddEffect("Sparkle", this, 1, 2, this);
AddEffect("CheckStuck", this, 1, 30);
}
func FxCheckStuckTimer(_, effect)
{
if(!GBackSolid(0, 1)) return 1;
DoSpawn();
return -1;
}
func FxSparkleTimer(_, effect)
{
CreateParticle("ItemSpark", PV_Random(0, GetXDir()/10), PV_Random(0, GetYDir()/10), GetXDir(), GetYDir(), 36, ItemSpark_particle, 5);
CreateParticle("ItemSpark", PV_Random(0, GetXDir()/10), PV_Random(0, GetYDir()/10), GetXDir(), GetYDir(), 20, ItemSpark_particle_additive, 5);
if(!Random(36))
for(var i=0;i<3;++i)
{
var e=AddEffect("SparkleDeath", nil, 5, 1, nil, GetID());
e.x=GetX();
e.y=GetY();
e.velX=RandomX(-10,10);
e.velY=RandomX(-2,2);;
e.size=40+Random(10);
e.from=this;
e.vAcc=1;
}
}
func FxSparkleDeathStart(_, effect, temp, x, y, velX, velY, size)
{
if(temp) return;
effect.target=_;
effect.xT=0;
effect.yT=0;
}
func FxSparkleDeathTimer(_, effect, effect_time)
{
if(effect.size <= 5) return -1;
if(GBackSolid(AbsX(effect.x), AbsY(effect.y)))
{
effect.velX*=-1;
effect.velY*=-1;
}
effect.from->CreateParticle("ItemSpark", AbsX(effect.x), AbsY(effect.y), 0, 0, 18, ItemSpark_particle, 1);
effect.from->CreateParticle("ItemSpark", AbsX(effect.x), AbsY(effect.y), 0, 0, 10, ItemSpark_particle_additive, 1);
effect.xT+=effect.velX;
effect.yT+=effect.velY;
effect.velY+=effect.vAcc;
var f=0;
while(Abs(effect.xT) > 10){if(effect.xT > 0) f=1; else f=-1; effect.x+=f; effect.xT-=f*10;}
while(Abs(effect.yT) > 10){if(effect.yT > 0) f=1; else f=-1; effect.y+=f; effect.yT-=f*10;}
effect.size-=2;
}
func DoSpawn()
{
if(toSpawn == nil)
toSpawn=GameCall("GetSparkItem", GetX(), GetY());
var item = CreateObjectAbove(toSpawn, 0, 0, NO_OWNER);
if (item)
{
item->SetYDir(-1);
GameCall("SetupSparkItem", item);
}
for(var cnt=0;cnt<5;++cnt)
{
var effect=AddEffect("SparkleDeath", nil, 5, 1, nil, GetID());
effect.x=GetX();
effect.y=GetY();
effect.velX=RandomX(-10,10);
effect.velY=RandomX(-50,-30);
effect.size=25+Random(10);
effect.from=this;
effect.vAcc=5;
}
AddEffect("Off", this, 1, 30*4, this);
RemoveEffect("Sparkle", this);
this.Plane=501;
}
func FxOffStop(_, effect, reason, temp)
{
if(temp) return;
if(this) RemoveObject();
}
func Hit()
{
if(GetEffect("Off", this)) return SetSpeed();
DoSpawn();
}
func SaveScenarioObject() { return false; }