From 8606045689b1ecfafd090500eff23385d1546183 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 5 Dec 2021 17:36:57 +0100 Subject: [PATCH] - Duke: made gamevars type safe and capable of managing actor pointers. Also a few unrelated changes needed to make it compile again. --- source/games/duke/src/actors_d.cpp | 2 +- source/games/duke/src/cheats.cpp | 4 +- source/games/duke/src/dukeactor.h | 13 -- source/games/duke/src/gameexec.cpp | 277 +++++++++++++++++------------ source/games/duke/src/gamevar.cpp | 140 ++++++++++----- source/games/duke/src/gamevar.h | 51 +++++- source/games/duke/src/input.cpp | 22 +-- source/games/duke/src/player.cpp | 20 +-- source/games/duke/src/player_d.cpp | 22 +-- source/games/duke/src/player_r.cpp | 4 +- source/games/duke/src/player_w.cpp | 6 +- source/games/duke/src/savegame.cpp | 19 +- source/games/duke/src/types.h | 8 +- 13 files changed, 365 insertions(+), 223 deletions(-) diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index 4ff5822ca..16ca73c24 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -1003,7 +1003,7 @@ static void movetripbomb(DDukeActor *actor) { auto s = actor->s; int j, x; - int lTripBombControl = GetGameVar("TRIPBOMB_CONTROL", TRIPBOMB_TRIPWIRE, nullptr, -1); + int lTripBombControl = GetGameVar("TRIPBOMB_CONTROL", TRIPBOMB_TRIPWIRE, nullptr, -1).safeValue(); if (lTripBombControl & TRIPBOMB_TIMER) { // we're on a timer.... diff --git a/source/games/duke/src/cheats.cpp b/source/games/duke/src/cheats.cpp index ee03db55a..1b9060380 100644 --- a/source/games/duke/src/cheats.cpp +++ b/source/games/duke/src/cheats.cpp @@ -248,9 +248,9 @@ static bool cheatInventory(int player) { SetGameVarID(g_iReturnVarID, defvalue, nullptr, player); OnEvent(evtype, player, nullptr, -1); - if (GetGameVarID(g_iReturnVarID, nullptr, player) >= 0) + if (GetGameVarID(g_iReturnVarID, nullptr, player).safeValue() >= 0) { - dest = GetGameVarID(g_iReturnVarID, nullptr, player); + dest = GetGameVarID(g_iReturnVarID, nullptr, player).value(); } }; diff --git a/source/games/duke/src/dukeactor.h b/source/games/duke/src/dukeactor.h index 10367c8fc..9695d1be8 100644 --- a/source/games/duke/src/dukeactor.h +++ b/source/games/duke/src/dukeactor.h @@ -19,19 +19,6 @@ inline int player_struct::GetPlayerNum() return actor->s->yvel; } -inline int ActorToScriptIndex(DDukeActor* a) -{ - if (!a) return -1; - return a->GetSpriteIndex(); -} - -inline DDukeActor* ScriptIndexToActor(int index) -{ - // only allow valid actors to get through here. Everything else gets null'ed. - if (index < 0 || index >= MAXSPRITES || hittype[index].s->statnum == MAXSTATUS) return nullptr; - return &hittype[index]; -} - DDukeActor* spawn(DDukeActor* spawner, int type); inline int ldist(DDukeActor* s1, DDukeActor* s2) diff --git a/source/games/duke/src/gameexec.cpp b/source/games/duke/src/gameexec.cpp index b7eb14bd8..dcd895825 100644 --- a/source/games/duke/src/gameexec.cpp +++ b/source/games/duke/src/gameexec.cpp @@ -95,11 +95,30 @@ void addspritetodelete(int spnum) killthesprite = true; } +sectortype* toSect(int index) +{ + return validSectorIndex(index) ? §or[index] : nullptr; +} + +int fromSect(sectortype* sect) +{ + return sect ? sectnum(sect) : -1; +} + +walltype* toWall(int index) +{ + return validWallIndex(index) ? &wall[index] : nullptr; +} + +int fromWall(walltype* sect) +{ + return sect ? wallnum(sect) : -1; +} + static void DoUserDef(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, int sPlayer, int lParm2) { - int lValue; - - lValue = GetGameVarID(lVar2, sActor, sPlayer); + auto vValue = GetGameVarID(lVar2, sActor, sPlayer); + auto lValue = vValue.safeValue(); // most settings have been removed because they are either pointless, no longer existent or simply too dangerous to access. // Others have been made read-only. @@ -131,8 +150,8 @@ static void DoUserDef(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* break; case USERDEFS_CAMERASPRITE: - if (bSet) ud.cameraactor = ScriptIndexToActor(lValue); - else SetGameVarID(lVar2, ActorToScriptIndex(ud.cameraactor), sActor, sPlayer); + if (bSet) ud.cameraactor = vValue.safeActor(); + else SetGameVarID(lVar2, ud.cameraactor, sActor, sPlayer); break; case USERDEFS_LAST_CAMSPRITE: @@ -251,11 +270,11 @@ static void DoUserDef(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* /////////////////////////////////////////// void DoPlayer(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, int sPlayer, int lParm2) { - int iPlayer; - int lValue; - int lTemp; + auto vValue = GetGameVarID(lVar2, sActor, sPlayer); + auto lValue = vValue.safeValue(); - lValue = GetGameVarID(lVar2, sActor, sPlayer); + int iPlayer; + int lTemp; if (lVar1 == g_iThisActorID) { @@ -264,7 +283,7 @@ void DoPlayer(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, } else { - iPlayer = GetGameVarID(lVar1, sActor, sPlayer); + iPlayer = GetGameVarID(lVar1, sActor, sPlayer).safeValue(); } if (iPlayer < 0 || iPlayer >= MAXPLAYERS) @@ -465,6 +484,11 @@ void DoPlayer(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, if (!bSet) SetGameVarID(lVar2, 0, sActor, sPlayer); break; + case PLAYER_CURSECTNUM: + if (bSet) ps[iPlayer].cursector = toSect(lValue); + else SetGameVarID(lVar2, fromSect(ps[iPlayer].cursector), sActor, sPlayer); + break; + case PLAYER_LOOK_ANG: if (bSet) ps[iPlayer].angle.look_ang = buildang(lValue); else SetGameVarID(lVar2, ps[iPlayer].angle.look_ang.asbuild(), sActor, sPlayer); @@ -481,14 +505,14 @@ void DoPlayer(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, break; case PLAYER_AMMO_AMOUNT: - lTemp = GetGameVarID(lParm2, sActor, sPlayer); + lTemp = GetGameVarID(lParm2, sActor, sPlayer).safeValue(); if (bSet) ps[iPlayer].ammo_amount[lTemp] = lValue; else SetGameVarID(lVar2, ps[iPlayer].ammo_amount[lTemp], sActor, sPlayer); break; case PLAYER_WACKEDBYACTOR: - if (bSet) ps[iPlayer].wackedbyactor = ScriptIndexToActor(lValue); - else SetGameVarID(lVar2, ActorToScriptIndex(ps[iPlayer].wackedbyactor), sActor, sPlayer); + if (bSet) ps[iPlayer].wackedbyactor = vValue.safeActor(); + else SetGameVarID(lVar2, ps[iPlayer].wackedbyactor, sActor, sPlayer); break; case PLAYER_FRAG: @@ -527,8 +551,8 @@ void DoPlayer(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, break; case PLAYER_NEWOWNER: - if (bSet) ps[iPlayer].newOwner = ScriptIndexToActor(lValue); - else SetGameVarID(lVar2, ActorToScriptIndex(ps[iPlayer].newOwner), sActor, sPlayer); + if (bSet) ps[iPlayer].newOwner = vValue.safeActor(); + else SetGameVarID(lVar2, ps[iPlayer].newOwner, sActor, sPlayer); break; case PLAYER_HURT_DELAY: @@ -561,6 +585,16 @@ void DoPlayer(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, else SetGameVarID(lVar2, ps[iPlayer].access_incs, sActor, sPlayer); break; + case PLAYER_ACCESS_WALLNUM: + if (bSet) ps[iPlayer].access_wall = toWall(lValue); + else SetGameVarID(lVar2, fromWall(ps[iPlayer].access_wall), sActor, sPlayer); + break; + + case PLAYER_ACCESS_SPRITENUM: + if (bSet) ps[iPlayer].access_spritenum = vValue.safeActor(); + else SetGameVarID(lVar2, ps[iPlayer].access_spritenum, sActor, sPlayer); + break; + case PLAYER_KICKBACK_PIC: if (bSet) ps[iPlayer].okickback_pic = ps[iPlayer].kickback_pic = lValue; else SetGameVarID(lVar2, ps[iPlayer].kickback_pic, sActor, sPlayer); @@ -582,13 +616,22 @@ void DoPlayer(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, break; case PLAYER_SOMETHINGONPLAYER: - if (bSet) ps[iPlayer].somethingonplayer = ScriptIndexToActor(lValue); - else SetGameVarID(lVar2, ActorToScriptIndex(ps[iPlayer].somethingonplayer), sActor, sPlayer); + if (bSet) ps[iPlayer].somethingonplayer = vValue.safeActor(); + else SetGameVarID(lVar2, (ps[iPlayer].somethingonplayer), sActor, sPlayer); break; case PLAYER_ON_CRANE: - if (bSet) ps[iPlayer].on_crane = ScriptIndexToActor(lValue); - else SetGameVarID(lVar2, ActorToScriptIndex(ps[iPlayer].on_crane), sActor, sPlayer); + if (bSet) ps[iPlayer].on_crane = vValue.safeActor(); + else SetGameVarID(lVar2, (ps[iPlayer].on_crane), sActor, sPlayer); + break; + + case PLAYER_I: // Read only, because this is very dangerous. + if (!bSet) SetGameVarID(lVar2, ps[iPlayer].actor, sActor, sPlayer); + break; + + case PLAYER_ONE_PARALLAX_SECTNUM: + if (bSet) ps[iPlayer].one_parallax_sectnum = toSect(lValue); + else SetGameVarID(lVar2, fromSect(ps[iPlayer].one_parallax_sectnum), sActor, sPlayer); break; case PLAYER_OVER_SHOULDER_ON: @@ -617,8 +660,8 @@ void DoPlayer(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, break; case PLAYER_DUMMYPLAYERSPRITE: - if (bSet) ps[iPlayer].dummyplayersprite = ScriptIndexToActor(lValue); - else SetGameVarID(lVar2, ActorToScriptIndex(ps[iPlayer].dummyplayersprite), sActor, sPlayer); + if (bSet) ps[iPlayer].dummyplayersprite = vValue.safeActor(); + else SetGameVarID(lVar2, (ps[iPlayer].dummyplayersprite), sActor, sPlayer); break; case PLAYER_EXTRA_EXTRA8: @@ -637,8 +680,8 @@ void DoPlayer(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, break; case PLAYER_ACTORSQU: - if (bSet) ps[iPlayer].actorsqu = ScriptIndexToActor(lValue); - else SetGameVarID(lVar2, ActorToScriptIndex(ps[iPlayer].actorsqu), sActor, sPlayer); + if (bSet) ps[iPlayer].actorsqu = vValue.safeActor(); + else SetGameVarID(lVar2, (ps[iPlayer].actorsqu), sActor, sPlayer); break; case PLAYER_TIMEBEFOREEXIT: @@ -706,8 +749,8 @@ void DoPlayer(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, break; case PLAYER_HOLODUKE_ON: - if (bSet) ps[iPlayer].holoduke_on = ScriptIndexToActor(lValue); - else SetGameVarID(lVar2, ActorToScriptIndex(ps[iPlayer].holoduke_on), sActor, sPlayer); + if (bSet) ps[iPlayer].holoduke_on = vValue.safeActor(); + else SetGameVarID(lVar2, (ps[iPlayer].holoduke_on), sActor, sPlayer); break; case PLAYER_PYCOUNT: @@ -906,14 +949,11 @@ void DoPlayer(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, //////////////////// void DoWall(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, int sPlayer, int lParm2) { - int iWall; - int lValue; + auto lValue = GetGameVarID(lVar2, sActor, sPlayer).safeValue(); + auto vWall = GetGameVarID(lVar1, sActor, sPlayer); + auto iWall = vWall.safeValue(); - lValue = GetGameVarID(lVar2, sActor, sPlayer); - - iWall = GetGameVarID(lVar1, sActor, sPlayer); - - if (iWall < 0 || iWall >= numwalls) + if (iWall < 0 || iWall >= numwalls || vWall.isActor()) { if (!bSet) SetGameVarID(lVar2, 0, sActor, sPlayer); return; @@ -996,6 +1036,7 @@ void DoSector(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, { int iSector; int lValue; + bool no = false; if (lVar1 == g_iThisActorID) { @@ -1004,16 +1045,18 @@ void DoSector(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, } else { - iSector = GetGameVarID(lVar1, sActor, sPlayer); + auto vv = GetGameVarID(lVar1, sActor, sPlayer); + no = vv.isActor(); + iSector = vv.safeValue(); } - if (iSector < 0 || iSector >= numsectors) + if (iSector < 0 || iSector >= numsectors || no) { if (!bSet) SetGameVarID(lVar2, 0, sActor, sPlayer); return; } - lValue = GetGameVarID(lVar2, sActor, sPlayer); + lValue = GetGameVarID(lVar2, sActor, sPlayer).safeValue(); auto sectp = §or[iSector]; // All fields affecting map geometry have been made read-only! @@ -1111,28 +1154,25 @@ void DoSector(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, } return; } + void DoActor(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, int sPlayer, int lParm2) { - int iActor; - int lValue; - - lValue = GetGameVarID(lVar2, sActor, sPlayer); + auto vValue = GetGameVarID(lVar2, sActor, sPlayer); + auto lValue = vValue.safeValue(); DDukeActor* act; if (lVar1 == g_iThisActorID) { // if they've asked for 'this', then use 'this'... act = sActor; - iActor = ActorToScriptIndex(sActor); } else { - iActor = GetGameVarID(lVar1, sActor, sPlayer); - act = ScriptIndexToActor(iActor); + act = GetGameVarID(lVar1, sActor, sPlayer).safeActor(); } auto spr = act->s; - if (iActor < 0 || iActor >= MAXSPRITES || spr->statnum == MAXSTATUS) + if (!act) { if (!bSet) SetGameVarID(lVar2, 0, sActor, sPlayer); return; @@ -1192,11 +1232,20 @@ void DoActor(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, if (bSet) spr->yoffset = lValue; else SetGameVarID(lVar2, spr->yoffset, sActor, sPlayer); break; + case ACTOR_SECTNUM: // made read only because this is not safe. + if (!bSet) /*changespritesect(iActor, lValue); + else*/ SetGameVarID(lVar2, spr->sectnum, sActor, sPlayer); + break; + case ACTOR_STATNUM: + if (!bSet) /*changespritestat(iActor, lValue); + else*/ SetGameVarID(lVar2, spr->statnum, sActor, sPlayer); + break; case ACTOR_ANG: if (bSet) spr->ang = lValue; else SetGameVarID(lVar2, spr->ang, sActor, sPlayer); break; case ACTOR_OWNER: + // there is no way to handle this well because we do not know whether this is an actor or not. Pity. if (bSet) spr->owner = lValue; else SetGameVarID(lVar2, spr->owner, sActor, sPlayer); break; @@ -1241,6 +1290,10 @@ void DoActor(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, if (bSet) act->extra = lValue; else SetGameVarID(lVar2, act->extra, sActor, sPlayer); break; + case ACTOR_HTOWNER: + if (bSet) act->hitOwnerActor = vValue.safeActor(); + else SetGameVarID(lVar2, act->hitOwnerActor, sActor, sPlayer); + break; case ACTOR_HTMOVFLAG: if (bSet) act->movflag = lValue; else SetGameVarID(lVar2, act->movflag, sActor, sPlayer); @@ -1249,6 +1302,10 @@ void DoActor(bool bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, if (bSet) act->tempang = lValue; else SetGameVarID(lVar2, act->tempang, sActor, sPlayer); break; + case ACTOR_HTACTORSTAYPUT: + if (bSet) act->actorstayput = toSect(lValue); + else SetGameVarID(lVar2, fromSect(act->actorstayput), sActor, sPlayer); + break; case ACTOR_HTDISPICNUM: if (bSet) act->dispicnum = lValue; else SetGameVarID(lVar2, act->dispicnum, sActor, sPlayer); @@ -2590,7 +2647,7 @@ int ParseState::parse(void) { int i; insptr++; i=*(insptr++); // ID of def - SetGameVarID(i, GetGameVarID(i, g_ac, g_p) + *insptr, g_ac, g_p ); + SetGameVarID(i, GetGameVarID(i, g_ac, g_p).safeValue() + *insptr, g_ac, g_p ); insptr++; break; } @@ -2599,7 +2656,7 @@ int ParseState::parse(void) { int i; insptr++; i=*(insptr++); // ID of def - SetGameVarID(i, GetGameVarID(i, g_ac, g_p) + GetGameVarID(*insptr, g_ac, g_p), g_ac, g_p ); + SetGameVarID(i, GetGameVarID(i, g_ac, g_p).safeValue() + GetGameVarID(*insptr, g_ac, g_p).safeValue(), g_ac, g_p ); insptr++; break; } @@ -2609,7 +2666,7 @@ int ParseState::parse(void) insptr++; i=*(insptr++); // ID of def j=0; - if(GetGameVarID(i, g_ac, g_p) == GetGameVarID(*(insptr), g_ac, g_p) ) + if(GetGameVarID(i, g_ac, g_p).safeValue() == GetGameVarID(*(insptr), g_ac, g_p).safeValue()) { j=1; } @@ -2622,7 +2679,7 @@ int ParseState::parse(void) insptr++; i=*(insptr++); // ID of def j=0; - if(GetGameVarID(i, g_ac, g_p) > GetGameVarID(*(insptr), g_ac, g_p) ) + if(GetGameVarID(i, g_ac, g_p).safeValue() > GetGameVarID(*(insptr), g_ac, g_p).safeValue()) { j=1; } @@ -2635,7 +2692,7 @@ int ParseState::parse(void) insptr++; i=*(insptr++); // ID of def j=0; - if(GetGameVarID(i, g_ac, g_p) < GetGameVarID(*(insptr), g_ac, g_p) ) + if(GetGameVarID(i, g_ac, g_p).safeValue() < GetGameVarID(*(insptr), g_ac, g_p).safeValue()) { j=1; } @@ -2648,7 +2705,7 @@ int ParseState::parse(void) insptr++; i=*(insptr++); // ID of def j=0; - if(GetGameVarID(i, g_ac, g_p) == *insptr) + if(GetGameVarID(i, g_ac, g_p).safeValue() == *insptr) { j=1; } @@ -2661,7 +2718,7 @@ int ParseState::parse(void) insptr++; i=*(insptr++); // ID of def j=0; - if(GetGameVarID(i, g_ac, g_p) > *insptr) + if(GetGameVarID(i, g_ac, g_p).safeValue() > *insptr) { j=1; } @@ -2674,7 +2731,7 @@ int ParseState::parse(void) insptr++; i=*(insptr++); // ID of def j=0; - if(GetGameVarID(i, g_ac, g_p) < *insptr) + if(GetGameVarID(i, g_ac, g_p).safeValue() < *insptr) { j=1; } @@ -2835,11 +2892,11 @@ int ParseState::parse(void) insptr++; lIn = *insptr++; - lIn = GetGameVarID(lIn, g_ac, g_p); + lIn = GetGameVarID(lIn, g_ac, g_p).safeValue(); if(g_ac->insector()) lReturn = spawn(g_ac, lIn); - SetGameVarID(g_iReturnVarID, ActorToScriptIndex(lReturn), g_ac, g_p); + SetGameVarID(g_iReturnVarID, (lReturn), g_ac, g_p); break; } case concmd_espawn: @@ -2849,7 +2906,7 @@ int ParseState::parse(void) if(g_ac->insector()) lReturn = spawn(g_ac, *insptr); insptr++; - SetGameVarID(g_iReturnVarID, ActorToScriptIndex(lReturn), g_ac, g_p); + SetGameVarID(g_iReturnVarID, (lReturn), g_ac, g_p); break; } case concmd_setsector: @@ -2881,7 +2938,7 @@ int ParseState::parse(void) insptr++; lInVarID = *(insptr++); lOutVarID = *(insptr++); - lIn = GetGameVarID(lInVarID, g_ac, g_p); + lIn = GetGameVarID(lInVarID, g_ac, g_p).safeValue(); SetGameVarID(lOutVarID, ksqrt(lIn), g_ac, g_p); break; } @@ -2923,7 +2980,7 @@ int ParseState::parse(void) } } - SetGameVarID(lVarID, ActorToScriptIndex(lFound), g_ac, g_p); + SetGameVarID(lVarID, (lFound), g_ac, g_p); break; } @@ -2946,7 +3003,7 @@ int ParseState::parse(void) lType = *(insptr++); lMaxDistVar = *(insptr++); lVarID = *(insptr++); - lMaxDist = GetGameVarID(lMaxDistVar, g_ac, g_p); + lMaxDist = GetGameVarID(lMaxDistVar, g_ac, g_p).safeValue(); DDukeActor* lFound = nullptr; lDist = 32767; // big number @@ -2966,7 +3023,7 @@ int ParseState::parse(void) } } - SetGameVarID(lVarID, ActorToScriptIndex(lFound), g_ac, g_p); + SetGameVarID(lVarID, (lFound), g_ac, g_p); break; } @@ -3033,7 +3090,6 @@ int ParseState::parse(void) // gets the value of the per-actor variable varx into VAR // int lVar1, lVar2, lVar3; - int lTemp, lSprite; insptr++; @@ -3041,11 +3097,11 @@ int ParseState::parse(void) lVar2 = *(insptr++); lVar3 = *(insptr++); - lSprite = GetGameVarID(lVar1, g_ac, g_p); - if (lSprite >= 0) + auto lSprite = GetGameVarID(lVar1, g_ac, g_p); + if (lSprite.isActor()) { - lTemp = GetGameVarID(lVar3, g_ac, g_p); - SetGameVarID(lVar2, lTemp, ScriptIndexToActor(lSprite), g_p); + auto lTemp = GetGameVarID(lVar3, g_ac, g_p); + SetGameVarID(lVar2, lTemp, lSprite.actor(), g_p); } break; @@ -3056,7 +3112,6 @@ int ParseState::parse(void) // gets the value of the per-actor variable varx into VAR // int lVar1, lVar2, lVar3; - int lTemp, lSprite; insptr++; @@ -3064,10 +3119,10 @@ int ParseState::parse(void) lVar2 = *(insptr++); lVar3 = *(insptr++); - lSprite = GetGameVarID(lVar1, g_ac, g_p); - if (lSprite >= 0) + auto lSprite = GetGameVarID(lVar1, g_ac, g_p); + if (lSprite.isActor()) { - lTemp = GetGameVarID(lVar2, ScriptIndexToActor(lSprite), g_p); + auto lTemp = GetGameVarID(lVar2, lSprite.actor(), g_p); SetGameVarID(lVar3, lTemp, g_ac, g_p); } @@ -3110,7 +3165,7 @@ int ParseState::parse(void) int i; insptr++; i = *(insptr++); // ID of def - ps[g_p].transporter_hold = GetGameVarID(i, g_ac, g_p); + ps[g_p].transporter_hold = GetGameVarID(i, g_ac, g_p).safeValue(); break; } case concmd_getplayerangle: @@ -3126,7 +3181,7 @@ int ParseState::parse(void) int i; insptr++; i = *(insptr++); // ID of def - ps[g_p].angle.ang = buildang(GetGameVarID(i, g_ac, g_p) & 2047); + ps[g_p].angle.ang = buildang(GetGameVarID(i, g_ac, g_p).safeValue() & 2047); break; } case concmd_getactorangle: @@ -3142,7 +3197,7 @@ int ParseState::parse(void) int i; insptr++; i = *(insptr++); // ID of def - g_sp->ang = GetGameVarID(i, g_ac, g_p); + g_sp->ang = GetGameVarID(i, g_ac, g_p).safeValue(); g_sp->ang &= 2047; break; } @@ -3160,7 +3215,7 @@ int ParseState::parse(void) int i; insptr++; i = *(insptr++); // ID of def - SetGameVarID(i, GetGameVarID(i, g_ac, g_p) * (*insptr), g_ac, g_p); + SetGameVarID(i, GetGameVarID(i, g_ac, g_p).safeValue()* (*insptr), g_ac, g_p); insptr++; break; } @@ -3173,7 +3228,7 @@ int ParseState::parse(void) { I_Error("Divide by Zero in CON."); } - SetGameVarID(i, GetGameVarID(i, g_ac, g_p) / (*insptr), g_ac, g_p); + SetGameVarID(i, GetGameVarID(i, g_ac, g_p).safeValue() / (*insptr), g_ac, g_p); insptr++; break; } @@ -3189,7 +3244,7 @@ int ParseState::parse(void) { I_Error("Divide by Zero in CON"); } - lResult = GetGameVarID(i, g_ac, g_p) % l; + lResult = GetGameVarID(i, g_ac, g_p).safeValue() % l; SetGameVarID(i, lResult, g_ac, g_p); insptr++; break; @@ -3202,7 +3257,7 @@ int ParseState::parse(void) insptr++; i = *(insptr++); // ID of def l = (*insptr); - lResult = GetGameVarID(i, g_ac, g_p) & l; + lResult = GetGameVarID(i, g_ac, g_p).safeValue() & l; SetGameVarID(i, lResult, g_ac, g_p); insptr++; break; @@ -3215,7 +3270,7 @@ int ParseState::parse(void) insptr++; i = *(insptr++); // ID of def l = (*insptr); - lResult = GetGameVarID(i, g_ac, g_p) ^ l; + lResult = GetGameVarID(i, g_ac, g_p).safeValue() ^ l; SetGameVarID(i, lResult, g_ac, g_p); insptr++; break; @@ -3228,7 +3283,7 @@ int ParseState::parse(void) insptr++; i = *(insptr++); // ID of def l = (*insptr); - lResult = GetGameVarID(i, g_ac, g_p) | l; + lResult = GetGameVarID(i, g_ac, g_p).safeValue() | l; SetGameVarID(i, lResult, g_ac, g_p); insptr++; break; @@ -3240,8 +3295,8 @@ int ParseState::parse(void) int lResult; insptr++; i = *(insptr++); // ID of def - l1 = GetGameVarID(i, g_ac, g_p); // not used for this command - l2 = GetGameVarID(*insptr, g_ac, g_p); + l1 = GetGameVarID(i, g_ac, g_p).safeValue(); // not used for this command + l2 = GetGameVarID(*insptr, g_ac, g_p).safeValue(); lResult = MulScale(rand(), l2, 15); SetGameVarID(i, lResult, g_ac, g_p); insptr++; @@ -3254,8 +3309,8 @@ int ParseState::parse(void) int lResult; insptr++; i = *(insptr++); // ID of def - l1 = GetGameVarID(i, g_ac, g_p); - l2 = GetGameVarID(*insptr, g_ac, g_p); // l2 not used in this one + l1 = GetGameVarID(i, g_ac, g_p).safeValue(); + l2 = GetGameVarID(*insptr, g_ac, g_p).safeValue(); // l2 not used in this one lResult = gs.max_ammo_amount[l1]; SetGameVarID(*insptr, lResult, g_ac, g_p); insptr++; @@ -3267,8 +3322,8 @@ int ParseState::parse(void) int l1, l2; insptr++; i = *(insptr++); // ID of def - l1 = GetGameVarID(i, g_ac, g_p); - l2 = GetGameVarID(*insptr, g_ac, g_p); + l1 = GetGameVarID(i, g_ac, g_p).safeValue(); + l2 = GetGameVarID(*insptr, g_ac, g_p).safeValue(); gs.max_ammo_amount[l1] = l2; insptr++; @@ -3281,8 +3336,8 @@ int ParseState::parse(void) int lResult; insptr++; i = *(insptr++); // ID of def - l1 = GetGameVarID(i, g_ac, g_p); - l2 = GetGameVarID(*insptr, g_ac, g_p); + l1 = GetGameVarID(i, g_ac, g_p).safeValue(); + l2 = GetGameVarID(*insptr, g_ac, g_p).safeValue(); lResult = l1 * l2; SetGameVarID(i, lResult, g_ac, g_p); insptr++; @@ -3295,8 +3350,8 @@ int ParseState::parse(void) int lResult; insptr++; i = *(insptr++); // ID of def - l1 = GetGameVarID(i, g_ac, g_p); - l2 = GetGameVarID(*insptr, g_ac, g_p); + l1 = GetGameVarID(i, g_ac, g_p).safeValue(); + l2 = GetGameVarID(*insptr, g_ac, g_p).safeValue(); if (l2 == 0) { I_Error("Divide by Zero in CON"); @@ -3313,8 +3368,8 @@ int ParseState::parse(void) int lResult; insptr++; i = *(insptr++); // ID of def - l1 = GetGameVarID(i, g_ac, g_p); - l2 = GetGameVarID(*insptr, g_ac, g_p); + l1 = GetGameVarID(i, g_ac, g_p).safeValue(); + l2 = GetGameVarID(*insptr, g_ac, g_p).safeValue(); if (l2 == 0) { I_Error("Mod by Zero in CON"); @@ -3331,8 +3386,8 @@ int ParseState::parse(void) int lResult; insptr++; i = *(insptr++); // ID of def - l1 = GetGameVarID(i, g_ac, g_p); - l2 = GetGameVarID(*insptr, g_ac, g_p); + l1 = GetGameVarID(i, g_ac, g_p).safeValue(); + l2 = GetGameVarID(*insptr, g_ac, g_p).safeValue(); lResult = l1 & l2; SetGameVarID(i, lResult, g_ac, g_p); insptr++; @@ -3345,8 +3400,8 @@ int ParseState::parse(void) int lResult; insptr++; i = *(insptr++); // ID of def - l1 = GetGameVarID(i, g_ac, g_p); - l2 = GetGameVarID(*insptr, g_ac, g_p); + l1 = GetGameVarID(i, g_ac, g_p).safeValue(); + l2 = GetGameVarID(*insptr, g_ac, g_p).safeValue(); lResult = l1 ^ l2; SetGameVarID(i, lResult, g_ac, g_p); insptr++; @@ -3359,8 +3414,8 @@ int ParseState::parse(void) int lResult; insptr++; i = *(insptr++); // ID of def - l1 = GetGameVarID(i, g_ac, g_p); - l2 = GetGameVarID(*insptr, g_ac, g_p); + l1 = GetGameVarID(i, g_ac, g_p).safeValue(); + l2 = GetGameVarID(*insptr, g_ac, g_p).safeValue(); lResult = l1 | l2; SetGameVarID(i, lResult, g_ac, g_p); insptr++; @@ -3371,7 +3426,7 @@ int ParseState::parse(void) int i; insptr++; i = *(insptr++); // ID of def - SetGameVarID(i, GetGameVarID(i, g_ac, g_p) - *insptr, g_ac, g_p); + SetGameVarID(i, GetGameVarID(i, g_ac, g_p).safeValue() - *insptr, g_ac, g_p); insptr++; break; } @@ -3380,7 +3435,7 @@ int ParseState::parse(void) int i; insptr++; i = *(insptr++); // ID of def - SetGameVarID(i, GetGameVarID(i, g_ac, g_p) - GetGameVarID(*insptr, g_ac, g_p), g_ac, g_p); + SetGameVarID(i, GetGameVarID(i, g_ac, g_p).safeValue() - GetGameVarID(*insptr, g_ac, g_p).safeValue(), g_ac, g_p); insptr++; break; } @@ -3390,7 +3445,7 @@ int ParseState::parse(void) int lValue; insptr++; i = *(insptr++); // ID of def - lValue = bsin(GetGameVarID(*insptr, g_ac, g_p)); + lValue = bsin(GetGameVarID(*insptr, g_ac, g_p).safeValue()); SetGameVarID(i, lValue, g_ac, g_p); insptr++; break; @@ -3434,8 +3489,8 @@ int ParseState::parse(void) int levnume; insptr++; // skip command - volnume = GetGameVarID(*insptr++, g_ac, g_p); - levnume = GetGameVarID(*insptr++, g_ac, g_p); + volnume = GetGameVarID(*insptr++, g_ac, g_p).safeValue(); + levnume = GetGameVarID(*insptr++, g_ac, g_p).safeValue(); auto level = FindMapByIndex(volnume, levnume); if (level != nullptr) ChangeLevel(level, g_nextskill); @@ -3453,14 +3508,14 @@ int ParseState::parse(void) int orientation; int pal; int tw = *insptr++; - x = GetGameVarID(*insptr++, g_ac, g_p); - y = GetGameVarID(*insptr++, g_ac, g_p); - tilenum = GetGameVarID(*insptr++, g_ac, g_p); - shade = GetGameVarID(*insptr++, g_ac, g_p); - orientation = GetGameVarID(*insptr++, g_ac, g_p); + x = GetGameVarID(*insptr++, g_ac, g_p).safeValue(); + y = GetGameVarID(*insptr++, g_ac, g_p).safeValue(); + tilenum = GetGameVarID(*insptr++, g_ac, g_p).safeValue(); + shade = GetGameVarID(*insptr++, g_ac, g_p).safeValue(); + orientation = GetGameVarID(*insptr++, g_ac, g_p).safeValue(); if (tw == concmd_myospal) { - pal = GetGameVarID(*insptr++, g_ac, g_p); + pal = GetGameVarID(*insptr++, g_ac, g_p).safeValue(); //myospal(x, y, tilenum, shade, orientation, pal); } else if (tw == concmd_myos) @@ -3473,7 +3528,7 @@ int ParseState::parse(void) } else if (tw == concmd_myospalx) { - pal = GetGameVarID(*insptr++, g_ac, g_p); + pal = GetGameVarID(*insptr++, g_ac, g_p).safeValue(); //myospal640(x, y, tilenum, shade, orientation, pal); } break; @@ -3508,7 +3563,7 @@ int ParseState::parse(void) // For each case: value, ptr to code insptr++; // p-code lVarID = *insptr++; - lValue = GetGameVarID(lVarID, g_ac, g_p); + lValue = GetGameVarID(lVarID, g_ac, g_p).safeValue(); lEnd = *insptr++; lCases = *insptr++; lpDefault = insptr++; @@ -3569,7 +3624,7 @@ int ParseState::parse(void) insptr++; i = *(insptr++); // ID of def j = 0; - if (GetGameVarID(i, g_ac, g_p) & GetGameVarID(*(insptr), g_ac, g_p)) + if (GetGameVarID(i, g_ac, g_p).safeValue() & GetGameVarID(*(insptr), g_ac, g_p).safeValue()) { j = 1; } @@ -3582,7 +3637,7 @@ int ParseState::parse(void) insptr++; i = *(insptr++); // ID of def j = 0; - if (GetGameVarID(i, g_ac, g_p) != GetGameVarID(*(insptr), g_ac, g_p)) + if (GetGameVarID(i, g_ac, g_p).safeValue() != GetGameVarID(*(insptr), g_ac, g_p).safeValue()) { j = 1; } @@ -3595,7 +3650,7 @@ int ParseState::parse(void) insptr++; i = *(insptr++); // ID of def j = 0; - if (GetGameVarID(i, g_ac, g_p) != *insptr) + if (GetGameVarID(i, g_ac, g_p).safeValue() != *insptr) { j = 1; } @@ -3608,7 +3663,7 @@ int ParseState::parse(void) insptr++; i = *(insptr++); // ID of def j = 0; - if (GetGameVarID(i, g_ac, g_p) & *insptr) + if (GetGameVarID(i, g_ac, g_p).safeValue() & *insptr) { j = 1; } diff --git a/source/games/duke/src/gamevar.cpp b/source/games/duke/src/gamevar.cpp index 7c3778729..468b42728 100644 --- a/source/games/duke/src/gamevar.cpp +++ b/source/games/duke/src/gamevar.cpp @@ -55,6 +55,45 @@ extern int errorcount, warningcount, line_count; //intptr_t *actorLoadEventScrptr[MAXTILES]; intptr_t apScriptGameEvent[MAXGAMEEVENTS]; + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +FSerializer& Serialize(FSerializer& arc, const char* keyname, GameVarValue& w, GameVarValue* def) +{ + if (arc.BeginObject(keyname)) + { + int type = w.isActor() ? 0 : 1; + arc("type", type); + switch (type) + { + case 0: + { + // pointless to handle now, fix when saving works again. +#pragma message(" fix me!"); +#if 0 + DDukeActor* a = arc.isWriting() ? w.actor() : nullptr; + arc("actor", a); + if (arc.isReading()) w = GameVarValue(a); + break; +#endif + } + case 1: + { + auto s = arc.isWriting()? w.value() : 0; + arc("value", s); + if (arc.isReading()) w = GameVarValue(s); + break; + } + } + arc.EndObject(); + } + return arc; +} + //--------------------------------------------------------------------------- // // @@ -72,8 +111,12 @@ void SerializeGameVars(FSerializer &arc) { if (arc.BeginObject(gv.szLabel)) { - arc("value", gv.lValue) - ("initvalue", gv.initValue) + if (gv.dwFlags & (GAMEVAR_FLAG_PERPLAYER | GAMEVAR_FLAG_PERACTOR)) + arc("index", gv.indexValue); + else + arc("value", gv.lValue); + + arc("initvalue", gv.initValue) .EndObject(); } } @@ -115,10 +158,10 @@ int AddGameVar(const char* pszLabel, intptr_t lValue, unsigned dwFlags) if (aGameVars[i].dwFlags & GAMEVAR_FLAG_SYSTEM && !(dwFlags & (GAMEVAR_FLAG_PLONG | GAMEVAR_FLAG_PFUNC))) { // if existing is system, they only get to change default value.... - aGameVars[i].lValue = (int)lValue; + aGameVars[i].lValue = GameVarValue(lValue); if (!(dwFlags & GAMEVAR_FLAG_NODEFAULT)) { - aGameVars[i].defaultValue = (int)lValue; + aGameVars[i].defaultValue = GameVarValue(lValue); } } else @@ -131,14 +174,14 @@ int AddGameVar(const char* pszLabel, intptr_t lValue, unsigned dwFlags) } else { - aGameVars[i].lValue = (int)lValue; + aGameVars[i].lValue = GameVarValue(lValue); } if (!(dwFlags & GAMEVAR_FLAG_NODEFAULT)) { - aGameVars[i].defaultValue = (int)lValue; + aGameVars[i].defaultValue = GameVarValue(lValue); } } - aGameVars[i].initValue = (int)lValue; + aGameVars[i].initValue = GameVarValue(lValue); if (i == iGameVarCount) { // we're adding a new one. @@ -232,7 +275,7 @@ void ResetGameVars(void) { for (auto &pl : ps) { - pl.uservars[aGameVars[i].lValue] = aGameVars[i].defaultValue; + pl.uservars[aGameVars[i].indexValue] = aGameVars[i].defaultValue; } } else if (!(aGameVars[i].dwFlags & GAMEVAR_FLAG_PERACTOR)) @@ -254,22 +297,22 @@ void ResetGameVars(void) // //--------------------------------------------------------------------------- -int GetGameVarID(int id, DDukeActor* sActor, int sPlayer) +GameVarValue GetGameVarID(int id, DDukeActor* sActor, int sPlayer) { if(id<0 || id >= iGameVarCount) { Printf("GetGameVarID: Invalid Game ID %d\n", id); - return -1; + return GameVarValue(-1); } if (id == g_iThisActorID) { - return ActorToScriptIndex(sActor); + return GameVarValue(sActor); } if( aGameVars[id].dwFlags & GAMEVAR_FLAG_PERPLAYER ) { // for the current player if (sPlayer >= 0 && sPlayer < MAXPLAYERS) - return ps[sPlayer].uservars[aGameVars[id].lValue]; + return ps[sPlayer].uservars[aGameVars[id].indexValue]; return aGameVars[id].initValue; } @@ -278,7 +321,7 @@ int GetGameVarID(int id, DDukeActor* sActor, int sPlayer) // for the current actor if(sActor != nullptr) { - return sActor->uservars[aGameVars[id].lValue]; + return sActor->uservars[aGameVars[id].indexValue]; } else { @@ -292,7 +335,7 @@ int GetGameVarID(int id, DDukeActor* sActor, int sPlayer) Printf("GetGameVarID NULL PlValues for PLONG Var=%s\n",aGameVars[id].szLabel); } - return *aGameVars[id].plValue; + return GameVarValue(*aGameVars[id].plValue); } else if (aGameVars[id].dwFlags & GAMEVAR_FLAG_PFUNC) { @@ -301,7 +344,7 @@ int GetGameVarID(int id, DDukeActor* sActor, int sPlayer) Printf("GetGameVarID NULL PlValues for PFUNC Var=%s\n", aGameVars[id].szLabel); } - return aGameVars[id].getter(); + return GameVarValue(aGameVars[id].getter()); } else { @@ -316,7 +359,7 @@ int GetGameVarID(int id, DDukeActor* sActor, int sPlayer) // //--------------------------------------------------------------------------- -void SetGameVarID(int id, int lValue, DDukeActor* sActor, int sPlayer) +void SetGameVarID(int id, GameVarValue lValue, DDukeActor* sActor, int sPlayer) { if(id<0 || id >= iGameVarCount) { @@ -329,24 +372,24 @@ void SetGameVarID(int id, int lValue, DDukeActor* sActor, int sPlayer) if (sPlayer >= 0) { if (sPlayer < MAXPLAYERS) - ps[sPlayer].uservars[aGameVars[id].lValue] = lValue; + ps[sPlayer].uservars[aGameVars[id].indexValue] = lValue; } else { for (int i = connecthead; i >= 0; i = connectpoint2[i]) - ps[i].uservars[aGameVars[id].lValue] = lValue; // set for all players + ps[i].uservars[aGameVars[id].indexValue] = lValue; // set for all players aGameVars[id].initValue = lValue; } } else if( aGameVars[id].dwFlags & GAMEVAR_FLAG_PERACTOR ) { // for the current actor - if (sActor != nullptr) sActor->uservars[aGameVars[id].lValue] = lValue; + if (sActor != nullptr) sActor->uservars[aGameVars[id].indexValue] = lValue; else { DukeSpriteIterator it; while (auto actor = it.Next()) - actor->uservars[aGameVars[id].lValue] = lValue; + actor->uservars[aGameVars[id].indexValue] = lValue; aGameVars[id].initValue = lValue; } @@ -354,7 +397,7 @@ void SetGameVarID(int id, int lValue, DDukeActor* sActor, int sPlayer) else if( aGameVars[id].dwFlags & GAMEVAR_FLAG_PLONG ) { // set the value at pointer - *aGameVars[id].plValue=lValue; + *aGameVars[id].plValue = lValue.safeValue(); } else if( !(aGameVars[id].dwFlags & GAMEVAR_FLAG_PFUNC) ) { @@ -363,13 +406,23 @@ void SetGameVarID(int id, int lValue, DDukeActor* sActor, int sPlayer) } +void SetGameVarID(int id, int lValue, DDukeActor* sActor, int sPlayer) +{ + SetGameVarID(id, GameVarValue(lValue), sActor, sPlayer); +} + +void SetGameVarID(int id, DDukeActor* lValue, DDukeActor* sActor, int sPlayer) +{ + SetGameVarID(id, GameVarValue(lValue), sActor, sPlayer); +} + //--------------------------------------------------------------------------- // // // //--------------------------------------------------------------------------- -int GetGameVar(const char *szGameLabel, int lDefault, DDukeActor* sActor, int sPlayer) +GameVarValue GetGameVar(const char *szGameLabel, GameVarValue lDefault, DDukeActor* sActor, int sPlayer) { for (int i = 0; i < iGameVarCount; i++) { @@ -381,6 +434,11 @@ int GetGameVar(const char *szGameLabel, int lDefault, DDukeActor* sActor, int sP return lDefault; } +GameVarValue GetGameVar(const char* szGameLabel, int lDefault, DDukeActor* sActor, int sPlayer) +{ + return GetGameVar(szGameLabel, GameVarValue(lDefault), sActor, sPlayer); +} + //--------------------------------------------------------------------------- // // only used for the aplWeapon stuff @@ -397,7 +455,7 @@ int GetGameValuePtr(char *szGameLabel) { I_FatalError("%s was overridden to something other than a player gamevar.", szGameLabel); } - return aGameVars[i].lValue; + return aGameVars[i].indexValue; } } I_FatalError("%s was overridden to something other than a player gamevar.", szGameLabel); @@ -468,21 +526,21 @@ static int i_aplWeaponFireSound[MAX_WEAPONS]; // Sound made when firing (each ti static int i_aplWeaponSound2Time[MAX_WEAPONS]; // Alternate sound time static int i_aplWeaponSound2Sound[MAX_WEAPONS]; // Alternate sound sound ID -int aplWeaponClip(int weapon, int player) { return ps[player].uservars[i_aplWeaponClip[weapon]]; } -int aplWeaponReload(int weapon, int player) { return ps[player].uservars[i_aplWeaponReload[weapon]]; } -int aplWeaponFireDelay(int weapon, int player) { return ps[player].uservars[i_aplWeaponFireDelay[weapon]]; } -int aplWeaponHoldDelay(int weapon, int player) { return ps[player].uservars[i_aplWeaponHoldDelay[weapon]]; } -int aplWeaponTotalTime(int weapon, int player) { return ps[player].uservars[i_aplWeaponTotalTime[weapon]]; } -int aplWeaponFlags(int weapon, int player) { return ps[player].uservars[i_aplWeaponFlags[weapon]]; } -int aplWeaponShoots(int weapon, int player) { return ps[player].uservars[i_aplWeaponShoots[weapon]]; } -int aplWeaponSpawnTime(int weapon, int player) { return ps[player].uservars[i_aplWeaponSpawnTime[weapon]]; } -int aplWeaponSpawn(int weapon, int player) { return ps[player].uservars[i_aplWeaponSpawn[weapon]]; } -int aplWeaponShotsPerBurst(int weapon, int player) { return ps[player].uservars[i_aplWeaponShotsPerBurst[weapon]]; } -int aplWeaponWorksLike(int weapon, int player) { return ps[player].uservars[i_aplWeaponWorksLike[weapon]]; } -int aplWeaponInitialSound(int weapon, int player) { return ps[player].uservars[i_aplWeaponInitialSound[weapon]]; } -int aplWeaponFireSound(int weapon, int player) { return ps[player].uservars[i_aplWeaponFireSound[weapon]]; } -int aplWeaponSound2Time(int weapon, int player) { return ps[player].uservars[i_aplWeaponSound2Time[weapon]]; } -int aplWeaponSound2Sound(int weapon, int player) { return ps[player].uservars[i_aplWeaponSound2Sound[weapon]]; } +int aplWeaponClip(int weapon, int player) { return ps[player].uservars[i_aplWeaponClip[weapon]].safeValue(); } +int aplWeaponReload(int weapon, int player) { return ps[player].uservars[i_aplWeaponReload[weapon]].safeValue(); } +int aplWeaponFireDelay(int weapon, int player) { return ps[player].uservars[i_aplWeaponFireDelay[weapon]].safeValue(); } +int aplWeaponHoldDelay(int weapon, int player) { return ps[player].uservars[i_aplWeaponHoldDelay[weapon]].safeValue(); } +int aplWeaponTotalTime(int weapon, int player) { return ps[player].uservars[i_aplWeaponTotalTime[weapon]].safeValue(); } +int aplWeaponFlags(int weapon, int player) { return ps[player].uservars[i_aplWeaponFlags[weapon]].safeValue(); } +int aplWeaponShoots(int weapon, int player) { return ps[player].uservars[i_aplWeaponShoots[weapon]].safeValue(); } +int aplWeaponSpawnTime(int weapon, int player) { return ps[player].uservars[i_aplWeaponSpawnTime[weapon]].safeValue(); } +int aplWeaponSpawn(int weapon, int player) { return ps[player].uservars[i_aplWeaponSpawn[weapon]].safeValue(); } +int aplWeaponShotsPerBurst(int weapon, int player) { return ps[player].uservars[i_aplWeaponShotsPerBurst[weapon]].safeValue(); } +int aplWeaponWorksLike(int weapon, int player) { return ps[player].uservars[i_aplWeaponWorksLike[weapon]].safeValue(); } +int aplWeaponInitialSound(int weapon, int player) { return ps[player].uservars[i_aplWeaponInitialSound[weapon]].safeValue(); } +int aplWeaponFireSound(int weapon, int player) { return ps[player].uservars[i_aplWeaponFireSound[weapon]].safeValue(); } +int aplWeaponSound2Time(int weapon, int player) { return ps[player].uservars[i_aplWeaponSound2Time[weapon]].safeValue(); } +int aplWeaponSound2Sound(int weapon, int player) { return ps[player].uservars[i_aplWeaponSound2Sound[weapon]].safeValue(); } //--------------------------------------------------------------------------- // @@ -1166,11 +1224,11 @@ void FinalizeGameVars(void) { if (aGameVars[i].dwFlags & GAMEVAR_FLAG_PERPLAYER) { - aGameVars[i].lValue = weapNdx++; + aGameVars[i].indexValue = weapNdx++; } if (aGameVars[i].dwFlags & GAMEVAR_FLAG_PERACTOR) { - aGameVars[i].lValue = actorNdx++; + aGameVars[i].indexValue = actorNdx++; } } for (auto& pl : ps) pl.uservars.Resize(weapNdx); @@ -1200,7 +1258,7 @@ void SetupGameVarsForActor(DDukeActor* actor) { if (aGameVars[i].dwFlags & GAMEVAR_FLAG_PERACTOR) { - actor->uservars[aGameVars[i].lValue] = aGameVars[i].initValue; + actor->uservars[aGameVars[i].indexValue] = aGameVars[i].initValue; } } } diff --git a/source/games/duke/src/gamevar.h b/source/games/duke/src/gamevar.h index c378b493a..658a7265f 100644 --- a/source/games/duke/src/gamevar.h +++ b/source/games/duke/src/gamevar.h @@ -6,6 +6,39 @@ BEGIN_DUKE_NS // gamedef.c +class DDukeActor; + +// Game vars can reference actors, we need a type-safe way to handle that so that index values won't get misappropriated and actors can be GC'd. +class GameVarValue +{ + enum EType + { + Actor = 0, + Value = 1 + }; + union + { + DDukeActor* ActorP; + uint64_t index; + }; + +public: + GameVarValue() = default; + explicit GameVarValue(DDukeActor* actor_) { ActorP = actor_; assert(isActor()); /* GC:WriteBarrier(actor);*/ } + explicit GameVarValue(int val) { index = (val << 8) | Value; } + + bool isActor() const { return (index & 7) == Actor; } + bool isValue() const { return (index & 7) == Value; } + + DDukeActor* actor() const { assert(isActor()); return /*GC::ReadBarrier*/(ActorP); } + int value() const { assert(isValue()); return index >> 8; } + int safeValue() const { return isValue() ? value() : actor() == nullptr ? 0 : -1; } // return -1 for valid actors and 0 for null. This allows most comparisons to work. + DDukeActor* safeActor() const { return isActor() ? actor() : nullptr; } + + bool operator==(const GameVarValue& other) const { return index == other.index; } + bool operator!=(const GameVarValue& other) const { return index != other.index; } +}; + enum { // store global game definitions @@ -95,12 +128,13 @@ typedef struct { union { - int lValue; + GameVarValue lValue; + int indexValue; int* plValue; int (*getter)(); }; - int defaultValue; - int initValue; // this is what gets copied to players/actors upon spawn. This is not the same as the default! + GameVarValue defaultValue; + GameVarValue initValue; // this is what gets copied to players/actors upon spawn. This is not the same as the default! unsigned int dwFlags; char szLabel[MAXVARLABEL]; } MATTGAMEVAR; @@ -126,10 +160,15 @@ int GetDefID(const char *szGameLabel); void ClearGameVars(void); void AddSystemVars(); void ResetGameVars(void); -struct DDukeActor; -int GetGameVarID(int id, DDukeActor* sActor, int sPlayer); +class DDukeActor; +class GameVarValue; +GameVarValue GetGameVarID(int id, DDukeActor* sActor, int sPlayer); +void SetGameVarID(int id, GameVarValue lValue, DDukeActor* sActor, int sPlayer); +GameVarValue GetGameVar(const char* szGameLabel, GameVarValue lDefault, DDukeActor* sActor, int sPlayer); +GameVarValue GetGameVar(const char* szGameLabel, int lDefault, DDukeActor* sActor, int sPlayer); void SetGameVarID(int id, int lValue, DDukeActor* sActor, int sPlayer); -int GetGameVar(const char* szGameLabel, int lDefault, DDukeActor* sActor, int sPlayer); +void SetGameVarID(int id, DDukeActor* lValue, DDukeActor* sActor, int sPlayer); + void ClearGameEvents(); bool IsGameEvent(int i); diff --git a/source/games/duke/src/input.cpp b/source/games/duke/src/input.cpp index ac2fb243f..890dd01ef 100644 --- a/source/games/duke/src/input.cpp +++ b/source/games/duke/src/input.cpp @@ -98,7 +98,7 @@ void hud_input(int plnum) { SetGameVarID(g_iReturnVarID, 0, nullptr, plnum); OnEvent(EVENT_QUICKKICK, plnum, nullptr, -1); - if (GetGameVarID(g_iReturnVarID, nullptr, plnum) == 0) + if (GetGameVarID(g_iReturnVarID, nullptr, plnum).value() == 0) { p->quick_kick = 14; if (!p->quick_kick_msg && plnum == screenpeek) FTA(QUOTE_MIGHTY_FOOT, p); @@ -123,7 +123,7 @@ void hud_input(int plnum) { SetGameVarID(g_iReturnVarID, 0, nullptr, plnum); OnEvent(EVENT_INVENTORY, plnum, nullptr, -1); - if (GetGameVarID(g_iReturnVarID, nullptr, plnum) == 0) + if (GetGameVarID(g_iReturnVarID, nullptr, plnum).value() == 0) { if (p->inven_icon > ICON_NONE && p->inven_icon <= ICON_HEATS) PlayerSetItemUsed(plnum, p->inven_icon); } @@ -133,7 +133,7 @@ void hud_input(int plnum) { SetGameVarID(g_iReturnVarID, 0, nullptr, plnum); OnEvent(EVENT_USENIGHTVISION, plnum, nullptr, -1); - if (GetGameVarID(g_iReturnVarID, nullptr, plnum) == 0 && p->heat_amount > 0) + if (GetGameVarID(g_iReturnVarID, nullptr, plnum).value() == 0 && p->heat_amount > 0) { p->heat_on = !p->heat_on; p->inven_icon = 5; @@ -146,7 +146,7 @@ void hud_input(int plnum) { SetGameVarID(g_iReturnVarID, 0, nullptr, plnum); OnEvent(EVENT_USESTEROIDS, plnum, nullptr, -1); - if (GetGameVarID(g_iReturnVarID, nullptr, plnum) == 0) + if (GetGameVarID(g_iReturnVarID, nullptr, plnum).value() == 0) { if (p->steroids_amount == 400) { @@ -229,13 +229,13 @@ void hud_input(int plnum) { SetGameVarID(g_iReturnVarID, dainv, nullptr, plnum); OnEvent(EVENT_INVENTORYLEFT, plnum, nullptr, -1); - dainv = GetGameVarID(g_iReturnVarID, nullptr, plnum); + dainv = GetGameVarID(g_iReturnVarID, nullptr, plnum).safeValue(); } if (PlayerInput(plnum, SB_INVNEXT)) { SetGameVarID(g_iReturnVarID, dainv, nullptr, plnum); OnEvent(EVENT_INVENTORYRIGHT, plnum, nullptr, -1); - dainv = GetGameVarID(g_iReturnVarID, nullptr, plnum); + dainv = GetGameVarID(g_iReturnVarID, nullptr, plnum).safeValue(); } p->inven_icon = dainv; // Someone must have really hated constant data, doing this with a switch/case (and of course also with literal numbers...) @@ -273,7 +273,7 @@ void hud_input(int plnum) { SetGameVarID(g_iReturnVarID, 0, nullptr, plnum); OnEvent(EVENT_HOLODUKEON, plnum, nullptr, -1); - if (GetGameVarID(g_iReturnVarID, nullptr, plnum) == 0) + if (GetGameVarID(g_iReturnVarID, nullptr, plnum).value() == 0) { if (!isRR()) { @@ -330,7 +330,7 @@ void hud_input(int plnum) { SetGameVarID(g_iReturnVarID, 0, nullptr, plnum); OnEvent(EVENT_USENIGHTVISION, plnum, nullptr, -1); - if (GetGameVarID(g_iReturnVarID, nullptr, plnum) == 0) + if (GetGameVarID(g_iReturnVarID, nullptr, plnum).value() == 0) { if (p->yehaa_timer == 0) { @@ -362,7 +362,7 @@ void hud_input(int plnum) { SetGameVarID(g_iReturnVarID, 0, nullptr, plnum); OnEvent(EVENT_USEMEDKIT, plnum, nullptr, -1); - if (GetGameVarID(g_iReturnVarID, nullptr, plnum) == 0) + if (GetGameVarID(g_iReturnVarID, nullptr, plnum).value() == 0) { if (p->firstaid_amount > 0 && p->GetActor()->s->extra < gs.max_player_health) { @@ -415,7 +415,7 @@ void hud_input(int plnum) { SetGameVarID(g_iReturnVarID, 0, nullptr, plnum); OnEvent(EVENT_USEJETPACK, plnum, nullptr, -1); - if (GetGameVarID(g_iReturnVarID, nullptr, plnum) == 0) + if (GetGameVarID(g_iReturnVarID, nullptr, plnum).value() == 0) { if (!isRR()) { @@ -483,7 +483,7 @@ void hud_input(int plnum) { SetGameVarID(g_iReturnVarID, 0, nullptr, plnum); OnEvent(EVENT_TURNAROUND, plnum, nullptr, -1); - if (GetGameVarID(g_iReturnVarID, nullptr, plnum) != 0) + if (GetGameVarID(g_iReturnVarID, nullptr, plnum).value() != 0) { p->sync.actions &= ~SB_TURNAROUND; } diff --git a/source/games/duke/src/player.cpp b/source/games/duke/src/player.cpp index 8dcdc03a4..253cc2f28 100644 --- a/source/games/duke/src/player.cpp +++ b/source/games/duke/src/player.cpp @@ -691,7 +691,7 @@ void playerCrouch(int snum) // crouching SetGameVarID(g_iReturnVarID, 0, p->GetActor(), snum); OnEvent(EVENT_CROUCH, snum, p->GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum) == 0) + if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum).value() == 0) { p->pos.z += (2048 + 768); p->crack_time = CRACK_TIME; @@ -707,7 +707,7 @@ void playerJump(int snum, int fz, int cz) { SetGameVarID(g_iReturnVarID, 0, p->GetActor(), snum); OnEvent(EVENT_JUMP, snum, p->GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum) == 0) + if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum).value() == 0) { p->jumping_counter = 1; p->jumping_toggle = 1; @@ -835,7 +835,7 @@ void checklook(int snum, ESyncBits actions) { SetGameVarID(g_iReturnVarID, 0, p->GetActor(), snum); OnEvent(EVENT_LOOKLEFT, snum, p->GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum) != 0) + if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum).value() != 0) { actions &= ~SB_LOOK_LEFT; } @@ -845,7 +845,7 @@ void checklook(int snum, ESyncBits actions) { SetGameVarID(g_iReturnVarID, 0, p->GetActor(), snum); OnEvent(EVENT_LOOKRIGHT, snum, p->GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum) != 0) + if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum).value() != 0) { actions &= ~SB_LOOK_RIGHT; } @@ -864,7 +864,7 @@ void playerCenterView(int snum) auto p = &ps[snum]; SetGameVarID(g_iReturnVarID, 0, p->GetActor(), snum); OnEvent(EVENT_RETURNTOCENTER, snum, p->GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum) == 0) + if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum).value() == 0) { p->sync.actions |= SB_CENTERVIEW; } @@ -879,7 +879,7 @@ void playerLookUp(int snum, ESyncBits actions) auto p = &ps[snum]; SetGameVarID(g_iReturnVarID, 0, p->GetActor(), snum); OnEvent(EVENT_LOOKUP, snum, p->GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum) == 0) + if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum).value() == 0) { p->sync.actions |= SB_CENTERVIEW; } @@ -894,7 +894,7 @@ void playerLookDown(int snum, ESyncBits actions) auto p = &ps[snum]; SetGameVarID(g_iReturnVarID, 0, p->GetActor(), snum); OnEvent(EVENT_LOOKDOWN, snum, p->GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum) == 0) + if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum).value() == 0) { p->sync.actions |= SB_CENTERVIEW; } @@ -909,7 +909,7 @@ void playerAimUp(int snum, ESyncBits actions) auto p = &ps[snum]; SetGameVarID(g_iReturnVarID, 0, p->GetActor(), snum); OnEvent(EVENT_AIMUP, snum, p->GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum) != 0) + if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum).value() != 0) { p->sync.actions &= ~SB_AIM_UP; } @@ -920,7 +920,7 @@ void playerAimDown(int snum, ESyncBits actions) auto p = &ps[snum]; SetGameVarID(g_iReturnVarID, 0, p->GetActor(), snum); OnEvent(EVENT_AIMDOWN, snum, p->GetActor(), -1); // due to a typo in WW2GI's CON files this is the same as EVENT_AIMUP. - if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum) != 0) + if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum).value() != 0) { p->sync.actions &= ~SB_AIM_DOWN; } @@ -1228,7 +1228,7 @@ DEFINE_ACTION_FUNCTION(_DukePlayer, GetGameVar) PARAM_SELF_STRUCT_PROLOGUE(player_struct); PARAM_STRING(name); PARAM_INT(def); - ACTION_RETURN_INT(GetGameVar(name, def, self->GetActor(), self->GetPlayerNum())); + ACTION_RETURN_INT(GetGameVar(name, def, self->GetActor(), self->GetPlayerNum()).safeValue()); } DEFINE_ACTION_FUNCTION(_Duke, GetViewPlayer) diff --git a/source/games/duke/src/player_d.cpp b/source/games/duke/src/player_d.cpp index 9510fe13a..385cf6c71 100644 --- a/source/games/duke/src/player_d.cpp +++ b/source/games/duke/src/player_d.cpp @@ -331,7 +331,7 @@ static void shootweapon(DDukeActor *actor, int p, int sx, int sy, int sz, int sa { SetGameVarID(g_iAimAngleVarID, AUTO_AIM_ANGLE, actor, p); OnEvent(EVENT_GETAUTOAIMANGLE, p, ps[p].GetActor(), -1); - int varval = GetGameVarID(g_iAimAngleVarID, actor, p); + int varval = GetGameVarID(g_iAimAngleVarID, actor, p).value(); DDukeActor* aimed = nullptr; if (varval > 0) { @@ -366,8 +366,8 @@ static void shootweapon(DDukeActor *actor, int p, int sx, int sy, int sz, int sa SetGameVarID(g_iAngRangeVarID, 32, actor, p); SetGameVarID(g_iZRangeVarID, 256, actor, p); OnEvent(EVENT_GETSHOTRANGE, p, ps[p].GetActor(), -1); - angRange = GetGameVarID(g_iAngRangeVarID, actor, p); - zRange = GetGameVarID(g_iZRangeVarID, actor, p); + angRange = GetGameVarID(g_iAngRangeVarID, actor, p).value(); + zRange = GetGameVarID(g_iZRangeVarID, actor, p).value(); sa += (angRange / 2) - (krand() & (angRange - 1)); if (aimed == nullptr) @@ -884,11 +884,11 @@ static void shootlaser(DDukeActor* actor, int p, int sx, int sy, int sz, int sa) if (!bomb) return; if (isWW2GI()) { - int lTripBombControl = GetGameVar("TRIPBOMB_CONTROL", TRIPBOMB_TRIPWIRE, nullptr, -1); + int lTripBombControl = GetGameVar("TRIPBOMB_CONTROL", TRIPBOMB_TRIPWIRE, nullptr, -1).value(); if (lTripBombControl & TRIPBOMB_TIMER) { - int lLifetime = GetGameVar("STICKYBOMB_LIFETIME", NAM_GRENADE_LIFETIME, nullptr, p); - int lLifetimeVar = GetGameVar("STICKYBOMB_LIFETIME_VAR", NAM_GRENADE_LIFETIME_VAR, nullptr, p); + int lLifetime = GetGameVar("STICKYBOMB_LIFETIME", NAM_GRENADE_LIFETIME, nullptr, p).value(); + int lLifetimeVar = GetGameVar("STICKYBOMB_LIFETIME_VAR", NAM_GRENADE_LIFETIME_VAR, nullptr, p).value(); // set timer. blows up when at zero.... bomb->s->extra = lLifetime + MulScale(krand(), lLifetimeVar, 14) @@ -1024,7 +1024,7 @@ void shoot_d(DDukeActor* actor, int atwith) SetGameVarID(g_iAtWithVarID, atwith, actor, p); SetGameVarID(g_iReturnVarID, 0, actor, p); OnEvent(EVENT_SHOOT, p, ps[p].GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, actor, p) != 0) + if (GetGameVarID(g_iReturnVarID, actor, p).safeValue() != 0) { return; } @@ -1716,7 +1716,7 @@ static void operateJetpack(int snum, ESyncBits actions, int psectlotag, int fz, // jump SetGameVarID(g_iReturnVarID, 0, p->GetActor(), snum); OnEvent(EVENT_SOARUP, snum, p->GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum) == 0) + if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum).value() == 0) { p->pos.z -= j; p->crack_time = CRACK_TIME; @@ -1728,7 +1728,7 @@ static void operateJetpack(int snum, ESyncBits actions, int psectlotag, int fz, // crouch SetGameVarID(g_iReturnVarID, 0, p->GetActor(), snum); OnEvent(EVENT_SOARDOWN, snum, p->GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum) == 0) + if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum).value() == 0) { p->pos.z += j; p->crack_time = CRACK_TIME; @@ -2657,7 +2657,7 @@ static void processweapon(int snum, ESyncBits actions) SetGameVarID(g_iWeaponVarID, p->curr_weapon, p->GetActor(), snum); SetGameVarID(g_iWorksLikeVarID, aplWeaponWorksLike(p->curr_weapon, snum), p->GetActor(), snum); OnEvent(EVENT_HOLSTER, snum, p->GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum) == 0) + if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum).value() == 0) { // now it uses the game definitions... if (aplWeaponFlags(p->curr_weapon, snum) & WEAPON_FLAG_HOLSTER_CLEARS_CLIP) @@ -3072,7 +3072,7 @@ HORIZONLY: psectp = s->sector(); if (ud.clipping == 0 && psectp->lotag == 31) { - auto secact = ScriptIndexToActor(psectp->hitag); + auto secact = static_cast(psectp->hitagactor); if (secact && secact->s->xvel && secact->temp_data[0] == 0) { quickkill(p); diff --git a/source/games/duke/src/player_r.cpp b/source/games/duke/src/player_r.cpp index 94b1de067..5688d9306 100644 --- a/source/games/duke/src/player_r.cpp +++ b/source/games/duke/src/player_r.cpp @@ -869,7 +869,7 @@ void shoot_r(DDukeActor* actor, int atwith) SetGameVarID(g_iAtWithVarID, atwith, actor, p); SetGameVarID(g_iReturnVarID, 0, actor, p); OnEvent(EVENT_SHOOT, p, ps[p].GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, actor, p) != 0) + if (GetGameVarID(g_iReturnVarID, actor, p).safeValue() != 0) { return; } @@ -3909,7 +3909,7 @@ HORIZONLY: psectp = s->sector(); if (ud.clipping == 0 && psectp->lotag == ST_31_TWO_WAY_TRAIN) { - auto act = ScriptIndexToActor(psectp->hitag); + auto act = static_cast(psectp->hitagactor); if (act && act->s->xvel && act->temp_data[0] == 0) { quickkill(p); diff --git a/source/games/duke/src/player_w.cpp b/source/games/duke/src/player_w.cpp index 975fc61ca..eb1488a3e 100644 --- a/source/games/duke/src/player_w.cpp +++ b/source/games/duke/src/player_w.cpp @@ -162,7 +162,7 @@ void fireweapon_ww(int snum) SetGameVarID(g_iWeaponVarID, p->curr_weapon, p->GetActor(), snum); SetGameVarID(g_iWorksLikeVarID, aplWeaponWorksLike(p->curr_weapon, snum), p->GetActor(), snum); OnEvent(EVENT_FIRE, snum, p->GetActor(), -1); - if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum) == 0) + if (GetGameVarID(g_iReturnVarID, p->GetActor(), snum).value() == 0) { switch (aplWeaponWorksLike(p->curr_weapon, snum)) { @@ -350,8 +350,8 @@ void operateweapon_ww(int snum, ESyncBits actions) if (j) { { - int lGrenadeLifetime = GetGameVar("GRENADE_LIFETIME", NAM_GRENADE_LIFETIME, nullptr, snum); - int lGrenadeLifetimeVar = GetGameVar("GRENADE_LIFETIME_VAR", NAM_GRENADE_LIFETIME_VAR, nullptr, snum); + int lGrenadeLifetime = GetGameVar("GRENADE_LIFETIME", NAM_GRENADE_LIFETIME, nullptr, snum).value(); + int lGrenadeLifetimeVar = GetGameVar("GRENADE_LIFETIME_VAR", NAM_GRENADE_LIFETIME_VAR, nullptr, snum).value(); // set timer. blows up when at zero.... j->s->extra = lGrenadeLifetime + MulScale(krand(), lGrenadeLifetimeVar, 14) diff --git a/source/games/duke/src/savegame.cpp b/source/games/duke/src/savegame.cpp index 448036340..ab426d052 100644 --- a/source/games/duke/src/savegame.cpp +++ b/source/games/duke/src/savegame.cpp @@ -32,6 +32,7 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms #include "gamestate.h" #include "dukeactor.h" #include "savegamehelp.h" +#include "gamevar.h" //========================================================================== // @@ -39,17 +40,19 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms // //========================================================================== -template<> FSerializer& Serialize(FSerializer& arc, const char* key, Duke3d::DDukeActor*& ht, Duke3d::DDukeActor** def) -{ - int index = ht? ht->GetSpriteIndex() : -1; - assert(index >= -1 && index < MAXSPRITES); - Serialize(arc, key, index, nullptr); - ht = index < 0? nullptr : &Duke3d::hittype[index]; - return arc; -} BEGIN_DUKE_NS +/*template<>*/ FSerializer& Serialize(FSerializer& arc, const char* key, Duke3d::DDukeActor*& ht, Duke3d::DDukeActor** def) +{ + int index = ht ? ht->GetSpriteIndex() : -1; + assert(index >= -1 && index < MAXSPRITES); + Serialize(arc, key, index, nullptr); + ht = index < 0 ? nullptr : &Duke3d::hittype[index]; + return arc; +} + +FSerializer& Serialize(FSerializer& arc, const char* keyname, GameVarValue& w, GameVarValue* def); void SerializeActorGlobals(FSerializer& arc); void lava_serialize(FSerializer& arc); void SerializeGameVars(FSerializer &arc); diff --git a/source/games/duke/src/types.h b/source/games/duke/src/types.h index cbe583304..8b0742a01 100644 --- a/source/games/duke/src/types.h +++ b/source/games/duke/src/types.h @@ -21,10 +21,10 @@ struct STATUSBARTYPE bool gotweapon[MAX_WEAPONS]; }; -struct DDukeActor : public DCoreActor +class DDukeActor : public DCoreActor { using Super = DCoreActor; - +public: uint8_t cgg; uint8_t spriteextra; // moved here for easier maintenance. This was originally a hacked in field in the sprite structure called 'filler'. DDukeActor* ownerActor, * hitOwnerActor; @@ -45,7 +45,7 @@ struct DDukeActor : public DCoreActor DDukeActor* temp_actor, *seek_actor; spritetype* s; // direct reference to the corresponding sprite. - TArray uservars; + TArray uservars; static DDukeActor* array(); // this is necessary to allow define inline functions referencing the global array inside the definition itself. @@ -304,7 +304,7 @@ struct player_struct double vehForwardScale, vehReverseScale, MotoSpeed; bool vehTurnLeft, vehTurnRight, vehBraking; - TArray uservars; + TArray uservars; // input stuff.