diff --git a/src/CGame.cpp b/src/CGame.cpp index b783defa3..c741a4609 100644 --- a/src/CGame.cpp +++ b/src/CGame.cpp @@ -291,8 +291,6 @@ void CGame::preallocateCKP(stCloneKeenPlus *pCKP) demomode = DEMO_NODEMO; current_demo = 1; - memset(&pCKP->Control, 0, sizeof(stControl)); - pCKP->Joystick = NULL; acceleratemode = 0; diff --git a/src/CGraphics.cpp b/src/CGraphics.cpp index 843024784..9740c6f33 100644 --- a/src/CGraphics.cpp +++ b/src/CGraphics.cpp @@ -48,7 +48,7 @@ bool CGraphics::allocScrollBufmem(void) if (g_pVideoDriver->getZoomValue() > 1) { g_pLogFile->ftextOut("allocmem(): allocating %d bytes for blit buffer...", blitbuf_memsize); - blitbuffer = (unsigned char*) malloc(blitbuf_memsize); + blitbuffer = new unsigned char[blitbuf_memsize]; if (!blitbuffer) { g_pLogFile->ftextOut(RED,"Failure
"); @@ -63,12 +63,12 @@ void CGraphics::freemem(void) { if (scrollbuffer) { - delete[] scrollbuffer; + delete[] scrollbuffer; scrollbuffer = NULL; g_pLogFile->ftextOut(BLACK,true," Scrollbuffer memory released to system.
"); } if (blitbuffer) { - free(blitbuffer); + delete[] blitbuffer; blitbuffer = NULL; g_pLogFile->ftextOut(BLACK,true," Blitbuffer memory released to system.
"); } } diff --git a/src/game.cpp b/src/game.cpp index 1c49f410b..014c2e98f 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1,1490 +1,1487 @@ -/* GAME.C - Main and miscellaneous functions for in-game, contains the main - game loop, etc. -*/ - -#include "keen.h" -#include "demobox.h" -#include "include/game.h" -#include "sdl/CVideoDriver.h" -#include "include/menu.h" -#include "include/misc.h" -#include "include/gamedo.h" -#include "include/gamepdo.h" -#include "include/gm_pdowm.h" -#include "include/eseq_ep3.h" -#include "sdl/CTimer.h" -#include "sdl/CInput.h" -#include "sdl/sound/CSound.h" -#include "include/enemyai.h" -#include "hqp/CMusic.h" -#include "vorticon/CPlayer.h" -#include "vorticon/CHighScores.h" -#include "hqp/CHQBitmap.h" -char otherplayer; - -// TODO: seperate status boxes for the different players -// TODO: Your Ship Needs These Parts in multiplayer - -int playerbaseframes[MAX_PLAYERS] = {0,0,0,0,0,0,0,0}; - -unsigned int max_scroll_x, max_scroll_y; -char debugmode=0,acceleratemode=0; - -// and this is where the magic happens -void gameloop(stCloneKeenPlus *pCKP) -{ - unsigned int i; - - int enter,lastquit; - - // Enable the yorp/garg statues elders switches animations - for(int i=0 ; iControl.levelcontrol.curlevel; - crashflag3 = pCKP->Control.levelcontrol.episode; - why_term_ptr = "No player start position! (flag2=pCKP->Control.levelcontrol.curlevel, flag3=pCKP->Control.levelcontrol.episode)"; - } - - if (!loadinggame) - { - gameloop_initialize(pCKP); - } - else - { - loadinggame = 0; - fade.mode = FADE_GO; - fade.dir = FADE_IN; - fade.curamt = 0; - fade.fadetimer = 0; - fade.rate = FADE_NORM; - } - - // fire all guns immediately first time around - gunfiretimer = (gunfirefreq+1); - - // if this is Mortimer's Castle, fade in and do the conversation - // with Mortimer. - if (pCKP->Control.levelcontrol.episode==3 && pCKP->Control.levelcontrol.curlevel==16) - { - for(i=0;ipollEvents(); - g_pTimer->SpeedThrottle(); - gamedo_RenderScreen(pCKP); - } while(fade.mode!=FADE_COMPLETE /*&& !immediate_keytable[KQUIT]*/); - - eseq3_Mortimer(pCKP); - } - - lastquit = 1; - g_pInput->flushKeys(); // The Windows need that. I don't know why! - - // Now, we are ready to loop the game scenes (map and level) - // Let's create the player objects - do - { - if (primaryplayer==1) otherplayer = 0; else otherplayer = 1; - - #ifdef NETWORK_PLAY -// if (numplayers>1) net_getdata(); - if (is_server) - { - Net_Server_Run(); - } - else if (is_client) - { - Net_Client_Run(); - } - #endif - - gamedo_fades(); - - // periodically make all enemy gun fixtures fire (in ep3) - // (also ice cannons in ep1) we do this in a global variable - // so they're all in sync. when gunfiretimer==0 all gun SE - // objects will fire. - if (gunfiretimer > gunfirefreq) - { - gunfiretimer = 0; - } - else gunfiretimer++; - - // gather input and copy to player[].keytable[] structures - gamedo_getInput(pCKP); - - // run the player behaviour for each player in the game - if (!map.isworldmap) - { - for(i=0;iControl.levelcontrol.gameovermode && pCKP->Control.levelcontrol.level_done==LEVEL_NOT_DONE) - { - ScreenIsScrolling = 0; - if (gamedo_ScrollTriggers(primaryplayer)) ScreenIsScrolling = 1; - } - - - - // do frameskipping, and render/blit the screen if it's time - gamedo_frameskipping(pCKP); - - // when we complete a fade out flag to exit the game loop - if (fade.mode==FADE_COMPLETE) - { - if (fade.dir==FADE_OUT) - { - demomode = DEMO_NODEMO; - pCKP->Control.levelcontrol.level_done = LEVEL_COMPLETE; - pCKP->Control.levelcontrol.command = LVLC_CHANGE_LEVEL; - if (pCKP->Control.levelcontrol.curlevel != WM_MAP_NUM) - { // exiting a level, going back to world map - for(i=0;iControl.levelcontrol.success==1) - { // mark level as completed on world map - pCKP->Control.levelcontrol.levels_completed[pCKP->Control.levelcontrol.curlevel] = 1; - } - pCKP->Control.levelcontrol.chglevelto = WM_MAP_NUM; - } - } - else - { - fade.mode = NO_FADE; - } - } - - // when walking through the exit door don't show keen's sprite past - // the door frame (so it looks like he walks "through" the door) - if (pCKP->Control.levelcontrol.level_done==LEVEL_DONE_WALK) - { - gamepdo_walkbehindexitdoor(pCKP->Control.levelcontrol.level_finished_by, pCKP); - } - - // allow enter to return to main menu - // if we're in game over mode - - enter = (g_pInput->getPressedCommand(IC_STATUS)); - if (pCKP->Control.levelcontrol.gameovermode) - { - if (enter) - { - int cities=0; - CHighScores *HighScoreTable; - - if (pCKP->Control.levelcontrol.levels_completed[4]) cities++; - if (pCKP->Control.levelcontrol.levels_completed[6]) cities++; - if (pCKP->Control.levelcontrol.levels_completed[7]) cities++; - if (pCKP->Control.levelcontrol.levels_completed[13]) cities++; - if (pCKP->Control.levelcontrol.levels_completed[11]) cities++; - if (pCKP->Control.levelcontrol.levels_completed[9]) cities++; - if (pCKP->Control.levelcontrol.levels_completed[15]) cities++; - if (pCKP->Control.levelcontrol.levels_completed[16]) cities++; - - HighScoreTable = new CHighScores(pCKP); - - bool extras[4]; - - // check inventory or saved cities - memset(extras,false,4*sizeof(bool)); - if(pCKP->Control.levelcontrol.episode == 1) - { - if(player[0].inventory.HasJoystick) - extras[0] = true; - if(player[0].inventory.HasBattery) - extras[1] = true; - if(player[0].inventory.HasVacuum) - extras[2] = true; - if(player[0].inventory.HasFuel) - extras[3] = true; - } - - HighScoreTable->writeHighScore((int)player[0].inventory.score,extras,cities); - - HighScoreTable->showHighScore(); - - delete HighScoreTable; - - - if (fade.mode!=FADE_GO && fade.dir!=FADE_OUT) - { - fade.dir = FADE_OUT; - fade.curamt = PAL_FADE_SHADES; - fade.fadetimer = 0; - fade.rate = FADE_NORM; - fade.mode = FADE_GO; - } - - pCKP->Control.levelcontrol.command = LVLC_GAME_OVER; - - } - - if (fade.mode==FADE_COMPLETE && fade.dir==FADE_OUT) - { - pCKP->Control.levelcontrol.command = LVLC_GAME_OVER; - } - } - - #ifdef NETWORK_PLAY -// if (numplayers>1) net_senddata(); - #endif - - if (g_pInput->getPressedKey(KQUIT)) - { - VerifyQuit(pCKP); - } - if (QuitState != NO_QUIT) return; - - // limit frame rate - if (!acceleratemode) - { - g_pInput->pollEvents(); - g_pTimer->SpeedThrottle(); - #ifdef NETWORK_PLAY -// if (numplayers>1) net_sync(); - #endif - } - - if(g_pInput->getExitEvent()) - { - g_pInput->sendKey(KQUIT); - g_pInput->cancelExitEvent(); - } - - } while(!crashflag && pCKP->Control.levelcontrol.command==LVLC_NOCOMMAND); - - // Cleanup the player structure! - -} - -// gives keycard for door doortile to player p -void give_keycard(int doortile, int p) -{ - bool keystack = options[OPT_KEYCARDSTACK].value; // True if set - g_pSound->playSound(SOUND_GET_CARD, PLAY_NOW); - - if (doortile==DOOR_YELLOW) player[p].inventory.HasCardYellow = keystack ? player[p].inventory.HasCardYellow + 1 : 1; - else if (doortile==DOOR_RED) player[p].inventory.HasCardRed = keystack ? player[p].inventory.HasCardRed + 1 : 1; - else if (doortile==DOOR_GREEN) player[p].inventory.HasCardGreen = keystack ? player[p].inventory.HasCardGreen + 1 : 1; - else if (doortile==DOOR_BLUE) player[p].inventory.HasCardBlue = keystack ? player[p].inventory.HasCardBlue + 1 : 1; - else - { - crashflag = 1; - crashflag2 = doortile; - why_term_ptr = "give_keycard(): invalid value for doortile parameter."; - } -} - -// take away the specified keycard from player p -void take_keycard(int doortile, int p) -{ - if (doortile==DOOR_YELLOW) player[p].inventory.HasCardYellow--; - else if (doortile==DOOR_RED) player[p].inventory.HasCardRed--; - else if (doortile==DOOR_GREEN) player[p].inventory.HasCardGreen--; - else if (doortile==DOOR_BLUE) player[p].inventory.HasCardBlue--; - - if(player[p].inventory.HasCardYellow > 9) player[p].inventory.HasCardYellow = 0; - if(player[p].inventory.HasCardRed > 9) player[p].inventory.HasCardRed = 0; - if(player[p].inventory.HasCardGreen > 9) player[p].inventory.HasCardGreen = 0; - if(player[p].inventory.HasCardBlue > 9) player[p].inventory.HasCardBlue = 0; -} - -// unregisters all animated tiles with baseframe tile -void unregister_animtiles(int tile) -{ -int i; - for(i=0;iplaySound(SOUND_DOOR_OPEN, PLAY_NOW); - - take_keycard(doortile, cp); - - /* erase door from map */ - if (pCKP->Control.levelcontrol.episode==3) - { - chgtotile = map.mapdata[mpx-1][mpy]; - } - else - { - chgtotile = tiles[map.mapdata[mpx][mpy]].chgtile; - } - - if(TileProperty[map.mapdata[mpx][mpy-1]][BEHAVIOR] > 1 && - TileProperty[map.mapdata[mpx][mpy-1]][BEHAVIOR] < 6) // This happens because, sometimes the player opens the door - // from a lower part. - { - map_chgtile(mpx, mpy-1, chgtotile); - tilefix=1; - - } - if(TileProperty[map.mapdata[mpx][mpy]][BEHAVIOR] > 1 && - TileProperty[map.mapdata[mpx][mpy]][BEHAVIOR] < 6) // This happens because, sometimes the player opens the door - // from a lower part. - { - map_chgtile(mpx, mpy, chgtotile); // upper? - - } - if(TileProperty[map.mapdata[mpx][mpy+1]][BEHAVIOR] > 1 && - TileProperty[map.mapdata[mpx][mpy+1]][BEHAVIOR] < 6) // This happens because, sometimes the player opens the door - // from a lower part. - { - map_chgtile(mpx, mpy+1, chgtotile); // When he stands in front of the door! - } - - // replace the door tiles with a door object, which will do the animation - o = spawn_object(mpx<<4< than "extra life at" and award 1-UPs when appropriate -void extralifeat(int cp) -{ - if (player[cp].inventory.score > player[cp].inventory.extralifeat) - { - g_pSound->playSound(SOUND_EXTRA_LIFE, PLAY_NOW); - player[cp].inventory.lives++; - player[cp].inventory.extralifeat += 20000; - } -} - -// have keen pick up the goodie at screen pixel position (px, py) -void keen_get_goodie(int px, int py, int theplayer, stCloneKeenPlus *pCKP) -{ -int mpx,mpy,t; -/*int i;*/ - mpx = px>>4; - mpy = py>>4; - t = map.mapdata[mpx][mpy]; - - if ((TileProperty[t][BEHAVIOR] < 17 && TileProperty[t][BEHAVIOR] > 5) || - (TileProperty[t][BEHAVIOR] > 17 && TileProperty[t][BEHAVIOR] < 22) || - (TileProperty[t][BEHAVIOR] == 27 || TileProperty[t][BEHAVIOR] == 28) ) // All pickupable items - //if (tiles[t].pickupable) - { // pick up the goodie, i.e. erase it from the map - map_chgtile(mpx, mpy, tiles[t].chgtile); - //if (tiles[t].isAnimated) map_deanimate(mpx, mpy); - if (TileProperty[t][ANIMATION] != 1) map_deanimate(mpx, mpy); - } - else if (TileProperty[t][BEHAVIOR] == 1) - //else if (tiles[t].lethal) - { // whoah, this "goodie" isn't so good... - killplayer(theplayer, pCKP); - return; - } - - // do whatever the goodie is supposed to do... - procgoodie(t, mpx, mpy, theplayer, pCKP); -} - -void initgame(stCloneKeenPlus *pCKP) -{ -int x,y; -unsigned int i; - - animtiletimer = curanimtileframe = 0; - //PlatExtending = 0; - - // reset player walk frame widths - for(i=0;iControl.levelcontrol.episode==1) - { - gunfirefreq = ICECANNON_FIRE_FREQ; - } - else - { - gunfirefreq = GUN_FIRE_FREQ; - } - - // reset the ysize attribute of all doors - sprites[DOOR_YELLOW_SPRITE].ysize = 32; - sprites[DOOR_RED_SPRITE].ysize = 32; - sprites[DOOR_GREEN_SPRITE].ysize = 32; - sprites[DOOR_BLUE_SPRITE].ysize = 32; - - pCKP->Control.levelcontrol.level_done_timer = 0; - pCKP->Control.levelcontrol.gameovermode = 0; - - // all objects -> not exist - for(i=1;iControl.levelcontrol.episode==1) - { - objdefsprites[OBJ_YORP] = OBJ_YORP_DEFSPRITE; - objdefsprites[OBJ_GARG] = OBJ_GARG_DEFSPRITE; - objdefsprites[OBJ_BUTLER] = OBJ_BUTLER_DEFSPRITE; - objdefsprites[OBJ_TANK] = OBJ_TANK_DEFSPRITE; - objdefsprites[OBJ_ICECHUNK] = OBJ_ICECHUNK_DEFSPRITE; - objdefsprites[OBJ_ICEBIT] = OBJ_ICEBIT_DEFSPRITE; - objdefsprites[OBJ_ROPE] = OBJ_ROPE_DEFSPRITE; - - objdefsprites[OBJ_RAY] = OBJ_RAY_DEFSPRITE_EP1; - objdefsprites[OBJ_VORT] = OBJ_VORT_DEFSPRITE_EP1; - } - else if (pCKP->Control.levelcontrol.episode==2) - { - objdefsprites[OBJ_WALKER] = OBJ_WALKER_DEFSPRITE; - objdefsprites[OBJ_TANKEP2] = OBJ_TANKEP2_DEFSPRITE; - objdefsprites[OBJ_BEAR] = OBJ_BEAR_DEFSPRITE; - - objdefsprites[OBJ_RAY] = OBJ_RAY_DEFSPRITE_EP2; - objdefsprites[OBJ_VORT] = OBJ_VORT_DEFSPRITE_EP2; - objdefsprites[OBJ_PLATFORM] = OBJ_PLATFORM_DEFSPRITE_EP2; - objdefsprites[OBJ_BABY] = OBJ_BABY_DEFSPRITE_EP2; - } - else if (pCKP->Control.levelcontrol.episode==3) - { - objdefsprites[OBJ_FOOB] = OBJ_FOOB_DEFSPRITE; - objdefsprites[OBJ_NINJA] = OBJ_NINJA_DEFSPRITE; - objdefsprites[OBJ_MOTHER] = OBJ_MOTHER_DEFSPRITE; - objdefsprites[OBJ_MEEP] = OBJ_MEEP_DEFSPRITE; - objdefsprites[OBJ_BALL] = OBJ_BJ_DEFSPRITE; - objdefsprites[OBJ_JACK] = OBJ_BJ_DEFSPRITE; - - objdefsprites[OBJ_RAY] = OBJ_RAY_DEFSPRITE_EP3; - objdefsprites[OBJ_VORT] = OBJ_VORT_DEFSPRITE_EP3; - objdefsprites[OBJ_PLATFORM] = OBJ_PLATFORM_DEFSPRITE_EP3; - objdefsprites[OBJ_BABY] = OBJ_BABY_DEFSPRITE_EP3; - } - - objdefsprites[OBJ_DOOR] = DOOR_YELLOW_SPRITE; - objdefsprites[OBJ_TELEPORTER] = OBJ_TELEPORTER_DEFSPRITE; - - objdefsprites[OBJ_SECTOREFFECTOR] = BlankSprite; - -// initilize game variables - pCKP->Control.levelcontrol.level_done = LEVEL_NOT_DONE; - animtiletimer = curanimtileframe = 0; - DemoObjectHandle = 0; - - for(i=0;iControl.levelcontrol.levels_completed[i] = 0; - - for(i=0;iControl.levelcontrol.episode==1) - { - player[i].inventory.charges = 0; - } - else if (pCKP->Control.levelcontrol.episode==2) - { - player[i].inventory.charges = 3; - } - else - { - player[i].inventory.charges = 5; - } - if (demomode) player[i].inventory.charges = 100; - - // start with pogo stick in all episodes but 1 - if (pCKP->Control.levelcontrol.episode!=1 || demomode) - { player[i].inventory.HasPogo = 1; } - else - { player[i].inventory.HasPogo = 0; } - } - - initsprites(pCKP, s); - - if (demomode) srand(375); - - primaryplayer = 0; - - return 0; -} - -char spawn_object(int x, int y, int otype) -{ -int i; - // find an unused object slot - for(i=1;i>CSF)+ysize; - if ((temp>>4)<<4 != temp) - { - objects[o].blockedd = 0; - } - else - { // on a tile boundary, test if tile under object is solid - objects[o].blockedd = 0; - x = (objects[o].x>>CSF); - y = (objects[o].y>>CSF)+ysize+1; - for(xa=0;xa 1 && - TileProperty[getmaptileat(x+xa,y)][BEHAVIOR] < 6) ) - { - objects[o].blockedd = 1; - goto setblockedd; - } - } - if(TileProperty[getmaptileat(x+xsize-2, y)][BUP] || (TileProperty[getmaptileat(x+xa,y)][BEHAVIOR] > 1 && - TileProperty[getmaptileat(x+xa,y)][BEHAVIOR] < 6) ) - { - objects[o].blockedd = 1; - } - setblockedd: ; - } - - // set blockedu - objects[o].blockedu = 0; - x = (objects[o].x>>CSF); - y = (objects[o].y>>CSF)-1; - for(xa=0;xa>CSF)-1; - y = (objects[o].y>>CSF)+1; - for(ya=0;ya>CSF)+ysize-1))][BRIGHT]) - //if (tiles[getmaptileat(x, ((objects[o].y>>CSF)+ysize-1))].solidr) - { - objects[o].blockedl = 1; - } - setblockedl: ; - - // set blockedr - objects[o].blockedr = 0; - x = (objects[o].x>>CSF)+xsize; - y = (objects[o].y>>CSF)+1; - for(ya=0;ya>CSF)+ysize-1))][BLEFT]) - //if (tiles[getmaptileat(x, ((objects[o].y>>CSF)+ysize-1))].solidl) - { - objects[o].blockedr = 1; - } - setblockedr: ; - - // hit detection with players - objects[o].touchPlayer = 0; - for(cplayer=0;cplayerOBJ_YINERTIA_RATE) - { - if (objects[o].yinertia < OBJFALLSPEED) objects[o].yinertia++; - objects[o].yinertiatimer = 0; - } else objects[o].yinertiatimer++; - } - objects[o].y += objects[o].yinertia; - } -} - -// returns nonzero if object1 overlaps object2 -char hitdetect(int object1, int object2) -{ -int s1, s2; -unsigned int rect1x1, rect1y1, rect1x2, rect1y2; -unsigned int rect2x1, rect2y1, rect2x2, rect2y2; - - // get the sprites used by the two objects - s1 = objects[object1].sprite; - s2 = objects[object2].sprite; - - // get the bounding rectangle of the first object - rect1x1 = objects[object1].x + sprites[s1].bboxX1; - rect1y1 = objects[object1].y + sprites[s1].bboxY1; - rect1x2 = objects[object1].x + sprites[s1].bboxX2; - rect1y2 = objects[object1].y + sprites[s1].bboxY2; - - // get the bounding rectangle of the second object - rect2x1 = objects[object2].x + sprites[s2].bboxX1; - rect2y1 = objects[object2].y + sprites[s2].bboxY1; - rect2x2 = objects[object2].x + sprites[s2].bboxX2; - rect2y2 = objects[object2].y + sprites[s2].bboxY2; - - // find out if the rectangles overlap - if ((rect1x1 < rect2x1) && (rect1x2 < rect2x1)) return 0; - if ((rect1x1 > rect2x2) && (rect1x2 > rect2x2)) return 0; - if ((rect1y1 < rect2y1) && (rect1y2 < rect2y1)) return 0; - if ((rect1y1 > rect2y2) && (rect1y2 > rect2y2)) return 0; - - return 1; -} - -void killplayer(int theplayer, stCloneKeenPlus *pCKP) -{ - if (player[theplayer].godmode || g_pInput->getHoldedKey(KTAB)) return; - if (player[theplayer].ankhtime) return; - if (pCKP->Control.levelcontrol.level_done) return; - if (!player[theplayer].pdie) - { - player[theplayer].pdie = PDIE_DYING; - player[theplayer].pdieframe = 0; - player[theplayer].pdietimer = 0; - player[theplayer].pdietillfly = DIE_TILL_FLY_TIME; - player[theplayer].pdie_xvect = rand()%(DIE_MAX_XVECT*2); - player[theplayer].pdie_xvect -= DIE_MAX_XVECT; - player[theplayer].inventory.lives--; - player[theplayer].y += (8<stop(); - g_pSound->playSound(SOUND_KEEN_DIE, PLAY_NOW); - } -} - -void freezeplayer(int theplayer) -{ - if (player[theplayer].godmode /*|| immediate_keytable[KTAB]*/) return; - if (player[theplayer].ankhtime) return; - // give the player a little "kick" - player[theplayer].pjumptime = PJUMP_NORMALTIME_1; - player[theplayer].pjumpupdecreaserate = PJUMP_UPDECREASERATE_1; - player[theplayer].pjumpupspeed = 15; - player[theplayer].pjumping = PJUMPUP; - player[theplayer].pjumpupspeed_decreasetimer = 0; - player[theplayer].pjustjumped = 1; - - // and freeze him (stun him on ep2/3) - player[theplayer].pfrozentime = PFROZEN_TIME; - player[theplayer].pfrozenframe = 0; - player[theplayer].pfrozenanimtimer = 0; - player[theplayer].ppogostick = false; -} - - -void PlayerTouchedExit(int theplayer, stCloneKeenPlus *pCKP) -{ -/*int i;*/ - if (!player[theplayer].pjumping && !player[theplayer].pfalling\ - && !player[theplayer].ppogostick && \ - pCKP->Control.levelcontrol.level_done==LEVEL_NOT_DONE) - { - // don't allow player to walk through a door if he's standing - // on an object such as a platform or an enemy - if (player[theplayer].psupportingobject) - { - return; - } - - // if player has ankh shut it off - if (player[theplayer].ankhtime) - { - player[theplayer].ankhtime = 0; - objects[player[theplayer].ankhshieldobject].exists = 0; - } - - player[theplayer].ppogostick = false; - - g_pMusicPlayer->stop(); - g_pSound->playSound(SOUND_LEVEL_DONE, PLAY_NOW); - pCKP->Control.levelcontrol.level_done = LEVEL_DONE_WALK; - pCKP->Control.levelcontrol.level_finished_by = theplayer; - } -} - -void endlevel(int success, stCloneKeenPlus *pCKP) -{ - if (fade.mode == NO_FADE) - { - fade.dir = FADE_OUT; - fade.curamt = PAL_FADE_SHADES; - fade.fadetimer = 0; - fade.rate = FADE_NORM; - fade.mode = FADE_GO; - pCKP->Control.levelcontrol.success = success; - pCKP->Control.levelcontrol.tobonuslevel = 0; - } -} - -void SetGameOver(stCloneKeenPlus *pCKP) -{ -/*int x,y,bmnum;*/ - if (!pCKP->Control.levelcontrol.gameovermode) - { - pCKP->Control.levelcontrol.gameovermode = 1; - g_pSound->playSound(SOUND_GAME_OVER, PLAY_NOW); - } -} - - -// this is so objects can block the player, -// player can stand on them, etc. -// x and y are the CSFed coordinates to check (e.g. playx and playy) -// returns nonzero if there is a solid object -// at that point -char checkobjsolid(unsigned int x, unsigned int y, unsigned int cp) -{ - int o; - - for(o=1;o= objects[o].x+sprites[objects[o].sprite].bboxX1) - if (x <= objects[o].x+sprites[objects[o].sprite].bboxX2) - if (y >= objects[o].y+sprites[objects[o].sprite].bboxY1) - if (y <= objects[o].y+sprites[objects[o].sprite].bboxY2) - return o; - } - } - return 0; -} - -// returns 1 if player cp has the card to door t, which -> door -char CheckDoorBlock(int t, int cp, int which,stCloneKeenPlus *pCKP) -{ - if (which==DOOR_YELLOW) - { - if (!player[cp].inventory.HasCardYellow) - { - player[cp].blockedby = t; - return 1; - } - } - else if (which==DOOR_RED) - { - if (!player[cp].inventory.HasCardRed) - { - player[cp].blockedby = t; - return 1; - } - } - else if (which==DOOR_GREEN) - { - if (!player[cp].inventory.HasCardGreen) - { - player[cp].blockedby = t; - return 1; - } - } - else if (which==DOOR_BLUE) - { - if (!player[cp].inventory.HasCardBlue) - { - player[cp].blockedby = t; - return 1; - } - } - - return 0; -} - -// checks if tile at (x,y) is solid to the player walking left into it. -// returns 1 and sets blockedby if so. -char checkissolidl(int x, int y, int cp, stCloneKeenPlus *pCKP) -{ -int t; - t = getmaptileat(x, y); - - if(TileProperty[t][BLEFT] || x < 0) - //if (tiles[t].solidl) - { - player[cp].blockedby = t; - return 1; - } - if (checkobjsolid(x<=16) - { - y2 = 0; - t++; - } - } -} - -// creates a mask from a sourcetile, places it in desttile -void MakeMask(int sourcetile, int desttile, int transparentcol) -{ -int x,y,c; - for(y=0;y<16;y++) - { - for(x=0;x<16;x++) - { - c = tiledata[sourcetile][y][x]; - if (c != transparentcol) c = 0; else c = 15; - tiledata[desttile][y][x] = c; - } - } -} - -// replaces all instances of color find in sprite s with -// color replace, as long as the y is greater than miny -void ReplaceSpriteColor(int s, int find, int replace, int miny) -{ -int x,y; - - for(y=miny;yControl.levelcontrol.episode==1) - { - -// MakeMask(443, 155, 7); - // tiles[443].masktile = 155; -// tiles[428].masktile = 155; - } -} - -void procgoodie(int t, int mpx, int mpy, int theplayer, stCloneKeenPlus *pCKP) -{ - if ((TileProperty[t][BEHAVIOR] > 5 && TileProperty[t][BEHAVIOR] < 11) || - (TileProperty[t][BEHAVIOR] > 17 && TileProperty[t][BEHAVIOR] < 22) ) - { - if((player[theplayer].x*player[theplayer].y) % 2 == 1) - g_pSound->playStereofromCoord(SOUND_GET_BONUS, PLAY_NOW, 0); - else - g_pSound->playStereofromCoord(SOUND_GET_BONUS, PLAY_NOW, 320); - } - else if (TileProperty[t][BEHAVIOR] > 10 && TileProperty[t][BEHAVIOR] < 16) g_pSound->playSound(SOUND_GET_ITEM, PLAY_NOW); - switch(TileProperty[t][BEHAVIOR]) - { - // keycards - case 18: give_keycard(DOOR_YELLOW, theplayer); break; - case 19: give_keycard(DOOR_RED, theplayer); break; - case 20: give_keycard(DOOR_GREEN, theplayer); break; - case 21: give_keycard(DOOR_BLUE, theplayer); break; - - case DOOR_YELLOW: - if (player[theplayer].inventory.HasCardYellow) - open_door(DOOR_YELLOW, DOOR_YELLOW_SPRITE, mpx, mpy, theplayer, pCKP); - break; - case DOOR_RED: - if (player[theplayer].inventory.HasCardRed) - open_door(DOOR_RED, DOOR_RED_SPRITE, mpx, mpy, theplayer, pCKP); - break; - case DOOR_GREEN: - if (player[theplayer].inventory.HasCardGreen) - open_door(DOOR_GREEN, DOOR_GREEN_SPRITE, mpx, mpy, theplayer, pCKP); - break; - case DOOR_BLUE: - if (player[theplayer].inventory.HasCardBlue) - open_door(DOOR_BLUE, DOOR_BLUE_SPRITE, mpx, mpy, theplayer, pCKP); - break; - - case 7: // What gives you 100 Points - player[theplayer].inventory.score += 100; extralifeat(theplayer); - break; - case 8: // What gives you 200 Points - player[theplayer].inventory.score += 200; extralifeat(theplayer); - break; - case 6: // What gives you 500 Points - player[theplayer].inventory.score += 500; extralifeat(theplayer); - break; - case 9: // What gives you 1000 Points - player[theplayer].inventory.score += 1000; extralifeat(theplayer); - break; - case 10: // What gives you 5000 Points - player[theplayer].inventory.score += 5000; extralifeat(theplayer); - break; - - case 15: // raygun - player[theplayer].inventory.charges += 5; - break; - case 16: // the Holy Pogo Stick - player[theplayer].inventory.HasPogo = 1; - g_pSound->playSound(SOUND_GET_PART, PLAY_NOW); - break; - - case 11: - player[theplayer].inventory.HasJoystick = 1; - g_pSound->playSound(SOUND_GET_PART, PLAY_NOW); - break; - - case 12: - player[theplayer].inventory.HasBattery = 1; - g_pSound->playSound(SOUND_GET_PART, PLAY_NOW); - break; - case 13: - - player[theplayer].inventory.HasVacuum = 1; - g_pSound->playSound(SOUND_GET_PART, PLAY_NOW); - break; - case 14: - player[theplayer].inventory.HasFuel = 1; - g_pSound->playSound(SOUND_GET_PART, PLAY_NOW); - break; - - // in-level teleporter - // (in level13.ck1 that takes you to the bonus level) - case 24: - endlevel(0, pCKP); - pCKP->Control.levelcontrol.tobonuslevel = 1; - break; - - case YORPSTATUEHEAD: - if(pCKP->Control.levelcontrol.episode == 1) - { - youseeinyourmind(mpx, mpy, pCKP); - } - else if(pCKP->Control.levelcontrol.episode == 2) - if(!player[theplayer].blockedr && !player[theplayer].blockedl) - VorticonElder(mpx, mpy, pCKP); - break; - - case 27: - if(pCKP->Control.levelcontrol.episode == 3) - GiveAnkh(theplayer); - break; - case 28: - player[theplayer].inventory.charges++; - g_pSound->playSound(SOUND_GET_ITEM, PLAY_NOW); - break; - - case 17: - if (pCKP->Control.levelcontrol.canexit && (!pCKP->Control.levelcontrol.isfinallevel || player[theplayer].inventory.HasFuel)) - { - pCKP->Control.levelcontrol.exitXpos = (mpx+2)<<4; - PlayerTouchedExit(theplayer, pCKP); - } - break; - - case 23:break; // these are switches. They cannot not be picked up! - case 25:break; // Refer to JumpandPogo to check the activation code - case 26:break; - - // we fell off the bottom of the map - case TILE_FELLOFFMAP_EP1: - if (!player[theplayer].pdie) - { - g_pSound->playSound(SOUND_KEEN_FALL, PLAY_FORCE); - player[theplayer].ankhtime = 0; - player[theplayer].godmode = 0; - player[theplayer].pdie = PDIE_FELLOFFMAP; - } - break; - - default: - why_term_ptr = "procgoodie_ep1: Unknown goodie-- value given in flag2."; - break; - } - - -} - -void GiveAnkh(int cp) -{ -int o; - if (!player[cp].ankhtime) - { - o = spawn_object(player[cp].x, player[cp].y, OBJ_SECTOREFFECTOR); - objects[o].ai.se.type = SE_ANKHSHIELD; - player[cp].ankhshieldobject = o; - } - - g_pSound->playSound(SOUND_ANKH, PLAY_NOW); - player[cp].ankhtime = PLAY_ANKH_TIME; - gamepdo_ankh(cp); -} - -void gameloop_initialize(stCloneKeenPlus *pCKP) -{ -unsigned int x,y,i/*,tl*/; -int timeout; - - if (pCKP->Control.levelcontrol.episode == 3) - { - // coat the top of the map ("oh no!" border) with a non-solid tile - // so keen can jump partially off the top of the screen - for(x=1;xControl.levelcontrol.episode==1) - { - // coat the bottom of the map below the border. - // since the border has solidceil=1 this provides - // a platform to catch yorps that fall off the map - y = map.ysize; - for(x=2;x>CSF>>4 < (map.xsize/2) || pCKP->Control.levelcontrol.episode==1) - { - x += (18<>CSF>>4 < (map.xsize/2) || pCKP->Control.levelcontrol.episode==1) - player[i].pdir = player[i].pshowdir = RIGHT; - else - player[i].pdir = player[i].pshowdir = LEFT; - } - } - -// scroll past the first two tiles (the level border), they'll -// now never be visible because you're not allowed to scroll -// left past X=32. - for(i=0;i<2*16;i++) - { - map_scroll_right(); - map_scroll_down(); - } - -// scroll the screen until the primary player is onscreen -// enough to where he doesn't set off the scroll triggers - for(timeout=0;timeout<10000;timeout++) - { - if (!gamedo_ScrollTriggers(primaryplayer)) break; - } - - // initiate fade-in - fade.mode = FADE_GO; - fade.dir = FADE_IN; - fade.rate = FADE_NORM; - fade.curamt = 0; - fade.fadetimer = 0; - - // "keens left" when returning to world map after dying - if (pCKP->Control.levelcontrol.dokeensleft) - { - keensleft(pCKP); - pCKP->Control.levelcontrol.dokeensleft = 0; - } - -} +/* GAME.C + Main and miscellaneous functions for in-game, contains the main + game loop, etc. +*/ + +#include "keen.h" +#include "demobox.h" +#include "include/game.h" +#include "sdl/CVideoDriver.h" +#include "include/menu.h" +#include "include/misc.h" +#include "include/gamedo.h" +#include "include/gamepdo.h" +#include "include/gm_pdowm.h" +#include "include/eseq_ep3.h" +#include "sdl/CTimer.h" +#include "sdl/CInput.h" +#include "sdl/sound/CSound.h" +#include "include/enemyai.h" +#include "hqp/CMusic.h" +#include "vorticon/CPlayer.h" +#include "vorticon/CHighScores.h" +#include "hqp/CHQBitmap.h" +char otherplayer; + +// TODO: seperate status boxes for the different players +// TODO: Your Ship Needs These Parts in multiplayer + +int playerbaseframes[MAX_PLAYERS] = {0,0,0,0,0,0,0,0}; + +unsigned int max_scroll_x, max_scroll_y; +char debugmode=0,acceleratemode=0; + +// and this is where the magic happens +void gameloop(stCloneKeenPlus *pCKP) +{ + unsigned int i; + + int enter,lastquit; + + // Enable the yorp/garg statues elders switches animations + for(int i=0 ; iControl.levelcontrol.curlevel; + crashflag3 = pCKP->Control.levelcontrol.episode; + why_term_ptr = "No player start position! (flag2=pCKP->Control.levelcontrol.curlevel, flag3=pCKP->Control.levelcontrol.episode)"; + } + + if (!loadinggame) + { + gameloop_initialize(pCKP); + } + else + { + loadinggame = 0; + fade.mode = FADE_GO; + fade.dir = FADE_IN; + fade.curamt = 0; + fade.fadetimer = 0; + fade.rate = FADE_NORM; + } + + // fire all guns immediately first time around + gunfiretimer = (gunfirefreq+1); + + // if this is Mortimer's Castle, fade in and do the conversation + // with Mortimer. + if (pCKP->Control.levelcontrol.episode==3 && pCKP->Control.levelcontrol.curlevel==16) + { + for(i=0;ipollEvents(); + g_pTimer->SpeedThrottle(); + gamedo_RenderScreen(pCKP); + } while(fade.mode!=FADE_COMPLETE /*&& !immediate_keytable[KQUIT]*/); + + eseq3_Mortimer(pCKP); + } + + lastquit = 1; + g_pInput->flushKeys(); // The Windows need that. I don't know why! + + // Now, we are ready to loop the game scenes (map and level) + // Let's create the player objects + do + { + if (primaryplayer==1) otherplayer = 0; else otherplayer = 1; + + #ifdef NETWORK_PLAY +// if (numplayers>1) net_getdata(); + if (is_server) + { + Net_Server_Run(); + } + else if (is_client) + { + Net_Client_Run(); + } + #endif + + gamedo_fades(); + + // periodically make all enemy gun fixtures fire (in ep3) + // (also ice cannons in ep1) we do this in a global variable + // so they're all in sync. when gunfiretimer==0 all gun SE + // objects will fire. + if (gunfiretimer > gunfirefreq) + { + gunfiretimer = 0; + } + else gunfiretimer++; + + // gather input and copy to player[].keytable[] structures + gamedo_getInput(pCKP); + + // run the player behaviour for each player in the game + if (!map.isworldmap) + { + for(i=0;iControl.levelcontrol.gameovermode && pCKP->Control.levelcontrol.level_done==LEVEL_NOT_DONE) + { + ScreenIsScrolling = 0; + if (gamedo_ScrollTriggers(primaryplayer)) ScreenIsScrolling = 1; + } + + + + // do frameskipping, and render/blit the screen if it's time + gamedo_frameskipping(pCKP); + + // when we complete a fade out flag to exit the game loop + if (fade.mode==FADE_COMPLETE) + { + if (fade.dir==FADE_OUT) + { + demomode = DEMO_NODEMO; + pCKP->Control.levelcontrol.level_done = LEVEL_COMPLETE; + pCKP->Control.levelcontrol.command = LVLC_CHANGE_LEVEL; + if (pCKP->Control.levelcontrol.curlevel != WM_MAP_NUM) + { // exiting a level, going back to world map + for(i=0;iControl.levelcontrol.success==1) + { // mark level as completed on world map + pCKP->Control.levelcontrol.levels_completed[pCKP->Control.levelcontrol.curlevel] = 1; + } + pCKP->Control.levelcontrol.chglevelto = WM_MAP_NUM; + } + } + else + { + fade.mode = NO_FADE; + } + } + + // when walking through the exit door don't show keen's sprite past + // the door frame (so it looks like he walks "through" the door) + if (pCKP->Control.levelcontrol.level_done==LEVEL_DONE_WALK) + { + gamepdo_walkbehindexitdoor(pCKP->Control.levelcontrol.level_finished_by, pCKP); + } + + // allow enter to return to main menu + // if we're in game over mode + + enter = (g_pInput->getPressedCommand(IC_STATUS)); + if (pCKP->Control.levelcontrol.gameovermode) + { + if (enter) + { + int cities=0; + CHighScores *HighScoreTable; + + if (pCKP->Control.levelcontrol.levels_completed[4]) cities++; + if (pCKP->Control.levelcontrol.levels_completed[6]) cities++; + if (pCKP->Control.levelcontrol.levels_completed[7]) cities++; + if (pCKP->Control.levelcontrol.levels_completed[13]) cities++; + if (pCKP->Control.levelcontrol.levels_completed[11]) cities++; + if (pCKP->Control.levelcontrol.levels_completed[9]) cities++; + if (pCKP->Control.levelcontrol.levels_completed[15]) cities++; + if (pCKP->Control.levelcontrol.levels_completed[16]) cities++; + + HighScoreTable = new CHighScores(pCKP); + + bool extras[4] = {false,false,false,false}; + + // check inventory or saved cities + if(pCKP->Control.levelcontrol.episode == 1) + { + if(player[0].inventory.HasJoystick) + extras[0] = true; + if(player[0].inventory.HasBattery) + extras[1] = true; + if(player[0].inventory.HasVacuum) + extras[2] = true; + if(player[0].inventory.HasFuel) + extras[3] = true; + } + + HighScoreTable->writeHighScore((int)player[0].inventory.score,extras,cities); + + HighScoreTable->showHighScore(); + + delete HighScoreTable; + + + if (fade.mode!=FADE_GO && fade.dir!=FADE_OUT) + { + fade.dir = FADE_OUT; + fade.curamt = PAL_FADE_SHADES; + fade.fadetimer = 0; + fade.rate = FADE_NORM; + fade.mode = FADE_GO; + } + + pCKP->Control.levelcontrol.command = LVLC_GAME_OVER; + + } + + if (fade.mode==FADE_COMPLETE && fade.dir==FADE_OUT) + { + pCKP->Control.levelcontrol.command = LVLC_GAME_OVER; + } + } + + #ifdef NETWORK_PLAY +// if (numplayers>1) net_senddata(); + #endif + + if (g_pInput->getPressedKey(KQUIT)) + { + VerifyQuit(pCKP); + } + if (QuitState != NO_QUIT) return; + + // limit frame rate + if (!acceleratemode) + { + g_pInput->pollEvents(); + g_pTimer->SpeedThrottle(); + #ifdef NETWORK_PLAY +// if (numplayers>1) net_sync(); + #endif + } + + if(g_pInput->getExitEvent()) + { + g_pInput->sendKey(KQUIT); + g_pInput->cancelExitEvent(); + } + + } while(!crashflag && pCKP->Control.levelcontrol.command==LVLC_NOCOMMAND); + + // Cleanup the player structure! + +} + +// gives keycard for door doortile to player p +void give_keycard(int doortile, int p) +{ + bool keystack = options[OPT_KEYCARDSTACK].value; // True if set + g_pSound->playSound(SOUND_GET_CARD, PLAY_NOW); + + if (doortile==DOOR_YELLOW) player[p].inventory.HasCardYellow = keystack ? player[p].inventory.HasCardYellow + 1 : 1; + else if (doortile==DOOR_RED) player[p].inventory.HasCardRed = keystack ? player[p].inventory.HasCardRed + 1 : 1; + else if (doortile==DOOR_GREEN) player[p].inventory.HasCardGreen = keystack ? player[p].inventory.HasCardGreen + 1 : 1; + else if (doortile==DOOR_BLUE) player[p].inventory.HasCardBlue = keystack ? player[p].inventory.HasCardBlue + 1 : 1; + else + { + crashflag = 1; + crashflag2 = doortile; + why_term_ptr = "give_keycard(): invalid value for doortile parameter."; + } +} + +// take away the specified keycard from player p +void take_keycard(int doortile, int p) +{ + if (doortile==DOOR_YELLOW) player[p].inventory.HasCardYellow--; + else if (doortile==DOOR_RED) player[p].inventory.HasCardRed--; + else if (doortile==DOOR_GREEN) player[p].inventory.HasCardGreen--; + else if (doortile==DOOR_BLUE) player[p].inventory.HasCardBlue--; + + if(player[p].inventory.HasCardYellow > 9) player[p].inventory.HasCardYellow = 0; + if(player[p].inventory.HasCardRed > 9) player[p].inventory.HasCardRed = 0; + if(player[p].inventory.HasCardGreen > 9) player[p].inventory.HasCardGreen = 0; + if(player[p].inventory.HasCardBlue > 9) player[p].inventory.HasCardBlue = 0; +} + +// unregisters all animated tiles with baseframe tile +void unregister_animtiles(int tile) +{ +int i; + for(i=0;iplaySound(SOUND_DOOR_OPEN, PLAY_NOW); + + take_keycard(doortile, cp); + + /* erase door from map */ + if (pCKP->Control.levelcontrol.episode==3) + { + chgtotile = map.mapdata[mpx-1][mpy]; + } + else + { + chgtotile = tiles[map.mapdata[mpx][mpy]].chgtile; + } + + if(TileProperty[map.mapdata[mpx][mpy-1]][BEHAVIOR] > 1 && + TileProperty[map.mapdata[mpx][mpy-1]][BEHAVIOR] < 6) // This happens because, sometimes the player opens the door + // from a lower part. + { + map_chgtile(mpx, mpy-1, chgtotile); + tilefix=1; + + } + if(TileProperty[map.mapdata[mpx][mpy]][BEHAVIOR] > 1 && + TileProperty[map.mapdata[mpx][mpy]][BEHAVIOR] < 6) // This happens because, sometimes the player opens the door + // from a lower part. + { + map_chgtile(mpx, mpy, chgtotile); // upper? + + } + if(TileProperty[map.mapdata[mpx][mpy+1]][BEHAVIOR] > 1 && + TileProperty[map.mapdata[mpx][mpy+1]][BEHAVIOR] < 6) // This happens because, sometimes the player opens the door + // from a lower part. + { + map_chgtile(mpx, mpy+1, chgtotile); // When he stands in front of the door! + } + + // replace the door tiles with a door object, which will do the animation + o = spawn_object(mpx<<4< than "extra life at" and award 1-UPs when appropriate +void extralifeat(int cp) +{ + if (player[cp].inventory.score > player[cp].inventory.extralifeat) + { + g_pSound->playSound(SOUND_EXTRA_LIFE, PLAY_NOW); + player[cp].inventory.lives++; + player[cp].inventory.extralifeat += 20000; + } +} + +// have keen pick up the goodie at screen pixel position (px, py) +void keen_get_goodie(int px, int py, int theplayer, stCloneKeenPlus *pCKP) +{ +int mpx,mpy,t; +/*int i;*/ + mpx = px>>4; + mpy = py>>4; + t = map.mapdata[mpx][mpy]; + + if ((TileProperty[t][BEHAVIOR] < 17 && TileProperty[t][BEHAVIOR] > 5) || + (TileProperty[t][BEHAVIOR] > 17 && TileProperty[t][BEHAVIOR] < 22) || + (TileProperty[t][BEHAVIOR] == 27 || TileProperty[t][BEHAVIOR] == 28) ) // All pickupable items + //if (tiles[t].pickupable) + { // pick up the goodie, i.e. erase it from the map + map_chgtile(mpx, mpy, tiles[t].chgtile); + //if (tiles[t].isAnimated) map_deanimate(mpx, mpy); + if (TileProperty[t][ANIMATION] != 1) map_deanimate(mpx, mpy); + } + else if (TileProperty[t][BEHAVIOR] == 1) + //else if (tiles[t].lethal) + { // whoah, this "goodie" isn't so good... + killplayer(theplayer, pCKP); + return; + } + + // do whatever the goodie is supposed to do... + procgoodie(t, mpx, mpy, theplayer, pCKP); +} + +void initgame(stCloneKeenPlus *pCKP) +{ +int x,y; +unsigned int i; + + animtiletimer = curanimtileframe = 0; + //PlatExtending = 0; + + // reset player walk frame widths + for(i=0;iControl.levelcontrol.episode==1) + { + gunfirefreq = ICECANNON_FIRE_FREQ; + } + else + { + gunfirefreq = GUN_FIRE_FREQ; + } + + // reset the ysize attribute of all doors + sprites[DOOR_YELLOW_SPRITE].ysize = 32; + sprites[DOOR_RED_SPRITE].ysize = 32; + sprites[DOOR_GREEN_SPRITE].ysize = 32; + sprites[DOOR_BLUE_SPRITE].ysize = 32; + + pCKP->Control.levelcontrol.level_done_timer = 0; + pCKP->Control.levelcontrol.gameovermode = 0; + + // all objects -> not exist + for(i=1;iControl.levelcontrol.episode==1) + { + objdefsprites[OBJ_YORP] = OBJ_YORP_DEFSPRITE; + objdefsprites[OBJ_GARG] = OBJ_GARG_DEFSPRITE; + objdefsprites[OBJ_BUTLER] = OBJ_BUTLER_DEFSPRITE; + objdefsprites[OBJ_TANK] = OBJ_TANK_DEFSPRITE; + objdefsprites[OBJ_ICECHUNK] = OBJ_ICECHUNK_DEFSPRITE; + objdefsprites[OBJ_ICEBIT] = OBJ_ICEBIT_DEFSPRITE; + objdefsprites[OBJ_ROPE] = OBJ_ROPE_DEFSPRITE; + + objdefsprites[OBJ_RAY] = OBJ_RAY_DEFSPRITE_EP1; + objdefsprites[OBJ_VORT] = OBJ_VORT_DEFSPRITE_EP1; + } + else if (pCKP->Control.levelcontrol.episode==2) + { + objdefsprites[OBJ_WALKER] = OBJ_WALKER_DEFSPRITE; + objdefsprites[OBJ_TANKEP2] = OBJ_TANKEP2_DEFSPRITE; + objdefsprites[OBJ_BEAR] = OBJ_BEAR_DEFSPRITE; + + objdefsprites[OBJ_RAY] = OBJ_RAY_DEFSPRITE_EP2; + objdefsprites[OBJ_VORT] = OBJ_VORT_DEFSPRITE_EP2; + objdefsprites[OBJ_PLATFORM] = OBJ_PLATFORM_DEFSPRITE_EP2; + objdefsprites[OBJ_BABY] = OBJ_BABY_DEFSPRITE_EP2; + } + else if (pCKP->Control.levelcontrol.episode==3) + { + objdefsprites[OBJ_FOOB] = OBJ_FOOB_DEFSPRITE; + objdefsprites[OBJ_NINJA] = OBJ_NINJA_DEFSPRITE; + objdefsprites[OBJ_MOTHER] = OBJ_MOTHER_DEFSPRITE; + objdefsprites[OBJ_MEEP] = OBJ_MEEP_DEFSPRITE; + objdefsprites[OBJ_BALL] = OBJ_BJ_DEFSPRITE; + objdefsprites[OBJ_JACK] = OBJ_BJ_DEFSPRITE; + + objdefsprites[OBJ_RAY] = OBJ_RAY_DEFSPRITE_EP3; + objdefsprites[OBJ_VORT] = OBJ_VORT_DEFSPRITE_EP3; + objdefsprites[OBJ_PLATFORM] = OBJ_PLATFORM_DEFSPRITE_EP3; + objdefsprites[OBJ_BABY] = OBJ_BABY_DEFSPRITE_EP3; + } + + objdefsprites[OBJ_DOOR] = DOOR_YELLOW_SPRITE; + objdefsprites[OBJ_TELEPORTER] = OBJ_TELEPORTER_DEFSPRITE; + + objdefsprites[OBJ_SECTOREFFECTOR] = BlankSprite; + +// initilize game variables + pCKP->Control.levelcontrol.level_done = LEVEL_NOT_DONE; + animtiletimer = curanimtileframe = 0; + DemoObjectHandle = 0; + + for(i=0;iControl.levelcontrol.levels_completed[i] = 0; + + for(i=0;iControl.levelcontrol.episode==1) + { + player[i].inventory.charges = 0; + } + else if (pCKP->Control.levelcontrol.episode==2) + { + player[i].inventory.charges = 3; + } + else + { + player[i].inventory.charges = 5; + } + if (demomode) player[i].inventory.charges = 100; + + // start with pogo stick in all episodes but 1 + if (pCKP->Control.levelcontrol.episode!=1 || demomode) + { player[i].inventory.HasPogo = 1; } + else + { player[i].inventory.HasPogo = 0; } + } + + initsprites(pCKP, s); + + if (demomode) srand(375); + + primaryplayer = 0; + + return 0; +} + +char spawn_object(int x, int y, int otype) +{ +int i; + // find an unused object slot + for(i=1;i>CSF)+ysize; + if ((temp>>4)<<4 != temp) + { + objects[o].blockedd = 0; + } + else + { // on a tile boundary, test if tile under object is solid + objects[o].blockedd = 0; + x = (objects[o].x>>CSF); + y = (objects[o].y>>CSF)+ysize+1; + for(xa=0;xa 1 && + TileProperty[getmaptileat(x+xa,y)][BEHAVIOR] < 6) ) + { + objects[o].blockedd = 1; + goto setblockedd; + } + } + if(TileProperty[getmaptileat(x+xsize-2, y)][BUP] || (TileProperty[getmaptileat(x+xa,y)][BEHAVIOR] > 1 && + TileProperty[getmaptileat(x+xa,y)][BEHAVIOR] < 6) ) + { + objects[o].blockedd = 1; + } + setblockedd: ; + } + + // set blockedu + objects[o].blockedu = 0; + x = (objects[o].x>>CSF); + y = (objects[o].y>>CSF)-1; + for(xa=0;xa>CSF)-1; + y = (objects[o].y>>CSF)+1; + for(ya=0;ya>CSF)+ysize-1))][BRIGHT]) + //if (tiles[getmaptileat(x, ((objects[o].y>>CSF)+ysize-1))].solidr) + { + objects[o].blockedl = 1; + } + setblockedl: ; + + // set blockedr + objects[o].blockedr = 0; + x = (objects[o].x>>CSF)+xsize; + y = (objects[o].y>>CSF)+1; + for(ya=0;ya>CSF)+ysize-1))][BLEFT]) + //if (tiles[getmaptileat(x, ((objects[o].y>>CSF)+ysize-1))].solidl) + { + objects[o].blockedr = 1; + } + setblockedr: ; + + // hit detection with players + objects[o].touchPlayer = 0; + for(cplayer=0;cplayerOBJ_YINERTIA_RATE) + { + if (objects[o].yinertia < OBJFALLSPEED) objects[o].yinertia++; + objects[o].yinertiatimer = 0; + } else objects[o].yinertiatimer++; + } + objects[o].y += objects[o].yinertia; + } +} + +// returns nonzero if object1 overlaps object2 +char hitdetect(int object1, int object2) +{ +int s1, s2; +unsigned int rect1x1, rect1y1, rect1x2, rect1y2; +unsigned int rect2x1, rect2y1, rect2x2, rect2y2; + + // get the sprites used by the two objects + s1 = objects[object1].sprite; + s2 = objects[object2].sprite; + + // get the bounding rectangle of the first object + rect1x1 = objects[object1].x + sprites[s1].bboxX1; + rect1y1 = objects[object1].y + sprites[s1].bboxY1; + rect1x2 = objects[object1].x + sprites[s1].bboxX2; + rect1y2 = objects[object1].y + sprites[s1].bboxY2; + + // get the bounding rectangle of the second object + rect2x1 = objects[object2].x + sprites[s2].bboxX1; + rect2y1 = objects[object2].y + sprites[s2].bboxY1; + rect2x2 = objects[object2].x + sprites[s2].bboxX2; + rect2y2 = objects[object2].y + sprites[s2].bboxY2; + + // find out if the rectangles overlap + if ((rect1x1 < rect2x1) && (rect1x2 < rect2x1)) return 0; + if ((rect1x1 > rect2x2) && (rect1x2 > rect2x2)) return 0; + if ((rect1y1 < rect2y1) && (rect1y2 < rect2y1)) return 0; + if ((rect1y1 > rect2y2) && (rect1y2 > rect2y2)) return 0; + + return 1; +} + +void killplayer(int theplayer, stCloneKeenPlus *pCKP) +{ + if (player[theplayer].godmode || g_pInput->getHoldedKey(KTAB)) return; + if (player[theplayer].ankhtime) return; + if (pCKP->Control.levelcontrol.level_done) return; + if (!player[theplayer].pdie) + { + player[theplayer].pdie = PDIE_DYING; + player[theplayer].pdieframe = 0; + player[theplayer].pdietimer = 0; + player[theplayer].pdietillfly = DIE_TILL_FLY_TIME; + player[theplayer].pdie_xvect = rand()%(DIE_MAX_XVECT*2); + player[theplayer].pdie_xvect -= DIE_MAX_XVECT; + player[theplayer].inventory.lives--; + player[theplayer].y += (8<stop(); + g_pSound->playSound(SOUND_KEEN_DIE, PLAY_NOW); + } +} + +void freezeplayer(int theplayer) +{ + if (player[theplayer].godmode /*|| immediate_keytable[KTAB]*/) return; + if (player[theplayer].ankhtime) return; + // give the player a little "kick" + player[theplayer].pjumptime = PJUMP_NORMALTIME_1; + player[theplayer].pjumpupdecreaserate = PJUMP_UPDECREASERATE_1; + player[theplayer].pjumpupspeed = 15; + player[theplayer].pjumping = PJUMPUP; + player[theplayer].pjumpupspeed_decreasetimer = 0; + player[theplayer].pjustjumped = 1; + + // and freeze him (stun him on ep2/3) + player[theplayer].pfrozentime = PFROZEN_TIME; + player[theplayer].pfrozenframe = 0; + player[theplayer].pfrozenanimtimer = 0; + player[theplayer].ppogostick = false; +} + + +void PlayerTouchedExit(int theplayer, stCloneKeenPlus *pCKP) +{ +/*int i;*/ + if (!player[theplayer].pjumping && !player[theplayer].pfalling\ + && !player[theplayer].ppogostick && \ + pCKP->Control.levelcontrol.level_done==LEVEL_NOT_DONE) + { + // don't allow player to walk through a door if he's standing + // on an object such as a platform or an enemy + if (player[theplayer].psupportingobject) + { + return; + } + + // if player has ankh shut it off + if (player[theplayer].ankhtime) + { + player[theplayer].ankhtime = 0; + objects[player[theplayer].ankhshieldobject].exists = 0; + } + + player[theplayer].ppogostick = false; + + g_pMusicPlayer->stop(); + g_pSound->playSound(SOUND_LEVEL_DONE, PLAY_NOW); + pCKP->Control.levelcontrol.level_done = LEVEL_DONE_WALK; + pCKP->Control.levelcontrol.level_finished_by = theplayer; + } +} + +void endlevel(int success, stCloneKeenPlus *pCKP) +{ + if (fade.mode == NO_FADE) + { + fade.dir = FADE_OUT; + fade.curamt = PAL_FADE_SHADES; + fade.fadetimer = 0; + fade.rate = FADE_NORM; + fade.mode = FADE_GO; + pCKP->Control.levelcontrol.success = success; + pCKP->Control.levelcontrol.tobonuslevel = 0; + } +} + +void SetGameOver(stCloneKeenPlus *pCKP) +{ +/*int x,y,bmnum;*/ + if (!pCKP->Control.levelcontrol.gameovermode) + { + pCKP->Control.levelcontrol.gameovermode = 1; + g_pSound->playSound(SOUND_GAME_OVER, PLAY_NOW); + } +} + + +// this is so objects can block the player, +// player can stand on them, etc. +// x and y are the CSFed coordinates to check (e.g. playx and playy) +// returns nonzero if there is a solid object +// at that point +char checkobjsolid(unsigned int x, unsigned int y, unsigned int cp) +{ + int o; + + for(o=1;o= objects[o].x+sprites[objects[o].sprite].bboxX1) + if (x <= objects[o].x+sprites[objects[o].sprite].bboxX2) + if (y >= objects[o].y+sprites[objects[o].sprite].bboxY1) + if (y <= objects[o].y+sprites[objects[o].sprite].bboxY2) + return o; + } + } + return 0; +} + +// returns 1 if player cp has the card to door t, which -> door +char CheckDoorBlock(int t, int cp, int which,stCloneKeenPlus *pCKP) +{ + if (which==DOOR_YELLOW) + { + if (!player[cp].inventory.HasCardYellow) + { + player[cp].blockedby = t; + return 1; + } + } + else if (which==DOOR_RED) + { + if (!player[cp].inventory.HasCardRed) + { + player[cp].blockedby = t; + return 1; + } + } + else if (which==DOOR_GREEN) + { + if (!player[cp].inventory.HasCardGreen) + { + player[cp].blockedby = t; + return 1; + } + } + else if (which==DOOR_BLUE) + { + if (!player[cp].inventory.HasCardBlue) + { + player[cp].blockedby = t; + return 1; + } + } + + return 0; +} + +// checks if tile at (x,y) is solid to the player walking left into it. +// returns 1 and sets blockedby if so. +char checkissolidl(int x, int y, int cp, stCloneKeenPlus *pCKP) +{ +int t; + t = getmaptileat(x, y); + + if(TileProperty[t][BLEFT] || x < 0) + //if (tiles[t].solidl) + { + player[cp].blockedby = t; + return 1; + } + if (checkobjsolid(x<=16) + { + y2 = 0; + t++; + } + } +} + +// creates a mask from a sourcetile, places it in desttile +void MakeMask(int sourcetile, int desttile, int transparentcol) +{ +int x,y,c; + for(y=0;y<16;y++) + { + for(x=0;x<16;x++) + { + c = tiledata[sourcetile][y][x]; + if (c != transparentcol) c = 0; else c = 15; + tiledata[desttile][y][x] = c; + } + } +} + +// replaces all instances of color find in sprite s with +// color replace, as long as the y is greater than miny +void ReplaceSpriteColor(int s, int find, int replace, int miny) +{ +int x,y; + + for(y=miny;yControl.levelcontrol.episode==1) + { + +// MakeMask(443, 155, 7); + // tiles[443].masktile = 155; +// tiles[428].masktile = 155; + } +} + +void procgoodie(int t, int mpx, int mpy, int theplayer, stCloneKeenPlus *pCKP) +{ + if ((TileProperty[t][BEHAVIOR] > 5 && TileProperty[t][BEHAVIOR] < 11) || + (TileProperty[t][BEHAVIOR] > 17 && TileProperty[t][BEHAVIOR] < 22) ) + { + if((player[theplayer].x*player[theplayer].y) % 2 == 1) + g_pSound->playStereofromCoord(SOUND_GET_BONUS, PLAY_NOW, 0); + else + g_pSound->playStereofromCoord(SOUND_GET_BONUS, PLAY_NOW, 320); + } + else if (TileProperty[t][BEHAVIOR] > 10 && TileProperty[t][BEHAVIOR] < 16) g_pSound->playSound(SOUND_GET_ITEM, PLAY_NOW); + switch(TileProperty[t][BEHAVIOR]) + { + // keycards + case 18: give_keycard(DOOR_YELLOW, theplayer); break; + case 19: give_keycard(DOOR_RED, theplayer); break; + case 20: give_keycard(DOOR_GREEN, theplayer); break; + case 21: give_keycard(DOOR_BLUE, theplayer); break; + + case DOOR_YELLOW: + if (player[theplayer].inventory.HasCardYellow) + open_door(DOOR_YELLOW, DOOR_YELLOW_SPRITE, mpx, mpy, theplayer, pCKP); + break; + case DOOR_RED: + if (player[theplayer].inventory.HasCardRed) + open_door(DOOR_RED, DOOR_RED_SPRITE, mpx, mpy, theplayer, pCKP); + break; + case DOOR_GREEN: + if (player[theplayer].inventory.HasCardGreen) + open_door(DOOR_GREEN, DOOR_GREEN_SPRITE, mpx, mpy, theplayer, pCKP); + break; + case DOOR_BLUE: + if (player[theplayer].inventory.HasCardBlue) + open_door(DOOR_BLUE, DOOR_BLUE_SPRITE, mpx, mpy, theplayer, pCKP); + break; + + case 7: // What gives you 100 Points + player[theplayer].inventory.score += 100; extralifeat(theplayer); + break; + case 8: // What gives you 200 Points + player[theplayer].inventory.score += 200; extralifeat(theplayer); + break; + case 6: // What gives you 500 Points + player[theplayer].inventory.score += 500; extralifeat(theplayer); + break; + case 9: // What gives you 1000 Points + player[theplayer].inventory.score += 1000; extralifeat(theplayer); + break; + case 10: // What gives you 5000 Points + player[theplayer].inventory.score += 5000; extralifeat(theplayer); + break; + + case 15: // raygun + player[theplayer].inventory.charges += 5; + break; + case 16: // the Holy Pogo Stick + player[theplayer].inventory.HasPogo = 1; + g_pSound->playSound(SOUND_GET_PART, PLAY_NOW); + break; + + case 11: + player[theplayer].inventory.HasJoystick = 1; + g_pSound->playSound(SOUND_GET_PART, PLAY_NOW); + break; + + case 12: + player[theplayer].inventory.HasBattery = 1; + g_pSound->playSound(SOUND_GET_PART, PLAY_NOW); + break; + case 13: + + player[theplayer].inventory.HasVacuum = 1; + g_pSound->playSound(SOUND_GET_PART, PLAY_NOW); + break; + case 14: + player[theplayer].inventory.HasFuel = 1; + g_pSound->playSound(SOUND_GET_PART, PLAY_NOW); + break; + + // in-level teleporter + // (in level13.ck1 that takes you to the bonus level) + case 24: + endlevel(0, pCKP); + pCKP->Control.levelcontrol.tobonuslevel = 1; + break; + + case YORPSTATUEHEAD: + if(pCKP->Control.levelcontrol.episode == 1) + { + youseeinyourmind(mpx, mpy, pCKP); + } + else if(pCKP->Control.levelcontrol.episode == 2) + if(!player[theplayer].blockedr && !player[theplayer].blockedl) + VorticonElder(mpx, mpy, pCKP); + break; + + case 27: + if(pCKP->Control.levelcontrol.episode == 3) + GiveAnkh(theplayer); + break; + case 28: + player[theplayer].inventory.charges++; + g_pSound->playSound(SOUND_GET_ITEM, PLAY_NOW); + break; + + case 17: + if (pCKP->Control.levelcontrol.canexit && (!pCKP->Control.levelcontrol.isfinallevel || player[theplayer].inventory.HasFuel)) + { + pCKP->Control.levelcontrol.exitXpos = (mpx+2)<<4; + PlayerTouchedExit(theplayer, pCKP); + } + break; + + case 23:break; // these are switches. They cannot not be picked up! + case 25:break; // Refer to JumpandPogo to check the activation code + case 26:break; + + // we fell off the bottom of the map + case TILE_FELLOFFMAP_EP1: + if (!player[theplayer].pdie) + { + g_pSound->playSound(SOUND_KEEN_FALL, PLAY_FORCE); + player[theplayer].ankhtime = 0; + player[theplayer].godmode = 0; + player[theplayer].pdie = PDIE_FELLOFFMAP; + } + break; + + default: + why_term_ptr = "procgoodie_ep1: Unknown goodie-- value given in flag2."; + break; + } + + +} + +void GiveAnkh(int cp) +{ +int o; + if (!player[cp].ankhtime) + { + o = spawn_object(player[cp].x, player[cp].y, OBJ_SECTOREFFECTOR); + objects[o].ai.se.type = SE_ANKHSHIELD; + player[cp].ankhshieldobject = o; + } + + g_pSound->playSound(SOUND_ANKH, PLAY_NOW); + player[cp].ankhtime = PLAY_ANKH_TIME; + gamepdo_ankh(cp); +} + +void gameloop_initialize(stCloneKeenPlus *pCKP) +{ +unsigned int x,y,i/*,tl*/; +int timeout; + + if (pCKP->Control.levelcontrol.episode == 3) + { + // coat the top of the map ("oh no!" border) with a non-solid tile + // so keen can jump partially off the top of the screen + for(x=1;xControl.levelcontrol.episode==1) + { + // coat the bottom of the map below the border. + // since the border has solidceil=1 this provides + // a platform to catch yorps that fall off the map + y = map.ysize; + for(x=2;x>CSF>>4 < (map.xsize/2) || pCKP->Control.levelcontrol.episode==1) + { + x += (18<>CSF>>4 < (map.xsize/2) || pCKP->Control.levelcontrol.episode==1) + player[i].pdir = player[i].pshowdir = RIGHT; + else + player[i].pdir = player[i].pshowdir = LEFT; + } + } + +// scroll past the first two tiles (the level border), they'll +// now never be visible because you're not allowed to scroll +// left past X=32. + for(i=0;i<2*16;i++) + { + map_scroll_right(); + map_scroll_down(); + } + +// scroll the screen until the primary player is onscreen +// enough to where he doesn't set off the scroll triggers + for(timeout=0;timeout<10000;timeout++) + { + if (!gamedo_ScrollTriggers(primaryplayer)) break; + } + + // initiate fade-in + fade.mode = FADE_GO; + fade.dir = FADE_IN; + fade.rate = FADE_NORM; + fade.curamt = 0; + fade.fadetimer = 0; + + // "keens left" when returning to world map after dying + if (pCKP->Control.levelcontrol.dokeensleft) + { + keensleft(pCKP); + pCKP->Control.levelcontrol.dokeensleft = 0; + } + +} diff --git a/src/include/declarations.h b/src/include/declarations.h index eba9dd909..4b1de124d 100644 --- a/src/include/declarations.h +++ b/src/include/declarations.h @@ -3,6 +3,7 @@ #include #include +#include #define MAX_COMMANDS 8 #define MAX_SOUND_LENGTH 1024 @@ -11,7 +12,7 @@ #define MAX_NUMBER_OF_FILES 100 -typedef struct stDisplay +struct stDisplay { unsigned int Width; unsigned int Height; @@ -21,15 +22,18 @@ typedef struct stDisplay short Filtermode; short Zoom; unsigned short FrameSkip; -} stDisplay; + + // as long as we only have POD + stDisplay() { memset(this, 0, sizeof(stDisplay)); } +}; -typedef struct stDevice +struct stDevice { SDL_Joystick *Joystick; SDL_Event Event; -} stDevice; +}; -typedef struct stLevelControl +struct stLevelControl { // level control int command; // used to give a command to playgame_levelmanager() @@ -57,18 +61,23 @@ typedef struct stLevelControl unsigned int level_done, level_done_timer; unsigned int level_finished_by; // index of player that finished level unsigned int exitXpos; -} stLevelControl; + + // as long as we only have POD + stLevelControl() { memset(this, 0, sizeof(stLevelControl)); } +}; -typedef struct stControl +struct stControl { - short eseq; // see only the ending sequence - short dtm; // go direct to map. - short storyboard; // go to storyboard - short skipstarting; // Skip Startmenu, Intro and Mainmenu. + bool eseq; // see only the ending sequence + bool dtm; // go direct to map. + bool storyboard; // go to storyboard + bool skipstarting; // Skip Startmenu, Intro and Mainmenu. stLevelControl levelcontrol; -} stControl; + + stControl() : eseq(false), dtm(false), storyboard(false), skipstarting(false) {} +}; struct stGameData { diff --git a/src/include/gui/dialog.h b/src/include/gui/dialog.h index feacde3fc..8f319b9e3 100644 --- a/src/include/gui/dialog.h +++ b/src/include/gui/dialog.h @@ -8,50 +8,52 @@ * Author: gerstrong */ +#ifndef __CG_DIALIG_H__ +#define __CG_DIALIG_H__ + +#include +#include + #define STARTER_SAVE 1 #define STARTER_ESCAPE 2 #define STARTER_SOUNDOPT 3 #define STARTER_DISPLAYOPT 4 #define STARTER_GAMEOPT 5 -typedef struct stTextLine +struct stTextLine { - char *Text; + std::string Text; short ID; // items are orded by ID -} stTextLine; +}; -typedef struct stSeparator +struct stSeparator { short ID; // items are orded by ID -} stSeparator; +}; -typedef struct stOptionSwitch +struct stOptionSwitch { char *Name; char **Option; short selected; short numSel; short ID; // items are orded by ID -} stOptionSwitch; +}; -typedef struct stStarterSwitch +struct stStarterSwitch { - char *Name; + std::string Name; int numFunctionToLaunch; short ID; // items are sorted by IDs -} stStarterSwitch; +}; -typedef struct stDlgStruct // imagine every substructure as typical control +struct stDlgStruct // imagine every substructure as typical control { - stTextLine *TextLine; - stOptionSwitch *OptionSwitch; - stStarterSwitch *StarterSwitch; - stSeparator *Separator; + std::vector TextLine; + std::vector OptionSwitch; + std::vector StarterSwitch; + std::vector Separator; +}; - short num_TextLines; - short num_OptionSwitches; - short num_StarterSwitch; - short num_Separators; - -} stDlgStruct; +#endif diff --git a/src/keen.h b/src/keen.h index 6c51fa217..20c5964fb 100644 --- a/src/keen.h +++ b/src/keen.h @@ -119,15 +119,15 @@ typedef struct stMap #define BDOWN 4 #define BLEFT 5 -typedef struct stBitmap +struct stBitmap { int xsize; int ysize; unsigned char *bmptr; char name[9]; -} stBitmap; +}; -typedef struct stSprite +struct stSprite { char xsize, ysize; unsigned char imgdata[64][64]; @@ -135,9 +135,9 @@ typedef struct stSprite // bounding box for hit detection unsigned int bboxX1, bboxY1; unsigned int bboxX2, bboxY2; -} stSprite; +}; -typedef struct stInventory +struct stInventory { unsigned long score; unsigned long extralifeat; @@ -153,7 +153,7 @@ typedef struct stInventory unsigned char HasFuel; unsigned char HasBattery; unsigned char HasVacuum; -} stInventory; +}; // for strings loaded from "strings.dat" #define MAX_STRINGS 100 @@ -169,7 +169,7 @@ struct stString }; /* Structs used for different enemies data, these are in a union */ -typedef struct stYorpData +struct stYorpData { unsigned char state; @@ -180,8 +180,9 @@ typedef struct stYorpData signed int yorpdie_inertia_y; unsigned char movedir; -} stYorpData; -typedef struct stGargData +}; + +struct stGargData { unsigned char state; @@ -194,8 +195,9 @@ typedef struct stGargData unsigned char movedir; unsigned char detectedPlayer, detectedPlayerIndex; -} stGargData; -typedef struct stVortData +}; + +struct stVortData { unsigned char state; @@ -218,8 +220,9 @@ typedef struct stVortData int JumpLeftFrame; int DyingFrame; int DeadFrame; -} stVortData; -typedef struct stBearData +}; + +struct stBearData { unsigned char state; @@ -232,8 +235,9 @@ typedef struct stBearData unsigned int running; int dist_traveled; -} stBearData; -typedef struct stButlerData +}; + +struct stButlerData { unsigned char state; unsigned char timer,animtimer; @@ -241,8 +245,9 @@ typedef struct stButlerData unsigned int dist_traveled; unsigned char movedir; -} stButlerData; -typedef struct stTankData +}; + +struct stTankData { unsigned char state; @@ -264,8 +269,9 @@ typedef struct stTankData unsigned int firetimes; unsigned int timetillcanfire; unsigned int timetillcanfirecauseonsamelevel; -} stTankData; -typedef struct stRayData +}; + +struct stRayData { char state; char direction; @@ -280,20 +286,23 @@ typedef struct stRayData // for earth chunks int baseframe; -} stRayData; -typedef struct stDoorData +}; + +struct stDoorData { char timer; char distance_traveled; -} stDoorData; -typedef struct stIceChunk +}; + +struct stIceChunk { char movedir; char state; unsigned int originalX, originalY; int timer; -} stIceChunk; -typedef struct stTeleportData +}; + +struct stTeleportData { char animtimer; char animframe; @@ -312,17 +321,18 @@ typedef struct stTeleportData char fadeamt; char fadetimer; -} stTeleportData; -typedef struct stRopeData +}; + +struct stRopeData { char state; int droptimer; int droptimes; int stoneX, stoneY; int vortboss; -} stRopeData; +}; -typedef struct stWalkerData +struct stWalkerData { unsigned char state; @@ -333,9 +343,9 @@ typedef struct stWalkerData unsigned char walkdir; unsigned char kickedplayer[MAX_PLAYERS]; -} stWalkerData; +}; -typedef struct stPlatformData +struct stPlatformData { unsigned char state; unsigned char animframe; @@ -344,9 +354,9 @@ typedef struct stPlatformData unsigned char movedir; unsigned char kickedplayer[MAX_PLAYERS]; -} stPlatformData; +}; -typedef struct stSEData +struct stSEData { unsigned int type; @@ -360,9 +370,9 @@ typedef struct stSEData unsigned int frame; int mx,my; int blowx,blowy; -} stSEData; +}; -typedef struct stBabyData +struct stBabyData { char state; char dir; @@ -373,9 +383,9 @@ typedef struct stBabyData char walkframe; int walktimer; -} stBabyData; +}; -typedef struct stFoobData +struct stFoobData { char state; char dir; @@ -385,9 +395,9 @@ typedef struct stFoobData int OffOfSameLevelTime; int spooktimer; int SpookedByWho; -} stFoobData; +}; -typedef struct stNinjaData +struct stNinjaData { char state; char dir; @@ -401,7 +411,7 @@ typedef struct stNinjaData int KickMoveTimer; int isdying; int dietimer; -} stNinjaData; +}; typedef struct stMotherData { @@ -644,7 +654,7 @@ typedef struct stAnimTile #define SCROLLTRIGGERDOWN 114 // this structure contains all the variables used by a player -typedef struct stPlayer +struct stPlayer { // these coordinates are CSFed unsigned long x; @@ -726,7 +736,9 @@ typedef struct stPlayer unsigned int ankhtime, ankhshieldobject; stInventory inventory; -} stPlayer; + + stPlayer() { memset(this, 0, sizeof(stPlayer)); } +}; typedef struct stShipQueue { @@ -845,7 +857,7 @@ typedef struct stShipQueue #include "keenext.h" #include "sdl/CSettings.h" -typedef struct stCloneKeenPlus +struct stCloneKeenPlus { stCommand Command[MAX_COMMANDS]; SDL_Joystick *Joystick; @@ -857,7 +869,11 @@ typedef struct stCloneKeenPlus stOption Option[NUM_OPTIONS]; unsigned short numGames; unsigned short shutdown; -}stCloneKeenPlus; + + stCloneKeenPlus() : Joystick(NULL), GameData(NULL), numGames(0), shutdown(SHUTDOWN_NONE) { + memset(&Event, 0, sizeof(Event)); + } +}; // keen.c void playgame_levelmanager(stCloneKeenPlus *pCKP); diff --git a/src/menu.cpp b/src/menu.cpp index ed50b0bca..2d372fe42 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -360,14 +360,6 @@ int mainmenu(stCloneKeenPlus *pCKP,int defaultopt) return selection; } -void initialiazeDlgStruct(stDlgStruct *pDlgStruct) -{ - pDlgStruct->OptionSwitch = (stOptionSwitch*) malloc(pDlgStruct->num_OptionSwitches*sizeof(stOptionSwitch)); - pDlgStruct->Separator = (stSeparator*) malloc(pDlgStruct->num_Separators*sizeof(stSeparator)); - pDlgStruct->StarterSwitch = (stStarterSwitch*) malloc(pDlgStruct->num_StarterSwitch*sizeof(stStarterSwitch)); - pDlgStruct->TextLine = (stTextLine*) malloc(pDlgStruct->num_TextLines*sizeof(stTextLine)); -} - int getDifficulty(stCloneKeenPlus *pCKP) { CDialog *DifficultyMenu;