]> 4ch.mooo.com Git - 16.git/blob - 16/cawat/C5_ACT3.C
wwww added catacombs source~
[16.git] / 16 / cawat / C5_ACT3.C
1 /* Catacomb Armageddon 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 /*\r
57 =============================================================================\r
58 \r
59                                                  LOCAL VARIABLES\r
60 \r
61 =============================================================================\r
62 */\r
63 \r
64 /*\r
65 =============================================================================\r
66 \r
67                                                 RED DEMON\r
68 \r
69 =============================================================================\r
70 */\r
71 \r
72 void T_RedDemon (objtype *ob);\r
73 void T_RedDemonCheckCnt (objtype *ob);\r
74 \r
75 extern  statetype s_red_demonpause;\r
76 \r
77 extern  statetype s_red_demon1;\r
78 extern  statetype s_red_demon2;\r
79 extern  statetype s_red_demon3;\r
80 extern  statetype s_red_demon4;\r
81 \r
82 extern  statetype s_red_demonattack1;\r
83 extern  statetype s_red_demonattack2;\r
84 extern  statetype s_red_demonattack3;\r
85 \r
86 extern  statetype s_red_demonouch;\r
87 \r
88 extern  statetype s_red_demondie1;\r
89 extern  statetype s_red_demondie2;\r
90 extern  statetype s_red_demondie3;\r
91 extern  statetype s_red_demondie4;\r
92 \r
93 statetype s_red_demonpause = {RED_DEMON1PIC,30,NULL,&s_red_demon2};\r
94 \r
95 statetype s_red_demon1 = {RED_DEMON1PIC,20,T_RedDemon,&s_red_demon2};\r
96 statetype s_red_demon2 = {RED_DEMON2PIC,20,T_RedDemon,&s_red_demon3};\r
97 statetype s_red_demon3 = {RED_DEMON3PIC,20,T_RedDemon,&s_red_demon4};\r
98 statetype s_red_demon4 = {RED_DEMON4PIC,20,T_RedDemon,&s_red_demon1};\r
99 \r
100 statetype s_red_demonattack1 = {RED_DEMONATTACK1PIC,20,NULL,&s_red_demonattack2};\r
101 statetype s_red_demonattack2 = {RED_DEMONATTACK2PIC,20,NULL,&s_red_demonattack3};\r
102 statetype s_red_demonattack3 = {RED_DEMONATTACK3PIC,30,T_DoDamage,&s_red_demon2};\r
103 \r
104 statetype s_red_demonouch = {RED_DEMONOUCHPIC,30,NULL,&s_red_demon1};\r
105 \r
106 statetype s_red_demondie1 = {RED_DEMONOUCHPIC,9,NULL,&s_red_demondie2};\r
107 statetype s_red_demondie2 = {RED_DEMONDIE1PIC,9,T_RedDemonCheckCnt,&s_red_demondie1};\r
108 statetype s_red_demondie3 = {RED_DEMONDIE2PIC,20,NULL,&s_red_demondie4};\r
109 statetype s_red_demondie4 = {RED_DEMONDIE3PIC,10,NULL,&s_red_demondie4};\r
110 \r
111 \r
112 /*\r
113 ===============\r
114 =\r
115 = SpawnRedDemon\r
116 =\r
117 ===============\r
118 */\r
119 \r
120 void SpawnRedDemon (int tilex, int tiley)\r
121 {\r
122         SpawnNewObj(tilex,tiley,&s_red_demon1,PIXRADIUS*35);\r
123         new->obclass = reddemonobj;\r
124         new->speed = 2048;\r
125         new->flags |= of_shootable;\r
126         new->hitpoints = EasyHitPoints(50);\r
127         new->temp1 = 25;\r
128 }\r
129 \r
130 \r
131 /*\r
132 ===============\r
133 =\r
134 = T_RedDemon\r
135 =\r
136 ===============\r
137 */\r
138 \r
139 void T_RedDemon (objtype *ob)\r
140 {\r
141         if (Chase (ob,true) || (random(1000)<RANDOM_ATTACK))\r
142         {\r
143                 ob->state = &s_red_demonattack1;\r
144                 ob->ticcount = ob->state->tictime;\r
145                 return;\r
146         }\r
147 }\r
148 \r
149 /*\r
150 ===============\r
151 =\r
152 = T_RedDemonCheckCnt\r
153 =\r
154 ===============\r
155 */\r
156 \r
157 void T_RedDemonCheckCnt (objtype *ob)\r
158 {\r
159         ob->temp1--;\r
160         if (!ob->temp1)\r
161         {\r
162                 ob->state = &s_red_demondie3;\r
163                 ob->ticcount = ob->state->tictime;\r
164         }\r
165 }\r
166 \r
167 \r
168 /*\r
169 =============================================================================\r
170 \r
171                                                         GRELMINAR\r
172 \r
173 =============================================================================\r
174 */\r
175 \r
176 \r
177 void T_Grelminar (objtype *ob);\r
178 void T_GrelminarShoot (objtype *ob);\r
179 void T_Grelm_DropKey(objtype *ob);\r
180 \r
181 extern  statetype s_grelpause;\r
182 \r
183 extern  statetype s_grel1;\r
184 extern  statetype s_grel2;\r
185 \r
186 extern  statetype s_grelattack1;\r
187 extern  statetype s_grelattack2;\r
188 extern  statetype s_grelattack3;\r
189 \r
190 extern  statetype s_grelouch;\r
191 \r
192 extern  statetype s_greldie1;\r
193 extern  statetype s_greldie2;\r
194 extern  statetype s_greldie3;\r
195 extern  statetype s_greldie4;\r
196 extern  statetype s_greldie5;\r
197 extern  statetype s_greldie5a;\r
198 extern  statetype s_greldie6;\r
199 \r
200 \r
201 statetype s_grelpause = {GREL1PIC,50,NULL,&s_grel2};\r
202 \r
203 statetype s_grel1 = {GREL1PIC,20,T_Grelminar,&s_grel2};\r
204 statetype s_grel2 = {GREL2PIC,20,T_Grelminar,&s_grel1};\r
205 \r
206 //statetype s_grelattack1 = {GRELATTACKPIC,20,NULL,&s_grelattack2};\r
207 //statetype s_grelattack2 = {GRELATTACKPIC,-1,T_GrelminarShoot,&s_grelattack3};\r
208 statetype s_grelattack3 = {GRELATTACKPIC,30,NULL,&s_grelpause};\r
209 \r
210 statetype s_grelouch = {GRELHITPIC,6,NULL,&s_grel1};\r
211 \r
212 statetype s_greldie1 = {GRELDIE1PIC,22,NULL,&s_greldie2};\r
213 statetype s_greldie2 = {GRELDIE2PIC,22,NULL,&s_greldie3};\r
214 statetype s_greldie3 = {GRELDIE3PIC,22,NULL,&s_greldie4};\r
215 statetype s_greldie4 = {GRELDIE4PIC,22,NULL,&s_greldie5};\r
216 statetype s_greldie5 = {GRELDIE5PIC,22,NULL,&s_greldie5a};\r
217 statetype s_greldie5a = {GRELDIE5PIC,1,T_Grelm_DropKey,&s_greldie6};\r
218 statetype s_greldie6 = {GRELDIE6PIC,0,NULL,&s_greldie6};\r
219 \r
220 \r
221 extern statetype s_gshot1;\r
222 \r
223 statetype s_gshot1 = {SKULL_SHOTPIC,8,T_ShootPlayer,&s_gshot1};\r
224 \r
225 /*\r
226 ===============\r
227 =\r
228 = SpawnGrelminar\r
229 =\r
230 ===============\r
231 */\r
232 \r
233 void SpawnGrelminar (int tilex, int tiley)\r
234 {\r
235         unsigned Grel_Hard;\r
236         unsigned DropKey;\r
237 \r
238         SpawnNewObj(tilex,tiley,&s_grel1,PIXRADIUS*35);\r
239         new->obclass = grelmobj;\r
240         new->speed = 2048;\r
241         new->flags |= of_shootable;\r
242 \r
243         //\r
244         // if Grelminar is to drop a key the info-plane byte to the right\r
245         //              should have a 1 in the highbyte, else he will not drop the key.\r
246         //\r
247         DropKey = *(mapsegs[2]+farmapylookup[tiley]+tilex+1);\r
248         if (DropKey)\r
249                 new->temp1 = DropKey>>8;\r
250         else\r
251                 new->temp1 = 0;\r
252 \r
253         //\r
254         // The info-plane byte below Grelminar will determine how powerful\r
255         //              Grelminar is.  If nothing is there, he is the most powerful.\r
256         //                      -- affected are the hit points and the shot damage.\r
257         //      The hit points are controlled here, the shot damage is controlled\r
258         //      within the spawning of the shot.  See ShootPlayer for more info.\r
259         //\r
260         Grel_Hard = *(mapsegs[2]+farmapylookup[tiley+1]+tilex);\r
261         if (Grel_Hard)\r
262         {\r
263                 new->temp2 = Grel_Hard>>8;\r
264                 new->hitpoints = EasyHitPoints((new->temp2 * 10));\r
265         }\r
266         else\r
267                 new->hitpoints = EasyHitPoints(100);\r
268 }\r
269 \r
270 \r
271 /*\r
272 ===============\r
273 =\r
274 = T_Grelminar\r
275 =\r
276 ===============\r
277 */\r
278 \r
279 void T_Grelminar (objtype *ob)\r
280 {\r
281         Chase (ob,false);\r
282 \r
283         if (!random(10))\r
284                 if (ShootPlayer(ob,gshotobj,ob->temp2,&s_gshot1))\r
285                 {\r
286                         ob->state = &s_grelattack3;\r
287                         ob->ticcount = ob->state->tictime;\r
288                 }\r
289         if (CheckHandAttack(ob))\r
290                 TakeDamage (ob->temp2*3);\r
291 \r
292 }\r
293 \r
294 \r
295 //=================================\r
296 //\r
297 // T_Grelm_DropKey\r
298 //\r
299 //=================================\r
300 void T_Grelm_DropKey(objtype *ob)\r
301 {\r
302         if (!(ob->temp1))\r
303         {\r
304                 ob->state = NULL;\r
305                 return;\r
306         }\r
307 \r
308         SpawnBonus(ob->tilex,ob->tiley,B_RKEY);\r
309         SD_PlaySound(GRELM_DEADSND);\r
310         ob->temp1 = false;\r
311 }\r
312 \r
313 /*\r
314 =============================================================================\r
315 \r
316                                                         BAT\r
317 \r
318 =============================================================================\r
319 */\r
320 \r
321 void T_Bat (objtype *ob);\r
322 void T_BatPast (objtype *ob);\r
323 \r
324 extern  statetype s_bat1;\r
325 extern  statetype s_bat2;\r
326 extern  statetype s_bat3;\r
327 extern  statetype s_bat4;\r
328 \r
329 extern  statetype s_batdie1;\r
330 extern  statetype s_batdie2;\r
331 \r
332 \r
333 statetype s_bat1 = {BAT1PIC,6,T_Bat,&s_bat2};\r
334 statetype s_bat2 = {BAT2PIC,6,T_Bat,&s_bat3};\r
335 statetype s_bat3 = {BAT3PIC,6,T_Bat,&s_bat4};\r
336 statetype s_bat4 = {BAT4PIC,6,T_Bat,&s_bat1};\r
337 \r
338 statetype s_batpast = {BAT4PIC,80,T_BatPast,&s_bat1};\r
339 \r
340 statetype s_batdie1 = {BATDIE1PIC,18,NULL,&s_batdie2};\r
341 statetype s_batdie2 = {BATDIE2PIC,18,NULL,NULL};\r
342 \r
343 \r
344 /*\r
345 ===============\r
346 =\r
347 = SpawnBat\r
348 =\r
349 ===============\r
350 */\r
351 \r
352 void SpawnBat (int tilex, int tiley)\r
353 {\r
354         SpawnNewObj(tilex,tiley,&s_bat1,PIXRADIUS*35);\r
355         new->obclass = batobj;\r
356         new->flags |= of_shootable;\r
357 \r
358         new->hitpoints = 1;\r
359         new->speed = 2000;\r
360 }\r
361 \r
362 \r
363 /*\r
364 ==================================\r
365 =\r
366 = BatChaseThink\r
367 =\r
368 ==================================\r
369 */\r
370 \r
371 void BatChaseThink (objtype *obj)\r
372 {\r
373         int deltax,deltay;\r
374 \r
375         deltax=player->tilex - obj->tilex;\r
376         deltay=player->tiley - obj->tiley;\r
377 \r
378         if (deltax>0)\r
379                 deltax = 2;\r
380         else if (deltax<0)\r
381                 deltax = 0;\r
382         else deltax = 1;\r
383 \r
384         if (deltay>0)\r
385                 deltay = 2;\r
386         else if (deltay<0)\r
387                 deltay = 0;\r
388         else deltay = 1;\r
389 \r
390         obj->dir = dirtable[deltay*3+deltax];\r
391         if (Walk(obj))\r
392                 return;\r
393 \r
394         obj->dir = dirtable[3+deltax];\r
395         if (Walk(obj))\r
396                 return;\r
397 \r
398         obj->dir = dirtable[deltay*3+1];\r
399         if (Walk(obj))\r
400                 return;\r
401 \r
402         obj->dir = nodir;\r
403 }\r
404 \r
405 \r
406 void BatRunThink (objtype *obj)\r
407 {\r
408         int deltax,deltay;\r
409 \r
410         deltax=player->tilex - obj->tilex;\r
411         deltay=player->tiley - obj->tiley;\r
412 \r
413         if (deltax>=0)\r
414                 deltax = 0;\r
415         else\r
416                 deltax = 2;\r
417 \r
418         if (deltay>=0)\r
419                 deltay = 0;\r
420         else\r
421                 deltay = 2;\r
422 \r
423         obj->dir = dirtable[deltay*3+deltax];\r
424         if (Walk(obj))\r
425                 return;\r
426 \r
427         obj->dir = dirtable[3+deltax];\r
428         if (Walk(obj))\r
429                 return;\r
430 \r
431         obj->dir = dirtable[deltay*3+1];\r
432         Walk(obj);\r
433 }\r
434 \r
435 \r
436 \r
437 /*\r
438 ===============\r
439 =\r
440 = T_Bat\r
441 =\r
442 ===============\r
443 */\r
444 \r
445 void T_Bat (objtype *ob)\r
446 {\r
447         long move;\r
448         long deltax,deltay,size;\r
449 \r
450         move = ob->speed*tics;\r
451         size = (long)ob->size + player->size + move;\r
452 \r
453 \r
454         do\r
455         {\r
456                 deltax = ob->x - player->x;\r
457                 deltay = ob->y - player->y;\r
458 \r
459                 if (deltax <= size && deltax >= -size\r
460                 && deltay <= size && deltay >= -size && !ob->temp1)\r
461                 {\r
462                         TakeDamage (4);\r
463                         ob->temp1 = 2;\r
464                 }\r
465 \r
466                 if (move < ob->distance)\r
467                 {\r
468                         MoveObj (ob,move);\r
469                         break;\r
470                 }\r
471 \r
472                 actorat[ob->tilex][ob->tiley] = 0;      // pick up marker from goal\r
473                 if (ob->dir == nodir)\r
474                         ob->dir = north;\r
475 \r
476                 ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
477                 ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
478                 move -= ob->distance;\r
479 \r
480                 if (ob->temp1)\r
481                 {\r
482                         Walk (ob);                              // go straight\r
483                         if (!--ob->temp1)\r
484                         {\r
485                                 ob->state = &s_batpast;\r
486                                 ob->ticcount = ob->state->tictime;\r
487                         }\r
488                 }\r
489                 else\r
490                         BatChaseThink (ob);             // head towards player\r
491 \r
492                 actorat[ob->tilex][ob->tiley] = ob;     // set down a new goal marker\r
493         } while (0);    // just once\r
494         CalcBounds (ob);\r
495 }\r
496 \r
497 \r
498 /*\r
499 ===============\r
500 =\r
501 = T_BatPast\r
502 =\r
503 ===============\r
504 */\r
505 \r
506 void T_BatPast (objtype *ob)\r
507 {\r
508         long move;\r
509         long deltax,deltay,size;\r
510 \r
511         move = ob->speed*tics;\r
512 \r
513         do\r
514         {\r
515                 if (move < ob->distance)\r
516                 {\r
517                         MoveObj (ob,move);\r
518                         break;\r
519                 }\r
520                 actorat[ob->tilex][ob->tiley] = 0;      // pick up marker from goal\r
521 \r
522                 ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
523                 ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
524                 move -= ob->distance;\r
525 \r
526                 BatRunThink (ob);\r
527 \r
528                 actorat[ob->tilex][ob->tiley] = ob;     // set down a new goal marker\r
529         } while (0);    //(move)\r
530         CalcBounds (ob);\r
531 }\r
532 \r
533 \r
534 void T_ChaseThink(objtype *obj);\r
535 void T_AwakeThink(objtype *obj);\r
536 \r
537 \r
538 \r
539 /*\r
540 =============================================================================\r
541 \r
542                                                         GODESS\r
543 \r
544 =============================================================================\r
545 */\r
546 \r
547 void T_Godess (objtype *ob);\r
548 \r
549 \r
550 extern  statetype s_godesspause;\r
551 \r
552 extern  statetype s_godess_statue1;\r
553 extern  statetype s_godess_statue2;\r
554 \r
555 extern  statetype s_godess1;\r
556 extern  statetype s_godess2;\r
557 extern  statetype s_godess3;\r
558 \r
559 extern  statetype s_godessattack1;\r
560 extern  statetype s_godessattack2;\r
561 extern  statetype s_godessattack3;\r
562 \r
563 extern  statetype s_godessouch;\r
564 \r
565 extern  statetype s_godessdie1;\r
566 extern  statetype s_godessdie2;\r
567 extern  statetype s_godessdie3;\r
568 \r
569 \r
570 statetype s_godesspause = {GODESS_WALK1PIC,25,NULL,&s_godess2};\r
571 \r
572 statetype s_godess_statue1 = {GODESS_STATUEPIC,20,T_ChaseThink,&s_godess_statue1};\r
573 statetype s_godess_statue2 = {GODESS_STATUEPIC,1,T_AwakeThink,&s_godess1};\r
574 \r
575 statetype s_godess1 = {GODESS_WALK1PIC,20,T_ChaseThink,&s_godess2};\r
576 statetype s_godess2 = {GODESS_WALK2PIC,20,T_ChaseThink,&s_godess3};\r
577 statetype s_godess3 = {GODESS_WALK3PIC,20,T_ChaseThink,&s_godess1};\r
578 \r
579 statetype s_godessattack1 = {GODESS_ATTACK1PIC,10,NULL,&s_godessattack2};//20\r
580 statetype s_godessattack2 = {GODESS_ATTACK2PIC,8,NULL,&s_godessattack3};//20\r
581 statetype s_godessattack3 = {GODESS_ATTACK3PIC,10,T_DoDamage,&s_godesspause};//30\r
582 \r
583 statetype s_godessouch = {GODESS_OUCHPIC,10,NULL,&s_godess1};\r
584 \r
585 statetype s_godessdie1 = {GODESS_DEATH1PIC,65,NULL,&s_godessdie2};\r
586 statetype s_godessdie2 = {GODESS_DEATH2PIC,30,NULL,&s_godessdie2};\r
587 \r
588 \r
589 \r
590 /*\r
591 ===============\r
592 =\r
593 = SpawnGodess\r
594 =\r
595 ===============\r
596 */\r
597 \r
598 void SpawnGodess (int tilex, int tiley)\r
599 {\r
600         objtype *ob;\r
601         short current_zombie_delay;\r
602         unsigned tile;\r
603 \r
604         SpawnNewObj(tilex,tiley,&s_godess_statue1,PIXRADIUS*35);\r
605         ob = new;\r
606         zombie_mode = zm_wait_for_dark;\r
607 \r
608         tile = *(mapsegs[2]+farmapylookup[tiley+1]+tilex);\r
609         if (tile)\r
610                 zombie_delay = (tile>>8)*30;\r
611         else\r
612         {\r
613                 current_zombie_delay = (2*60)+random(4*60);\r
614                 zombie_delay = zombie_base_delay+current_zombie_delay;\r
615                 zombie_base_delay += current_zombie_delay;\r
616                 if (zombie_base_delay > 8*60)\r
617                         zombie_base_delay = 0;\r
618         }\r
619 \r
620         new->obclass = realsolidobj;//godessobj;\r
621         new->speed = 3000;\r
622         new->flags |= of_shootable;\r
623         new->flags &= ~of_tree;\r
624 //      new->hitpoints = EasyHitPoints(10);\r
625 }\r
626 \r
627 \r
628 \r
629 \r
630 /*\r
631 =============================================================================\r
632 \r
633                                         ANT\r
634 \r
635 =============================================================================\r
636 */\r
637 \r
638 void T_Ant(objtype *ob);\r
639 \r
640 statetype s_ant_wait = {ANT_EGG1PIC,10,T_ChaseThink,&s_ant_wait};\r
641 \r
642 statetype s_ant_egg = {ANT_EGG2PIC,45,T_AwakeThink,&s_ant_walk1};\r
643 \r
644 statetype s_ant_walk1 = {ANT_WALK1PIC,20,T_ChaseThink,&s_ant_walk2};\r
645 statetype s_ant_walk2 = {ANT_WALK2PIC,20,T_ChaseThink,&s_ant_walk3};\r
646 statetype s_ant_walk3 = {ANT_WALK3PIC,20,T_ChaseThink,&s_ant_walk1};\r
647 \r
648 statetype s_ant_attack1 = {ANT_ATTACKPIC,20,NULL,&s_ant_pause};\r
649 \r
650 statetype s_ant_pause  = {ANT_WALK2PIC,15,T_DoDamage,&s_ant_walk1};\r
651 \r
652 statetype s_ant_ouch = {ANT_WALK1PIC,15,NULL,&s_ant_walk1};\r
653 \r
654 statetype s_ant_die1 = {ANT_DEATH1PIC,40,NULL,&s_ant_die2};\r
655 statetype s_ant_die2 = {ANT_DEATH2PIC,10,NULL,&s_ant_die3};\r
656 statetype s_ant_die3 = {ANT_DEATH3PIC,10,NULL,&s_ant_die2};\r
657 \r
658 #define ant_mode        ob->temp1\r
659 #define ant_delay       ob->temp2\r
660 \r
661 /*\r
662 ===============\r
663 =\r
664 = SpawnAnt\r
665 =\r
666 ===============\r
667 */\r
668 void SpawnAnt(int tilex, int tiley)\r
669 {\r
670         objtype *ob;\r
671         unsigned tile;\r
672         SpawnNewObj(tilex,tiley,&s_ant_wait,PIXRADIUS*35);\r
673         ob = new;\r
674 \r
675         tile = *(mapsegs[2]+farmapylookup[tiley+1]+tilex);\r
676         if (tile)\r
677                 ant_delay = (tile>>8)*30;\r
678         else\r
679                 ant_delay = 2*60+random(5*60);\r
680 \r
681         ant_mode = zm_wait_for_dark;\r
682 \r
683         new->obclass = antobj;\r
684         new->speed = 1900;\r
685         new->flags &= ~of_shootable;\r
686         new->hitpoints = EasyHitPoints(15);\r
687 }\r
688 \r
689 \r
690 \r
691 /*\r
692 =============================================================================\r
693 \r
694                                                         ZOMBIE\r
695 \r
696 =============================================================================\r
697 */\r
698 \r
699 extern statetype s_zombie_rise1;\r
700 extern statetype s_zombie_rise2;\r
701 extern statetype s_zombie_rise3;\r
702 extern statetype s_zombie_rise4;\r
703 \r
704 extern statetype s_zombie_alive1;\r
705 extern statetype s_zombie_alive2;\r
706 extern statetype s_zombie_alive3;\r
707 \r
708 //extern statetype s_zombie_attack1;\r
709 \r
710 extern statetype s_zombie_death1;\r
711 extern statetype s_zombie_death2;\r
712 extern statetype s_zombie_death3;\r
713 \r
714 void T_Zombie (objtype *ob);\r
715 void T_ZombieRisen(objtype *obj);\r
716 \r
717 statetype s_zombie_risen = {ZOMB_WALK3PIC,1,T_AwakeThink,&s_zombie_alive1};\r
718 \r
719 statetype s_zombie_pause = {ZOMB_WALK1PIC,20,NULL,&s_zombie_alive1};\r
720 \r
721 statetype s_zombie_inground = {0,13,T_ChaseThink,&s_zombie_inground};\r
722 \r
723 statetype s_zombie_rise1 = {ZOMB_APPEAR1PIC,24,NULL,&s_zombie_rise2};\r
724 statetype s_zombie_rise2 = {ZOMB_APPEAR2PIC,24,NULL,&s_zombie_rise3};\r
725 statetype s_zombie_rise3 = {ZOMB_APPEAR3PIC,24,NULL,&s_zombie_rise4};\r
726 statetype s_zombie_rise4 = {ZOMB_APPEAR4PIC,24,NULL,&s_zombie_risen};\r
727 \r
728 statetype s_zombie_alive1 = {ZOMB_WALK1PIC,13,T_ChaseThink,&s_zombie_alive2};\r
729 statetype s_zombie_alive2 = {ZOMB_WALK2PIC,13,T_ChaseThink,&s_zombie_alive3};\r
730 statetype s_zombie_alive3 = {ZOMB_WALK3PIC,13,T_ChaseThink,&s_zombie_alive1};\r
731 \r
732 statetype s_zombie_death1 = {ZOMB_DIE1PIC,16,NULL,&s_zombie_death2};\r
733 statetype s_zombie_death2 = {ZOMB_DIE2PIC,16,NULL,&s_zombie_death3};\r
734 statetype s_zombie_death3 = {ZOMB_DIE3PIC,16,NULL,&s_zombie_death3};\r
735 \r
736 statetype s_zombie_attack  = {ZOMB_ATTACKPIC,15,T_DoDamage,&s_zombie_pause};\r
737 //statetype s_zombie_attack1 = {ZOMB_ATTACKPIC,15,NULL,&s_zombie_pause};\r
738 \r
739 statetype s_zombie_ouch = {ZOMB_OUCHPIC,15,NULL,&s_zombie_alive1};\r
740 \r
741 \r
742 //--------------------------------------------------------------------------\r
743 // SpawnZombie()\r
744 //--------------------------------------------------------------------------\r
745 void SpawnZombie (int tilex, int tiley)\r
746 {\r
747         objtype *ob;\r
748         short current_zombie_delay;\r
749         unsigned tile;\r
750 \r
751         SpawnNewObj(tilex,tiley,&s_zombie_inground,35*PIXRADIUS);\r
752         ob = new;\r
753         zombie_mode = zm_wait_for_dark;\r
754 \r
755         tile = *(mapsegs[2]+farmapylookup[tiley+1]+tilex);\r
756         if (tile)\r
757                 zombie_delay = (tile>>8)*30;\r
758         else\r
759         {\r
760                 current_zombie_delay = (2*60)+random(4*60);\r
761                 zombie_delay = zombie_base_delay+current_zombie_delay;\r
762                 zombie_base_delay += current_zombie_delay;\r
763                 if (zombie_base_delay > 8*60)\r
764                         zombie_base_delay = 0;\r
765         }\r
766 \r
767         new->speed = 2500;\r
768         new->obclass = zombieobj;\r
769         new->hitpoints = EasyHitPoints(8);\r
770         new->active = yes;\r
771         new->flags &= ~of_shootable;\r
772 }\r
773 \r
774 \r
775 /*\r
776 =============================================================================\r
777 \r
778                                         TREE\r
779 \r
780 =============================================================================\r
781 */\r
782 \r
783 extern statetype s_tree_pause;\r
784 extern statetype s_tree_idle;\r
785 extern statetype s_tree_awakening1;\r
786 extern statetype s_tree_awakening2;\r
787 extern statetype s_tree_walk1;\r
788 extern statetype s_tree_walk2;\r
789 extern statetype s_tree_walk3;\r
790 extern statetype s_tree_death1;\r
791 extern statetype s_tree_death2;\r
792 extern statetype s_tree_death3;\r
793 extern statetype s_tree_death4;\r
794 extern statetype s_tree_death5;\r
795 extern statetype s_tree_attack1;\r
796 extern statetype s_tree_attack2;\r
797 extern statetype s_tree_attack3;\r
798 extern statetype s_tree_ouch;\r
799 \r
800 void T_Tree (objtype *ob);\r
801 void T_DeathThink(objtype *ob);\r
802 \r
803 statetype s_tree_pause = {TREE_WALK1PIC,25,NULL,&s_tree_walk2};\r
804 \r
805 statetype s_tree_idle = {TREE_IDLEPIC,13,T_ChaseThink,&s_tree_idle};\r
806 \r
807 statetype s_tree_awakening1 = {TREE_AWAKENINGPIC,1,T_AwakeThink,&s_tree_awakening2};\r
808 statetype s_tree_awakening2 = {TREE_AWAKENINGPIC,50,NULL,&s_tree_walk1};\r
809 \r
810 statetype s_tree_walk1 = {TREE_WALK1PIC,13,T_ChaseThink,&s_tree_walk2};\r
811 statetype s_tree_walk2 = {TREE_WALK2PIC,13,T_ChaseThink,&s_tree_walk1};\r
812 \r
813 statetype s_tree_death1 = {TREE_DEATH1PIC,45,NULL,&s_tree_death2};\r
814 statetype s_tree_death2 = {TREE_DEATH2PIC,25,NULL,&s_tree_death3};\r
815 statetype s_tree_death3 = {TREE_DEATH1PIC,15,T_DeathThink,&s_tree_death4};\r
816 statetype s_tree_death4 = {TREE_DEATH2PIC,15,T_DeathThink,&s_tree_death5};\r
817 statetype s_tree_death5 = {TREE_DEATH3PIC,15,T_DeathThink,&s_tree_death3};\r
818 \r
819 statetype s_tree_attack1  = {TREE_ATTACK1PIC,15,T_DoDamage,&s_tree_attack2};\r
820 statetype s_tree_attack2  = {TREE_ATTACK2PIC,15,T_DoDamage,&s_tree_attack3};\r
821 statetype s_tree_attack3  = {TREE_ATTACK3PIC,15,T_DoDamage,&s_tree_pause};\r
822 \r
823 statetype s_tree_ouch = {TREE_AWAKENINGPIC,15,NULL,&s_tree_walk1};\r
824 \r
825 \r
826 #define zombie_mode     ob->temp1\r
827 #define zombie_delay    ob->temp2\r
828 \r
829 \r
830 //--------------------------------------------------------------------------\r
831 // SpawnTree()\r
832 //--------------------------------------------------------------------------\r
833 void SpawnTree(int tilex, int tiley)\r
834 {\r
835         objtype *ob;\r
836         short current_zombie_delay;\r
837         unsigned tile;\r
838 \r
839         SpawnNewObj(tilex,tiley,&s_tree_idle,35*PIXRADIUS);\r
840         ob = new;\r
841         zombie_mode = zm_wait_for_dark;\r
842 \r
843         tile = *(mapsegs[2]+farmapylookup[tiley+1]+tilex);\r
844         if (tile)\r
845                 zombie_delay = (tile>>8)*30;\r
846         else\r
847         {\r
848                 current_zombie_delay = (2*60)+random(4*60);\r
849                 zombie_delay = zombie_base_delay+current_zombie_delay;\r
850                 zombie_base_delay += current_zombie_delay;\r
851                 if (zombie_base_delay > 8*60)\r
852                         zombie_base_delay = 0;\r
853         }\r
854 \r
855         new->speed = 2500;\r
856         new->obclass = realsolidobj;\r
857 //      new->hitpoints = EasyHitPoints(12);\r
858         new->active = yes;\r
859         new->flags |= of_shootable;\r
860         new->flags |= of_tree;\r
861 }\r
862 \r
863 //--------------------------------------------------------------------------\r
864 // T_DeathThink()\r
865 //--------------------------------------------------------------------------\r
866 void T_DeathThink(objtype *ob)\r
867 {\r
868         char num;\r
869 \r
870         if ((ob->ticcount - realtics) <= 0)\r
871         {\r
872                 num = random(2);\r
873                 switch (ob->temp1)\r
874                 {\r
875                         case 3:\r
876                                 if (num)\r
877                                         ob->state = &s_tree_death4;\r
878                                 else\r
879                                         ob->state = &s_tree_death5;\r
880                                 ob->temp1++;\r
881                         break;\r
882 \r
883                         case 4:\r
884                                 if (num)\r
885                                         ob->state = &s_tree_death3;\r
886                                 else\r
887                                         ob->state = &s_tree_death5;\r
888                                 ob->temp1++;\r
889                         break;\r
890 \r
891                         case 5:\r
892                                 if (num)\r
893                                         ob->state = &s_tree_death3;\r
894                                 else\r
895                                         ob->state = &s_tree_death4;\r
896                                 ob->temp1 = 3;\r
897                         break;\r
898                 }\r
899                 ob->ticcount = ob->state->tictime;\r
900         }\r
901 \r
902 \r
903 \r
904         if (CheckHandAttack(ob))\r
905                 TakeDamage (1);\r
906 }\r
907 \r
908 \r
909 //////////////////////////////////////////////////////////////////////////\r
910 //\r
911 //     GENERAL THINK ROUTINES USED BY THE ZOMBIE, TREE, ANT, AND GODESS\r
912 //             ----trying to cut down on the code size----\r
913 //\r
914 //////////////////////////////////////////////////////////////////////////\r
915 \r
916 \r
917 //--------------------------------------------------------------------------\r
918 // T_ChaseThink()\r
919 //--------------------------------------------------------------------------\r
920 void T_ChaseThink(objtype *ob)\r
921 {\r
922         switch (zombie_mode)\r
923         {\r
924                 case zm_wait_for_dark:\r
925 #if 0\r
926                         if (gamestate.mapon == 0)\r
927                         {\r
928                                 if (BGFLAGS & BGF_NIGHT)\r
929                                         zombie_mode = zm_wait_to_rise;\r
930                         }\r
931                         else\r
932 #endif\r
933                                 zombie_mode = zm_wait_to_rise;\r
934                 break;\r
935 \r
936                 case zm_wait_to_rise:\r
937                         if (zombie_delay < 0)\r
938                         {\r
939                                 if ((ob->tilex == player->tilex) && (ob->tiley == player->tiley))\r
940                                         break;\r
941                                 if (CheckHandAttack(ob))\r
942                                         break;\r
943 \r
944                                 ob->active = always;\r
945                                 switch (ob->obclass)\r
946                                 {\r
947                                         case zombieobj:\r
948                                                 ob->state = &s_zombie_rise1;\r
949                                         break;\r
950 \r
951                                         case antobj:\r
952                                                 ob->state = &s_ant_egg;\r
953                                         break;\r
954 \r
955                                         case realsolidobj:      //tree and godess\r
956                                                 if (ob->flags & of_tree)\r
957                                                         ob->state = &s_tree_awakening1;\r
958                                                 else\r
959                                                         ob->state = &s_godess_statue2;\r
960                                         break;\r
961                                 }\r
962                                 ob->ticcount = ob->state->tictime;\r
963                                 zombie_mode = zm_active;\r
964                         }\r
965                         else\r
966                                 zombie_delay -= tics;\r
967 \r
968                 break;\r
969 \r
970                 case zm_active:\r
971                         if (Chase (ob,true) || (random(1000)<RANDOM_ATTACK))\r
972                         {\r
973                                 switch (ob->obclass)\r
974                                 {\r
975                                         case zombieobj:\r
976                                                 ob->state = &s_zombie_attack;\r
977                                         break;\r
978 \r
979                                         case antobj:\r
980                                                 ob->state = &s_ant_attack1;\r
981                                         break;\r
982 \r
983                                         case treeobj:\r
984                                                 ob->state = &s_tree_attack1;\r
985                                         break;\r
986 \r
987                                         case godessobj:\r
988                                                 ob->state = &s_godessattack1;\r
989                                         break;\r
990                                 }\r
991                                 ob->ticcount = ob->state->tictime;\r
992                                 return;\r
993                         }\r
994                 break;\r
995         }\r
996 }\r
997 \r
998 //--------------------------------------------------------------------------\r
999 // T_AwakeThink()\r
1000 //--------------------------------------------------------------------------\r
1001 void T_AwakeThink(objtype *obj)\r
1002 {\r
1003         if (obj->obclass == realsolidobj)\r
1004         {\r
1005                 if (obj->flags & of_tree)\r
1006                         obj->obclass = treeobj;\r
1007                 else\r
1008                         obj->obclass = godessobj;\r
1009                 obj->hitpoints = EasyHitPoints(12);\r
1010         }\r
1011         else\r
1012                 obj->flags |= of_shootable;\r
1013 }\r
1014 \r
1015 \r
1016 \r
1017 \r
1018 \r
1019 //--------------------------------------------------------------------------\r
1020 // ShootPlayer()\r
1021 //--------------------------------------------------------------------------\r
1022 boolean ShootPlayer(objtype *ob, short obclass, short speed, statetype *state)\r
1023 {\r
1024         int angle = AngleNearPlayer(ob);\r
1025 \r
1026         if (angle == -1)\r
1027                 return(false);\r
1028 \r
1029         DSpawnNewObjFrac (ob->x,ob->y,state,PIXRADIUS*35);\r
1030         new->obclass = obclass;\r
1031         new->active = always;\r
1032         new->angle = angle;\r
1033 \r
1034         //\r
1035         //      If the shot is Grelminar's, then determine the power of the shot.\r
1036         //      The shot speed is hard-wired as 10000.  But the shot power is\r
1037         //              determined by speed.  Speed now contains "Grelminar's level of\r
1038         //              hardness" and this is multiplied by 3 to get the shot power.\r
1039         //\r
1040         if (obclass == gshotobj)\r
1041         {\r
1042                 new->speed = 10000;\r
1043                 new->temp1 = speed*3;\r
1044         }\r
1045         else\r
1046                 new->speed = speed;\r
1047 \r
1048 \r
1049         return(true);\r
1050 }\r
1051 \r
1052 //--------------------------------------------------------------------------\r
1053 // T_ShootPlayer()\r
1054 //--------------------------------------------------------------------------\r
1055 void T_ShootPlayer(objtype *ob)\r
1056 {\r
1057         objtype *check;\r
1058         long xmove,ymove,speed;\r
1059 \r
1060         speed = ob->speed*tics;\r
1061 \r
1062         xmove = FixedByFrac(speed,costable[ob->angle]);\r
1063         ymove = -FixedByFrac(speed,sintable[ob->angle]);\r
1064 \r
1065         if (ShotClipMove(ob,xmove,ymove))\r
1066         {\r
1067                 ob->state = &s_pshot_exp1;\r
1068                 ob->ticcount = ob->state->tictime;\r
1069                 return;\r
1070         }\r
1071 \r
1072         ob->tilex = ob->x >> TILESHIFT;\r
1073         ob->tiley = ob->y >> TILESHIFT;\r
1074 \r
1075 \r
1076 // check for collision with wall\r
1077 //\r
1078         if (tilemap[ob->tilex][ob->tiley])\r
1079         {\r
1080                 SD_PlaySound (SHOOTWALLSND);\r
1081                 ob->state = &s_pshot_exp1;\r
1082                 ob->ticcount = s_pshot_exp1.tictime;\r
1083                 return;\r
1084         }\r
1085 \r
1086 \r
1087 \r
1088 // check for collision with player\r
1089 //\r
1090         if ( ob->xl <= player->xh\r
1091         && ob->xh >= player->xl\r
1092         && ob->yl <= player->yh\r
1093         && ob->yh >= player->yl)\r
1094         {\r
1095                 switch (ob->obclass)\r
1096                 {\r
1097                         case eshotobj:\r
1098                                 TakeDamage (ESHOTDAMAGE);\r
1099                         break;\r
1100 \r
1101                         case mshotobj:\r
1102                                 TakeDamage (MSHOTDAMAGE);\r
1103                         break;\r
1104 \r
1105                         case gshotobj:\r
1106                                 TakeDamage (ob->temp1);         // the damage of Grelminar's shot -\r
1107                         break;                                                          //   see Grelminar's spawning\r
1108 \r
1109                         case sshotobj:\r
1110                                 TakeDamage(SSHOTDAMAGE);\r
1111                         break;\r
1112 \r
1113                         case dshotobj:\r
1114                                 TakeDamage(7);\r
1115                         break;\r
1116                 }\r
1117                 ob->state = NULL;\r
1118                 return;\r
1119         }\r
1120 \r
1121 // check for collision with other solid and realsolid objects.\r
1122 //  Great terminology!! -- solid objects really aren't solid\r
1123 //                      -- realsolid objects ARE solid\r
1124 //      if ((actorat[ob->tilex][ob->tiley]) && (actorat[ob->tilex][ob->tiley]->obclass != ob->obclass))\r
1125         if (((actorat[ob->tilex][ob->tiley]->obclass == realsolidobj) ||\r
1126                  (actorat[ob->tilex][ob->tiley]->obclass == solidobj)) &&\r
1127                  (actorat[ob->tilex][ob->tiley]->flags & of_shootable))\r
1128         {\r
1129                         ob->state = &s_pshot_exp1;\r
1130                         ob->ticcount = s_pshot_exp1.tictime;\r
1131                         return;\r
1132         }\r
1133 \r
1134 \r
1135 // check for collision with player\r
1136 //\r
1137         for (check = player->next; check; check=check->next)\r
1138                 if ((ob->flags & of_shootable) && ob->obclass != mageobj\r
1139                 && ob->xl <= check->xh\r
1140                 && ob->xh >= check->xl\r
1141                 && ob->yl <= check->yh\r
1142                 && ob->yh >= check->yl)\r
1143                 {\r
1144                         switch (ob->obclass)\r
1145                         {\r
1146                                 case eshotobj:\r
1147                                         ShootActor (check,ESHOTDAMAGE);\r
1148                                 break;\r
1149 \r
1150                                 case mshotobj:\r
1151                                         ShootActor (check,MSHOTDAMAGE);\r
1152                                 break;\r
1153 \r
1154                                 case gshotobj:\r
1155                                         ShootActor (check,25);          //NOLAN--check on me!!!!!!!\r
1156                                 break;\r
1157 \r
1158                                 case pshotobj:\r
1159                                         ShootActor (check,25);\r
1160                                 break;\r
1161 \r
1162                                 case sshotobj:\r
1163                                         ShootActor(check, SSHOTDAMAGE);\r
1164                                 break;\r
1165 \r
1166                                 case dshotobj:\r
1167                                         ShootActor(check, 7);\r
1168                                 break;\r
1169                         }\r
1170                         ob->state = &s_pshot_exp1;\r
1171                         ob->ticcount = s_pshot_exp1.tictime;\r
1172                         return;\r
1173                 }\r
1174 }\r
1175 \r
1176 //-------------------------------------------------------------------------\r
1177 // AngleNearPlayer()\r
1178 //-------------------------------------------------------------------------\r
1179 int AngleNearPlayer(objtype *ob)\r
1180 {\r
1181         int angle=-1;\r
1182         int xdiff = ob->tilex-player->tilex;\r
1183         int ydiff = ob->tiley-player->tiley;\r
1184 \r
1185         if (ob->tiley == player->tiley)\r
1186         {\r
1187                 if (ob->tilex < player->tilex)\r
1188                         angle = 0;\r
1189                 else\r
1190                         angle = 180;\r
1191         }\r
1192         else\r
1193         if (ob->tilex == player->tilex)\r
1194         {\r
1195                 if (ob->tiley < player->tiley)\r
1196                         angle = 270;\r
1197                 else\r
1198                         angle = 90;\r
1199         }\r
1200         else\r
1201         if (xdiff == ydiff)\r
1202                 if (ob->tilex < player->tilex)\r
1203                 {\r
1204                         if (ob->tiley < player->tiley)\r
1205                                 angle = 315;\r
1206                         else\r
1207                                 angle = 45;\r
1208                 }\r
1209                 else\r
1210                 {\r
1211                         if (ob->tiley < player->tiley)\r
1212                                 angle = 225;\r
1213                         else\r
1214                                 angle = 135;\r
1215                 }\r
1216 \r
1217         return(angle);\r
1218 }\r