1 /*
2 Copyright (C) 2003 Parallel Realities
3 Copyright (C) 2011, 2012 Guus Sliepen
4 Copyright (C) 2012, 2015-2020 The Diligent Circle <diligentcircle@riseup.net>
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 3
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <libintl.h>
21 #include <math.h>
22 #include <stdlib.h>
23
24 #include "defs.h"
25 #include "structs.h"
26
27 #include "alien.h"
28 #include "audio.h"
29 #include "bullet.h"
30 #include "cargo.h"
31 #include "collectable.h"
32 #include "engine.h"
33 #include "game.h"
34 #include "gfx.h"
35 #include "info.h"
36 #include "mission.h"
37 #include "player.h"
38 #include "radio.h"
39 #include "screen.h"
40 #include "ship.h"
41 #include "weapons.h"
42
43 Object alien_defs[CD_MAX];
44 Object aliens[ALIEN_MAX];
45
46
47 /*
48 This simply pulls back an alien from the array that is
49 "dead" (no shield) and returns the index number so we can have
50 a new one.
51 */
alien_getFreeIndex()52 static int alien_getFreeIndex()
53 {
54 for (int i = 0 ; i < engine.maxAliens ; i++)
55 {
56 if (!aliens[i].active)
57 {
58 return i;
59 }
60 }
61
62 return -1;
63 }
64
alien_nerf(int index)65 void alien_nerf(int index)
66 {
67 if (game.difficulty == DIFFICULTY_SUPEREASY)
68 {
69 if ((aliens[index].classDef == CD_SID)
70 || (aliens[index].classDef == CD_PHOEBE)
71 || (aliens[index].classDef == CD_URSULA)
72 || (aliens[index].classDef == CD_GOODTRANSPORT)
73 || (aliens[index].classDef == CD_REBELCARRIER)
74 || ((game.area == MISN_URUSOR)
75 && (aliens[index].classDef == CD_CARGOSHIP)))
76 {
77 aliens[index].shield *= 4;
78 aliens[index].maxShield *= 4;
79 }
80 else if ((aliens[index].classDef != CD_ASTEROID)
81 && (aliens[index].classDef != CD_ASTEROID2))
82 {
83 aliens[index].shield /= 2;
84 aliens[index].maxShield /= 2;
85 }
86 }
87 }
88
alien_defs_init()89 void alien_defs_init()
90 {
91 // Dual Plasma Fighter.
92 alien_defs[CD_DUALFIGHTER].classDef = CD_DUALFIGHTER;
93 alien_defs[CD_DUALFIGHTER].AIType = AI_NORMAL;
94 alien_defs[CD_DUALFIGHTER].AITypeOriginal = AI_NORMAL;
95 alien_defs[CD_DUALFIGHTER].speed = 4;
96 alien_defs[CD_DUALFIGHTER].maxShield = 5;
97 alien_defs[CD_DUALFIGHTER].shield = 5;
98 alien_defs[CD_DUALFIGHTER].imageIndex[0] = SS_DUALFIGHTER;
99 alien_defs[CD_DUALFIGHTER].imageIndex[1] = SS_DUALFIGHTER_L;
100 alien_defs[CD_DUALFIGHTER].weaponType[0] = W_DOUBLE_SHOT;
101 alien_defs[CD_DUALFIGHTER].weaponType[1] = W_ROCKETS;
102 alien_defs[CD_DUALFIGHTER].chance[0] = 100;
103 alien_defs[CD_DUALFIGHTER].chance[1] = 1;
104 alien_defs[CD_DUALFIGHTER].collectChance = 50;
105 alien_defs[CD_DUALFIGHTER].collectType = P_ANYTHING;
106 alien_defs[CD_DUALFIGHTER].collectValue = 50;
107 alien_defs[CD_DUALFIGHTER].collectTypeOriginal = P_ANYTHING;
108 alien_defs[CD_DUALFIGHTER].collectValueOriginal = 50;
109 alien_defs[CD_DUALFIGHTER].score = 25;
110 alien_defs[CD_DUALFIGHTER].flags = FL_WEAPCO;
111
112 // Missile Boat
113 alien_defs[CD_MISSILEBOAT].classDef = CD_MISSILEBOAT;
114 alien_defs[CD_MISSILEBOAT].AIType = AI_DEFENSIVE;
115 alien_defs[CD_MISSILEBOAT].AITypeOriginal = AI_DEFENSIVE;
116 alien_defs[CD_MISSILEBOAT].speed = 2;
117 alien_defs[CD_MISSILEBOAT].maxShield = 50;
118 alien_defs[CD_MISSILEBOAT].shield = 50;
119 alien_defs[CD_MISSILEBOAT].imageIndex[0] = SS_MISSILEBOAT;
120 alien_defs[CD_MISSILEBOAT].imageIndex[1] = SS_MISSILEBOAT_L;
121 alien_defs[CD_MISSILEBOAT].weaponType[0] = W_ROCKETS;
122 alien_defs[CD_MISSILEBOAT].weaponType[1] = W_DOUBLE_ROCKETS;
123 alien_defs[CD_MISSILEBOAT].chance[0] = 25;
124 alien_defs[CD_MISSILEBOAT].chance[1] = 4;
125 alien_defs[CD_MISSILEBOAT].collectChance = 25;
126 alien_defs[CD_MISSILEBOAT].collectType = P_ANYTHING;
127 alien_defs[CD_MISSILEBOAT].collectValue = 75;
128 alien_defs[CD_MISSILEBOAT].collectTypeOriginal = P_ANYTHING;
129 alien_defs[CD_MISSILEBOAT].collectValueOriginal = 75;
130 alien_defs[CD_MISSILEBOAT].score = 250;
131 alien_defs[CD_MISSILEBOAT].flags = FL_WEAPCO;
132
133 //Prototype fighter
134 alien_defs[CD_PROTOFIGHTER].classDef = CD_PROTOFIGHTER;
135 alien_defs[CD_PROTOFIGHTER].AIType = AI_DEFENSIVE;
136 alien_defs[CD_PROTOFIGHTER].AITypeOriginal = AI_DEFENSIVE;
137 alien_defs[CD_PROTOFIGHTER].speed = 5;
138 alien_defs[CD_PROTOFIGHTER].maxShield = 15;
139 alien_defs[CD_PROTOFIGHTER].shield = 15;
140 alien_defs[CD_PROTOFIGHTER].imageIndex[0] = SS_PROTOFIGHTER;
141 alien_defs[CD_PROTOFIGHTER].imageIndex[1] = SS_PROTOFIGHTER_L;
142 alien_defs[CD_PROTOFIGHTER].weaponType[0] = W_TRIPLE_SHOT;
143 alien_defs[CD_PROTOFIGHTER].weaponType[1] = P_ANYTHING;
144 alien_defs[CD_PROTOFIGHTER].chance[0] = 100;
145 alien_defs[CD_PROTOFIGHTER].chance[1] = 1;
146 alien_defs[CD_PROTOFIGHTER].collectChance = 50;
147 alien_defs[CD_PROTOFIGHTER].collectType = P_ANYTHING;
148 alien_defs[CD_PROTOFIGHTER].collectValue = 50;
149 alien_defs[CD_PROTOFIGHTER].collectTypeOriginal = P_ANYTHING;
150 alien_defs[CD_PROTOFIGHTER].collectValueOriginal = 50;
151 alien_defs[CD_PROTOFIGHTER].score = 50;
152 alien_defs[CD_PROTOFIGHTER].flags = FL_WEAPCO;
153
154 // Phoebe and Ursula
155 alien_defs[CD_FRIEND].classDef = CD_FRIEND;
156 alien_defs[CD_FRIEND].AIType = AI_OFFENSIVE;
157 alien_defs[CD_FRIEND].AITypeOriginal = AI_OFFENSIVE;
158 alien_defs[CD_FRIEND].speed = 3;
159 alien_defs[CD_FRIEND].maxShield = 50;
160 alien_defs[CD_FRIEND].shield = 50;
161 alien_defs[CD_FRIEND].imageIndex[0] = SS_FRIEND;
162 alien_defs[CD_FRIEND].imageIndex[1] = SS_FRIEND_L;
163 alien_defs[CD_FRIEND].weaponType[0] = W_DOUBLE_SHOT;
164 alien_defs[CD_FRIEND].weaponType[1] = W_HOMING_MISSILE;
165 alien_defs[CD_FRIEND].chance[0] = 100;
166 alien_defs[CD_FRIEND].chance[1] = 5;
167 alien_defs[CD_FRIEND].collectChance = 0;
168 alien_defs[CD_FRIEND].collectType = P_CASH;
169 alien_defs[CD_FRIEND].collectValue = 0;
170 alien_defs[CD_FRIEND].collectTypeOriginal = P_CASH;
171 alien_defs[CD_FRIEND].collectValueOriginal = 0;
172 alien_defs[CD_FRIEND].score = 0;
173 alien_defs[CD_FRIEND].flags = FL_FRIEND;
174
175 // Boss 1
176 alien_defs[CD_FRIGATE].classDef = CD_BOSS;
177 alien_defs[CD_FRIGATE].AIType = AI_NORMAL;
178 alien_defs[CD_FRIGATE].AITypeOriginal = AI_NORMAL;
179 alien_defs[CD_FRIGATE].speed = 2;
180 alien_defs[CD_FRIGATE].maxShield = 550;
181 alien_defs[CD_FRIGATE].shield = 550;
182 alien_defs[CD_FRIGATE].imageIndex[0] = SS_FRIGATE;
183 alien_defs[CD_FRIGATE].imageIndex[1] = SS_FRIGATE_L;
184 alien_defs[CD_FRIGATE].weaponType[0] = W_MICRO_ROCKETS;
185 alien_defs[CD_FRIGATE].weaponType[1] = W_ENERGYRAY;
186 alien_defs[CD_FRIGATE].chance[0] = 100;
187 alien_defs[CD_FRIGATE].chance[1] = 85;
188 alien_defs[CD_FRIGATE].collectChance = 100;
189 alien_defs[CD_FRIGATE].collectType = P_CASH;
190 alien_defs[CD_FRIGATE].collectValue = 500;
191 alien_defs[CD_FRIGATE].collectTypeOriginal = P_CASH;
192 alien_defs[CD_FRIGATE].collectValueOriginal = 250;
193 alien_defs[CD_FRIGATE].score = 500;
194 alien_defs[CD_FRIGATE].flags = FL_WEAPCO | FL_NOBANTER;
195
196 alien_defs[CD_FRIGATE_WING1].classDef = CD_FRIGATE_WING1;
197 alien_defs[CD_FRIGATE_WING1].AIType = AI_NORMAL;
198 alien_defs[CD_FRIGATE_WING1].AITypeOriginal = AI_NORMAL;
199 alien_defs[CD_FRIGATE_WING1].speed = 2;
200 alien_defs[CD_FRIGATE_WING1].maxShield = 100;
201 alien_defs[CD_FRIGATE_WING1].shield = 100;
202 alien_defs[CD_FRIGATE_WING1].imageIndex[0] = SS_FRIGATE_WING1;
203 alien_defs[CD_FRIGATE_WING1].imageIndex[1] = SS_FRIGATE_WING1_L;
204 alien_defs[CD_FRIGATE_WING1].weaponType[0] = W_TRIPLE_SHOT;
205 alien_defs[CD_FRIGATE_WING1].weaponType[1] = W_ROCKETS;
206 alien_defs[CD_FRIGATE_WING1].chance[0] = 100;
207 alien_defs[CD_FRIGATE_WING1].chance[1] = 10;
208 alien_defs[CD_FRIGATE_WING1].collectChance = 100;
209 alien_defs[CD_FRIGATE_WING1].collectType = P_ANYTHING;
210 alien_defs[CD_FRIGATE_WING1].collectValue = 250;
211 alien_defs[CD_FRIGATE_WING1].collectTypeOriginal = P_ANYTHING;
212 alien_defs[CD_FRIGATE_WING1].collectValueOriginal = 250;
213 alien_defs[CD_FRIGATE_WING1].score = 500;
214 alien_defs[CD_FRIGATE_WING1].flags = FL_WEAPCO | FL_DAMAGEOWNER;
215
216 alien_defs[CD_FRIGATE_WING2].classDef = CD_FRIGATE_WING2;
217 alien_defs[CD_FRIGATE_WING2].AIType = AI_NORMAL;
218 alien_defs[CD_FRIGATE_WING2].AITypeOriginal = AI_NORMAL;
219 alien_defs[CD_FRIGATE_WING2].speed = 2;
220 alien_defs[CD_FRIGATE_WING2].maxShield = 100;
221 alien_defs[CD_FRIGATE_WING2].shield = 100;
222 alien_defs[CD_FRIGATE_WING2].imageIndex[0] = SS_FRIGATE_WING2;
223 alien_defs[CD_FRIGATE_WING2].imageIndex[1] = SS_FRIGATE_WING2_L;
224 alien_defs[CD_FRIGATE_WING2].weaponType[0] = W_TRIPLE_SHOT;
225 alien_defs[CD_FRIGATE_WING2].weaponType[1] = W_ROCKETS;
226 alien_defs[CD_FRIGATE_WING2].chance[0] = 100;
227 alien_defs[CD_FRIGATE_WING2].chance[1] = 10;
228 alien_defs[CD_FRIGATE_WING2].collectChance = 100;
229 alien_defs[CD_FRIGATE_WING2].collectType = P_ANYTHING;
230 alien_defs[CD_FRIGATE_WING2].collectValue = 250;
231 alien_defs[CD_FRIGATE_WING2].collectTypeOriginal = P_ANYTHING;
232 alien_defs[CD_FRIGATE_WING2].collectValueOriginal = 250;
233 alien_defs[CD_FRIGATE_WING2].score = 500;
234 alien_defs[CD_FRIGATE_WING2].flags = FL_WEAPCO | FL_DAMAGEOWNER;
235
236 // Transport ship
237 alien_defs[CD_TRANSPORTSHIP].classDef = CD_TRANSPORTSHIP;
238 alien_defs[CD_TRANSPORTSHIP].AIType = AI_EVASIVE;
239 alien_defs[CD_TRANSPORTSHIP].AITypeOriginal = AI_EVASIVE;
240 alien_defs[CD_TRANSPORTSHIP].speed = 4;
241 alien_defs[CD_TRANSPORTSHIP].maxShield = 10;
242 alien_defs[CD_TRANSPORTSHIP].shield = 10;
243 alien_defs[CD_TRANSPORTSHIP].imageIndex[0] = SS_TRANSPORTSHIP;
244 alien_defs[CD_TRANSPORTSHIP].imageIndex[1] = SS_TRANSPORTSHIP_L;
245 alien_defs[CD_TRANSPORTSHIP].weaponType[0] = W_DOUBLE_SHOT;
246 alien_defs[CD_TRANSPORTSHIP].weaponType[1] = W_DOUBLE_SHOT;
247 alien_defs[CD_TRANSPORTSHIP].chance[0] = 0;
248 alien_defs[CD_TRANSPORTSHIP].chance[1] = 0;
249 alien_defs[CD_TRANSPORTSHIP].collectChance = 100;
250 alien_defs[CD_TRANSPORTSHIP].collectType = P_WEAPONS;
251 alien_defs[CD_TRANSPORTSHIP].collectValue = 40;
252 alien_defs[CD_TRANSPORTSHIP].collectTypeOriginal = P_WEAPONS;
253 alien_defs[CD_TRANSPORTSHIP].collectValueOriginal = 30;
254 alien_defs[CD_TRANSPORTSHIP].score = 25;
255 alien_defs[CD_TRANSPORTSHIP].flags = FL_WEAPCO | FL_NOFIRE;
256
257 // Cargo ship
258 alien_defs[CD_CARGOSHIP].classDef = CD_CARGOSHIP;
259 alien_defs[CD_CARGOSHIP].AIType = AI_EVASIVE;
260 alien_defs[CD_CARGOSHIP].AITypeOriginal = AI_EVASIVE;
261 alien_defs[CD_CARGOSHIP].speed = 4;
262 alien_defs[CD_CARGOSHIP].maxShield = 10;
263 alien_defs[CD_CARGOSHIP].shield = 10;
264 alien_defs[CD_CARGOSHIP].imageIndex[0] = SS_CARGOSHIP;
265 alien_defs[CD_CARGOSHIP].imageIndex[1] = SS_CARGOSHIP_L;
266 alien_defs[CD_CARGOSHIP].weaponType[0] = W_DOUBLE_SHOT;
267 alien_defs[CD_CARGOSHIP].weaponType[1] = W_DOUBLE_SHOT;
268 alien_defs[CD_CARGOSHIP].chance[0] = 0;
269 alien_defs[CD_CARGOSHIP].chance[1] = 0;
270 alien_defs[CD_CARGOSHIP].collectChance = 50;
271 alien_defs[CD_CARGOSHIP].collectType = P_ANYTHING;
272 alien_defs[CD_CARGOSHIP].collectValue = 100;
273 alien_defs[CD_CARGOSHIP].collectTypeOriginal = P_ANYTHING;
274 alien_defs[CD_CARGOSHIP].collectValueOriginal = 100;
275 alien_defs[CD_CARGOSHIP].score = 25;
276 alien_defs[CD_CARGOSHIP].flags = FL_WEAPCO | FL_NOFIRE;
277
278 // Weapco Miner
279 alien_defs[CD_MINER].classDef = CD_MINER;
280 alien_defs[CD_MINER].AIType = AI_EVASIVE;
281 alien_defs[CD_MINER].AITypeOriginal = AI_EVASIVE;
282 alien_defs[CD_MINER].speed = 4;
283 alien_defs[CD_MINER].maxShield = 25;
284 alien_defs[CD_MINER].shield = 25;
285 alien_defs[CD_MINER].imageIndex[0] = SS_MINER;
286 alien_defs[CD_MINER].imageIndex[1] = SS_MINER_L;
287 alien_defs[CD_MINER].weaponType[0] = W_DOUBLE_SHOT;
288 alien_defs[CD_MINER].weaponType[1] = W_DOUBLE_SHOT;
289 alien_defs[CD_MINER].chance[0] = 0;
290 alien_defs[CD_MINER].chance[1] = 0;
291 alien_defs[CD_MINER].collectChance = 100;
292 alien_defs[CD_MINER].collectType = P_ANYTHING;
293 alien_defs[CD_MINER].collectValue = 30;
294 alien_defs[CD_MINER].collectTypeOriginal = P_ANYTHING;
295 alien_defs[CD_MINER].collectValueOriginal = 30;
296 alien_defs[CD_MINER].score = 100;
297 alien_defs[CD_MINER].flags = FL_WEAPCO | FL_NOFIRE | FL_DROPMINES;
298
299 // Kline
300 alien_defs[CD_KLINE].classDef = CD_KLINE;
301 alien_defs[CD_KLINE].AIType = AI_OFFENSIVE;
302 alien_defs[CD_KLINE].AITypeOriginal = AI_OFFENSIVE;
303 alien_defs[CD_KLINE].speed = 5;
304 alien_defs[CD_KLINE].maxShield = 2000;
305 alien_defs[CD_KLINE].shield = 2000;
306 alien_defs[CD_KLINE].imageIndex[0] = SS_KLINE;
307 alien_defs[CD_KLINE].imageIndex[1] = SS_KLINE_L;
308 alien_defs[CD_KLINE].weaponType[0] = W_TRIPLE_SHOT;
309 alien_defs[CD_KLINE].weaponType[1] = W_MICRO_ROCKETS;
310 alien_defs[CD_KLINE].chance[0] = 100;
311 alien_defs[CD_KLINE].chance[1] = 2;
312 alien_defs[CD_KLINE].collectChance = 0;
313 alien_defs[CD_KLINE].collectType = P_ANYTHING;
314 alien_defs[CD_KLINE].collectValue = 0;
315 alien_defs[CD_KLINE].collectTypeOriginal = P_ANYTHING;
316 alien_defs[CD_KLINE].collectValueOriginal = 0;
317 alien_defs[CD_KLINE].score = 0;
318 alien_defs[CD_KLINE].flags = FL_WEAPCO | FL_ALWAYSFACE | FL_CIRCLES | FL_NOBANTER;
319
320 // Aim Fighter
321 alien_defs[CD_AIMFIGHTER].classDef = CD_AIMFIGHTER;
322 alien_defs[CD_AIMFIGHTER].AIType = AI_NORMAL;
323 alien_defs[CD_AIMFIGHTER].AITypeOriginal = AI_NORMAL;
324 alien_defs[CD_AIMFIGHTER].speed = 3;
325 alien_defs[CD_AIMFIGHTER].maxShield = 15;
326 alien_defs[CD_AIMFIGHTER].shield = 15;
327 alien_defs[CD_AIMFIGHTER].imageIndex[0] = SS_AIMFIGHTER;
328 alien_defs[CD_AIMFIGHTER].imageIndex[1] = SS_AIMFIGHTER_L;
329 alien_defs[CD_AIMFIGHTER].weaponType[0] = W_AIMED_SHOT;
330 alien_defs[CD_AIMFIGHTER].weaponType[1] = W_AIMED_SHOT;
331 alien_defs[CD_AIMFIGHTER].chance[0] = 7;
332 alien_defs[CD_AIMFIGHTER].chance[1] = 1;
333 alien_defs[CD_AIMFIGHTER].collectChance = 75;
334 alien_defs[CD_AIMFIGHTER].collectType = P_ANYTHING;
335 alien_defs[CD_AIMFIGHTER].collectValue = 100;
336 alien_defs[CD_AIMFIGHTER].collectTypeOriginal = P_ANYTHING;
337 alien_defs[CD_AIMFIGHTER].collectValueOriginal = 100;
338 alien_defs[CD_AIMFIGHTER].score = 50;
339 alien_defs[CD_AIMFIGHTER].flags = FL_WEAPCO | FL_AIMS;
340
341 // Slave ship
342 alien_defs[CD_SLAVETRANSPORT].classDef = CD_SLAVETRANSPORT;
343 alien_defs[CD_SLAVETRANSPORT].AIType = AI_EVASIVE;
344 alien_defs[CD_SLAVETRANSPORT].AITypeOriginal = AI_EVASIVE;
345 alien_defs[CD_SLAVETRANSPORT].speed = 2;
346 alien_defs[CD_SLAVETRANSPORT].maxShield = 10;
347 alien_defs[CD_SLAVETRANSPORT].shield = 20;
348 alien_defs[CD_SLAVETRANSPORT].imageIndex[0] = SS_SLAVETRANSPORT;
349 alien_defs[CD_SLAVETRANSPORT].imageIndex[1] = SS_SLAVETRANSPORT_L;
350 alien_defs[CD_SLAVETRANSPORT].weaponType[0] = W_DOUBLE_SHOT;
351 alien_defs[CD_SLAVETRANSPORT].weaponType[1] = W_DOUBLE_SHOT;
352 alien_defs[CD_SLAVETRANSPORT].chance[0] = 0;
353 alien_defs[CD_SLAVETRANSPORT].chance[1] = 0;
354 alien_defs[CD_SLAVETRANSPORT].collectChance = 100;
355 alien_defs[CD_SLAVETRANSPORT].collectType = P_SLAVES;
356 alien_defs[CD_SLAVETRANSPORT].collectValue = 25;
357 alien_defs[CD_SLAVETRANSPORT].collectTypeOriginal = P_SLAVES;
358 alien_defs[CD_SLAVETRANSPORT].collectValueOriginal = 25;
359 alien_defs[CD_SLAVETRANSPORT].score = 25;
360 alien_defs[CD_SLAVETRANSPORT].flags = FL_WEAPCO | FL_NOFIRE | FL_NOBANTER;
361
362 // Good Transport
363 alien_defs[CD_GOODTRANSPORT].classDef = CD_GOODTRANSPORT;
364 alien_defs[CD_GOODTRANSPORT].AIType = AI_EVASIVE;
365 alien_defs[CD_GOODTRANSPORT].AITypeOriginal = AI_EVASIVE;
366 alien_defs[CD_GOODTRANSPORT].speed = 3;
367 alien_defs[CD_GOODTRANSPORT].maxShield = 75;
368 alien_defs[CD_GOODTRANSPORT].shield = 75;
369 alien_defs[CD_GOODTRANSPORT].imageIndex[0] = SS_GOODTRANSPORT;
370 alien_defs[CD_GOODTRANSPORT].imageIndex[1] = SS_GOODTRANSPORT_L;
371 alien_defs[CD_GOODTRANSPORT].weaponType[0] = W_AIMED_SHOT;
372 alien_defs[CD_GOODTRANSPORT].weaponType[1] = W_AIMED_SHOT;
373 alien_defs[CD_GOODTRANSPORT].chance[0] = 100;
374 alien_defs[CD_GOODTRANSPORT].chance[1] = 100;
375 alien_defs[CD_GOODTRANSPORT].collectChance = 0;
376 alien_defs[CD_GOODTRANSPORT].collectType = P_ANYTHING;
377 alien_defs[CD_GOODTRANSPORT].collectValue = 0;
378 alien_defs[CD_GOODTRANSPORT].collectTypeOriginal = P_ANYTHING;
379 alien_defs[CD_GOODTRANSPORT].collectValueOriginal = 0;
380 alien_defs[CD_GOODTRANSPORT].score = 0;
381 alien_defs[CD_GOODTRANSPORT].flags = FL_FRIEND | FL_NOFIRE | FL_AIMS;
382
383 // Sid Wilson
384 alien_defs[CD_SID].classDef = CD_SID;
385 alien_defs[CD_SID].AIType = AI_NORMAL;
386 alien_defs[CD_SID].AITypeOriginal = AI_NORMAL;
387 alien_defs[CD_SID].speed = 3;
388 alien_defs[CD_SID].maxShield = 50;
389 alien_defs[CD_SID].shield = 50;
390 alien_defs[CD_SID].imageIndex[0] = SS_SID;
391 alien_defs[CD_SID].imageIndex[1] = SS_SID_L;
392 alien_defs[CD_SID].weaponType[0] = W_IONCANNON;
393 alien_defs[CD_SID].weaponType[1] = W_IONCANNON;
394 alien_defs[CD_SID].chance[0] = 100;
395 alien_defs[CD_SID].chance[1] = 0;
396 alien_defs[CD_SID].collectChance = 0;
397 alien_defs[CD_SID].collectType = P_ANYTHING;
398 alien_defs[CD_SID].collectValue = 0;
399 alien_defs[CD_SID].collectTypeOriginal = P_ANYTHING;
400 alien_defs[CD_SID].collectValueOriginal = 0;
401 alien_defs[CD_SID].score = 0;
402 alien_defs[CD_SID].flags = FL_FRIEND | FL_AIMS;
403
404 // Mining Vessel Boss
405 alien_defs[CD_MINEBOSS].classDef = CD_BOSS;
406 alien_defs[CD_MINEBOSS].AIType = AI_NORMAL;
407 alien_defs[CD_MINEBOSS].AITypeOriginal = AI_NORMAL;
408 alien_defs[CD_MINEBOSS].speed = 3;
409 alien_defs[CD_MINEBOSS].maxShield = 1000;
410 alien_defs[CD_MINEBOSS].shield = 1000;
411 alien_defs[CD_MINEBOSS].imageIndex[0] = SS_MINERBOSS;
412 alien_defs[CD_MINEBOSS].imageIndex[1] = SS_MINERBOSS_L;
413 alien_defs[CD_MINEBOSS].weaponType[0] = W_TRIPLE_SHOT;
414 alien_defs[CD_MINEBOSS].weaponType[1] = W_SPREADSHOT;
415 alien_defs[CD_MINEBOSS].chance[0] = 0;
416 alien_defs[CD_MINEBOSS].chance[1] = 0;
417 alien_defs[CD_MINEBOSS].collectChance = 100;
418 alien_defs[CD_MINEBOSS].collectType = P_ANYTHING;
419 alien_defs[CD_MINEBOSS].collectValue = 1000;
420 alien_defs[CD_MINEBOSS].collectTypeOriginal = P_ANYTHING;
421 alien_defs[CD_MINEBOSS].collectValueOriginal = 255;
422 alien_defs[CD_MINEBOSS].score = 1000;
423 alien_defs[CD_MINEBOSS].flags = FL_WEAPCO | FL_IMMORTAL | FL_NOBANTER;
424
425 alien_defs[CD_BOSS2_WING1].classDef = CD_BOSS2_WING1;
426 alien_defs[CD_BOSS2_WING1].AIType = AI_NORMAL;
427 alien_defs[CD_BOSS2_WING1].AITypeOriginal = AI_NORMAL;
428 alien_defs[CD_BOSS2_WING1].speed = 1;
429 alien_defs[CD_BOSS2_WING1].maxShield = 250;
430 alien_defs[CD_BOSS2_WING1].shield = 250;
431 alien_defs[CD_BOSS2_WING1].imageIndex[0] = SS_MINERBOSS_WING1;
432 alien_defs[CD_BOSS2_WING1].imageIndex[1] = SS_MINERBOSS_WING1_L;
433 alien_defs[CD_BOSS2_WING1].weaponType[0] = W_TRIPLE_SHOT;
434 alien_defs[CD_BOSS2_WING1].weaponType[1] = W_SPREADSHOT;
435 alien_defs[CD_BOSS2_WING1].chance[0] = 0;
436 alien_defs[CD_BOSS2_WING1].chance[1] = 0;
437 alien_defs[CD_BOSS2_WING1].collectChance = 100;
438 alien_defs[CD_BOSS2_WING1].collectType = P_ANYTHING;
439 alien_defs[CD_BOSS2_WING1].collectValue = 250;
440 alien_defs[CD_BOSS2_WING1].collectTypeOriginal = P_ANYTHING;
441 alien_defs[CD_BOSS2_WING1].collectValueOriginal = 255;
442 alien_defs[CD_BOSS2_WING1].score = 1000;
443 alien_defs[CD_BOSS2_WING1].flags = FL_WEAPCO | FL_DAMAGEOWNER | FL_NOBANTER;
444
445 alien_defs[CD_BOSS2_WING2].classDef = CD_BOSS2_WING2;
446 alien_defs[CD_BOSS2_WING2].AIType = AI_NORMAL;
447 alien_defs[CD_BOSS2_WING2].AITypeOriginal = AI_NORMAL;
448 alien_defs[CD_BOSS2_WING2].speed = 1;
449 alien_defs[CD_BOSS2_WING2].maxShield = 500;
450 alien_defs[CD_BOSS2_WING2].shield = 500;
451 alien_defs[CD_BOSS2_WING2].imageIndex[0] = SS_MINERBOSS_WING2;
452 alien_defs[CD_BOSS2_WING2].imageIndex[1] = SS_MINERBOSS_WING2_L;
453 alien_defs[CD_BOSS2_WING2].weaponType[0] = W_TRIPLE_SHOT;
454 alien_defs[CD_BOSS2_WING2].weaponType[1] = W_SPREADSHOT;
455 alien_defs[CD_BOSS2_WING2].chance[0] = 0;
456 alien_defs[CD_BOSS2_WING2].chance[1] = 0;
457 alien_defs[CD_BOSS2_WING2].collectChance = 100;
458 alien_defs[CD_BOSS2_WING2].collectType = P_ANYTHING;
459 alien_defs[CD_BOSS2_WING2].collectValue = 250;
460 alien_defs[CD_BOSS2_WING2].collectTypeOriginal = P_ANYTHING;
461 alien_defs[CD_BOSS2_WING2].collectValueOriginal = 255;
462 alien_defs[CD_BOSS2_WING2].score = 1000;
463 alien_defs[CD_BOSS2_WING2].flags = FL_WEAPCO | FL_DEPLOYDRONES | FL_DAMAGEOWNER | FL_NOBANTER;
464
465 alien_defs[CD_BOSS2_WING3].classDef = CD_BOSS2_WING3;
466 alien_defs[CD_BOSS2_WING3].AIType = AI_NORMAL;
467 alien_defs[CD_BOSS2_WING3].AITypeOriginal = AI_NORMAL;
468 alien_defs[CD_BOSS2_WING3].speed = 1;
469 alien_defs[CD_BOSS2_WING3].maxShield = 500;
470 alien_defs[CD_BOSS2_WING3].shield = 500;
471 alien_defs[CD_BOSS2_WING3].imageIndex[0] = SS_MINERBOSS_WING3;
472 alien_defs[CD_BOSS2_WING3].imageIndex[1] = SS_MINERBOSS_WING3_L;
473 alien_defs[CD_BOSS2_WING3].weaponType[0] = W_TRIPLE_SHOT;
474 alien_defs[CD_BOSS2_WING3].weaponType[1] = W_SPREADSHOT;
475 alien_defs[CD_BOSS2_WING3].chance[0] = 0;
476 alien_defs[CD_BOSS2_WING3].chance[1] = 0;
477 alien_defs[CD_BOSS2_WING3].collectChance = 100;
478 alien_defs[CD_BOSS2_WING3].collectType = P_ANYTHING;
479 alien_defs[CD_BOSS2_WING3].collectValue = 250;
480 alien_defs[CD_BOSS2_WING3].collectTypeOriginal = P_ANYTHING;
481 alien_defs[CD_BOSS2_WING3].collectValueOriginal = 255;
482 alien_defs[CD_BOSS2_WING3].score = 1000;
483 alien_defs[CD_BOSS2_WING3].flags = FL_WEAPCO | FL_DEPLOYDRONES | FL_DAMAGEOWNER | FL_NOBANTER;
484
485 alien_defs[CD_BOSS2_WING4].classDef = CD_BOSS2_WING4;
486 alien_defs[CD_BOSS2_WING4].AIType = AI_NORMAL;
487 alien_defs[CD_BOSS2_WING4].AITypeOriginal = AI_NORMAL;
488 alien_defs[CD_BOSS2_WING4].speed = 1;
489 alien_defs[CD_BOSS2_WING4].maxShield = 250;
490 alien_defs[CD_BOSS2_WING4].shield = 250;
491 alien_defs[CD_BOSS2_WING4].imageIndex[0] = SS_MINERBOSS_WING4;
492 alien_defs[CD_BOSS2_WING4].imageIndex[1] = SS_MINERBOSS_WING4_L;
493 alien_defs[CD_BOSS2_WING4].weaponType[0] = W_TRIPLE_SHOT;
494 alien_defs[CD_BOSS2_WING4].weaponType[1] = W_SPREADSHOT;
495 alien_defs[CD_BOSS2_WING4].chance[0] = 0;
496 alien_defs[CD_BOSS2_WING4].chance[1] = 0;
497 alien_defs[CD_BOSS2_WING4].collectChance = 100;
498 alien_defs[CD_BOSS2_WING4].collectType = P_ANYTHING;
499 alien_defs[CD_BOSS2_WING4].collectValue = 250;
500 alien_defs[CD_BOSS2_WING4].collectTypeOriginal = P_ANYTHING;
501 alien_defs[CD_BOSS2_WING4].collectValueOriginal = 255;
502 alien_defs[CD_BOSS2_WING4].score = 1000;
503 alien_defs[CD_BOSS2_WING4].flags = FL_WEAPCO | FL_DAMAGEOWNER | FL_NOBANTER;
504
505 // Drone
506 alien_defs[CD_DRONE].classDef = CD_DRONE;
507 alien_defs[CD_DRONE].AIType = AI_OFFENSIVE;
508 alien_defs[CD_DRONE].AITypeOriginal = AI_OFFENSIVE;
509 alien_defs[CD_DRONE].speed = 8;
510 alien_defs[CD_DRONE].maxShield = 5;
511 alien_defs[CD_DRONE].shield = 5;
512 alien_defs[CD_DRONE].imageIndex[0] = SS_DRONE;
513 alien_defs[CD_DRONE].imageIndex[1] = SS_DRONE_L;
514 alien_defs[CD_DRONE].weaponType[0] = W_DOUBLE_SHOT;
515 alien_defs[CD_DRONE].weaponType[1] = W_LASER;
516 alien_defs[CD_DRONE].chance[0] = 100;
517 alien_defs[CD_DRONE].chance[1] = 0;
518 alien_defs[CD_DRONE].collectChance = 10;
519 alien_defs[CD_DRONE].collectType = P_SHIELD;
520 alien_defs[CD_DRONE].collectValue = 1;
521 alien_defs[CD_DRONE].collectTypeOriginal = P_SHIELD;
522 alien_defs[CD_DRONE].collectValueOriginal = 1;
523 alien_defs[CD_DRONE].score = 0;
524 alien_defs[CD_DRONE].flags = FL_WEAPCO | FL_NOBANTER;
525
526 // Experimental Fighter
527 alien_defs[CD_CLOAKFIGHTER].classDef = CD_CLOAKFIGHTER;
528 alien_defs[CD_CLOAKFIGHTER].AIType = AI_OFFENSIVE;
529 alien_defs[CD_CLOAKFIGHTER].AITypeOriginal = AI_OFFENSIVE;
530 alien_defs[CD_CLOAKFIGHTER].speed = 6;
531 alien_defs[CD_CLOAKFIGHTER].maxShield = 1000;
532 alien_defs[CD_CLOAKFIGHTER].shield = 1000;
533 alien_defs[CD_CLOAKFIGHTER].imageIndex[0] = SS_CLOAKFIGHTER;
534 alien_defs[CD_CLOAKFIGHTER].imageIndex[1] = SS_CLOAKFIGHTER_L;
535 alien_defs[CD_CLOAKFIGHTER].weaponType[0] = W_SPREADSHOT;
536 alien_defs[CD_CLOAKFIGHTER].weaponType[1] = W_DOUBLE_ROCKETS;
537 alien_defs[CD_CLOAKFIGHTER].chance[0] = 100;
538 alien_defs[CD_CLOAKFIGHTER].chance[1] = 5;
539 alien_defs[CD_CLOAKFIGHTER].collectChance = 100;
540 alien_defs[CD_CLOAKFIGHTER].collectType = P_CASH;
541 alien_defs[CD_CLOAKFIGHTER].collectValue = 250;
542 alien_defs[CD_CLOAKFIGHTER].collectTypeOriginal = P_CASH;
543 alien_defs[CD_CLOAKFIGHTER].collectValueOriginal = 255;
544 alien_defs[CD_CLOAKFIGHTER].score = 550;
545 alien_defs[CD_CLOAKFIGHTER].flags = FL_WEAPCO | FL_CANCLOAK | FL_RUNSAWAY;
546
547 // Evil Ursula
548 alien_defs[CD_EVILURSULA].classDef = CD_EVILURSULA;
549 alien_defs[CD_EVILURSULA].AIType = AI_OFFENSIVE;
550 alien_defs[CD_EVILURSULA].AITypeOriginal = AI_OFFENSIVE;
551 alien_defs[CD_EVILURSULA].speed = 5;
552 alien_defs[CD_EVILURSULA].maxShield = 500;
553 alien_defs[CD_EVILURSULA].shield = 500;
554 alien_defs[CD_EVILURSULA].imageIndex[0] = SS_EVILURSULA;
555 alien_defs[CD_EVILURSULA].imageIndex[1] = SS_EVILURSULA_L;
556 alien_defs[CD_EVILURSULA].weaponType[0] = W_TRIPLE_SHOT;
557 alien_defs[CD_EVILURSULA].weaponType[1] = W_HOMING_MISSILE;
558 alien_defs[CD_EVILURSULA].chance[0] = 100;
559 alien_defs[CD_EVILURSULA].chance[1] = 100;
560 alien_defs[CD_EVILURSULA].collectChance = 100;
561 alien_defs[CD_EVILURSULA].collectType = P_ESCAPEPOD;
562 alien_defs[CD_EVILURSULA].collectValue = 1;
563 alien_defs[CD_EVILURSULA].collectTypeOriginal = P_ESCAPEPOD;
564 alien_defs[CD_EVILURSULA].collectValueOriginal = 1;
565 alien_defs[CD_EVILURSULA].score = 500;
566 alien_defs[CD_EVILURSULA].flags = FL_WEAPCO | FL_NOBANTER;
567
568 // Mercenary
569 alien_defs[CD_KRASS].classDef = CD_KRASS;
570 alien_defs[CD_KRASS].AIType = AI_OFFENSIVE;
571 alien_defs[CD_KRASS].AITypeOriginal = AI_OFFENSIVE;
572 alien_defs[CD_KRASS].speed = 5;
573 alien_defs[CD_KRASS].maxShield = 1000;
574 alien_defs[CD_KRASS].shield = 1000;
575 alien_defs[CD_KRASS].imageIndex[0] = SS_KRASS;
576 alien_defs[CD_KRASS].imageIndex[1] = SS_KRASS_L;
577 alien_defs[CD_KRASS].weaponType[0] = W_SPREADSHOT;
578 alien_defs[CD_KRASS].weaponType[1] = W_CHARGER;
579 alien_defs[CD_KRASS].chance[0] = 100;
580 alien_defs[CD_KRASS].chance[1] = 0;
581 alien_defs[CD_KRASS].collectChance = 100;
582 alien_defs[CD_KRASS].collectType = P_ANYTHING;
583 alien_defs[CD_KRASS].collectValue = 2250;
584 alien_defs[CD_KRASS].collectTypeOriginal = P_ANYTHING;
585 alien_defs[CD_KRASS].collectValueOriginal = 255;
586 alien_defs[CD_KRASS].score = 2000;
587 alien_defs[CD_KRASS].flags = FL_FRIEND | FL_IMMORTAL | FL_NOBANTER;
588
589 // Executive Transport
590 alien_defs[CD_EXEC].classDef = CD_BOSS;
591 alien_defs[CD_EXEC].AIType = AI_EVASIVE;
592 alien_defs[CD_EXEC].AITypeOriginal = AI_NORMAL;
593 alien_defs[CD_EXEC].speed = 5;
594 alien_defs[CD_EXEC].maxShield = 1000;
595 alien_defs[CD_EXEC].shield = 1000;
596 alien_defs[CD_EXEC].imageIndex[0] = SS_EXEC;
597 alien_defs[CD_EXEC].imageIndex[1] = SS_EXEC_L;
598 alien_defs[CD_EXEC].weaponType[0] = W_SPREADSHOT;
599 alien_defs[CD_EXEC].weaponType[1] = W_HOMING_MISSILE;
600 alien_defs[CD_EXEC].chance[0] = 0;
601 alien_defs[CD_EXEC].chance[1] = 0;
602 alien_defs[CD_EXEC].collectChance = 0;
603 alien_defs[CD_EXEC].collectType = P_ANYTHING;
604 alien_defs[CD_EXEC].collectValue = 0;
605 alien_defs[CD_EXEC].collectTypeOriginal = P_ANYTHING;
606 alien_defs[CD_EXEC].collectValueOriginal = 0;
607 alien_defs[CD_EXEC].score = 2000;
608 alien_defs[CD_EXEC].flags = FL_WEAPCO | FL_NOFIRE | FL_NOBANTER;
609
610 // Asteroid
611 alien_defs[CD_ASTEROID].classDef = CD_ASTEROID;
612 alien_defs[CD_ASTEROID].AIType = AI_WANDER;
613 alien_defs[CD_ASTEROID].AITypeOriginal = AI_WANDER;
614 alien_defs[CD_ASTEROID].speed = 1;
615 alien_defs[CD_ASTEROID].maxShield = 50;
616 alien_defs[CD_ASTEROID].shield = 50;
617 alien_defs[CD_ASTEROID].imageIndex[0] = SS_ASTEROID;
618 alien_defs[CD_ASTEROID].imageIndex[1] = SS_ASTEROID;
619 alien_defs[CD_ASTEROID].weaponType[0] = W_SPREADSHOT;
620 alien_defs[CD_ASTEROID].weaponType[1] = W_HOMING_MISSILE;
621 alien_defs[CD_ASTEROID].chance[0] = 0;
622 alien_defs[CD_ASTEROID].chance[1] = 0;
623 alien_defs[CD_ASTEROID].collectChance = 25;
624 alien_defs[CD_ASTEROID].collectType = P_ORE;
625 alien_defs[CD_ASTEROID].collectValue = 1;
626 alien_defs[CD_ASTEROID].collectTypeOriginal = P_ORE;
627 alien_defs[CD_ASTEROID].collectValueOriginal = 1;
628 alien_defs[CD_ASTEROID].score = 0;
629 alien_defs[CD_ASTEROID].flags = FL_WEAPCO | FL_NOBANTER;
630
631 alien_defs[CD_ASTEROID2].classDef = CD_ASTEROID2;
632 alien_defs[CD_ASTEROID2].AIType = AI_WANDER;
633 alien_defs[CD_ASTEROID2].AITypeOriginal = AI_WANDER;
634 alien_defs[CD_ASTEROID2].speed = 1;
635 alien_defs[CD_ASTEROID2].maxShield = 10;
636 alien_defs[CD_ASTEROID2].shield = 10;
637 alien_defs[CD_ASTEROID2].imageIndex[0] = SS_ASTEROID_SMALL;
638 alien_defs[CD_ASTEROID2].imageIndex[1] = SS_ASTEROID_SMALL_L;
639 alien_defs[CD_ASTEROID2].weaponType[0] = W_SPREADSHOT;
640 alien_defs[CD_ASTEROID2].weaponType[1] = W_HOMING_MISSILE;
641 alien_defs[CD_ASTEROID2].chance[0] = 0;
642 alien_defs[CD_ASTEROID2].chance[1] = 0;
643 alien_defs[CD_ASTEROID2].collectChance = 25;
644 alien_defs[CD_ASTEROID2].collectType = P_ORE;
645 alien_defs[CD_ASTEROID2].collectValue = 1;
646 alien_defs[CD_ASTEROID2].collectTypeOriginal = P_ORE;
647 alien_defs[CD_ASTEROID2].collectValueOriginal = 1;
648 alien_defs[CD_ASTEROID2].score = 0;
649 alien_defs[CD_ASTEROID2].flags = FL_WEAPCO | FL_NOBANTER;
650
651 // Escort
652 alien_defs[CD_ESCORT].classDef = CD_ESCORT;
653 alien_defs[CD_ESCORT].AIType = AI_NORMAL;
654 alien_defs[CD_ESCORT].AITypeOriginal = AI_NORMAL;
655 alien_defs[CD_ESCORT].speed = 3;
656 alien_defs[CD_ESCORT].maxShield = 200;
657 alien_defs[CD_ESCORT].shield = 200;
658 alien_defs[CD_ESCORT].imageIndex[0] = SS_ESCORT;
659 alien_defs[CD_ESCORT].imageIndex[1] = SS_ESCORT_L;
660 alien_defs[CD_ESCORT].weaponType[0] = W_LASER;
661 alien_defs[CD_ESCORT].weaponType[1] = W_LASER;
662 alien_defs[CD_ESCORT].chance[0] = 25;
663 alien_defs[CD_ESCORT].chance[1] = 25;
664 alien_defs[CD_ESCORT].collectChance = 100;
665 alien_defs[CD_ESCORT].collectType = P_ANYTHING;
666 alien_defs[CD_ESCORT].collectValue = 100;
667 alien_defs[CD_ESCORT].collectTypeOriginal = P_ANYTHING;
668 alien_defs[CD_ESCORT].collectValueOriginal = 100;
669 alien_defs[CD_ESCORT].score = 450;
670 alien_defs[CD_ESCORT].flags = FL_WEAPCO;
671
672 // Mobile Ray Cannon
673 alien_defs[CD_MOBILE_RAY].classDef = CD_MOBILE_RAY;
674 alien_defs[CD_MOBILE_RAY].AIType = AI_OFFENSIVE;
675 alien_defs[CD_MOBILE_RAY].AITypeOriginal = AI_OFFENSIVE;
676 alien_defs[CD_MOBILE_RAY].speed = 5;
677 alien_defs[CD_MOBILE_RAY].maxShield = 250;
678 alien_defs[CD_MOBILE_RAY].shield = 250;
679 alien_defs[CD_MOBILE_RAY].imageIndex[0] = SS_MOBILE_RAY;
680 alien_defs[CD_MOBILE_RAY].imageIndex[1] = SS_MOBILE_RAY_L;
681 alien_defs[CD_MOBILE_RAY].weaponType[0] = W_ENERGYRAY;
682 alien_defs[CD_MOBILE_RAY].weaponType[1] = W_ENERGYRAY;
683 alien_defs[CD_MOBILE_RAY].chance[0] = 50;
684 alien_defs[CD_MOBILE_RAY].chance[1] = 0;
685 alien_defs[CD_MOBILE_RAY].collectChance = 75;
686 alien_defs[CD_MOBILE_RAY].collectType = P_ANYTHING;
687 alien_defs[CD_MOBILE_RAY].collectValue = 100;
688 alien_defs[CD_MOBILE_RAY].collectTypeOriginal = P_SHIELD;
689 alien_defs[CD_MOBILE_RAY].collectValueOriginal = 2;
690 alien_defs[CD_MOBILE_RAY].score = 1000;
691 alien_defs[CD_MOBILE_RAY].flags = FL_WEAPCO;
692
693 // Rebel Carrier
694 alien_defs[CD_REBELCARRIER].classDef = CD_REBELCARRIER;
695 alien_defs[CD_REBELCARRIER].AIType = AI_OFFENSIVE;
696 alien_defs[CD_REBELCARRIER].AITypeOriginal = AI_OFFENSIVE;
697 alien_defs[CD_REBELCARRIER].speed = 2;
698 alien_defs[CD_REBELCARRIER].maxShield = 100;
699 alien_defs[CD_REBELCARRIER].shield = 100;
700 alien_defs[CD_REBELCARRIER].imageIndex[0] = SS_REBELCARRIER;
701 alien_defs[CD_REBELCARRIER].imageIndex[1] = SS_REBELCARRIER_L;
702 alien_defs[CD_REBELCARRIER].weaponType[0] = W_DOUBLE_ROCKETS;
703 alien_defs[CD_REBELCARRIER].weaponType[1] = W_MICRO_ROCKETS;
704 alien_defs[CD_REBELCARRIER].chance[0] = 50;
705 alien_defs[CD_REBELCARRIER].chance[1] = 2;
706 alien_defs[CD_REBELCARRIER].collectChance = 0;
707 alien_defs[CD_REBELCARRIER].collectType = P_SHIELD;
708 alien_defs[CD_REBELCARRIER].collectValue = 0;
709 alien_defs[CD_REBELCARRIER].collectTypeOriginal = P_SHIELD;
710 alien_defs[CD_REBELCARRIER].collectValueOriginal = 0;
711 alien_defs[CD_REBELCARRIER].score = 0;
712 alien_defs[CD_REBELCARRIER].flags = FL_FRIEND;
713
714 // Pluto Boss
715 alien_defs[CD_PLUTOBOSS].classDef = CD_PLUTOBOSS;
716 alien_defs[CD_PLUTOBOSS].AIType = AI_OFFENSIVE;
717 alien_defs[CD_PLUTOBOSS].AITypeOriginal = AI_OFFENSIVE;
718 alien_defs[CD_PLUTOBOSS].speed = 4;
719 alien_defs[CD_PLUTOBOSS].maxShield = 500;
720 alien_defs[CD_PLUTOBOSS].shield = 500;
721 alien_defs[CD_PLUTOBOSS].imageIndex[0] = SS_PLUTOBOSS;
722 alien_defs[CD_PLUTOBOSS].imageIndex[1] = SS_PLUTOBOSS_L;
723 alien_defs[CD_PLUTOBOSS].weaponType[0] = W_DOUBLE_ROCKETS;
724 alien_defs[CD_PLUTOBOSS].weaponType[1] = W_MICRO_ROCKETS;
725 alien_defs[CD_PLUTOBOSS].chance[0] = 50;
726 alien_defs[CD_PLUTOBOSS].chance[1] = 2;
727 alien_defs[CD_PLUTOBOSS].collectChance = 100;
728 alien_defs[CD_PLUTOBOSS].collectType = P_ANYTHING;
729 alien_defs[CD_PLUTOBOSS].collectValue = 1000;
730 alien_defs[CD_PLUTOBOSS].collectTypeOriginal = P_SHIELD;
731 alien_defs[CD_PLUTOBOSS].collectValueOriginal = 0;
732 alien_defs[CD_PLUTOBOSS].score = 1000;
733 alien_defs[CD_PLUTOBOSS].flags = FL_WEAPCO | FL_NOBANTER;
734
735 // Pluto Boss Barrier
736 alien_defs[CD_BARRIER].classDef = CD_BARRIER;
737 alien_defs[CD_BARRIER].AIType = AI_OFFENSIVE;
738 alien_defs[CD_BARRIER].AITypeOriginal = AI_OFFENSIVE;
739 alien_defs[CD_BARRIER].speed = 1;
740 alien_defs[CD_BARRIER].maxShield = 250;
741 alien_defs[CD_BARRIER].shield = 250;
742 alien_defs[CD_BARRIER].imageIndex[0] = SS_BARRIER;
743 alien_defs[CD_BARRIER].imageIndex[1] = SS_BARRIER;
744 alien_defs[CD_BARRIER].weaponType[0] = W_DOUBLE_SHOT;
745 alien_defs[CD_BARRIER].weaponType[1] = W_MICRO_ROCKETS;
746 alien_defs[CD_BARRIER].chance[0] = 0;
747 alien_defs[CD_BARRIER].chance[1] = 0;
748 alien_defs[CD_BARRIER].collectChance = 100;
749 alien_defs[CD_BARRIER].collectType = P_ANYTHING;
750 alien_defs[CD_BARRIER].collectValue = 25;
751 alien_defs[CD_BARRIER].collectTypeOriginal = P_ANYTHING;
752 alien_defs[CD_BARRIER].collectValueOriginal = 25;
753 alien_defs[CD_BARRIER].score = 1000;
754 alien_defs[CD_BARRIER].flags = FL_WEAPCO | FL_NOFIRE | FL_NOBANTER;
755
756 // Neptune Boss
757 alien_defs[CD_NEPTUNEBOSS].classDef = CD_NEPTUNEBOSS;
758 alien_defs[CD_NEPTUNEBOSS].AIType = AI_OFFENSIVE;
759 alien_defs[CD_NEPTUNEBOSS].AITypeOriginal = AI_OFFENSIVE;
760 alien_defs[CD_NEPTUNEBOSS].speed = 4;
761 alien_defs[CD_NEPTUNEBOSS].maxShield = 800;
762 alien_defs[CD_NEPTUNEBOSS].shield = 800;
763 alien_defs[CD_NEPTUNEBOSS].imageIndex[0] = SS_PLUTOBOSS;
764 alien_defs[CD_NEPTUNEBOSS].imageIndex[1] = SS_PLUTOBOSS_L;
765 alien_defs[CD_NEPTUNEBOSS].weaponType[0] = W_DOUBLE_SHOT;
766 alien_defs[CD_NEPTUNEBOSS].weaponType[1] = W_MICRO_ROCKETS;
767 alien_defs[CD_NEPTUNEBOSS].chance[0] = 100;
768 alien_defs[CD_NEPTUNEBOSS].chance[1] = 0;
769 alien_defs[CD_NEPTUNEBOSS].collectChance = 100;
770 alien_defs[CD_NEPTUNEBOSS].collectType = P_ANYTHING;
771 alien_defs[CD_NEPTUNEBOSS].collectValue = 1000;
772 alien_defs[CD_NEPTUNEBOSS].collectTypeOriginal = P_ANYTHING;
773 alien_defs[CD_NEPTUNEBOSS].collectValueOriginal = 25;
774 alien_defs[CD_NEPTUNEBOSS].score = 1000;
775 alien_defs[CD_NEPTUNEBOSS].flags = FL_WEAPCO | FL_NOBANTER;
776
777 // Mobile Shield
778 alien_defs[CD_MOBILESHIELD].classDef = CD_MOBILESHIELD;
779 alien_defs[CD_MOBILESHIELD].AIType = AI_EVASIVE;
780 alien_defs[CD_MOBILESHIELD].AITypeOriginal = AI_EVASIVE;
781 alien_defs[CD_MOBILESHIELD].speed = 6;
782 alien_defs[CD_MOBILESHIELD].maxShield = 150;
783 alien_defs[CD_MOBILESHIELD].shield = 150;
784 alien_defs[CD_MOBILESHIELD].imageIndex[0] = SS_MOBILESHIELD;
785 alien_defs[CD_MOBILESHIELD].imageIndex[1] = SS_MOBILESHIELD_L;
786 alien_defs[CD_MOBILESHIELD].weaponType[0] = W_DOUBLE_SHOT;
787 alien_defs[CD_MOBILESHIELD].weaponType[1] = W_MICRO_ROCKETS;
788 alien_defs[CD_MOBILESHIELD].chance[0] = 0;
789 alien_defs[CD_MOBILESHIELD].chance[1] = 0;
790 alien_defs[CD_MOBILESHIELD].collectChance = 100;
791 alien_defs[CD_MOBILESHIELD].collectType = P_ANYTHING;
792 alien_defs[CD_MOBILESHIELD].collectValue = 25;
793 alien_defs[CD_MOBILESHIELD].collectTypeOriginal = P_ANYTHING;
794 alien_defs[CD_MOBILESHIELD].collectValueOriginal = 25;
795 alien_defs[CD_MOBILESHIELD].score = 250;
796 alien_defs[CD_MOBILESHIELD].flags = FL_WEAPCO | FL_NOFIRE | FL_NOBANTER;
797
798 // Firefly
799 alien_defs[CD_FIREFLY].classDef = CD_FIREFLY;
800 alien_defs[CD_FIREFLY].AIType = AI_OFFENSIVE;
801 alien_defs[CD_FIREFLY].AITypeOriginal = AI_OFFENSIVE;
802 alien_defs[CD_FIREFLY].speed = 5;
803 alien_defs[CD_FIREFLY].maxShield = 250;
804 alien_defs[CD_FIREFLY].shield = 250;
805 alien_defs[CD_FIREFLY].imageIndex[0] = SS_FIREFLY;
806 alien_defs[CD_FIREFLY].imageIndex[1] = SS_FIREFLY_L;
807 alien_defs[CD_FIREFLY].weaponType[0] = W_TRIPLE_SHOT;
808 alien_defs[CD_FIREFLY].weaponType[1] = W_DOUBLE_ROCKETS;
809 alien_defs[CD_FIREFLY].chance[0] = 100;
810 alien_defs[CD_FIREFLY].chance[1] = 5;
811 alien_defs[CD_FIREFLY].collectChance = 100;
812 alien_defs[CD_FIREFLY].collectType = P_ANYTHING;
813 alien_defs[CD_FIREFLY].collectValue = 250;
814 alien_defs[CD_FIREFLY].collectTypeOriginal = P_ANYTHING;
815 alien_defs[CD_FIREFLY].collectValueOriginal = 250;
816 alien_defs[CD_FIREFLY].score = 500;
817 alien_defs[CD_FIREFLY].flags = FL_WEAPCO | FL_NOBANTER;
818
819 // Uranus Boss
820 alien_defs[CD_URANUSBOSS].classDef = CD_URANUSBOSS;
821 alien_defs[CD_URANUSBOSS].AIType = AI_OFFENSIVE;
822 alien_defs[CD_URANUSBOSS].AITypeOriginal = AI_OFFENSIVE;
823 alien_defs[CD_URANUSBOSS].speed = 4;
824 alien_defs[CD_URANUSBOSS].maxShield = 750;
825 alien_defs[CD_URANUSBOSS].shield = 750;
826 alien_defs[CD_URANUSBOSS].imageIndex[0] = SS_URANUSBOSS;
827 alien_defs[CD_URANUSBOSS].imageIndex[1] = SS_URANUSBOSS_L;
828 alien_defs[CD_URANUSBOSS].weaponType[0] = W_SPREADSHOT;
829 alien_defs[CD_URANUSBOSS].weaponType[1] = W_DOUBLE_ROCKETS;
830 alien_defs[CD_URANUSBOSS].chance[0] = 100;
831 alien_defs[CD_URANUSBOSS].chance[1] = 5;
832 alien_defs[CD_URANUSBOSS].collectChance = 100;
833 alien_defs[CD_URANUSBOSS].collectType = P_ANYTHING;
834 alien_defs[CD_URANUSBOSS].collectValue = 500;
835 alien_defs[CD_URANUSBOSS].collectTypeOriginal = P_ANYTHING;
836 alien_defs[CD_URANUSBOSS].collectValueOriginal = 250;
837 alien_defs[CD_URANUSBOSS].score = 500;
838 alien_defs[CD_URANUSBOSS].flags = FL_WEAPCO | FL_NOBANTER;
839
840 // Uranus Boss Wing 1
841 alien_defs[CD_URANUSBOSSWING1].classDef = CD_URANUSBOSSWING1;
842 alien_defs[CD_URANUSBOSSWING1].AIType = AI_OFFENSIVE;
843 alien_defs[CD_URANUSBOSSWING1].AITypeOriginal = AI_OFFENSIVE;
844 alien_defs[CD_URANUSBOSSWING1].speed = 4;
845 alien_defs[CD_URANUSBOSSWING1].maxShield = 250;
846 alien_defs[CD_URANUSBOSSWING1].shield = 250;
847 alien_defs[CD_URANUSBOSSWING1].imageIndex[0] = SS_URANUSBOSS_WING1;
848 alien_defs[CD_URANUSBOSSWING1].imageIndex[1] = SS_URANUSBOSS_WING1_L;
849 alien_defs[CD_URANUSBOSSWING1].weaponType[0] = W_DOUBLE_ROCKETS;
850 alien_defs[CD_URANUSBOSSWING1].weaponType[1] = W_DOUBLE_ROCKETS;
851 alien_defs[CD_URANUSBOSSWING1].chance[0] = 5;
852 alien_defs[CD_URANUSBOSSWING1].chance[1] = 0;
853 alien_defs[CD_URANUSBOSSWING1].collectChance = 100;
854 alien_defs[CD_URANUSBOSSWING1].collectType = P_ANYTHING;
855 alien_defs[CD_URANUSBOSSWING1].collectValue = 250;
856 alien_defs[CD_URANUSBOSSWING1].collectTypeOriginal = P_ANYTHING;
857 alien_defs[CD_URANUSBOSSWING1].collectValueOriginal = 250;
858 alien_defs[CD_URANUSBOSSWING1].score = 500;
859 alien_defs[CD_URANUSBOSSWING1].flags = FL_WEAPCO | FL_IMMORTAL | FL_DAMAGEOWNER;
860
861 // Uranus Boss Wing 2
862 alien_defs[CD_URANUSBOSSWING2].classDef = CD_URANUSBOSSWING2;
863 alien_defs[CD_URANUSBOSSWING2].AIType = AI_OFFENSIVE;
864 alien_defs[CD_URANUSBOSSWING2].AITypeOriginal = AI_OFFENSIVE;
865 alien_defs[CD_URANUSBOSSWING2].speed = 4;
866 alien_defs[CD_URANUSBOSSWING2].maxShield = 250;
867 alien_defs[CD_URANUSBOSSWING2].shield = 250;
868 alien_defs[CD_URANUSBOSSWING2].imageIndex[0] = SS_URANUSBOSS_WING2;
869 alien_defs[CD_URANUSBOSSWING2].imageIndex[1] = SS_URANUSBOSS_WING2_L;
870 alien_defs[CD_URANUSBOSSWING2].weaponType[0] = W_DOUBLE_ROCKETS;
871 alien_defs[CD_URANUSBOSSWING2].weaponType[1] = W_DOUBLE_ROCKETS;
872 alien_defs[CD_URANUSBOSSWING2].chance[0] = 5;
873 alien_defs[CD_URANUSBOSSWING2].chance[1] = 0;
874 alien_defs[CD_URANUSBOSSWING2].collectChance = 100;
875 alien_defs[CD_URANUSBOSSWING2].collectType = P_ANYTHING;
876 alien_defs[CD_URANUSBOSSWING2].collectValue = 250;
877 alien_defs[CD_URANUSBOSSWING2].collectTypeOriginal = P_ANYTHING;
878 alien_defs[CD_URANUSBOSSWING2].collectValueOriginal = 250;
879 alien_defs[CD_URANUSBOSSWING2].score = 500;
880 alien_defs[CD_URANUSBOSSWING2].flags = FL_WEAPCO | FL_IMMORTAL | FL_DAMAGEOWNER;
881 }
882
aliens_init()883 void aliens_init()
884 {
885 int placeAttempt;
886 int barrierSpeed;
887
888 engine.targetIndex = -1;
889 barrierSpeed = 1;
890
891 for (int i = 0 ; i < ALIEN_MAX ; i++)
892 {
893 aliens[i].active = 0;
894 aliens[i].shield = -1;
895 aliens[i].flags = 0;
896 aliens[i].badTargetCount = 0;
897 }
898
899 switch (game.area)
900 {
901 case MISN_START:
902 aliens[0] = alien_defs[CD_TRANSPORTSHIP];
903 break;
904
905 case MISN_CERADSE:
906 aliens[0] = alien_defs[CD_CARGOSHIP];
907 aliens[1] = alien_defs[CD_CARGOSHIP];
908 aliens[2] = alien_defs[CD_CARGOSHIP];
909 aliens[3] = alien_defs[CD_CARGOSHIP];
910 aliens[4] = alien_defs[CD_CARGOSHIP];
911 aliens[5] = alien_defs[CD_CARGOSHIP];
912 break;
913
914 case MISN_HINSTAG:
915 aliens[0] = alien_defs[CD_MISSILEBOAT];
916 aliens[1] = alien_defs[CD_MISSILEBOAT];
917 aliens[2] = alien_defs[CD_MISSILEBOAT];
918 aliens[3] = alien_defs[CD_MISSILEBOAT];
919 aliens[4] = alien_defs[CD_MISSILEBOAT];
920 break;
921
922 case MISN_JOLDAR:
923 aliens[0] = alien_defs[CD_MINER];
924 aliens[1] = alien_defs[CD_MINER];
925 aliens[2] = alien_defs[CD_MINER];
926 aliens[3] = alien_defs[CD_MINER];
927 aliens[4] = alien_defs[CD_MINER];
928 aliens[5] = alien_defs[CD_MINER];
929 aliens[6] = alien_defs[CD_MINER];
930 aliens[7] = alien_defs[CD_MINER];
931 aliens[8] = alien_defs[CD_MINER];
932 break;
933
934 case MISN_MOEBO:
935 aliens[ALIEN_BOSS] = alien_defs[CD_FRIGATE];
936 aliens[ALIEN_BOSS_PART1] = alien_defs[CD_FRIGATE_WING1];
937 aliens[ALIEN_BOSS_PART2] = alien_defs[CD_FRIGATE_WING2];
938 break;
939
940 case MISN_NEROD:
941 aliens[0] = alien_defs[CD_CARGOSHIP];
942 break;
943
944 case MISN_ALLEZ:
945 aliens[ALIEN_FRIEND1] = alien_defs[CD_GOODTRANSPORT];
946 break;
947
948 case MISN_URUSOR:
949 aliens[ALIEN_BOSS_PART1] = alien_defs[CD_CARGOSHIP];
950 aliens[ALIEN_BOSS_PART2] = alien_defs[CD_CARGOSHIP];
951 aliens[ALIEN_BOSS_PART3] = alien_defs[CD_CARGOSHIP];
952 aliens[ALIEN_BOSS_PART4] = alien_defs[CD_CARGOSHIP];
953 aliens[ALIEN_BOSS_PART5] = alien_defs[CD_CARGOSHIP];
954 break;
955
956 case MISN_ELAMALE:
957 aliens[ALIEN_BOSS] = alien_defs[CD_MINEBOSS];
958 aliens[ALIEN_BOSS_PART1] = alien_defs[CD_BOSS2_WING1];
959 aliens[ALIEN_BOSS_PART2] = alien_defs[CD_BOSS2_WING2];
960 aliens[ALIEN_BOSS_PART3] = alien_defs[CD_BOSS2_WING3];
961 aliens[ALIEN_BOSS_PART4] = alien_defs[CD_BOSS2_WING4];
962 aliens[ALIEN_KLINE] = alien_defs[CD_KLINE];
963 aliens[ALIEN_BOSS_PART5] = alien_defs[CD_SLAVETRANSPORT];
964 aliens[ALIEN_BOSS_PART6] = alien_defs[CD_SLAVETRANSPORT];
965 break;
966
967 case MISN_ODEON:
968 aliens[ALIEN_BOSS] = alien_defs[CD_EVILURSULA];
969 break;
970
971 case MISN_FELLON:
972 aliens[ALIEN_BOSS] = alien_defs[CD_MINEBOSS];
973 aliens[ALIEN_BOSS_PART1] = alien_defs[CD_BOSS2_WING1];
974 aliens[ALIEN_BOSS_PART2] = alien_defs[CD_BOSS2_WING2];
975 aliens[ALIEN_BOSS_PART3] = alien_defs[CD_BOSS2_WING3];
976 aliens[ALIEN_BOSS_PART4] = alien_defs[CD_BOSS2_WING4];
977 aliens[ALIEN_FRIEND1] = alien_defs[CD_REBELCARRIER];
978 aliens[ALIEN_FRIEND2] = alien_defs[CD_REBELCARRIER];
979 break;
980
981 case MISN_ALMARTHA:
982 aliens[ALIEN_BOSS_PART1] = alien_defs[CD_CLOAKFIGHTER];
983 aliens[ALIEN_BOSS_PART2] = alien_defs[CD_CLOAKFIGHTER];
984 aliens[ALIEN_BOSS_PART3] = alien_defs[CD_CLOAKFIGHTER];
985 aliens[ALIEN_FRIEND1] = alien_defs[CD_KRASS];
986 break;
987
988 case MISN_POSWIC:
989 aliens[0] = alien_defs[CD_ESCORT];
990 aliens[1] = alien_defs[CD_ESCORT];
991 aliens[2] = alien_defs[CD_ESCORT];
992 aliens[3] = alien_defs[CD_ESCORT];
993 aliens[4] = alien_defs[CD_ESCORT];
994 aliens[ALIEN_BOSS] = alien_defs[CD_EXEC];
995 break;
996
997 case MISN_ELLESH:
998 aliens[ALIEN_BOSS] = alien_defs[CD_EXEC];
999 break;
1000
1001 case MISN_PLUTO:
1002 aliens[ALIEN_BOSS] = alien_defs[CD_PLUTOBOSS];
1003 aliens[ALIEN_BOSS_PART1] = alien_defs[CD_BARRIER];
1004 aliens[ALIEN_BOSS_PART2] = alien_defs[CD_BARRIER];
1005 aliens[ALIEN_BOSS_PART3] = alien_defs[CD_BARRIER];
1006 aliens[ALIEN_BOSS_PART4] = alien_defs[CD_BARRIER];
1007 aliens[ALIEN_BOSS_PART5] = alien_defs[CD_BARRIER];
1008 aliens[ALIEN_BOSS_PART6] = alien_defs[CD_BARRIER];
1009 break;
1010
1011 case MISN_NEPTUNE:
1012 aliens[ALIEN_BOSS] = alien_defs[CD_NEPTUNEBOSS];
1013 aliens[ALIEN_BOSS_PART1] = alien_defs[CD_MOBILESHIELD];
1014 aliens[ALIEN_BOSS_PART2] = alien_defs[CD_MOBILESHIELD];
1015 aliens[ALIEN_BOSS_PART3] = alien_defs[CD_MOBILESHIELD];
1016 aliens[ALIEN_BOSS_PART4] = alien_defs[CD_MOBILESHIELD];
1017 aliens[ALIEN_BOSS_PART5] = alien_defs[CD_MOBILESHIELD];
1018 break;
1019
1020 case MISN_URANUS:
1021 aliens[ALIEN_BOSS] = alien_defs[CD_URANUSBOSS];
1022 aliens[ALIEN_BOSS_PART1] = alien_defs[CD_URANUSBOSSWING1];
1023 aliens[ALIEN_BOSS_PART2] = alien_defs[CD_URANUSBOSSWING2];
1024 break;
1025
1026 case MISN_SATURN:
1027 aliens[ALIEN_BOSS_PART1] = alien_defs[CD_MOBILE_RAY];
1028 aliens[ALIEN_BOSS_PART2] = alien_defs[CD_MOBILE_RAY];
1029 aliens[ALIEN_BOSS_PART3] = alien_defs[CD_MOBILE_RAY];
1030 aliens[ALIEN_BOSS_PART4] = alien_defs[CD_MOBILE_RAY];
1031 aliens[ALIEN_BOSS_PART5] = alien_defs[CD_MOBILE_RAY];
1032 aliens[ALIEN_BOSS_PART6] = alien_defs[CD_MOBILE_RAY];
1033 break;
1034
1035 case MISN_JUPITER:
1036 aliens[ALIEN_BOSS] = alien_defs[CD_KRASS];
1037 aliens[ALIEN_BOSS_PART1] = alien_defs[CD_FIREFLY];
1038 aliens[ALIEN_BOSS_PART2] = alien_defs[CD_FIREFLY];
1039 aliens[ALIEN_BOSS_PART3] = alien_defs[CD_FIREFLY];
1040 aliens[ALIEN_BOSS_PART4] = alien_defs[CD_FIREFLY];
1041 break;
1042
1043 case MISN_EARTH:
1044 case MISN_VENUS:
1045 aliens[ALIEN_KLINE] = alien_defs[CD_KLINE];
1046 break;
1047 }
1048
1049 for (int i = 0 ; i < ALIEN_MAX ; i++)
1050 {
1051 if (aliens[i].shield != -1)
1052 {
1053 placeAttempt = 0;
1054
1055 aliens[i].owner = &aliens[i];
1056 aliens[i].target = &aliens[i];
1057 aliens[i].face = RANDRANGE(0, 1);
1058 aliens[i].active = 1;
1059
1060 /*
1061 we make 1000 attempts to place this enemy since it is required. If after
1062 1000 attempts we still haven't managed to place the alien, then it
1063 simply isn't going to happen and we will just exit the game. The chances
1064 of this happening are very very low!
1065 */
1066 while (1)
1067 {
1068 placeAttempt++;
1069
1070 if (alien_place(&aliens[i]))
1071 break;
1072
1073 if (placeAttempt > 1000)
1074 engine_showError(2, "");
1075 }
1076
1077 if (game.area == MISN_CERADSE)
1078 cargo_add(&aliens[i], P_CARGO);
1079 else if (game.area == MISN_NEROD)
1080 cargo_add(&aliens[i], P_PHOEBE);
1081
1082 if (i == ALIEN_KLINE)
1083 {
1084 aliens[ALIEN_KLINE].target = &player;
1085 }
1086
1087 if (aliens[i].classDef == CD_CLOAKFIGHTER)
1088 {
1089 aliens[i].active = 0;
1090 aliens[i].maxShield = 400;
1091 aliens[i].shield = 400;
1092 aliens[i].flags &= ~FL_RUNSAWAY;
1093 aliens[i].speed = 3;
1094 }
1095
1096 if ((aliens[i].classDef == CD_MOBILE_RAY) && (i >= ALIEN_BOSS_PART3))
1097 {
1098 aliens[i].active = 0;
1099 }
1100
1101 if (aliens[i].classDef == CD_FIREFLY)
1102 {
1103 aliens[i].active = 0;
1104 }
1105
1106 if (aliens[i].classDef == CD_BARRIER)
1107 {
1108 aliens[i].owner = &aliens[ALIEN_BOSS];
1109 aliens[i].speed = barrierSpeed;
1110 barrierSpeed++;
1111 }
1112
1113 if ((game.area == MISN_POSWIC)
1114 && (aliens[i].classDef == CD_BOSS))
1115 {
1116 aliens[i].flags |= FL_IMMORTAL;
1117 }
1118
1119 if (game.area == MISN_ELLESH)
1120 aliens[i].flags |= FL_HASMINIMUMSPEED;
1121
1122 if (game.area == MISN_JUPITER)
1123 {
1124 aliens[i].flags = FL_WEAPCO | FL_NOBANTER;
1125 if (i == ALIEN_BOSS)
1126 aliens[i].chance[1] = 5;
1127 }
1128 }
1129 }
1130
1131 if (game.area == MISN_MOEBO)
1132 {
1133 aliens[ALIEN_BOSS].target = &player;
1134 aliens[ALIEN_BOSS].x = -screen->w / 2;
1135 aliens[ALIEN_BOSS].y = screen->h / 2;
1136
1137 aliens[ALIEN_BOSS_PART1].owner = &aliens[ALIEN_BOSS];
1138 aliens[ALIEN_BOSS_PART1].target = &player;
1139 aliens[ALIEN_BOSS_PART1].dx = -25;
1140 aliens[ALIEN_BOSS_PART1].dy = -21;
1141
1142 aliens[ALIEN_BOSS_PART2].owner = &aliens[ALIEN_BOSS];
1143 aliens[ALIEN_BOSS_PART2].target = &player;
1144 aliens[ALIEN_BOSS_PART2].dx = -20;
1145 aliens[ALIEN_BOSS_PART2].dy = 37;
1146 }
1147 else if ((game.area == MISN_ELAMALE)
1148 || (game.area == MISN_FELLON))
1149 {
1150 aliens[ALIEN_BOSS].target = &player;
1151 aliens[ALIEN_BOSS].x = -screen->w / 2;
1152 aliens[ALIEN_BOSS].y = screen->h / 2;
1153
1154 aliens[ALIEN_BOSS_PART1].owner = &aliens[ALIEN_BOSS_PART2];
1155 aliens[ALIEN_BOSS_PART1].target = &player;
1156 aliens[ALIEN_BOSS_PART1].dx = -35;
1157 aliens[ALIEN_BOSS_PART1].dy = -12;
1158
1159 aliens[ALIEN_BOSS_PART2].owner = &aliens[ALIEN_BOSS];
1160 aliens[ALIEN_BOSS_PART2].target = &player;
1161 aliens[ALIEN_BOSS_PART2].dx = 15;
1162 aliens[ALIEN_BOSS_PART2].dy = -22;
1163
1164 aliens[ALIEN_BOSS_PART3].owner = &aliens[ALIEN_BOSS];
1165 aliens[ALIEN_BOSS_PART3].target = &player;
1166 aliens[ALIEN_BOSS_PART3].dx = 15;
1167 aliens[ALIEN_BOSS_PART3].dy = 22;
1168
1169 aliens[ALIEN_BOSS_PART4].owner = &aliens[ALIEN_BOSS_PART3];
1170 aliens[ALIEN_BOSS_PART4].target = &player;
1171 aliens[ALIEN_BOSS_PART4].dx = -35;
1172 aliens[ALIEN_BOSS_PART4].dy = 20;
1173
1174 if (game.area == MISN_FELLON)
1175 {
1176 aliens[ALIEN_BOSS].AIType = AI_EVASIVE;
1177 }
1178 }
1179 else if (game.area == MISN_URANUS)
1180 {
1181 aliens[ALIEN_BOSS].target = &player;
1182 aliens[ALIEN_BOSS].x = -screen->w / 2;
1183 aliens[ALIEN_BOSS].y = screen->h / 2;
1184
1185 aliens[ALIEN_BOSS_PART1].owner = &aliens[ALIEN_BOSS];
1186 aliens[ALIEN_BOSS_PART1].dy = -16;
1187
1188 aliens[ALIEN_BOSS_PART2].owner = &aliens[ALIEN_BOSS];
1189 aliens[ALIEN_BOSS_PART2].dy = 20;
1190 }
1191 }
1192
alien_add()1193 int alien_add()
1194 {
1195 int index = alien_getFreeIndex();
1196
1197 if ((index == -1) || (game.area == MISN_JUPITER)
1198 || (game.area == MISN_VENUS))
1199 return 0;
1200
1201 int *alienArray;
1202 int numberOfAliens = 1;
1203
1204 alienArray = malloc(8 * sizeof(*alienArray));
1205 if (alienArray == NULL)
1206 {
1207 engine_warn("Failed to allocate memory for aliens");
1208 return 0;
1209 }
1210
1211 switch(game.area)
1212 {
1213 case MISN_START:
1214 case MISN_HINSTAG:
1215 case MISN_ELAMALE:
1216 numberOfAliens = 1;
1217 alienArray[0] = CD_DUALFIGHTER;
1218 break;
1219 case MISN_HAIL:
1220 case MISN_CERADSE:
1221 case MISN_JOLDAR:
1222 case MISN_MOEBO:
1223 numberOfAliens = 2;
1224 alienArray[0] = CD_DUALFIGHTER;
1225 alienArray[1] = CD_PROTOFIGHTER;
1226 break;
1227 case MISN_NEROD:
1228 case MISN_ALLEZ:
1229 numberOfAliens = 3;
1230 alienArray[0] = CD_DUALFIGHTER;
1231 alienArray[1] = CD_PROTOFIGHTER;
1232 alienArray[2] = CD_AIMFIGHTER;
1233 break;
1234 case MISN_URUSOR:
1235 // This is the mission where you need to disable cargo ships.
1236 // Missiles are extremely bad in this mission, not because
1237 // of the damage they do to you, but because they tend to
1238 // accidentally destroy the cargo ships. Therefore, ships
1239 // with missiles (dual fighters and missile boats) are
1240 // excluded from this mission.
1241 numberOfAliens = 2;
1242 alienArray[0] = CD_PROTOFIGHTER;
1243 alienArray[1] = CD_AIMFIGHTER;
1244 // ...That is, unless we're in Classic difficulty, because
1245 // the original game actually had these enemies.
1246 if (game.difficulty == DIFFICULTY_ORIGINAL)
1247 {
1248 numberOfAliens = 4;
1249 alienArray[2] = CD_DUALFIGHTER;
1250 alienArray[3] = CD_MISSILEBOAT;
1251 }
1252 break;
1253 case MISN_DORIM:
1254 case MISN_SIVEDI:
1255 numberOfAliens = 1;
1256 alienArray[0] = CD_ASTEROID;
1257 break;
1258 case MISN_ODEON:
1259 case MISN_FELLON:
1260 case MISN_ALMARTHA:
1261 numberOfAliens = 4;
1262 alienArray[0] = CD_DUALFIGHTER;
1263 alienArray[1] = CD_PROTOFIGHTER;
1264 alienArray[2] = CD_MISSILEBOAT;
1265 alienArray[3] = CD_AIMFIGHTER;
1266 break;
1267 case MISN_ELLESH:
1268 numberOfAliens = 2;
1269 alienArray[0] = CD_DUALFIGHTER;
1270 alienArray[1] = CD_MINER;
1271 break;
1272 case MISN_SATURN:
1273 numberOfAliens = 2;
1274 alienArray[0] = CD_AIMFIGHTER;
1275 alienArray[1] = CD_DUALFIGHTER;
1276 break;
1277 case MISN_MARS:
1278 numberOfAliens = 2;
1279 alienArray[0] = CD_ASTEROID;
1280 alienArray[1] = CD_ASTEROID2;
1281 break;
1282 case MISN_EARTH:
1283 numberOfAliens = 6;
1284 alienArray[0] = CD_DUALFIGHTER;
1285 alienArray[1] = CD_PROTOFIGHTER;
1286 alienArray[2] = CD_MISSILEBOAT;
1287 alienArray[3] = CD_AIMFIGHTER;
1288 alienArray[4] = CD_ESCORT;
1289 alienArray[5] = CD_MOBILE_RAY;
1290 break;
1291 case MISN_INTERCEPTION:
1292 numberOfAliens = 1;
1293 alienArray[0] = CD_DUALFIGHTER;
1294 if (game.system > SYSTEM_SPIRIT)
1295 {
1296 numberOfAliens = 3;
1297 alienArray[1] = CD_MISSILEBOAT;
1298 alienArray[2] = CD_AIMFIGHTER;
1299 if (game.system == SYSTEM_MORDOR)
1300 {
1301 numberOfAliens = 4;
1302 alienArray[3] = CD_PROTOFIGHTER;
1303 }
1304 }
1305 break;
1306 default:
1307 numberOfAliens = 1;
1308 alienArray[0] = CD_DUALFIGHTER;
1309 break;
1310 }
1311
1312 int randEnemy = alienArray[rand() % numberOfAliens];
1313
1314 if ((game.area != MISN_DORIM)
1315 && (game.area != MISN_SIVEDI)
1316 && (game.area != MISN_MARS))
1317 {
1318 if ((game.system == SYSTEM_EYANANTH) && (game.area == MISN_INTERCEPTION))
1319 {
1320 if (CHANCE(1. / 5.))
1321 randEnemy = CD_SLAVETRANSPORT;
1322 }
1323
1324 if (CHANCE(1. / 6.))
1325 randEnemy = CD_TRANSPORTSHIP;
1326 }
1327
1328 free(alienArray);
1329
1330 aliens[index] = alien_defs[randEnemy];
1331 aliens[index].active = 1;
1332 aliens[index].face = RANDRANGE(0, 1);
1333 aliens[index].owner = &aliens[index]; // Most enemies will own themselves
1334 aliens[index].target = &aliens[index];
1335 aliens[index].thinktime = RANDRANGE(50, 100);
1336 aliens[index].systemPower = aliens[index].maxShield;
1337 aliens[index].deathCounter = 0 - (aliens[index].maxShield * 3);
1338 aliens[index].hit = 0;
1339
1340 LIMIT(aliens[index].deathCounter, -250, 0);
1341
1342 // Attempts to place an alien. If it fails, the alien is deactivated.
1343 if (!alien_place(&aliens[index]))
1344 {
1345 aliens[index].active = 0;
1346 return 0;
1347 }
1348
1349 if (aliens[index].classDef == CD_CARGOSHIP)
1350 cargo_add(&aliens[index], P_CARGO);
1351
1352 if (aliens[index].classDef == CD_MOBILE_RAY)
1353 aliens[index].shield = 25;
1354
1355 if (aliens[index].classDef == CD_ESCORT)
1356 aliens[index].shield = 50;
1357
1358 aliens[index].dx = RANDRANGE(-2, 2);
1359 aliens[index].dy = RANDRANGE(-2, 2);
1360
1361 aliens[index].ammo[0] = 0;
1362
1363 if (game.area == MISN_ELLESH)
1364 aliens[index].flags |= FL_HASMINIMUMSPEED;
1365
1366 alien_nerf(index);
1367
1368 return 1;
1369 }
1370
alien_addDrone(Object * hostAlien)1371 void alien_addDrone(Object *hostAlien)
1372 {
1373 int index = alien_getFreeIndex();
1374
1375 if (index == -1)
1376 return;
1377
1378 aliens[index] = alien_defs[CD_DRONE];
1379 aliens[index].active = 1;
1380 aliens[index].face = RANDRANGE(0, 1);
1381 aliens[index].owner = &aliens[index]; // Most enemies will own themselves
1382 aliens[index].target = &aliens[index];
1383 aliens[index].thinktime = RANDRANGE(50, 100);
1384 aliens[index].systemPower = aliens[index].maxShield;
1385 aliens[index].deathCounter = 0 - (aliens[index].maxShield * 3);
1386 aliens[index].hit = 0;
1387
1388 aliens[index].x = hostAlien->x + RANDRANGE(0, 50);
1389 aliens[index].y = hostAlien->y + RANDRANGE(0, 50);
1390
1391 alien_nerf(index);
1392 }
1393
alien_addSmallAsteroid(Object * hostAlien)1394 void alien_addSmallAsteroid(Object *hostAlien)
1395 {
1396 if (engine.missionCompleteTimer != 0)
1397 return;
1398
1399 int index = -1;
1400 int debris = RANDRANGE(1, 10);
1401
1402 for (int i = 0 ; i < debris ; i++)
1403 bullet_add(&weapons[W_ROCKETS], hostAlien, 0, 0);
1404
1405 for (int i = 0 ; i <= ALIEN_NORMAL_LAST ; i++)
1406 if (!aliens[i].active)
1407 index = i;
1408
1409 if (index == -1)
1410 return;
1411
1412 if (CHANCE(3 / 5.))
1413 {
1414 aliens[index] = alien_defs[CD_ASTEROID2];
1415 aliens[index].imageIndex[0] = RANDRANGE(SS_ASTEROID_SMALL, SS_ASTEROID_SMALL_L);
1416 aliens[index].imageIndex[1] = aliens[index].imageIndex[0];
1417 aliens[index].image[0] = gfx_shipSprites[aliens[index].imageIndex[0]];
1418 aliens[index].image[1] = gfx_shipSprites[aliens[index].imageIndex[1]];
1419 }
1420 else
1421 {
1422 aliens[index] = alien_defs[CD_DRONE];
1423 }
1424
1425 aliens[index].owner = &aliens[index]; // Most enemies will own themselves
1426 aliens[index].target = &aliens[index];
1427 aliens[index].thinktime = 1;
1428 aliens[index].systemPower = aliens[index].maxShield;
1429 aliens[index].deathCounter = 0 - (aliens[index].maxShield * 3);
1430 aliens[index].hit = 0;
1431
1432 aliens[index].x = hostAlien->x;
1433 aliens[index].y = hostAlien->y;
1434 aliens[index].active = 1;
1435 }
1436
alien_addFriendly(int type)1437 void alien_addFriendly(int type)
1438 {
1439 if (type != ALIEN_SID)
1440 aliens[type] = alien_defs[CD_FRIEND];
1441 else
1442 aliens[type] = alien_defs[CD_SID];
1443
1444 aliens[type].owner = &aliens[type];
1445 aliens[type].target = &aliens[type];
1446 aliens[type].active = 1;
1447 aliens[type].x = RANDRANGE((screen->w / 2) - 150, (screen->w / 2) + 150);
1448 aliens[type].y = RANDRANGE((screen->h / 2) - 150, (screen->h / 2) + 150);
1449
1450 if (type == ALIEN_PHOEBE)
1451 aliens[type].classDef = CD_PHOEBE;
1452
1453 if (type == ALIEN_URSULA)
1454 aliens[type].classDef = CD_URSULA;
1455
1456 // For the sake of it being the final battle :)
1457 if (game.area == MISN_EARTH)
1458 aliens[type].flags |= FL_IMMORTAL;
1459
1460 alien_nerf(type);
1461 }
1462
alien_place(Object * alien)1463 int alien_place(Object *alien)
1464 {
1465 if (CHANCE(0.5))
1466 alien->x = RANDRANGE(screen->w, screen->w * 2);
1467 else
1468 alien->x = RANDRANGE(-screen->w, 0);
1469
1470 if (CHANCE(0.5))
1471 alien->y = RANDRANGE(screen->h, screen->h * 2);
1472 else
1473 alien->y = RANDRANGE(-screen->h, 0);
1474
1475 if (game.area == MISN_MARS)
1476 {
1477 if (game.difficulty == DIFFICULTY_SUPEREASY)
1478 {
1479 alien->x = screen->w + RANDRANGE(0, 1200);
1480 alien->y = RANDRANGE(-screen->h, screen->h);
1481 }
1482 else
1483 {
1484 alien->x = screen->w + RANDRANGE(0, 400);
1485 alien->y = RANDRANGE(-screen->h / 3, (4 * screen->h) / 3);
1486 }
1487 }
1488
1489 for (int i = 0 ; i < ALIEN_MAX ; i++)
1490 {
1491 if ((aliens[i].owner != alien) && (aliens[i].shield > 0))
1492 {
1493 if (ship_collision(alien, &aliens[i]))
1494 return 0;
1495 }
1496 }
1497
1498 return 1;
1499 }
1500
alien_setAI(Object * alien)1501 void alien_setAI(Object *alien)
1502 {
1503 int i;
1504 float tx;
1505 float ty;
1506
1507 int chase = 0; // Chance in 10 of chasing player
1508 int area = 0; // Chance in 10 of moving to an area around the player
1509 int stop = 0; // Chance in 10 of hanging back
1510 int point = 0; // Size of area alien will move into
1511
1512 // Make friendly craft generally concentrate on smaller fighters
1513 if ((alien->flags & FL_FRIEND) && (alien->target == &aliens[ALIEN_BOSS]))
1514 {
1515 if (CHANCE(0.2))
1516 {
1517 alien->target = alien;
1518 alien->thinktime = 0;
1519 return;
1520 }
1521 }
1522
1523 i = RANDRANGE(0, 9);
1524 tx = alien->target->x;
1525 ty = alien->target->y;
1526
1527 switch ((game.difficulty == DIFFICULTY_ORIGINAL) ?
1528 alien->AITypeOriginal : alien->AIType)
1529 {
1530 case AI_NORMAL:
1531 chase = 3;
1532 point = 6;
1533 stop = 9;
1534 area = 250;
1535 break;
1536 case AI_OFFENSIVE:
1537 chase = 7;
1538 point = 8;
1539 stop = 9;
1540 area = 50;
1541 break;
1542 case AI_DEFENSIVE:
1543 chase = 2;
1544 point = 6;
1545 stop = 8;
1546 area = 300;
1547 break;
1548 case AI_EVASIVE:
1549 chase = 1;
1550 point = 8;
1551 stop = 9;
1552 area = 600;
1553 break;
1554 case AI_WANDER:
1555 chase = -1;
1556 point = 0;
1557 stop = 10;
1558 area = 1200;
1559 break;
1560 }
1561
1562 if (i <= chase)
1563 {
1564 // Chase the target
1565 alien->dx = ((alien->x - tx) / ((300 / alien->speed) + RANDRANGE(0, 100)));
1566 alien->dy = ((alien->y - ty) / ((300 / alien->speed) + RANDRANGE(0, 100)));
1567 return;
1568 }
1569 else if ((i >= point) && (i <= stop))
1570 {
1571 // Fly to a random point around the target
1572 tx += RANDRANGE(-area, area);
1573 ty += RANDRANGE(-area, area);
1574 alien->dx = ((alien->x - tx) / ((300 / alien->speed) + RANDRANGE(0, 100)));
1575 alien->dy = ((alien->y - ty) / ((300 / alien->speed) + RANDRANGE(0, 100)));
1576 return;
1577 }
1578 else
1579 {
1580 // Hang back
1581 alien->dx = 0;
1582 alien->dy = 0;
1583 return;
1584 }
1585 }
1586
alien_setKlineAttackMethod(Object * alien)1587 void alien_setKlineAttackMethod(Object *alien)
1588 {
1589 if (alien->shield <= alien->maxShield / 4)
1590 {
1591 /// Dialog (Kline Kethlan)
1592 /// Used when the final "stage" of the Venus fight is entered.
1593 radio_setMessage(FS_KLINE, _("ENOUGH! THIS ENDS NOW!"), 1);
1594 alien->weaponType[0] = W_AIMED_SHOT;
1595 alien->weaponType[1] = W_MICRO_HOMING_MISSILES;
1596 alien->flags |= FL_CANCLOAK;
1597 alien->chance[0] = 100;
1598 alien->chance[1] = 2;
1599 }
1600 else if (alien->shield <= alien->maxShield / 2)
1601 {
1602 /// Dialog (Kline Kethlan)
1603 /// Used when the third "stage" of the Vinus fight is entered.
1604 radio_setMessage(FS_KLINE, _("Your ability to stay alive irritates me! Try dodging some of these!"), 1);
1605 if (game.difficulty == DIFFICULTY_ORIGINAL)
1606 {
1607 alien->weaponType[0] = W_DIRSHOCKMISSILE;
1608 alien->chance[0] = 2;
1609 }
1610 alien->weaponType[1] = W_DIRSHOCKMISSILE;
1611 alien->chance[1] = 2;
1612 alien->flags |= FL_AIMS;
1613 }
1614 else
1615 {
1616 /// Dialog (Kline Kethlan)
1617 /// Used when the second "stage" of the Venus fight is entered.
1618 radio_setMessage(FS_KLINE, _("Very good, Bainfield. Now let's get a little more serious..."), 1);
1619 alien->weaponType[0] = W_SPREADSHOT;
1620 alien->chance[1] = 40;
1621 }
1622 }
1623
1624 /*
1625 This AI is exclusively for Kline.
1626 */
alien_setKlineAI(Object * alien)1627 void alien_setKlineAI(Object *alien)
1628 {
1629 int threshold;
1630
1631 // Weapon type change
1632 if (CHANCE(1. / 3.))
1633 {
1634 if ((game.area != MISN_VENUS)
1635 || (game.difficulty != DIFFICULTY_ORIGINAL))
1636 {
1637 alien->flags &= ~FL_AIMS;
1638
1639 if (CHANCE(0.5))
1640 {
1641 if (game.difficulty == DIFFICULTY_SUPEREASY)
1642 threshold = 750;
1643 else
1644 threshold = 1500;
1645
1646 if ((game.area != MISN_VENUS)
1647 || (alien->shield > threshold))
1648 alien->weaponType[0] = W_TRIPLE_SHOT;
1649 else
1650 alien->weaponType[0] = W_SPREADSHOT;
1651 }
1652 else
1653 {
1654 alien->weaponType[0] = W_AIMED_SHOT;
1655 alien->flags |= FL_AIMS;
1656
1657 }
1658 }
1659 }
1660
1661 alien->flags &= ~(FL_CIRCLES | FL_CONTINUOUS_FIRE | FL_DROPMINES);
1662
1663 switch(RANDRANGE(0, 9))
1664 {
1665 case 0:
1666 if ((alien->weaponType[0] != W_DIRSHOCKMISSILE)
1667 && (alien->weaponType[1] != W_MICRO_HOMING_MISSILES))
1668 alien->flags |= FL_CONTINUOUS_FIRE;
1669 alien->dx = ((alien->x - alien->target->x) /
1670 ((300 / alien->speed) + RANDRANGE(0, 100)));
1671 alien->dy = ((alien->y - alien->target->y) /
1672 ((300 / alien->speed) + RANDRANGE(0, 100)));
1673 break;
1674 case 1:
1675 case 2:
1676 // Kline only attacks when he is ready!
1677 if ((!(alien->flags & FL_NOFIRE))
1678 && ((game.area == MISN_ELAMALE)
1679 || game.difficulty != DIFFICULTY_ORIGINAL))
1680 alien->flags |= FL_DROPMINES;
1681 break;
1682 case 3:
1683 case 4:
1684 alien->flags |= FL_CIRCLES;
1685 break;
1686 default:
1687 alien_setAI(alien);
1688 break;
1689 }
1690 }
1691
1692 /*
1693 "Looks" for an enemy by picking a randomly active enemy and using them
1694 as a target. If the target is too far away, it will be ignored.
1695 */
alien_searchForTarget(Object * alien)1696 void alien_searchForTarget(Object *alien)
1697 {
1698 int i;
1699 Object *targetEnemy;
1700 int badTarget = 0;
1701
1702 if (alien->flags & FL_WEAPCO)
1703 {
1704 if (CHANCE(1 / 10.))
1705 {
1706 alien->target = &player;
1707 alien->badTargetCount = 0;
1708 return;
1709 }
1710 }
1711
1712 i = rand() % ALIEN_MAX;
1713 targetEnemy = &aliens[i];
1714
1715 // Tell Sid not to attack craft that are already disabled or can
1716 // return fire. This will save him from messing about (unless we're on the last mission)
1717 if ((alien->classDef == CD_SID) && (game.area != MISN_EARTH))
1718 {
1719 if (targetEnemy->flags & FL_DISABLED)
1720 return;
1721
1722 if (game.difficulty == DIFFICULTY_ORIGINAL)
1723 {
1724 if (!(targetEnemy->flags & FL_NOFIRE))
1725 badTarget = 1;
1726 }
1727 else
1728 {
1729 if ((targetEnemy->classDef != CD_CARGOSHIP)
1730 && (targetEnemy->classDef != CD_BOSS))
1731 {
1732 badTarget = 1;
1733 }
1734 }
1735 }
1736
1737 // Tell Phoebe and Ursula not to attack ships that cannot fire or are disabled (unless we're on the last mission)
1738 if (game.area != MISN_EARTH)
1739 {
1740 if ((alien->classDef == CD_PHOEBE) || (alien->classDef == CD_URSULA))
1741 {
1742 // Don't attack the boss or we could be here all day(!)
1743 if (targetEnemy->classDef == CD_BOSS)
1744 return;
1745
1746 if ((targetEnemy->flags & FL_DISABLED)
1747 || (targetEnemy->flags & FL_NOFIRE))
1748 badTarget = 1;
1749 }
1750 }
1751
1752 if ((targetEnemy->shield < 1) || (!targetEnemy->active))
1753 return;
1754
1755 if ((targetEnemy->flags & FL_WEAPCO) && (alien->flags & FL_WEAPCO))
1756 return;
1757
1758 if ((targetEnemy->flags & FL_FRIEND) && (alien->flags & FL_FRIEND))
1759 return;
1760
1761 if (abs((int)alien->x - (int)alien->target->x) > 550)
1762 badTarget = 1;
1763
1764 if (abs((int)alien->y - (int)alien->target->y) > 400)
1765 badTarget = 1;
1766
1767 if (badTarget)
1768 {
1769 if (game.difficulty == DIFFICULTY_ORIGINAL)
1770 {
1771 return;
1772 }
1773 else
1774 {
1775 alien->badTargetCount++;
1776 if (alien->badTargetCount < BAD_TARGET_ALLOW_TIME)
1777 return;
1778 }
1779 }
1780
1781 alien->target = targetEnemy;
1782 alien->badTargetCount = 0;
1783 }
1784
1785 /*
1786 Do various checks to see if the alien can fire at the target.
1787 */
alien_checkTarget(Object * alien)1788 int alien_checkTarget(Object *alien)
1789 {
1790 // No target
1791 if (alien->target == alien)
1792 return 0;
1793
1794 // Whilst firing a Ray, no other weapons can be fired!
1795 if (alien->flags & FL_FIRERAY)
1796 return 0;
1797
1798 // The target is on the same side as you!
1799 if ((alien->flags & FL_WEAPCO) && (alien->target->flags & FL_WEAPCO))
1800 return 0;
1801 if ((alien->flags & FL_FRIEND) && (alien->target->flags & FL_FRIEND))
1802 return 0;
1803
1804 // You're facing the wrong way
1805 if ((alien->face == 0) && (alien->target->x < alien->x))
1806 return 0;
1807 if ((alien->face == 1) && (alien->target->x > alien->x))
1808 return 0;
1809
1810 // Slightly more than half a screen away from you
1811 if (abs((int)alien->x - (int)alien->target->x) > 550)
1812 return 0;
1813
1814 if ((alien->flags & FL_AIMS) || (alien->flags & FL_CONTINUOUS_FIRE))
1815 return 1;
1816
1817 // Not at the correct vertical height
1818 if ((alien->y < alien->target->y - 15)
1819 || (alien->y > alien->target->y + alien->target->image[0]->h + 15))
1820 return 0;
1821
1822 return 1;
1823 }
1824
1825 /*
1826 Currently only used for the allies. Whilst flying around, the allies will fire on
1827 any enemy craft that enter their line of sight.
1828 */
alien_enemiesInFront(Object * alien)1829 int alien_enemiesInFront(Object *alien)
1830 {
1831 for (int i = 0 ; i < ALIEN_MAX ; i++)
1832 {
1833 if ((alien != &aliens[i]) && (aliens[i].flags & FL_WEAPCO)
1834 && (aliens[i].shield > 0))
1835 {
1836 if ((alien->y > aliens[i].y - 15)
1837 && (alien->y < aliens[i].y + aliens[i].image[0]->h + 15))
1838 {
1839 if ((alien->face == 1) && (aliens[i].x < alien->x))
1840 return 1;
1841 if ((alien->face == 0) && (aliens[i].x > alien->x))
1842 return 1;
1843 }
1844 }
1845 }
1846
1847 return 0;
1848 }
1849
alien_move(Object * alien)1850 void alien_move(Object *alien)
1851 {
1852 int checkCollisions;
1853 int collided = 0;
1854
1855 if ((alien->flags & FL_LEAVESECTOR) || (alien->shield < 1))
1856 checkCollisions = 0;
1857 else
1858 checkCollisions = 1;
1859
1860 if (alien->owner == alien)
1861 {
1862 if ((alien->flags & FL_CIRCLES) && (!(alien->flags & FL_LEAVESECTOR)))
1863 {
1864 if (alien->face == 0)
1865 {
1866 alien->dx += 0.02;
1867 alien->dy += 0.02;
1868 }
1869 else
1870 {
1871 alien->dx -= 0.02;
1872 alien->dy -= 0.02;
1873 }
1874
1875 alien->x -= (sinf(alien->dx) * 4);
1876 alien->y -= (cosf(alien->dy) * 4);
1877 }
1878 else
1879 {
1880 alien->x -= alien->dx;
1881 alien->y -= alien->dy;
1882 }
1883 }
1884
1885 if (checkCollisions)
1886 {
1887 for (int i = 0 ; i < ALIEN_MAX ; i++)
1888 {
1889 if ((aliens[i].owner != alien) && (aliens[i].active)
1890 && (aliens[i].shield > 0)
1891 && (!(aliens[i].flags & FL_LEAVESECTOR))
1892 && (alien->classDef != CD_BARRIER)
1893 && ship_collision(alien, &aliens[i]))
1894 {
1895 if ((game.difficulty == DIFFICULTY_ORIGINAL)
1896 && (alien->classDef != CD_DRONE)
1897 && (alien->classDef != CD_ASTEROID)
1898 && (alien->classDef != CD_ASTEROID2)
1899 && (alien->owner == alien)
1900 && (game.area != MISN_ELLESH))
1901 {
1902 collided = 1;
1903 }
1904
1905 if (aliens[i].classDef == CD_BARRIER)
1906 {
1907 alien->shield--;
1908 alien->hit = 3;
1909 alien->dx *= -1;
1910 alien->dy *= -1;
1911 audio_playSound(SFX_HIT, alien->x, alien->y);
1912 }
1913 }
1914 }
1915
1916 // Handle a collision with the player
1917 if ((player.shield > 0) && ship_collision(alien, &player))
1918 {
1919 if (alien->classDef == CD_ASTEROID)
1920 {
1921 player_damage(alien->shield, 0);
1922 alien->shield = 0;
1923 audio_playSound(SFX_EXPLOSION, alien->x, alien->y);
1924 }
1925
1926 if (alien->classDef == CD_ASTEROID2)
1927 {
1928 player_damage(alien->shield, 0);
1929 alien->shield = 0;
1930 audio_playSound(SFX_EXPLOSION, alien->x, alien->y);
1931 }
1932
1933 if (alien->classDef == CD_BARRIER)
1934 {
1935 player_damage(1, 0);
1936 }
1937 }
1938
1939 // Ship collision (only in Classic difficulty)
1940 if (collided)
1941 {
1942 if (alien->flags & FL_CIRCLES)
1943 {
1944 if (alien->face == 0)
1945 {
1946 alien->dx -= 0.02;
1947 alien->dy -= 0.02;
1948 }
1949 else
1950 {
1951 alien->dx += 0.02;
1952 alien->dy += 0.02;
1953 }
1954
1955 alien->x += (sinf(alien->dx) * 4);
1956 alien->y += (cosf(alien->dy) * 4);
1957
1958 alien->thinktime = 0;
1959 }
1960 else
1961 {
1962 alien->x += alien->dx;
1963 alien->y += alien->dy;
1964
1965 alien->dx *= -0.2;
1966 alien->dy *= -0.2;
1967
1968 LIMIT(alien->thinktime, 0, 15);
1969 }
1970 }
1971 }
1972 }
1973
1974 /*
1975 Fill in later...
1976 */
alien_destroy(Object * alien,Object * attacker)1977 void alien_destroy(Object *alien, Object *attacker)
1978 {
1979 int collect_type, collect_value, value;
1980 char msg[STRMAX];
1981
1982 audio_playSound(SFX_EXPLOSION, alien->x, alien->y);
1983
1984 // Chain reaction damage if needed (Classic Difficulty version)
1985 if ((game.difficulty == DIFFICULTY_ORIGINAL)
1986 && (alien->owner != alien) && (alien->flags & FL_DAMAGEOWNER))
1987 {
1988 alien_hurt(alien->owner, attacker, alien->maxShield, 0);
1989 }
1990
1991 if (alien->flags & FL_FRIEND)
1992 {
1993 if (alien->classDef == CD_PHOEBE)
1994 game.wingMate1Ejects++;
1995 else if (alien->classDef == CD_URSULA)
1996 game.wingMate2Ejects++;
1997
1998 // Phoebe cannot eject on the rescue mission
1999 if (game.area != MISN_NEROD)
2000 {
2001 if ((alien->classDef == CD_PHOEBE) || (alien->classDef == CD_URSULA))
2002 info_setLine(_(">> Ally has ejected! <<"), FONT_RED);
2003 else
2004 info_setLine(_(">> Friendly craft has been destroyed! <<"), FONT_RED);
2005 }
2006 }
2007
2008 if (attacker != NULL)
2009 {
2010 if (attacker == &player)
2011 {
2012 game.totalKills++;
2013 if (game.difficulty == DIFFICULTY_ORIGINAL)
2014 {
2015 if (game.area != MISN_INTERCEPTION)
2016 {
2017 game.cash += alien->score;
2018 game.cashEarned += alien->score;
2019 }
2020 }
2021
2022 if (CHANCE(1 / 16.) && (alien->flags & FL_WEAPCO)
2023 && (!(alien->flags & FL_NOBANTER)))
2024 {
2025 radio_getRandomMessage(msg, _(
2026 /// Chris brag messages
2027 /// This is a list of brags separated by "\n". They are randomly
2028 /// broadcast when Chris successfully kills an enemy.
2029 /// Instead of directly translating these, please populate the list
2030 /// with brag messages that work well in the target language,
2031 /// following the English version only as a general guideline. Any
2032 /// number of brag messages is permitted.
2033 "Take that, robot oppressors!\n"
2034 "Come on, WEAPCO, give me a challenge already!\n"
2035 "Is that all you've got?\n"
2036 "I could kill these robots with my hands tied behind my back!\n"
2037 "And now you're nothing but a pile of scrap metal!\n"
2038 "Who else wants some?!\n"
2039 "Humans do it better!\n"
2040 "A century of AI research is no match for me!\n"
2041 "What's the matter, WEAPCO? Can't keep up?\n"
2042 "I eat robots like you for breakfast!\n"
2043 "Target destroyed!\n"
2044 "Bring it on, WEAPCO!\n"
2045 "I wish the guys back at home could see this!\n"
2046 "How do you like that, WEAPCO?\n"
2047 "Maybe you should change your name to WEEPCO!"
2048 ));
2049 radio_setMessage(FS_CHRIS, msg, 0);
2050 }
2051 }
2052 else if (attacker->classDef == CD_PHOEBE)
2053 {
2054 game.wingMate1Kills++;
2055 if (CHANCE(1 / 8.) && (alien-> flags & FL_WEAPCO)
2056 && (!(alien->flags & FL_NOBANTER)))
2057 {
2058 radio_getRandomMessage(msg, _(
2059 /// Phoebe brag messages
2060 /// This is a list of brags separated by "\n". They are randomly
2061 /// broadcast when Phoebe successfully kills an enemy.
2062 /// Instead of directly translating these, please populate the list
2063 /// with brag messages that work well in the target language,
2064 /// following the English version only as a general guideline. Any
2065 /// number of brag messages is permitted.
2066 "I got another one!\n"
2067 "Target destroyed!\n"
2068 "One more for me!\n"
2069 "Yes! Did you see that, Chris?\n"
2070 "Hey Chris, remind me to check my kill count later!\n"
2071 "Bring it on, WEAPCO!\n"
2072 "Take that, WEAPCO!\n"
2073 "My kill count is going up!\n"
2074 "Another one bites the dust!\n"
2075 "Yeah! Nothing can stand in our way!\n"
2076 "I got it!"
2077 ));
2078 radio_setMessage(FS_PHOEBE, msg, 0);
2079 }
2080 }
2081 else if (attacker->classDef == CD_URSULA)
2082 {
2083 game.wingMate2Kills++;
2084 if (CHANCE(1 / 8.) && (alien-> flags & FL_WEAPCO)
2085 && (!(alien->flags & FL_NOBANTER)))
2086 {
2087 radio_getRandomMessage(msg, _(
2088 /// Ursula brag messages
2089 /// This is a list of brags separated by "\n". They are randomly
2090 /// broadcast when Ursula successfully kills an enemy.
2091 /// Instead of directly translating these, please populate the list
2092 /// with brag messages that work well in the target language,
2093 /// following the English version only as a general guideline. Any
2094 /// number of brag messages is permitted.
2095 "Kicked your ass!\n"
2096 "You ain't so tough!\n"
2097 "I was always a better WEAPCO pilot than you!\n"
2098 "Target destroyed!\n"
2099 "That'll teach you!\n"
2100 "Take that, you cruddy robots!\n"
2101 "Is that all you've got?\n"
2102 "Who else wants some?!\n"
2103 "I'm not letting you beat me, Phoebe!\n"
2104 "Bring it on, you mindless drones!\n"
2105 "Oh, I'm sorry, are you getting your metal asses handed to you?\n"
2106 "No one messes with the Lexx family!\n"
2107 "Die, damned WEAPCO drones!\n"
2108 "Don't think you can get away from me!"
2109 ));
2110 radio_setMessage(FS_URSULA, msg, 0);
2111 }
2112 }
2113 else
2114 {
2115 game.totalOtherKills++;
2116 }
2117 }
2118
2119 mission_updateRequirements(M_DESTROY_TARGET_TYPE, alien->classDef, 1);
2120 mission_updateRequirements(M_PROTECT_TARGET, alien->classDef, 1);
2121
2122 if (CHANCE(alien->collectChance / 100.))
2123 {
2124 if (game.difficulty == DIFFICULTY_ORIGINAL)
2125 {
2126 collect_type = alien->collectTypeOriginal;
2127 collect_value = alien->collectValueOriginal;
2128 }
2129 else
2130 {
2131 collect_type = alien->collectType;
2132 collect_value = alien->collectValue;
2133 }
2134
2135 if (CHANCE(1 / 10.))
2136 collect_value *= 2;
2137
2138 while (collect_value > 0)
2139 {
2140 value = RANDRANGE(10, 100);
2141 if (value > collect_value)
2142 value = collect_value;
2143 collectable_add(alien->x, alien->y, collect_type, value, MAX(600, 2 * collect_value));
2144 collect_value -= value;
2145 }
2146 }
2147
2148 // Make it explode immediately
2149 if (alien->classDef == CD_ASTEROID)
2150 {
2151 alien->shield = -999;
2152 }
2153
2154 if ((alien->classDef == CD_KRASS) && (attacker == &player))
2155 {
2156 /// Dialog (Chris Bainfield)
2157 /// Used when Krass Tyler is beaten in the Jupiter mission.
2158 radio_setMessage(FS_CHRIS, _("The name's CHRIS, old-timer."), 1);
2159 }
2160
2161 if (alien->classDef == CD_KLINE)
2162 {
2163 /// Dialog (Kline Kethlan)
2164 /// Used when Kline is killed in the Venus mission.
2165 radio_setMessage(FS_KLINE, _("It was an honor... to have fought you..."), 1);
2166 alien->dx = alien->dy = 0;
2167 alien->shield = -150;
2168 }
2169 }
2170
alien_hurt(Object * alien,Object * attacker,int damage,int ion)2171 void alien_hurt(Object *alien, Object *attacker, int damage, int ion)
2172 {
2173 int ai_type;
2174 double run_chance;
2175 int stage1_shield, stage2_shield, stage3_shield;
2176
2177 ai_type = ((game.difficulty == DIFFICULTY_ORIGINAL) ?
2178 alien->AITypeOriginal : alien->AIType);
2179
2180 if (ion)
2181 alien->systemPower -= damage;
2182 else
2183 alien->shield -= damage;
2184
2185 // Chain reaction damage if needed
2186 if ((game.difficulty != DIFFICULTY_ORIGINAL)
2187 && (alien->owner != alien) && (alien->flags & FL_DAMAGEOWNER))
2188 {
2189 alien_hurt(alien->owner, attacker, damage, ion);
2190 }
2191
2192 if (alien->classDef == CD_KLINE)
2193 {
2194 if (game.area == MISN_ELAMALE)
2195 {
2196 if (game.difficulty == DIFFICULTY_ORIGINAL)
2197 stage1_shield = KLINE_SHIELD_MEDIUM;
2198 else
2199 stage1_shield = KLINE_SHIELD_SMALL;
2200
2201 if ((alien->shield <= alien->maxShield - stage1_shield)
2202 && !(alien->flags & FL_LEAVESECTOR))
2203 {
2204 alien->flags |= FL_LEAVESECTOR;
2205 /// Dialog (Kline Kethlan)
2206 /// Used when Kline is beaten in the Elamale mission.
2207 radio_setMessage(FS_KLINE, _("Seems I underestimated you, Bainfield. We'll meet again!"), 1);
2208 }
2209 }
2210 else if (game.area == MISN_EARTH)
2211 {
2212 if (game.difficulty == DIFFICULTY_ORIGINAL)
2213 stage1_shield = KLINE_SHIELD_SMALL;
2214 else
2215 stage1_shield = KLINE_SHIELD_MEDIUM;
2216
2217 if ((alien->shield <= alien->maxShield - stage1_shield)
2218 && !(alien->flags & FL_LEAVESECTOR))
2219 {
2220 alien->flags |= FL_LEAVESECTOR;
2221 /// Dialog (Sid Wilson)
2222 /// Used when Kline is beaten in the Earth mission.
2223 radio_setMessage(FS_SID, _("Chris, Kethlan is getting away!"), 1);
2224 }
2225 }
2226 else if (game.area == MISN_VENUS)
2227 {
2228 stage1_shield = KLINE_STAGE1_SHIELD;
2229 stage2_shield = KLINE_STAGE2_SHIELD;
2230 stage3_shield = KLINE_STAGE3_SHIELD;
2231
2232 if (alien->shield + damage > stage1_shield
2233 && alien->shield <= stage1_shield)
2234 {
2235 alien_setKlineAttackMethod(alien);
2236 if (game.difficulty == DIFFICULTY_ORIGINAL)
2237 alien->shield = stage1_shield;
2238 }
2239 else if (alien->shield + damage > stage2_shield
2240 && alien->shield <= stage2_shield)
2241 {
2242 alien_setKlineAttackMethod(alien);
2243 if (game.difficulty == DIFFICULTY_ORIGINAL)
2244 alien->shield = stage2_shield;
2245 }
2246 else if (alien->shield + damage > stage3_shield
2247 && alien->shield <= stage3_shield)
2248 {
2249 alien_setKlineAttackMethod(alien);
2250 if (game.difficulty == DIFFICULTY_ORIGINAL)
2251 alien->shield = stage3_shield;
2252 }
2253 }
2254 else
2255 {
2256 stage1_shield = KLINE_SHIELD_TINY;
2257
2258 if ((alien->shield <= alien->maxShield - stage1_shield)
2259 && !(alien->flags & FL_LEAVESECTOR))
2260 {
2261 alien->flags |= FL_LEAVESECTOR;
2262 }
2263 }
2264 }
2265
2266 run_chance = (game.difficulty == DIFFICULTY_ORIGINAL) ? 0.02 : damage / 50.;
2267
2268 if ((alien->flags & FL_RUNSAWAY) && CHANCE(run_chance))
2269 {
2270 alien->flags |= FL_LEAVESECTOR;
2271 }
2272
2273 audio_playSound(SFX_HIT, alien->x, alien->y);
2274 if (ai_type == AI_EVASIVE)
2275 alien->thinktime = 0;
2276
2277 if (alien->shield < 1)
2278 alien_destroy(alien, attacker);
2279
2280 if (alien->systemPower < 1)
2281 {
2282 if (!(alien->flags & FL_DISABLED))
2283 {
2284 alien->flags += FL_DISABLED;
2285 mission_updateRequirements(M_DISABLE_TARGET,
2286 alien->classDef, 1);
2287 }
2288
2289 alien->systemPower = 0;
2290 }
2291 }
2292