123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953 |
- // G_game.c
- #include <stdio.h>
- #include <string.h>
- #include "DoomDef.h"
- #include "P_local.h"
- #include "soundst.h"
- // Macros
- #define SVG_RAM 0
- #define SVG_FILE 1
- #define SAVE_GAME_TERMINATOR 0x1d
- #define AM_STARTKEY 9
- // Functions
- boolean G_CheckDemoStatus (void);
- void G_ReadDemoTiccmd (ticcmd_t *cmd);
- void G_WriteDemoTiccmd (ticcmd_t *cmd);
- void G_PlayerReborn (int player);
- void G_InitNew (skill_t skill, int episode, int map);
- void G_DoReborn (int playernum);
- void G_DoLoadLevel (void);
- void G_DoNewGame (void);
- void G_DoLoadGame (void);
- void G_DoPlayDemo (void);
- void G_DoCompleted (void);
- void G_DoVictory (void);
- void G_DoWorldDone (void);
- void G_DoSaveGame (void);
- void D_PageTicker(void);
- void D_AdvanceDemo(void);
- struct
- {
- mobjtype_t type;
- int speed[2];
- } MonsterMissileInfo[] =
- {
- { MT_IMPBALL, 10, 20 },
- { MT_MUMMYFX1, 9, 18 },
- { MT_KNIGHTAXE, 9, 18 },
- { MT_REDAXE, 9, 18 },
- { MT_BEASTBALL, 12, 20 },
- { MT_WIZFX1, 18, 24 },
- { MT_SNAKEPRO_A, 14, 20 },
- { MT_SNAKEPRO_B, 14, 20 },
- { MT_HEADFX1, 13, 20 },
- { MT_HEADFX3, 10, 18 },
- { MT_MNTRFX1, 20, 26 },
- { MT_MNTRFX2, 14, 20 },
- { MT_SRCRFX1, 20, 28 },
- { MT_SOR2FX1, 20, 28 },
- { -1, -1, -1 } // Terminator
- };
- FILE *SaveGameFP;
- int SaveGameType;
- gameaction_t gameaction;
- gamestate_t gamestate;
- skill_t gameskill;
- boolean respawnmonsters;
- int gameepisode;
- int gamemap;
- int prevmap;
- boolean paused;
- boolean sendpause; // send a pause event next tic
- boolean sendsave; // send a save event next tic
- boolean usergame; // ok to save / end game
- boolean timingdemo; // if true, exit with report on completion
- int starttime; // for comparative timing purposes
- boolean viewactive;
- boolean deathmatch; // only if started as net death
- boolean netgame; // only true if packets are broadcast
- boolean playeringame[MAXPLAYERS];
- player_t players[MAXPLAYERS];
- int consoleplayer; // player taking events and displaying
- int displayplayer; // view being displayed
- int gametic;
- int levelstarttic; // gametic at level start
- int totalkills, totalitems, totalsecret; // for intermission
- char demoname[32];
- boolean demorecording;
- boolean demoplayback;
- byte *demobuffer, *demo_p;
- boolean singledemo; // quit after playing a demo from cmdline
- boolean precache = true; // if true, load all graphics at start
- short consistancy[MAXPLAYERS][BACKUPTICS];
- byte *savebuffer, *save_p;
- //
- // controls (have defaults)
- //
- int key_right, key_left, key_up, key_down;
- int key_strafeleft, key_straferight;
- int key_fire, key_use, key_strafe, key_speed;
- int key_flyup, key_flydown, key_flycenter;
- int key_lookup, key_lookdown, key_lookcenter;
- int key_invleft, key_invright, key_useartifact;
- int mousebfire;
- int mousebstrafe;
- int mousebforward;
- int joybfire;
- int joybstrafe;
- int joybuse;
- int joybspeed;
- #define MAXPLMOVE 0x32
- fixed_t forwardmove[2] = {0x19, 0x32};
- fixed_t sidemove[2] = {0x18, 0x28};
- fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn
- #define SLOWTURNTICS 6
- #define NUMKEYS 256
- boolean gamekeydown[NUMKEYS];
- int turnheld; // for accelerative turning
- int lookheld;
- boolean mousearray[4];
- boolean *mousebuttons = &mousearray[1];
- // allow [-1]
- int mousex, mousey; // mouse values are used once
- int dclicktime, dclickstate, dclicks;
- int dclicktime2, dclickstate2, dclicks2;
- int joyxmove, joyymove; // joystick values are repeated
- boolean joyarray[5];
- boolean *joybuttons = &joyarray[1]; // allow [-1]
- int savegameslot;
- char savedescription[32];
- int inventoryTics;
- #ifdef __WATCOMC__
- extern externdata_t *i_ExternData;
- #endif
- //=============================================================================
- // Not used - ripped out for Heretic
- /*
- int G_CmdChecksum(ticcmd_t *cmd)
- {
- int i;
- int sum;
- sum = 0;
- for(i = 0; i < sizeof(*cmd)/4-1; i++)
- {
- sum += ((int *)cmd)[i];
- }
- return(sum);
- }
- */
- /*
- ====================
- =
- = G_BuildTiccmd
- =
- = Builds a ticcmd from all of the available inputs or reads it from the
- = demo buffer.
- = If recording a demo, write it out
- ====================
- */
- extern boolean inventory;
- extern int curpos;
- extern int inv_ptr;
- extern int isCyberPresent; // is CyberMan present?
- boolean usearti = true;
- void I_ReadCyberCmd (ticcmd_t *cmd);
- void G_BuildTiccmd (ticcmd_t *cmd)
- {
- int i;
- boolean strafe, bstrafe;
- int speed, tspeed, lspeed;
- int forward, side;
- int look, arti;
- int flyheight;
- extern boolean noartiskip;
- #ifdef __WATCOMC__
- int angleDelta;
- static int oldAngle;
- extern int newViewAngleOff;
- static int externInvKey;
- extern boolean automapactive;
- event_t ev;
- #endif
- memset (cmd,0,sizeof(*cmd));
- //cmd->consistancy =
- // consistancy[consoleplayer][(maketic*ticdup)%BACKUPTICS];
- cmd->consistancy =
- consistancy[consoleplayer][maketic%BACKUPTICS];
- if (isCyberPresent)
- I_ReadCyberCmd (cmd);
- //printf ("cons: %i\n",cmd->consistancy);
- strafe = gamekeydown[key_strafe] || mousebuttons[mousebstrafe]
- || joybuttons[joybstrafe];
- speed = gamekeydown[key_speed] || joybuttons[joybspeed]
- || joybuttons[joybspeed];
- #ifdef __WATCOMC__
- if(useexterndriver)
- {
- speed |= (i_ExternData->buttons&EBT_SPEED);
- strafe |= (i_ExternData->buttons&EBT_STRAFE);
- }
- #endif
- forward = side = look = arti = flyheight = 0;
- //
- // use two stage accelerative turning on the keyboard and joystick
- //
- if (joyxmove < 0 || joyxmove > 0
- || gamekeydown[key_right] || gamekeydown[key_left])
- turnheld += ticdup;
- else
- turnheld = 0;
- if (turnheld < SLOWTURNTICS)
- tspeed = 2; // slow turn
- else
- tspeed = speed;
- if(gamekeydown[key_lookdown] || gamekeydown[key_lookup])
- {
- lookheld += ticdup;
- }
- else
- {
- lookheld = 0;
- }
- if(lookheld < SLOWTURNTICS)
- {
- lspeed = 1;
- }
- else
- {
- lspeed = 2;
- }
- //
- // let movement keys cancel each other out
- //
- if(strafe)
- {
- if (gamekeydown[key_right])
- side += sidemove[speed];
- if (gamekeydown[key_left])
- side -= sidemove[speed];
- if (joyxmove > 0)
- side += sidemove[speed];
- if (joyxmove < 0)
- side -= sidemove[speed];
- }
- else
- {
- if (gamekeydown[key_right])
- cmd->angleturn -= angleturn[tspeed];
- if (gamekeydown[key_left])
- cmd->angleturn += angleturn[tspeed];
- if (joyxmove > 0)
- cmd->angleturn -= angleturn[tspeed];
- if (joyxmove < 0)
- cmd->angleturn += angleturn[tspeed];
- }
- if (gamekeydown[key_up])
- forward += forwardmove[speed];
- if (gamekeydown[key_down])
- forward -= forwardmove[speed];
- if (joyymove < 0)
- forward += forwardmove[speed];
- if (joyymove > 0)
- forward -= forwardmove[speed];
- if (gamekeydown[key_straferight])
- side += sidemove[speed];
- if (gamekeydown[key_strafeleft])
- side -= sidemove[speed];
- // Look up/down/center keys
- if(gamekeydown[key_lookup])
- {
- look = lspeed;
- }
- if(gamekeydown[key_lookdown])
- {
- look = -lspeed;
- }
- #ifdef __WATCOMC__
- if(gamekeydown[key_lookcenter] && !useexterndriver)
- {
- look = TOCENTER;
- }
- #else
- if(gamekeydown[key_lookcenter])
- {
- look = TOCENTER;
- }
- #endif
- #ifdef __WATCOMC__
- if(useexterndriver && look != TOCENTER && (gamestate == GS_LEVEL ||
- gamestate == GS_INTERMISSION))
- {
- if(i_ExternData->moveForward)
- {
- forward += i_ExternData->moveForward;
- if(speed)
- {
- forward <<= 1;
- }
- }
- if(i_ExternData->angleTurn)
- {
- if(strafe)
- {
- side += i_ExternData->angleTurn;
- }
- else
- {
- cmd->angleturn += i_ExternData->angleTurn;
- }
- }
- if(i_ExternData->moveSideways)
- {
- side += i_ExternData->moveSideways;
- if(speed)
- {
- side <<= 1;
- }
- }
- if(i_ExternData->buttons&EBT_CENTERVIEW)
- {
- look = TOCENTER;
- oldAngle = 0;
- }
- else if(i_ExternData->pitch)
- {
- angleDelta = i_ExternData->pitch-oldAngle;
- if(abs(angleDelta) < 35)
- {
- look = angleDelta/5;
- }
- else
- {
- look = 7*(angleDelta > 0 ? 1 : -1);
- }
- if(look == TOCENTER)
- {
- look++;
- }
- oldAngle += look*5;
- }
- if(i_ExternData->flyDirection)
- {
- if(i_ExternData->flyDirection > 0)
- {
- flyheight = 5;
- }
- else
- {
- flyheight = -5;
- }
- }
- if(abs(newViewAngleOff-i_ExternData->angleHead) < 3000)
- {
- newViewAngleOff = i_ExternData->angleHead;
- }
- if(i_ExternData->buttons&EBT_FIRE)
- {
- cmd->buttons |= BT_ATTACK;
- }
- if(i_ExternData->buttons&EBT_OPENDOOR)
- {
- cmd->buttons |= BT_USE;
- }
- if(i_ExternData->buttons&EBT_PAUSE)
- {
- cmd->buttons = BT_SPECIAL | BTS_PAUSE;
- i_ExternData->buttons &= ~EBT_PAUSE;
- }
- if(externInvKey&EBT_USEARTIFACT)
- {
- ev.type = ev_keyup;
- ev.data1 = key_useartifact;
- D_PostEvent(&ev);
- externInvKey &= ~EBT_USEARTIFACT;
- }
- else if(i_ExternData->buttons&EBT_USEARTIFACT)
- {
- externInvKey |= EBT_USEARTIFACT;
- ev.type = ev_keydown;
- ev.data1 = key_useartifact;
- D_PostEvent(&ev);
- }
- if(externInvKey&EBT_INVENTORYRIGHT)
- {
- ev.type = ev_keyup;
- ev.data1 = key_invright;
- D_PostEvent(&ev);
- externInvKey &= ~EBT_INVENTORYRIGHT;
- }
- else if(i_ExternData->buttons&EBT_INVENTORYRIGHT)
- {
- externInvKey |= EBT_INVENTORYRIGHT;
- ev.type = ev_keydown;
- ev.data1 = key_invright;
- D_PostEvent(&ev);
- }
- if(externInvKey&EBT_INVENTORYLEFT)
- {
- ev.type = ev_keyup;
- ev.data1 = key_invleft;
- D_PostEvent(&ev);
- externInvKey &= ~EBT_INVENTORYLEFT;
- }
- else if(i_ExternData->buttons&EBT_INVENTORYLEFT)
- {
- externInvKey |= EBT_INVENTORYLEFT;
- ev.type = ev_keydown;
- ev.data1 = key_invleft;
- D_PostEvent(&ev);
- }
- if(i_ExternData->buttons&EBT_FLYDROP)
- {
- flyheight = TOCENTER;
- }
- if(gamestate == GS_LEVEL)
- {
- if(externInvKey&EBT_MAP)
- { // AutoMap
- ev.type = ev_keyup;
- ev.data1 = AM_STARTKEY;
- D_PostEvent(&ev);
- externInvKey &= ~EBT_MAP;
- }
- else if(i_ExternData->buttons&EBT_MAP)
- {
- externInvKey |= EBT_MAP;
- ev.type = ev_keydown;
- ev.data1 = AM_STARTKEY;
- D_PostEvent(&ev);
- }
- }
- #if 0
- if((i = (i_ExternData->buttons>>EBT_WEAPONSHIFT)&EBT_WEAPONMASK) != 0)
- {
- cmd->buttons |= BT_CHANGE;
- cmd->buttons |= (i-1)<<BT_WEAPONSHIFT;
- }
- #endif
- if(i_ExternData->buttons&EBT_WEAPONCYCLE)
- {
- int curWeapon;
- player_t *pl;
- pl = &players[consoleplayer];
- curWeapon = pl->readyweapon;
- for(curWeapon = (curWeapon+1)&7; curWeapon != pl->readyweapon;
- curWeapon = (curWeapon+1)&7)
- {
- if(pl->weaponowned[curWeapon])
- {
- if(curWeapon >= wp_goldwand && curWeapon <= wp_mace &&
- !pl->ammo[wpnlev1info[curWeapon].ammo])
- { // weapon that requires ammo is empty
- continue;
- }
- break;
- }
- }
- cmd->buttons |= BT_CHANGE;
- cmd->buttons |= curWeapon<<BT_WEAPONSHIFT;
- }
- }
- #endif
- // Fly up/down/drop keys
- if(gamekeydown[key_flyup])
- {
- flyheight = 5; // note that the actual flyheight will be twice this
- }
- if(gamekeydown[key_flydown])
- {
- flyheight = -5;
- }
- if(gamekeydown[key_flycenter])
- {
- flyheight = TOCENTER;
- #ifdef __WATCOMC__
- if(!useexterndriver)
- {
- look = TOCENTER;
- }
- #else
- look = TOCENTER;
- #endif
- }
- // Use artifact key
- if(gamekeydown[key_useartifact])
- {
- if(gamekeydown[key_speed] && !noartiskip)
- {
- if(players[consoleplayer].inventory[inv_ptr].type != arti_none)
- {
- gamekeydown[key_useartifact] = false;
- cmd->arti = 0xff; // skip artifact code
- }
- }
- else
- {
- if(inventory)
- {
- players[consoleplayer].readyArtifact =
- players[consoleplayer].inventory[inv_ptr].type;
- inventory = false;
- cmd->arti = 0;
- usearti = false;
- }
- else if(usearti)
- {
- cmd->arti = players[consoleplayer].inventory[inv_ptr].type;
- usearti = false;
- }
- }
- }
- if(gamekeydown[127] && !cmd->arti
- && !players[consoleplayer].powers[pw_weaponlevel2])
- {
- gamekeydown[127] = false;
- cmd->arti = arti_tomeofpower;
- }
- //
- // buttons
- //
- cmd->chatchar = CT_dequeueChatChar();
- if (gamekeydown[key_fire] || mousebuttons[mousebfire]
- || joybuttons[joybfire])
- cmd->buttons |= BT_ATTACK;
- if (gamekeydown[key_use] || joybuttons[joybuse] )
- {
- cmd->buttons |= BT_USE;
- dclicks = 0; // clear double clicks if hit use button
- }
- for(i = 0; i < NUMWEAPONS-2; i++)
- {
- if(gamekeydown['1'+i])
- {
- cmd->buttons |= BT_CHANGE;
- cmd->buttons |= i<<BT_WEAPONSHIFT;
- break;
- }
- }
- //
- // mouse
- //
- if (mousebuttons[mousebforward])
- {
- forward += forwardmove[speed];
- }
- //
- // forward double click
- //
- if (mousebuttons[mousebforward] != dclickstate && dclicktime > 1 )
- {
- dclickstate = mousebuttons[mousebforward];
- if (dclickstate)
- dclicks++;
- if (dclicks == 2)
- {
- cmd->buttons |= BT_USE;
- dclicks = 0;
- }
- else
- dclicktime = 0;
- }
- else
- {
- dclicktime += ticdup;
- if (dclicktime > 20)
- {
- dclicks = 0;
- dclickstate = 0;
- }
- }
- //
- // strafe double click
- //
- bstrafe = mousebuttons[mousebstrafe]
- || joybuttons[joybstrafe];
- if (bstrafe != dclickstate2 && dclicktime2 > 1 )
- {
- dclickstate2 = bstrafe;
- if (dclickstate2)
- dclicks2++;
- if (dclicks2 == 2)
- {
- cmd->buttons |= BT_USE;
- dclicks2 = 0;
- }
- else
- dclicktime2 = 0;
- }
- else
- {
- dclicktime2 += ticdup;
- if (dclicktime2 > 20)
- {
- dclicks2 = 0;
- dclickstate2 = 0;
- }
- }
- if (strafe)
- {
- side += mousex*2;
- }
- else
- {
- cmd->angleturn -= mousex*0x8;
- }
- forward += mousey;
- mousex = mousey = 0;
- if (forward > MAXPLMOVE)
- forward = MAXPLMOVE;
- else if (forward < -MAXPLMOVE)
- forward = -MAXPLMOVE;
- if (side > MAXPLMOVE)
- side = MAXPLMOVE;
- else if (side < -MAXPLMOVE)
- side = -MAXPLMOVE;
- cmd->forwardmove += forward;
- cmd->sidemove += side;
- if(players[consoleplayer].playerstate == PST_LIVE)
- {
- if(look < 0)
- {
- look += 16;
- }
- cmd->lookfly = look;
- }
- if(flyheight < 0)
- {
- flyheight += 16;
- }
- cmd->lookfly |= flyheight<<4;
- //
- // special buttons
- //
- if (sendpause)
- {
- sendpause = false;
- cmd->buttons = BT_SPECIAL | BTS_PAUSE;
- }
- if (sendsave)
- {
- sendsave = false;
- cmd->buttons = BT_SPECIAL | BTS_SAVEGAME | (savegameslot<<BTS_SAVESHIFT);
- }
- }
- /*
- ==============
- =
- = G_DoLoadLevel
- =
- ==============
- */
- void G_DoLoadLevel (void)
- {
- int i;
- levelstarttic = gametic; // for time calculation
- gamestate = GS_LEVEL;
- for (i=0 ; i<MAXPLAYERS ; i++)
- {
- if (playeringame[i] && players[i].playerstate == PST_DEAD)
- players[i].playerstate = PST_REBORN;
- memset (players[i].frags,0,sizeof(players[i].frags));
- }
- P_SetupLevel (gameepisode, gamemap, 0, gameskill);
- displayplayer = consoleplayer; // view the guy you are playing
- starttime = I_GetTime ();
- gameaction = ga_nothing;
- Z_CheckHeap ();
- //
- // clear cmd building stuff
- //
- memset (gamekeydown, 0, sizeof(gamekeydown));
- joyxmove = joyymove = 0;
- mousex = mousey = 0;
- sendpause = sendsave = paused = false;
- memset (mousebuttons, 0, sizeof(mousebuttons));
- memset (joybuttons, 0, sizeof(joybuttons));
- }
- /*
- ===============================================================================
- =
- = G_Responder
- =
- = get info needed to make ticcmd_ts for the players
- =
- ===============================================================================
- */
- boolean G_Responder(event_t *ev)
- {
- player_t *plr;
- extern boolean MenuActive;
- plr = &players[consoleplayer];
- if(ev->type == ev_keyup && ev->data1 == key_useartifact)
- { // flag to denote that it's okay to use an artifact
- if(!inventory)
- {
- plr->readyArtifact = plr->inventory[inv_ptr].type;
- }
- usearti = true;
- }
- // Check for spy mode player cycle
- if(gamestate == GS_LEVEL && ev->type == ev_keydown
- && ev->data1 == KEY_F12 && !deathmatch)
- { // Cycle the display player
- do
- {
- displayplayer++;
- if(displayplayer == MAXPLAYERS)
- {
- displayplayer = 0;
- }
- } while(!playeringame[displayplayer]
- && displayplayer != consoleplayer);
- return(true);
- }
- if(gamestate == GS_LEVEL)
- {
- if(CT_Responder(ev))
- { // Chat ate the event
- return(true);
- }
- if(SB_Responder(ev))
- { // Status bar ate the event
- return(true);
- }
- if(AM_Responder(ev))
- { // Automap ate the event
- return(true);
- }
- }
- switch(ev->type)
- {
- case ev_keydown:
- if(ev->data1 == key_invleft)
- {
- inventoryTics = 5*35;
- if(!inventory)
- {
- inventory = true;
- break;
- }
- inv_ptr--;
- if(inv_ptr < 0)
- {
- inv_ptr = 0;
- }
- else
- {
- curpos--;
- if(curpos < 0)
- {
- curpos = 0;
- }
- }
- return(true);
- }
- if(ev->data1 == key_invright)
- {
- inventoryTics = 5*35;
- if(!inventory)
- {
- inventory = true;
- break;
- }
- inv_ptr++;
- if(inv_ptr >= plr->inventorySlotNum)
- {
- inv_ptr--;
- if(inv_ptr < 0)
- inv_ptr = 0;
- }
- else
- {
- curpos++;
- if(curpos > 6)
- {
- curpos = 6;
- }
- }
- return(true);
- }
- if(ev->data1 == KEY_PAUSE && !MenuActive)
- {
- sendpause = true;
- return(true);
- }
- if(ev->data1 < NUMKEYS)
- {
- gamekeydown[ev->data1] = true;
- }
- return(true); // eat key down events
- case ev_keyup:
- if(ev->data1 < NUMKEYS)
- {
- gamekeydown[ev->data1] = false;
- }
- return(false); // always let key up events filter down
- case ev_mouse:
- mousebuttons[0] = ev->data1&1;
- mousebuttons[1] = ev->data1&2;
- mousebuttons[2] = ev->data1&4;
- mousex = ev->data2*(mouseSensitivity+5)/10;
- mousey = ev->data3*(mouseSensitivity+5)/10;
- return(true); // eat events
- case ev_joystick:
- joybuttons[0] = ev->data1&1;
- joybuttons[1] = ev->data1&2;
- joybuttons[2] = ev->data1&4;
- joybuttons[3] = ev->data1&8;
- joyxmove = ev->data2;
- joyymove = ev->data3;
- return(true); // eat events
- default:
- break;
- }
- return(false);
- }
- /*
- ===============================================================================
- =
- = G_Ticker
- =
- ===============================================================================
- */
- void G_Ticker (void)
- {
- int i, buf;
- ticcmd_t *cmd;
- //
- // do player reborns if needed
- //
- for (i=0 ; i<MAXPLAYERS ; i++)
- if (playeringame[i] && players[i].playerstate == PST_REBORN)
- G_DoReborn (i);
- //
- // do things to change the game state
- //
- while (gameaction != ga_nothing)
- {
- switch (gameaction)
- {
- case ga_loadlevel:
- G_DoLoadLevel ();
- break;
- case ga_newgame:
- G_DoNewGame ();
- break;
- case ga_loadgame:
- G_DoLoadGame ();
- break;
- case ga_savegame:
- G_DoSaveGame ();
- break;
- case ga_playdemo:
- G_DoPlayDemo ();
- break;
- case ga_screenshot:
- M_ScreenShot ();
- gameaction = ga_nothing;
- break;
- case ga_completed:
- G_DoCompleted ();
- break;
- case ga_worlddone:
- G_DoWorldDone();
- break;
- case ga_victory:
- F_StartFinale();
- break;
- default:
- break;
- }
- }
- //
- // get commands, check consistancy, and build new consistancy check
- //
- //buf = gametic%BACKUPTICS;
- buf = (gametic/ticdup)%BACKUPTICS;
- for (i=0 ; i<MAXPLAYERS ; i++)
- if (playeringame[i])
- {
- cmd = &players[i].cmd;
- memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t));
- if (demoplayback)
- G_ReadDemoTiccmd (cmd);
- if (demorecording)
- G_WriteDemoTiccmd (cmd);
- if (netgame && !(gametic%ticdup) )
- {
- if (gametic > BACKUPTICS
- && consistancy[i][buf] != cmd->consistancy)
- {
- I_Error ("consistency failure (%i should be %i)",cmd->consistancy, consistancy[i][buf]);
- }
- if (players[i].mo)
- consistancy[i][buf] = players[i].mo->x;
- else
- consistancy[i][buf] = rndindex;
- }
- }
- //
- // check for special buttons
- //
- for (i=0 ; i<MAXPLAYERS ; i++)
- if (playeringame[i])
- {
- if (players[i].cmd.buttons & BT_SPECIAL)
- {
- switch (players[i].cmd.buttons & BT_SPECIALMASK)
- {
- case BTS_PAUSE:
- paused ^= 1;
- if(paused)
- {
- S_PauseSound();
- }
- else
- {
- S_ResumeSound();
- }
- break;
- case BTS_SAVEGAME:
- if (!savedescription[0])
- {
- if(netgame)
- {
- strcpy (savedescription, "NET GAME");
- }
- else
- {
- strcpy(savedescription, "SAVE GAME");
- }
- }
- savegameslot =
- (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT;
- gameaction = ga_savegame;
- break;
- }
- }
- }
- // turn inventory off after a certain amount of time
- if(inventory && !(--inventoryTics))
- {
- players[consoleplayer].readyArtifact =
- players[consoleplayer].inventory[inv_ptr].type;
- inventory = false;
- cmd->arti = 0;
- }
- //
- // do main actions
- //
- //
- // do main actions
- //
- switch (gamestate)
- {
- case GS_LEVEL:
- P_Ticker ();
- SB_Ticker ();
- AM_Ticker ();
- CT_Ticker();
- break;
- case GS_INTERMISSION:
- IN_Ticker ();
- break;
- case GS_FINALE:
- F_Ticker();
- break;
- case GS_DEMOSCREEN:
- D_PageTicker ();
- break;
- }
- }
- /*
- ==============================================================================
- PLAYER STRUCTURE FUNCTIONS
- also see P_SpawnPlayer in P_Things
- ==============================================================================
- */
- /*
- ====================
- =
- = G_InitPlayer
- =
- = Called at the start
- = Called by the game initialization functions
- ====================
- */
- void G_InitPlayer (int player)
- {
- player_t *p;
- // set up the saved info
- p = &players[player];
- // clear everything else to defaults
- G_PlayerReborn (player);
- }
- /*
- ====================
- =
- = G_PlayerFinishLevel
- =
- = Can when a player completes a level
- ====================
- */
- extern int curpos;
- extern int inv_ptr;
- extern int playerkeys;
- void G_PlayerFinishLevel(int player)
- {
- player_t *p;
- int i;
- /* // BIG HACK
- inv_ptr = 0;
- curpos = 0;
- */
- // END HACK
- p = &players[player];
- for(i=0; i<p->inventorySlotNum; i++)
- {
- p->inventory[i].count = 1;
- }
- p->artifactCount = p->inventorySlotNum;
- if(!deathmatch)
- {
- for(i = 0; i < 16; i++)
- {
- P_PlayerUseArtifact(p, arti_fly);
- }
- }
- memset(p->powers, 0, sizeof(p->powers));
- memset(p->keys, 0, sizeof(p->keys));
- playerkeys = 0;
- // memset(p->inventory, 0, sizeof(p->inventory));
- if(p->chickenTics)
- {
- p->readyweapon = p->mo->special1; // Restore weapon
- p->chickenTics = 0;
- }
- p->messageTics = 0;
- p->lookdir = 0;
- p->mo->flags &= ~MF_SHADOW; // Remove invisibility
- p->extralight = 0; // Remove weapon flashes
- p->fixedcolormap = 0; // Remove torch
- p->damagecount = 0; // No palette changes
- p->bonuscount = 0;
- p->rain1 = NULL;
- p->rain2 = NULL;
- if(p == &players[consoleplayer])
- {
- SB_state = -1; // refresh the status bar
- }
- }
- /*
- ====================
- =
- = G_PlayerReborn
- =
- = Called after a player dies
- = almost everything is cleared and initialized
- ====================
- */
- void G_PlayerReborn(int player)
- {
- player_t *p;
- int i;
- int frags[MAXPLAYERS];
- int killcount, itemcount, secretcount;
- boolean secret;
- secret = false;
- memcpy(frags, players[player].frags, sizeof(frags));
- killcount = players[player].killcount;
- itemcount = players[player].itemcount;
- secretcount = players[player].secretcount;
- p = &players[player];
- if(p->didsecret)
- {
- secret = true;
- }
- memset(p, 0, sizeof(*p));
- memcpy(players[player].frags, frags, sizeof(players[player].frags));
- players[player].killcount = killcount;
- players[player].itemcount = itemcount;
- players[player].secretcount = secretcount;
- p->usedown = p->attackdown = true; // don't do anything immediately
- p->playerstate = PST_LIVE;
- p->health = MAXHEALTH;
- p->readyweapon = p->pendingweapon = wp_goldwand;
- p->weaponowned[wp_staff] = true;
- p->weaponowned[wp_goldwand] = true;
- p->messageTics = 0;
- p->lookdir = 0;
- p->ammo[am_goldwand] = 50;
- for(i = 0; i < NUMAMMO; i++)
- {
- p->maxammo[i] = maxammo[i];
- }
- if(gamemap == 9 || secret)
- {
- p->didsecret = true;
- }
- if(p == &players[consoleplayer])
- {
- SB_state = -1; // refresh the status bar
- inv_ptr = 0; // reset the inventory pointer
- curpos = 0;
- }
- }
- /*
- ====================
- =
- = G_CheckSpot
- =
- = Returns false if the player cannot be respawned at the given mapthing_t spot
- = because something is occupying it
- ====================
- */
- void P_SpawnPlayer (mapthing_t *mthing);
- boolean G_CheckSpot (int playernum, mapthing_t *mthing)
- {
- fixed_t x,y;
- subsector_t *ss;
- unsigned an;
- mobj_t *mo;
- x = mthing->x << FRACBITS;
- y = mthing->y << FRACBITS;
- players[playernum].mo->flags2 &= ~MF2_PASSMOBJ;
- if (!P_CheckPosition (players[playernum].mo, x, y) )
- {
- players[playernum].mo->flags2 |= MF2_PASSMOBJ;
- return false;
- }
- players[playernum].mo->flags2 |= MF2_PASSMOBJ;
- // spawn a teleport fog
- ss = R_PointInSubsector (x,y);
- an = ( ANG45 * (mthing->angle/45) ) >> ANGLETOFINESHIFT;
- mo = P_SpawnMobj (x+20*finecosine[an], y+20*finesine[an]
- , ss->sector->floorheight+TELEFOGHEIGHT
- , MT_TFOG);
- if (players[consoleplayer].viewz != 1)
- S_StartSound (mo, sfx_telept); // don't start sound on first frame
- return true;
- }
- /*
- ====================
- =
- = G_DeathMatchSpawnPlayer
- =
- = Spawns a player at one of the random death match spots
- = called at level load and each death
- ====================
- */
- void G_DeathMatchSpawnPlayer (int playernum)
- {
- int i,j;
- int selections;
- selections = deathmatch_p - deathmatchstarts;
- if (selections < 4)
- I_Error ("Only %i deathmatch spots, 4 required", selections);
- for (j=0 ; j<20 ; j++)
- {
- i = P_Random() % selections;
- if (G_CheckSpot (playernum, &deathmatchstarts[i]) )
- {
- deathmatchstarts[i].type = playernum+1;
- P_SpawnPlayer (&deathmatchstarts[i]);
- return;
- }
- }
- // no good spot, so the player will probably get stuck
- P_SpawnPlayer (&playerstarts[playernum]);
- }
- /*
- ====================
- =
- = G_DoReborn
- =
- ====================
- */
- void G_DoReborn (int playernum)
- {
- int i;
- if (G_CheckDemoStatus ())
- return;
- if (!netgame)
- gameaction = ga_loadlevel; // reload the level from scratch
- else
- { // respawn at the start
- players[playernum].mo->player = NULL; // dissasociate the corpse
- // spawn at random spot if in death match
- if (deathmatch)
- {
- G_DeathMatchSpawnPlayer (playernum);
- return;
- }
- if (G_CheckSpot (playernum, &playerstarts[playernum]) )
- {
- P_SpawnPlayer (&playerstarts[playernum]);
- return;
- }
- // try to spawn at one of the other players spots
- for (i=0 ; i<MAXPLAYERS ; i++)
- if (G_CheckSpot (playernum, &playerstarts[i]) )
- {
- playerstarts[i].type = playernum+1; // fake as other player
- P_SpawnPlayer (&playerstarts[i]);
- playerstarts[i].type = i+1; // restore
- return;
- }
- // he's going to be inside something. Too bad.
- P_SpawnPlayer (&playerstarts[playernum]);
- }
- }
- void G_ScreenShot (void)
- {
- gameaction = ga_screenshot;
- }
- /*
- ====================
- =
- = G_DoCompleted
- =
- ====================
- */
- boolean secretexit;
- void G_ExitLevel (void)
- {
- secretexit = false;
- gameaction = ga_completed;
- }
- void G_SecretExitLevel (void)
- {
- secretexit = true;
- gameaction = ga_completed;
- }
- void G_DoCompleted(void)
- {
- int i;
- static int afterSecret[5] = { 7, 5, 5, 5, 4 };
- gameaction = ga_nothing;
- if(G_CheckDemoStatus())
- {
- return;
- }
- for(i = 0; i < MAXPLAYERS; i++)
- {
- if(playeringame[i])
- {
- G_PlayerFinishLevel(i);
- }
- }
- prevmap = gamemap;
- if(secretexit == true)
- {
- gamemap = 9;
- }
- else if(gamemap == 9)
- { // Finished secret level
- gamemap = afterSecret[gameepisode-1];
- }
- else if(gamemap == 8)
- {
- gameaction = ga_victory;
- return;
- }
- else
- {
- gamemap++;
- }
- gamestate = GS_INTERMISSION;
- IN_Start();
- }
- //============================================================================
- //
- // G_WorldDone
- //
- //============================================================================
- void G_WorldDone(void)
- {
- gameaction = ga_worlddone;
- }
- //============================================================================
- //
- // G_DoWorldDone
- //
- //============================================================================
- void G_DoWorldDone(void)
- {
- gamestate = GS_LEVEL;
- G_DoLoadLevel();
- gameaction = ga_nothing;
- viewactive = true;
- }
- //---------------------------------------------------------------------------
- //
- // PROC G_LoadGame
- //
- // Can be called by the startup code or the menu task.
- //
- //---------------------------------------------------------------------------
- char savename[256];
- void G_LoadGame(char *name)
- {
- strcpy(savename, name);
- gameaction = ga_loadgame;
- }
- //---------------------------------------------------------------------------
- //
- // PROC G_DoLoadGame
- //
- // Called by G_Ticker based on gameaction.
- //
- //---------------------------------------------------------------------------
- #define VERSIONSIZE 16
- void G_DoLoadGame(void)
- {
- int length;
- int i;
- int a, b, c;
- char vcheck[VERSIONSIZE];
- gameaction = ga_nothing;
- length = M_ReadFile(savename, &savebuffer);
- save_p = savebuffer+SAVESTRINGSIZE;
- // Skip the description field
- memset(vcheck, 0, sizeof(vcheck));
- sprintf(vcheck, "version %i", VERSION);
- if (strcmp (save_p, vcheck))
- { // Bad version
- return;
- }
- save_p += VERSIONSIZE;
- gameskill = *save_p++;
- gameepisode = *save_p++;
- gamemap = *save_p++;
- for(i = 0; i < MAXPLAYERS; i++)
- {
- playeringame[i] = *save_p++;
- }
- // Load a base level
- G_InitNew(gameskill, gameepisode, gamemap);
- // Create leveltime
- a = *save_p++;
- b = *save_p++;
- c = *save_p++;
- leveltime = (a<<16)+(b<<8)+c;
- // De-archive all the modifications
- P_UnArchivePlayers();
- P_UnArchiveWorld();
- P_UnArchiveThinkers();
- P_UnArchiveSpecials();
- if(*save_p != SAVE_GAME_TERMINATOR)
- { // Missing savegame termination marker
- I_Error("Bad savegame");
- }
- Z_Free(savebuffer);
- }
- /*
- ====================
- =
- = G_InitNew
- =
- = Can be called by the startup code or the menu task
- = consoleplayer, displayplayer, playeringame[] should be set
- ====================
- */
- skill_t d_skill;
- int d_episode;
- int d_map;
- void G_DeferedInitNew (skill_t skill, int episode, int map)
- {
- d_skill = skill;
- d_episode = episode;
- d_map = map;
- gameaction = ga_newgame;
- }
- void G_DoNewGame (void)
- {
- G_InitNew (d_skill, d_episode, d_map);
- gameaction = ga_nothing;
- }
- extern int skytexture;
- void G_InitNew(skill_t skill, int episode, int map)
- {
- int i;
- int speed;
- static char *skyLumpNames[5] =
- {
- "SKY1", "SKY2", "SKY3", "SKY1", "SKY3"
- };
- if(paused)
- {
- paused = false;
- S_ResumeSound();
- }
- if(skill < sk_baby)
- skill = sk_baby;
- if(skill > sk_nightmare)
- skill = sk_nightmare;
- if(episode < 1)
- episode = 1;
- // Up to 9 episodes for testing
- if(episode > 9)
- episode = 9;
- if(map < 1)
- map = 1;
- if(map > 9)
- map = 9;
- M_ClearRandom();
- if(respawnparm)
- {
- respawnmonsters = true;
- }
- else
- {
- respawnmonsters = false;
- }
- // Set monster missile speeds
- speed = skill == sk_nightmare;
- for(i = 0; MonsterMissileInfo[i].type != -1; i++)
- {
- mobjinfo[MonsterMissileInfo[i].type].speed
- = MonsterMissileInfo[i].speed[speed]<<FRACBITS;
- }
- // Force players to be initialized upon first level load
- for(i = 0; i < MAXPLAYERS; i++)
- {
- players[i].playerstate = PST_REBORN;
- players[i].didsecret = false;
- }
- // Set up a bunch of globals
- usergame = true; // will be set false if a demo
- paused = false;
- demorecording = false;
- demoplayback = false;
- viewactive = true;
- gameepisode = episode;
- gamemap = map;
- gameskill = skill;
- viewactive = true;
- BorderNeedRefresh = true;
- // Set the sky map
- if(episode > 5)
- {
- skytexture = R_TextureNumForName("SKY1");
- }
- else
- {
- skytexture = R_TextureNumForName(skyLumpNames[episode-1]);
- }
- //
- // give one null ticcmd_t
- //
- #if 0
- gametic = 0;
- maketic = 1;
- for (i=0 ; i<MAXPLAYERS ; i++)
- nettics[i] = 1; // one null event for this gametic
- memset (localcmds,0,sizeof(localcmds));
- memset (netcmds,0,sizeof(netcmds));
- #endif
- G_DoLoadLevel();
- }
- /*
- ===============================================================================
- DEMO RECORDING
- ===============================================================================
- */
- #define DEMOMARKER 0x80
- void G_ReadDemoTiccmd (ticcmd_t *cmd)
- {
- if (*demo_p == DEMOMARKER)
- { // end of demo data stream
- G_CheckDemoStatus ();
- return;
- }
- cmd->forwardmove = ((signed char)*demo_p++);
- cmd->sidemove = ((signed char)*demo_p++);
- cmd->angleturn = ((unsigned char)*demo_p++)<<8;
- cmd->buttons = (unsigned char)*demo_p++;
- cmd->lookfly = (unsigned char)*demo_p++;
- cmd->arti = (unsigned char)*demo_p++;
- }
- void G_WriteDemoTiccmd (ticcmd_t *cmd)
- {
- if (gamekeydown['q']) // press q to end demo recording
- G_CheckDemoStatus ();
- *demo_p++ = cmd->forwardmove;
- *demo_p++ = cmd->sidemove;
- *demo_p++ = cmd->angleturn>>8;
- *demo_p++ = cmd->buttons;
- *demo_p++ = cmd->lookfly;
- *demo_p++ = cmd->arti;
- demo_p -= 6;
- G_ReadDemoTiccmd (cmd); // make SURE it is exactly the same
- }
- /*
- ===================
- =
- = G_RecordDemo
- =
- ===================
- */
- void G_RecordDemo (skill_t skill, int numplayers, int episode, int map, char *name)
- {
- int i;
- G_InitNew (skill, episode, map);
- usergame = false;
- strcpy (demoname, name);
- strcat (demoname, ".lmp");
- demobuffer = demo_p = Z_Malloc (0x20000,PU_STATIC,NULL);
- *demo_p++ = skill;
- *demo_p++ = episode;
- *demo_p++ = map;
- for (i=0 ; i<MAXPLAYERS ; i++)
- *demo_p++ = playeringame[i];
- demorecording = true;
- }
- /*
- ===================
- =
- = G_PlayDemo
- =
- ===================
- */
- char *defdemoname;
- void G_DeferedPlayDemo (char *name)
- {
- defdemoname = name;
- gameaction = ga_playdemo;
- }
- void G_DoPlayDemo (void)
- {
- skill_t skill;
- int i, episode, map;
- gameaction = ga_nothing;
- demobuffer = demo_p = W_CacheLumpName (defdemoname, PU_STATIC);
- skill = *demo_p++;
- episode = *demo_p++;
- map = *demo_p++;
- for (i=0 ; i<MAXPLAYERS ; i++)
- playeringame[i] = *demo_p++;
- precache = false; // don't spend a lot of time in loadlevel
- G_InitNew (skill, episode, map);
- precache = true;
- usergame = false;
- demoplayback = true;
- }
- /*
- ===================
- =
- = G_TimeDemo
- =
- ===================
- */
- void G_TimeDemo (char *name)
- {
- skill_t skill;
- int episode, map;
- demobuffer = demo_p = W_CacheLumpName (name, PU_STATIC);
- skill = *demo_p++;
- episode = *demo_p++;
- map = *demo_p++;
- G_InitNew (skill, episode, map);
- usergame = false;
- demoplayback = true;
- timingdemo = true;
- singletics = true;
- }
- /*
- ===================
- =
- = G_CheckDemoStatus
- =
- = Called after a death or level completion to allow demos to be cleaned up
- = Returns true if a new demo loop action will take place
- ===================
- */
- boolean G_CheckDemoStatus (void)
- {
- int endtime;
- if (timingdemo)
- {
- endtime = I_GetTime ();
- I_Error ("timed %i gametics in %i realtics",gametic
- , endtime-starttime);
- }
- if (demoplayback)
- {
- if (singledemo)
- I_Quit ();
- Z_ChangeTag (demobuffer, PU_CACHE);
- demoplayback = false;
- D_AdvanceDemo ();
- return true;
- }
- if (demorecording)
- {
- *demo_p++ = DEMOMARKER;
- M_WriteFile (demoname, demobuffer, demo_p - demobuffer);
- Z_Free (demobuffer);
- demorecording = false;
- I_Error ("Demo %s recorded",demoname);
- }
- return false;
- }
- /**************************************************************************/
- /**************************************************************************/
- //==========================================================================
- //
- // G_SaveGame
- //
- // Called by the menu task. <description> is a 24 byte text string.
- //
- //==========================================================================
- void G_SaveGame(int slot, char *description)
- {
- savegameslot = slot;
- strcpy(savedescription, description);
- sendsave = true;
- }
- //==========================================================================
- //
- // G_DoSaveGame
- //
- // Called by G_Ticker based on gameaction.
- //
- //==========================================================================
- void G_DoSaveGame(void)
- {
- int i;
- char name[100];
- char verString[VERSIONSIZE];
- char *description;
- if(cdrom)
- {
- sprintf(name, SAVEGAMENAMECD"%d.hsg", savegameslot);
- }
- else
- {
- sprintf(name, SAVEGAMENAME"%d.hsg", savegameslot);
- }
- description = savedescription;
- SV_Open(name);
- SV_Write(description, SAVESTRINGSIZE);
- memset(verString, 0, sizeof(verString));
- sprintf(verString, "version %i", VERSION);
- SV_Write(verString, VERSIONSIZE);
- SV_WriteByte(gameskill);
- SV_WriteByte(gameepisode);
- SV_WriteByte(gamemap);
- for(i = 0; i < MAXPLAYERS; i++)
- {
- SV_WriteByte(playeringame[i]);
- }
- SV_WriteByte(leveltime>>16);
- SV_WriteByte(leveltime>>8);
- SV_WriteByte(leveltime);
- P_ArchivePlayers();
- P_ArchiveWorld();
- P_ArchiveThinkers();
- P_ArchiveSpecials();
- SV_Close(name);
- gameaction = ga_nothing;
- savedescription[0] = 0;
- P_SetMessage(&players[consoleplayer], TXT_GAMESAVED, true);
- }
- //==========================================================================
- //
- // SV_Open
- //
- //==========================================================================
- void SV_Open(char *fileName)
- {
- MallocFailureOk = true;
- save_p = savebuffer = Z_Malloc(SAVEGAMESIZE, PU_STATIC, NULL);
- MallocFailureOk = false;
- if(savebuffer == NULL)
- { // Not enough memory - use file save method
- SaveGameType = SVG_FILE;
- SaveGameFP = fopen(fileName, "wb");
- }
- else
- {
- SaveGameType = SVG_RAM;
- }
- }
- //==========================================================================
- //
- // SV_Close
- //
- //==========================================================================
- void SV_Close(char *fileName)
- {
- int length;
- SV_WriteByte(SAVE_GAME_TERMINATOR);
- if(SaveGameType == SVG_RAM)
- {
- length = save_p-savebuffer;
- if(length > SAVEGAMESIZE)
- {
- I_Error("Savegame buffer overrun");
- }
- M_WriteFile(fileName, savebuffer, length);
- Z_Free(savebuffer);
- }
- else
- { // SVG_FILE
- fclose(SaveGameFP);
- }
- }
- //==========================================================================
- //
- // SV_Write
- //
- //==========================================================================
- void SV_Write(void *buffer, int size)
- {
- if(SaveGameType == SVG_RAM)
- {
- memcpy(save_p, buffer, size);
- save_p += size;
- }
- else
- { // SVG_FILE
- fwrite(buffer, size, 1, SaveGameFP);
- }
- }
- void SV_WriteByte(byte val)
- {
- SV_Write(&val, sizeof(byte));
- }
- void SV_WriteWord(unsigned short val)
- {
- SV_Write(&val, sizeof(unsigned short));
- }
- void SV_WriteLong(unsigned int val)
- {
- SV_Write(&val, sizeof(int));
- }
|