Exemple #1
0
func FxFireDashStop(object target, proplist effect, int reason, bool temporary)
{
	if(temporary)
		return;
	
	target->Unstuck();
	target->SetObjectLayer(nil);
	
	target->SetAction("Jump");
	ExplosionEffect(effect.Size2, target->GetX(), target->GetY(),0,0,0);
	
	for(var o in FindObjects(Find_Distance(effect.Size2, target->GetX(), target->GetY()), Find_Func("CanBeHit", target)))
	{
		if(o->GetOwner() == target->GetOwner())
			continue;
			
		var angle = Angle(target->GetX(), target->GetY(), o->GetX(), o->GetY());
		
		o->AddFireHitEffect();
		o->Fling(Sin(angle, 8), -Cos(angle, 8) - 2);
		target->WeaponDamage(o, effect.SpellDamage2);
	}
	
	target->CastObjects(Flame, RandomX(6,8), RandomX(10,25));
	//effect.marker->RemoveObject();
	//effect.clonk->MakeHitable(true);

}
Exemple #2
0
func Initialize()
{
  var iTimeout,pWipf;
  SetGamma(RGB(15,15,15),RGB(118,118,118),RGB(215,215,215));
  SetSkyParallax(0,15,17,0,0,0,0); 
  //Handgemacht... ;)
  Meeresrauschen(170);
  Meeresrauschen(1100);
  Meeresrauschen(2060);
  Meeresrauschen(2900);
  Meeresrauschen(3800);
  Meeresrauschen(4800);
  Meeresrauschen(5700);
  Moewen(900);
  Moewen(2300);
  Moewen(3900);
  Moewen(5000);
  //Nebel platzieren
  for(var i;i<260;++i) 
    CreateParticle("Fog",Random(LandscapeWidth()),Random(LandscapeHeight()*2/3),RandomX(3,9),0,RandomX(1000,1500));
  //Wipfe platzieren
  while(pWipf=FindObject(WIPF,0,0,0,0,0,0,0,0,pWipf)) {
    iTimeout=0;
    while(Stuck(pWipf)||GetMaterial(GetX(pWipf),GetY(pWipf))!=Material("Tunnel")) {
      SetPosition(Random(LandscapeWidth()),RandomX(LandscapeHeight()*2/3,LandscapeHeight()),pWipf);
      if(iTimeout++ > 50000) { RemoveObject(pWipf); break; }
    }
  }  
  ScriptGo(1);
}
Exemple #3
0
func FxDischargeStart(object target, proplist effect, int temporary)
{
	for(var i = 0; i < 360; i+= 10)
	{
		var props = {
			Size = PV_Linear(4, 0),
			Stretch = 10000,
			Rotation = i + 180,
		    R = pR,
		    G = pG,
		    B = pB,
			BlitMode = GFX_BLIT_Additive,
		};
		
		var x = Sin(i, DischargeSize + RandomX(-2, 2));
		var y = -Cos(i, DischargeSize + RandomX(-2, 2));
		
		var rnd = RandomX(4,20);
		var xdir = Sin(i + 180, rnd);
		var ydir = -Cos(i + 180, rnd);
		
		CreateParticle("Flash", x, y, xdir, ydir, 25, props, 1);
	}
	
}
Exemple #4
0
// Called be the engine: draw the complete map here.
public func InitializeMap(proplist map)
{
	// Initialize the map settings from scenario parameters. If a map is created in god mode
	// these settings are already up to date.
	InitMapSettings();
	
	// Resize the map.
	Resize(Settings_MapWdt, Settings_MapHgt);
	
	// Draw empty map according to type setting.
	if (Settings_MapType == CSETTING_MapType_Empty)
		return true;
	
	// Create the main surface: a rectangle with some turbulence on top.
	var height = [9 * map.Hgt / 20, 9 * map.Hgt / 20, 11 * map.Hgt / 20][Settings_MapType - 1];
	var amplitude = [[0, 10], [0, 18], [0, 40]][Settings_MapType - 1];
	var scale = [[0, 10], [0, 16], [0, 24]][Settings_MapType - 1];
	var rect = {X = 0, Y = height, Wdt = map.Wdt,  Hgt = map.Hgt - height};
	var surface = {Algo = MAPALGO_Rect, X = rect.X, Y = rect.Y, Wdt = rect.Wdt, Hgt = 8 * rect.Hgt / 6};
	surface = {Algo = MAPALGO_Turbulence, Iterations = 4, Amplitude = amplitude, Scale = scale, Seed = Random(65536), Op = surface};
	
	// Draw materials inside the main surface.
	DrawMaterials(rect, surface);
	
	// Draw some sky islands.
	for (var x = RandomX(30, 60); x < map.Wdt - 30; x += RandomX(45, 85))
		DrawSkyIsland(map, x, RandomX(32, 52), RandomX(20, 30), RandomX(18, 24)); 
	
	// Return true to tell the engine a map has been successfully created.
	return true;
}
Exemple #5
0
global func CreateBurnMark(int iX, int iY, int iLevel, int Count) 
{
  var boom;
  if(!ObjectCount(BOOM)) boom = CreateObject(BOOM,0,0,-1);
  else boom = FindObject(BOOM);
  
  var angle=Random(360/Count); //variablen für die überprüfung
  var type;
  for(var z; z < Count; z++)
	{
    angle += Max(1,360/Count);

    // Check: Sky or Solid/Liquid
    var x = iX+Cos(angle,iLevel);
    var y = iY+Sin(angle,iLevel);
    if((GetMaterialVal("Density","Material",GetMaterial(x,y)) != 0) || (GetMaterial(x,y) == -1))
      continue;

    type = 1+Random(3);
    var size = BurnMarkCheck(angle,RandomX(iLevel/2,iLevel*2),iX,iY);
    var sin = Sin(angle,(size-iLevel)/2+iLevel+Random(3));
    var cos = Cos(angle,(size-iLevel)/2+iLevel+Random(3));

    CreateParticle("BurnMark",iX+cos,iY+sin,Cos(angle+RandomX(-5,5),50),Sin(angle+RandomX(-5,5),50),size*5+Random(25),RGBa(0,0,0,64),boom,1); 
  }
}
Exemple #6
0
func Hit()
{
	CastObjects(Flame, RandomX(1,2), RandomX(10,15));
	for(var o in FindObjects(Find_Distance(SpellDamage), Find_Func("CanBeHit", this)))
	{
		o->AddFireHitEffect();
	}
	Explode(SpellDamage);
}
Exemple #7
0
// Spawns a new fish. Called by the old fish.
func Hatch(id fish_id)
{
	for (var i = 0; i < 5; ++i)
		Bubble(1, RandomX(-5, 5), RandomX(-5, 5));
	var fish = CreateObject(fish_id, 0, 0, GetOwner());
	fish->SetCon(1);
	AddEffect("FastGrow", fish, 1, 1, nil, GetID());
	RemoveObject();
}
/* 
 * Better EarthObj Placement. Besides many new parameters it also does the following:
 * - Leaves at least 10 pixels distance between each placed object
 * - Makes sure they are *really* stuck in the material
 * Parameters:
 *
 * objectid:  Object to be placed
 * quantity: Quantity to be planted
 * rect: Target rect as array [x,y,wdt,hgt], Offset in local calls
 * materials: array of materials it should be placed in. If not set, the objects will be placed in Materials with Soil=1
 * nearbymaterials: material the object has to be somewhat close to
 *
 * Returns:
 * Amount of actually placed objects (algo gives up after 10.000 iterations) 
 *
 * Examples:
 *
 * PlaceObjects2(FLNT, 20, 0, LandscapeHeight()/3, LandscapeWidth(), LandscapeHeight()/3, ["Rock", "Granite"])
 * - Places 20 flints inside rock and granite between 33% and 66% landscape height 
 */
global func PlaceObjects2(id objectid, int quantity, array rect, array inmaterials, int nearbymaterial) {
	var x = rect[0], y = rect[1], wdt = rect[2], hgt = rect[3];
	
	var haveinmaterials = GetType(inmaterials) == C4V_Array;
	
	
	// Failsafe
	var attempts = 0;
	var placed = 0;
	
	// Create a dozen random places and try there
	var rndx, rndy, valid, obj, matatpos;
	var objhgt = GetDefHeight(objectid);
	
		
	if (nearbymaterial) {
		while (quantity > 0 && attempts++ < 20000) {
			rndx = x + Random(wdt);
			rndy = y + Random(hgt);
			
			matatpos = GetMaterial(rndx,rndy);
	
			if (matatpos == nearbymaterial) {
				for (var i = 0; i < 8; i++) {
					// Generate a random number between -10 to -4 or 4 to 10
					rndx += RandomX(10, 20) * (Random(2)*2-1);
					rndy += RandomX(10, 20) * (Random(2)*2-1);
					matatpos = GetMaterial(rndx,rndy);
					
					valid = false;
					if (haveinmaterials) {
						for (var mat in inmaterials) {
							if (mat == matatpos && mat != nearbymaterial) { 
								valid = true;
								break;
							}
						}
					} else {
						valid = isMaterialSoil(rndx, rndy);
					}
					
					if (valid) {
						obj = CreateObject(objectid, rndx, rndy + objhgt / 2, -1);
						obj->SetR(Random(360));
					}

					if (Stuck(obj)) {
						placed++;
						quantity--;
						break;
					} else {
						RemoveObject(obj);
					}
				}
			}
		}
	} else {
Exemple #9
0
global func CastBlood()
{
	if(!this) return;
	for(var i = 0; i < 5; ++i)
	{
		var b = CreateObject(FLSH);
		b->SetSpeed(RandomX(-30, 30), RandomX(-30, 0));
		b->SetRDir(RandomX(-50,50));
	}
}
Exemple #10
0
func Hit2()
{
	// Cast flames on impact.
	for (var i = 0; i < 20; i++)
		CastObjects(Flame, 1, 20, RandomX(-3, 3), RandomX(-4, 0));
	// Cast some particles.
		// TODO?
	// Sound effects.
	Sound("Hits::Materials::Glass::GlassBreak");
	Sound("Fire::Inflame");
	Explode(10, true);
}
Exemple #11
0
func Hit()
  {
  if(!GBackLiquid())
    {
    for(var i=15; i>0; i--)
      {
      var iX=Sin(GetR(), RandomX(4,8)), iY=-Cos(GetR(), RandomX(4,8)), iXDir=GetWind()*30/100, iYDir=-Cos(GetR()+RandomX(-2,2), Random(7));
      InsertMaterial(Material("Water"), iX, iY, iXDir, iYDir);
      }
    SetEmpty();
    }
  }
Exemple #12
0
func JumpEffect(object clonk, dir)
{
	var from;
	var to;

	if (dir == "Up")
	{
		from = 50; 
		to = 130;
	}
	if (dir == "Left")
	{
		from = -30; 
		to = 50;
	}
	if (dir == "Right")
	{
		from = 130; 
		to = 210;
	}
	if (dir == "Down")
	{
		from = 230; 
		to = 310;
	}

	Sound("hookjump", false, 30);

	for(var i = from; i < to; i+=5)
	{
		var r = 10;
		var x = clonk->GetX() + Cos(i, r);
		var y = clonk->GetY() + Sin(i, r);
		
		var angle = Angle(0,0,Cos(i, r),Sin(i, r));
		
		var trailparticles =
		{
			//Prototype = Particles_ElectroSpark2(),
			Size = PV_Linear(10,0),
			Rotation = angle,
			R = 150,
			G = 150,
			B = 150,
			OnCollision = PC_Bounce(),
		};
	
		CreateParticle("Shockwave", x, y, Cos(i, r + RandomX(-1,1)), Sin(i, r + RandomX(-1, 1)), 10, trailparticles);
	}
}
Exemple #13
0
func Intro_16()
{
	var x = this.plane->GetX();
	var y = this.plane->GetY();
	this.pilot->Exit();
	Intro_CreateBoompack(RandomX(x-5,x+5), RandomX(y-5,y+5), 160)->Launch(290 + Random(26), this.pilot);
	var clonk;
	while(clonk = this.pilot->Contents())
	{
		clonk->Exit();
		Intro_CreateBoompack(RandomX(x-5,x+5), RandomX(y-5,y+5), 160)->Launch(290 + Random(26), clonk);
	}
	return ScheduleNext(100);
}
Exemple #14
0
func Destruction()
{
	if(partner)
		partner->LoseConnection();
	if(elevator)
		elevator->LostCase();
		
	for(var i = 0; i < 3; ++i)
	{
		var wood = CreateObject(Wood, 0, 0, NO_OWNER);
		wood->Incinerate();
		wood->SetXDir(RandomX(-10, 10));
		wood->SetYDir(RandomX(-2, 0));
	}
}
Exemple #15
0
func Place(int amount, proplist rectangle, proplist settings)
{
	var max_tries = 2 * amount;
	var loc_area = nil;
	if (rectangle) loc_area = Loc_InArea(rectangle);
	var f;
	
	while ((amount > 0) && (--max_tries > 0))
	{
		var spot = FindLocation(Loc_Material("Water"), Loc_Space(20), loc_area);
		if (!spot) continue;
		
		f = CreateObjectAbove(this, spot.x, spot.y, NO_OWNER);
		if (!f) continue;
		// Randomly add some large/slim fish
		if (Random(3))
		{
			// There are naturally smaller and larger fishes. Fishes above around 150 can be clipped, so stay below that.
			f->SetCon(RandomX(75, 140));
			// make sure the smaller ones don't grow larger any more
			f->StopGrowth(); 
			// Slim fish.
			if (f->GetCon() > 100 || !Random(3))
				f->SetYZScale(1000 - Random(300));  
		}
		
		if (f->Stuck())
		{
			f->RemoveObject();
			continue;
		}
		--amount;
	}
	return f; // return last created fish
}
Exemple #16
0
public func Construction()
{
	this.MeshTransformation = Trans_Rotate(Random(360), 0, 1, 0);
	
	var sibling = nil;
	for (var bone in ["bone1", "bone2", "bone3"])
	{
		var transformation;
		var rand = Random(2);
		if (rand == 0) 
			transformation = Trans_Rotate(RandomX(-20, 20), 1, 0, 0);
		else if(rand == 1)
			transformation = Trans_Rotate(RandomX(-20, 20), 0, 0, 1);
		sibling = TransformBone(bone, transformation, 1, Anim_Const(1000), sibling);
	}
}
Exemple #17
0
func Initialize() {
  MarsSky();
  SetSkyAdjust(RGBa(255,255,255,160), RGB(70,30,15));
  //Hintergrund
  CreateObject(BG_1,-0,0,-1);
  CreateObject(DUSK,0,0,-1);
  ScriptGo(1);

  // Spielziel setzen
  var goal = FindObject(RCOB);
  goal->AddType(DBSE);
  goal->AddType(DLAB);
  goal->AddType(DSOL);
  
  //Forschungsstation
  PlaceObjects(DBSE,1,"Durolava",950,1200,150,150);
  PlaceObjects(DLAB,1,"Durolava",950,1200,150,150);
  PlaceObjects(BONE,9,"Durolava",950,1200,150,150);
  PlaceObjects(SKUL,3,"Durolava",950,1200,150,150);    
  PlaceObjects(DSOL,3,"Durolava",950,1200,150,150);   
  PlaceObjects(METL,2,"Durolava",950,1200,150,150);   
  PlaceObjects(CELL,1,"Durolava",950,1200,150,150);   
  PlaceObjects(SATD,1,"Durolava",950,1200,150,150);
  PlaceObjects(ORE1,8,"Durolava",950,1200,150,150);  
  
  // Spouter
  PlaceObjects(OILS, RandomX(1,3), "Oil", 0, 1300, LandscapeWidth(), 300);  
  
  // Kristalle
  PlaceCrystals(5, 20);
  
  return(1);
}
Exemple #18
0
func Initialize()
{
	AddEffect("Sparkle", this, 1, 30 + RandomX(-3, 3), this);
	graphics_index = Random(4);
	if (graphics_index) SetGraphics(Format("%d", graphics_index+1));
	return true;
}
Exemple #19
0
global func FxRandomMeteorTimer()
{
	if (!Random(GetPlayerCount() + 2)) 
		return FX_OK;
	LaunchMeteor(50 + Random(LandscapeWidth() - 100), -10, 40 + Random(40), RandomX(-20, 20), 0);
	return FX_OK;
}
Exemple #20
0
// Called be the engine: draw the complete map here.
protected func InitializeMap(proplist map)
{
	// Retrieve the settings according to the MapSize setting.
	var map_size, main_size, nr_islands;
	if (SCENPAR_MapSize == 1)
	{
		map_size = [240, 200]; main_size = 80; nr_islands = RandomX(6, 7);
	}
Exemple #21
0
func FillCheck()
  {
  ++iTimer;
  if(!(iTimer%5))
    {
    var iX = Sin(GetR(), RandomX(-4,8) );
    var iY = -Cos(GetR(), RandomX(-4,4) );
    if(!Contained())
      CreateParticle("NoGravSpark", iX, iY,0,0,RandomX(25, 55),RGBa(255,255,0,120));
    iTimer=0;
    }
  if(GetMaterial() == Material("Water"))
    {
    if((iFill+=ExtractMaterialAmount(0,2, Material("Water"), 6))>=10 )
      ChangeDef(GBLT);
    }
  }
func Incineration()
{
	if(power_seconds == 0)
		return Extinguish();
	
	
	for(var i = 0; i < 2; ++i)
	{
		var x = -7 + 14 * i;
		var b = CreateObject(Compensator_BurningBattery, x, 6, NO_OWNER);
		b->SetController(GetController()); // killtracing

		b->SetSpeed(-30 + 60 * i + RandomX(-10, 10), RandomX(-50, -30));
	}
	
	Explode(30);
}
Exemple #23
0
func InitClouds()
{
	for(var i = 0; i < 8; i++)
	{
		var cloud = CreateObject(DecoCloud, Random(LandscapeWidth() + 400) - 200, Random(LandscapeHeight()), -1);
		cloud->SetClrModulation(RGBa(255, 128, 0, 40));
		cloud->SetXDir(RandomX(1, 3));
	}
}
Exemple #24
0
private func Timer()
{
  // Positionen
  var x0 = GetX(GetActionTarget(1)), y0 = GetY(GetActionTarget(1)), 
  x1 = GetX(GetActionTarget(0)), y1 = GetY(GetActionTarget(0));
  // Einzelne Vertexe mit Partikeln verschönern
  var i=0;
  var iVtxNum = GetVertexNum();
  while(i<iVtxNum)
  {
    SetVertex(i, 0, (x0+(x1-x0)*i/iVtxNum)+RandomX(5,-5)); 
    SetVertex(i, 1, (y0+(y1-y0)*i/iVtxNum)+RandomX(5,-5));
    DrawParticleLine ("LightningSpark", GetVertex(i)-GetX(), GetVertex(i, 1)-GetY(), 
		    GetVertex(i+1)-GetX(), GetVertex(i+1,1)-GetY(), 6, 60, RGB(250,0,0), RGB(250,0,0));
    DrawParticleLine ("BloodSpark", GetVertex(i)-GetX(), GetVertex(i, 1)-GetY(), 
		    GetVertex(i+1)-GetX(), GetVertex(i+1,1)-GetY(),  3, 25, RGB(250,100,100), RGB(250,100,100));
    i++;
  }
}
Exemple #25
0
func FxBlockedTimer(object target, proplist fx, int time)
{
	if(time >= BlockDur)
		return -1;
	
	var lightning =
	{
		Prototype = Particles_ElectroSpark2(),
		Size = PV_Linear(PV_Random(3,6),0),
		BlitMode = GFX_BLIT_Additive,
		Rotation = PV_Random(0,360),
		R = 100,
		G = 100,
		B = pB,
		Attach = ATTACH_Front,
	};
	
	target->CreateParticle("Lightning", RandomX(-6, 6), RandomX(-6, 6), 0, 0, 20, lightning, 3);
}
Exemple #26
0
func FxTimeHitTimer(object target, proplist effect, int time)
{
	var lightning =
	{
		Prototype = Particles_ElectroSpark2(),
		Size = PV_Linear(PV_Random(2,5),0),
		BlitMode = GFX_BLIT_Additive,
		Rotation = PV_Random(0,360),
		R = 255,
		G = 150,
		B = 50,
		Attach = ATTACH_Front | ATTACH_MoveRelative,
	};
	
	target->CreateParticle("Lightning", RandomX(-5, 5), RandomX(-10, 10), 0, 0, 10, lightning, 2);
	
	if(time > 40)
		return -1;
}
Exemple #27
0
func FillCheck()
  {
  if(!Contained())
      if(Inside(GetR(), 20, 340))
        Hit();
    if(!(iTimer%5))
    {
    var iX = Sin(GetR(), RandomX(-4,4) );
    var iY = -Cos(GetR(), RandomX(-4,1) );
    if(!Contained())
      CreateParticle("NoGravSpark", iX, iY,0,0,RandomX(25, 55),RGBa(255,255,0,120));
    }
  iTimer++;
  if(iTimer>=17)
    {
    if(GetOCF(Contained()) & OCF_CrewMember())
      DoEnergy(+1, Contained());
    iTimer=0;
    }
  return(1);
  }
Exemple #28
0
global func FxSmokeTrailTimer(object pTarget, int iEffectNumber, int iEffectTime)
{
  var iStrength = EffectVar(0, pTarget, iEffectNumber);
  var iAStr = EffectVar(1, pTarget, iEffectNumber);
  var iX = EffectVar(2, pTarget, iEffectNumber);
  var iY = EffectVar(3, pTarget, iEffectNumber);
  var iXDir = EffectVar(4, pTarget, iEffectNumber);
  var iYDir = EffectVar(5, pTarget, iEffectNumber);

  iAStr = Max(1,iAStr-iAStr/10+Random(2));
  iAStr--;
  iYDir += GetGravity()*2/3;
  iYDir += GetWind(iX,iY)/20;

  var xdir = iXDir*iAStr/iStrength;
  var ydir = iYDir*iAStr/iStrength;

  // Neu: Random
  iX += RandomX(-3,3);
  iY += RandomX(-3,3);
  
  // zuerst zeichnen
  CreateParticle("Smoke3",iX,iY,RandomX(-2,2),RandomX(-2,2)-3,20+iAStr*8,RGBa(128,128,128,55+35*iAStr/iStrength));
  CreateParticle("Blast",iX,iY,0,0,10+iAStr*8,RGBa(250,100+Random(100),100,160));

  // dann nächste position berechnen
  iX += xdir/100;
  iY += ydir/100;
  
  if(GBackSemiSolid(iX,iY))
    return -1;
  if(iAStr <= 1)
    return -1;
    
  EffectVar(1, pTarget, iEffectNumber) = iAStr;
  EffectVar(2, pTarget, iEffectNumber) = iX;
  EffectVar(3, pTarget, iEffectNumber) = iY;
  EffectVar(5, pTarget, iEffectNumber) = iYDir;
}
Exemple #29
0
global func FxIntIntroTimer(object target, proplist effect, int time)
{
	if(effect.Time == 40)
	{
		effect.Sister->SetCommand("MoveTo", effect.Sister, effect.Cabin->GetX() + 65 - effect.Sister->GetX(), effect.Cabin->GetY() + 10 - effect.Sister->GetY());
	}

	if(effect.Time == 110)
		effect.Dialog->MessageBoxAll("$MsgIntro1$", effect.Sister);

	if(effect.Time == 150)
	{
		for(var crew in effect.Players)
		{
			crew = crew->Contained();

			crew->SetCommand("Exit", crew);
			crew->AppendCommand("MoveTo", crew, effect.Cabin->GetX() + RandomX(10,40) - crew->GetX(), effect.Cabin->GetY() - crew->GetY());
		}
	}

	if(effect.Time == 200)
		effect.Dialog->MessageBoxAll("$MsgIntro2$", GetCrew(GetPlayerByIndex(Random(GetPlayerCount())), 0));

	if(effect.Time == 270)
	{
		effect.Dialog->MessageBoxAll("$MsgIntro3$", effect.Sister);
	}

	if(effect.Time == 350)
	{
		effect.Sister->SetCommand("MoveTo", effect.Sister, 214 - effect.Sister->GetX(), 540 - effect.Sister->GetY());
	}

	if(effect.Time == 370)
	{
		for(var crew in effect.Players)
		{
			crew = crew->Contained();
			crew->SetCommand("MoveTo", crew, 245 - crew->GetX(), 555 - crew->GetY());
		}
	}

	if(effect.Time == 500)
	{
		effect.Sister->SetCommand("MoveTo", effect.Sister, 214 - effect.Sister->GetX(), 540 - effect.Sister->GetY());
		for(var crew in effect.Players)
			crew->Contained()->SetDir(DIR_Left);
		effect.Dialog->MessageBoxAll("$MsgIntro4$", GetCrew(GetPlayerByIndex(Random(GetPlayerCount())), 0));
	}
Exemple #30
0
func ChargeEffect(proplist params)
{
	var clonk = params.clonk;

	for(var i = 0; i < 360; i+= RandomX(3,15))
	{
		if(!Random(10))
		{
			var props =
			{
				Prototype = Particles_FireTrail(),
				Size = PV_Linear(10,0),
				BlitMode = GFX_BLIT_Additive,
				OnCollision=nil,
				CollisionVertex=nil
			};
			
			var xdir = Sin(i + 180, RandomX(15, 30));
			var ydir = -Cos(i + 180, RandomX(15, 30));
			
			CreateParticle("Fire", clonk->GetX() - GetX() + Sin(i, 30), clonk->GetY() - GetY() - Cos(i, 30), PV_Random(xdir -2, xdir + 2), PV_Random(ydir - 2 , ydir + 2), 20, props, 2);
		}
	}
}