diff --git a/changelog.txt b/changelog.txt index a47b00953..8bce63b4f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,13 @@ Commander Genius Pre-Release v0.3 (CloneKeenPlus): --------------------------------------------------- +-------------------------------------------------- + +08-08-2009 +- Special key items can only be taken once. Even replaying the levels +- Now levels can be exited without doing something before through the exit door. Be careful ;-) +- Vorticon Commander in Ep1 now dies with 105 shots. +- Improved consistency of the program +- Improved Enemys AI + 05-08-2009 - fixed crash when game in EP1 or 2 was ending - fixed fonts problems in story section. diff --git a/src/CGame.cpp b/src/CGame.cpp index 01e8766f7..698f8ab37 100644 --- a/src/CGame.cpp +++ b/src/CGame.cpp @@ -287,8 +287,6 @@ void CGame::preallocateCKP(stCloneKeenPlus *pCKP) pCKP->GameData = NULL; pCKP->GameData = new stGameData[1]; - framebyframe = 0; - pCKP->Control.levelcontrol.demomode = DEMO_NODEMO; current_demo = 1; diff --git a/src/CGraphics.cpp b/src/CGraphics.cpp index 9abfc39a0..5a0593b4a 100644 --- a/src/CGraphics.cpp +++ b/src/CGraphics.cpp @@ -494,7 +494,6 @@ void CGraphics::fadePalette(int fadeamt) { int c; int r,g,b; -if (framebyframe) fadeamt = PAL_FADE_SHADES; for(c=0;c<17;c++) { diff --git a/src/ai/enemydata.h b/src/ai/enemydata.h index 6bb634618..cde4e8b6e 100644 --- a/src/ai/enemydata.h +++ b/src/ai/enemydata.h @@ -51,7 +51,7 @@ typedef struct stVortData unsigned int dist_traveled; signed int inertiay; - char ep1style; // episode 1 style four-shots-to-kill + char hp; // episode 1 style four-shots-to-kill unsigned char movedir; // these hold the animation frames indexes since they're diff --git a/src/ai/vort.cpp b/src/ai/vort.cpp index 5cdafde2a..13e783382 100644 --- a/src/ai/vort.cpp +++ b/src/ai/vort.cpp @@ -44,11 +44,17 @@ int bonk,kill; objects[o].canbezapped = 1; objects[o].needinit = 0; - if (p_levelcontrol->hardmode) + // give him some health points, depening on episode and level + if(p_levelcontrol->episode == 1) { - objects[o].ai.vort.ep1style = 1; + if(p_levelcontrol->curlevel == 16) // He is the vorticon commander and has much more HP + objects[o].ai.vort.hp = 105; + else + objects[o].ai.vort.hp = 4; } - else objects[o].ai.vort.ep1style = 0; + else + objects[o].ai.vort.hp = (p_levelcontrol->hardmode) ? 4 : 1; + // In EP2 and 3 the Vorticons are much weaker, when no hardmode selected // copy in animation frame indexes for the current ep if (p_levelcontrol->episode==1) @@ -59,7 +65,6 @@ int bonk,kill; objects[o].ai.vort.JumpRightFrame = VORT1_JUMP_RIGHT_FRAME; objects[o].ai.vort.JumpLeftFrame = VORT1_JUMP_LEFT_FRAME; objects[o].ai.vort.DyingFrame = VORT1_DYING_FRAME; - objects[o].ai.vort.ep1style = 1; } else if (p_levelcontrol->episode==2) { @@ -89,13 +94,10 @@ int bonk,kill; kill = 0; // if we touch a glowcell, we die! - if (objects[o].zapped >= VORT_HP && !p_levelcontrol->isfinallevel) kill = 1; - else if (objects[o].zapped >= VORT_COMMANDER_HP && p_levelcontrol->isfinallevel) kill = 1; - else if (objects[o].zapped && !objects[o].ai.vort.ep1style) kill = 1; + if ( objects[o].zapped >= objects[o].ai.vort.hp ) kill = 1; else if (p_levelcontrol->episode==2 && getmaptileat((objects[o].x>>CSF)+12, (objects[o].y>>CSF)+16)==TILE_GLOWCELL) - { kill = 1; - } + if (kill) { objects[o].inhibitfall = 0; @@ -294,11 +296,6 @@ vort_reprocess: ; case VORT_DYING: objects[o].sprite = objects[o].ai.vort.DyingFrame + objects[o].ai.vort.frame; - if (p_levelcontrol->isfinallevel && p_levelcontrol->episode==1) - { - p_levelcontrol->canexit = true; - } - if (objects[o].ai.vort.animtimer > VORT_DIE_ANIM_TIME) { objects[o].ai.vort.palflashamt -= PAL_FLASH_DEC_AMT; diff --git a/src/ai/vort.h b/src/ai/vort.h index ec9bb4410..df7e730c6 100644 --- a/src/ai/vort.h +++ b/src/ai/vort.h @@ -19,7 +19,7 @@ // number of shots to kill #define VORT_HP 4 -#define VORT_COMMANDER_HP 99 +#define VORT_COMMANDER_HP 105 #define VORT_DIE_ANIM_TIME 125 #define VORT2_DIE_ANIM_TIME 125 diff --git a/src/cinematics/EndingSequenceEp2.h b/src/cinematics/EndingSequenceEp2.h index 680d366a5..8c357b3f2 100644 --- a/src/cinematics/EndingSequenceEp2.h +++ b/src/cinematics/EndingSequenceEp2.h @@ -14,7 +14,7 @@ void eseq_showmsg(const std::string& text, int boxleft, int boxtop, int boxwidth, int boxheight, bool autodismiss); // references to ../gamedo.cpp -void gamedo_frameskipping(); +void gamedo_frameskipping( bool gameovermode = false ); void gamedo_enemyai(stLevelControl *p_levelcontrol); #endif /* ENDINGSEQUENCEEP2_H_ */ diff --git a/src/fileio.cpp b/src/fileio.cpp index a35e8ec97..44b44943c 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -24,18 +24,31 @@ unsigned int curmapx, curmapy; unsigned char mapdone; void addmaptile(unsigned int t) { - map.mapdata[curmapx][curmapy] = t; - curmapx++; - if (curmapx >= map.xsize) - { - curmapx = 0; - curmapy++; + // Special cases. Those happen normally, when level are not replayed. + // For example if one player has battery, the level won't show that item + for(unsigned int cp=0 ; cp= map.ysize) mapdone = 1; - } + // Now set this this tile at pos(curmapx, curmapy) + map.mapdata[curmapx][curmapy] = t; + + curmapx++; + if (curmapx >= map.xsize) + { + curmapx = 0; + curmapy++; + + if (curmapy >= map.ysize) mapdone = 1; + } } - short checkConsistencyofGameData(stGameData *p_GameData) { short ok = 0; @@ -200,7 +213,7 @@ levelmarker: ; } void addenemytile(unsigned int t, int episode, - int chglevelto, bool *canexit) + int chglevelto) { int o,x; map.objectlayer[curmapx][curmapy] = t; @@ -339,7 +352,6 @@ int o,x; if (episode==2) { o = spawn_object(curmapx<<4<episode; int chglevelto = p_levelcontrol->chglevelto; int *levels_completed = p_levelcontrol->levels_completed; - bool *p_canexit = &(p_levelcontrol->canexit); - NessieAlreadySpawned = 0; map.isworldmap = (lvlnum == 80); @@ -552,7 +562,7 @@ unsigned int loadmap(const std::string& filename, const std::string& path, t = filebuf[c]; if (map.isworldmap) addobjectlayertile(t, episode, levels_completed); - else addenemytile(t, episode, chglevelto, p_canexit); + else addenemytile(t, episode, chglevelto); if (++resetcnt==resetpt) curmapx=curmapy=0; diff --git a/src/game.cpp b/src/game.cpp index b07b6a8de..b07eab089 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -136,10 +136,8 @@ void gameloop(stCloneKeenPlus *pCKP) if (gamedo_ScrollTriggers(primaryplayer)) ScreenIsScrolling = 1; } - - // do frameskipping, and render/blit the screen if it's time - gamedo_frameskipping(); + gamedo_frameskipping( pCKP->Control.levelcontrol.gameovermode ); // when we complete a fade out flag to exit the game loop if (fade.mode==FADE_COMPLETE) @@ -212,7 +210,7 @@ void gameloop(stCloneKeenPlus *pCKP) extras[1] = true; if(player[0].inventory.HasVacuum) extras[2] = true; - if(player[0].inventory.HasFuel) + if(player[0].inventory.HasWiskey) extras[3] = true; } @@ -438,7 +436,7 @@ unsigned int i; sprites[DOOR_BLUE_SPRITE].ysize = 32; p_levelcontrol->level_done_timer = 0; - p_levelcontrol->gameovermode = 0; + p_levelcontrol->gameovermode = false; // all objects -> not exist for(i=1;iControl.levelcontrol.canexit = 1; + player[theplayer].inventory.HasJoystick = true; g_pSound->playSound(SOUND_GET_PART, PLAY_NOW); break; case 12: - player[theplayer].inventory.HasBattery = 1; - pCKP->Control.levelcontrol.canexit = 1; + player[theplayer].inventory.HasBattery = true; g_pSound->playSound(SOUND_GET_PART, PLAY_NOW); break; case 13: - player[theplayer].inventory.HasVacuum = 1; - pCKP->Control.levelcontrol.canexit = 1; + player[theplayer].inventory.HasVacuum = true; g_pSound->playSound(SOUND_GET_PART, PLAY_NOW); break; case 14: - player[theplayer].inventory.HasFuel = 1; - pCKP->Control.levelcontrol.canexit = 1; + player[theplayer].inventory.HasWiskey = true; g_pSound->playSound(SOUND_GET_PART, PLAY_NOW); break; @@ -1251,12 +1245,9 @@ void procgoodie(int t, int mpx, int mpy, int theplayer, stCloneKeenPlus *pCKP) break; case 17: - if (pCKP->Control.levelcontrol.canexit) - { - pCKP->Control.levelcontrol.exitXpos = (mpx+2)<<4; - PlayerTouchedExit(theplayer, pCKP); - } - break; + 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 diff --git a/src/gamedo.cpp b/src/gamedo.cpp index a134b320c..7eb7177eb 100644 --- a/src/gamedo.cpp +++ b/src/gamedo.cpp @@ -21,7 +21,6 @@ #include "include/enemyai.h" - extern unsigned long gotPlayX; extern unsigned long CurrentTickCount; @@ -664,33 +663,26 @@ extern int NumConsoleMessages; // performs frameskipping and blits the display as needed, // at end of functions erases all drawn objects from the scrollbuf. -void gamedo_RenderScreen() -{ - //int x,y, bmnum; - +void gamedo_RenderScreen(bool gameovermode) // gameovermode is not a good idea. +{ // TODO: Make a list of Bitmaps to be drawn and draw them, like the objects and tiles g_pGraphics->renderHQBitmap(); - //if(pCKP != NULL) - //{ - gamedo_render_drawobjects(); + gamedo_render_drawobjects(); // (Sprites) - //if (pCKP->Control.levelcontrol.gameovermode) - // TODO: make this Bitmap also a object or tile to be added. - /*if (special_bitmap == GAMEOVER_BITMAP) - { - // figure out where to center the gameover bitmap and draw it - bmnum = g_pGraphics->getBitmapNumberFromName("GAMEOVER"); - x = (320/2)-(bitmaps[bmnum].xsize/2); - y = (200/2)-(bitmaps[bmnum].ysize/2); - g_pGraphics->drawBitmap(x, y, bmnum); - }*/ - //} - - g_pVideoDriver->sb_blit(); // blit scrollbuffer to display + g_pVideoDriver->sb_blit(); // blit scrollbuffer to display (Tiles) gamedo_render_erasedebug(); gamedo_render_eraseobjects(); + if(gameovermode) // (Gameover Bitmap) More to come! + { + int bmnum = g_pGraphics->getBitmapNumberFromName("GAMEOVER"); + // figure out where to center the gameover bitmap and draw it + int x = (320/2)-(bitmaps[bmnum].xsize/2); + int y = (200/2)-(bitmaps[bmnum].ysize/2); + g_pGraphics->drawBitmap(x, y, bmnum); + } + curfps++; } @@ -804,30 +796,19 @@ int i; player[i].pfrozentime = 0; } } - // F8 - frame by frame - if(g_pInput->getPressedKey(KF8)) - { - framebyframe = 1; - #ifdef BUILD_SDL - g_pVideoDriver->AddConsoleMsg("Frame-by-frame mode F8:advance F7:stop"); - #endif - } + // F9 - exit level immediately if(g_pInput->getPressedKey(KF9)) { endlevel(1, &(pCKP->Control.levelcontrol) ); } + // F6 - onscreen debug--toggle through debug/radar/off if(g_pInput->getPressedKey(KF6)) { debugmode++; if (debugmode>2) debugmode=0; } - // F7 - accelerate mode/frame by frame frame advance - if(g_pInput->getPressedKey(KF7)) - { - if (!framebyframe) acceleratemode=1-acceleratemode; - } } // F10 - change primary player @@ -878,32 +859,20 @@ void gamedo_fades(void) } } -void gamedo_frameskipping() +void gamedo_frameskipping( bool gameovermode ) { - if (framebyframe) - { - gamedo_RenderScreen(); - return; - } - if (frameskiptimer >= g_pVideoDriver->getFrameskip()) { - gamedo_RenderScreen(); - frameskiptimer = 0; - } else frameskiptimer++; + gamedo_RenderScreen(gameovermode); + frameskiptimer = 0; + } else frameskiptimer++; } // same as above but only does a sb_blit, not the full RenderScreen. // used for intros etc. void gamedo_frameskipping_blitonly() { - if (framebyframe) - { - g_pVideoDriver->sb_blit(); - return; - } - if (frameskiptimer >= g_pVideoDriver->getFrameskip()) { g_pVideoDriver->sb_blit(); diff --git a/src/gamepdo.cpp b/src/gamepdo.cpp index 3dc73fb5d..d5cad0939 100644 --- a/src/gamepdo.cpp +++ b/src/gamepdo.cpp @@ -33,9 +33,7 @@ char doFall; { gamepdo_dieanim(cp, pCKP); if (!pCKP->Control.levelcontrol.gameovermode) - { gamepdo_StatusBox(cp, pCKP); - } } else { @@ -79,15 +77,13 @@ char doFall; if (player[cp].inhibitfall) doFall = 0; if (doFall) - { - gamepdo_falling(cp, pCKP); - } + gamepdo_falling(cp, pCKP); else { if(player[cp].pjumping == PJUMPED) player[cp].pfalling = 0; - player[cp].psupportingtile = 145; - player[cp].psupportingobject = 0; + player[cp].psupportingtile = 145; + player[cp].psupportingobject = 0; } } diff --git a/src/include/declarations.h b/src/include/declarations.h index 7a9a06145..b38cac536 100644 --- a/src/include/declarations.h +++ b/src/include/declarations.h @@ -41,11 +41,9 @@ struct stLevelControl int tobonuslevel; // if 1 player will warp to bonus level on return to WM (for ep1) // data about current level int curlevel; // number of current level - char success; // 1 if level was finished, 0 if he died - char isfinallevel; // 1 if this is the final level - bool canexit; // true if player is allowed to use the exit door - char gameovermode; // 1 if "Game Over" is displayed - bool dokeensleft; // 1 if we need to do the "Keens Left" + bool success; // true if level was finished, 0 if he died + bool gameovermode; // true if "Game Over" is displayed + bool dokeensleft; // true if we need to do the "Keens Left" bool dark; // true if level is currently dark (lights are out) int episode; // which episode we're playing (1-3) diff --git a/src/include/fileio.h b/src/include/fileio.h index 39c98654a..dcd8891e3 100644 --- a/src/include/fileio.h +++ b/src/include/fileio.h @@ -12,8 +12,6 @@ unsigned int loadmap(const std::string& filename, const std::string& path, int lvlnum, stLevelControl* p_levelcontrol); -void addmaptile(unsigned int t); -void addenemytile(unsigned int t, stCloneKeenPlus *pCKP); short checkConsistencyofGameData(stGameData *p_GameData); std::string formatPathString(const std::string& path); void assignChangeTileAttribute(stTile *tile, int episode); diff --git a/src/include/gamedo.h b/src/include/gamedo.h index 5ddc02f14..96e2b33c6 100644 --- a/src/include/gamedo.h +++ b/src/include/gamedo.h @@ -1,7 +1,7 @@ -void gamedo_RenderScreen(); +void gamedo_RenderScreen(bool gameovermode = false); -void gamedo_frameskipping(); +void gamedo_frameskipping( bool gameovermode = false ); void gamedo_HandleFKeys(stCloneKeenPlus *pCKP); void gamedo_frameskipping_blitonly(); void gamedo_getInput(stLevelControl *p_levelcontrol); diff --git a/src/keen.h b/src/keen.h index 8e18a9036..f13be07e7 100644 --- a/src/keen.h +++ b/src/keen.h @@ -141,11 +141,12 @@ struct stInventory unsigned char HasCardRed; unsigned char HasCardGreen; unsigned char HasCardBlue; - // ep1 only - unsigned char HasJoystick; - unsigned char HasFuel; - unsigned char HasBattery; - unsigned char HasVacuum; + + // ep1 normally + bool HasJoystick; + bool HasWiskey; + bool HasBattery; + bool HasVacuum; }; // for strings loaded from "strings.dat" diff --git a/src/main.cpp b/src/main.cpp index b3377ac26..171907592 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -53,7 +53,6 @@ int NessieObjectHandle; int DemoObjectHandle; int BlankSprite; int DemoSprite; -int framebyframe; int fps=0, curfps=0; stOption *options = NULL; @@ -300,11 +299,7 @@ void playgame_levelmanager(stCloneKeenPlus *pCKP) char SaveGameFileName[40]; int newlevel; - stLevelControl *p_levelcontrol; - stOption *p_option; - - p_option = pCKP->Option; - p_levelcontrol = &(pCKP->Control.levelcontrol); + stLevelControl *p_levelcontrol = &(pCKP->Control.levelcontrol); if( p_levelcontrol->command != LVLC_START_LEVEL ) { @@ -333,14 +328,9 @@ void playgame_levelmanager(stCloneKeenPlus *pCKP) sprintf(levelname, "level%02d.ck%d", newlevel, p_levelcontrol->episode); if (p_levelcontrol->chglevelto==WORLD_MAP) - { wm = 1; - } else - { wm = 0; - } - p_levelcontrol->canexit = 1; // assume can exit before loading map if (loadmap(levelname, pCKP->GameData[pCKP->Resources.GameSelected-1].DataDirectory, newlevel, p_levelcontrol)) { @@ -350,15 +340,6 @@ void playgame_levelmanager(stCloneKeenPlus *pCKP) } p_levelcontrol->curlevel = p_levelcontrol->chglevelto; - if (p_levelcontrol->curlevel == FINAL_MAP && p_levelcontrol->episode == 1) - { - p_levelcontrol->isfinallevel = 1; - p_levelcontrol->canexit = 0; - } - else - { - p_levelcontrol->isfinallevel = 0; - } if (firsttime) { diff --git a/src/menu.cpp b/src/menu.cpp index cf46aea2d..2e0086a06 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -8,7 +8,6 @@ #include "include/misc.h" #include "sdl/CVideoDriver.h" #include "include/game.h" -#include "include/gamedo.h" #include "sdl/CTimer.h" #include "sdl/sound/CSound.h" #include "include/fileio.h" @@ -22,6 +21,7 @@ #include "vorticon/CDialog.h" #include "CLogFile.h" #include "sdl/CSettings.h" + #include #include #include @@ -1020,7 +1020,7 @@ void showPage(const std::string& str_text, stCloneKeenPlus *pCKP, int textsize) delete [] text; - std::string coverline(38, (char)2); + std::string coverline(38, (char) 2); do { diff --git a/src/misc.cpp b/src/misc.cpp index 886628461..c6e5d9a9c 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -275,7 +275,7 @@ int dlgX,dlgY,dlgW,dlgH; g_pGraphics->drawTile_direct((dlgX+21)<<3, ((dlgY+4)<<3)+3, t); if (player[p].inventory.HasVacuum) t=450; else t=323; g_pGraphics->drawTile_direct((dlgX+24)<<3, ((dlgY+4)<<3)+3, t); - if (player[p].inventory.HasFuel) t=451; else t=324; + if (player[p].inventory.HasWiskey) t=451; else t=324; g_pGraphics->drawTile_direct((dlgX+27)<<3, ((dlgY+4)<<3)+3, t); // ray gun charges i = player[p].inventory.charges; @@ -580,7 +580,7 @@ int dlgX,dlgY,dlgW,dlgH; if (!player[cp].inventory.HasVacuum) g_pGraphics->drawTile_direct((dlgX+15)<<3, (dlgY+3)<<3, 450); - if (!player[cp].inventory.HasFuel) + if (!player[cp].inventory.HasWiskey) g_pGraphics->drawTile_direct((dlgX+18)<<3, (dlgY+3)<<3, 451); g_pVideoDriver->update_screen(); @@ -1004,7 +1004,7 @@ int i; { if (player[i].inventory.HasJoystick) partcount++; if (player[i].inventory.HasBattery) partcount++; - if (player[i].inventory.HasFuel) partcount++; + if (player[i].inventory.HasWiskey) partcount++; if (player[i].inventory.HasVacuum) partcount++; } } @@ -1047,6 +1047,8 @@ return 0; void usage(void) { + // TODO: Many options has to be changed. For now it is disabled + /* printf("Usage: keen [lvlnum] [-*player] [-nopk] [-ep*] [-dtm] [-nocheat] [-rec] -[eseq]
\n"); printf("lvlnum specify a level number (such as 2) to go directly to that level
"); printf("-*player select number of players (1-4); defaults to 1
"); @@ -1063,15 +1065,13 @@ void usage(void) printf("-ogl hardware acceleration
"); printf("-showfps show FPS in upper-right of screen
"); #endif -#ifdef TARGET_WIN32 - printf("
-host & -join for the experimental network play mode. These DON'T work yet.\n"); -#endif printf("
"); printf("Examples:
"); printf(" keen 3 -ep2 play ep 2, level 3 in 1-player mode
"); printf(" keen -ep3 -dtm -2player play ep3, skip title&intro, 2-player mode
"); printf(" keen -ep3 play a normal game of ep3
"); + */ } unsigned int rnd(void) diff --git a/src/vorticon/CDialog.cpp b/src/vorticon/CDialog.cpp index d1193bb7e..b187027dc 100644 --- a/src/vorticon/CDialog.cpp +++ b/src/vorticon/CDialog.cpp @@ -229,6 +229,7 @@ void CDialog::renderDialog() // The original Game had a open Dialog Animation. This is what that function does... void CDialog::animateDialogBox(bool value){ isanimated = value; } + void CDialog::renderOpenDialogAnimation(int x,int y, int w, int h) { if(!isanimated || !isVisible)