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 / c3_act1.c
1 /* Catacomb 3-D 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 "C3_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 \r
33 /*\r
34 =============================================================================\r
35 \r
36                                                  GLOBAL VARIABLES\r
37 \r
38 =============================================================================\r
39 */\r
40 \r
41 \r
42 \r
43 /*\r
44 =============================================================================\r
45 \r
46                                                  LOCAL VARIABLES\r
47 \r
48 =============================================================================\r
49 */\r
50 \r
51 \r
52 dirtype dirtable[9] = {northwest,north,northeast,west,nodir,east,\r
53         southwest,south,southeast};\r
54 \r
55 \r
56 \r
57 /*\r
58 =============================================================================\r
59 \r
60                                                   BONUS ITEMS\r
61 \r
62 =============================================================================\r
63 */\r
64 \r
65 extern statetype        s_boltbonus2;\r
66 extern statetype        s_nukebonus2;\r
67 \r
68 statetype s_boltbonus = {BOLTOBJPIC,8,NULL,&s_boltbonus2};\r
69 statetype s_boltbonus2 = {BOLTOBJ2PIC,8,NULL,&s_boltbonus};\r
70 \r
71 statetype s_nukebonus = {NUKEOBJPIC,8,NULL,&s_nukebonus2};\r
72 statetype s_nukebonus2 = {NUKEOBJ2PIC,8,NULL,&s_nukebonus};\r
73 \r
74 statetype s_potionbonus = {POTIONOBJPIC,0,NULL,&s_potionbonus};\r
75 statetype s_rkeybonus = {RKEYOBJPIC,0,NULL,&s_rkeybonus};\r
76 statetype s_ykeybonus = {YKEYOBJPIC,0,NULL,&s_ykeybonus};\r
77 statetype s_gkeybonus = {GKEYOBJPIC,0,NULL,&s_gkeybonus};\r
78 statetype s_bkeybonus = {BKEYOBJPIC,0,NULL,&s_bkeybonus};\r
79 statetype s_scrollbonus = {SCROLLOBJPIC,0,NULL,&s_scrollbonus};\r
80 statetype s_chestbonus = {CHESTOBJPIC,0,NULL,&s_chestbonus};\r
81 statetype s_goalbonus = {NEMESISPIC,0,NULL,&s_goalbonus};\r
82 \r
83 /*\r
84 ===============\r
85 =\r
86 = SpawnBonus\r
87 =\r
88 ===============\r
89 */\r
90 \r
91 void SpawnBonus (int tilex, int tiley, int number)\r
92 {\r
93         statetype *state;\r
94 \r
95         if (number == B_BOLT)\r
96                 state = &s_boltbonus;\r
97         else if (number == B_NUKE)\r
98                 state = &s_nukebonus;\r
99         else if (number == B_POTION)\r
100                 state = &s_potionbonus;\r
101         else if (number == B_RKEY)\r
102                 state = &s_rkeybonus;\r
103         else if (number == B_YKEY)\r
104                 state = &s_ykeybonus;\r
105         else if (number == B_GKEY)\r
106                 state = &s_gkeybonus;\r
107         else if (number == B_BKEY)\r
108                 state = &s_bkeybonus;\r
109         else if (number >= B_SCROLL1 && number <= B_SCROLL8)\r
110                 state = &s_scrollbonus;\r
111         else if (number == B_CHEST)\r
112                 state = &s_chestbonus;\r
113         else if (number == B_GOAL)\r
114                 state = &s_goalbonus;\r
115 \r
116         SpawnNewObj (tilex,tiley,state,TILEGLOBAL/2);\r
117         new->tileobject = true;\r
118         new->temp1 = number;\r
119         new->obclass = bonusobj;\r
120         new->shootable = false;\r
121 }\r
122 \r
123 \r
124 /*\r
125 =============================================================================\r
126 \r
127                                           EXPLODING WALL\r
128 \r
129 =============================================================================\r
130 */\r
131 \r
132 \r
133 void T_WallDie (objtype *ob);\r
134 \r
135 extern  statetype s_walldie1;\r
136 extern  statetype s_walldie2;\r
137 extern  statetype s_walldie3;\r
138 extern  statetype s_walldie4;\r
139 extern  statetype s_walldie5;\r
140 extern  statetype s_walldie6;\r
141 \r
142 statetype s_walldie1 = {0,20,NULL,&s_walldie2};\r
143 statetype s_walldie2 = {0,-1,T_WallDie,&s_walldie3};\r
144 statetype s_walldie3 = {0,20,NULL,&s_walldie4};\r
145 statetype s_walldie4 = {0,-1,T_WallDie,&s_walldie5};\r
146 statetype s_walldie5 = {0,20,NULL,&s_walldie6};\r
147 statetype s_walldie6 = {0,-1,T_WallDie,NULL};\r
148 \r
149 /*\r
150 ================\r
151 =\r
152 = ExplodeWall\r
153 =\r
154 ================\r
155 */\r
156 \r
157 void ExplodeWall (int tilex, int tiley)\r
158 {\r
159         SpawnNewObj (tilex,tiley,&s_walldie1,0);\r
160         new->obclass = inertobj;\r
161         new->active = true;\r
162         (unsigned)actorat[new->tilex][new->tiley] = tilemap[new->tilex][new->tiley] =\r
163         *(mapsegs[0]+farmapylookup[new->tiley]+new->tilex) = WALLEXP;\r
164 }\r
165 \r
166 \r
167 /*\r
168 ================\r
169 =\r
170 = T_WallDie\r
171 =\r
172 ================\r
173 */\r
174 \r
175 void T_WallDie (objtype *ob)\r
176 {\r
177         unsigned tile,other;\r
178 \r
179         if (++ob->temp1 == 3)\r
180                 tile = 0;\r
181         else\r
182                 tile = WALLEXP-1 + ob->temp1;\r
183 \r
184         (unsigned)actorat[ob->tilex][ob->tiley] = tilemap[ob->tilex][ob->tiley] =\r
185         *(mapsegs[0]+farmapylookup[ob->tiley]+ob->tilex) = tile;\r
186 \r
187         if (ob->temp1 == 1)\r
188         {\r
189         //\r
190         // blow up nearby walls\r
191         //\r
192                 other = tilemap[ob->tilex-1][ob->tiley];\r
193                 if ((unsigned)(other-EXPWALLSTART)<NUMEXPWALLS)\r
194                         ExplodeWall (ob->tilex-1,ob->tiley);\r
195                 other = tilemap[ob->tilex+1][ob->tiley];\r
196                 if ((unsigned)(other-EXPWALLSTART)<NUMEXPWALLS)\r
197                         ExplodeWall (ob->tilex+1,ob->tiley);\r
198                 other = tilemap[ob->tilex][ob->tiley-1];\r
199                 if ((unsigned)(other-EXPWALLSTART)<NUMEXPWALLS)\r
200                         ExplodeWall (ob->tilex,ob->tiley-1);\r
201                 other = tilemap[ob->tilex][ob->tiley+1];\r
202                 if ((unsigned)(other-EXPWALLSTART)<NUMEXPWALLS)\r
203                         ExplodeWall (ob->tilex,ob->tiley+1);\r
204         }\r
205 }\r
206 \r
207 \r
208 /*\r
209 =============================================================================\r
210 \r
211                                                  WARP GATE\r
212 \r
213 =============================================================================\r
214 */\r
215 \r
216 void T_Gate (objtype *ob);\r
217 \r
218 extern  statetype s_gate1;\r
219 extern  statetype s_gate2;\r
220 extern  statetype s_gate3;\r
221 extern  statetype s_gate4;\r
222 \r
223 extern  statetype s_fgate1;\r
224 extern  statetype s_fgate2;\r
225 extern  statetype s_fgate3;\r
226 extern  statetype s_fgate4;\r
227 \r
228 statetype s_gate1 = {WARP1PIC,12,T_Gate,&s_gate2};\r
229 statetype s_gate2 = {WARP2PIC,12,T_Gate,&s_gate3};\r
230 statetype s_gate3 = {WARP3PIC,12,T_Gate,&s_gate4};\r
231 statetype s_gate4 = {WARP4PIC,12,T_Gate,&s_gate1};\r
232 \r
233 statetype s_fgate1 = {WARP1PIC,6,T_Gate,&s_fgate2};\r
234 statetype s_fgate2 = {WARP2PIC,6,T_Gate,&s_fgate3};\r
235 statetype s_fgate3 = {WARP3PIC,6,T_Gate,&s_fgate4};\r
236 statetype s_fgate4 = {WARP4PIC,6,T_Gate,&s_fgate1};\r
237 \r
238 /*\r
239 ===============\r
240 =\r
241 = SpawnWarp\r
242 =\r
243 ===============\r
244 */\r
245 \r
246 void SpawnWarp (int tilex, int tiley, int type)\r
247 {\r
248         if (type)\r
249                 SpawnNewObj (tilex,tiley,&s_fgate1,TILEGLOBAL/3);\r
250         else\r
251                 SpawnNewObj (tilex,tiley,&s_gate1,TILEGLOBAL/3);\r
252         new->obclass = gateobj;\r
253         new->temp1 = type;\r
254 }\r
255 \r
256 \r
257 /*\r
258 ===============\r
259 =\r
260 = T_Gate\r
261 =\r
262 ===============\r
263 */\r
264 \r
265 #define STATUSCOLOR     4\r
266 \r
267 void T_Gate (objtype *ob)\r
268 {\r
269         int     spot;\r
270         objtype *check;\r
271         unsigned        temp;\r
272 \r
273         if (CheckHandAttack (ob) && !playstate)\r
274         {\r
275         //\r
276         // warp\r
277         //\r
278                 temp = bufferofs;\r
279                 bufferofs = 0;\r
280                 VW_Bar (26,4,232,9,STATUSCOLOR);                // clear text description\r
281                 bufferofs = temp;\r
282                 IN_ClearKeysDown ();\r
283                 if (ob->temp1)\r
284                 {\r
285                 //\r
286                 // teleport inside level\r
287                 //\r
288                         for (check=player->next;check;check=check->next)\r
289                                 if (check->obclass==gateobj && check->temp1==ob->temp1 &&\r
290                                         check != ob)\r
291                                 {\r
292                                         player->x = check->x;\r
293                                         player->y = check->y;\r
294                                         Thrust (player->angle,TILEGLOBAL/2);            // move forwards\r
295                                         Thrust (player->angle,TILEGLOBAL/2);            // move forwards\r
296                                         Thrust (player->angle,TILEGLOBAL/2);            // move forwards\r
297                                         fizzlein=true;\r
298                                 }\r
299                 }\r
300                 else\r
301                 {\r
302                 //\r
303                 // teleport out of level\r
304                 //\r
305                         playstate = ex_warped;\r
306                         spot = *(mapsegs[0]+farmapylookup[ob->tiley]+ob->tilex)-NAMESTART;\r
307                         if (spot<1)\r
308                                 gamestate.mapon++;\r
309                         else\r
310                                 gamestate.mapon=spot-1;\r
311                         SD_PlaySound(WARPUPSND);\r
312                 }\r
313         }\r
314 }\r
315 \r
316 \r
317 /*\r
318 =============================================================================\r
319 \r
320                                                    TROLLS\r
321 \r
322 =============================================================================\r
323 */\r
324 \r
325 void T_Troll (objtype *ob);\r
326 \r
327 extern  statetype s_trollpause;\r
328 \r
329 extern  statetype s_troll1;\r
330 extern  statetype s_troll2;\r
331 extern  statetype s_troll3;\r
332 extern  statetype s_troll4;\r
333 \r
334 extern  statetype s_trollattack1;\r
335 extern  statetype s_trollattack2;\r
336 extern  statetype s_trollattack3;\r
337 \r
338 extern  statetype s_trollouch;\r
339 \r
340 extern  statetype s_trolldie1;\r
341 extern  statetype s_trolldie2;\r
342 extern  statetype s_trolldie3;\r
343 \r
344 \r
345 statetype s_trollpause = {TROLL1PIC,40,NULL,&s_troll2};\r
346 \r
347 statetype s_troll1 = {TROLL1PIC,13,T_Troll,&s_troll2};\r
348 statetype s_troll2 = {TROLL2PIC,13,T_Troll,&s_troll3};\r
349 statetype s_troll3 = {TROLL3PIC,13,T_Troll,&s_troll4};\r
350 statetype s_troll4 = {TROLL4PIC,13,T_Troll,&s_troll1};\r
351 \r
352 statetype s_trollattack1 = {TROLLATTACK1PIC,20,NULL,&s_trollattack2};\r
353 statetype s_trollattack2 = {TROLLATTACK2PIC,10,T_DoDamage,&s_trollattack3};\r
354 statetype s_trollattack3 = {TROLLATTACK2PIC,40,NULL,&s_trollpause};\r
355 \r
356 statetype s_trollouch = {TROLLOUCHPIC,8,NULL,&s_troll1};\r
357 \r
358 statetype s_trolldie1 = {TROLLDIE1PIC,8,NULL,&s_trolldie2};\r
359 statetype s_trolldie2 = {TROLLDIE2PIC,8,NULL,&s_trolldie3};\r
360 statetype s_trolldie3 = {TROLLDIE3PIC,0,NULL,&s_trolldie3};\r
361 \r
362 \r
363 /*\r
364 ===============\r
365 =\r
366 = SpawnTroll\r
367 =\r
368 ===============\r
369 */\r
370 \r
371 void SpawnTroll (int tilex, int tiley)\r
372 {\r
373         SpawnNewObj(tilex,tiley,&s_troll1,40*PIXRADIUS);\r
374         new->speed = 2500;\r
375         new->obclass = trollobj;\r
376         new->shootable = true;\r
377         new->hitpoints = 10;\r
378 }\r
379 \r
380 \r
381 /*\r
382 ===============\r
383 =\r
384 = T_Troll\r
385 =\r
386 ===============\r
387 */\r
388 \r
389 void T_Troll (objtype *ob)\r
390 {\r
391         if (Chase (ob,true))\r
392         {\r
393                 ob->state = &s_trollattack1;\r
394                 ob->ticcount = ob->state->tictime;\r
395                 return;\r
396         }\r
397 }\r
398 \r
399 \r
400 \r
401 /*\r
402 =============================================================================\r
403 \r
404                                                    ORCS\r
405 \r
406 =============================================================================\r
407 */\r
408 \r
409 void T_Orc (objtype *ob);\r
410 \r
411 extern  statetype s_orcpause;\r
412 \r
413 extern  statetype s_orc1;\r
414 extern  statetype s_orc2;\r
415 extern  statetype s_orc3;\r
416 extern  statetype s_orc4;\r
417 \r
418 extern  statetype s_orcattack1;\r
419 extern  statetype s_orcattack2;\r
420 extern  statetype s_orcattack3;\r
421 \r
422 extern  statetype s_orcouch;\r
423 \r
424 extern  statetype s_orcdie1;\r
425 extern  statetype s_orcdie2;\r
426 extern  statetype s_orcdie3;\r
427 \r
428 \r
429 \r
430 statetype s_orcpause = {ORC1PIC,40,NULL,&s_orc2};\r
431 \r
432 statetype s_orc1 = {ORC1PIC,20,T_Orc,&s_orc2};\r
433 statetype s_orc2 = {ORC2PIC,20,T_Orc,&s_orc3};\r
434 statetype s_orc3 = {ORC3PIC,20,T_Orc,&s_orc4};\r
435 statetype s_orc4 = {ORC4PIC,20,T_Orc,&s_orc1};\r
436 \r
437 statetype s_orcattack1 = {ORCATTACK1PIC,20,NULL,&s_orcattack2};\r
438 statetype s_orcattack2 = {ORCATTACK2PIC,10,T_DoDamage,&s_orcattack3};\r
439 statetype s_orcattack3 = {ORCATTACK2PIC,40,NULL,&s_orcpause};\r
440 \r
441 statetype s_orcouch = {ORCOUCHPIC,10,NULL,&s_orc1};\r
442 \r
443 statetype s_orcdie1 = {ORCDIE1PIC,8,NULL,&s_orcdie2};\r
444 statetype s_orcdie2 = {ORCDIE2PIC,8,NULL,&s_orcdie3};\r
445 statetype s_orcdie3 = {ORCDIE3PIC,0,NULL,&s_orcdie3};\r
446 \r
447 \r
448 /*\r
449 ===============\r
450 =\r
451 = SpawnOrc\r
452 =\r
453 ===============\r
454 */\r
455 \r
456 void SpawnOrc (int tilex, int tiley)\r
457 {\r
458         SpawnNewObj(tilex,tiley,&s_orc1,PIXRADIUS*32);\r
459         new->obclass = orcobj;\r
460         new->speed = 1536;\r
461         new->shootable = true;\r
462         new->hitpoints = 3;\r
463 }\r
464 \r
465 \r
466 /*\r
467 ===============\r
468 =\r
469 = T_Orc\r
470 =\r
471 ===============\r
472 */\r
473 \r
474 void T_Orc (objtype *ob)\r
475 {\r
476         if (Chase (ob,true))\r
477         {\r
478                 ob->state = &s_orcattack1;\r
479                 ob->ticcount = ob->state->tictime;\r
480                 return;\r
481         }\r
482 }\r
483 \r
484 \r
485 /*\r
486 =============================================================================\r
487 \r
488                                                    DEMON\r
489 \r
490 =============================================================================\r
491 */\r
492 \r
493 void T_Demon (objtype *ob);\r
494 \r
495 \r
496 extern  statetype s_demonpause;\r
497 \r
498 extern  statetype s_demon1;\r
499 extern  statetype s_demon2;\r
500 extern  statetype s_demon3;\r
501 extern  statetype s_demon4;\r
502 \r
503 extern  statetype s_demonattack1;\r
504 extern  statetype s_demonattack2;\r
505 extern  statetype s_demonattack3;\r
506 \r
507 extern  statetype s_demonouch;\r
508 \r
509 extern  statetype s_demondie1;\r
510 extern  statetype s_demondie2;\r
511 extern  statetype s_demondie3;\r
512 \r
513 \r
514 statetype s_demonpause = {DEMON1PIC,40,NULL,&s_demon2};\r
515 \r
516 statetype s_demon1 = {DEMON1PIC,20,T_Demon,&s_demon2};\r
517 statetype s_demon2 = {DEMON2PIC,20,T_Demon,&s_demon3};\r
518 statetype s_demon3 = {DEMON3PIC,20,T_Demon,&s_demon4};\r
519 statetype s_demon4 = {DEMON4PIC,20,T_Demon,&s_demon1};\r
520 \r
521 statetype s_demonattack1 = {DEMONATTACK1PIC,20,NULL,&s_demonattack2};\r
522 statetype s_demonattack2 = {DEMONATTACK2PIC,20,T_DoDamage,&s_demonattack3};\r
523 statetype s_demonattack3 = {DEMONATTACK3PIC,30,NULL,&s_demonpause};\r
524 \r
525 statetype s_demonouch = {DEMONOUCHPIC,10,NULL,&s_demon1};\r
526 \r
527 statetype s_demondie1 = {DEMONDIE1PIC,20,NULL,&s_demondie2};\r
528 statetype s_demondie2 = {DEMONDIE2PIC,20,NULL,&s_demondie3};\r
529 statetype s_demondie3 = {DEMONDIE3PIC,0,NULL,&s_demondie3};\r
530 \r
531 \r
532 \r
533 /*\r
534 ===============\r
535 =\r
536 = SpawnDemon\r
537 =\r
538 ===============\r
539 */\r
540 \r
541 void SpawnDemon (int tilex, int tiley)\r
542 {\r
543         SpawnNewObj(tilex,tiley,&s_demon1,TILEGLOBAL/2);\r
544         new->obclass = demonobj;\r
545         new->speed = 2048;\r
546         new->shootable = true;\r
547         new->hitpoints = 50;\r
548 }\r
549 \r
550 \r
551 /*\r
552 ===============\r
553 =\r
554 = T_Demon\r
555 =\r
556 ===============\r
557 */\r
558 \r
559 void T_Demon (objtype *ob)\r
560 {\r
561         if (Chase (ob,true))\r
562         {\r
563                 ob->state = &s_demonattack1;\r
564                 ob->ticcount = ob->state->tictime;\r
565                 return;\r
566         }\r
567 }\r
568 \r
569 /*\r
570 =============================================================================\r
571 \r
572                                                         MSHOTS\r
573 \r
574 temp1 = dir\r
575 \r
576 =============================================================================\r
577 */\r
578 \r
579 #define MSHOTDAMAGE     2\r
580 #define MSHOTSPEED      10000\r
581 \r
582 void T_Mshot (objtype *ob);\r
583 \r
584 \r
585 extern  statetype s_mshot1;\r
586 extern  statetype s_mshot2;\r
587 \r
588 statetype s_mshot1 = {PSHOT1PIC,8,&T_Mshot,&s_mshot2};\r
589 statetype s_mshot2 = {PSHOT2PIC,8,&T_Mshot,&s_mshot1};\r
590 \r
591 \r
592 /*\r
593 ===============\r
594 =\r
595 = T_Mshot\r
596 =\r
597 ===============\r
598 */\r
599 \r
600 void T_Mshot (objtype *ob)\r
601 {\r
602         objtype *check;\r
603         long    xmove,ymove,speed;\r
604 \r
605         xmove = ymove = 0;\r
606 \r
607         switch (ob->dir)\r
608         {\r
609         case north:\r
610                 ymove = -ob->speed*tics;\r
611                 break;\r
612         case east:\r
613                 xmove = ob->speed*tics;\r
614                 break;\r
615         case south:\r
616                 ymove = ob->speed*tics;\r
617                 break;\r
618         case west:\r
619                 xmove = -ob->speed*tics;\r
620                 break;\r
621         }\r
622 \r
623         ob->x+=xmove;\r
624         ob->y+=ymove;\r
625 \r
626         CalcBounds (ob);\r
627 \r
628         ob->tilex = ob->x>>TILESHIFT;\r
629         ob->tiley = ob->y>>TILESHIFT;\r
630 \r
631         if (tilemap[ob->tilex][ob->tiley])\r
632         {\r
633                 SD_PlaySound (SHOOTWALLSND);\r
634                 ob->state = NULL;\r
635                 return;\r
636         }\r
637 \r
638 //\r
639 // check final position for monsters hit\r
640 //\r
641         if ( ob->xl <= player->xh\r
642         && ob->xh >= player->xl\r
643         && ob->yl <= player->yh\r
644         && ob->yh >= player->yl)\r
645         {\r
646                 TakeDamage (MSHOTDAMAGE*2);\r
647                 ob->state = NULL;\r
648                 return;\r
649         }\r
650 \r
651         for (check = player->next; check; check=check->next)\r
652                 if (ob->shootable && ob->obclass != mageobj\r
653                 && ob->xl <= check->xh\r
654                 && ob->xh >= check->xl\r
655                 && ob->yl <= check->yh\r
656                 && ob->yh >= check->yl)\r
657                 {\r
658                         ShootActor (check,MSHOTDAMAGE);\r
659                         ob->state = NULL;\r
660                         return;\r
661                 }\r
662 }\r
663 \r
664 \r
665 \r
666 \r
667 /*\r
668 =============================================================================\r
669 \r
670                                                         MAGE\r
671 \r
672 =============================================================================\r
673 */\r
674 \r
675 \r
676 void T_Mage (objtype *ob);\r
677 void T_MageShoot (objtype *ob);\r
678 \r
679 extern  statetype s_magepause;\r
680 \r
681 extern  statetype s_mage1;\r
682 extern  statetype s_mage2;\r
683 \r
684 extern  statetype s_mageattack1;\r
685 extern  statetype s_mageattack2;\r
686 extern  statetype s_mageattack3;\r
687 \r
688 extern  statetype s_mageouch;\r
689 \r
690 extern  statetype s_magedie1;\r
691 extern  statetype s_magedie2;\r
692 \r
693 \r
694 statetype s_magepause = {MAGE1PIC,100,NULL,&s_mage2};\r
695 \r
696 statetype s_mage1 = {MAGE1PIC,20,T_Mage,&s_mage2};\r
697 statetype s_mage2 = {MAGE2PIC,20,T_Mage,&s_mage1};\r
698 \r
699 statetype s_mageattack1 = {MAGEATTACKPIC,20,NULL,&s_mageattack2};\r
700 statetype s_mageattack2 = {MAGEATTACKPIC,-1,T_MageShoot,&s_mageattack3};\r
701 statetype s_mageattack3 = {MAGEATTACKPIC,30,NULL,&s_magepause};\r
702 \r
703 statetype s_mageouch = {MAGEOUCHPIC,10,NULL,&s_mage1};\r
704 \r
705 statetype s_magedie1 = {MAGEDIE1PIC,20,NULL,&s_magedie2};\r
706 statetype s_magedie2 = {MAGEDIE2PIC,0,NULL,&s_magedie2};\r
707 \r
708 \r
709 /*\r
710 ===============\r
711 =\r
712 = SpawnMage\r
713 =\r
714 ===============\r
715 */\r
716 \r
717 void SpawnMage (int tilex, int tiley)\r
718 {\r
719         SpawnNewObj(tilex,tiley,&s_mage1,TILEGLOBAL/2);\r
720         new->obclass = mageobj;\r
721         new->speed = 2048;\r
722         new->shootable = true;\r
723         new->hitpoints = 5;\r
724 }\r
725 \r
726 \r
727 /*\r
728 ===============\r
729 =\r
730 = T_Mage\r
731 =\r
732 ===============\r
733 */\r
734 \r
735 void T_Mage (objtype *ob)\r
736 {\r
737         Chase (ob,false);\r
738 //\r
739 // check for line up with player\r
740 //\r
741 \r
742         if (ob->x-PIXRADIUS*14 < player->xh\r
743         && ob->x+PIXRADIUS > player->xl)\r
744         {\r
745                 ob->temp1 = 1;\r
746                 ob->state = &s_mageattack1;\r
747         }\r
748         else if (ob->y-PIXRADIUS*14 < player->yh\r
749         && ob->y+PIXRADIUS > player->yl)\r
750         {\r
751                 ob->temp1 = 0;\r
752                 ob->state = &s_mageattack1;\r
753         }\r
754 }\r
755 \r
756 \r
757 /*\r
758 ===============\r
759 =\r
760 = T_MageShoot\r
761 =\r
762 ===============\r
763 */\r
764 \r
765 void T_MageShoot (objtype *ob)\r
766 {\r
767         SpawnNewObjFrac (ob->x,ob->y,&s_mshot1,PIXRADIUS*14);\r
768         new->obclass = mshotobj;\r
769         new->speed = MSHOTSPEED;\r
770         if (ob->temp1)\r
771         {\r
772                 if (ob->tiley < player->tiley)\r
773                         new->dir = south;\r
774                 else\r
775                         new->dir = north;\r
776         }\r
777         else\r
778         {\r
779                 if (ob->tilex < player->tilex)\r
780                         new->dir = east;\r
781                 else\r
782                         new->dir = west;\r
783         }\r
784 }\r
785 \r
786 \r
787 /*\r
788 =============================================================================\r
789 \r
790                                                         nemesis\r
791 \r
792 =============================================================================\r
793 */\r
794 \r
795 \r
796 void T_Nemesis (objtype *ob);\r
797 void T_NemesisShoot (objtype *ob);\r
798 \r
799 extern  statetype s_grelpause;\r
800 \r
801 extern  statetype s_grel1;\r
802 extern  statetype s_grel2;\r
803 \r
804 extern  statetype s_grelattack1;\r
805 extern  statetype s_grelattack2;\r
806 extern  statetype s_grelattack3;\r
807 \r
808 extern  statetype s_grelouch;\r
809 \r
810 extern  statetype s_greldie1;\r
811 extern  statetype s_greldie2;\r
812 extern  statetype s_greldie3;\r
813 extern  statetype s_greldie4;\r
814 extern  statetype s_greldie5;\r
815 extern  statetype s_greldie6;\r
816 \r
817 \r
818 statetype s_grelpause = {GREL1PIC,50,NULL,&s_grel2};\r
819 \r
820 statetype s_grel1 = {GREL1PIC,20,T_Nemesis,&s_grel2};\r
821 statetype s_grel2 = {GREL2PIC,20,T_Nemesis,&s_grel1};\r
822 \r
823 statetype s_grelattack1 = {GRELATTACKPIC,20,NULL,&s_grelattack2};\r
824 statetype s_grelattack2 = {GRELATTACKPIC,-1,T_NemesisShoot,&s_grelattack3};\r
825 statetype s_grelattack3 = {GRELATTACKPIC,30,NULL,&s_grelpause};\r
826 \r
827 statetype s_grelouch = {GRELHITPIC,6,NULL,&s_grel1};\r
828 \r
829 statetype s_greldie1 = {GRELDIE1PIC,20,NULL,&s_greldie2};\r
830 statetype s_greldie2 = {GRELDIE2PIC,20,NULL,&s_greldie3};\r
831 statetype s_greldie3 = {GRELDIE3PIC,20,NULL,&s_greldie4};\r
832 statetype s_greldie4 = {GRELDIE4PIC,20,NULL,&s_greldie5};\r
833 statetype s_greldie5 = {GRELDIE5PIC,20,NULL,&s_greldie6};\r
834 statetype s_greldie6 = {GRELDIE6PIC,0,NULL,&s_greldie6};\r
835 \r
836 \r
837 /*\r
838 ===============\r
839 =\r
840 = SpawnNemesis\r
841 =\r
842 ===============\r
843 */\r
844 \r
845 void SpawnNemesis (int tilex, int tiley)\r
846 {\r
847         SpawnNewObj(tilex,tiley,&s_grel1,PIXRADIUS*56);\r
848         new->obclass = grelmobj;\r
849         new->speed = 2048;\r
850         new->shootable = true;\r
851         new->hitpoints = 100;\r
852 }\r
853 \r
854 \r
855 /*\r
856 ===============\r
857 =\r
858 = T_Nemesis\r
859 =\r
860 ===============\r
861 */\r
862 \r
863 void T_Nemesis (objtype *ob)\r
864 {\r
865         Chase (ob,false);\r
866 //\r
867 // check for line up with player\r
868 //\r
869         if (ob->tilex == player->tilex)\r
870         {\r
871                 ob->temp1 = 1;\r
872                 ob->state = &s_grelattack1;\r
873         }\r
874         else if (ob->tiley == player->tiley)\r
875         {\r
876                 ob->temp1 = 0;\r
877                 ob->state = &s_grelattack1;\r
878         }\r
879 }\r
880 \r
881 \r
882 /*\r
883 ===============\r
884 =\r
885 = T_NemesisShoot\r
886 =\r
887 ===============\r
888 */\r
889 \r
890 void T_NemesisShoot (objtype *ob)\r
891 {\r
892         SpawnNewObjFrac (ob->x,ob->y,&s_mshot1,PIXRADIUS*14);\r
893         new->obclass = mshotobj;\r
894         new->speed = MSHOTSPEED;\r
895         if (ob->temp1)\r
896         {\r
897                 if (ob->tiley < player->tiley)\r
898                         new->dir = south;\r
899                 else\r
900                         new->dir = north;\r
901         }\r
902         else\r
903         {\r
904                 if (ob->tilex < player->tilex)\r
905                         new->dir = east;\r
906                 else\r
907                         new->dir = west;\r
908         }\r
909 }\r
910 \r
911 \r
912 /*\r
913 =============================================================================\r
914 \r
915                                                    BAT\r
916 \r
917 =============================================================================\r
918 */\r
919 \r
920 void T_Bat (objtype *ob);\r
921 void T_BatPast (objtype *ob);\r
922 \r
923 extern  statetype s_bat1;\r
924 extern  statetype s_bat2;\r
925 extern  statetype s_bat3;\r
926 extern  statetype s_bat4;\r
927 \r
928 extern  statetype s_batdie1;\r
929 extern  statetype s_batdie2;\r
930 \r
931 \r
932 statetype s_bat1 = {BAT1PIC,6,T_Bat,&s_bat2};\r
933 statetype s_bat2 = {BAT2PIC,6,T_Bat,&s_bat3};\r
934 statetype s_bat3 = {BAT3PIC,6,T_Bat,&s_bat4};\r
935 statetype s_bat4 = {BAT4PIC,6,T_Bat,&s_bat1};\r
936 \r
937 statetype s_batpast = {BAT4PIC,80,T_BatPast,&s_bat1};\r
938 \r
939 statetype s_batdie1 = {BATDIE1PIC,8,NULL,&s_batdie2};\r
940 statetype s_batdie2 = {BATDIE2PIC,8,NULL,NULL};\r
941 \r
942 \r
943 /*\r
944 ===============\r
945 =\r
946 = SpawnBat\r
947 =\r
948 ===============\r
949 */\r
950 \r
951 void SpawnBat (int tilex, int tiley)\r
952 {\r
953         SpawnNewObj(tilex,tiley,&s_bat1,PIXRADIUS*24);\r
954         new->obclass =batobj;\r
955         new->shootable = true;\r
956 \r
957         new->hitpoints = 1;\r
958         new->speed = 2000;\r
959 }\r
960 \r
961 \r
962 /*\r
963 ==================================\r
964 =\r
965 = BatChaseThink\r
966 =\r
967 ==================================\r
968 */\r
969 \r
970 void BatChaseThink (objtype *obj)\r
971 {\r
972         int deltax,deltay;\r
973 \r
974         deltax=player->tilex - obj->tilex;\r
975         deltay=player->tiley - obj->tiley;\r
976 \r
977         if (deltax>0)\r
978                 deltax = 2;\r
979         else if (deltax<0)\r
980                 deltax = 0;\r
981         else deltax = 1;\r
982 \r
983         if (deltay>0)\r
984                 deltay = 2;\r
985         else if (deltay<0)\r
986                 deltay = 0;\r
987         else deltay = 1;\r
988 \r
989         obj->dir = dirtable[deltay*3+deltax];\r
990         if (Walk(obj))\r
991                 return;\r
992 \r
993         obj->dir = dirtable[3+deltax];\r
994         if (Walk(obj))\r
995                 return;\r
996 \r
997         obj->dir = dirtable[deltay*3+1];\r
998         if (Walk(obj))\r
999                 return;\r
1000 \r
1001         obj->dir = nodir;\r
1002 }\r
1003 \r
1004 \r
1005 void BatRunThink (objtype *obj)\r
1006 {\r
1007         int deltax,deltay;\r
1008 \r
1009         deltax=player->tilex - obj->tilex;\r
1010         deltay=player->tiley - obj->tiley;\r
1011 \r
1012         if (deltax>=0)\r
1013                 deltax = 0;\r
1014         else\r
1015                 deltax = 2;\r
1016 \r
1017         if (deltay>=0)\r
1018                 deltay = 0;\r
1019         else\r
1020                 deltay = 2;\r
1021 \r
1022         obj->dir = dirtable[deltay*3+deltax];\r
1023         if (Walk(obj))\r
1024                 return;\r
1025 \r
1026         obj->dir = dirtable[3+deltax];\r
1027         if (Walk(obj))\r
1028                 return;\r
1029 \r
1030         obj->dir = dirtable[deltay*3+1];\r
1031         Walk(obj);\r
1032 }\r
1033 \r
1034 \r
1035 \r
1036 /*\r
1037 ===============\r
1038 =\r
1039 = T_Bat\r
1040 =\r
1041 ===============\r
1042 */\r
1043 \r
1044 void T_Bat (objtype *ob)\r
1045 {\r
1046         long move;\r
1047         long deltax,deltay,size;\r
1048 \r
1049         move = ob->speed*tics;\r
1050         size = (long)ob->size + player->size + move;\r
1051 \r
1052 \r
1053         do\r
1054         {\r
1055                 deltax = ob->x - player->x;\r
1056                 deltay = ob->y - player->y;\r
1057 \r
1058                 if (deltax <= size && deltax >= -size\r
1059                 && deltay <= size && deltay >= -size && !ob->temp1)\r
1060                 {\r
1061                         TakeDamage (4);\r
1062                         ob->temp1 = 2;\r
1063                 }\r
1064 \r
1065                 if (move < ob->distance)\r
1066                 {\r
1067                         MoveObj (ob,move);\r
1068                         break;\r
1069                 }\r
1070 \r
1071                 actorat[ob->tilex][ob->tiley] = 0;      // pick up marker from goal\r
1072                 if (ob->dir == nodir)\r
1073                         ob->dir = north;\r
1074 \r
1075                 ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
1076                 ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
1077                 move -= ob->distance;\r
1078 \r
1079                 if (ob->temp1)\r
1080                 {\r
1081                         Walk (ob);                              // go straight\r
1082                         if (!--ob->temp1)\r
1083                         {\r
1084                                 ob->state = &s_batpast;\r
1085                                 ob->ticcount = ob->state->tictime;\r
1086                         }\r
1087                 }\r
1088                 else\r
1089                         BatChaseThink (ob);             // head towards player\r
1090 \r
1091                 actorat[ob->tilex][ob->tiley] = ob;     // set down a new goal marker\r
1092         } while (0);    // just once\r
1093         CalcBounds (ob);\r
1094 }\r
1095 \r
1096 \r
1097 /*\r
1098 ===============\r
1099 =\r
1100 = T_BatPast\r
1101 =\r
1102 ===============\r
1103 */\r
1104 \r
1105 void T_BatPast (objtype *ob)\r
1106 {\r
1107         long move;\r
1108         long deltax,deltay,size;\r
1109 \r
1110         move = ob->speed*tics;\r
1111 \r
1112         do\r
1113         {\r
1114                 if (move < ob->distance)\r
1115                 {\r
1116                         MoveObj (ob,move);\r
1117                         break;\r
1118                 }\r
1119                 actorat[ob->tilex][ob->tiley] = 0;      // pick up marker from goal\r
1120 \r
1121                 ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
1122                 ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
1123                 move -= ob->distance;\r
1124 \r
1125                 BatRunThink (ob);\r
1126 \r
1127                 actorat[ob->tilex][ob->tiley] = ob;     // set down a new goal marker\r
1128         } while (0);    //(move)\r
1129         CalcBounds (ob);\r
1130 }\r
1131 \r
1132 \r
1133 \r
1134 /*\r
1135 =============================================================================\r
1136 \r
1137                                                    BOUNCE\r
1138 \r
1139 temp2 = set when hit player, reset when hit wall\r
1140 \r
1141 =============================================================================\r
1142 */\r
1143 \r
1144 #define SPDBOUNCE       4096\r
1145 #define DMGBOUNCE       10\r
1146 \r
1147 void T_Bounce (objtype *ob);\r
1148 \r
1149 extern  statetype s_bounce1;\r
1150 extern  statetype s_bounce2;\r
1151 \r
1152 \r
1153 statetype s_bounce1 = {BIGPSHOT1PIC,8,T_Bounce,&s_bounce2};\r
1154 statetype s_bounce2 = {BIGPSHOT2PIC,8,T_Bounce,&s_bounce1};\r
1155 \r
1156 /*\r
1157 ===============\r
1158 =\r
1159 = SpawnBounce\r
1160 =\r
1161 ===============\r
1162 */\r
1163 \r
1164 void SpawnBounce (int tilex, int tiley, boolean towest)\r
1165 {\r
1166         SpawnNewObj(tilex,tiley,&s_bounce1,24*PIXRADIUS);\r
1167         new->obclass = bounceobj;\r
1168         if (towest)\r
1169                 new->dir = west;\r
1170         else\r
1171                 new->dir = north;\r
1172 }\r
1173 \r
1174 \r
1175 /*\r
1176 ===============\r
1177 =\r
1178 = T_Bounce\r
1179 =\r
1180 ===============\r
1181 */\r
1182 \r
1183 void T_Bounce (objtype *ob)\r
1184 {\r
1185         long move;\r
1186         long deltax,deltay,size;\r
1187 \r
1188         move = SPDBOUNCE*tics;\r
1189         size = (long)ob->size + player->size + move;\r
1190 \r
1191         while (move)\r
1192         {\r
1193                 deltax = ob->x - player->x;\r
1194                 deltay = ob->y - player->y;\r
1195 \r
1196                 if (deltax <= size && deltax >= -size\r
1197                 && deltay <= size && deltay >= -size && !ob->temp2)\r
1198                 {\r
1199                         ob->temp2 = 1;\r
1200                         TakeDamage (DMGBOUNCE);\r
1201                 }\r
1202 \r
1203                 if (move < ob->distance)\r
1204                 {\r
1205                         MoveObj (ob,move);\r
1206                         break;\r
1207                 }\r
1208                 actorat[ob->tilex][ob->tiley] = 0;      // pick up marker from goal\r
1209 \r
1210                 ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
1211                 ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
1212                 move -= ob->distance;\r
1213 \r
1214                 //\r
1215                 // bounce if hit wall\r
1216                 //\r
1217                 switch (ob->dir)\r
1218                 {\r
1219                 case north:\r
1220                         if (tilemap[ob->tilex][--ob->tiley])\r
1221                         {\r
1222                                 ob->dir = south;\r
1223                                 ob->tiley+=2;\r
1224                                 ob->temp2 = 0;\r
1225                         }\r
1226                         break;\r
1227                 case east:\r
1228                         if (tilemap[++ob->tilex][ob->tiley])\r
1229                         {\r
1230                                 ob->dir = west;\r
1231                                 ob->tilex-=2;\r
1232                                 ob->temp2 = 0;\r
1233                         }\r
1234                         break;\r
1235                 case south:\r
1236                         if (tilemap[ob->tilex][++ob->tiley])\r
1237                         {\r
1238                                 ob->dir = north;\r
1239                                 ob->tiley-=2;\r
1240                                 ob->temp2 = 0;\r
1241                         }\r
1242                         break;\r
1243                 case west:\r
1244                         if (tilemap[--ob->tilex][ob->tiley])\r
1245                         {\r
1246                                 ob->dir = east;\r
1247                                 ob->tilex+=2;\r
1248                                 ob->temp2 = 0;\r
1249                         }\r
1250                         break;\r
1251                 }\r
1252 \r
1253                 ob->distance = TILEGLOBAL;\r
1254 \r
1255                 actorat[ob->tilex][ob->tiley] = ob;     // set down a new goal marker\r
1256         }\r
1257         CalcBounds (ob);\r
1258 }\r
1259 \r