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 / c6_act1.c
1 /* Catacomb Apocalypse Source Code\r
2  * Copyright (C) 1993-2014 Flat Rock Software\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 // C3_PLAY.C\r
20 \r
21 #include "DEF.H"\r
22 #pragma hdrstop\r
23 \r
24 /*\r
25 =============================================================================\r
26 \r
27                                                  LOCAL CONSTANTS\r
28 \r
29 =============================================================================\r
30 */\r
31 \r
32 #if 0\r
33 #define MSHOTDAMAGE     2\r
34 #define MSHOTSPEED      10000\r
35 \r
36 #define ESHOTDAMAGE     1\r
37 #define ESHOTSPEED      5000\r
38 \r
39 #define SSHOTDAMAGE     3\r
40 #define SSHOTSPEED      6500\r
41 \r
42 #define RANDOM_ATTACK 20\r
43 #endif\r
44 \r
45 /*\r
46 =============================================================================\r
47 \r
48                                                  GLOBAL VARIABLES\r
49 \r
50 =============================================================================\r
51 */\r
52 \r
53 boolean ShootPlayer (objtype *ob, short obclass, short speed, statetype *state);\r
54 void T_ShootPlayer(objtype *ob);\r
55 \r
56 short zombie_base_delay;\r
57 \r
58 short other_x[] = {0,39,39,0},\r
59                 other_y[] = {0,0,27,27};\r
60 \r
61 /*\r
62 =============================================================================\r
63 \r
64                                                  LOCAL VARIABLES\r
65 \r
66 =============================================================================\r
67 */\r
68 \r
69 \r
70 dirtype dirtable[9] = {northwest,north,northeast,west,nodir,east,\r
71         southwest,south,southeast};\r
72 \r
73 \r
74 /*\r
75 =============================================================================\r
76 \r
77                                                   BONUS ITEMS\r
78 \r
79 =============================================================================\r
80 */\r
81 \r
82 statetype s_boltbonus = {BOLTOBJPIC,8,NULL,&s_boltbonus2};\r
83 statetype s_boltbonus2 = {BOLT2OBJPIC,8,NULL,&s_boltbonus3};\r
84 statetype s_boltbonus3 = {BOLT3OBJPIC,8,NULL,&s_boltbonus};\r
85 \r
86 statetype s_nukebonus = {NUKEOBJPIC,8,NULL,&s_nukebonus2};\r
87 statetype s_nukebonus2 = {NUKE2OBJPIC,8,NULL,&s_nukebonus3};\r
88 statetype s_nukebonus3 = {NUKE3OBJPIC,8,NULL,&s_nukebonus};\r
89 \r
90 statetype s_potionbonus = {POTIONOBJPIC,0,NULL,&s_potionbonus};\r
91 statetype s_rkeybonus = {RKEYOBJPIC,0,NULL,&s_rkeybonus};\r
92 statetype s_ykeybonus = {YKEYOBJPIC,0,NULL,&s_ykeybonus};\r
93 statetype s_gkeybonus = {GKEYOBJPIC,0,NULL,&s_gkeybonus};\r
94 statetype s_bkeybonus = {BKEYOBJPIC,0,NULL,&s_bkeybonus};\r
95 statetype s_chestbonus = {CHESTOBJPIC,0,NULL,&s_chestbonus};\r
96 statetype s_oldchestbonus = {OLD_CHESTPIC,0,NULL,&s_oldchestbonus};\r
97 \r
98 statetype s_waterchestbonus1 = {O_WATER_CHEST1PIC, 10, NULL, &s_waterchestbonus2};\r
99 statetype s_waterchestbonus2 = {O_WATER_CHEST2PIC, 10, NULL, &s_waterchestbonus3};\r
100 statetype s_waterchestbonus3 = {O_WATER_CHEST3PIC, 10, NULL, &s_waterchestbonus1};\r
101 \r
102 statetype s_rgem1bonus = {RGEM1PIC,30,NULL,&s_rgem1bonus};\r
103 statetype s_ygem1bonus = {YGEM1PIC,30,NULL,&s_ygem1bonus};\r
104 statetype s_ggem1bonus = {GGEM1PIC,30,NULL,&s_ggem1bonus};\r
105 statetype s_bgem1bonus = {BGEM1PIC,30,NULL,&s_bgem1bonus};\r
106 statetype s_pgem1bonus = {PGEM1PIC,30,NULL,&s_pgem1bonus};\r
107 \r
108 statetype s_bonus_die = {0,8,NULL,NULL};\r
109 \r
110 /*\r
111 ===============\r
112 =\r
113 = SpawnBonus\r
114 =\r
115 ===============\r
116 */\r
117 \r
118 void SpawnBonus (int tilex, int tiley, int number)\r
119 {\r
120         extern unsigned gcolor;\r
121 \r
122         statetype *state;\r
123 \r
124         switch (number)\r
125         {\r
126                 case B_BOLT:                    state = &s_boltbonus;           break;\r
127                 case B_NUKE:                    state = &s_nukebonus;           break;\r
128                 case B_POTION:                  state = &s_potionbonus;         break;\r
129 \r
130                 case B_RKEY:                    state = &s_rkeybonus;           break;\r
131                 case B_YKEY:                    state = &s_ykeybonus;           break;\r
132                 case B_GKEY:                    state = &s_gkeybonus;           break;\r
133                 case B_BKEY:                    state = &s_bkeybonus;           break;\r
134 \r
135                 case B_RGEM:                    state = &s_rgem1bonus;          break;\r
136                 case B_YGEM:                    state = &s_ygem1bonus;          break;\r
137                 case B_GGEM:                    state = &s_ggem1bonus;          break;\r
138                 case B_BGEM:                    state = &s_bgem1bonus;          break;\r
139                 case B_PGEM:                    state = &s_pgem1bonus;          break;\r
140 \r
141                 case B_CHEST:\r
142                         if (gcolor == 0x0101)\r
143                                 state = &s_waterchestbonus1;\r
144                         else\r
145                                 state = &s_chestbonus;\r
146                 break;\r
147 \r
148                 case B_OLDCHEST:                state = &s_oldchestbonus;       break;\r
149 \r
150 \r
151                 default:\r
152                         Quit("SpawnBonus(): INVALID BONUS");\r
153                 break;\r
154         }\r
155 \r
156         SpawnNewObj (tilex,tiley,state,TILEGLOBAL/2);\r
157         new->temp1 = number;\r
158         new->obclass = bonusobj;\r
159 \r
160         switch (number)\r
161         {\r
162                 case B_POTION:\r
163                 case B_OLDCHEST:\r
164                 case B_CHEST:\r
165                 case B_BOLT:\r
166                 case B_NUKE:\r
167                         new->flags |= of_shootable;\r
168                 break;\r
169 \r
170                 default:\r
171                         new->flags &= ~of_shootable;\r
172                 break;\r
173         }\r
174 }\r
175 \r
176 \r
177 \r
178 /*\r
179 ============================================================================\r
180 \r
181                                                                         FREEZE TIME OBJECT\r
182 \r
183 ============================================================================\r
184 */\r
185 \r
186 extern statetype s_ftimebonus;\r
187 extern statetype s_ftimebonus2;\r
188 \r
189 statetype s_ftimebonus = {TIMEOBJ1PIC,6,NULL,&s_ftimebonus2};\r
190 statetype s_ftimebonus2 = {TIMEOBJ2PIC,6,NULL,&s_ftimebonus};\r
191 \r
192 /*\r
193 ===============\r
194 =\r
195 = SpawnFTime\r
196 =\r
197 ===============\r
198 */\r
199 void SpawnFTime(int tilex, int tiley)\r
200 {\r
201         SpawnNewObj(tilex,tiley,&s_ftimebonus,TILEGLOBAL/2);\r
202 //      new->tileobject = true;\r
203         new->obclass = freezeobj;\r
204         new->flags |= of_shootable;\r
205 }\r
206 \r
207 /*\r
208 =============================================================================\r
209 \r
210                                           EXPLODING WALL\r
211 \r
212 =============================================================================\r
213 */\r
214 \r
215 \r
216 void T_WallDie (objtype *ob);\r
217 \r
218 extern  statetype s_walldie1;\r
219 extern  statetype s_walldie2;\r
220 extern  statetype s_walldie3;\r
221 extern  statetype s_walldie4;\r
222 extern  statetype s_walldie5;\r
223 extern  statetype s_walldie6;\r
224 \r
225 statetype s_walldie1 = {0,20,NULL,&s_walldie2};\r
226 statetype s_walldie2 = {0,-1,T_WallDie,&s_walldie3};\r
227 statetype s_walldie3 = {0,20,NULL,&s_walldie4};\r
228 statetype s_walldie4 = {0,-1,T_WallDie,&s_walldie5};\r
229 statetype s_walldie5 = {0,20,NULL,&s_walldie6};\r
230 statetype s_walldie6 = {0,-1,T_WallDie,NULL};\r
231 \r
232 \r
233 /*\r
234 ================\r
235 =\r
236 = ExplodeWall\r
237 =\r
238 ================\r
239 */\r
240 \r
241 void ExplodeWall (int tilex, int tiley)\r
242 {\r
243         extern unsigned gcolor;\r
244         unsigned tilenum;\r
245 \r
246         DSpawnNewObj (tilex,tiley,&s_walldie1,0);\r
247         if (new == &dummyobj)\r
248                 return;\r
249         new->obclass = inertobj;\r
250         new->active = always;\r
251         if (gcolor == 0x0101)\r
252                 tilenum = WATEREXP;\r
253         else\r
254                 tilenum = WALLEXP;\r
255         (unsigned)actorat[new->tilex][new->tiley] = tilemap[new->tilex][new->tiley] =\r
256                 *(mapsegs[0]+farmapylookup[new->tiley]+new->tilex) = tilenum;\r
257         *(mapsegs[2]+farmapylookup[new->tiley]+new->tilex) &= 0xFF;\r
258 }\r
259 \r
260 \r
261 /*\r
262 ================\r
263 =\r
264 = T_WallDie\r
265 =\r
266 ================\r
267 */\r
268 \r
269 void T_WallDie (objtype *ob)\r
270 {\r
271         extern unsigned gcolor;\r
272         unsigned tile,other,spot,x,y;\r
273 \r
274         if (++ob->temp1 == 3)\r
275                 tile = 0;\r
276         else\r
277                 if (gcolor == 0x0101)\r
278                         tile = WATEREXP-1 + ob->temp1;\r
279                 else\r
280                         tile = WALLEXP-1 + ob->temp1;\r
281         x = ob->tilex;\r
282         y = ob->tiley;\r
283 \r
284         (unsigned)actorat[x][y] = tilemap[x][y] = *(mapsegs[0]+farmapylookup[y]+x) = tile;\r
285 \r
286         if (ob->temp1 == 1)\r
287         {\r
288         //\r
289         // blow up nearby walls\r
290         //\r
291                 spot = (*(mapsegs[2]+farmapylookup[y]+(x-1))) >> 8;\r
292                 if (spot == EXP_WALL_CODE)\r
293                         ExplodeWall (x-1,y);\r
294                 spot = (*(mapsegs[2]+farmapylookup[y]+(x+1))) >> 8;\r
295                 if (spot == EXP_WALL_CODE)\r
296                         ExplodeWall (x+1,y);\r
297                 spot = (*(mapsegs[2]+farmapylookup[y-1]+x)) >> 8;\r
298                 if (spot == EXP_WALL_CODE)\r
299                         ExplodeWall (x,y-1);\r
300                 spot = (*(mapsegs[2]+farmapylookup[y+1]+x)) >> 8;\r
301                 if (spot == EXP_WALL_CODE)\r
302                         ExplodeWall (x,y+1);\r
303         }\r
304 }\r
305 /*\r
306 =============================================================================\r
307 \r
308                                                                 OBJ_WARP GATE\r
309 \r
310 =============================================================================\r
311 */\r
312 \r
313 void T_Gate (objtype *ob);\r
314 void T_Gate_Wait (objtype *ob);\r
315 \r
316 extern statetype s_portal_wait;\r
317 statetype s_portal_wait = {0, 10, &T_Gate_Wait, &s_portal_wait};\r
318 \r
319 statetype s_portal1 = {PORTAL1PIC, 6, &T_Gate, &s_portal2};\r
320 statetype s_portal2 = {PORTAL2PIC, 6, &T_Gate, &s_portal3};\r
321 statetype s_portal3 = {PORTAL3PIC, 6, &T_Gate, &s_portal4};\r
322 statetype s_portal4 = {PORTAL4PIC, 6, &T_Gate, &s_portal5};\r
323 statetype s_portal5 = {PORTAL5PIC, 6, &T_Gate, &s_portal6};\r
324 statetype s_portal6 = {PORTAL6PIC, 6, &T_Gate, &s_portal1};\r
325 \r
326 //---------------------------------------------------------------------------\r
327 //      SpawnWarp()\r
328 //---------------------------------------------------------------------------\r
329 void SpawnWarp (int tilex, int tiley)\r
330 {\r
331         unsigned spot;\r
332         objtype *ob;\r
333 \r
334         spot = (*(mapsegs[2]+farmapylookup[tiley]+tilex+1)) >> 8;\r
335 \r
336         if (spot)\r
337         {\r
338                 SpawnNewObj (tilex, tiley, &s_portal_wait, TILEGLOBAL/3);\r
339                 new->temp1 = spot*70;\r
340         }\r
341         else\r
342                 SpawnNewObj (tilex, tiley, &s_portal1, TILEGLOBAL/3);\r
343 \r
344         new->obclass = gateobj;\r
345 }\r
346 \r
347 /*\r
348 ===============\r
349 =\r
350 = T_Gate_Wait\r
351 =\r
352 ===============\r
353 */\r
354 \r
355 void T_Gate_Wait (objtype *ob)\r
356 {\r
357         if ((ob->temp1 -= tics) <= 0)\r
358         {\r
359                 if ((ob->tilex == player->tilex) && (ob->tiley == player->tiley))\r
360                         return;\r
361                 if (CheckHandAttack(ob))\r
362                         return;\r
363 \r
364                 SD_PlaySound(PORTALSND);\r
365                 ob->state = &s_portal1;\r
366                 ob->ticcount = ob->state->tictime;\r
367 \r
368         }\r
369 \r
370 }\r
371 \r
372 \r
373 \r
374 /*\r
375 ===============\r
376 =\r
377 = T_Gate\r
378 =\r
379 ===============\r
380 */\r
381 \r
382 void T_Gate (objtype *ob)\r
383 {\r
384         objtype *check;\r
385         unsigned        temp,spot;\r
386 \r
387         if (CheckHandAttack (ob) && !playstate)\r
388         {\r
389                 //\r
390                 // teleport out of level\r
391                 //\r
392                 playstate = ex_warped;\r
393                 spot = (*(mapsegs[2]+farmapylookup[ob->tiley+1]+ob->tilex)) >> 8;\r
394                 gamestate.mapon=spot;\r
395                 SD_PlaySound(WARPUPSND);\r
396         }\r
397 }\r
398 \r
399 \r
400 \r
401 /*\r
402 =============================================================================\r
403 \r
404                                                                                         AQUAMAN\r
405 \r
406 =============================================================================\r
407 */\r
408 \r
409 void T_AquaMan(objtype *ob);\r
410 \r
411 statetype s_aqua_under1 = {EYESTALKUNDER1PIC, 25, &T_AquaMan, &s_aqua_under2};\r
412 statetype s_aqua_under2 = {EYESTALKUNDER2PIC, 20, &T_AquaMan, &s_aqua_under3};\r
413 statetype s_aqua_under3 = {EYESTALKUNDER3PIC, 20, &T_AquaMan, &s_aqua_under2};\r
414 \r
415 statetype s_aqua_left = {EYESTALKUNDER4PIC, 40, NULL, &s_aqua_under3};\r
416 statetype s_aqua_right = {EYESTALKUNDER5PIC, 40, NULL, &s_aqua_under3};\r
417 \r
418 statetype s_aqua_rise1 = {EYESTALKRISE1PIC, 20, NULL, &s_aqua_rise2};\r
419 statetype s_aqua_rise2 = {EYESTALKRISE2PIC, 15, NULL, &s_aqua_walk1};\r
420 \r
421 statetype s_aqua_sink1 = {EYESTALKRISE2PIC, 15, NULL, &s_aqua_sink2};\r
422 statetype s_aqua_sink2 = {EYESTALKRISE1PIC, 20, NULL, &s_aqua_under1};\r
423 \r
424 statetype s_aqua_walk1 = {EYESTALKWALK1PIC, 12, &T_AquaMan, &s_aqua_walk2};\r
425 statetype s_aqua_walk2 = {EYESTALKWALK2PIC, 12, &T_AquaMan, &s_aqua_walk1};\r
426 \r
427 statetype s_aqua_attack1 = {EYESTALKATTACKPIC, 10, NULL, &s_aqua_attack2};\r
428 statetype s_aqua_attack2 = {EYESTALKWALK1PIC, 10, &T_DoDamage, &s_aqua_walk1};\r
429 \r
430 statetype s_aqua_die1 = {EYESTALKDEATH1PIC, 8, NULL, &s_aqua_die2};\r
431 statetype s_aqua_die2 = {EYESTALKDEATH2PIC, 8, NULL, &s_aqua_die3};\r
432 statetype s_aqua_die3 = {EYESTALKDEATH2PIC, -1, &T_AlternateStates, &s_aqua_die1};\r
433 statetype s_aqua_die4 = {EYESTALKDEATH2PIC, 30, NULL, &s_aqua_die5};\r
434 statetype s_aqua_die5 = {EYESTALKDEATH3PIC, 40, NULL, &s_aqua_die6};\r
435 statetype s_aqua_die6 = {EYESTALKDEATH4PIC, 30, &ExplosionSnd, &s_aqua_die7};\r
436 statetype s_aqua_die7 = {EYESTALKDEATH5PIC, 20, NULL, NULL};\r
437 \r
438 typedef enum {wt_UNDER, wt_WALK} AquaManTypes;\r
439 \r
440 #define AQ_TIMEREMAIN   (ob->temp1)\r
441 #define AQ_STAGE                        (ob->temp2)\r
442 \r
443 /*\r
444 ===============\r
445 =\r
446 = SpawnAquaMan\r
447 =\r
448 ===============\r
449 */\r
450 void SpawnAquaMan(int tilex, int tiley)\r
451 {\r
452         objtype *ob;\r
453         SpawnNewObj(tilex,tiley,&s_aqua_under1,PIXRADIUS*32);\r
454         ob = new;\r
455 \r
456         AQ_STAGE = wt_UNDER;\r
457         AQ_TIMEREMAIN = 60*4+random(60*3);\r
458 \r
459         new->obclass = aquamanobj;\r
460         new->speed = 1000;\r
461         new->flags &= ~of_shootable;\r
462         new->hitpoints = EasyHitPoints(15);\r
463 }\r
464 \r
465 void ExplosionSnd(objtype *ob)\r
466 {\r
467         if (ob->temp1 != SOUNDPLAYED)\r
468         {\r
469                 SD_PlaySound(BODY_EXPLODESND);\r
470                 ob->temp1 = SOUNDPLAYED;\r
471 \r
472         }\r
473 }\r
474 \r
475 \r
476 /*\r
477 ===============\r
478 =\r
479 = T_AquaMan\r
480 =\r
481 ===============\r
482 */\r
483 \r
484 void T_AquaMan(objtype *ob)\r
485 {\r
486         switch (AQ_STAGE)\r
487         {\r
488                 case wt_UNDER:\r
489                         ob->flags &= ~of_shootable;\r
490                         if (Chase(ob,true))\r
491                         {\r
492                                 // RISE & GOTO WALK STAGE\r
493                                 //\r
494 \r
495                                 AQ_STAGE = wt_WALK;\r
496                                 AQ_TIMEREMAIN = 60*5+random(60*5);\r
497                                         ob->state = &s_aqua_rise1;\r
498                                 ob->speed = 2200;\r
499                                 ob->ticcount = ob->state->tictime;\r
500                         }\r
501                         else\r
502                         {\r
503                                 // DEC COUNTER - And check for WALK\r
504                                 //\r
505                                 if ((AQ_TIMEREMAIN-=realtics) < 0)\r
506                                 {\r
507                                         // RISE & GOTO WALK STAGE\r
508                                         //\r
509 \r
510                                         if (CheckHandAttack(ob))\r
511                                                 break;\r
512 \r
513                                         AQ_STAGE = wt_WALK;\r
514                                         AQ_TIMEREMAIN = 60+random(60*2);\r
515                                                 ob->state = &s_aqua_rise1;\r
516                                         ob->speed = 2200;\r
517                                         ob->ticcount = ob->state->tictime;\r
518                                 }\r
519                                 else\r
520                                 if (random(1000)<5)\r
521                                 {\r
522                                         // RANDOM PEEK UP OUT OF WATER\r
523                                         //\r
524                                                 if (random(2) == 0)\r
525                                                         ob->state = &s_aqua_left;\r
526                                                 else\r
527                                                         ob->state = &s_aqua_right;\r
528                                         ob->ticcount = ob->state->tictime;\r
529                                 }\r
530                         }\r
531                         break;\r
532 \r
533 \r
534                 case wt_WALK:\r
535                         ob->flags |= of_shootable;\r
536                         if (Chase(ob,true) || (random(1000)<RANDOM_ATTACK))\r
537                         {\r
538                                         ob->state = &s_aqua_attack1;\r
539                                 ob->ticcount = ob->state->tictime;\r
540                         }\r
541                         else\r
542                         {\r
543                                 // DEC COUNTER - And check for SINK\r
544                                 //\r
545                                 if ((AQ_TIMEREMAIN-=realtics) < 0)\r
546                                 {\r
547                                         // SINK & GOTO BUBBLE STAGE\r
548                                         //\r
549 \r
550                                         AQ_STAGE = wt_UNDER;\r
551                                         AQ_TIMEREMAIN = 60*4+random(60*3);\r
552                                                 ob->state = &s_aqua_sink1;\r
553                                         ob->speed = 1200;\r
554                                         ob->ticcount = ob->state->tictime;\r
555                                         ob->flags &= ~of_shootable;\r
556                                 }\r
557 \r
558                         }\r
559                         break;\r
560         }\r
561 }\r
562 \r
563 \r
564 \r
565 \r
566 /*\r
567 =============================================================================\r
568 \r
569                                                                                         WIZARD\r
570 \r
571 =============================================================================\r
572 */\r
573 \r
574 void T_Wizard(objtype *ob);\r
575 void T_WizardShoot(objtype *ob);\r
576 \r
577 statetype s_wizard_walk1 = {WIZARDWALK1PIC, 20, &T_Wizard, &s_wizard_walk2};\r
578 statetype s_wizard_walk2 = {WIZARDWALK2PIC, 20, &T_Wizard, &s_wizard_walk3};\r
579 statetype s_wizard_walk3 = {WIZARDWALK3PIC, 20, &T_Wizard, &s_wizard_walk4};\r
580 statetype s_wizard_walk4 = {WIZARDWALK4PIC, 20, &T_Wizard, &s_wizard_walk1};\r
581 \r
582 statetype s_wizard_attack1 = {WIZARDATTACK1PIC, 20, NULL, &s_wizard_attack2};\r
583 statetype s_wizard_attack2 = {WIZARDATTACK2PIC, 20, &T_DoDamage, &s_wizard_walk1};\r
584 \r
585 statetype s_wizard_ouch = {WIZARDOUCHPIC, 15, NULL, &s_wizard_walk1};\r
586 \r
587 statetype s_wizard_die1 = {WIZARDDEATH1PIC, 45, &SmallSound, &s_wizard_die2};\r
588 statetype s_wizard_die2 = {WIZARDDEATH2PIC, 30, NULL, &s_wizard_die3};\r
589 statetype s_wizard_die3 = {WIZARDDEATH3PIC, 15, NULL, &s_wizard_die4};\r
590 statetype s_wizard_die4 = {WIZARDDEATH4PIC, 15, NULL, &s_wizard_die4};\r
591 \r
592 statetype s_wizard_shoot1 = {WIZARDATTACK1PIC, 20, NULL, &s_wizard_shoot2};\r
593 statetype s_wizard_shoot2 = {WIZARDATTACK1PIC, -1, &T_WizardShoot, &s_wizard_shoot3};\r
594 statetype s_wizard_shoot3 = {WIZARDATTACK2PIC, 20, NULL, &s_wizard_walk1};\r
595 \r
596 statetype s_wizard_shot1 = {WIZARD_SHOT1PIC, 8, &T_ShootPlayer, &s_wizard_shot2};\r
597 statetype s_wizard_shot2 = {WIZARD_SHOT2PIC, 8, &T_ShootPlayer, &s_wizard_shot1};\r
598 \r
599 \r
600 /*\r
601 ===============\r
602 =\r
603 = SpawnWizard\r
604 =\r
605 ===============\r
606 */\r
607 \r
608 void SpawnWizard (int tilex, int tiley)\r
609 {\r
610         SpawnNewObj(tilex,tiley,&s_wizard_walk1,TILEGLOBAL/2);\r
611         new->obclass    = wizardobj;\r
612         new->speed              = 1536;\r
613         new->flags |= of_shootable;\r
614         new->hitpoints  = EasyHitPoints(10);\r
615 }\r
616 \r
617 \r
618 /*\r
619 ===============\r
620 =\r
621 = T_Wizard\r
622 =\r
623 ===============\r
624 */\r
625 \r
626 void T_Wizard(objtype *ob)\r
627 {\r
628         if (Chase (ob,true))// || (random(1000)<RANDOM_ATTACK))\r
629         {\r
630                 ob->state = &s_wizard_attack1;\r
631                 ob->ticcount = ob->state->tictime;\r
632                 return;\r
633         }\r
634         else\r
635                 if (AngleNearPlayer(ob) != -1)\r
636                 {\r
637                         ob->state = &s_wizard_shoot1;\r
638                         ob->ticcount = ob->state->tictime;\r
639                         return;\r
640                 }\r
641 }\r
642 \r
643 /*\r
644 ===============\r
645 =\r
646 = T_Wizard\r
647 =\r
648 ===============\r
649 */\r
650 void T_WizardShoot(objtype *ob)\r
651 {\r
652         ShootPlayer(ob, wshotobj, 10000, &s_wizard_shot1);\r
653 }\r
654 \r
655 \r
656 \r
657 /*\r
658 =============================================================================\r
659 \r
660                                                                                         RAY\r
661 \r
662 =============================================================================\r
663 */\r
664 \r
665 void T_BlobRay(objtype *ob);\r
666 void T_RayShoot (objtype *ob);\r
667 \r
668 statetype s_ray_under = {0, 20, &T_BlobRay, &s_ray_under};\r
669 \r
670 statetype s_ray_rise = {RAYRISEPIC, 30, NULL, &s_ray_fly1};\r
671 \r
672 statetype s_ray_sink = {RAYRISEPIC, 30, NULL, &s_ray_under};\r
673 \r
674 statetype s_ray_fly1 = {RAYFLY1PIC, 10, &T_BlobRay, &s_ray_fly2};\r
675 statetype s_ray_fly2 = {RAYFLY2PIC, 10, &T_BlobRay, &s_ray_fly3};\r
676 statetype s_ray_fly3 = {RAYFLY1PIC, 10, &T_BlobRay, &s_ray_fly4};\r
677 statetype s_ray_fly4 = {RAYFLY3PIC, 10, &T_BlobRay, &s_ray_fly1};\r
678 \r
679 statetype s_ray_attack1 = {RAYSHOOT1PIC, 15, NULL, &s_ray_attack2};\r
680 statetype s_ray_attack2 = {RAYSHOOT2PIC, -1, &T_RayShoot, &s_ray_attack3};\r
681 statetype s_ray_attack3 = {RAYSHOOT2PIC, 20, NULL, &s_ray_fly1};\r
682 \r
683 statetype s_ray_die1 = {RAYDEATH1PIC, 50, &SmallSound, &s_ray_die2};\r
684 statetype s_ray_die2 = {RAYDEATH2PIC, 30, NULL, NULL};\r
685 \r
686 statetype s_ray_shot1 = {RAYSHOT1PIC, 8, &T_ShootPlayer, &s_ray_shot2};\r
687 statetype s_ray_shot2 = {RAYSHOT2PIC, 8, &T_ShootPlayer, &s_ray_shot1};\r
688 \r
689 \r
690 typedef enum {br_GND, br_WALK, br_CORNER1, br_CORNER2, br_CORNER3, br_CORNER4} BlobTypes;\r
691 \r
692 #define BR_TIMEREMAIN   (ob->temp1)\r
693 #define BR_STAGE                        (ob->temp2)\r
694 #define BLOB_LEAVE              0x04\r
695 \r
696 /*\r
697 ===============\r
698 =\r
699 = SpawnRay\r
700 =\r
701 ===============\r
702 */\r
703 void SpawnRay(int tilex, int tiley)\r
704 {\r
705         objtype *ob;\r
706         SpawnNewObj(tilex, tiley, &s_ray_under, PIXRADIUS*25);\r
707         ob=new;\r
708 \r
709         BR_STAGE = br_GND;\r
710         BR_TIMEREMAIN = random(60)+random(100);\r
711 \r
712         new->obclass    = rayobj;\r
713         new->speed              = 1700;\r
714         new->flags      &= ~of_shootable;\r
715         new->hitpoints  = EasyHitPoints(15);\r
716 }\r
717 \r
718 \r
719 \r
720 /*\r
721 =============================================================================\r
722 \r
723                                                                                 BLOB\r
724 \r
725 =============================================================================\r
726 */\r
727 \r
728 \r
729 statetype s_blob_gnd1 = {BLOBGND1PIC, 13, T_BlobRay, &s_blob_gnd2};\r
730 statetype s_blob_gnd2 = {BLOBGND2PIC, 15, T_BlobRay, &s_blob_gnd1};\r
731 \r
732 statetype s_blob_rise1 = {BLOBRISE1PIC, 20, NULL, &s_blob_rise2};\r
733 statetype s_blob_rise2 = {BLOBRISE2PIC, 20, NULL, &s_blob_walk1};\r
734 \r
735 statetype s_blob_sink1 = {BLOBRISE2PIC, 20, NULL, &s_blob_sink2};\r
736 statetype s_blob_sink2 = {BLOBRISE1PIC, 20, NULL, &s_blob_gnd1};\r
737 \r
738 statetype s_blob_walk1 = {BLOBWALK1PIC, 15, T_BlobRay, &s_blob_walk2};\r
739 statetype s_blob_walk2 = {BLOBWALK2PIC, 15, T_BlobRay, &s_blob_walk3};\r
740 statetype s_blob_walk3 = {BLOBWALK3PIC, 15, T_BlobRay, &s_blob_walk1};\r
741 \r
742 statetype s_blob_ouch = {BLOBRISE2PIC, 10, T_BlobRay, &s_blob_walk1};\r
743 \r
744 statetype s_blob_die1 = {BLOBDEATH1PIC, 30, &ExplosionSnd, &s_blob_die2};\r
745 statetype s_blob_die2 = {BLOBDEATH2PIC, 30, NULL, &s_blob_die3};\r
746 statetype s_blob_die3 = {BLOBDEATH3PIC, 30, NULL, NULL};\r
747 \r
748 statetype s_blob_shot1 = {BLOB_SHOT1PIC, 8, &T_ShootPlayer, &s_blob_shot2};\r
749 statetype s_blob_shot2 = {BLOB_SHOT2PIC, 8, &T_ShootPlayer, &s_blob_shot1};\r
750 \r
751 \r
752 /*\r
753 ===============\r
754 =\r
755 = SpawnBlob\r
756 =\r
757 ===============\r
758 */\r
759 void SpawnBlob(int tilex, int tiley)\r
760 {\r
761         objtype *ob;\r
762         SpawnNewObj(tilex, tiley, &s_blob_gnd1, PIXRADIUS*14);\r
763         ob=new;\r
764 \r
765         BR_STAGE = br_GND;\r
766         BR_TIMEREMAIN = random(60)+random(100);\r
767 \r
768         new->obclass    = blobobj;\r
769         new->speed              = 1200;\r
770         new->flags      &= ~of_shootable;\r
771         new->hitpoints  = EasyHitPoints(13);\r
772 }\r
773 \r
774 \r
775 /*\r
776 ===============\r
777 =\r
778 = T_BlobRay\r
779 =\r
780 ===============\r
781 */\r
782 \r
783 void T_BlobRay(objtype *ob)\r
784 {\r
785         switch (BR_STAGE)\r
786         {\r
787                 case br_GND:\r
788                         ob->flags &= ~of_shootable;\r
789                         if (Chase(ob,true))\r
790                         {\r
791                                 // RISE & GOTO WALK STAGE\r
792                                 //\r
793 \r
794                                 BR_STAGE                        = br_WALK;\r
795                                 BR_TIMEREMAIN   = 60*8+random(60*5);\r
796                                 if (ob->obclass == blobobj)\r
797                                         ob->state       = &s_blob_rise1;\r
798                                 else\r
799                                         ob->state       = &s_ray_rise;\r
800                                 ob->speed               = 2200;\r
801                                 ob->ticcount    = ob->state->tictime;\r
802                         }\r
803                         else\r
804                         {\r
805                                 // DEC COUNTER - And check for WALK\r
806                                 //\r
807                                 if ((BR_TIMEREMAIN -= realtics) < 0)\r
808                                 {\r
809                                         // RISE & GOTO WALK STAGE\r
810                                         //\r
811 \r
812                                         BR_STAGE                        = br_WALK;\r
813                                         BR_TIMEREMAIN   = 60*8+random(60*5);\r
814                                         if (ob->obclass == blobobj)\r
815                                                 ob->state       = &s_blob_rise1;\r
816                                         else\r
817                                                 ob->state       = &s_ray_rise;\r
818                                         ob->speed               = 2200;\r
819                                         ob->ticcount    = ob->state->tictime;\r
820                                 }\r
821                         }\r
822                         break;\r
823 \r
824 \r
825                 case br_WALK:\r
826                         ob->flags |= of_shootable;\r
827 \r
828                         if (Chase(ob,true) || (CheckHandAttack(ob)))\r
829 \r
830                         {\r
831                                         ob->flags               |= BLOB_LEAVE;\r
832                                         BR_STAGE                        = random(br_CORNER3) + 2;\r
833                                         BR_TIMEREMAIN   = 60*2+(random(6)*60);\r
834                                         if (ob->obclass == blobobj)\r
835                                                 ob->state       = &s_blob_gnd1;\r
836                                         else\r
837                                                 ob->state       = &s_ray_under;\r
838                                         ob->ticcount    = ob->state->tictime;\r
839                         }\r
840                         else\r
841                                 if (AngleNearPlayer(ob) != -1)\r
842                                 {\r
843                                         if (ob->obclass == blobobj)\r
844                                         {\r
845                                                 if (!(random(15)))\r
846                                                                 ShootPlayer(ob, bshotobj, 10000, &s_blob_shot1);\r
847                                         }\r
848                                         else\r
849                                                 if (!(random(7)))\r
850                                                 {\r
851                                                         ob->state = &s_ray_attack1;\r
852                                                         ob->ticcount = ob->state->tictime;\r
853                                                 }\r
854                                 }\r
855 \r
856                         else\r
857                         {\r
858                                 // DEC COUNTER - And check for SINK\r
859                                 //\r
860                                 if ((BR_TIMEREMAIN -= realtics) < 0)\r
861                                 {\r
862                                         // SINK & GOTO GROUND STAGE\r
863                                         //\r
864 \r
865                                         BR_STAGE                        = br_GND;\r
866                                         BR_TIMEREMAIN   = 60*2+random(60*2);\r
867                                         if (ob->obclass == blobobj)\r
868                                         {\r
869                                                 ob->state               = &s_blob_sink1;\r
870                                                 ob->speed               = 1200;\r
871                                         }\r
872                                         else\r
873                                         {\r
874                                                 ob->state               = &s_ray_sink;\r
875                                                 ob->speed               = 1700;\r
876                                         }\r
877                                         ob->ticcount    = ob->state->tictime;\r
878                                         ob->flags               &= ~of_shootable;\r
879                                 }\r
880 \r
881                         }\r
882                         break;\r
883                 case br_CORNER1:\r
884                 case br_CORNER2:\r
885                 case br_CORNER3:\r
886                 case br_CORNER4:\r
887                         ob->flags &= ~of_shootable;\r
888                         if ((BR_TIMEREMAIN -= realtics) < 0)\r
889                         {\r
890                                 BR_STAGE = br_GND;\r
891                                 ob->flags &= ~BLOB_LEAVE;\r
892                         }\r
893                         else\r
894                         {\r
895                                 fixed tempx,tempy;\r
896                                 unsigned temp_tilex,temp_tiley;\r
897 \r
898                                 tempx                   = player->x;\r
899                                 tempy                   = player->y;\r
900                                 temp_tilex      = player->tilex;\r
901                                 temp_tiley      = player->tiley;\r
902 \r
903                                 player->x = ((long)other_x[BR_STAGE-2]<<TILESHIFT)+TILEGLOBAL/2;\r
904                                 player->y = ((long)other_y[BR_STAGE-2]<<TILESHIFT)+TILEGLOBAL/2;\r
905                                 player->tilex = other_x[BR_STAGE-2];\r
906                                 player->tiley = other_y[BR_STAGE-2];\r
907 \r
908 \r
909                                 Chase(ob,true);\r
910 \r
911                                 player->x               = tempx;\r
912                                 player->y               = tempy;\r
913                                 player->tilex   = temp_tilex;\r
914                                 player->tiley   = temp_tiley;\r
915                         }\r
916                         break;\r
917         }\r
918 }\r
919 \r
920 /*\r
921 ===============\r
922 =\r
923 = T_RayShoot\r
924 =\r
925 ===============\r
926 */\r
927 void T_RayShoot (objtype *ob)\r
928 {\r
929         ShootPlayer(ob, rshotobj, 10000, &s_ray_shot1);\r
930 }