1 /**
2 	IronBomb
3 	Explodes after a short fuse. Explodes on contact if shot by the grenade launcher.
4 
5 	@author Ringwaul, Clonkonaut
6 */
7 
8 // If true, explodes on contact.
9 local armed;
10 
ControlUse(object clonk,int x,int y)11 public func ControlUse(object clonk, int x, int y)
12 {
13 	// If already activated, nothing (so, throw).
14 	if (GetEffect("FuseBurn", this))
15 	{
16 		clonk->ControlThrow(this, x, y);
17 		return true;
18 	}
19 	Fuse();
20 	return true;
21 }
22 
Fuse(bool explode_on_hit)23 public func Fuse(bool explode_on_hit)
24 {
25 	armed = explode_on_hit;
26 	AddEffect("FuseBurn", this, 1, 1, this);
27 	return;
28 }
29 
FuseTime()30 public func FuseTime() { return 90; }
31 
IsFusing()32 public func IsFusing() { return !!GetEffect("FuseBurn", this); }
33 
OnCannonShot(object cannon)34 public func OnCannonShot(object cannon)
35 {
36 	return Fuse(true);
37 }
38 
FxFuseBurnStart(object target,effect fx,int temp)39 public func FxFuseBurnStart(object target, effect fx, int temp)
40 {
41 	if (temp)
42 		return FX_OK;
43 	Sound("Fire::FuseLoop", {loop_count = +1});
44 	return FX_OK;
45 }
46 
47 
FxFuseBurnTimer(object target,effect fx,int time)48 public func FxFuseBurnTimer(object target, effect fx, int time)
49 {
50 	// Emit some smoke from the fuse hole.
51 	var i = 3;
52 	var x = +Sin(GetR(), i);
53 	var y = -Cos(GetR(), i);
54 	CreateParticle("Smoke", x, y, x, y, PV_Random(18, 36), Particles_Smoke(), 2);
55 	// Explode if time is up.
56 	if (time >= FuseTime())
57 	{
58 		DoExplode();
59 		return FX_Execute_Kill;
60 	}
61 	return FX_OK;
62 }
63 
FxFuseBurnStop(object target,effect fx,int reason,bool temp)64 public func FxFuseBurnStop(object target, effect fx, int reason, bool temp)
65 {
66 	if (temp)
67 		return FX_OK;
68 	Sound("Fire::FuseLoop", {loop_count = -1});
69 	return FX_OK;
70 }
71 
DoExplode()72 public func DoExplode()
73 {
74 	// Cast lots of shrapnel.
75 	var shrapnel_count = 20;
76 	for (var cnt = 0; cnt < shrapnel_count; cnt++)
77 	{
78 		var shrapnel = CreateObjectAbove(Shrapnel);
79 		shrapnel->SetVelocity(Random(359), RandomX(100, 140));
80 		shrapnel->SetRDir(-30 + Random(61));
81 		shrapnel->Launch(GetController());
82 		CreateObject(BulletTrail)->Set(shrapnel, 2, 30);
83 	}
84 	if (GBackLiquid())
85 		Sound("Fire::BlastLiquid2");
86 	else
87 		Sound("Fire::BlastMetal");
88 	CreateParticle("Smoke", PV_Random(-30, 30), PV_Random(-30, 30), 0, 0, PV_Random(40, 60), Particles_Smoke(), 60);
89 	Explode(28);
90 	return;
91 }
92 
Hit(int x,int y)93 protected func Hit(int x, int y)
94 {
95 	if (armed)
96 		return DoExplode();
97 	return StonyObjectHit(x,y);
98 }
99 
Incineration(int caused_by)100 protected func Incineration(int caused_by)
101 {
102 	Extinguish();
103 	Fuse();
104 	SetController(caused_by);
105 	return;
106 }
107 
108 // Drop fusing bomb on death to prevent explosion directly after respawn
IsDroppedOnDeath(object clonk)109 public func IsDroppedOnDeath(object clonk)
110 {
111 	return !!GetEffect("FuseBurn", this);
112 }
113 
HasExplosionOnImpact()114 public func HasExplosionOnImpact() { return armed; }
115 
IsWeapon()116 public func IsWeapon() { return true; }
IsArmoryProduct()117 public func IsArmoryProduct() { return true; }
IsGrenadeLauncherAmmo()118 public func IsGrenadeLauncherAmmo() { return true; }
IsExplosive()119 public func IsExplosive() { return true; }
120 
121 /*-- Properties --*/
122 
123 local Name = "$Name$";
124 local Description = "$Description$";
125 local Collectible = true;
126 local BlastIncinerate = 1;
127 local ContactIncinerate = 1;
128 local Components = {Firestone = 1, Metal = 1};