OSDN Git Service

going to start wolf3d core core (loop with input only) work soon. I was mostly brains...
[proj16/16.git] / src / lib / hb / act / kd_act2.c
1 /* Keen Dreams Source Code\r
2  * Copyright (C) 2014 Javier M. Chavez\r
3  *\r
4  * This program is free software; you can redistribute it and/or modify\r
5  * it under the terms of the GNU General Public License as published by\r
6  * the Free Software Foundation; either version 2 of the License, or\r
7  * (at your option) any later version.\r
8  *\r
9  * This program is distributed in the hope that it will be useful,\r
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
12  * GNU General Public License for more details.\r
13  *\r
14  * You should have received a copy of the GNU General Public License along\r
15  * with this program; if not, write to the Free Software Foundation, Inc.,\r
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
17  */\r
18 \r
19 // KD_ACT1.C\r
20 #include "KD_DEF.H"\r
21 #pragma hdrstop\r
22 \r
23 \r
24 /*\r
25 =============================================================================\r
26 \r
27                                                  LOCAL CONSTANTS\r
28 \r
29 =============================================================================\r
30 */\r
31 \r
32 #define PLACESPRITE RF_PlaceSprite (&ob->sprite,ob->x,ob->y,ob->shapenum, \\r
33         spritedraw,0);\r
34 \r
35 \r
36 void    ProjectileReact (objtype *ob);\r
37 \r
38 /*\r
39 =============================================================================\r
40 \r
41                                                    TATER TROOPER\r
42 \r
43 temp1 = chasing player\r
44 temp2 = nothink time\r
45 \r
46 =============================================================================\r
47 */\r
48 \r
49 void TaterThink (objtype *ob);\r
50 void BackupReact (objtype *ob);\r
51 \r
52 extern  statetype s_taterwalk1;\r
53 extern  statetype s_taterwalk2;\r
54 extern  statetype s_taterwalk3;\r
55 extern  statetype s_taterwalk4;\r
56 \r
57 \r
58 extern  statetype s_taterattack1;\r
59 extern  statetype s_taterattack2;\r
60 extern  statetype s_taterattack3;\r
61 \r
62 #pragma warn -sus\r
63 \r
64 statetype s_taterwalk1  = {TATERTROOPWALKL1SPR,TATERTROOPWALKR1SPR,step,false,\r
65         true,10, 128,0, TaterThink, NULL, WalkReact, &s_taterwalk2};\r
66 statetype s_taterwalk2  = {TATERTROOPWALKL2SPR,TATERTROOPWALKR2SPR,step,false,\r
67         true,10, 128,0, TaterThink, NULL, WalkReact, &s_taterwalk3};\r
68 statetype s_taterwalk3  = {TATERTROOPWALKL3SPR,TATERTROOPWALKR3SPR,step,false,\r
69         true,10, 128,0, TaterThink, NULL, WalkReact, &s_taterwalk4};\r
70 statetype s_taterwalk4  = {TATERTROOPWALKL4SPR,TATERTROOPWALKR4SPR,step,false,\r
71         true,10, 128,0, TaterThink, NULL, WalkReact, &s_taterwalk1};\r
72 \r
73 statetype s_taterattack1= {TATERTROOPLUNGEL1SPR,TATERTROOPLUNGER1SPR,step,false,\r
74         false,12, 0,0, NULL, NULL, BackupReact, &s_taterattack2};\r
75 statetype s_taterattack2= {TATERTROOPLUNGEL2SPR,TATERTROOPLUNGER2SPR,step,false,\r
76         false,20, 0,0, NULL, NULL, DrawReact, &s_taterattack3};\r
77 statetype s_taterattack3= {TATERTROOPLUNGEL1SPR,TATERTROOPLUNGER1SPR,step,false,\r
78         false,8, 0,0, NULL, NULL, DrawReact, &s_taterwalk1};\r
79 \r
80 #pragma warn +sus\r
81 \r
82 /*\r
83 ====================\r
84 =\r
85 = SpawnTater\r
86 =\r
87 ====================\r
88 */\r
89 \r
90 void SpawnTater (int tilex, int tiley)\r
91 {\r
92         GetNewObj (false);\r
93 \r
94         new->obclass = taterobj;\r
95         new->x = tilex<<G_T_SHIFT;\r
96         new->y = (tiley<<G_T_SHIFT)-2*BLOCKSIZE + 15;\r
97         new->xdir = 1;\r
98         new->ydir = 1;\r
99         NewState (new,&s_taterwalk1);\r
100         new->hitnorth = 1;\r
101 }\r
102 \r
103 /*\r
104 ====================\r
105 =\r
106 = TaterThink\r
107 =\r
108 ====================\r
109 */\r
110 \r
111 void TaterThink (objtype *ob)\r
112 {\r
113         int delta;\r
114 \r
115         if (ob->top > player->bottom || ob->bottom < player->top)\r
116                 return;\r
117 \r
118         if ( ob->xdir == -1 )\r
119         {\r
120                 delta = ob->left - player->right;\r
121                 if (delta > TILEGLOBAL)\r
122                         return;\r
123                 if (delta < -8*PIXGLOBAL)\r
124                 {\r
125                         ob->xdir = 1;\r
126                         return;\r
127                 }\r
128                 SD_PlaySound (TATERSWINGSND);\r
129                 ob->state = &s_taterattack1;\r
130                 return;\r
131         }\r
132         else\r
133         {\r
134                 delta = player->left - ob->right;\r
135                 if (delta > TILEGLOBAL)\r
136                         return;\r
137                 if (delta < -8*PIXGLOBAL)\r
138                 {\r
139                         ob->xdir = -1;\r
140                         return;\r
141                 }\r
142                 SD_PlaySound (TATERSWINGSND);\r
143                 ob->state = &s_taterattack1;\r
144                 return;\r
145         }\r
146 }\r
147 \r
148 \r
149 /*\r
150 ====================\r
151 =\r
152 = BackupReact\r
153 =\r
154 ====================\r
155 */\r
156 \r
157 void BackupReact (objtype *ob)\r
158 {\r
159         if (!ob->hitnorth)\r
160         {\r
161                 ob->x-=ob->xmove;\r
162                 ob->y-=ob->ymove;\r
163         }\r
164 \r
165         PLACESPRITE;\r
166 }\r
167 \r
168 /*\r
169 =============================================================================\r
170 \r
171                                                    CANTELOUPE CART\r
172 \r
173 =============================================================================\r
174 */\r
175 \r
176 extern  statetype s_cartroll1;\r
177 extern  statetype s_cartroll2;\r
178 \r
179 void CartReact (objtype *ob);\r
180 \r
181 #pragma warn -sus\r
182 \r
183 statetype s_cartroll1   = {CANTCARTL1SPR,CANTCARTL1SPR,slide,true,\r
184         false,5, 32,0, NULL, NULL, CartReact, &s_cartroll2};\r
185 statetype s_cartroll2   = {CANTCARTL2SPR,CANTCARTL2SPR,slide,true,\r
186         false,5, 32,0, NULL, NULL, CartReact, &s_cartroll1};\r
187 \r
188 #pragma warn +sus\r
189 \r
190 /*\r
191 ====================\r
192 =\r
193 = SpawnCart\r
194 =\r
195 ====================\r
196 */\r
197 \r
198 void SpawnCart (int tilex, int tiley)\r
199 {\r
200         GetNewObj (false);\r
201 \r
202         new->obclass = cartobj;\r
203         new->x = tilex<<G_T_SHIFT;\r
204         new->y = (tiley<<G_T_SHIFT)-3*PIXGLOBAL;\r
205         new->xdir = 1;\r
206         new->ydir = 1;\r
207         new->active = allways;\r
208         NewState (new,&s_cartroll1);\r
209 }\r
210 \r
211 \r
212 \r
213 /*\r
214 ====================\r
215 =\r
216 = CartReact\r
217 =\r
218 ====================\r
219 */\r
220 \r
221 void CartReact (objtype *ob)\r
222 {\r
223         unsigned far *map;\r
224 \r
225         if (ob->xdir == 1 && ob->hitwest)\r
226         {\r
227                 ob->xdir = -1;\r
228         }\r
229         else if (ob->xdir == -1 && ob->hiteast)\r
230         {\r
231                 ob->xdir = 1;\r
232         }\r
233 \r
234         map = mapsegs[1] + mapbwidthtable[ob->tilebottom+1]/2;\r
235         if (ob->xdir == 1)\r
236                 map += ob->tileright;\r
237         else\r
238                 map += ob->tileleft;\r
239 \r
240         if ( !tinf[NORTHWALL + *map] )\r
241                 ob->xdir = -ob->xdir;\r
242 \r
243         PLACESPRITE;\r
244 }\r
245 \r
246 \r
247 /*\r
248 =============================================================================\r
249 \r
250                                                         FRENCHY\r
251 \r
252 =============================================================================\r
253 */\r
254 \r
255 #define FRYXSPEED       40\r
256 #define FRYYSPEED       -20\r
257 \r
258 \r
259 void FrenchyThink (objtype *ob);\r
260 void FrenchyRunThink (objtype *ob);\r
261 void FrenchyThrow (objtype *ob);\r
262 \r
263 extern  statetype s_frenchywalk1;\r
264 extern  statetype s_frenchywalk2;\r
265 extern  statetype s_frenchywalk3;\r
266 extern  statetype s_frenchywalk4;\r
267 \r
268 extern  statetype s_frenchyrun1;\r
269 extern  statetype s_frenchyrun2;\r
270 extern  statetype s_frenchyrun3;\r
271 extern  statetype s_frenchyrun4;\r
272 \r
273 extern  statetype s_frenchythrow1;\r
274 extern  statetype s_frenchythrow2;\r
275 extern  statetype s_frenchythrow3;\r
276 \r
277 extern  statetype s_fry1;\r
278 extern  statetype s_fry2;\r
279 \r
280 #pragma warn -sus\r
281 \r
282 statetype s_frenchywalk1        = {FRENCHYRUNL1SPR,FRENCHYRUNR1SPR,step,false,\r
283         true,10, 128,0, FrenchyThink, NULL, WalkReact, &s_frenchywalk2};\r
284 statetype s_frenchywalk2        = {FRENCHYRUNL2SPR,FRENCHYRUNR2SPR,step,false,\r
285         true,10, 128,0, FrenchyThink, NULL, WalkReact, &s_frenchywalk3};\r
286 statetype s_frenchywalk3        = {FRENCHYRUNL3SPR,FRENCHYRUNR3SPR,step,false,\r
287         true,10, 128,0, FrenchyThink, NULL, WalkReact, &s_frenchywalk4};\r
288 statetype s_frenchywalk4        = {FRENCHYRUNL4SPR,FRENCHYRUNR4SPR,step,false,\r
289         true,10, 128,0, FrenchyThink, NULL, WalkReact, &s_frenchywalk1};\r
290 \r
291 statetype s_frenchyrun1 = {FRENCHYRUNL1SPR,FRENCHYRUNR1SPR,step,true,\r
292         true,5, 128,0, FrenchyRunThink, NULL, WalkReact, &s_frenchyrun2};\r
293 statetype s_frenchyrun2 = {FRENCHYRUNL2SPR,FRENCHYRUNR2SPR,step,true,\r
294         true,5, 128,0, FrenchyRunThink, NULL, WalkReact, &s_frenchyrun3};\r
295 statetype s_frenchyrun3 = {FRENCHYRUNL3SPR,FRENCHYRUNR3SPR,step,true,\r
296         true,5, 128,0, FrenchyRunThink, NULL, WalkReact, &s_frenchyrun4};\r
297 statetype s_frenchyrun4 = {FRENCHYRUNL4SPR,FRENCHYRUNR4SPR,step,true,\r
298         true,5, 128,0, FrenchyRunThink, NULL, WalkReact, &s_frenchyrun1};\r
299 \r
300 statetype s_frenchythrow1       = {FRENCHYTHROWL1SPR,FRENCHYTHROWR1SPR,step,false,\r
301         false,10, 0,0, NULL, NULL, DrawReact, &s_frenchythrow2};\r
302 statetype s_frenchythrow2       = {FRENCHYTHROWL2SPR,FRENCHYTHROWR2SPR,step,false,\r
303         false,1, 0,0, FrenchyThrow, NULL, DrawReact, &s_frenchythrow3};\r
304 statetype s_frenchythrow3       = {FRENCHYTHROWL2SPR,FRENCHYTHROWR2SPR,step,false,\r
305         false,10, -128,0, NULL, NULL, DrawReact, &s_frenchywalk1};\r
306 \r
307 statetype s_fry1                = {FRENCHFRY1SPR,FRENCHFRY1SPR,stepthink,false,\r
308         false,4, 0,0, ProjectileThink, NULL, ProjectileReact, &s_fry2};\r
309 statetype s_fry2                = {FRENCHFRY2SPR,FRENCHFRY2SPR,stepthink,false,\r
310         false,4, 0,0, ProjectileThink, NULL, ProjectileReact, &s_fry1};\r
311 \r
312 \r
313 #pragma warn +sus\r
314 \r
315 \r
316 /*\r
317 ====================\r
318 =\r
319 = SpawnFrenchy\r
320 =\r
321 ====================\r
322 */\r
323 \r
324 void SpawnFrenchy (int tilex, int tiley)\r
325 {\r
326         GetNewObj (false);\r
327 \r
328         new->obclass = frenchyobj;\r
329         new->x = tilex<<G_T_SHIFT;\r
330         new->y = (tiley<<G_T_SHIFT)-2*BLOCKSIZE;\r
331         new->xdir = 1;\r
332         new->ydir = 1;\r
333         NewState (new,&s_frenchywalk1);\r
334 }\r
335 \r
336 \r
337 /*\r
338 ====================\r
339 =\r
340 = FrenchyRunThink\r
341 =\r
342 ====================\r
343 */\r
344 \r
345 void FrenchyRunThink (objtype *ob)\r
346 {\r
347         ob->state = &s_frenchywalk1;\r
348 }\r
349 \r
350 \r
351 /*\r
352 ====================\r
353 =\r
354 = FrenchyThrow\r
355 =\r
356 ====================\r
357 */\r
358 \r
359 void FrenchyThrow (objtype *ob)\r
360 {\r
361         GetNewObj (true);\r
362         new->obclass = shotobj;\r
363         if (ob->xdir == 1)\r
364         {\r
365                 new->x = ob->x+24*16;\r
366                 new->y = ob->y+8*16;\r
367         }\r
368         else\r
369         {\r
370                 new->x = ob->x;\r
371                 new->y = ob->y+8*16;\r
372         }\r
373         new->xdir = ob->xdir;\r
374         new->ydir = 1;\r
375         new->xspeed = ob->xdir * FRYXSPEED-(US_RndT()>>4);\r
376         new->yspeed = FRYYSPEED;\r
377         new->active = removable;\r
378         NewState (new,&s_fry1);\r
379 \r
380         ob->nothink = 2;\r
381 }\r
382 \r
383 \r
384 /*\r
385 ====================\r
386 =\r
387 = FrenchyThink\r
388 =\r
389 ====================\r
390 */\r
391 \r
392 void FrenchyThink (objtype *ob)\r
393 {\r
394         int delta;\r
395 \r
396         if ( abs(ob->y - player->y) > 3*TILEGLOBAL )\r
397         {\r
398                 if (US_RndT()<8)\r
399                         ob->xdir = -ob->xdir;           // turn randomly\r
400                 return;\r
401         }\r
402 \r
403         delta = player->x - ob->x;\r
404 \r
405         if (delta < -8*TILEGLOBAL)\r
406         {\r
407         // walk closer\r
408                 ob->xdir = -1;\r
409         }\r
410         if (delta < -4*TILEGLOBAL)\r
411         {\r
412         // throw\r
413                 ob->xdir = -1;\r
414                 ob->state = &s_frenchythrow1;\r
415         }\r
416         else if (delta < 0)\r
417         {\r
418         // run away\r
419                 ob->xdir = 1;\r
420                 ob->state = &s_frenchyrun1;\r
421                 ob->nothink = 8;\r
422         }\r
423         else if (delta < 4*TILEGLOBAL)\r
424         {\r
425         // run away\r
426                 ob->xdir = -1;\r
427                 ob->state = &s_frenchyrun1;\r
428                 ob->nothink = 8;\r
429         }\r
430         else if (delta < 8*TILEGLOBAL)\r
431         {\r
432         // throw and walk closer\r
433                 ob->xdir = 1;\r
434                 ob->state = &s_frenchythrow1;\r
435         }\r
436         else\r
437         {\r
438         // walk closer\r
439                 ob->xdir = 1;\r
440         }\r
441 }\r
442 \r
443 \r
444 /*\r
445 =============================================================================\r
446 \r
447                                                   MELON LIPS\r
448 \r
449 ob->temp1 = direction : 0 = left, 1 = right, 2 = down\r
450 \r
451 =============================================================================\r
452 */\r
453 \r
454 #define SPITXSPEED      48\r
455 #define SPITYSPEED      -20\r
456 \r
457 void MelonSpitThink (objtype *ob);\r
458 void    ProjectileReact (objtype *ob);\r
459 \r
460 extern  statetype s_melonside;\r
461 extern  statetype s_melonsidespit;\r
462 extern  statetype s_melonsidespit2;\r
463 \r
464 extern  statetype s_melondown;\r
465 extern  statetype s_melondownspit;\r
466 extern  statetype s_melondownspit2;\r
467 \r
468 extern  statetype s_melonseed1;\r
469 extern  statetype s_melonseed2;\r
470 \r
471 extern  statetype s_melonseedd1;\r
472 extern  statetype s_melonseedd2;\r
473 \r
474 #pragma warn -sus\r
475 \r
476 statetype s_melonside   = {MELONLIPSL1SPR,MELONLIPSR1SPR,step,false,\r
477         false,200, 0,0, NULL, NULL, DrawReact, &s_melonsidespit};\r
478 statetype s_melonsidespit= {MELONLIPSL2SPR,MELONLIPSR2SPR,step,false,\r
479         false,6, 0,0, MelonSpitThink, NULL, DrawReact, &s_melonsidespit2};\r
480 statetype s_melonsidespit2= {MELONLIPSL2SPR,MELONLIPSR2SPR,step,false,\r
481         false,6, 0,0, NULL, NULL, DrawReact, &s_melonside};\r
482 \r
483 statetype s_melondown   = {MELONLIPSD1SPR,MELONLIPSD1SPR,step,false,\r
484         false,200, 0,0, NULL, NULL, DrawReact, &s_melondownspit};\r
485 statetype s_melondownspit       = {MELONLIPSD2SPR,MELONLIPSD2SPR,step,false,\r
486         false,6, 0,0, MelonSpitThink, NULL, DrawReact, &s_melondownspit2};\r
487 statetype s_melondownspit2      = {MELONLIPSD2SPR,MELONLIPSD2SPR,step,false,\r
488         false,6, 0,0, NULL, NULL, DrawReact, &s_melondown};\r
489 \r
490 statetype s_melonseed1  = {MELONSEEDL1SPR,MELONSEEDR1SPR,think,false,\r
491         false,4, 0,0, ProjectileThink, NULL, ProjectileReact, &s_melonseed2};\r
492 statetype s_melonseed2  = {MELONSEEDL2SPR,MELONSEEDR2SPR,think,false,\r
493         false,4, 0,0, ProjectileThink, NULL, ProjectileReact, &s_melonseed1};\r
494 \r
495 statetype s_melonseedd1 = {MELONSEEDD1SPR,MELONSEEDD1SPR,stepthink,false,\r
496         false,4, 0,0, ProjectileThink, NULL, ProjectileReact, &s_melonseedd2};\r
497 statetype s_melonseedd2 = {MELONSEEDD2SPR,MELONSEEDD2SPR,stepthink,false,\r
498         false,4, 0,0, ProjectileThink, NULL, ProjectileReact, &s_melonseedd1};\r
499 \r
500 #pragma warn +sus\r
501 \r
502 /*\r
503 ====================\r
504 =\r
505 = SpawnMelon\r
506 =\r
507 ====================\r
508 */\r
509 \r
510 void SpawnMelon (int tilex, int tiley,int dir)\r
511 {\r
512         GetNewObj (false);\r
513 \r
514         new->obclass = melonobj;\r
515         new->x = tilex<<G_T_SHIFT;\r
516         new->y = tiley<<G_T_SHIFT;\r
517         if (dir)\r
518                 new->xdir = 1;\r
519         else\r
520                 new->xdir = -1;\r
521         if (dir <2)\r
522                 NewState (new,&s_melonside);\r
523         else\r
524                 NewState (new,&s_melondown);\r
525 \r
526         new->ticcount = US_RndT()>>1;\r
527         new->temp1 = dir;\r
528 }\r
529 \r
530 \r
531 /*\r
532 ====================\r
533 =\r
534 = MelonSpitThink\r
535 =\r
536 ====================\r
537 */\r
538 \r
539 void MelonSpitThink (objtype *ob)\r
540 {\r
541         GetNewObj (false);\r
542         new->obclass = shotobj;\r
543         switch (ob->temp1)\r
544         {\r
545         case 0:\r
546                 new->x = ob->x+24*16;\r
547                 new->y = ob->y+8*16;\r
548                 new->xdir = ob->xdir;\r
549                 new->ydir = 1;\r
550                 new->xspeed = -SPITXSPEED-(US_RndT()>>4);\r
551                 new->yspeed = SPITYSPEED;\r
552                 NewState (new,&s_melonseed1);\r
553                 break;\r
554         case 1:\r
555                 new->x = ob->x;\r
556                 new->y = ob->y+8*16;\r
557                 new->xdir = ob->xdir;\r
558                 new->ydir = 1;\r
559                 new->xspeed = SPITXSPEED+(US_RndT()>>4);\r
560                 new->yspeed = SPITYSPEED;\r
561                 NewState (new,&s_melonseed1);\r
562                 break;\r
563         case 2:\r
564                 new->x = ob->x+8*16;\r
565                 new->y = ob->y+24*16;\r
566                 new->ydir = 1;\r
567                 new->yspeed = -SPITYSPEED;\r
568                 NewState (new,&s_melonseedd1);\r
569                 break;\r
570         }\r
571 \r
572         new->active = removable;\r
573 }\r
574 \r
575 /*\r
576 ============================\r
577 =\r
578 = ProjectileReact\r
579 =\r
580 ============================\r
581 */\r
582 \r
583 void    ProjectileReact (objtype *ob)\r
584 {\r
585         unsigned wall,absx,absy,angle,newangle;\r
586         unsigned long speed;\r
587 \r
588         PLACESPRITE;\r
589         if (ob->hiteast || ob->hitwest)\r
590                 ob->xspeed= -ob->xspeed/2;\r
591 \r
592         if (ob->hitsouth)\r
593                 ob->yspeed= -ob->yspeed/2;\r
594 \r
595         wall = ob->hitnorth;\r
596         if (wall)\r
597         {\r
598                 if (ob->yspeed < 0)\r
599                         ob->yspeed = 0;\r
600 \r
601                 absx = abs(ob->xspeed);\r
602                 absy = ob->yspeed;\r
603                 if (absx>absy)\r
604                 {\r
605                         if (absx>absy*2)        // 22 degrees\r
606                         {\r
607                                 angle = 0;\r
608                                 speed = absx*286;       // x*sqrt(5)/2\r
609                         }\r
610                         else                            // 45 degrees\r
611                         {\r
612                                 angle = 1;\r
613                                 speed = absx*362;       // x*sqrt(2)\r
614                         }\r
615                 }\r
616                 else\r
617                 {\r
618                         if (absy>absx*2)        // 90 degrees\r
619                         {\r
620                                 angle = 3;\r
621                                 speed = absy*256;\r
622                         }\r
623                         else\r
624                         {\r
625                                 angle = 2;              // 67 degrees\r
626                                 speed = absy*286;       // y*sqrt(5)/2\r
627                         }\r
628                 }\r
629                 if (ob->xspeed > 0)\r
630                         angle = 7-angle;\r
631 \r
632                 speed >>= 1;\r
633                 newangle = bounceangle[ob->hitnorth][angle];\r
634                 switch (newangle)\r
635                 {\r
636                 case 0:\r
637                         ob->xspeed = speed / 286;\r
638                         ob->yspeed = -ob->xspeed / 2;\r
639                         break;\r
640                 case 1:\r
641                         ob->xspeed = speed / 362;\r
642                         ob->yspeed = -ob->xspeed;\r
643                         break;\r
644                 case 2:\r
645                         ob->yspeed = -(speed / 286);\r
646                         ob->xspeed = -ob->yspeed / 2;\r
647                         break;\r
648                 case 3:\r
649 \r
650                 case 4:\r
651                         ob->xspeed = 0;\r
652                         ob->yspeed = -(speed / 256);\r
653                         break;\r
654                 case 5:\r
655                         ob->yspeed = -(speed / 286);\r
656                         ob->xspeed = ob->yspeed / 2;\r
657                         break;\r
658                 case 6:\r
659                         ob->xspeed = ob->yspeed = -(speed / 362);\r
660                         break;\r
661                 case 7:\r
662                         ob->xspeed = -(speed / 286);\r
663                         ob->yspeed = ob->xspeed / 2;\r
664                         break;\r
665 \r
666                 case 8:\r
667                         ob->xspeed = -(speed / 286);\r
668                         ob->yspeed = -ob->xspeed / 2;\r
669                         break;\r
670                 case 9:\r
671                         ob->xspeed = -(speed / 362);\r
672                         ob->yspeed = -ob->xspeed;\r
673                         break;\r
674                 case 10:\r
675                         ob->yspeed = speed / 286;\r
676                         ob->xspeed = -ob->yspeed / 2;\r
677                         break;\r
678                 case 11:\r
679 \r
680                 case 12:\r
681                         ob->xspeed = 0;\r
682                         ob->yspeed = -(speed / 256);\r
683                         break;\r
684                 case 13:\r
685                         ob->yspeed = speed / 286;\r
686                         ob->xspeed = ob->yspeed / 2;\r
687                         break;\r
688                 case 14:\r
689                         ob->xspeed = speed / 362;\r
690                         ob->yspeed = speed / 362;\r
691                         break;\r
692                 case 15:\r
693                         ob->xspeed = speed / 286;\r
694                         ob->yspeed = ob->xspeed / 2;\r
695                         break;\r
696                 }\r
697 \r
698                 if (speed < 256*16)\r
699                         RemoveObj (ob);\r
700         }\r
701 }\r
702 \r
703 /*\r
704 =============================================================================\r
705 \r
706                                                         SQUASHER\r
707 \r
708 =============================================================================\r
709 */\r
710 \r
711 #define SPDSQUASHLEAPY  50\r
712 \r
713 \r
714 void SquasherThink (objtype *ob);\r
715 void SquasherJumpReact (objtype *ob);\r
716 \r
717 extern  statetype s_squasherwalk1;\r
718 extern  statetype s_squasherwalk2;\r
719 \r
720 extern  statetype s_squasherjump1;\r
721 extern  statetype s_squasherjump2;\r
722 \r
723 extern  statetype s_squasherwait;\r
724 \r
725 #pragma warn -sus\r
726 \r
727 statetype s_squasherwalk1       = {SQUASHERWALKL1SPR,SQUASHERWALKR1SPR,step,false,\r
728         true,10, 128,0, SquasherThink, NULL, WalkReact, &s_squasherwalk2};\r
729 statetype s_squasherwalk2       = {SQUASHERWALKL2SPR,SQUASHERWALKR2SPR,step,false,\r
730         true,10, 128,0, SquasherThink, NULL, WalkReact, &s_squasherwalk1};\r
731 \r
732 statetype s_squasherjump1       = {SQUASHERJUMPL1SPR,SQUASHERJUMPR1SPR,stepthink,false,\r
733         false,20, 0,0, ProjectileThink, NULL, SquasherJumpReact, &s_squasherjump2};\r
734 statetype s_squasherjump2       = {SQUASHERJUMPL2SPR,SQUASHERJUMPR2SPR,think,false,\r
735         false,0, 0,0, ProjectileThink, NULL, SquasherJumpReact, NULL};\r
736 \r
737 statetype s_squasherwait        = {SQUASHERJUMPL2SPR,SQUASHERJUMPR2SPR,step,false,\r
738         false,10, 0,0, ProjectileThink, NULL, DrawReact, &s_squasherwalk1};\r
739 \r
740 #pragma warn +sus\r
741 \r
742 /*\r
743 ====================\r
744 =\r
745 = SpawnSquasher\r
746 =\r
747 ====================\r
748 */\r
749 \r
750 void SpawnSquasher (int tilex, int tiley)\r
751 {\r
752         GetNewObj (false);\r
753 \r
754         new->obclass = squashobj;\r
755         new->x = tilex<<G_T_SHIFT;\r
756         new->y = (tiley<<G_T_SHIFT)-2*BLOCKSIZE;\r
757         new->xdir = 1;\r
758         new->ydir = 1;\r
759         NewState (new,&s_squasherwalk1);\r
760 }\r
761 \r
762 /*\r
763 ====================\r
764 =\r
765 = SquasherThink\r
766 =\r
767 ====================\r
768 */\r
769 \r
770 void SquasherThink (objtype *ob)\r
771 {\r
772         int delta;\r
773 \r
774         if ( abs(ob->y - player->y) > 3*TILEGLOBAL )\r
775         {\r
776                 if (US_RndT()<8)\r
777                         ob->xdir = -ob->xdir;           // turn randomly\r
778                 return;\r
779         }\r
780 \r
781 \r
782         delta = player->x - ob->x;\r
783 \r
784         if ( ob->xdir == -1 )\r
785         {\r
786                 if (delta < -6*TILEGLOBAL)\r
787                         return;\r
788                 if (delta > 8*PIXGLOBAL)\r
789                 {\r
790                         ob->xdir = 1;\r
791                         return;\r
792                 }\r
793         }\r
794         else\r
795         {\r
796                 if (delta > 6*TILEGLOBAL)\r
797                         return;\r
798                 if (delta < -8*PIXGLOBAL)\r
799                 {\r
800                         ob->xdir = 1;\r
801                         return;\r
802                 }\r
803         }\r
804 \r
805         ob->yspeed = -SPDSQUASHLEAPY;\r
806         ob->xspeed = delta/60;\r
807         ob->state = &s_squasherjump1;\r
808 }\r
809 \r
810 /*\r
811 ====================\r
812 =\r
813 = SquasherJumpReact\r
814 =\r
815 ====================\r
816 */\r
817 \r
818 void SquasherJumpReact (objtype *ob)\r
819 {\r
820         if (ob->hitsouth)\r
821                 ob->yspeed = 0;\r
822 \r
823         if (ob->hitnorth)\r
824                 ChangeState (ob,&s_squasherwait);\r
825 \r
826         PLACESPRITE;\r
827 }\r
828 \r
829 \r
830 /*\r
831 =============================================================================\r
832 \r
833                                                                 APEL\r
834 \r
835 temp4 = pole x coordinate\r
836 \r
837 =============================================================================\r
838 */\r
839 \r
840 void ApelThink (objtype *ob);\r
841 void ApelClimbThink (objtype *ob);\r
842 void ApelSlideThink (objtype *ob);\r
843 void ApelFallThink (objtype *ob);\r
844 \r
845 void ApelClimbReact (objtype *ob);\r
846 void ApelSlideReact (objtype *ob);\r
847 void ApelFallReact (objtype *ob);\r
848 \r
849 extern  statetype s_apelwalk1;\r
850 extern  statetype s_apelwalk2;\r
851 extern  statetype s_apelwalk3;\r
852 \r
853 extern  statetype s_apelclimb1;\r
854 extern  statetype s_apelclimb2;\r
855 \r
856 extern  statetype s_apelslide1;\r
857 extern  statetype s_apelslide2;\r
858 extern  statetype s_apelslide3;\r
859 extern  statetype s_apelslide4;\r
860 \r
861 extern  statetype s_apelfall;\r
862 \r
863 #pragma warn -sus\r
864 \r
865 statetype s_apelwalk1   = {APELWALKL1SPR,APELWALKR1SPR,step,false,\r
866         true,10, 128,0, ApelThink, NULL, WalkReact, &s_apelwalk2};\r
867 statetype s_apelwalk2   = {APELWALKL2SPR,APELWALKR2SPR,step,false,\r
868         true,10, 128,0, ApelThink, NULL, WalkReact, &s_apelwalk3};\r
869 statetype s_apelwalk3   = {APELWALKL3SPR,APELWALKR3SPR,step,false,\r
870         true,10, 128,0, ApelThink, NULL, WalkReact, &s_apelwalk1};\r
871 \r
872 statetype s_apelclimb1  = {APELSHINNY1SPR,APELSHINNY1SPR,slide,false,\r
873         false,6, 0,-16, ApelClimbThink, NULL, ApelClimbReact, &s_apelclimb2};\r
874 statetype s_apelclimb2  = {APELSHINNY2SPR,APELSHINNY2SPR,slide,false,\r
875         false,6, 0,-16, ApelClimbThink, NULL, ApelClimbReact, &s_apelclimb1};\r
876 \r
877 statetype s_apelslide1  = {APELSLIDE1SPR,APELSLIDE1SPR,slide,false,\r
878         false,6, 0,16, ApelSlideThink, NULL, ApelFallReact, &s_apelslide2};\r
879 statetype s_apelslide2  = {APELSLIDE2SPR,APELSLIDE2SPR,slide,false,\r
880         false,6, 0,16, ApelSlideThink, NULL, ApelFallReact, &s_apelslide3};\r
881 statetype s_apelslide3  = {APELSLIDE3SPR,APELSLIDE3SPR,slide,false,\r
882         false,6, 0,16, ApelSlideThink, NULL, ApelFallReact, &s_apelslide4};\r
883 statetype s_apelslide4  = {APELSLIDE4SPR,APELSLIDE4SPR,slide,false,\r
884         false,6, 0,16, ApelSlideThink, NULL, ApelFallReact, &s_apelslide1};\r
885 \r
886 statetype s_apelfall = {APELWALKL1SPR,APELWALKR1SPR,think,false,\r
887         false,0, 0,0, ProjectileThink, NULL, ApelFallReact, NULL};\r
888 \r
889 #pragma warn +sus\r
890 \r
891 \r
892 /*\r
893 ====================\r
894 =\r
895 = SpawnApel\r
896 =\r
897 ====================\r
898 */\r
899 \r
900 void SpawnApel (int tilex, int tiley)\r
901 {\r
902         GetNewObj (false);\r
903 \r
904         new->obclass = apelobj;\r
905         new->x = tilex<<G_T_SHIFT;\r
906         new->y = (tiley<<G_T_SHIFT)-2*BLOCKSIZE;\r
907         new->xdir = 1;\r
908         new->ydir = 1;\r
909         NewState (new,&s_apelwalk1);\r
910 }\r
911 \r
912 \r
913 /*\r
914 ====================\r
915 =\r
916 = ApelThink\r
917 =\r
918 ====================\r
919 */\r
920 \r
921 void ApelThink (objtype *ob)\r
922 {\r
923         int     x,y;\r
924         unsigned far *map;\r
925 \r
926         if (ob->top > player->bottom || ob->bottom < player->top)\r
927         {\r
928         //\r
929         // try to climb a pole to reach player\r
930         //\r
931                 if (ob->y < player->y)\r
932                         y = ob->tilebottom;\r
933                 else\r
934                         y = ob->tiletop;\r
935 \r
936                 map = (unsigned _seg *)mapsegs[1]+\r
937                         mapbwidthtable[y]/2 + ob->tilemidx;\r
938 \r
939                 if ((tinf[INTILE+*map]&0x7f) == 1)\r
940                 {\r
941                         ob->xmove = (ob->tilemidx<<G_T_SHIFT) - ob->x;\r
942                         ob->ymove = 0;\r
943                         ob->temp4 = ob->tilemidx;       // for future reference\r
944                         ob->needtoclip = false;         // can climb through pole holes\r
945                         if (ob->y < player->y)\r
946                                 ob->state = &s_apelslide1;\r
947                         else\r
948                                 ob->state = &s_apelclimb1;\r
949                         return;\r
950                 }\r
951         }\r
952 \r
953         if (US_RndT()>32)               // don't turn around all the time\r
954                 return;\r
955 \r
956         if (ob->x < player->x)\r
957                 ob->xdir = 1;\r
958         else\r
959                 ob->xdir = -1;\r
960 \r
961 }\r
962 \r
963 \r
964 /*\r
965 ====================\r
966 =\r
967 = ApelClimbThink\r
968 =\r
969 ====================\r
970 */\r
971 \r
972 void ApelClimbThink (objtype *ob)\r
973 {\r
974         unsigned far *map;\r
975 \r
976         map = (unsigned _seg *)mapsegs[1]+\r
977                 mapbwidthtable[ob->tiletop]/2 + ob->temp4;\r
978 \r
979         if ((tinf[INTILE+*map]&0x7f) != 1)\r
980         {\r
981                 ob->needtoclip = true;\r
982                 ob->state = &s_apelfall;\r
983         }\r
984 }\r
985 \r
986 \r
987 /*\r
988 ====================\r
989 =\r
990 = ApelSlideThink\r
991 =\r
992 ====================\r
993 */\r
994 \r
995 void ApelSlideThink (objtype *ob)\r
996 {\r
997         unsigned far *map;\r
998 \r
999         map = (unsigned _seg *)mapsegs[1]+\r
1000                 mapbwidthtable[ob->tilebottom]/2 + ob->temp4;\r
1001 \r
1002         if ((tinf[INTILE+*map]&0x7f) != 1)\r
1003         {\r
1004                 ob->needtoclip = true;\r
1005                 ob->state = &s_apelfall;\r
1006         }\r
1007 }\r
1008 \r
1009 \r
1010 /*\r
1011 ====================\r
1012 =\r
1013 = ApelClimbReact\r
1014 =\r
1015 ====================\r
1016 */\r
1017 \r
1018 void ApelClimbReact (objtype *ob)\r
1019 {\r
1020         if (ob->hitsouth)\r
1021                 ChangeState (ob,&s_apelfall);\r
1022         PLACESPRITE;\r
1023 }\r
1024 \r
1025 \r
1026 /*\r
1027 ====================\r
1028 =\r
1029 = ApelFallReact\r
1030 =\r
1031 ====================\r
1032 */\r
1033 \r
1034 void ApelFallReact (objtype *ob)\r
1035 {\r
1036         if (ob->hitnorth)\r
1037                 ChangeState (ob,&s_apelwalk1);\r
1038         PLACESPRITE;\r
1039 }\r
1040 \r
1041 \r
1042 /*\r
1043 =============================================================================\r
1044 \r
1045                                                                 PEA BRAIN\r
1046 \r
1047 =============================================================================\r
1048 */\r
1049 \r
1050 void PeaBrainThink (objtype *ob);\r
1051 void PeaFlyReact (objtype *ob);\r
1052 \r
1053 extern statetype s_peabrainfly;\r
1054 \r
1055 extern  statetype s_peabrainwalk1;\r
1056 extern  statetype s_peabrainwalk2;\r
1057 extern  statetype s_peabrainwalk3;\r
1058 extern  statetype s_peabrainwalk4;\r
1059 \r
1060 #pragma warn -sus\r
1061 \r
1062 statetype s_peabrainfly = {PEABRAINWALKL1SPR,PEABRAINWALKR1SPR,think,false,\r
1063         false,0, 0,0, ProjectileThink, NULL, PeaFlyReact, NULL};\r
1064 \r
1065 statetype s_peabrainwalk1       = {PEABRAINWALKL1SPR,PEABRAINWALKR1SPR,step,false,\r
1066         true,10, 128,0, PeaBrainThink, NULL, WalkReact, &s_peabrainwalk2};\r
1067 statetype s_peabrainwalk2       = {PEABRAINWALKL2SPR,PEABRAINWALKR2SPR,step,false,\r
1068         true,10, 128,0, PeaBrainThink, NULL, WalkReact, &s_peabrainwalk3};\r
1069 statetype s_peabrainwalk3       = {PEABRAINWALKL3SPR,PEABRAINWALKR3SPR,step,false,\r
1070         true,10, 128,0, PeaBrainThink, NULL, WalkReact, &s_peabrainwalk4};\r
1071 statetype s_peabrainwalk4       = {PEABRAINWALKL4SPR,PEABRAINWALKR4SPR,step,false,\r
1072         true,10, 128,0, PeaBrainThink, NULL, WalkReact, &s_peabrainwalk1};\r
1073 \r
1074 #pragma warn +sus\r
1075 \r
1076 /*\r
1077 ====================\r
1078 =\r
1079 = SpawnPeaBrain\r
1080 =\r
1081 ====================\r
1082 */\r
1083 \r
1084 void SpawnPeaBrain (int tilex, int tiley)\r
1085 {\r
1086         GetNewObj (false);\r
1087 \r
1088         new->obclass = peabrainobj;\r
1089         new->x = tilex<<G_T_SHIFT;\r
1090         new->y = tiley<<G_T_SHIFT;\r
1091         NewState (new,&s_peabrainwalk1);\r
1092 }\r
1093 \r
1094 /*\r
1095 ====================\r
1096 =\r
1097 = PeaBrainThink\r
1098 =\r
1099 ====================\r
1100 */\r
1101 \r
1102 void PeaBrainThink (objtype *ob)\r
1103 {\r
1104         ob++;\r
1105 }\r
1106 \r
1107 \r
1108 /*\r
1109 ====================\r
1110 =\r
1111 = PeaFlyReact\r
1112 =\r
1113 ====================\r
1114 */\r
1115 \r
1116 void PeaFlyReact (objtype *ob)\r
1117 {\r
1118         if (ob->hitnorth)\r
1119                 ChangeState (ob,&s_peabrainwalk1);\r
1120 \r
1121         PLACESPRITE;\r
1122 }\r
1123 \r
1124 \r
1125 /*\r
1126 =============================================================================\r
1127 \r
1128                                                                 PEA POD\r
1129 \r
1130 temp1 = number of peas spit\r
1131 \r
1132 =============================================================================\r
1133 */\r
1134 \r
1135 #define MAXPEASPIT      4\r
1136 \r
1137 #define PEAXSPEED       48\r
1138 #define PEAYSPEED       -20\r
1139 \r
1140 \r
1141 void PeaPodThink (objtype *ob);\r
1142 void SpitPeaBrain (objtype *ob);\r
1143 \r
1144 extern  statetype s_peapodwalk1;\r
1145 extern  statetype s_peapodwalk2;\r
1146 extern  statetype s_peapodwalk3;\r
1147 extern  statetype s_peapodwalk4;\r
1148 \r
1149 extern  statetype s_peapodspit1;\r
1150 extern  statetype s_peapodspit2;\r
1151 \r
1152 #pragma warn -sus\r
1153 \r
1154 statetype s_peapodwalk1 = {PEAPODRUNL1SPR,PEAPODRUNR1SPR,step,false,\r
1155         true,10, 128,0, PeaPodThink, NULL, WalkReact, &s_peapodwalk2};\r
1156 statetype s_peapodwalk2 = {PEAPODRUNL2SPR,PEAPODRUNR2SPR,step,false,\r
1157         true,10, 128,0, PeaPodThink, NULL, WalkReact, &s_peapodwalk3};\r
1158 statetype s_peapodwalk3 = {PEAPODRUNL3SPR,PEAPODRUNR3SPR,step,false,\r
1159         true,10, 128,0, PeaPodThink, NULL, WalkReact, &s_peapodwalk4};\r
1160 statetype s_peapodwalk4 = {PEAPODRUNL4SPR,PEAPODRUNR4SPR,step,false,\r
1161         true,10, 128,0, PeaPodThink, NULL, WalkReact, &s_peapodwalk1};\r
1162 \r
1163 statetype s_peapodspit1 = {PEAPODSPITLSPR,PEAPODSPITRSPR,step,false,\r
1164         true,30, 0,0, SpitPeaBrain, NULL, DrawReact, &s_peapodspit2};\r
1165 statetype s_peapodspit2 = {PEAPODSPITLSPR,PEAPODSPITRSPR,step,false,\r
1166         true,30, 0,0, NULL, NULL, DrawReact, &s_peapodwalk1};\r
1167 \r
1168 #pragma warn +sus\r
1169 \r
1170 /*\r
1171 ====================\r
1172 =\r
1173 = SpawnPeaPod\r
1174 =\r
1175 ====================\r
1176 */\r
1177 \r
1178 void SpawnPeaPod (int tilex, int tiley)\r
1179 {\r
1180         GetNewObj (false);\r
1181 \r
1182         new->obclass = peapodobj;\r
1183         new->x = tilex<<G_T_SHIFT;\r
1184         new->y = (tiley<<G_T_SHIFT)-2*BLOCKSIZE;\r
1185         new->xdir = 1;\r
1186         new->ydir = 1;\r
1187         NewState (new,&s_peapodwalk1);\r
1188 }\r
1189 \r
1190 /*\r
1191 ====================\r
1192 =\r
1193 = SpitPeaBrain\r
1194 =\r
1195 ====================\r
1196 */\r
1197 \r
1198 void SpitPeaBrain (objtype *ob)\r
1199 {\r
1200         GetNewObj (true);\r
1201         new->obclass = peabrainobj;\r
1202         if (ob->xdir == 1)\r
1203         {\r
1204                 new->x = ob->x+8*16;\r
1205                 new->y = ob->y+8*16;\r
1206         }\r
1207         else\r
1208         {\r
1209                 new->x = ob->x;\r
1210                 new->y = ob->y+8*16;\r
1211         }\r
1212         new->xdir = ob->xdir;\r
1213         new->ydir = 1;\r
1214         new->xspeed = ob->xdir * PEAXSPEED-(US_RndT()>>4);\r
1215         new->yspeed = PEAYSPEED;\r
1216         NewState (new,&s_peabrainfly);\r
1217 }\r
1218 \r
1219 \r
1220 \r
1221 /*\r
1222 ====================\r
1223 =\r
1224 = PeaPodThink\r
1225 =\r
1226 ====================\r
1227 */\r
1228 \r
1229 void PeaPodThink (objtype *ob)\r
1230 {\r
1231         int delta;\r
1232 \r
1233         if ( abs(ob->y - player->y) > 3*TILEGLOBAL )\r
1234                 return;\r
1235 \r
1236         if (player->x < ob->x && ob->xdir == 1)\r
1237                 return;\r
1238 \r
1239         if (player->x > ob->x && ob->xdir == -1)\r
1240                 return;\r
1241 \r
1242         if (US_RndT()<8 && ob->temp1 < MAXPEASPIT)\r
1243         {\r
1244                 ob->temp1 ++;\r
1245                 ob->state = &s_peapodspit1;\r
1246                 ob->xmove = 0;\r
1247         }\r
1248 }\r
1249 \r
1250 \r
1251 /*\r
1252 =============================================================================\r
1253 \r
1254                                                         BOOBUS TUBOR\r
1255 \r
1256 temp4 = hit points\r
1257 \r
1258 =============================================================================\r
1259 */\r
1260 \r
1261 #define PREFRAGTHINK    60\r
1262 #define POSTFRAGTHINK   60\r
1263 \r
1264 #define SPDBOOBUSJUMP   60\r
1265 #define SPDBOOBUSRUNJUMP 24\r
1266 \r
1267 void BoobusThink (objtype *ob);\r
1268 void FinishThink (objtype *ob);\r
1269 void FragThink (objtype *ob);\r
1270 void BoobusGroundReact (objtype *ob);\r
1271 void BoobusAirReact (objtype *ob);\r
1272 \r
1273 extern  statetype s_boobuswalk1;\r
1274 extern  statetype s_boobuswalk2;\r
1275 extern  statetype s_boobuswalk3;\r
1276 extern  statetype s_boobuswalk4;\r
1277 \r
1278 extern  statetype s_boobusjump;\r
1279 \r
1280 extern  statetype s_deathwait1;\r
1281 extern  statetype s_deathwait2;\r
1282 extern  statetype s_deathwait3;\r
1283 extern  statetype s_deathboom1;\r
1284 extern  statetype s_deathboom2;\r
1285 extern  statetype s_deathboom3;\r
1286 extern  statetype s_deathboom4;\r
1287 extern  statetype s_deathboom5;\r
1288 extern  statetype s_deathboom6;\r
1289 \r
1290 #pragma warn -sus\r
1291 \r
1292 statetype s_boobuswalk1 = {BOOBUSWALKL1SPR,BOOBUSWALKR1SPR,step,false,\r
1293         true,10, 128,0, BoobusThink, NULL, BoobusGroundReact, &s_boobuswalk2};\r
1294 statetype s_boobuswalk2 = {BOOBUSWALKL2SPR,BOOBUSWALKR2SPR,step,false,\r
1295         true,10, 128,0, BoobusThink, NULL, BoobusGroundReact, &s_boobuswalk3};\r
1296 statetype s_boobuswalk3 = {BOOBUSWALKL3SPR,BOOBUSWALKR3SPR,step,false,\r
1297         true,10, 128,0, BoobusThink, NULL, BoobusGroundReact, &s_boobuswalk4};\r
1298 statetype s_boobuswalk4 = {BOOBUSWALKL4SPR,BOOBUSWALKR4SPR,step,false,\r
1299         true,10, 128,0, BoobusThink, NULL, BoobusGroundReact, &s_boobuswalk1};\r
1300 \r
1301 statetype s_boobusjump  = {BOOBUSJUMPSPR,BOOBUSJUMPSPR,think,false,\r
1302         false,0, 0,0, ProjectileThink, NULL, BoobusAirReact, NULL};\r
1303 \r
1304 statetype s_boobusdie   = {BOOBUSJUMPSPR,BOOBUSJUMPSPR,step,false,\r
1305         false,4, 0,0, FragThink, NULL, DrawReact, &s_boobusdie};\r
1306 statetype s_boobusdie2  = {NULL,NULL,step,false,\r
1307         false,4, 0,0, FragThink, NULL, NULL, &s_boobusdie2};\r
1308 statetype s_boobusdie3  = {NULL,NULL,step,false,\r
1309         false,250, 0,0, FinishThink, NULL, NULL, NULL};\r
1310 \r
1311 statetype s_deathboom1  = {BOOBUSBOOM1SPR,BOOBUSBOOM1SPR,step,false,\r
1312         false,20, 0,0, ProjectileThink, NULL, DrawReact3, &s_deathboom2};\r
1313 statetype s_deathboom2  = {BOOBUSBOOM2SPR,BOOBUSBOOM2SPR,step,false,\r
1314         false,20, 0,0, ProjectileThink, NULL, DrawReact3, &s_deathboom3};\r
1315 statetype s_deathboom3  = {POOF1SPR,POOF1SPR,step,false,\r
1316         false,40, 0,0, ProjectileThink, NULL, DrawReact3, &s_deathboom4};\r
1317 statetype s_deathboom4  = {POOF2SPR,POOF2SPR,step,false,\r
1318         false,30, 0,0, ProjectileThink, NULL, DrawReact3, &s_deathboom5};\r
1319 statetype s_deathboom5  = {POOF3SPR,POOF3SPR,step,false,\r
1320         false,30, 0,0, ProjectileThink, NULL, DrawReact3, &s_deathboom6};\r
1321 statetype s_deathboom6  = {POOF4SPR,POOF4SPR,step,false,\r
1322         false,30, 0,0, ProjectileThink, NULL, DrawReact3, NULL};\r
1323 \r
1324 \r
1325 #pragma warn +sus\r
1326 \r
1327 /*\r
1328 ====================\r
1329 =\r
1330 = SpawnBoobus\r
1331 =\r
1332 ====================\r
1333 */\r
1334 \r
1335 void SpawnBoobus (int tilex, int tiley)\r
1336 {\r
1337         GetNewObj (false);\r
1338 \r
1339         new->obclass = boobusobj;\r
1340         new->x = tilex<<G_T_SHIFT;\r
1341         new->y = (tiley<<G_T_SHIFT)-11*BLOCKSIZE;\r
1342         new->xdir = -1;\r
1343         NewState (new,&s_boobuswalk1);\r
1344         new->temp4 = 12;                        // hit points\r
1345 }\r
1346 \r
1347 \r
1348 /*\r
1349 ===================\r
1350 =\r
1351 = FragThink\r
1352 =\r
1353 ===================\r
1354 */\r
1355 \r
1356 void FragThink (objtype *ob)\r
1357 {\r
1358         if (++ob->temp1 == PREFRAGTHINK)\r
1359                 ob->state = &s_boobusdie2;\r
1360         if (++ob->temp1 == POSTFRAGTHINK)\r
1361         {\r
1362                 RF_RemoveSprite (&ob->sprite);\r
1363                 ob->state = &s_boobusdie3;\r
1364         }\r
1365 \r
1366         SD_PlaySound (BOMBBOOMSND);\r
1367         GetNewObj (true);\r
1368         new->x = ob->x-BLOCKSIZE + 5*US_RndT();\r
1369         new->y = ob->y-BLOCKSIZE + 5*US_RndT();\r
1370         new->xspeed = 0; //US_RndT()/4-32;\r
1371         new->yspeed = 0; //US_RndT()/4-32;\r
1372         US_RndT();                                      // keep rnd from even wrapping\r
1373         ChangeState (new,&s_deathboom1);\r
1374 }\r
1375 \r
1376 \r
1377 /*\r
1378 ===================\r
1379 =\r
1380 = FinishThink\r
1381 =\r
1382 ===================\r
1383 */\r
1384 \r
1385 void FinishThink (objtype *ob)\r
1386 {\r
1387         playstate = victorious;\r
1388         ob++;\r
1389         SD_PlaySound (BOOBUSGONESND);\r
1390 }\r
1391 \r
1392 \r
1393 /*\r
1394 ====================\r
1395 =\r
1396 = BoobusThink\r
1397 =\r
1398 ====================\r
1399 */\r
1400 \r
1401 void BoobusThink (objtype *ob)\r
1402 {\r
1403         unsigned        move;\r
1404         boolean inline = false;\r
1405 \r
1406         if (ob->left > player->right)\r
1407                 ob->xdir = -1;\r
1408         else if (ob->right < player->left)\r
1409                 ob->xdir = 1;\r
1410         else\r
1411                 inline = true;\r
1412 \r
1413         if (player->top < ob->bottom && player->bottom > ob->top)\r
1414         {\r
1415         // on same level as player, so charge!\r
1416 \r
1417         }\r
1418         else\r
1419         {\r
1420         // above or below player, so get directly in line and jump\r
1421                 if (inline)\r
1422                 {\r
1423                         if (ob->y < player->y)\r
1424                         {\r
1425                         // drop down\r
1426                                 move = PIXGLOBAL*8;\r
1427                                 ob->tilebottom++;\r
1428                                 ob->bottom += move;\r
1429                                 ob->y += move;\r
1430                                 ob->state = &s_boobusjump;\r
1431                                 ob->yspeed = ob->xmove = ob->xspeed = ob->ymove = 0;\r
1432                         }\r
1433                         else\r
1434                         {\r
1435                         // jump up\r
1436                                 ob->state = &s_boobusjump;\r
1437                                 ob->yspeed = -SPDBOOBUSJUMP;\r
1438                                 ob->xspeed = 0;\r
1439                         }\r
1440 \r
1441                 }\r
1442         }\r
1443 }\r
1444 \r
1445 /*\r
1446 ====================\r
1447 =\r
1448 = BoobusGroundReact\r
1449 =\r
1450 ====================\r
1451 */\r
1452 \r
1453 void BoobusGroundReact (objtype *ob)\r
1454 {\r
1455         if (ob->xdir == 1 && ob->hitwest)\r
1456         {\r
1457                 ob->x -= ob->xmove;\r
1458                 ob->xdir = -1;\r
1459                 ob->nothink = US_RndT()>>5;\r
1460                 ChangeState (ob,ob->state);\r
1461         }\r
1462         else if (ob->xdir == -1 && ob->hiteast)\r
1463         {\r
1464                 ob->x -= ob->xmove;\r
1465                 ob->xdir = 1;\r
1466                 ob->nothink = US_RndT()>>5;\r
1467                 ChangeState (ob,ob->state);\r
1468         }\r
1469         else if (!ob->hitnorth)\r
1470         {\r
1471                 if (ob->bottom >= player->bottom)\r
1472                 {\r
1473                  // jump over\r
1474                         ob->x -= ob->xmove;\r
1475                         ob->y -= ob->ymove;\r
1476                         ob->yspeed = -SPDBOOBUSJUMP;\r
1477                         ob->xspeed = ob->xdir * SPDBOOBUSRUNJUMP;\r
1478                 }\r
1479                 else\r
1480                 {\r
1481                 // drop down\r
1482                         ob->xspeed = ob->yspeed = 0;\r
1483                 }\r
1484                 ChangeState (ob,&s_boobusjump);\r
1485         }\r
1486 \r
1487         PLACESPRITE;\r
1488 }\r
1489 \r
1490 \r
1491 \r
1492 /*\r
1493 ====================\r
1494 =\r
1495 = BoobusAirReact\r
1496 =\r
1497 ====================\r
1498 */\r
1499 \r
1500 void BoobusAirReact (objtype *ob)\r
1501 {\r
1502         if (ob->hitsouth)\r
1503                 ob->yspeed = 0;\r
1504 \r
1505         if (ob->hitnorth)\r
1506                 ChangeState (ob,&s_boobuswalk1);\r
1507 \r
1508         PLACESPRITE;\r
1509 }\r