Files
commandergenius/src/eseq_ep2.cpp

717 lines
18 KiB
C++

/* ESEQ_EP2.C
Ending sequence for Episode 2.
*/
#include "keen.h"
#include "include/game.h"
#include "include/gamedo.h"
#include "include/gamepdo.h"
#include "sdl/CTimer.h"
#include "sdl/CInput.h"
#include "sdl/sound/CSound.h"
#include "include/eseq_ep2.h"
#include "include/eseq_ep1.h"
#include "include/menu.h"
#include "include/enemyai.h"
#include "CGraphics.h"
#include "StringUtils.h"
#define CMD_MOVE 0
#define CMD_WAIT 1
#define CMD_SPAWNSPR 2
#define CMD_REMOVESPR 3
#define CMD_FADEOUT 4
#define CMD_ENDOFQUEUE 5
#define CMD_ENABLESCROLLING 6
#define CMD_DISABLESCROLLING 7
stShipQueue shipqueue[32];
int ShipQueuePtr;
#define LETTER_SHOW_SPD 30
// start x,y map scroll position for eseq2_TantalusRay()
#define TANTALUS_X 0
#define TANTALUS_Y 0
#define TANTALUS_SPD_X 21
#define TANTALUS_SPD_Y 9
#define TANTALUS_SPRITE 58
#define TAN_DELAY_BEFORE_FIRE 500
#define TAN_STATE_WAITBEFOREFIRE 0
#define TAN_STATE_FIRING 1
#define TAN_STATE_EARTH_EXPLODING 2
#define TAN_STATE_CHUNKS_FLYING 3
#define TAN_STATE_GAMEOVER 4
#define EARTHCHUNK_BIG_UP 64
#define EARTHCHUNK_BIG_DN 66
#define EARTHCHUNK_SMALL_UP 68
#define EARTHCHUNK_SMALL_DN 70
int eseq2_TantalusRay(stCloneKeenPlus *pCKP)
{
char enter,lastenterstate;
int x, y, t, o, i;
int tantalus_animframe, tantalus_animtimer=0;
int state, timer, spawnedcount=0;
o=0;
fade.mode = FADE_GO;
fade.rate = FADE_NORM;
fade.dir = FADE_OUT;
fade.curamt = PAL_FADE_SHADES;
fade.fadetimer = 0;
do
{
gamedo_fades();
g_pInput->pollEvents();
g_pTimer->SpeedThrottle(); } while(fade.mode!=FADE_COMPLETE);
pCKP->Control.levelcontrol.dark = 0;
g_pGraphics->initPalette(pCKP->Control.levelcontrol.dark);
initgame(pCKP);
state = TAN_STATE_WAITBEFOREFIRE;
showmapatpos(81,TANTALUS_X, TANTALUS_Y, 0, pCKP);
AllPlayersInvisible();
numplayers = 1;
player[0].hideplayer = 0;
objects[player[0].useObject].onscreen = 1;
// place the player (which is actually the tantalus ray) at the mouth
// of the vorticon mothership
if (map_findtile(593, &x, &y))
{ // found the tile
player[0].x = ((x<<4)-1)<<CSF;
player[0].y = ((y<<4)-0)<<CSF;
}
else
{
crashflag = 1;
why_term_ptr = "eseq2_TantalusRay(): unable to find tile 593.";
return 0;
}
player[0].playframe = BlankSprite;
fade.mode = FADE_GO;
fade.rate = FADE_NORM;
fade.dir = FADE_IN;
fade.curamt = 0;
fade.fadetimer = 0;
tantalus_animframe = 0;
timer = 0;
do
{
switch(state)
{
case TAN_STATE_WAITBEFOREFIRE:
if (timer > TAN_DELAY_BEFORE_FIRE)
{
g_pSound->playStereofromCoord(SOUND_KEEN_FIRE, PLAY_NOW, objects[o].scrx);
state = TAN_STATE_FIRING;
timer = 0;
}
else timer++;
break;
case TAN_STATE_FIRING:
if (tantalus_animtimer>5)
{
tantalus_animframe ^= 1;
player[0].playframe = TANTALUS_SPRITE + tantalus_animframe;
}
else tantalus_animtimer++;
player[0].x += TANTALUS_SPD_X;
player[0].y += TANTALUS_SPD_Y;
t = getmaptileat((player[0].x>>CSF)+(sprites[TANTALUS_SPRITE].xsize/2), (player[0].y>>CSF)+(sprites[TANTALUS_SPRITE].ysize/2));
if (t==586)
{ // hit center of earth
state = TAN_STATE_EARTH_EXPLODING;
player[0].playframe = BlankSprite;
timer = 0;
spawnedcount = 0;
srand(300);
o = spawn_object(player[0].x+(24<<CSF), player[0].y-(8<<CSF), OBJ_EXPLOSION);
g_pSound->playSound(SOUND_EARTHPOW, PLAY_NOW);
}
break;
case TAN_STATE_EARTH_EXPLODING:
if (!timer)
{
if (spawnedcount<16) o = spawn_object(player[0].x+((rand()%32)<<CSF), player[0].y+((rand()%32)<<CSF)-(8<<CSF), OBJ_EXPLOSION);
switch(spawnedcount)
{
case 0: o = spawn_object(player[0].x-(8<<CSF), player[0].y-(8<<CSF), OBJ_EXPLOSION); break;
case 1: o = spawn_object(player[0].x+(24<<CSF), player[0].y+(4<<CSF), OBJ_EXPLOSION); break;
case 2: o = spawn_object(player[0].x+(16<<CSF), player[0].y-(8<<CSF), OBJ_EXPLOSION); break;
case 3: o = spawn_object(player[0].x+(24<<CSF), player[0].y+(16<<CSF), OBJ_EXPLOSION); break;
case 4: o = spawn_object(player[0].x-(8<<CSF), player[0].y+(4<<CSF), OBJ_EXPLOSION); break;
case 5:
o = spawn_object(player[0].x-(8<<CSF), player[0].y+(16<<CSF), OBJ_EXPLOSION);
// spawn a bunch of small fragments of the earth to go flying off
// spawn small earth chunks in all possible directions
// (upleft/upright/dnleft/dnright)
// up/left/down/right
for(i=0;i<=9;i++)
{
o = spawn_object(player[0].x+(16<<CSF), player[0].y, OBJ_EARTHCHUNK);
objects[o].ai.ray.direction = i;
if (i > 4)
{
objects[o].sprite = EARTHCHUNK_SMALL_DN;
}
else
{
objects[o].sprite = EARTHCHUNK_SMALL_UP;
}
}
break;
case 6:
o = spawn_object(player[0].x+(16<<CSF), player[0].y+(16<<CSF), OBJ_EXPLOSION);
break;
case 7: o = spawn_object(player[0].x+(24<<CSF), player[0].y-(8<<CSF), OBJ_EXPLOSION); break;
case 8: o = spawn_object(player[0].x+(16<<CSF), player[0].y+(4<<CSF), OBJ_EXPLOSION); break;
case 10:
// spawn four big fragments of the earth to go flying off
o = spawn_object(player[0].x+(16<<CSF), player[0].y, OBJ_EARTHCHUNK);
objects[o].sprite = EARTHCHUNK_BIG_UP;
objects[o].ai.ray.direction = EC_UPLEFT;
o = spawn_object(player[0].x+(16<<CSF), player[0].y, OBJ_EARTHCHUNK);
objects[o].sprite = EARTHCHUNK_BIG_UP;
objects[o].ai.ray.direction = EC_UPRIGHT;
o = spawn_object(player[0].x+(16<<CSF), player[0].y, OBJ_EARTHCHUNK);
objects[o].sprite = EARTHCHUNK_BIG_DN;
objects[o].ai.ray.direction = EC_DOWNRIGHT;
o = spawn_object(player[0].x+(16<<CSF), player[0].y, OBJ_EARTHCHUNK);
objects[o].sprite = EARTHCHUNK_BIG_DN;
objects[o].ai.ray.direction = EC_DOWNLEFT;
break;
case 32:
state = TAN_STATE_GAMEOVER;
g_pSound->playSound(SOUND_GAME_OVER, PLAY_NOW);
SetGameOver(pCKP);
break;
}
spawnedcount++;
timer = 60;
}
else timer--;
break;
case TAN_STATE_GAMEOVER:
break;
}
if (fade.dir==FADE_OUT && fade.mode==FADE_COMPLETE)
{ // we're done
return 0;
}
enter = (g_pInput->getPressedCommand(KENTER) || g_pInput->getPressedCommand(KCTRL) || g_pInput->getPressedCommand(KALT) );
if (enter && state==TAN_STATE_GAMEOVER)
{
if (fade.dir!=FADE_OUT)
{
fade.dir = FADE_OUT;
fade.curamt = PAL_FADE_SHADES;
fade.fadetimer = 0;
fade.rate = FADE_NORM;
fade.mode = FADE_GO;
}
}
lastenterstate = enter;
gamedo_fades();
if (state!=TAN_STATE_GAMEOVER) gamedo_AnimatedTiles();
gamedo_frameskipping(pCKP);
gamedo_enemyai(pCKP);
if(((player[0].x>>CSF)-scroll_x) > 160-16) map_scroll_right();
if (((player[0].y>>CSF)-scroll_y) > 100)
{
map_scroll_down();
}
g_pInput->pollEvents();
g_pTimer->SpeedThrottle();
} while(!g_pInput->getPressedCommand(KQUIT));
return 1;
}
void eseq2_vibrate(stCloneKeenPlus *pCKP)
{
int xamt, yamt;
int xdir, ydir;
int vibratetimes;
//int enter,lastenterstate;
int i;
int x,y,w,h;
vibratetimes = 0;
#define VIBRATE_AMT 16
#define VIBRATE_NUM_FRAMES 500
xamt = yamt = 0;
xdir = 0; ydir = 0;
do
{
// undo the scroll from last time
if (!xdir)
{
for(i=0;i<xamt;i++) map_scroll_right();
}
else
{
for(i=0;i<xamt;i++) map_scroll_left();
}
if (!ydir)
{
for(i=0;i<yamt;i++) map_scroll_down();
}
else
{
for(i=0;i<yamt;i++) map_scroll_up();
}
// randomize a new amount to scroll this frame
xamt = (rand()%VIBRATE_AMT);
yamt = (rand()%VIBRATE_AMT);
xdir = rand() & 1;
ydir = rand() & 1;
// scroll the map
if (xdir)
{
for(i=0;i<xamt;i++) map_scroll_right();
}
else
{
for(i=0;i<xamt;i++) map_scroll_left();
}
if (ydir)
{
for(i=0;i<yamt;i++) map_scroll_down();
}
else
{
for(i=0;i<yamt;i++) map_scroll_up();
}
// align sprites with new scroll position
for(i=0;i<MAX_OBJECTS;i++)
{
if (objects[i].exists && objects[i].type!=OBJ_PLAYER)
{
objects[i].scrx = (objects[i].x>>CSF)-scroll_x;
objects[i].scry = (objects[i].y>>CSF)-scroll_y;
}
}
// show the frame
gamedo_frameskipping(pCKP);
vibratetimes++;
g_pInput->pollEvents();
g_pTimer->SpeedThrottle();
} while(!g_pInput->getPressedCommand(KQUIT) && vibratetimes < VIBRATE_NUM_FRAMES);
// display the "uh-oh."
x = GetStringAttribute("EP2_AfterVibrateString", "LEFT");
y = GetStringAttribute("EP2_AfterVibrateString", "TOP");
w = GetStringAttribute("EP2_AfterVibrateString", "WIDTH");
h = GetStringAttribute("EP2_AfterVibrateString", "HEIGHT");
eseq_showmsg(getstring("EP2_AfterVibrateString"),x,y,w,h,1, pCKP);
}
#define HEADFOREARTH_X 0
#define HEADFOREARTH_Y 0
#define HEADFOREARTH_WAIT_TIME 600
#define SPR_SHIP_RIGHT_EP2 132
#define SPR_SHIP_LEFT_EP2 133
#define SPR_VORTICON_MOTHERSHIP 72
#define HEADSFOREARTH_X 3
#define HEADSFOREARTH_Y 15
#define HEADSFOREARTH_W 33
#define HEADSFOREARTH_H 8
void eseq_showmsg(const std::string& text, int boxleft, int boxtop, int boxwidth, int boxheight, char autodismiss, stCloneKeenPlus *pCKP)
{
//int draw;
//int i;
std::string tempbuf;
char textline, showtimer;
unsigned int amountshown;
int waittimer;
int cancel, lastcancelstate;
textline = 0;
amountshown = 0;
showtimer = 0;
lastcancelstate = 1;
waittimer = 0;
do
{
gamedo_fades();
gamedo_AnimatedTiles();
gamedo_render_drawobjects(pCKP);
cancel = (g_pInput->getPressedCommand(KENTER) || g_pInput->getPressedCommand(KCTRL) || g_pInput->getPressedCommand(KALT));
// draw the text up to the amount currently shown
tempbuf = text;
tempbuf.erase(amountshown);
sb_dialogbox(boxleft,boxtop,boxwidth,boxheight);
g_pGraphics->sb_font_draw( tempbuf, (boxleft+1)*8, (boxtop+1+textline)*8);
gamedo_frameskipping_blitonly();
gamedo_render_eraseobjects();
if (showtimer > LETTER_SHOW_SPD)
{ // it's time to show a new letter
if (amountshown < text.size())
{
amountshown++;
}
showtimer = 0;
} else showtimer++;
// user pressed enter or some other key
if (cancel && !lastcancelstate)
{
if (amountshown < text.size())
{
amountshown = text.size();
}
else return;
}
// when all text is shown wait a sec then return
if (autodismiss)
{
if (amountshown >= text.size())
{
if (waittimer > HEADFOREARTH_WAIT_TIME) return;
waittimer++;
}
}
lastcancelstate = cancel;
g_pInput->pollEvents();
g_pTimer->SpeedThrottle();
} while(!g_pInput->getPressedCommand(KQUIT));
return;
}
int eseq2_HeadsForEarth(stCloneKeenPlus *pCKP)
{
char enter,lastenterstate;
int x, y;
int downtimer;
int afterfadewaittimer;
initgame(pCKP);
// set up the ship's route
ShipQueuePtr = 0;
addshipqueue(CMD_WAIT, 10, 0);
addshipqueue(CMD_MOVE, 2360, DDOWNRIGHT);
addshipqueue(CMD_FADEOUT, 0, 0);
showmapatpos(81, HEADFOREARTH_X, HEADFOREARTH_Y, 0, pCKP);
numplayers = 1;
// place the player near the vorticon mothership
if (map_findtile(593, &x, &y))
{
player[0].x = ((x<<4)+2)<<CSF;
player[0].y = ((y<<4)-24)<<CSF;
}
else
{
crashflag = 1;
why_term_ptr = "eseq2_HeadForEarth(): unable to find Vorticon Mothership.";
return 1;
}
player[0].playframe = SPR_SHIP_RIGHT_EP2;
ShipQueuePtr = 0;
max_scroll_x = max_scroll_y = 20000;
fade.mode = FADE_GO;
fade.rate = FADE_NORM;
fade.dir = FADE_IN;
fade.curamt = 0;
fade.fadetimer = 0;
eseq_showmsg(getstring("EP2_ESEQ_PART1"),HEADSFOREARTH_X,HEADSFOREARTH_Y,HEADSFOREARTH_W,HEADSFOREARTH_H,1, pCKP);
// erase the message dialog
map_redraw();
lastenterstate = 1;
downtimer = 0;
afterfadewaittimer = 0;
do
{
// execute the current command in the queue
if (fade.dir != FADE_OUT)
{
switch(shipqueue[ShipQueuePtr].cmd)
{
case CMD_MOVE:
// down-right only, here
player[0].x+=9;
player[0].y+=4;
// we need a little bit more resolution that we can get--
// the Y speed needs to be somewhere between 4 and 5 for
// him to end up at the center of the earth
if (downtimer > 6)
{
player[0].y++;
downtimer = 0;
}
else downtimer++;
break;
case CMD_WAIT:
break;
case CMD_FADEOUT:
if (fade.dir!=FADE_OUT)
{
fade.dir = FADE_OUT;
fade.curamt = PAL_FADE_SHADES;
fade.fadetimer = 0;
fade.rate = FADE_NORM;
fade.mode = FADE_GO;
}
break;
default: break;
}
// decrease the time remaining
if (shipqueue[ShipQueuePtr].time)
{
shipqueue[ShipQueuePtr].time--;
}
else
{ // no time left on this command, go to next cmd
ShipQueuePtr++;
}
}
if (fade.dir==FADE_OUT && fade.mode==FADE_COMPLETE)
{
if (afterfadewaittimer > 80)
{
return 0;
}
else afterfadewaittimer++;
}
enter = (g_pInput->getPressedCommand(KENTER)||g_pInput->getPressedCommand(KCTRL)||g_pInput->getPressedCommand(KALT));
if (enter && !lastenterstate)
{
if (fade.dir!=FADE_OUT)
{
fade.dir = FADE_OUT;
fade.curamt = PAL_FADE_SHADES;
fade.fadetimer = 0;
fade.rate = FADE_NORM;
fade.mode = FADE_GO;
}
}
lastenterstate = enter;
gamedo_fades();
gamedo_AnimatedTiles();
gamedo_frameskipping(pCKP);
gamedo_ScrollTriggers(0);
g_pInput->pollEvents();
g_pTimer->SpeedThrottle();
} while(!g_pInput->getPressedCommand(KQUIT));
return 1;
}
#define LIMPSHOME_X 0
#define LIMPSHOME_Y 344
int eseq2_LimpsHome(stCloneKeenPlus *pCKP)
{
char enter,lastenterstate;
//int x, y;
int downtimer;
int afterfadewaittimer = 0;
initgame(pCKP);
// set up the ship's route
ShipQueuePtr = 0;
addshipqueue(CMD_WAIT, 10, 0);
addshipqueue(CMD_MOVE, 1600, DUPLEFT);
addshipqueue(CMD_FADEOUT, 0, 0);
showmapatpos(81, LIMPSHOME_X, LIMPSHOME_Y, 0, pCKP);
numplayers = 1;
player[0].x = (10 <<4<<CSF);
player[0].y = (26 <<4<<CSF);
player[0].playframe = SPR_VORTICON_MOTHERSHIP;
ShipQueuePtr = 0;
fade.mode = FADE_GO;
fade.rate = FADE_NORM;
fade.dir = FADE_IN;
fade.curamt = 0;
fade.fadetimer = 0;
eseq_showmsg(getstring("EP2_ESEQ_PART2"),HEADSFOREARTH_X,HEADSFOREARTH_Y,HEADSFOREARTH_W,HEADSFOREARTH_H-1,1, pCKP);
// erase the message dialog
map_redraw();
lastenterstate = 1;
downtimer = 0;
do
{
// execute the current command in the queue
if (fade.dir != FADE_OUT)
{
switch(shipqueue[ShipQueuePtr].cmd)
{
case CMD_MOVE:
// up-left only, here
player[0].x-=1;
player[0].y-=2;
break;
case CMD_WAIT:
break;
case CMD_FADEOUT:
if (fade.dir!=FADE_OUT)
{
fade.dir = FADE_OUT;
fade.curamt = PAL_FADE_SHADES;
fade.fadetimer = 0;
fade.rate = FADE_NORM;
fade.mode = FADE_GO;
}
break;
default: break;
}
// decrease the time remaining
if (shipqueue[ShipQueuePtr].time)
{
shipqueue[ShipQueuePtr].time--;
}
else
{ // no time left on this command, go to next cmd
ShipQueuePtr++;
}
}
if (fade.dir==FADE_OUT && fade.mode==FADE_COMPLETE)
{
if (afterfadewaittimer > 80)
{
return 0;
}
else afterfadewaittimer++;
}
enter = (g_pInput->getPressedCommand(KENTER)||g_pInput->getPressedCommand(KCTRL)||g_pInput->getPressedCommand(KALT));
if (enter && !lastenterstate)
{
if (fade.dir!=FADE_OUT)
{
fade.dir = FADE_OUT;
fade.curamt = PAL_FADE_SHADES;
fade.fadetimer = 0;
fade.rate = FADE_NORM;
fade.mode = FADE_GO;
}
}
lastenterstate = enter;
gamedo_fades();
gamedo_AnimatedTiles();
gamedo_frameskipping(pCKP);
g_pInput->pollEvents();
g_pTimer->SpeedThrottle();
} while(!g_pInput->getPressedCommand(KQUIT));
return 1;
}
int eseq2_SnowedOutside(stCloneKeenPlus *pCKP)
{
int curpage;
int lastpage;
std::string tempstr;
std::string text;
//int enter, lastenterstate;
int dlgX, dlgY, dlgW, dlgH;
scrollx_buf = scroll_x = 0;
scrolly_buf = scroll_y = 0;
finale_draw("finale.ck2", pCKP->GameData[pCKP->Resources.GameSelected-1].DataDirectory);
curpage = 1;
fade.mode = FADE_GO;
fade.rate = FADE_NORM;
fade.dir = FADE_IN;
fade.curamt = 0;
fade.fadetimer = 0;
numplayers = 1;
player[0].x = player[0].y = 0;
player[0].playframe = BlankSprite;
do
{
tempstr = "EP2_ESEQ_PART3_PAGE" + itoa(curpage);
text = getstring(tempstr);
dlgX = GetStringAttribute(tempstr, "LEFT");
dlgY = GetStringAttribute(tempstr, "TOP");
dlgW = GetStringAttribute(tempstr, "WIDTH");
dlgH = GetStringAttribute(tempstr, "HEIGHT");
lastpage = GetStringAttribute(tempstr, "LASTPAGE");
eseq_showmsg(text, dlgX, dlgY, dlgW, dlgH, 1, pCKP);
if (lastpage==1) break;
curpage++;
} while(!g_pInput->getPressedCommand(KQUIT));
finale_draw("finale.ck2", pCKP->GameData[pCKP->Resources.GameSelected-1].DataDirectory);
eseq_ToBeContinued(pCKP);
return 0;
}