/* Catacomb 3-D Source Code * Copyright (C) 1993-2014 Flat Rock Software * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ // C3_PLAY.C #include "C3_DEF.H" #pragma hdrstop /* ============================================================================= LOCAL CONSTANTS ============================================================================= */ /* ============================================================================= GLOBAL VARIABLES ============================================================================= */ /* ============================================================================= LOCAL VARIABLES ============================================================================= */ dirtype dirtable[9] = {northwest,north,northeast,west,nodir,east, southwest,south,southeast}; /* ============================================================================= BONUS ITEMS ============================================================================= */ extern statetype s_boltbonus2; extern statetype s_nukebonus2; statetype s_boltbonus = {BOLTOBJPIC,8,NULL,&s_boltbonus2}; statetype s_boltbonus2 = {BOLTOBJ2PIC,8,NULL,&s_boltbonus}; statetype s_nukebonus = {NUKEOBJPIC,8,NULL,&s_nukebonus2}; statetype s_nukebonus2 = {NUKEOBJ2PIC,8,NULL,&s_nukebonus}; statetype s_potionbonus = {POTIONOBJPIC,0,NULL,&s_potionbonus}; statetype s_rkeybonus = {RKEYOBJPIC,0,NULL,&s_rkeybonus}; statetype s_ykeybonus = {YKEYOBJPIC,0,NULL,&s_ykeybonus}; statetype s_gkeybonus = {GKEYOBJPIC,0,NULL,&s_gkeybonus}; statetype s_bkeybonus = {BKEYOBJPIC,0,NULL,&s_bkeybonus}; statetype s_scrollbonus = {SCROLLOBJPIC,0,NULL,&s_scrollbonus}; statetype s_chestbonus = {CHESTOBJPIC,0,NULL,&s_chestbonus}; statetype s_goalbonus = {NEMESISPIC,0,NULL,&s_goalbonus}; /* =============== = = SpawnBonus = =============== */ void SpawnBonus (int tilex, int tiley, int number) { statetype *state; if (number == B_BOLT) state = &s_boltbonus; else if (number == B_NUKE) state = &s_nukebonus; else if (number == B_POTION) state = &s_potionbonus; else if (number == B_RKEY) state = &s_rkeybonus; else if (number == B_YKEY) state = &s_ykeybonus; else if (number == B_GKEY) state = &s_gkeybonus; else if (number == B_BKEY) state = &s_bkeybonus; else if (number >= B_SCROLL1 && number <= B_SCROLL8) state = &s_scrollbonus; else if (number == B_CHEST) state = &s_chestbonus; else if (number == B_GOAL) state = &s_goalbonus; SpawnNewObj (tilex,tiley,state,TILEGLOBAL/2); new->tileobject = true; new->temp1 = number; new->obclass = bonusobj; new->shootable = false; } /* ============================================================================= EXPLODING WALL ============================================================================= */ void T_WallDie (objtype *ob); extern statetype s_walldie1; extern statetype s_walldie2; extern statetype s_walldie3; extern statetype s_walldie4; extern statetype s_walldie5; extern statetype s_walldie6; statetype s_walldie1 = {0,20,NULL,&s_walldie2}; statetype s_walldie2 = {0,-1,T_WallDie,&s_walldie3}; statetype s_walldie3 = {0,20,NULL,&s_walldie4}; statetype s_walldie4 = {0,-1,T_WallDie,&s_walldie5}; statetype s_walldie5 = {0,20,NULL,&s_walldie6}; statetype s_walldie6 = {0,-1,T_WallDie,NULL}; /* ================ = = ExplodeWall = ================ */ void ExplodeWall (int tilex, int tiley) { SpawnNewObj (tilex,tiley,&s_walldie1,0); new->obclass = inertobj; new->active = true; (unsigned)actorat[new->tilex][new->tiley] = tilemap[new->tilex][new->tiley] = *(mapsegs[0]+farmapylookup[new->tiley]+new->tilex) = WALLEXP; } /* ================ = = T_WallDie = ================ */ void T_WallDie (objtype *ob) { unsigned tile,other; if (++ob->temp1 == 3) tile = 0; else tile = WALLEXP-1 + ob->temp1; (unsigned)actorat[ob->tilex][ob->tiley] = tilemap[ob->tilex][ob->tiley] = *(mapsegs[0]+farmapylookup[ob->tiley]+ob->tilex) = tile; if (ob->temp1 == 1) { // // blow up nearby walls // other = tilemap[ob->tilex-1][ob->tiley]; if ((unsigned)(other-EXPWALLSTART)tilex-1,ob->tiley); other = tilemap[ob->tilex+1][ob->tiley]; if ((unsigned)(other-EXPWALLSTART)tilex+1,ob->tiley); other = tilemap[ob->tilex][ob->tiley-1]; if ((unsigned)(other-EXPWALLSTART)tilex,ob->tiley-1); other = tilemap[ob->tilex][ob->tiley+1]; if ((unsigned)(other-EXPWALLSTART)tilex,ob->tiley+1); } } /* ============================================================================= WARP GATE ============================================================================= */ void T_Gate (objtype *ob); extern statetype s_gate1; extern statetype s_gate2; extern statetype s_gate3; extern statetype s_gate4; extern statetype s_fgate1; extern statetype s_fgate2; extern statetype s_fgate3; extern statetype s_fgate4; statetype s_gate1 = {WARP1PIC,12,T_Gate,&s_gate2}; statetype s_gate2 = {WARP2PIC,12,T_Gate,&s_gate3}; statetype s_gate3 = {WARP3PIC,12,T_Gate,&s_gate4}; statetype s_gate4 = {WARP4PIC,12,T_Gate,&s_gate1}; statetype s_fgate1 = {WARP1PIC,6,T_Gate,&s_fgate2}; statetype s_fgate2 = {WARP2PIC,6,T_Gate,&s_fgate3}; statetype s_fgate3 = {WARP3PIC,6,T_Gate,&s_fgate4}; statetype s_fgate4 = {WARP4PIC,6,T_Gate,&s_fgate1}; /* =============== = = SpawnWarp = =============== */ void SpawnWarp (int tilex, int tiley, int type) { if (type) SpawnNewObj (tilex,tiley,&s_fgate1,TILEGLOBAL/3); else SpawnNewObj (tilex,tiley,&s_gate1,TILEGLOBAL/3); new->obclass = gateobj; new->temp1 = type; } /* =============== = = T_Gate = =============== */ #define STATUSCOLOR 4 void T_Gate (objtype *ob) { int spot; objtype *check; unsigned temp; if (CheckHandAttack (ob) && !playstate) { // // warp // temp = bufferofs; bufferofs = 0; VW_Bar (26,4,232,9,STATUSCOLOR); // clear text description bufferofs = temp; IN_ClearKeysDown (); if (ob->temp1) { // // teleport inside level // for (check=player->next;check;check=check->next) if (check->obclass==gateobj && check->temp1==ob->temp1 && check != ob) { player->x = check->x; player->y = check->y; Thrust (player->angle,TILEGLOBAL/2); // move forwards Thrust (player->angle,TILEGLOBAL/2); // move forwards Thrust (player->angle,TILEGLOBAL/2); // move forwards fizzlein=true; } } else { // // teleport out of level // playstate = ex_warped; spot = *(mapsegs[0]+farmapylookup[ob->tiley]+ob->tilex)-NAMESTART; if (spot<1) gamestate.mapon++; else gamestate.mapon=spot-1; SD_PlaySound(WARPUPSND); } } } /* ============================================================================= TROLLS ============================================================================= */ void T_Troll (objtype *ob); extern statetype s_trollpause; extern statetype s_troll1; extern statetype s_troll2; extern statetype s_troll3; extern statetype s_troll4; extern statetype s_trollattack1; extern statetype s_trollattack2; extern statetype s_trollattack3; extern statetype s_trollouch; extern statetype s_trolldie1; extern statetype s_trolldie2; extern statetype s_trolldie3; statetype s_trollpause = {TROLL1PIC,40,NULL,&s_troll2}; statetype s_troll1 = {TROLL1PIC,13,T_Troll,&s_troll2}; statetype s_troll2 = {TROLL2PIC,13,T_Troll,&s_troll3}; statetype s_troll3 = {TROLL3PIC,13,T_Troll,&s_troll4}; statetype s_troll4 = {TROLL4PIC,13,T_Troll,&s_troll1}; statetype s_trollattack1 = {TROLLATTACK1PIC,20,NULL,&s_trollattack2}; statetype s_trollattack2 = {TROLLATTACK2PIC,10,T_DoDamage,&s_trollattack3}; statetype s_trollattack3 = {TROLLATTACK2PIC,40,NULL,&s_trollpause}; statetype s_trollouch = {TROLLOUCHPIC,8,NULL,&s_troll1}; statetype s_trolldie1 = {TROLLDIE1PIC,8,NULL,&s_trolldie2}; statetype s_trolldie2 = {TROLLDIE2PIC,8,NULL,&s_trolldie3}; statetype s_trolldie3 = {TROLLDIE3PIC,0,NULL,&s_trolldie3}; /* =============== = = SpawnTroll = =============== */ void SpawnTroll (int tilex, int tiley) { SpawnNewObj(tilex,tiley,&s_troll1,40*PIXRADIUS); new->speed = 2500; new->obclass = trollobj; new->shootable = true; new->hitpoints = 10; } /* =============== = = T_Troll = =============== */ void T_Troll (objtype *ob) { if (Chase (ob,true)) { ob->state = &s_trollattack1; ob->ticcount = ob->state->tictime; return; } } /* ============================================================================= ORCS ============================================================================= */ void T_Orc (objtype *ob); extern statetype s_orcpause; extern statetype s_orc1; extern statetype s_orc2; extern statetype s_orc3; extern statetype s_orc4; extern statetype s_orcattack1; extern statetype s_orcattack2; extern statetype s_orcattack3; extern statetype s_orcouch; extern statetype s_orcdie1; extern statetype s_orcdie2; extern statetype s_orcdie3; statetype s_orcpause = {ORC1PIC,40,NULL,&s_orc2}; statetype s_orc1 = {ORC1PIC,20,T_Orc,&s_orc2}; statetype s_orc2 = {ORC2PIC,20,T_Orc,&s_orc3}; statetype s_orc3 = {ORC3PIC,20,T_Orc,&s_orc4}; statetype s_orc4 = {ORC4PIC,20,T_Orc,&s_orc1}; statetype s_orcattack1 = {ORCATTACK1PIC,20,NULL,&s_orcattack2}; statetype s_orcattack2 = {ORCATTACK2PIC,10,T_DoDamage,&s_orcattack3}; statetype s_orcattack3 = {ORCATTACK2PIC,40,NULL,&s_orcpause}; statetype s_orcouch = {ORCOUCHPIC,10,NULL,&s_orc1}; statetype s_orcdie1 = {ORCDIE1PIC,8,NULL,&s_orcdie2}; statetype s_orcdie2 = {ORCDIE2PIC,8,NULL,&s_orcdie3}; statetype s_orcdie3 = {ORCDIE3PIC,0,NULL,&s_orcdie3}; /* =============== = = SpawnOrc = =============== */ void SpawnOrc (int tilex, int tiley) { SpawnNewObj(tilex,tiley,&s_orc1,PIXRADIUS*32); new->obclass = orcobj; new->speed = 1536; new->shootable = true; new->hitpoints = 3; } /* =============== = = T_Orc = =============== */ void T_Orc (objtype *ob) { if (Chase (ob,true)) { ob->state = &s_orcattack1; ob->ticcount = ob->state->tictime; return; } } /* ============================================================================= DEMON ============================================================================= */ void T_Demon (objtype *ob); extern statetype s_demonpause; extern statetype s_demon1; extern statetype s_demon2; extern statetype s_demon3; extern statetype s_demon4; extern statetype s_demonattack1; extern statetype s_demonattack2; extern statetype s_demonattack3; extern statetype s_demonouch; extern statetype s_demondie1; extern statetype s_demondie2; extern statetype s_demondie3; statetype s_demonpause = {DEMON1PIC,40,NULL,&s_demon2}; statetype s_demon1 = {DEMON1PIC,20,T_Demon,&s_demon2}; statetype s_demon2 = {DEMON2PIC,20,T_Demon,&s_demon3}; statetype s_demon3 = {DEMON3PIC,20,T_Demon,&s_demon4}; statetype s_demon4 = {DEMON4PIC,20,T_Demon,&s_demon1}; statetype s_demonattack1 = {DEMONATTACK1PIC,20,NULL,&s_demonattack2}; statetype s_demonattack2 = {DEMONATTACK2PIC,20,T_DoDamage,&s_demonattack3}; statetype s_demonattack3 = {DEMONATTACK3PIC,30,NULL,&s_demonpause}; statetype s_demonouch = {DEMONOUCHPIC,10,NULL,&s_demon1}; statetype s_demondie1 = {DEMONDIE1PIC,20,NULL,&s_demondie2}; statetype s_demondie2 = {DEMONDIE2PIC,20,NULL,&s_demondie3}; statetype s_demondie3 = {DEMONDIE3PIC,0,NULL,&s_demondie3}; /* =============== = = SpawnDemon = =============== */ void SpawnDemon (int tilex, int tiley) { SpawnNewObj(tilex,tiley,&s_demon1,TILEGLOBAL/2); new->obclass = demonobj; new->speed = 2048; new->shootable = true; new->hitpoints = 50; } /* =============== = = T_Demon = =============== */ void T_Demon (objtype *ob) { if (Chase (ob,true)) { ob->state = &s_demonattack1; ob->ticcount = ob->state->tictime; return; } } /* ============================================================================= MSHOTS temp1 = dir ============================================================================= */ #define MSHOTDAMAGE 2 #define MSHOTSPEED 10000 void T_Mshot (objtype *ob); extern statetype s_mshot1; extern statetype s_mshot2; statetype s_mshot1 = {PSHOT1PIC,8,&T_Mshot,&s_mshot2}; statetype s_mshot2 = {PSHOT2PIC,8,&T_Mshot,&s_mshot1}; /* =============== = = T_Mshot = =============== */ void T_Mshot (objtype *ob) { objtype *check; long xmove,ymove,speed; xmove = ymove = 0; switch (ob->dir) { case north: ymove = -ob->speed*tics; break; case east: xmove = ob->speed*tics; break; case south: ymove = ob->speed*tics; break; case west: xmove = -ob->speed*tics; break; } ob->x+=xmove; ob->y+=ymove; CalcBounds (ob); ob->tilex = ob->x>>TILESHIFT; ob->tiley = ob->y>>TILESHIFT; if (tilemap[ob->tilex][ob->tiley]) { SD_PlaySound (SHOOTWALLSND); ob->state = NULL; return; } // // check final position for monsters hit // if ( ob->xl <= player->xh && ob->xh >= player->xl && ob->yl <= player->yh && ob->yh >= player->yl) { TakeDamage (MSHOTDAMAGE*2); ob->state = NULL; return; } for (check = player->next; check; check=check->next) if (ob->shootable && ob->obclass != mageobj && ob->xl <= check->xh && ob->xh >= check->xl && ob->yl <= check->yh && ob->yh >= check->yl) { ShootActor (check,MSHOTDAMAGE); ob->state = NULL; return; } } /* ============================================================================= MAGE ============================================================================= */ void T_Mage (objtype *ob); void T_MageShoot (objtype *ob); extern statetype s_magepause; extern statetype s_mage1; extern statetype s_mage2; extern statetype s_mageattack1; extern statetype s_mageattack2; extern statetype s_mageattack3; extern statetype s_mageouch; extern statetype s_magedie1; extern statetype s_magedie2; statetype s_magepause = {MAGE1PIC,100,NULL,&s_mage2}; statetype s_mage1 = {MAGE1PIC,20,T_Mage,&s_mage2}; statetype s_mage2 = {MAGE2PIC,20,T_Mage,&s_mage1}; statetype s_mageattack1 = {MAGEATTACKPIC,20,NULL,&s_mageattack2}; statetype s_mageattack2 = {MAGEATTACKPIC,-1,T_MageShoot,&s_mageattack3}; statetype s_mageattack3 = {MAGEATTACKPIC,30,NULL,&s_magepause}; statetype s_mageouch = {MAGEOUCHPIC,10,NULL,&s_mage1}; statetype s_magedie1 = {MAGEDIE1PIC,20,NULL,&s_magedie2}; statetype s_magedie2 = {MAGEDIE2PIC,0,NULL,&s_magedie2}; /* =============== = = SpawnMage = =============== */ void SpawnMage (int tilex, int tiley) { SpawnNewObj(tilex,tiley,&s_mage1,TILEGLOBAL/2); new->obclass = mageobj; new->speed = 2048; new->shootable = true; new->hitpoints = 5; } /* =============== = = T_Mage = =============== */ void T_Mage (objtype *ob) { Chase (ob,false); // // check for line up with player // if (ob->x-PIXRADIUS*14 < player->xh && ob->x+PIXRADIUS > player->xl) { ob->temp1 = 1; ob->state = &s_mageattack1; } else if (ob->y-PIXRADIUS*14 < player->yh && ob->y+PIXRADIUS > player->yl) { ob->temp1 = 0; ob->state = &s_mageattack1; } } /* =============== = = T_MageShoot = =============== */ void T_MageShoot (objtype *ob) { SpawnNewObjFrac (ob->x,ob->y,&s_mshot1,PIXRADIUS*14); new->obclass = mshotobj; new->speed = MSHOTSPEED; if (ob->temp1) { if (ob->tiley < player->tiley) new->dir = south; else new->dir = north; } else { if (ob->tilex < player->tilex) new->dir = east; else new->dir = west; } } /* ============================================================================= nemesis ============================================================================= */ void T_Nemesis (objtype *ob); void T_NemesisShoot (objtype *ob); extern statetype s_grelpause; extern statetype s_grel1; extern statetype s_grel2; extern statetype s_grelattack1; extern statetype s_grelattack2; extern statetype s_grelattack3; extern statetype s_grelouch; extern statetype s_greldie1; extern statetype s_greldie2; extern statetype s_greldie3; extern statetype s_greldie4; extern statetype s_greldie5; extern statetype s_greldie6; statetype s_grelpause = {GREL1PIC,50,NULL,&s_grel2}; statetype s_grel1 = {GREL1PIC,20,T_Nemesis,&s_grel2}; statetype s_grel2 = {GREL2PIC,20,T_Nemesis,&s_grel1}; statetype s_grelattack1 = {GRELATTACKPIC,20,NULL,&s_grelattack2}; statetype s_grelattack2 = {GRELATTACKPIC,-1,T_NemesisShoot,&s_grelattack3}; statetype s_grelattack3 = {GRELATTACKPIC,30,NULL,&s_grelpause}; statetype s_grelouch = {GRELHITPIC,6,NULL,&s_grel1}; statetype s_greldie1 = {GRELDIE1PIC,20,NULL,&s_greldie2}; statetype s_greldie2 = {GRELDIE2PIC,20,NULL,&s_greldie3}; statetype s_greldie3 = {GRELDIE3PIC,20,NULL,&s_greldie4}; statetype s_greldie4 = {GRELDIE4PIC,20,NULL,&s_greldie5}; statetype s_greldie5 = {GRELDIE5PIC,20,NULL,&s_greldie6}; statetype s_greldie6 = {GRELDIE6PIC,0,NULL,&s_greldie6}; /* =============== = = SpawnNemesis = =============== */ void SpawnNemesis (int tilex, int tiley) { SpawnNewObj(tilex,tiley,&s_grel1,PIXRADIUS*56); new->obclass = grelmobj; new->speed = 2048; new->shootable = true; new->hitpoints = 100; } /* =============== = = T_Nemesis = =============== */ void T_Nemesis (objtype *ob) { Chase (ob,false); // // check for line up with player // if (ob->tilex == player->tilex) { ob->temp1 = 1; ob->state = &s_grelattack1; } else if (ob->tiley == player->tiley) { ob->temp1 = 0; ob->state = &s_grelattack1; } } /* =============== = = T_NemesisShoot = =============== */ void T_NemesisShoot (objtype *ob) { SpawnNewObjFrac (ob->x,ob->y,&s_mshot1,PIXRADIUS*14); new->obclass = mshotobj; new->speed = MSHOTSPEED; if (ob->temp1) { if (ob->tiley < player->tiley) new->dir = south; else new->dir = north; } else { if (ob->tilex < player->tilex) new->dir = east; else new->dir = west; } } /* ============================================================================= BAT ============================================================================= */ void T_Bat (objtype *ob); void T_BatPast (objtype *ob); extern statetype s_bat1; extern statetype s_bat2; extern statetype s_bat3; extern statetype s_bat4; extern statetype s_batdie1; extern statetype s_batdie2; statetype s_bat1 = {BAT1PIC,6,T_Bat,&s_bat2}; statetype s_bat2 = {BAT2PIC,6,T_Bat,&s_bat3}; statetype s_bat3 = {BAT3PIC,6,T_Bat,&s_bat4}; statetype s_bat4 = {BAT4PIC,6,T_Bat,&s_bat1}; statetype s_batpast = {BAT4PIC,80,T_BatPast,&s_bat1}; statetype s_batdie1 = {BATDIE1PIC,8,NULL,&s_batdie2}; statetype s_batdie2 = {BATDIE2PIC,8,NULL,NULL}; /* =============== = = SpawnBat = =============== */ void SpawnBat (int tilex, int tiley) { SpawnNewObj(tilex,tiley,&s_bat1,PIXRADIUS*24); new->obclass =batobj; new->shootable = true; new->hitpoints = 1; new->speed = 2000; } /* ================================== = = BatChaseThink = ================================== */ void BatChaseThink (objtype *obj) { int deltax,deltay; deltax=player->tilex - obj->tilex; deltay=player->tiley - obj->tiley; if (deltax>0) deltax = 2; else if (deltax<0) deltax = 0; else deltax = 1; if (deltay>0) deltay = 2; else if (deltay<0) deltay = 0; else deltay = 1; obj->dir = dirtable[deltay*3+deltax]; if (Walk(obj)) return; obj->dir = dirtable[3+deltax]; if (Walk(obj)) return; obj->dir = dirtable[deltay*3+1]; if (Walk(obj)) return; obj->dir = nodir; } void BatRunThink (objtype *obj) { int deltax,deltay; deltax=player->tilex - obj->tilex; deltay=player->tiley - obj->tiley; if (deltax>=0) deltax = 0; else deltax = 2; if (deltay>=0) deltay = 0; else deltay = 2; obj->dir = dirtable[deltay*3+deltax]; if (Walk(obj)) return; obj->dir = dirtable[3+deltax]; if (Walk(obj)) return; obj->dir = dirtable[deltay*3+1]; Walk(obj); } /* =============== = = T_Bat = =============== */ void T_Bat (objtype *ob) { long move; long deltax,deltay,size; move = ob->speed*tics; size = (long)ob->size + player->size + move; do { deltax = ob->x - player->x; deltay = ob->y - player->y; if (deltax <= size && deltax >= -size && deltay <= size && deltay >= -size && !ob->temp1) { TakeDamage (4); ob->temp1 = 2; } if (move < ob->distance) { MoveObj (ob,move); break; } actorat[ob->tilex][ob->tiley] = 0; // pick up marker from goal if (ob->dir == nodir) ob->dir = north; ob->x = ((long)ob->tilex<y = ((long)ob->tiley<distance; if (ob->temp1) { Walk (ob); // go straight if (!--ob->temp1) { ob->state = &s_batpast; ob->ticcount = ob->state->tictime; } } else BatChaseThink (ob); // head towards player actorat[ob->tilex][ob->tiley] = ob; // set down a new goal marker } while (0); // just once CalcBounds (ob); } /* =============== = = T_BatPast = =============== */ void T_BatPast (objtype *ob) { long move; long deltax,deltay,size; move = ob->speed*tics; do { if (move < ob->distance) { MoveObj (ob,move); break; } actorat[ob->tilex][ob->tiley] = 0; // pick up marker from goal ob->x = ((long)ob->tilex<y = ((long)ob->tiley<distance; BatRunThink (ob); actorat[ob->tilex][ob->tiley] = ob; // set down a new goal marker } while (0); //(move) CalcBounds (ob); } /* ============================================================================= BOUNCE temp2 = set when hit player, reset when hit wall ============================================================================= */ #define SPDBOUNCE 4096 #define DMGBOUNCE 10 void T_Bounce (objtype *ob); extern statetype s_bounce1; extern statetype s_bounce2; statetype s_bounce1 = {BIGPSHOT1PIC,8,T_Bounce,&s_bounce2}; statetype s_bounce2 = {BIGPSHOT2PIC,8,T_Bounce,&s_bounce1}; /* =============== = = SpawnBounce = =============== */ void SpawnBounce (int tilex, int tiley, boolean towest) { SpawnNewObj(tilex,tiley,&s_bounce1,24*PIXRADIUS); new->obclass = bounceobj; if (towest) new->dir = west; else new->dir = north; } /* =============== = = T_Bounce = =============== */ void T_Bounce (objtype *ob) { long move; long deltax,deltay,size; move = SPDBOUNCE*tics; size = (long)ob->size + player->size + move; while (move) { deltax = ob->x - player->x; deltay = ob->y - player->y; if (deltax <= size && deltax >= -size && deltay <= size && deltay >= -size && !ob->temp2) { ob->temp2 = 1; TakeDamage (DMGBOUNCE); } if (move < ob->distance) { MoveObj (ob,move); break; } actorat[ob->tilex][ob->tiley] = 0; // pick up marker from goal ob->x = ((long)ob->tilex<y = ((long)ob->tiley<distance; // // bounce if hit wall // switch (ob->dir) { case north: if (tilemap[ob->tilex][--ob->tiley]) { ob->dir = south; ob->tiley+=2; ob->temp2 = 0; } break; case east: if (tilemap[++ob->tilex][ob->tiley]) { ob->dir = west; ob->tilex-=2; ob->temp2 = 0; } break; case south: if (tilemap[ob->tilex][++ob->tiley]) { ob->dir = north; ob->tiley-=2; ob->temp2 = 0; } break; case west: if (tilemap[--ob->tilex][ob->tiley]) { ob->dir = east; ob->tilex+=2; ob->temp2 = 0; } break; } ob->distance = TILEGLOBAL; actorat[ob->tilex][ob->tiley] = ob; // set down a new goal marker } CalcBounds (ob); }