]> 4ch.mooo.com Git - 16.git/blob - 16/keen456/KEEN4-6/KEEN6/K6_ACT3.C
extrcted keen code remake
[16.git] / 16 / keen456 / KEEN4-6 / KEEN6 / K6_ACT3.C
1 /* Reconstructed Commander Keen 4-6 Source Code\r
2  * Copyright (C) 2021 K1n9_Duk3\r
3  *\r
4  * This file is loosely based on:\r
5  * Keen Dreams Source Code\r
6  * Copyright (C) 2014 Javier M. Chavez\r
7  *\r
8  * This program is free software; you can redistribute it and/or modify\r
9  * it under the terms of the GNU General Public License as published by\r
10  * the Free Software Foundation; either version 2 of the License, or\r
11  * (at your option) any later version.\r
12  *\r
13  * This program is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16  * GNU General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU General Public License along\r
19  * with this program; if not, write to the Free Software Foundation, Inc.,\r
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
21  */\r
22 \r
23 /*\r
24 K6_ACT3.C\r
25 =========\r
26 \r
27 Contains the following actor types (in this order):\r
28 \r
29 - Fleex\r
30 - Bobba\r
31 - Babobba\r
32 - Blorb\r
33 - Ceilick\r
34 \r
35 */\r
36 \r
37 #include "CK_DEF.H"\r
38 \r
39 /*\r
40 =============================================================================\r
41 \r
42                                                   FLEEX\r
43 \r
44 temp1 = flash countdown\r
45 temp2 = health\r
46 \r
47 =============================================================================\r
48 */\r
49 \r
50 statetype s_fleexwalk1 = {FLEEXWALKL1SPR, FLEEXWALKR1SPR, step,  false, true,  7, 128, 0, T_FleexWalk, C_Fleex, R_Blooguard, &s_fleexwalk2};\r
51 statetype s_fleexwalk2 = {FLEEXWALKL2SPR, FLEEXWALKR2SPR, step,  false, true,  7, 128, 0, T_FleexWalk, C_Fleex, R_Blooguard, &s_fleexwalk1};\r
52 statetype s_fleexrun1  = {FLEEXWALKL1SPR, FLEEXWALKR1SPR, step,  false, true,  7, 128, 0, NULL, C_Fleex, R_Blooguard, &s_fleexrun2};\r
53 statetype s_fleexrun2  = {FLEEXWALKL2SPR, FLEEXWALKR2SPR, step,  false, true,  7, 128, 0, NULL, C_Fleex, R_Blooguard, &s_fleexrun3};\r
54 statetype s_fleexrun3  = {FLEEXWALKL1SPR, FLEEXWALKR1SPR, step,  false, true,  7, 128, 0, NULL, C_Fleex, R_Blooguard, &s_fleexrun4};\r
55 statetype s_fleexrun4  = {FLEEXWALKL2SPR, FLEEXWALKR2SPR, step,  false, true,  7, 128, 0, NULL, C_Fleex, R_Blooguard, &s_fleexwalk1};\r
56 statetype s_fleexlook1 = {FLEEXLOOK1SPR,  FLEEXLOOK1SPR,  step,  false, true, 60,   0, 0, NULL, C_Fleex, R_Blooguard, &s_fleexlook2};\r
57 statetype s_fleexlook2 = {FLEEXLOOK2SPR,  FLEEXLOOK2SPR,  step,  false, true, 60,   0, 0, T_FleexLook, C_Fleex, R_Blooguard, &s_fleexrun1};\r
58 statetype s_fleexstun  = {FLEEXSTUNSPR,   FLEEXSTUNSPR,   think, false, false, 0,   0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
59 \r
60 /*\r
61 ===========================\r
62 =\r
63 = SpawnFleex\r
64 =\r
65 ===========================\r
66 */\r
67 \r
68 void SpawnFleex(Uint16 tileX, Uint16 tileY)\r
69 {\r
70         GetNewObj(false);\r
71         new->obclass = fleexobj;\r
72         new->active = ac_yes;\r
73         new->priority = 0;\r
74         new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
75         new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -40*PIXGLOBAL;\r
76         if (US_RndT() < 0x80)\r
77         {\r
78                 new->xdir = 1;\r
79         }\r
80         else\r
81         {\r
82                 new->xdir = -1;\r
83         }\r
84         new->ydir = 1;\r
85         NewState(new, &s_fleexwalk1);\r
86         new->temp2 = 4; // health\r
87 }\r
88 \r
89 /*\r
90 ===========================\r
91 =\r
92 = T_FleexWalk\r
93 =\r
94 ===========================\r
95 */\r
96 \r
97 void T_FleexWalk(objtype *ob)\r
98 {\r
99         if (!player->xmove && !ob->temp1)\r
100         {\r
101                 ob->state = &s_fleexlook1;\r
102         }\r
103         else\r
104         {\r
105                 ob->xdir = (ob->x < player->x)? 1 : -1;\r
106         }\r
107 }\r
108 \r
109 /*\r
110 ===========================\r
111 =\r
112 = T_FleexLook\r
113 =\r
114 ===========================\r
115 */\r
116 \r
117 void T_FleexLook(objtype *ob)\r
118 {\r
119         ob->xdir = (ob->x < player->x)? 1 : -1;\r
120 }\r
121 \r
122 /*\r
123 ===========================\r
124 =\r
125 = C_Fleex\r
126 =\r
127 ===========================\r
128 */\r
129 \r
130 void C_Fleex(objtype *ob, objtype *hit)\r
131 {\r
132         if (hit->obclass == keenobj)\r
133         {\r
134                 KillKeen();\r
135         }\r
136         if (hit->obclass == stunshotobj)        // this is not 'else if' in the original code\r
137         {\r
138                 if (--ob->temp2 == 0)\r
139                 {\r
140                         StunObj(ob, hit, &s_fleexstun);\r
141                         ob->yspeed = -20;\r
142                 }\r
143                 else\r
144                 {\r
145                         ob->temp1 = 2;  // draw white twice\r
146                         ob->needtoreact = true;\r
147                         ExplodeShot(hit);\r
148                         if (ob->state == &s_fleexlook1 || ob->state == &s_fleexlook2)\r
149                         {\r
150                                 ob->xdir = (ob->x < player->x)? 1 : -1;\r
151                                 ChangeState(ob, &s_fleexwalk1);\r
152                         }\r
153                 }\r
154         }\r
155 }\r
156 \r
157 /*\r
158 =============================================================================\r
159 \r
160                                                   BOBBA\r
161 \r
162 temp1 = jump counter\r
163 \r
164 =============================================================================\r
165 */\r
166 \r
167 statetype s_bobbajump1       = {BOBBAL2SPR,    BOBBAR2SPR,    stepthink, false, false,  8,  0, 0, T_Projectile, C_Bobba, R_Bobba, &s_bobbajump2};\r
168 statetype s_bobbajump2       = {BOBBAL3SPR,    BOBBAR3SPR,    think,     false, false,  8,  0, 0, T_Projectile, C_Bobba, R_Bobba, &s_bobbajump2};\r
169 statetype s_bobbastand       = {BOBBAL1SPR,    BOBBAR1SPR,    step,      false, false, 20,  0, 0, T_BobbaStand, C_Bobba, R_Draw, &s_bobbajump1};\r
170 statetype s_bobbaattack      = {BOBBAL1SPR,    BOBBAR1SPR,    step,      false, false, 40,  0, 0, NULL, C_Bobba, R_Draw, &s_bobbajump1};\r
171 statetype s_bobbashot1       = {BOBBASHOT1SPR, BOBBASHOT1SPR, step,      false, false,  8,  0, 0, NULL, NULL, R_Draw, &s_bobbashot2};\r
172 statetype s_bobbashot2       = {BOBBASHOT2SPR, BOBBASHOT2SPR, step,      false, false,  8,  0, 0, NULL, NULL, R_Draw, &s_bobbashot3};\r
173 statetype s_bobbashot3       = {BOBBASHOT1SPR, BOBBASHOT1SPR, step,      false, false,  8,  0, 0, NULL, NULL, R_Draw, &s_bobbashot4};\r
174 statetype s_bobbashot4       = {BOBBASHOT2SPR, BOBBASHOT2SPR, step,      false, false,  8,  0, 0, T_BobbaShot, NULL, R_Draw, &s_bobbashot5};\r
175 statetype s_bobbashot5       = {BOBBASHOT3SPR, BOBBASHOT3SPR, slide,     false, false,  8, 48, 0, NULL, C_Lethal, R_BobbaShot, &s_bobbashot6};\r
176 statetype s_bobbashot6       = {BOBBASHOT4SPR, BOBBASHOT4SPR, slide,     false, false,  8, 48, 0, NULL, C_Lethal, R_BobbaShot, &s_bobbashot7};\r
177 statetype s_bobbashot7       = {BOBBASHOT5SPR, BOBBASHOT5SPR, slide,     false, false,  8, 48, 0, NULL, C_Lethal, R_BobbaShot, &s_bobbashot8};\r
178 statetype s_bobbashot8       = {BOBBASHOT6SPR, BOBBASHOT6SPR, slide,     false, false,  8, 48, 0, NULL, C_Lethal, R_BobbaShot, &s_bobbashot5};\r
179 statetype s_bobbashotvanish1 = {BOBBASHOT6SPR, BOBBASHOT6SPR, step,      false, false,  8,  0, 0, NULL, NULL, R_Draw, &s_bobbashotvanish2};\r
180 statetype s_bobbashotvanish2 = {BOBBASHOT6SPR, BOBBASHOT6SPR, step,      false, false,  8,  0, 0, NULL, NULL, R_Draw, &s_bobbashotvanish3};\r
181 statetype s_bobbashotvanish3 = {BOBBASHOT6SPR, BOBBASHOT6SPR, step,      false, false,  8,  0, 0, NULL, NULL, R_Draw, NULL};\r
182 \r
183 /*\r
184 ===========================\r
185 =\r
186 = SpawnBobba\r
187 =\r
188 ===========================\r
189 */\r
190 \r
191 void SpawnBobba(Uint16 tileX, Uint16 tileY)\r
192 {\r
193         GetNewObj(false);\r
194         new->obclass = bobbaobj;\r
195         new->active = ac_yes;\r
196         new->priority = 0;\r
197         new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
198         new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -2*TILEGLOBAL;\r
199         if (US_RndT() < 0x80)\r
200         {\r
201                 new->xdir = 1;\r
202         }\r
203         else\r
204         {\r
205                 new->xdir = -1;\r
206         }\r
207         new->ydir = 1;\r
208         NewState(new, &s_bobbajump1);\r
209 }\r
210 \r
211 /*\r
212 ===========================\r
213 =\r
214 = T_BobbaShot\r
215 =\r
216 ===========================\r
217 */\r
218 \r
219 #pragma argsused\r
220 void T_BobbaShot(objtype *ob)\r
221 {\r
222         SD_PlaySound(SND_BOBBASHOT);\r
223 }\r
224 \r
225 /*\r
226 ===========================\r
227 =\r
228 = T_BobbaStand\r
229 =\r
230 ===========================\r
231 */\r
232 \r
233 void T_BobbaStand(objtype *ob)\r
234 {\r
235         Sint16 i;\r
236         Uint16 far *map;\r
237 \r
238         if (++ob->temp1 == 3)\r
239         {\r
240                 ob->temp1 = 0;\r
241                 GetNewObj(true);\r
242                 new->active = ac_removable;\r
243                 new->obclass = mshotobj;\r
244                 new->y = ob->y + 11*PIXGLOBAL;\r
245                 new->xdir = ob->xdir;\r
246                 if (ob->xdir == 1)\r
247                 {\r
248                         new->x = ob->x + 16*PIXGLOBAL;\r
249                 }\r
250                 else\r
251                 {\r
252                         new->x = ob->x + 11*PIXGLOBAL;\r
253                 }\r
254                 NewState(new, &s_bobbashot1);\r
255                 new->priority = 2;\r
256                 ob->state = &s_bobbaattack;\r
257         }\r
258         else\r
259         {\r
260                 map = mapsegs[1] + mapbwidthtable[ob->tilebottom+1]/2 + ob->tilemidx;\r
261                 for (i=0; i<4; map += ob->xdir, i++)\r
262                 {\r
263                         if ( !tinf[*map+NORTHWALL]\r
264                                 && !tinf[*(map-mapwidth)+NORTHWALL]\r
265                                 && !tinf[*(map+mapwidth)+NORTHWALL] )\r
266                         {\r
267                                 ob->xdir = -ob->xdir;\r
268                                 break;\r
269                         }\r
270                 }\r
271                 ob->xspeed = ob->xdir << 5;\r
272                 ob->yspeed = -32;\r
273                 SD_PlaySound(SND_BOBBAJUMP);\r
274         }\r
275 }\r
276 \r
277 /*\r
278 ===========================\r
279 =\r
280 = C_Bobba\r
281 =\r
282 ===========================\r
283 */\r
284 \r
285 void C_Bobba(objtype *ob, objtype *hit)\r
286 {\r
287         if (hit->obclass == keenobj)\r
288         {\r
289                 KillKeen();\r
290         }\r
291         else if (hit->obclass == stunshotobj)\r
292         {\r
293                 ExplodeShot(hit);\r
294                 if (hit->xdir != 0)\r
295                 {\r
296                         ob->xdir = -hit->xdir;\r
297                 }\r
298         }\r
299 }\r
300 \r
301 /*\r
302 ===========================\r
303 =\r
304 = R_Bobba\r
305 =\r
306 ===========================\r
307 */\r
308 \r
309 void R_Bobba(objtype *ob)\r
310 {\r
311         if (ob->hiteast)\r
312         {\r
313                 ob->xdir = 1;\r
314                 ob->xspeed = -ob->xspeed;\r
315         }\r
316         else if (ob->hitwest)\r
317         {\r
318                 ob->xdir = -1;\r
319                 ob->xspeed = -ob->xspeed;\r
320         }\r
321 \r
322         if (ob->hitsouth)\r
323                 ob->yspeed = 0;\r
324 \r
325         if (ob->hitnorth)\r
326         {\r
327                 SD_PlaySound(SND_BOBBALAND);\r
328                 ChangeState(ob, &s_bobbastand);\r
329         }\r
330         RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
331 }\r
332 \r
333 /*\r
334 ===========================\r
335 =\r
336 = R_BobbaShot\r
337 =\r
338 ===========================\r
339 */\r
340 \r
341 void R_BobbaShot(objtype *ob)\r
342 {\r
343         if (ob->hitnorth || ob->hitsouth || ob->hiteast || ob->hitwest)\r
344         {\r
345                 ChangeState(ob, &s_bobbashotvanish1);\r
346         }\r
347         RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
348 }\r
349 \r
350 /*\r
351 =============================================================================\r
352 \r
353                                                   BABOBBA\r
354 \r
355 temp1 = jump counter (Babobba) / animation counter (Shot)\r
356 \r
357 =============================================================================\r
358 */\r
359 \r
360 statetype s_babobbajump1       = {BABOBBAL2SPR,     BABOBBAR2SPR,     stepthink, false, false,   8, 0, 0, T_Projectile, C_Babobba, R_Babobba, &s_babobbajump2};\r
361 statetype s_babobbajump2       = {BABOBBAL3SPR,     BABOBBAR3SPR,     think,     false, false,   8, 0, 0, T_Projectile, C_Babobba, R_Babobba, &s_babobbajump2};\r
362 statetype s_babobbastand       = {BABOBBAL1SPR,     BABOBBAR1SPR,     step,      false, false,  20, 0, 0, T_BabobbaStand, C_Babobba, R_Draw, &s_babobbajump1};\r
363 statetype s_babobbaattack      = {BABOBBAL1SPR,     BABOBBAR1SPR,     step,      false, false,  70, 0, 0, NULL, C_Babobba, R_Draw, &s_babobbastand};\r
364 statetype s_babobbastun1       = {BABOBBAL2SPR,     BABOBBAR2SPR,     think,     false, false,   0, 0, 0, T_Projectile, NULL, R_Stunned, &s_babobbastun2};\r
365 statetype s_babobbastun2       = {BABOBBASTUNSPR,   BABOBBASTUNSPR,   think,     false, false,   0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
366 statetype s_babobbasleep1      = {BABOBBASLEEP1SPR, BABOBBASLEEP1SPR, step,      false, false,  15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep2};\r
367 statetype s_babobbasleep2      = {BABOBBASLEEP2SPR, BABOBBASLEEP2SPR, step,      false, false,  15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep3};\r
368 statetype s_babobbasleep3      = {BABOBBASLEEP3SPR, BABOBBASLEEP3SPR, step,      false, false,  15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep4};\r
369 statetype s_babobbasleep4      = {BABOBBASLEEP4SPR, BABOBBASLEEP4SPR, step,      false, false, 500, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep5};\r
370 statetype s_babobbasleep5      = {BABOBBASLEEP3SPR, BABOBBASLEEP3SPR, step,      false, false,  15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep6};\r
371 statetype s_babobbasleep6      = {BABOBBASLEEP2SPR, BABOBBASLEEP2SPR, step,      false, false,  15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep7};\r
372 statetype s_babobbasleep7      = {BABOBBASLEEP1SPR, BABOBBASLEEP1SPR, step,      false, false,  15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbastand};\r
373 statetype s_babobbashot1       = {BABOBBASHOT1SPR,  BABOBBASHOT1SPR,  think,     false, false,   0, 0, 0, T_Projectile, C_Lethal, R_Bounce, &s_babobbashot2};\r
374 statetype s_babobbashot2       = {BABOBBASHOT2SPR,  BABOBBASHOT2SPR,  step,      false, false,   8, 0, 0, T_BabobbaShot, C_Lethal, R_Draw, &s_babobbashot3};\r
375 statetype s_babobbashot3       = {BABOBBASHOT1SPR,  BABOBBASHOT1SPR,  step,      false, false,   8, 0, 0, NULL, C_Lethal, R_Draw, &s_babobbashot2};\r
376 statetype s_babobbashotvanish1 = {BABOBBASHOT2SPR,  BABOBBASHOT2SPR,  step,      false, false,   8, 0, 0, T_BabobbaShotVanish, C_Lethal, R_Draw, &s_babobbashotvanish2};\r
377 statetype s_babobbashotvanish2 = {-1,               -1,               step,      false, false,   8, 0, 0, NULL, NULL, R_Draw, &s_babobbashotvanish1};\r
378 \r
379 /*\r
380 ===========================\r
381 =\r
382 = SpawnBabobba\r
383 =\r
384 ===========================\r
385 */\r
386 \r
387 void SpawnBabobba(Uint16 tileX, Uint16 tileY)\r
388 {\r
389         GetNewObj(false);\r
390         new->obclass = babobbaobj;\r
391         new->active = ac_yes;\r
392         new->priority = 0;\r
393         new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
394         new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -2*TILEGLOBAL;\r
395         if (US_RndT() < 0x80)\r
396         {\r
397                 new->xdir = 1;\r
398         }\r
399         else\r
400         {\r
401                 new->xdir = -1;\r
402         }\r
403         new->ydir = 1;\r
404         NewState(new, &s_babobbajump1);\r
405 }\r
406 \r
407 /*\r
408 ===========================\r
409 =\r
410 = T_BabobbaStand\r
411 =\r
412 ===========================\r
413 */\r
414 \r
415 void T_BabobbaStand(objtype *ob)\r
416 {\r
417         Sint16 i;\r
418         Uint16 far *map;\r
419 \r
420         if (US_RndT() < 4)\r
421         {\r
422                 ob->temp1 = 0;\r
423                 ob->state = &s_babobbasleep1;\r
424         }\r
425         else if (++ob->temp1 == 3)\r
426         {\r
427                 ob->temp1 = 0;\r
428 \r
429                 GetNewObj(true);\r
430                 new->active = ac_removable;\r
431                 new->obclass = mshotobj;\r
432                 new->y = ob->y + 4*PIXGLOBAL;\r
433                 new->xdir = ob->xdir;\r
434                 if (ob->xdir == 1)\r
435                 {\r
436                         new->x = ob->x + 16*PIXGLOBAL;\r
437                 }\r
438                 else\r
439                 {\r
440                         new->x = ob->x + 11*PIXGLOBAL;\r
441                 }\r
442                 new->xspeed = new->xdir << 5;\r
443                 NewState(new, &s_babobbashot1);\r
444                 new->priority = 2;\r
445                 ob->state = &s_babobbaattack;\r
446         }\r
447         else\r
448         {\r
449                 map = mapsegs[1] + mapbwidthtable[ob->tilebottom+1]/2 + ob->tilemidx;\r
450                 for (i=0; i<4; map += ob->xdir, i++)\r
451                 {\r
452                         if ( !tinf[*map+NORTHWALL]\r
453                                 && !tinf[*(map-mapwidth)+NORTHWALL]\r
454                                 && !tinf[*(map+mapwidth)+NORTHWALL] )\r
455                         {\r
456                                 ob->xdir = -ob->xdir;\r
457                                 break;\r
458                         }\r
459                 }\r
460                 ob->xspeed = ob->xdir *24;\r
461                 ob->yspeed = -32;\r
462         }\r
463 }\r
464 \r
465 /*\r
466 ===========================\r
467 =\r
468 = C_Babobba\r
469 =\r
470 ===========================\r
471 */\r
472 \r
473 void C_Babobba(objtype *ob, objtype *hit)\r
474 {\r
475         if (hit->obclass == keenobj)\r
476         {\r
477                 KillKeen();\r
478         }\r
479         else if (hit->obclass == stunshotobj)\r
480         {\r
481                 StunObj(ob, hit, &s_babobbastun1);\r
482         }\r
483 }\r
484 \r
485 /*\r
486 ===========================\r
487 =\r
488 = C_BabobbaSleep\r
489 =\r
490 ===========================\r
491 */\r
492 \r
493 void C_BabobbaSleep(objtype *ob, objtype *hit)\r
494 {\r
495         if (hit->obclass == stunshotobj)\r
496         {\r
497                 StunObj(ob, hit, &s_babobbastun1);\r
498         }\r
499 }\r
500 \r
501 /*\r
502 ===========================\r
503 =\r
504 = R_Babobba\r
505 =\r
506 ===========================\r
507 */\r
508 \r
509 void R_Babobba(objtype *ob)\r
510 {\r
511         if (ob->hiteast)\r
512         {\r
513                 ob->xdir = 1;\r
514                 ob->xspeed = -ob->xspeed;\r
515         }\r
516         else if (ob->hitwest)\r
517         {\r
518                 ob->xdir = -1;\r
519                 ob->xspeed = -ob->xspeed;\r
520         }\r
521 \r
522         if (ob->hitsouth)\r
523                 ob->yspeed = 0;\r
524 \r
525         if (ob->hitnorth)\r
526         {\r
527                 ChangeState(ob, &s_babobbastand);\r
528         }\r
529         RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
530 }\r
531 \r
532 /*\r
533 ===========================\r
534 =\r
535 = T_BabobbaShot\r
536 =\r
537 ===========================\r
538 */\r
539 \r
540 void T_BabobbaShot(objtype *ob)\r
541 {\r
542         if (++ob->temp1 == 10)\r
543         {\r
544                 ob->temp1 = 0;\r
545                 ob->state = &s_babobbashotvanish1;\r
546         }\r
547 }\r
548 \r
549 /*\r
550 ===========================\r
551 =\r
552 = T_BabobbaShotVanish\r
553 =\r
554 ===========================\r
555 */\r
556 \r
557 void T_BabobbaShotVanish(objtype *ob)\r
558 {\r
559         if (++ob->temp1 == 5)\r
560         {\r
561                 RemoveObj(ob);\r
562         }\r
563 }\r
564 \r
565 /*\r
566 =============================================================================\r
567 \r
568                                                   BLORB\r
569 \r
570 =============================================================================\r
571 */\r
572 \r
573 statetype s_blorb1        = {BLORB1SPR, BLORB1SPR, slide, false, false, 20, 8, 8, 0, C_Lethal, R_Blorb, &s_blorb2};\r
574 statetype s_blorb2        = {BLORB2SPR, BLORB2SPR, slide, false, false, 20, 8, 8, 0, C_Lethal, R_Blorb, &s_blorb3};\r
575 statetype s_blorb3        = {BLORB3SPR, BLORB3SPR, slide, false, false, 20, 8, 8, 0, C_Lethal, R_Blorb, &s_blorb1};\r
576 \r
577 /*\r
578 ===========================\r
579 =\r
580 = SpawnBlorb\r
581 =\r
582 ===========================\r
583 */\r
584 \r
585 void SpawnBlorb(Uint16 tileX, Uint16 tileY)\r
586 {\r
587         GetNewObj(false);\r
588         new->obclass = blorbobj;\r
589         new->active = ac_yes;\r
590         new->priority = 0;\r
591         new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
592         new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -8*PIXGLOBAL;\r
593         if (US_RndT() < 0x80)\r
594         {\r
595                 new->xdir = 1;\r
596         }\r
597         else\r
598         {\r
599                 new->xdir = -1;\r
600         }\r
601         if (US_RndT() < 0x80)\r
602         {\r
603                 new->ydir = 1;\r
604         }\r
605         else\r
606         {\r
607                 new->ydir = -1;\r
608         }\r
609         new->needtoclip = cl_fullclip;\r
610         NewState(new, &s_blorb1);\r
611 }\r
612 \r
613 /*\r
614 ===========================\r
615 =\r
616 = R_Blorb\r
617 =\r
618 ===========================\r
619 */\r
620 \r
621 void R_Blorb(objtype *ob)\r
622 {\r
623         if (ob->hitnorth)\r
624         {\r
625                 ob->ydir = -1;\r
626                 SD_PlaySound(SND_BLORBBOUNCE);\r
627         }\r
628         else if (ob->hitsouth)\r
629         {\r
630                 ob->ydir = 1;\r
631                 SD_PlaySound(SND_BLORBBOUNCE);\r
632         }\r
633         if (ob->hitwest)\r
634         {\r
635                 ob->xdir = -1;\r
636                 SD_PlaySound(SND_BLORBBOUNCE);\r
637         }\r
638         else if (ob->hiteast)\r
639         {\r
640                 ob->xdir = 1;\r
641                 SD_PlaySound(SND_BLORBBOUNCE);\r
642         }\r
643         RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
644 }\r
645 \r
646 /*\r
647 =============================================================================\r
648 \r
649                                                   CEILICK\r
650 \r
651 temp1 = initial y position\r
652 \r
653 =============================================================================\r
654 */\r
655 \r
656 statetype s_ceilickhidden   = {TONGUE1SPR,     TONGUE1SPR,     think, false, false, 20, 0,   0, T_CeilickHidden, NULL, R_Draw, NULL};\r
657 statetype s_ceilickattack1  = {TONGUE1SPR,     TONGUE1SPR,     step,  false, false,  6, 0,   0, NULL, NULL, R_Draw, &s_ceilickattack2};\r
658 statetype s_ceilickattack2  = {TONGUE2SPR,     TONGUE2SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack3};\r
659 statetype s_ceilickattack3  = {TONGUE3SPR,     TONGUE3SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack4};\r
660 statetype s_ceilickattack4  = {TONGUE4SPR,     TONGUE4SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack5};\r
661 statetype s_ceilickattack5  = {TONGUE5SPR,     TONGUE5SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack6};\r
662 statetype s_ceilickattack6  = {TONGUE4SPR,     TONGUE4SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack7};\r
663 statetype s_ceilickattack7  = {TONGUE3SPR,     TONGUE3SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack8};\r
664 statetype s_ceilickattack8  = {TONGUE4SPR,     TONGUE4SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack9};\r
665 statetype s_ceilickattack9  = {TONGUE5SPR,     TONGUE5SPR,     step,  false, false,  6, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack10};\r
666 statetype s_ceilickattack10 = {TONGUE2SPR,     TONGUE2SPR,     step,  false, false, 10, 0,   0, NULL, C_Lethal, R_Draw, &s_ceilickattack11};\r
667 statetype s_ceilickattack11 = {TONGUE1SPR,     TONGUE1SPR,     step,  false, false, 10, 0,   0, NULL, NULL, R_Draw, &s_ceilicklaugh1};\r
668 statetype s_ceilicklaugh1   = {CEILICK1SPR,    CEILICK1SPR,    slide, true,  false, 16, 0,  16, T_CeilickLaugh, C_Ceilick, R_Draw, &s_ceilicklaugh2};\r
669 statetype s_ceilicklaugh2   = {CEILICK2SPR,    CEILICK2SPR,    step,  true,  false, 10, 0,   0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh3};\r
670 statetype s_ceilicklaugh3   = {CEILICK1SPR,    CEILICK1SPR,    step,  true,  false, 10, 0,   0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh4};\r
671 statetype s_ceilicklaugh4   = {CEILICK2SPR,    CEILICK2SPR,    step,  true,  false, 10, 0,   0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh5};\r
672 statetype s_ceilicklaugh5   = {CEILICK1SPR,    CEILICK1SPR,    step,  true,  false, 10, 0,   0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh6};\r
673 statetype s_ceilicklaugh6   = {CEILICK2SPR,    CEILICK2SPR,    step,  true,  false, 10, 0,   0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh7};\r
674 statetype s_ceilicklaugh7   = {CEILICK1SPR,    CEILICK1SPR,    step,  true,  false, 10, 0,   0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh8};\r
675 statetype s_ceilicklaugh8   = {CEILICK1SPR,    CEILICK1SPR,    slide, true,  false, 16, 0, -16, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh9};\r
676 statetype s_ceilicklaugh9   = {-1,             -1,             step,  true,  false, 60, 0,   0, NULL, C_Ceilick, R_Draw, &s_ceilickhidden};\r
677 statetype s_ceilickstun     = {CEILICKSTUNSPR, CEILICKSTUNSPR, think, true,  false,  0, 0,   0, T_CeilickStunned, NULL, R_Stunned, NULL};\r
678 \r
679 /*\r
680 ===========================\r
681 =\r
682 = SpawnCeilick\r
683 =\r
684 ===========================\r
685 */\r
686 \r
687 void SpawnCeilick(Uint16 tileX, Uint16 tileY)\r
688 {\r
689         GetNewObj(false);\r
690         new->obclass = ceilickobj;\r
691         new->active = ac_yes;\r
692         new->priority = 0;\r
693         new->needtoclip = cl_noclip;\r
694         new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
695         new->y = new->temp1 = CONVERT_TILE_TO_GLOBAL(tileY);\r
696         new->ydir = 1;\r
697         NewState(new, &s_ceilickhidden);\r
698 }\r
699 \r
700 /*\r
701 ===========================\r
702 =\r
703 = T_CeilickHidden\r
704 =\r
705 ===========================\r
706 */\r
707 \r
708 void T_CeilickHidden(objtype *ob)\r
709 {\r
710         if ( player->y - ob->y <= 40*PIXGLOBAL\r
711                 && player->left < ob->right+PIXGLOBAL\r
712                 && player->right > ob->left-PIXGLOBAL )\r
713         {\r
714                 SD_PlaySound(SND_CEILICKATTACK);\r
715                 ob->state = &s_ceilickattack1;\r
716         }\r
717 }\r
718 \r
719 /*\r
720 ===========================\r
721 =\r
722 = T_CeilickLaugh\r
723 =\r
724 ===========================\r
725 */\r
726 \r
727 #pragma argsused\r
728 void T_CeilickLaugh(objtype *ob)\r
729 {\r
730         SD_PlaySound(SND_CEILICKLAUGH);\r
731 }\r
732 \r
733 /*\r
734 ===========================\r
735 =\r
736 = T_CeilickStunned\r
737 =\r
738 ===========================\r
739 */\r
740 \r
741 void T_CeilickStunned(objtype *ob)\r
742 {\r
743         ob->needtoreact = true; // to make sure the stunned stars animate\r
744 }\r
745 \r
746 /*\r
747 ===========================\r
748 =\r
749 = C_Ceilick\r
750 =\r
751 ===========================\r
752 */\r
753 \r
754 void C_Ceilick(objtype *ob, objtype *hit)\r
755 {\r
756         if (hit->obclass == stunshotobj)\r
757         {\r
758                 ob->y = ob->temp1;\r
759                 ExplodeShot(hit);\r
760                 ob->temp1 = ob->temp2 = ob->temp3 = 0;\r
761                 ob->temp4 = ob->obclass;\r
762                 ChangeState(ob, &s_ceilickstun);\r
763                 ob->obclass = stunnedobj;\r
764         }\r
765 }