1 /*
2 	Zap
3 
4 	Author: Clonkonaut
5 
6 	Protects its hive!
7 */
8 
9 #include Library_InsectSwarm
10 
11 local lib_swarm_standard = 5;
12 local swarm_enraged = 20;
13 local lib_swarm_density = 5;
14 local lib_insect_max_dist = 100;
15 
16 local home;
17 local enraged;
18 local enrage_target;
19 local sting_damage = 2;
20 
21 // Called by the zaphive
SetHome(object my_castle)22 public func SetHome(object my_castle)
23 {
24 	home = my_castle;
25 	this->CreateSwarm(lib_swarm_standard);
26 }
27 
28 // Called by the zaphive
SetEnraged()29 public func SetEnraged()
30 {
31 	this->CreateSwarm(swarm_enraged);
32 	SwarmCall("SetEnragedSwarm");
33 }
34 
35 // Called by swarm helper
SetEnragedSwarm()36 public func SetEnragedSwarm()
37 {
38 	enraged = true;
39 	SetAction("Attack");
40 }
41 
Initialize()42 private func Initialize()
43 {
44 	SetAction("Fly");
45 	SetPhase(Random(3));
46 
47 	_inherited(...);
48 }
49 
Death()50 private func Death()
51 {
52 	_inherited(...);
53 	RemoveObject();
54 }
55 
MissionComplete()56 private func MissionComplete()
57 {
58 	if (enraged)
59 		MoveToTarget();
60 	else
61 		_inherited(...);
62 }
63 
Sleep()64 private func Sleep()
65 {
66 	if (enraged) return MoveToTarget();
67 	if (lib_insect_sleeping) return;
68 
69 	if (lib_insect_going2sleep)
70 	{
71 		SetAction("Sleep");
72 		lib_insect_sleeping = true;
73 		return;
74 	}
75 	// One last trip, then become invisible
76 	MoveToTarget();
77 	// Insect might have been removed.
78 	if (this)
79 		lib_insect_going2sleep = true;
80 }
81 
SleepComplete()82 private func SleepComplete()
83 {
84 	SetAction("Sleep");
85 	_inherited(...);
86 }
87 
WakeUp()88 private func WakeUp()
89 {
90 	SetAction("Fly");
91 	_inherited(...);
92 }
93 
GetAttraction(proplist coordinates)94 private func GetAttraction(proplist coordinates)
95 {
96 	if (enraged) return Enrage(coordinates);
97 	if (!home)
98 	{
99 		HomeIsLost();
100 		return false;
101 	}
102 	// GetAttraction will only be called for the swarm master, perfect to have just one being make sound
103 	if(!Random(20))
104 		Sound("Animals::Zap::Zap?", nil,nil,nil,nil, 200, Random(100));
105 
106 	coordinates.x = home->GetX() + Random(20)-10;
107 	coordinates.y = home->GetY() + Random(20)-10;
108 	return true;
109 }
110 
HomeIsLost()111 private func HomeIsLost()
112 {
113 	if (!Random(2)) Kill();
114 }
115 
Enrage(proplist coordinates)116 private func Enrage(proplist coordinates)
117 {
118 	if (!enrage_target)
119 		CheckTarget();
120 	if (!this)
121 		return false;
122 	if (!enrage_target)
123 		return false;
124 	if (ObjectDistance(enrage_target) < 10)
125 		return Sting();
126 
127 	if (!(enrage_target->GetAlive())) return Kill();
128 	if (enrage_target->Contained())
129 	{
130 		if (!Random(25)) return Kill();
131 		return false;
132 	}
133 	if (!Random(50)) return Kill();
134 	if (!GBackSky() && !Random(25)) return Kill();
135 
136 	coordinates.x = enrage_target->GetX();
137 	coordinates.y = enrage_target->GetY();
138 	return true;
139 }
140 
Sting()141 private func Sting()
142 {
143 	if (!enrage_target) return false;
144 
145 	Punch(enrage_target, sting_damage);
146 	Kill();
147 	return true;
148 }
149 
150 // Look for a target to attack
CheckTarget()151 private func CheckTarget()
152 {
153 	var clonk = FindObject(Find_Distance(200), Find_OCF(OCF_CrewMember), Find_OCF(OCF_Alive), Find_NoContainer(), Find_PathFree(), Sort_Distance());
154 	if (clonk)
155 	{
156 		SwarmCall("DoAttack", clonk);
157 		return;
158 	}
159 	if (!Random(10)) Kill();
160 }
161 
DoAttack(object to_kill)162 public func DoAttack(object to_kill)
163 {
164 	enrage_target = to_kill;
165 }
166 
CheckTurn()167 private func CheckTurn()
168 {
169 	if (GetXDir() < 0)
170 		SetDir(DIR_Left);
171 	if (GetXDir() > 0)
172 		SetDir(DIR_Right);
173 }
174 
AngryBuzz()175 private func AngryBuzz()
176 {
177 	Sound("Animals::Zap::Zap?", {pitch = -Random(100)});
178 }
179 
180 /*-- Saving --*/
181 
SaveScenarioObject(proplist props)182 public func SaveScenarioObject(proplist props)
183 {
184 	if (!inherited(props, ...)) return false;
185 	// Ignore some fast-changing stuff
186 	props->Remove("XDir");
187 	props->Remove("YDir");
188 	props->Remove("Command");
189 	return true;
190 }
191 
192 /* Definition */
193 
194 local ActMap = {
195 	Fly = {
196 		Prototype = Action,
197 		Name = "Fly",
198 		Procedure = DFA_FLOAT,
199 		Speed = 100,
200 		Accel = 5,
201 		Decel = 5,
202 		Directions = 2,
203 		FlipDir = 1,
204 		Length = 3,
205 		Delay = 2,
206 		X = 0,
207 		Y = 0,
208 		Wdt = 2,
209 		Hgt = 2,
210 		NextAction = "Fly",
211 		EndCall = "CheckTurn",
212 	},
213 	Attack = {
214 		Prototype = Action,
215 		Name = "Attack",
216 		Procedure = DFA_FLOAT,
217 		Speed = 200,
218 		Accel = 30,
219 		Decel = 30,
220 		Directions = 2,
221 		FlipDir = 1,
222 		Length = 3,
223 		Delay = 2,
224 		X = 0,
225 		Y = 0,
226 		Wdt = 2,
227 		Hgt = 2,
228 		NextAction = "Attack",
229 		StartCall = "AngryBuzz",
230 		EndCall = "CheckTurn",
231 	},
232 	Sleep = {
233 		Prototype = Action,
234 		Name = "Sleep",
235 		Procedure = DFA_FLOAT,
236 		Speed = 0,
237 		Directions = 2,
238 		FlipDir = 1,
239 		Length = 1,
240 		Delay = 1,
241 		X = 6,
242 		Y = 0,
243 		Wdt = 2,
244 		Hgt = 2,
245 		NextAction = "Hold",
246 	},
247 };
248 
249 local Name = "$Name$";
250 local MaxEnergy = 30000;
251 local MaxBreath = 250;
252 local Placement = 2;
253 local NoBurnDecay = true;
254 local BorderBound = C4D_Border_Sides | C4D_Border_Top | C4D_Border_Bottom;
255 local ContactCalls = true;
256