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