X-Git-Url: http://4ch.mooo.com/gitweb/?p=16.git;a=blobdiff_plain;f=16%2Fkeen456%2FKEEN4-6%2FKEEN6%2FK6_ACT1.C;fp=16%2Fkeen456%2FKEEN4-6%2FKEEN6%2FK6_ACT1.C;h=0000000000000000000000000000000000000000;hp=a2004bdf82b17f6e0574ebdfd4b92365b50ea16a;hb=a387b1ff6f02e2da93e870a330af886d1c8233da;hpb=7d1948e210bb7b58af0a0412e71f2a0a0a2010af diff --git a/16/keen456/KEEN4-6/KEEN6/K6_ACT1.C b/16/keen456/KEEN4-6/KEEN6/K6_ACT1.C deleted file mode 100755 index a2004bdf..00000000 --- a/16/keen456/KEEN4-6/KEEN6/K6_ACT1.C +++ /dev/null @@ -1,2137 +0,0 @@ -/* Reconstructed Commander Keen 4-6 Source Code - * Copyright (C) 2021 K1n9_Duk3 - * - * This file is loosely based on: - * Keen Dreams Source Code - * Copyright (C) 2014 Javier M. Chavez - * - * 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. - */ - -/* -K6_ACT1.C -========= - -Contains the following actor types (in this order): - -- some shared routines -- Bonus Items -- Grabbiter -- Rocket -- Grapple spots -- Satellite -- Quest Items (Sandwich, Grappling Hook, Passcard, Molly) -- Platforms -- falling platforms -- static platforms -- Goplat platforms -- Trick platforms -- Bloog -- Blooguard -- Blooglet - -*/ - -#include "CK_DEF.H" - -/* -============================================================================= - - SHARED STUFF - -============================================================================= -*/ - -Sint16 pdirx[] = {0, 1, 0, -1, 1, 1, -1, -1}; -Sint16 pdiry[] = {-1, 0, 1, 0, -1, 1, 1, -1}; - -/* -=========================== -= -= C_ClipSide -= -=========================== -*/ - -void C_ClipSide(objtype *ob, objtype *hit) -{ - if (hit->obclass == keenobj) - { - playerkludgeclipcancel = true; - ClipToSpriteSide(hit, ob); - playerkludgeclipcancel = false; - } -} - -/* -=========================== -= -= C_ClipTop -= -=========================== -*/ - -void C_ClipTop(objtype *ob, objtype *hit) -{ - if (hit->obclass == keenobj) - ClipToSpriteTop(hit, ob); -} - -/* -=========================== -= -= R_Land -= -=========================== -*/ - -void R_Land(objtype *ob) -{ - if (ob->hiteast || ob->hitwest) - ob->xspeed = 0; - - if (ob->hitsouth) - ob->yspeed = 0; - - if (ob->hitnorth) - { - ob->yspeed = 0; - if (ob->state->nextstate) - { - ChangeState(ob, ob->state->nextstate); - } - else - { - RemoveObj(ob); - return; - } - } - - RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority); -} - -/* -=========================== -= -= R_Bounce -= -=========================== -*/ - -void R_Bounce(objtype *ob) -{ - Uint16 wall,absx,absy,angle,newangle; - Uint32 speed; - - - RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority); - - if (ob->hiteast || ob->hitwest) - ob->xspeed = -ob->xspeed/2; - - if (ob->hitsouth) - { - ob->yspeed = -ob->yspeed/2; - return; - } - - wall = ob->hitnorth; -#ifdef KEEN6Ev15 - if (!wall) - { - return; - } - else -#else - if (wall) -#endif - { - if (ob->yspeed < 0) - ob->yspeed = 0; - - absx = abs(ob->xspeed); - absy = ob->yspeed; - if (absx>absy) - { - if (absx>absy*2) // 22 degrees - { - angle = 0; - speed = absx*286; // x*sqrt(5)/2 - } - else // 45 degrees - { - angle = 1; - speed = absx*362; // x*sqrt(2) - } - } - else - { - if (absy>absx*2) // 90 degrees - { - angle = 3; - speed = absy*256; - } - else - { - angle = 2; // 67 degrees - speed = absy*286; // y*sqrt(5)/2 - } - } - if (ob->xspeed > 0) - angle = 7-angle; - - speed >>= 1; - newangle = bounceangle[ob->hitnorth][angle]; - switch (newangle) - { - case 0: - ob->xspeed = speed / 286; - ob->yspeed = -ob->xspeed / 2; - break; - case 1: - ob->xspeed = speed / 362; - ob->yspeed = -ob->xspeed; - break; - case 2: - ob->yspeed = -(speed / 286); - ob->xspeed = -ob->yspeed / 2; - break; - case 3: - - case 4: - ob->xspeed = 0; - ob->yspeed = -(speed / 256); - break; - case 5: - ob->yspeed = -(speed / 286); - ob->xspeed = ob->yspeed / 2; - break; - case 6: - ob->xspeed = ob->yspeed = -(speed / 362); - break; - case 7: - ob->xspeed = -(speed / 286); - ob->yspeed = ob->xspeed / 2; - break; - - case 8: - ob->xspeed = -(speed / 286); - ob->yspeed = -ob->xspeed / 2; - break; - case 9: - ob->xspeed = -(speed / 362); - ob->yspeed = -ob->xspeed; - break; - case 10: - ob->yspeed = speed / 286; - ob->xspeed = -ob->yspeed / 2; - break; - case 11: - - case 12: - ob->xspeed = 0; - ob->yspeed = -(speed / 256); - break; - case 13: - ob->yspeed = speed / 286; - ob->xspeed = ob->yspeed / 2; - break; - case 14: - ob->xspeed = speed / 362; - ob->yspeed = speed / 362; - break; - case 15: - ob->xspeed = speed / 286; - ob->yspeed = ob->xspeed / 2; - break; - } - - if (speed < 256*16) - { - ChangeState(ob, ob->state->nextstate); - } - } -} - -/* -============================================================================= - - BONUS ITEMS - -temp1 = bonus type -temp2 = base shape number -temp3 = last animated shape number +1 - -============================================================================= -*/ - -statetype s_bonus1 = {0, 0, step, false, false, 20, 0, 0, T_Bonus, NULL, R_Draw, &s_bonus2}; -statetype s_bonus2 = {0, 0, step, false, false, 20, 0, 0, T_Bonus, NULL, R_Draw, &s_bonus1}; -statetype s_bonusfly1 = {0, 0, stepthink, false, false, 20, 0, 0, T_FlyBonus, NULL, R_Draw, &s_bonusfly2}; -statetype s_bonusfly2 = {0, 0, stepthink, false, false, 20, 0, 0, T_FlyBonus, NULL, R_Draw, &s_bonusfly1}; -statetype s_bonusrise = {0, 0, slide, false, false, 40, 0, 8, NULL, NULL, R_Draw, NULL}; - -statetype s_splash1 = {VIVASPLASH1SPR, VIVASPLASH1SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, &s_splash2}; -statetype s_splash2 = {VIVASPLASH2SPR, VIVASPLASH2SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, &s_splash3}; -statetype s_splash3 = {VIVASPLASH3SPR, VIVASPLASH3SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, &s_splash4}; -statetype s_splash4 = {VIVASPLASH4SPR, VIVASPLASH4SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, NULL}; - -Uint16 bonusshape[] = { - REDGEM1SPR, YELLOWGEM1SPR, BLUEGEM1SPR, GREENGEM1SPR, - SUGAR1ASPR, SUGAR2ASPR, SUGAR3ASPR, - SUGAR4ASPR, SUGAR5ASPR, SUGAR6ASPR, - ONEUPASPR, STUNCLIP1SPR -}; - -/* -=========================== -= -= SpawnBonus -= -=========================== -*/ - -void SpawnBonus(Uint16 tileX, Uint16 tileY, Uint16 type) -{ - GetNewObj(false); - new->needtoclip = cl_noclip; - new->priority = 2; - new->obclass = bonusobj; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY); - new->ydir = -1; - new->temp1 = type; - new->temp2=new->shapenum = bonusshape[type]; - new->temp3 = new->temp2+2; - NewState(new, &s_bonus1); -} - -/* -=========================== -= -= SpawnSplash -= -=========================== -*/ - -void SpawnSplash(Uint16 tileX, Uint16 tileY) -{ - GetNewObj(true); - new->needtoclip = cl_noclip; - new->priority = 3; - new->obclass = inertobj; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY); - NewState(new, &s_splash1); -} - -/* -=========================== -= -= T_Bonus -= -=========================== -*/ - -void T_Bonus(objtype *ob) -{ - if (++ob->shapenum == ob->temp3) - ob->shapenum = ob->temp2; -} - -/* -=========================== -= -= T_FlyBonus -= -=========================== -*/ - -void T_FlyBonus(objtype *ob) -{ - if (ob->hitnorth) - ob->state = &s_bonus1; - - if (++ob->shapenum == ob->temp3) - ob->shapenum = ob->temp2; - - DoGravity(ob); -} - -/* -============================================================================= - - GRABBITER - -============================================================================= -*/ - -statetype s_grabbiter1 = {GRABBITER1SPR, GRABBITER1SPR, step, false, false, 12, 0, 0, NULL, C_Grabbiter, R_Draw, &s_grabbiter2}; -statetype s_grabbiter2 = {GRABBITER2SPR, GRABBITER2SPR, step, false, false, 12, 0, 0, NULL, C_Grabbiter, R_Draw, &s_grabbiter1}; -statetype s_grabbitersleep1 = {GRABBITERSLEEP1SPR, GRABBITERSLEEP1SPR, step, false, false, 12, 0, 0, NULL, NULL, R_Draw, &s_grabbitersleep2}; -statetype s_grabbitersleep2 = {GRABBITERSLEEP2SPR, GRABBITERSLEEP2SPR, step, false, false, 12, 0, 0, NULL, NULL, R_Draw, &s_grabbitersleep1}; - -/* -=========================== -= -= SpawnGrabbiter -= -=========================== -*/ - -void SpawnGrabbiter(Uint16 tileX, Uint16 tileY) -{ - GetNewObj(false); - new->active = ac_yes; - new->needtoclip = cl_noclip; - new->priority = 2; - new->obclass = grabbiterobj; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY); - if (gamestate.sandwichstate == 2) - { - NewState(new, &s_grabbitersleep1); - } - else - { - NewState(new, &s_grabbiter1); - } -} - -/* -=========================== -= -= C_Grabbiter -= -=========================== -*/ - -void C_Grabbiter(objtype *ob, objtype *hit) -{ - // BUG: this is executed for every object, not just (Map-)Keen! - switch (gamestate.sandwichstate) - { - case 0: - CA_CacheGrChunk(KEENTALK1PIC); - SD_PlaySound(SND_GRABBITER); - VW_FixRefreshBuffer(); - US_CenterWindow(26, 8); - VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC); - WindowW -= 48; - PrintY += 5; - US_CPrint( - "Oh, no!\n" - "It's a slavering\n" - "Grabbiter! He says,\n" - "\"Get me lunch and\n" - "I'll tell ya a secret!\"" - ); - VW_UpdateScreen(); - SD_PlaySound(SND_NOWAY); - VW_WaitVBL(30); - IN_ClearKeysDown(); - IN_Ack(); - RF_ForceRefresh(); - - //push Keen back - xtry = -hit->xmove; - ytry = -hit->ymove; - hit->xdir = hit->ydir = 0; - ClipToWalls(hit); - break; - - case 1: - gamestate.sandwichstate++; - CA_CacheGrChunk(KEENTALK1PIC); - VW_FixRefreshBuffer(); - US_CenterWindow(26, 8); - VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC); - WindowW -= 48; - PrintY += 2; - US_CPrint( - "The Grabbiter grabs\n" - "the gigantic sandwich,\n" - "downs it in one bite,\n" - "and says,\"Here's your\n" - "secret. Big meals\n" - "make me sleepy!\n" // BUG: quote is missing at the end - ); - VW_UpdateScreen(); - VW_WaitVBL(30); - IN_ClearKeysDown(); - IN_Ack(); - ChangeState(ob, &s_grabbitersleep1); - RF_ForceRefresh(); - } -} - -/* -============================================================================= - - ROCKET - -temp1 = direction -temp2 = countdown to next dir check - -============================================================================= -*/ - -statetype s_rocket = {ROCKETSPR, ROCKETSPR, think, false, false, 0, 0, 0, NULL, C_Rocket, R_Draw, NULL}; -statetype s_rocketfly1 = {ROCKETFLY1SPR, ROCKETFLY1SPR, stepthink, false, false, 8, 0, 0, T_RocketFly, C_RocketFly, R_Draw, &s_rocketfly2}; -statetype s_rocketfly2 = {ROCKETFLY2SPR, ROCKETFLY2SPR, stepthink, false, false, 8, 0, 0, T_RocketFly, C_RocketFly, R_Draw, &s_rocketfly1}; -statetype s_keenrocket = {0, 0, think, false, false, 0, 0, 0, T_Rocket, NULL, R_Draw, NULL}; - -/* -=========================== -= -= SpawnRocket -= -=========================== -*/ - -void SpawnRocket(Uint16 tileX, Uint16 tileY, Uint16 state) -{ - if (gamestate.rocketstate == state) - { - GetNewObj(false); - new->active = ac_yes; - new->needtoclip = cl_noclip; - new->priority = 3; - new->obclass = rocketobj; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY); - NewState(new, &s_rocket); - } -} - -/* -=========================== -= -= T_Rocket -= -=========================== -*/ - -void T_Rocket(objtype *ob) -{ - ob->needtoreact = true; -} - -/* -=========================== -= -= C_Rocket -= -=========================== -*/ - -void C_Rocket(objtype *ob, objtype *hit) -{ - // BUG: this is executed for every object, not just (Map-)Keen! - switch (gamestate.passcardstate) - { - case 0: - CA_CacheGrChunk(KEENTALK1PIC); - VW_FixRefreshBuffer(); - US_CenterWindow(26, 8); - VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC); - WindowW -= 48; - PrintY += 5; - US_CPrint( - "The door makes a loud\n" - "blooping noise.\n" - "It says,\n" - "\"Passcard required\n" - "for entry.\"" - ); - VW_UpdateScreen(); - SD_PlaySound(SND_NOWAY); - VW_WaitVBL(30); - IN_ClearKeysDown(); - IN_Ack(); - RF_ForceRefresh(); - - //push Keen back - xtry = -hit->xmove; - ytry = -hit->ymove; - hit->xdir = hit->ydir = 0; - ClipToWalls(hit); - break; - - case 1: - ob->temp1 = arrow_North; - ob->temp2 = TILEGLOBAL; - ChangeState(ob, &s_rocketfly1); - - hit->x = ob->x; - hit->y = ob->y + TILEGLOBAL; - hit->needtoclip = cl_noclip; - ChangeState(hit, &s_keenrocket); - SD_PlaySound(SND_ROCKETSTART); - SD_WaitSoundDone(); - } -} - -/* -=========================== -= -= C_RocketFly -= -=========================== -*/ - -void C_RocketFly(objtype *ob, objtype *hit) -{ - if (hit->obclass == keenobj) - { - hit->x = ob->x; - hit->y = ob->y+TILEGLOBAL; - ChangeState(hit, hit->state); - } -} - -/* -=========================== -= -= T_RocketFly -= -=========================== -*/ - -void T_RocketFly(objtype *ob) -{ - Uint16 move, tx, ty; - Sint16 dir; - - // - // this code could be executed twice during the same frame because the - // object's animation/state changed during that frame, so don't update - // anything if we already have movement for the current frame i.e. the - // update code has already been executed this frame - // - if (xtry == 0 && ytry == 0) - { - if (!SD_SoundPlaying()) - SD_PlaySound(SND_ROCKETFLY); - - move = tics << 5; - if (ob->temp2 > move) - { - ob->temp2 = ob->temp2 - move; - dir = pdirx[ob->temp1]; - if (dir == 1) - { - xtry = move; - } - else if (dir == -1) - { - xtry = -move; - } - dir = pdiry[ob->temp1]; - if (dir == 1) - { - ytry = move; - - } - else if (dir == -1) - { - ytry = -move; - } - } - else - { - dir = pdirx[ob->temp1]; - if (dir == 1) - { - xtry = ob->temp2; - } - else if (dir == -1) - { - xtry = -ob->temp2; - } - dir = pdiry[ob->temp1]; - if (dir == 1) - { - ytry = ob->temp2; - } - else if (dir == -1) - { - ytry = -ob->temp2; - } - - tx = CONVERT_GLOBAL_TO_TILE(ob->x + xtry); - ty = CONVERT_GLOBAL_TO_TILE(ob->y + ytry); - ob->temp1 = *(mapsegs[2]+mapbwidthtable[ty]/2 + tx)-DIRARROWSTART; - if (ob->temp1 < arrow_North || ob->temp1 > arrow_None) - { - ob->x += xtry; - ob->y += ytry; - ChangeState(ob, &s_rocket); - - player->x = CONVERT_TILE_TO_GLOBAL(tx+1) + 1*PIXGLOBAL; - player->y = CONVERT_TILE_TO_GLOBAL(ty+1); - player->obclass = keenobj; - player->shapenum = WORLDKEENR3SPR; - player->needtoclip = cl_midclip; - NewState(player, &s_worldkeen); - gamestate.rocketstate ^= 1; - } - else - { - move -= ob->temp2; - ob->temp2 = TILEGLOBAL - move; - dir = pdirx[ob->temp1]; - if (dir == 1) - { - xtry = xtry + move; - } - else if (dir == -1) - { - xtry = xtry - move; - } - dir = pdiry[ob->temp1]; - if (dir == 1) - { - ytry = ytry + move; - } - else if (dir == -1) - { - ytry = ytry - move; - } - } - } - } -} - -/* -============================================================================= - - GRAPPLE SPOT - -temp1 = type (0 = top of cliff, 1 = bottom of cliff) - -============================================================================= -*/ - -statetype s_grapplespot = {-1, -1, think, false, false, 0, 0, 0, NULL, C_GrappleSpot, R_Draw, NULL}; -statetype s_throwrope1 = {WORLDKEENTRHOW1SPR, WORLDKEENTRHOW1SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_throwrope2}; -statetype s_throwrope2 = {WORLDKEENTRHOW2SPR, WORLDKEENTRHOW2SPR, step, false, false, 8, 0, 0, T_ThrowRope, NULL, R_Draw, &s_worldkeen}; -statetype s_climbrope1 = {WORLDKEENCLIMB1SPR, WORLDKEENCLIMB1SPR, slide, true, false, 4, 0, 16, NULL, NULL, R_Draw, &s_climbrope2}; -statetype s_climbrope2 = {WORLDKEENCLIMB2SPR, WORLDKEENCLIMB2SPR, slide, true, false, 4, 0, 16, T_ClimbRope, NULL, R_Draw, &s_climbrope1}; -statetype s_maprope = {ROPETHROW2SPR, ROPETHROW2SPR, think, false, false, 0, 0, 0, NULL, NULL, R_Draw, NULL}; -statetype s_mapropeshort = {ROPETHROW1SPR, ROPETHROW1SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_mapropeshort}; - -/* -=========================== -= -= SpawnGrappleSpot -= -=========================== -*/ - -void SpawnGrappleSpot(Uint16 tileX, Uint16 tileY, Uint16 type) -{ - GetNewObj(false); - new->active = ac_yes; - new->needtoclip = cl_noclip; - new->priority = 2; - new->obclass = grapplespotobj; - new->tileleft = new->tileright = tileX; - new->tiletop = new->tilebottom = tileY; - new->temp1 = type; - new->x = new->left = CONVERT_TILE_TO_GLOBAL(tileX); - new->right = new->left + TILEGLOBAL; - if (type) - { - new->y = new->top = CONVERT_TILE_TO_GLOBAL(tileY+1)-1; - } - else - { - new->y = new->top = CONVERT_TILE_TO_GLOBAL(tileY); - } - new->bottom = new->top + 1; - NewState(new, &s_grapplespot); - - if (gamestate.hookstate == 2 && type) - { - GetNewObj(false); - new->active = ac_yes; - new->needtoclip = cl_noclip; - new->priority = 0; - new->obclass = inertobj; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY+1); - NewState(new, &s_maprope); - } -} - -/* -=========================== -= -= T_ThrowRope -= -=========================== -*/ - -void T_ThrowRope(objtype *ob) -{ - GetNewObj(false); - new->active = ac_yes; - new->needtoclip = cl_noclip; - new->priority = 0; - new->obclass = inertobj; - new->x = CONVERT_TILE_TO_GLOBAL(ob->tileright); - new->y = ob->y - 2*TILEGLOBAL; - NewState(new, &s_maprope); - - ob->obclass = keenobj; - ob->shapenum = WORLDKEENU3SPR; -} - -/* -=========================== -= -= T_ClimbRope -= -=========================== -*/ - -void T_ClimbRope(objtype *ob) -{ - if (--ob->temp4 == 0) - { - if (ob->ydir == 1) - { - ob->y += 3*PIXGLOBAL; - ob->shapenum = WORLDKEEND3SPR; - } - else - { - ob->y -= 3*PIXGLOBAL; - ob->shapenum = WORLDKEENU3SPR; - } - ob->obclass = keenobj; - NewState(ob, &s_worldkeen); - } -} - -/* -=========================== -= -= C_GrappleSpot -= -=========================== -*/ - -void C_GrappleSpot(objtype *ob, objtype *hit) -{ - if (hit->obclass == keenobj) - { - switch (gamestate.hookstate) - { - case 0: - CA_CacheGrChunk(KEENTALK1PIC); - VW_FixRefreshBuffer(); - US_CenterWindow(26, 8); - VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC); - WindowW -= 48; - PrintY += 15; - US_CPrint( - "What a tall cliff!\n" - "Wish I had a rope\n" - "and grappling hook.\n" - ); - VW_UpdateScreen(); - SD_PlaySound(SND_NOWAY); - VW_WaitVBL(30); - IN_ClearKeysDown(); - IN_Ack(); - RF_ForceRefresh(); - - //push Keen back - xtry = -hit->xmove; - ytry = -hit->ymove; - hit->xdir = hit->ydir = 0; - ClipToWalls(hit); - break; - - case 1: - gamestate.hookstate++; - SD_PlaySound(SND_THROWROPE); - ChangeState(hit, &s_throwrope1); - hit->obclass = inertobj; - break; - - case 2: - if (ob->temp1) - { - hit->y += 4*PIXGLOBAL; - hit->temp4 = 6; - hit->ydir = 1; - } - else - { - hit->y -= 4*PIXGLOBAL; - hit->temp4 = 6; - hit->ydir = -1; - } - NewState(hit, &s_climbrope1); - hit->obclass = inertobj; - } - } -} - -/* -============================================================================= - - SATELLITE - -temp1 = direction (satellite) / type (stop points) -temp2 = countdown to next dir check -temp3 = type of stop point touched (low byte: current; high byte: previous) - is updated every frame and resets to 0 when no longer touching a spot -temp4 = type of last stop point passed over (1 or 2, never 0) - is updated when no longer touching the spot - -============================================================================= -*/ - -statetype s_satellitestopspot = {-1, -1, think, false, false, 0, 0, 0, NULL, NULL, NULL, NULL}; -statetype s_worldkeensatellite = {WORLDKEENHANGSPR, WORLDKEENHANGSPR, think, false, false, 0, 0, 0, NULL, NULL, R_WorldKeenSatellite, NULL}; -statetype s_satellite1 = {SATELLITE1SPR, SATELLITE1SPR, stepthink, false, false, 10, 0, 0, T_Satellite, C_Satellite, R_Draw, &s_satellite2}; -statetype s_satellite2 = {SATELLITE2SPR, SATELLITE2SPR, stepthink, false, false, 10, 0, 0, T_Satellite, C_Satellite, R_Draw, &s_satellite3}; -statetype s_satellite3 = {SATELLITE3SPR, SATELLITE3SPR, stepthink, false, false, 10, 0, 0, T_Satellite, C_Satellite, R_Draw, &s_satellite4}; -statetype s_satellite4 = {SATELLITE4SPR, SATELLITE4SPR, stepthink, false, false, 10, 0, 0, T_Satellite, C_Satellite, R_Draw, &s_satellite1}; - -/* -=========================== -= -= SpawnSatelliteStop -= -=========================== -*/ - -void SpawnSatelliteStop(Uint16 tileX, Uint16 tileY, Uint16 type) -{ - GetNewObj(false); - new->active = ac_allways; - new->needtoclip = cl_noclip; - new->priority = 2; - new->obclass = satellitestopobj; - new->tileleft=new->tileright=tileX; - new->tiletop=new->tilebottom=tileY; - new->temp1 = (type ^ 1) + 1; // type is either 0 or 1, so this just maps 0 to 2 and 1 to 1 - new->x=new->left = CONVERT_TILE_TO_GLOBAL(tileX); - new->right = new->left + TILEGLOBAL; - new->y=new->top = CONVERT_TILE_TO_GLOBAL(tileY); - new->bottom = new->top + TILEGLOBAL; - NewState(new, &s_satellitestopspot); -} - -/* -=========================== -= -= SpawnSatellite -= -=========================== -*/ - -void SpawnSatellite(Uint16 tileX, Uint16 tileY) -{ - Sint16 dir; - - GetNewObj(false); - new->needtoclip = cl_noclip; - new->priority = 2; - new->active = ac_allways; - new->obclass = satelliteobj; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY); - new->xdir = 0; - new->ydir = 1; - NewState(new, &s_satellite1); - - dir = arrow_West; - (mapsegs[2]+mapbwidthtable[tileY]/2)[tileX] = (dir+DIRARROWSTART); - new->temp1 = dir; - new->temp2 = TILEGLOBAL; - new->temp4 = 2; -} - -/* -=========================== -= -= T_Satellite -= -=========================== -*/ - -void T_Satellite(objtype *ob) -{ - // - // this code could be executed twice during the same frame because the - // object's animation/state changed during that frame, so don't update - // anything if we already have movement for the current frame i.e. the - // update code has already been executed this frame - // - if (xtry == 0 && ytry == 0) - { - // - // if current stop spot type is 0 (not touching a spot), but previous - // type is not 0, then set temp4 to the previous type - // - if (!(ob->temp3 & 0xFF) && (ob->temp3 & 0xFF00)) - { - ob->temp4 = ob->temp3 >> 8; - } - // - // move current type into previous type and set current stop type to 0 - // - ob->temp3 <<= 8; - - // - // follow the arrow path like a GoPlat - // - T_GoPlat(ob); - } -} - -/* -=========================== -= -= C_Satellite -= -=========================== -*/ - -void C_Satellite(objtype *ob, objtype *hit) -{ - Sint16 temp; - objtype *o; - - if (hit->state == &s_satellitestopspot) - { - ob->temp3 |= hit->temp1; - } - else if (hit->obclass == keenobj) - { - // - // check if satellite has reaced a new stop spot - // - temp = ob->temp3 >> 8; - if (temp && temp != ob->temp4) - { - SD_PlaySound(SND_GRABSATELLITE); - // - // update last spot value (don't grab or drop Keen until moved to the next spot) - // - ob->temp4 = temp; - if (player->state == &s_worldkeensatellite) - { - // - // drop Keen off at the current stop spot - // - for (o=player->next; o; o=o->next) - { - if (o->obclass == satellitestopobj && o->temp1 == temp) - { - hit->x = o->x; - hit->y = o->y; - hit->shapenum = WORLDKEENU3SPR; - ChangeState(player, &s_worldkeen); - hit->needtoclip = cl_midclip; - return; - } - } - } - else - { - // - // grab and carry Keen - // - hit->x = ob->x + 12*PIXGLOBAL; - hit->y = ob->y + 16*PIXGLOBAL; - hit->needtoclip = cl_noclip; - ChangeState(player, &s_worldkeensatellite); - } - } - else if (hit->state == &s_worldkeensatellite) - { - // - // move Keen along with the satellite - // - hit->x = ob->x + 12*PIXGLOBAL; - hit->y = ob->y + 16*PIXGLOBAL; - ChangeState(hit, hit->state); - } - } -} - -/* -=========================== -= -= R_WorldKeenSatellite -= -=========================== -*/ - -void R_WorldKeenSatellite(objtype *ob) -{ - RF_PlaceSprite(&ob->sprite, ob->x + 4*PIXGLOBAL, ob->y + 8*PIXGLOBAL, WORLDKEENHANGSPR, spritedraw, 1); -} - -/* -============================================================================= - - SANDWICH - -============================================================================= -*/ - -statetype s_sandwich = {SANDWICHSPR, SANDWICHSPR, think, false, false, 0, 0, 0, NULL, C_Molly, R_Draw, NULL}; - -/* -=========================== -= -= SpawnSandwich -= -=========================== -*/ - -void SpawnSandwich(Uint16 tileX, Uint16 tileY) -{ - GetNewObj(false); - new->needtoclip = cl_noclip; - new->priority = 2; - new->obclass = sandwichobj; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY); - NewState(new, &s_sandwich); -} - -/* -============================================================================= - - GRAPPLING HOOK - -============================================================================= -*/ - -statetype s_hook = {HOOKSPR, HOOKSPR, think, false, false, 0, 0, 0, NULL, C_Molly, R_Draw, NULL}; - -/* -=========================== -= -= SpawnHook -= -=========================== -*/ - -void SpawnHook(Uint16 tileX, Uint16 tileY) -{ - GetNewObj(false); - new->needtoclip = cl_noclip; - new->priority = 2; - new->obclass = hookobj; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY); - NewState(new, &s_hook); -} - -/* -============================================================================= - - PASSCARD - -============================================================================= -*/ - -statetype s_passcard = {PASSCARDSPR, PASSCARDSPR, think, false, false, 0, 0, 0, NULL, C_Molly, R_Draw, NULL}; - -/* -=========================== -= -= SpawnPasscard -= -=========================== -*/ - -void SpawnPasscard(Uint16 tileX, Uint16 tileY) -{ - GetNewObj(false); - new->needtoclip = cl_noclip; - new->priority = 2; - new->obclass = passcardobj; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY); - NewState(new, &s_passcard); -} - -//============================================================================ - -/* -=========================== -= -= C_Molly -= -=========================== -*/ - -void C_Molly(objtype *ob, objtype *hit) -{ - if (hit->obclass == keenobj) - { - switch (ob->obclass) - { - case sandwichobj: - playstate = ex_sandwich; - break; - - case hookobj: - playstate = ex_hook; - break; - - case passcardobj: - playstate = ex_card; - break; - - case mollyobj: - playstate = ex_molly; - } - } -} - -/* -============================================================================= - - MOLLY - -============================================================================= -*/ - -statetype s_molly1 = {MOLLY1SPR, MOLLY1SPR, step, false, false, 20, 0, 0, NULL, C_Molly, R_Draw, &s_molly2}; -statetype s_molly2 = {MOLLY2SPR, MOLLY2SPR, step, false, false, 40, 0, 0, NULL, C_Molly, R_Draw, &s_molly3}; -statetype s_molly3 = {MOLLY1SPR, MOLLY1SPR, step, false, false, 40, 0, 0, NULL, C_Molly, R_Draw, &s_molly4}; -statetype s_molly4 = {MOLLY2SPR, MOLLY2SPR, step, false, false, 20, 0, 0, NULL, C_Molly, R_Draw, &s_molly1}; - -/* -=========================== -= -= SpawnMolly -= -=========================== -*/ - -void SpawnMolly(Uint16 tileX, Uint16 tileY) -{ - GetNewObj(false); - new->obclass = mollyobj; - new->active = ac_yes; - new->priority = 0; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -8*PIXGLOBAL; - if (US_RndT() < 0x80) - { - new->xdir = 1; - } - else - { - new->xdir = -1; - } - new->ydir = 1; - NewState(new, &s_molly1); -} - -/* -============================================================================= - - PLATFORM - -============================================================================= -*/ - -statetype s_platform = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_Platform, NULL, R_Draw, NULL}; - -/* -=========================== -= -= SpawnPlatform -= -=========================== -*/ - -void SpawnPlatform(Uint16 tileX, Uint16 tileY, Sint16 dir) -{ - GetNewObj(false); - new->obclass = platformobj; - new->active = ac_allways; - new->priority = 0; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY); - switch (dir) - { - case 0: - new->xdir = 0; - new->ydir = -1; - break; - case 1: - new->xdir = 1; - new->ydir = 0; - break; - case 2: - new->xdir = 0; - new->ydir = 1; - break; - case 3: - new->xdir = -1; - new->ydir = 0; - } - NewState(new, &s_platform); -} - -/* -=========================== -= -= T_Platform -= -=========================== -*/ - -void T_Platform(objtype *ob) -{ - Uint16 newpos, newtile; - - xtry = ob->xdir * 12 * tics; - ytry = ob->ydir * 12 * tics; - - if (ob->xdir == 1) - { - newpos = ob->right + xtry; - newtile = CONVERT_GLOBAL_TO_TILE(newpos); - if (ob->tileright != newtile) - { - if (*(mapsegs[2]+mapbwidthtable[ob->tiletop]/2 + newtile) == PLATFORMBLOCK) - { - ob->xdir = -1; - xtry = xtry - (newpos & 0xFF); - } - } - } - else if (ob->xdir == -1) - { - newpos = ob->left + xtry; - newtile = CONVERT_GLOBAL_TO_TILE(newpos); - if (ob->tileleft != newtile) - { - if (*(mapsegs[2]+mapbwidthtable[ob->tiletop]/2 + newtile) == PLATFORMBLOCK) - { - ob->xdir = 1; - xtry = xtry + (TILEGLOBAL - (newpos & 0xFF)); - } - } - } - else if (ob->ydir == 1) - { - newpos = ob->bottom + ytry; - newtile = CONVERT_GLOBAL_TO_TILE(newpos); - if (ob->tilebottom != newtile) - { - if (*(mapsegs[2]+mapbwidthtable[newtile]/2 + ob->tileleft) == PLATFORMBLOCK) - { - if (*(mapsegs[2]+mapbwidthtable[newtile-2]/2 + ob->tileleft) == PLATFORMBLOCK) - { - ytry = 0; - ob->needtoreact = true; - } - else - { - ob->ydir = -1; - ytry = ytry - (newpos & 0xFF); - } - } - } - } - else if (ob->ydir == -1) - { - newpos = ob->top + ytry; - newtile = CONVERT_GLOBAL_TO_TILE(newpos); - if (ob->tiletop != newtile) - { - if (*(mapsegs[2]+mapbwidthtable[newtile]/2 + ob->tileleft) == PLATFORMBLOCK) - { - if (*(mapsegs[2]+mapbwidthtable[newtile+2]/2 + ob->tileleft) == PLATFORMBLOCK) - { - ytry = 0; - ob->needtoreact = true; - } - else - { - ob->ydir = 1; - ytry = ytry + (TILEGLOBAL - (newpos & 0xFF)); - } - } - } - } -} - -/* -============================================================================= - - DROPPING PLATFORM - -temp1 = initial y position - -============================================================================= -*/ - -statetype s_dropplatsit = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_DropPlatSit, NULL, R_Draw, NULL}; -statetype s_fallplatfall = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_DropPlatFall, NULL, R_Draw, NULL}; -statetype s_fallplatrise = {PLATFORMSPR, PLATFORMSPR, slidethink, false, false, 0, 0, -32, T_DropPlatRise, NULL, R_Draw, NULL}; - -/* -=========================== -= -= SpawnDropPlat -= -=========================== -*/ - -void SpawnDropPlat(Uint16 tileX, Uint16 tileY) -{ - GetNewObj(false); - new->obclass = platformobj; - new->active = ac_allways; - new->priority = 0; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y=new->temp1 = CONVERT_TILE_TO_GLOBAL(tileY); - new->xdir = 0; - new->ydir = 1; - new->needtoclip = cl_noclip; - NewState(new, &s_dropplatsit); -} - -/* -=========================== -= -= T_DropPlatSit -= -=========================== -*/ - -void T_DropPlatSit(objtype *ob) -{ - if (gamestate.riding == ob) - { - ytry = tics << 4; //tics * 16; - ob->yspeed = 0; - if (ob->y + ytry - ob->temp1 >= 8*PIXGLOBAL) - ob->state = &s_fallplatfall; - } -} - -/* -=========================== -= -= T_DropPlatFall -= -=========================== -*/ - -void T_DropPlatFall(objtype *ob) -{ - Uint16 newpos, newtile; - - DoGravity(ob); - -#if 0 - // bugfix: don't skip a tile (this is present in Keen 4, but missing in 5 & 6) - if (ytry >= 15*PIXGLOBAL) - ytry = 15*PIXGLOBAL; -#endif - - newpos = ob->bottom + ytry; - newtile = CONVERT_GLOBAL_TO_TILE(newpos); - if (ob->tilebottom != newtile) - { - if (*(mapsegs[2]+mapbwidthtable[newtile]/2 + ob->tileleft) == PLATFORMBLOCK) - { - ytry = 0xFF - (ob->bottom & 0xFF); - if (gamestate.riding != ob) - ob->state = &s_fallplatrise; - } - } -} - -/* -=========================== -= -= T_DropPlatRise -= -=========================== -*/ - -void T_DropPlatRise(objtype *ob) -{ - if (gamestate.riding == ob) - { - ob->yspeed = 0; - ob->state = &s_fallplatfall; - } - else if (ob->y <= ob->temp1) - { - ytry = ob->temp1 - ob->y; - ob->state = &s_dropplatsit; - } -} - -/* -============================================================================= - - STATIC PLATFORM - -temp1 = initial y position (is set but never used) - -============================================================================= -*/ - -statetype s_staticplatform = {PLATFORMSPR, PLATFORMSPR, step, false, false, 32000, 0, 0, NULL, NULL, R_Draw, &s_staticplatform}; - -/* -=========================== -= -= SpawnStaticPlat -= -=========================== -*/ - -void SpawnStaticPlat(Uint16 tileX, Uint16 tileY) -{ - GetNewObj(false); - new->obclass = platformobj; - new->active = ac_yes; - new->priority = 0; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y=new->temp1 = CONVERT_TILE_TO_GLOBAL(tileY); - new->xdir = 0; - new->ydir = 1; - new->needtoclip = cl_noclip; - NewState(new, &s_staticplatform); -} - -/* -============================================================================= - - GO PLATFORM - -temp1 = direction -temp2 = countdown to next dir check -temp3 = sprite pointer for the Bip sprite - -============================================================================= -*/ - -statetype s_goplat = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_GoPlat, NULL, R_GoPlat, NULL}; - -/* -=========================== -= -= SpawnGoPlat -= -=========================== -*/ - -void SpawnGoPlat(Uint16 tileX, Uint16 tileY, Sint16 dir) -{ - GetNewObj(false); - new->obclass = platformobj; - new->active = ac_allways; - new->priority = 0; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY); - new->xdir = 0; - new->ydir = 1; - new->needtoclip = cl_noclip; - NewState(new, &s_goplat); - *(mapsegs[2]+mapbwidthtable[tileY]/2 + tileX) = dir + DIRARROWSTART; - new->temp1 = dir; - new->temp2 = TILEGLOBAL; -} - -/* -=========================== -= -= T_GoPlat -= -=========================== -*/ - -void T_GoPlat(objtype *ob) -{ - Uint16 move; - Sint16 dir; - Uint16 tx, ty; - - move = tics * 12; - if (ob->temp2 > move) - { - ob->temp2 = ob->temp2 - move; - - dir = pdirx[ob->temp1]; - if (dir == 1) - { - xtry = xtry + move; - } - else if (dir == -1) - { - xtry = xtry + -move; - } - - dir = pdiry[ob->temp1]; - if (dir == 1) - { - ytry = ytry + move; - } - else if (dir == -1) - { - ytry = ytry + -move; - } - } - else - { - dir = pdirx[ob->temp1]; - if (dir == 1) - { - xtry += ob->temp2; - } - else if (dir == -1) - { - xtry += -ob->temp2; - } - - dir = pdiry[ob->temp1]; - if (dir == 1) - { - ytry += ob->temp2; - } - else if (dir == -1) - { - ytry += -ob->temp2; - } - - tx = CONVERT_GLOBAL_TO_TILE(ob->x + xtry); - ty = CONVERT_GLOBAL_TO_TILE(ob->y + ytry); - ob->temp1 = *(mapsegs[2]+mapbwidthtable[ty]/2 + tx) - DIRARROWSTART; - if (ob->temp1 < arrow_North || ob->temp1 > arrow_None) - { - Quit("Goplat moved to a bad spot!"); - } - - move -= ob->temp2; - ob->temp2 = TILEGLOBAL - move; - - dir = pdirx[ob->temp1]; - if (dir == 1) - { - xtry = xtry + move; - } - else if (dir == -1) - { - xtry = xtry - move; - } - - dir = pdiry[ob->temp1]; - if (dir == 1) - { - ytry = ytry + move; - } - else if (dir == -1) - { - ytry = ytry - move; - } - } -} - -/* -=========================== -= -= R_GoPlat -= -=========================== -*/ - -void R_GoPlat(objtype *ob) -{ - RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority); - RF_PlaceSprite((void**)&ob->temp3, ob->x+TILEGLOBAL, ob->y+TILEGLOBAL, ob->temp1+PLATBIP1SPR, spritedraw, ob->priority); -} - -/* -============================================================================= - - SNEAKY PLATFORM - -temp1 = initial x position (is set but never used) - -============================================================================= -*/ - -statetype s_sneakplatsit = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_SneakPlat, NULL, R_Draw, NULL}; -statetype s_sneakplatdodge = {PLATFORMSPR, PLATFORMSPR, slide, false, false, 48, 32, 0, NULL, NULL, R_Draw, &s_sneakplatreturn}; -statetype s_sneakplatreturn = {PLATFORMSPR, PLATFORMSPR, slide, false, false, 96, -16, 0, NULL, NULL, R_Draw, &s_sneakplatsit}; - -/* -=========================== -= -= SpawnSneakPlat -= -=========================== -*/ - -void SpawnSneakPlat(Uint16 tileX, Uint16 tileY) -{ - GetNewObj(false); - new->obclass = platformobj; - new->active = ac_allways; - new->priority = 0; - new->x=new->temp1 = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY); - new->xdir = 0; - new->ydir = 1; - new->needtoclip = cl_noclip; - NewState(new, &s_sneakplatsit); -} - -/* -=========================== -= -= T_SneakPlat -= -=========================== -*/ - -void T_SneakPlat(objtype *ob) -{ - Sint16 dist; - - if (player->state != &s_keenjump1) - return; - - if (player->xdir == 1) - { - dist = ob->left-player->right; - if (dist > 4*TILEGLOBAL || dist < 0) - return; - } - else - { - dist = player->left-ob->right; - if (dist > 4*TILEGLOBAL || dist < 0) - return; - } - - dist = player->y - ob->y; - if (dist < -6*TILEGLOBAL || dist > 6*TILEGLOBAL) - return; - - ob->xdir = player->xdir; - ob->state = &s_sneakplatdodge; -} - -/* -============================================================================= - - BLOOG - -============================================================================= -*/ - -statetype s_bloogwalk1 = {BLOOGWALKL1SPR, BLOOGWALKR1SPR, step, false, true, 10, 128, 0, T_BloogWalk, C_Bloog, R_Walk, &s_bloogwalk2}; -statetype s_bloogwalk2 = {BLOOGWALKL2SPR, BLOOGWALKR2SPR, step, false, true, 10, 128, 0, T_BloogWalk, C_Bloog, R_Walk, &s_bloogwalk3}; -statetype s_bloogwalk3 = {BLOOGWALKL3SPR, BLOOGWALKR3SPR, step, false, true, 10, 128, 0, T_BloogWalk, C_Bloog, R_Walk, &s_bloogwalk4}; -statetype s_bloogwalk4 = {BLOOGWALKL4SPR, BLOOGWALKR4SPR, step, false, true, 10, 128, 0, T_BloogWalk, C_Bloog, R_Walk, &s_bloogwalk1}; -statetype s_bloogstun = {BLOOGSTUNSPR, BLOOGSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, &s_bloogstun}; - -/* -=========================== -= -= SpawnBloog -= -=========================== -*/ - -void SpawnBloog(Uint16 tileX, Uint16 tileY) -{ - GetNewObj(false); - new->obclass = bloogobj; - new->active = ac_yes; - new->priority = 0; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -2*TILEGLOBAL; - if (US_RndT() < 0x80) - { - new->xdir = 1; - } - else - { - new->xdir = -1; - } - new->ydir = 1; - NewState(new, &s_bloogwalk1); -} - -/* -=========================== -= -= T_BloogWalk -= -=========================== -*/ - -void T_BloogWalk(objtype *ob) -{ - if (US_RndT() < 0x20) - { - if (ob->x < player->x) - { - ob->xdir = 1; - } - else - { - ob->xdir = -1; - } - } -} - -/* -=========================== -= -= C_Bloog -= -=========================== -*/ - -void C_Bloog(objtype *ob, objtype *hit) -{ - if (hit->obclass == keenobj) - { - KillKeen(); - } - else if (hit->obclass == stunshotobj) - { - StunObj(ob, hit, &s_bloogstun); - } -} - -/* -============================================================================= - - BLOOGUARD - -temp1 = flash countdown -temp2 = health - -============================================================================= -*/ - -statetype s_blooguardwalk1 = {BLOOGUARDWALKL1SPR, BLOOGUARDWALKR1SPR, step, false, true, 9, 128, 0, T_BlooguardWalk, C_Blooguard, R_Blooguard, &s_blooguardwalk2}; -statetype s_blooguardwalk2 = {BLOOGUARDWALKL2SPR, BLOOGUARDWALKR2SPR, step, false, true, 9, 128, 0, T_BlooguardWalk, C_Blooguard, R_Blooguard, &s_blooguardwalk3}; -statetype s_blooguardwalk3 = {BLOOGUARDWALKL3SPR, BLOOGUARDWALKR3SPR, step, false, true, 9, 128, 0, T_BlooguardWalk, C_Blooguard, R_Blooguard, &s_blooguardwalk4}; -statetype s_blooguardwalk4 = {BLOOGUARDWALKL4SPR, BLOOGUARDWALKR4SPR, step, false, true, 9, 128, 0, T_BlooguardWalk, C_Blooguard, R_Blooguard, &s_blooguardwalk1}; -statetype s_blooguardattack1 = {BLOOGUARDSWINGL1SPR, BLOOGUARDSWINGR1SPR, step, false, true, 30, 0, 0, NULL, C_Blooguard, R_Blooguard, &s_blooguardattack2}; -statetype s_blooguardattack2 = {BLOOGUARDSWINGL2SPR, BLOOGUARDSWINGR2SPR, step, false, true, 9, 0, 0, NULL, C_Blooguard, R_Blooguard, &s_blooguardattack3}; -statetype s_blooguardattack3 = {BLOOGUARDSWINGL3SPR, BLOOGUARDSWINGR3SPR, step, true, true, 1, 0, 0, T_BlooguardAttack, C_Blooguard, R_Blooguard, &s_blooguardattack4}; -statetype s_blooguardattack4 = {BLOOGUARDSWINGL3SPR, BLOOGUARDSWINGR3SPR, step, false, true, 9, 0, 0, NULL, C_Blooguard, R_Blooguard, &s_blooguardwalk1}; -statetype s_blooguardstun = {BLOOGUARDSTUNSPR, BLOOGUARDSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, &s_blooguardstun}; - -/* -=========================== -= -= SpawnBlooguard -= -=========================== -*/ - -void SpawnBlooguard(Uint16 tileX, Uint16 tileY) -{ - GetNewObj(false); - new->obclass = blooguardobj; - new->active = ac_yes; - new->priority = 0; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -40*PIXGLOBAL; - if (US_RndT() < 0x80) - { - new->xdir = 1; - } - else - { - new->xdir = -1; - } - new->ydir = 1; - new->temp2 = 3; // health - NewState(new, &s_blooguardwalk1); -} - -/* -=========================== -= -= T_BlooguardWalk -= -=========================== -*/ - -void T_BlooguardWalk(objtype *ob) -{ - if (US_RndT() < 0x20) - { - if (ob->x < player->x) - { - ob->xdir = 1; - } - else - { - ob->xdir = -1; - } - } - if ( ((ob->xdir == 1 && ob->x < player->x) || (ob->xdir == -1 && ob->x > player->x)) - && ob->bottom == player->bottom && US_RndT() < 0x20) - { - ob->state = &s_blooguardattack1; - } -} - -/* -=========================== -= -= T_BlooguardAttack -= -=========================== -*/ - -#pragma argsused -void T_BlooguardAttack(objtype *ob) -{ - SD_PlaySound(SND_SMASH); - groundslam = 23; - if (player->hitnorth) - { - ChangeState(player, &s_keenstun); - } -} - -/* -=========================== -= -= C_Blooguard -= -=========================== -*/ - -void C_Blooguard(objtype *ob, objtype *hit) -{ - if (hit->obclass == keenobj) - { - KillKeen(); - } - if (hit->obclass == stunshotobj) // not 'else if' in the original code - { - if (--ob->temp2 == 0) // handle health - { - StunObj(ob, hit, &s_blooguardstun); - } - else - { - ob->temp1 = 2; // draw white twice - ob->needtoreact = true; - ExplodeShot(hit); - } - } -} - -/* -=========================== -= -= R_Blooguard -= -=========================== -*/ - -void R_Blooguard(objtype *ob) -{ - if (ob->xdir == 1 && ob->hitwest) - { - ob->x -= ob->xmove; - ob->xdir = -1; - ob->nothink = US_RndT() >> 5; - ChangeState(ob, ob->state); - } - else if (ob->xdir == -1 && ob->hiteast) - { - ob->x -= ob->xmove; - ob->xdir = 1; - ob->nothink = US_RndT() >> 5; - ChangeState(ob, ob->state); - } - else if (!ob->hitnorth) - { - ob->x -= ob->xmove*2; - ob->xdir = -ob->xdir; - ob->nothink = US_RndT() >> 5; - ChangeState(ob, ob->state); - } - if (ob->temp1) - { - ob->temp1--; - RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, maskdraw, ob->priority); - } - else - { - RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority); - } -} - -/* -============================================================================= - - BLOOGLET - -temp1 = type - -============================================================================= -*/ - -// red Blooglet: -statetype s_rbloogletwalk1 = {RBLOOGLETWALKL1SPR, RBLOOGLETWALKR1SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_rbloogletwalk2}; -statetype s_rbloogletwalk2 = {RBLOOGLETWALKL2SPR, RBLOOGLETWALKR2SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_rbloogletwalk3}; -statetype s_rbloogletwalk3 = {RBLOOGLETWALKL3SPR, RBLOOGLETWALKR3SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_rbloogletwalk4}; -statetype s_rbloogletwalk4 = {RBLOOGLETWALKL4SPR, RBLOOGLETWALKR4SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_rbloogletwalk1}; -statetype s_rbloogletstun = {RBLOOGLETSTUNSPR, RBLOOGLETSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL}; - -// yellow Blooglet: -statetype s_ybloogletwalk1 = {YBLOOGLETWALKL1SPR, YBLOOGLETWALKR1SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_ybloogletwalk2}; -statetype s_ybloogletwalk2 = {YBLOOGLETWALKL2SPR, YBLOOGLETWALKR2SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_ybloogletwalk3}; -statetype s_ybloogletwalk3 = {YBLOOGLETWALKL3SPR, YBLOOGLETWALKR3SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_ybloogletwalk4}; -statetype s_ybloogletwalk4 = {YBLOOGLETWALKL4SPR, YBLOOGLETWALKR4SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_ybloogletwalk1}; -statetype s_ybloogletstun = {YBLOOGLETSTUNSPR, YBLOOGLETSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL}; - -// blue Blooglet: -statetype s_bbloogletwalk1 = {BBLOOGLETWALKL1SPR, BBLOOGLETWALKR1SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_bbloogletwalk2}; -statetype s_bbloogletwalk2 = {BBLOOGLETWALKL2SPR, BBLOOGLETWALKR2SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_bbloogletwalk3}; -statetype s_bbloogletwalk3 = {BBLOOGLETWALKL3SPR, BBLOOGLETWALKR3SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_bbloogletwalk4}; -statetype s_bbloogletwalk4 = {BBLOOGLETWALKL4SPR, BBLOOGLETWALKR4SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_bbloogletwalk1}; -statetype s_bbloogletstun = {BBLOOGLETSTUNSPR, BBLOOGLETSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL}; - -// green Blooglet: -statetype s_gbloogletwalk1 = {GBLOOGLETWALKL1SPR, GBLOOGLETWALKR1SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_gbloogletwalk2}; -statetype s_gbloogletwalk2 = {GBLOOGLETWALKL2SPR, GBLOOGLETWALKR2SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_gbloogletwalk3}; -statetype s_gbloogletwalk3 = {GBLOOGLETWALKL3SPR, GBLOOGLETWALKR3SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_gbloogletwalk4}; -statetype s_gbloogletwalk4 = {GBLOOGLETWALKL4SPR, GBLOOGLETWALKR4SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_gbloogletwalk1}; -statetype s_gbloogletstun = {GBLOOGLETSTUNSPR, GBLOOGLETSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL}; - -/* -=========================== -= -= SpawnBlooglet -= -=========================== -*/ - -void SpawnBlooglet(Uint16 tileX, Uint16 tileY, Sint16 type) -{ - GetNewObj(false); - new->obclass = bloogletobj; - new->active = ac_yes; - new->priority = 0; - new->x = CONVERT_TILE_TO_GLOBAL(tileX); - new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -8*PIXGLOBAL; - if (US_RndT() < 0x80) - { - new->xdir = 1; - } - else - { - new->xdir = -1; - } - new->ydir = 1; - new->temp1 = type; - - switch (type % 4) - { - case 0: - NewState(new, &s_rbloogletwalk1); - break; - - case 1: - NewState(new, &s_ybloogletwalk1); - break; - - case 2: - NewState(new, &s_bbloogletwalk1); - break; - - case 3: - NewState(new, &s_gbloogletwalk1); - } -} - -/* -=========================== -= -= C_Blooglet -= -=========================== -*/ - -void C_Blooglet(objtype *ob, objtype *hit) -{ - static statetype *stunnedstate[4] = { - &s_rbloogletstun, - &s_ybloogletstun, - &s_bbloogletstun, - &s_gbloogletstun - }; - Sint16 color; - - if (hit->obclass == keenobj && hit->state->contact) - { - playerkludgeclipcancel = true; - ClipToSpriteSide(hit, ob); - playerkludgeclipcancel = false; - } - else if (hit->obclass == stunshotobj) - { - color = ob->temp1 & 3; - if (ob->temp1 > 3) - { - // - // spawn a key gem - // - GetNewObj(false); - new->needtoclip = cl_midclip; - new->priority = 2; - new->obclass = bonusobj; - new->x = ob->x; - new->y = ob->y; - new->ydir = -1; - new->yspeed = -40; - new->temp1 = color; - new->temp2=new->shapenum = bonusshape[color]; - new->temp3 = new->temp2 + 2; - NewState(new, &s_bonusfly1); - SD_PlaySound(SND_DROPKEY); - } - StunObj(ob, hit, stunnedstate[color]); - } -} \ No newline at end of file