1 /* Catacomb Apocalypse Source Code
\r
2 * Copyright (C) 1993-2014 Flat Rock Software
\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
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
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
25 =============================================================================
\r
29 =============================================================================
\r
33 #define MSHOTDAMAGE 2
\r
34 #define MSHOTSPEED 10000
\r
36 #define ESHOTDAMAGE 1
\r
37 #define ESHOTSPEED 5000
\r
39 #define SSHOTDAMAGE 3
\r
40 #define SSHOTSPEED 6500
\r
42 #define RANDOM_ATTACK 20
\r
46 =============================================================================
\r
50 =============================================================================
\r
53 boolean ShootPlayer (objtype *ob, short obclass, short speed, statetype *state);
\r
54 void T_ShootPlayer(objtype *ob);
\r
56 short zombie_base_delay;
\r
58 short other_x[] = {0,39,39,0},
\r
59 other_y[] = {0,0,27,27};
\r
62 =============================================================================
\r
66 =============================================================================
\r
70 dirtype dirtable[9] = {northwest,north,northeast,west,nodir,east,
\r
71 southwest,south,southeast};
\r
75 =============================================================================
\r
79 =============================================================================
\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
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
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
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
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
108 statetype s_bonus_die = {0,8,NULL,NULL};
\r
118 void SpawnBonus (int tilex, int tiley, int number)
\r
120 extern unsigned gcolor;
\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
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
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
142 if (gcolor == 0x0101)
\r
143 state = &s_waterchestbonus1;
\r
145 state = &s_chestbonus;
\r
148 case B_OLDCHEST: state = &s_oldchestbonus; break;
\r
152 Quit("SpawnBonus(): INVALID BONUS");
\r
156 SpawnNewObj (tilex,tiley,state,TILEGLOBAL/2);
\r
157 new->temp1 = number;
\r
158 new->obclass = bonusobj;
\r
167 new->flags |= of_shootable;
\r
171 new->flags &= ~of_shootable;
\r
179 ============================================================================
\r
183 ============================================================================
\r
186 extern statetype s_ftimebonus;
\r
187 extern statetype s_ftimebonus2;
\r
189 statetype s_ftimebonus = {TIMEOBJ1PIC,6,NULL,&s_ftimebonus2};
\r
190 statetype s_ftimebonus2 = {TIMEOBJ2PIC,6,NULL,&s_ftimebonus};
\r
199 void SpawnFTime(int tilex, int tiley)
\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
208 =============================================================================
\r
212 =============================================================================
\r
216 void T_WallDie (objtype *ob);
\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
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
241 void ExplodeWall (int tilex, int tiley)
\r
243 extern unsigned gcolor;
\r
246 DSpawnNewObj (tilex,tiley,&s_walldie1,0);
\r
247 if (new == &dummyobj)
\r
249 new->obclass = inertobj;
\r
250 new->active = always;
\r
251 if (gcolor == 0x0101)
\r
252 tilenum = WATEREXP;
\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
269 void T_WallDie (objtype *ob)
\r
271 extern unsigned gcolor;
\r
272 unsigned tile,other,spot,x,y;
\r
274 if (++ob->temp1 == 3)
\r
277 if (gcolor == 0x0101)
\r
278 tile = WATEREXP-1 + ob->temp1;
\r
280 tile = WALLEXP-1 + ob->temp1;
\r
284 (unsigned)actorat[x][y] = tilemap[x][y] = *(mapsegs[0]+farmapylookup[y]+x) = tile;
\r
286 if (ob->temp1 == 1)
\r
289 // blow up nearby walls
\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
306 =============================================================================
\r
310 =============================================================================
\r
313 void T_Gate (objtype *ob);
\r
314 void T_Gate_Wait (objtype *ob);
\r
316 extern statetype s_portal_wait;
\r
317 statetype s_portal_wait = {0, 10, &T_Gate_Wait, &s_portal_wait};
\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
326 //---------------------------------------------------------------------------
\r
328 //---------------------------------------------------------------------------
\r
329 void SpawnWarp (int tilex, int tiley)
\r
334 spot = (*(mapsegs[2]+farmapylookup[tiley]+tilex+1)) >> 8;
\r
338 SpawnNewObj (tilex, tiley, &s_portal_wait, TILEGLOBAL/3);
\r
339 new->temp1 = spot*70;
\r
342 SpawnNewObj (tilex, tiley, &s_portal1, TILEGLOBAL/3);
\r
344 new->obclass = gateobj;
\r
355 void T_Gate_Wait (objtype *ob)
\r
357 if ((ob->temp1 -= tics) <= 0)
\r
359 if ((ob->tilex == player->tilex) && (ob->tiley == player->tiley))
\r
361 if (CheckHandAttack(ob))
\r
364 SD_PlaySound(PORTALSND);
\r
365 ob->state = &s_portal1;
\r
366 ob->ticcount = ob->state->tictime;
\r
382 void T_Gate (objtype *ob)
\r
385 unsigned temp,spot;
\r
387 if (CheckHandAttack (ob) && !playstate)
\r
390 // teleport out of level
\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
402 =============================================================================
\r
406 =============================================================================
\r
409 void T_AquaMan(objtype *ob);
\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
415 statetype s_aqua_left = {EYESTALKUNDER4PIC, 40, NULL, &s_aqua_under3};
\r
416 statetype s_aqua_right = {EYESTALKUNDER5PIC, 40, NULL, &s_aqua_under3};
\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
421 statetype s_aqua_sink1 = {EYESTALKRISE2PIC, 15, NULL, &s_aqua_sink2};
\r
422 statetype s_aqua_sink2 = {EYESTALKRISE1PIC, 20, NULL, &s_aqua_under1};
\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
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
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
438 typedef enum {wt_UNDER, wt_WALK} AquaManTypes;
\r
440 #define AQ_TIMEREMAIN (ob->temp1)
\r
441 #define AQ_STAGE (ob->temp2)
\r
450 void SpawnAquaMan(int tilex, int tiley)
\r
453 SpawnNewObj(tilex,tiley,&s_aqua_under1,PIXRADIUS*32);
\r
456 AQ_STAGE = wt_UNDER;
\r
457 AQ_TIMEREMAIN = 60*4+random(60*3);
\r
459 new->obclass = aquamanobj;
\r
461 new->flags &= ~of_shootable;
\r
462 new->hitpoints = EasyHitPoints(15);
\r
465 void ExplosionSnd(objtype *ob)
\r
467 if (ob->temp1 != SOUNDPLAYED)
\r
469 SD_PlaySound(BODY_EXPLODESND);
\r
470 ob->temp1 = SOUNDPLAYED;
\r
484 void T_AquaMan(objtype *ob)
\r
489 ob->flags &= ~of_shootable;
\r
490 if (Chase(ob,true))
\r
492 // RISE & GOTO WALK STAGE
\r
495 AQ_STAGE = wt_WALK;
\r
496 AQ_TIMEREMAIN = 60*5+random(60*5);
\r
497 ob->state = &s_aqua_rise1;
\r
499 ob->ticcount = ob->state->tictime;
\r
503 // DEC COUNTER - And check for WALK
\r
505 if ((AQ_TIMEREMAIN-=realtics) < 0)
\r
507 // RISE & GOTO WALK STAGE
\r
510 if (CheckHandAttack(ob))
\r
513 AQ_STAGE = wt_WALK;
\r
514 AQ_TIMEREMAIN = 60+random(60*2);
\r
515 ob->state = &s_aqua_rise1;
\r
517 ob->ticcount = ob->state->tictime;
\r
520 if (random(1000)<5)
\r
522 // RANDOM PEEK UP OUT OF WATER
\r
524 if (random(2) == 0)
\r
525 ob->state = &s_aqua_left;
\r
527 ob->state = &s_aqua_right;
\r
528 ob->ticcount = ob->state->tictime;
\r
535 ob->flags |= of_shootable;
\r
536 if (Chase(ob,true) || (random(1000)<RANDOM_ATTACK))
\r
538 ob->state = &s_aqua_attack1;
\r
539 ob->ticcount = ob->state->tictime;
\r
543 // DEC COUNTER - And check for SINK
\r
545 if ((AQ_TIMEREMAIN-=realtics) < 0)
\r
547 // SINK & GOTO BUBBLE STAGE
\r
550 AQ_STAGE = wt_UNDER;
\r
551 AQ_TIMEREMAIN = 60*4+random(60*3);
\r
552 ob->state = &s_aqua_sink1;
\r
554 ob->ticcount = ob->state->tictime;
\r
555 ob->flags &= ~of_shootable;
\r
567 =============================================================================
\r
571 =============================================================================
\r
574 void T_Wizard(objtype *ob);
\r
575 void T_WizardShoot(objtype *ob);
\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
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
585 statetype s_wizard_ouch = {WIZARDOUCHPIC, 15, NULL, &s_wizard_walk1};
\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
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
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
608 void SpawnWizard (int tilex, int tiley)
\r
610 SpawnNewObj(tilex,tiley,&s_wizard_walk1,TILEGLOBAL/2);
\r
611 new->obclass = wizardobj;
\r
613 new->flags |= of_shootable;
\r
614 new->hitpoints = EasyHitPoints(10);
\r
626 void T_Wizard(objtype *ob)
\r
628 if (Chase (ob,true))// || (random(1000)<RANDOM_ATTACK))
\r
630 ob->state = &s_wizard_attack1;
\r
631 ob->ticcount = ob->state->tictime;
\r
635 if (AngleNearPlayer(ob) != -1)
\r
637 ob->state = &s_wizard_shoot1;
\r
638 ob->ticcount = ob->state->tictime;
\r
650 void T_WizardShoot(objtype *ob)
\r
652 ShootPlayer(ob, wshotobj, 10000, &s_wizard_shot1);
\r
658 =============================================================================
\r
662 =============================================================================
\r
665 void T_BlobRay(objtype *ob);
\r
666 void T_RayShoot (objtype *ob);
\r
668 statetype s_ray_under = {0, 20, &T_BlobRay, &s_ray_under};
\r
670 statetype s_ray_rise = {RAYRISEPIC, 30, NULL, &s_ray_fly1};
\r
672 statetype s_ray_sink = {RAYRISEPIC, 30, NULL, &s_ray_under};
\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
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
683 statetype s_ray_die1 = {RAYDEATH1PIC, 50, &SmallSound, &s_ray_die2};
\r
684 statetype s_ray_die2 = {RAYDEATH2PIC, 30, NULL, NULL};
\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
690 typedef enum {br_GND, br_WALK, br_CORNER1, br_CORNER2, br_CORNER3, br_CORNER4} BlobTypes;
\r
692 #define BR_TIMEREMAIN (ob->temp1)
\r
693 #define BR_STAGE (ob->temp2)
\r
694 #define BLOB_LEAVE 0x04
\r
703 void SpawnRay(int tilex, int tiley)
\r
706 SpawnNewObj(tilex, tiley, &s_ray_under, PIXRADIUS*25);
\r
710 BR_TIMEREMAIN = random(60)+random(100);
\r
712 new->obclass = rayobj;
\r
714 new->flags &= ~of_shootable;
\r
715 new->hitpoints = EasyHitPoints(15);
\r
721 =============================================================================
\r
725 =============================================================================
\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
732 statetype s_blob_rise1 = {BLOBRISE1PIC, 20, NULL, &s_blob_rise2};
\r
733 statetype s_blob_rise2 = {BLOBRISE2PIC, 20, NULL, &s_blob_walk1};
\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
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
742 statetype s_blob_ouch = {BLOBRISE2PIC, 10, T_BlobRay, &s_blob_walk1};
\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
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
759 void SpawnBlob(int tilex, int tiley)
\r
762 SpawnNewObj(tilex, tiley, &s_blob_gnd1, PIXRADIUS*14);
\r
766 BR_TIMEREMAIN = random(60)+random(100);
\r
768 new->obclass = blobobj;
\r
770 new->flags &= ~of_shootable;
\r
771 new->hitpoints = EasyHitPoints(13);
\r
783 void T_BlobRay(objtype *ob)
\r
788 ob->flags &= ~of_shootable;
\r
789 if (Chase(ob,true))
\r
791 // RISE & GOTO WALK STAGE
\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
799 ob->state = &s_ray_rise;
\r
801 ob->ticcount = ob->state->tictime;
\r
805 // DEC COUNTER - And check for WALK
\r
807 if ((BR_TIMEREMAIN -= realtics) < 0)
\r
809 // RISE & GOTO WALK STAGE
\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
817 ob->state = &s_ray_rise;
\r
819 ob->ticcount = ob->state->tictime;
\r
826 ob->flags |= of_shootable;
\r
828 if (Chase(ob,true) || (CheckHandAttack(ob)))
\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
837 ob->state = &s_ray_under;
\r
838 ob->ticcount = ob->state->tictime;
\r
841 if (AngleNearPlayer(ob) != -1)
\r
843 if (ob->obclass == blobobj)
\r
846 ShootPlayer(ob, bshotobj, 10000, &s_blob_shot1);
\r
851 ob->state = &s_ray_attack1;
\r
852 ob->ticcount = ob->state->tictime;
\r
858 // DEC COUNTER - And check for SINK
\r
860 if ((BR_TIMEREMAIN -= realtics) < 0)
\r
862 // SINK & GOTO GROUND STAGE
\r
866 BR_TIMEREMAIN = 60*2+random(60*2);
\r
867 if (ob->obclass == blobobj)
\r
869 ob->state = &s_blob_sink1;
\r
874 ob->state = &s_ray_sink;
\r
877 ob->ticcount = ob->state->tictime;
\r
878 ob->flags &= ~of_shootable;
\r
887 ob->flags &= ~of_shootable;
\r
888 if ((BR_TIMEREMAIN -= realtics) < 0)
\r
891 ob->flags &= ~BLOB_LEAVE;
\r
896 unsigned temp_tilex,temp_tiley;
\r
900 temp_tilex = player->tilex;
\r
901 temp_tiley = player->tiley;
\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
913 player->tilex = temp_tilex;
\r
914 player->tiley = temp_tiley;
\r
927 void T_RayShoot (objtype *ob)
\r
929 ShootPlayer(ob, rshotobj, 10000, &s_ray_shot1);
\r