From 82c04173b634553f1a1ef967755baad6e402d338 Mon Sep 17 00:00:00 2001 From: Pavel Solodovnikov Date: Fri, 2 Feb 2024 18:48:19 +0300 Subject: [PATCH] Add `getWeaponStats()` member function for `STRUCTURE` Moved `getWeaponStats()` from `DROID` to `BASE_OBJECT`, so that `STRUCTURE` class can also use it. Actually, `BASE_OBJECT` may not be the best place to store `asWeaps` and other weaponry-related data, since `FEATURE` class doesn't use them at all (one of the direct descendants of `BASE_OBJECT`). But, for the time being, let it remain in `BASE_OBJECT`, so that the diff is kept relatively small and easy-to-review. Signed-off-by: Pavel Solodovnikov --- src/ai.cpp | 8 ++++---- src/basedef.h | 4 ++++ src/baseobject.cpp | 6 ++++++ src/display.cpp | 4 ++-- src/droid.cpp | 5 ----- src/droiddef.h | 1 - src/game.cpp | 2 +- src/keybind.cpp | 2 +- src/loop.cpp | 4 ++-- src/map.cpp | 2 +- src/multistruct.cpp | 2 +- src/quickjs_backend.cpp | 4 ++-- src/structure.cpp | 14 +++++++------- src/visibility.cpp | 4 ++-- 14 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/ai.cpp b/src/ai.cpp index 207f1a4469a..745ed3d1a07 100644 --- a/src/ai.cpp +++ b/src/ai.cpp @@ -110,7 +110,7 @@ static bool aiStructHasRange(STRUCTURE *psStruct, BASE_OBJECT *psTarget, int wea return false; } - WEAPON_STATS *psWStats = &asWeaponStats[psStruct->asWeaps[weapon_slot].nStat]; + WEAPON_STATS *psWStats = psStruct->getWeaponStats(weapon_slot); int longRange = proj_GetLongRange(*psWStats, psStruct->player); return objPosDiffSq(psStruct, psTarget) < longRange * longRange && lineOfFire(psStruct, psTarget, weapon_slot, true); @@ -335,7 +335,7 @@ static SDWORD targetAttackWeight(BASE_OBJECT *psTarget, BASE_OBJECT *psAttacker, } else if (psAttacker->type == OBJ_STRUCTURE) { - attackerWeapon = (WEAPON_STATS *)(&asWeaponStats[((STRUCTURE *)psAttacker)->asWeaps[weapon_slot].nStat]); + attackerWeapon = ((STRUCTURE*)psAttacker)->getWeaponStats(weapon_slot); } else /* feature */ { @@ -887,7 +887,7 @@ bool aiChooseTarget(BASE_OBJECT *psObj, BASE_OBJECT **ppsTarget, int weapon_slot ASSERT_OR_RETURN(false, psObj->asWeaps[weapon_slot].nStat > 0, "Invalid weapon turret"); - WEAPON_STATS *psWStats = &asWeaponStats[psObj->asWeaps[weapon_slot].nStat]; + WEAPON_STATS *psWStats = ((const STRUCTURE*)psObj)->getWeaponStats(weapon_slot); int longRange = proj_GetLongRange(*psWStats, psObj->player); // see if there is a target from the command droids @@ -1317,7 +1317,7 @@ bool validTarget(BASE_OBJECT const *psObject, BASE_OBJECT const *psTarget, int w // Can't attack without a weapon if (((const STRUCTURE *)psObject)->numWeaps != 0 && ((const STRUCTURE *)psObject)->asWeaps[weapon_slot].nStat != 0) { - surfaceToAir = asWeaponStats[((const STRUCTURE *)psObject)->asWeaps[weapon_slot].nStat].surfaceToAir; + surfaceToAir = ((const STRUCTURE*)psObject)->getWeaponStats(weapon_slot)->surfaceToAir; } else { diff --git a/src/basedef.h b/src/basedef.h index 3b68e477dbd..8abca0384d0 100644 --- a/src/basedef.h +++ b/src/basedef.h @@ -84,11 +84,15 @@ enum OBJECT_FLAG OBJECT_FLAG_COUNT }; +struct WEAPON_STATS; + struct BASE_OBJECT : public SIMPLE_OBJECT { BASE_OBJECT(OBJECT_TYPE type, uint32_t id, unsigned player); ~BASE_OBJECT(); + WEAPON_STATS* getWeaponStats(int weaponSlot) const; + SCREEN_DISP_DATA sDisplay; ///< screen coordinate details UBYTE group = 0; ///< Which group selection is the droid currently in? UBYTE selected; ///< Whether the object is selected (might want this elsewhere) diff --git a/src/baseobject.cpp b/src/baseobject.cpp index 89c5ef1b120..bd400b2e184 100644 --- a/src/baseobject.cpp +++ b/src/baseobject.cpp @@ -117,6 +117,12 @@ BASE_OBJECT::~BASE_OBJECT() visRemoveVisibility(this); } + +WEAPON_STATS* BASE_OBJECT::getWeaponStats(int weaponSlot) const +{ + return &asWeaponStats[asWeaps[weaponSlot].nStat]; +} + // Query visibility for display purposes (i.e. for `selectedPlayer`) // *DO NOT USE TO QUERY VISIBILITY FOR CALCULATIONS INVOLVING GAME / SIMULATION STATE* UBYTE BASE_OBJECT::visibleForLocalDisplay() const diff --git a/src/display.cpp b/src/display.cpp index bcda9a3486b..94392b09f20 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -944,7 +944,7 @@ void processMouseClickInput() else if (arnMPointers[item][selection] == CURSOR_NOTPOSSIBLE && ObjUnderMouse && (ObjUnderMouse->player == selectedPlayer) && ObjUnderMouse->type == OBJ_STRUCTURE && ((STRUCTURE *)ObjUnderMouse)->asWeaps[0].nStat && - (asWeaponStats[((STRUCTURE *)ObjUnderMouse)->asWeaps[0].nStat].weaponSubClass == WSC_LAS_SAT)) + (((STRUCTURE*)ObjUnderMouse)->getWeaponStats(0)->weaponSubClass == WSC_LAS_SAT)) { wzSetCursor(CURSOR_SELECT); // Special casing for LasSat } @@ -990,7 +990,7 @@ void processMouseClickInput() } else if (ObjUnderMouse && (ObjUnderMouse->player == selectedPlayer) && ((ObjUnderMouse->type == OBJ_STRUCTURE && ((STRUCTURE *)ObjUnderMouse)->asWeaps[0].nStat - && (asWeaponStats[((STRUCTURE *)ObjUnderMouse)->asWeaps[0].nStat].weaponSubClass == WSC_LAS_SAT)) + && (((STRUCTURE*)ObjUnderMouse)->getWeaponStats(0)->weaponSubClass == WSC_LAS_SAT)) || ObjUnderMouse->type == OBJ_DROID)) { wzSetCursor(CURSOR_SELECT); // Special casing for LasSat or own unit diff --git a/src/droid.cpp b/src/droid.cpp index 3d7bfb6f883..970cf33b9ce 100644 --- a/src/droid.cpp +++ b/src/droid.cpp @@ -3590,8 +3590,3 @@ CONSTRUCT_STATS* DROID::getConstructStats() const { return &asConstructStats[asBits[COMP_CONSTRUCT]]; } - -WEAPON_STATS* DROID::getWeaponStats(int weaponSlot) const -{ - return &asWeaponStats[asWeaps[weaponSlot].nStat]; -} diff --git a/src/droiddef.h b/src/droiddef.h index 5c392cc7d30..439ba258e88 100644 --- a/src/droiddef.h +++ b/src/droiddef.h @@ -129,7 +129,6 @@ struct DROID : public BASE_OBJECT ECM_STATS* getECMStats() const; REPAIR_STATS* getRepairStats() const; CONSTRUCT_STATS* getConstructStats() const; - WEAPON_STATS* getWeaponStats(int weaponSlot) const; /// UTF-8 name of the droid. This is generated from the droid template /// WARNING: This *can* be changed by the game player after creation & can be translated, do NOT rely on this being the same for everyone! diff --git a/src/game.cpp b/src/game.cpp index 8d093e51dda..f6e97f97c34 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -6557,7 +6557,7 @@ bool writeStructFile(const char *pFileName) ini.setValue("weapons", psCurr->numWeaps); for (unsigned j = 0; j < psCurr->numWeaps; j++) { - ini.setValue("parts/weapon/" + WzString::number(j + 1), asWeaponStats[psCurr->asWeaps[j].nStat].id); + ini.setValue("parts/weapon/" + WzString::number(j + 1), psCurr->getWeaponStats(j)->id); if (psCurr->asWeaps[j].nStat > 0) { ini.setValue("ammo/" + WzString::number(j), psCurr->asWeaps[j].ammo); diff --git a/src/keybind.cpp b/src/keybind.cpp index fc5e4ad2735..afc4e6a29b3 100644 --- a/src/keybind.cpp +++ b/src/keybind.cpp @@ -1528,7 +1528,7 @@ void kf_Reload() { if (isLasSat(psCurr->pStructureType) && psCurr->selected) { - unsigned int firePause = weaponFirePause(asWeaponStats[psCurr->asWeaps[0].nStat], psCurr->player); + unsigned int firePause = weaponFirePause(*psCurr->getWeaponStats(0), psCurr->player); psCurr->asWeaps[0].lastFired -= firePause; CONPRINTF("%s", _("Selected buildings instantly recharged!")); diff --git a/src/loop.cpp b/src/loop.cpp index c53f651aaaa..8b50b544dc7 100644 --- a/src/loop.cpp +++ b/src/loop.cpp @@ -465,7 +465,7 @@ void countUpdate(bool synch) setSatUplinkExists(true, i); } //don't wait for the Las Sat to be built - can't build another if one is partially built - if (asWeaponStats[psCBuilding->asWeaps[0].nStat].weaponSubClass == WSC_LAS_SAT) + if (psCBuilding->getWeaponStats(0)->weaponSubClass == WSC_LAS_SAT) { setLasSatExists(true, i); } @@ -477,7 +477,7 @@ void countUpdate(bool synch) setSatUplinkExists(true, i); } //don't wait for the Las Sat to be built - can't build another if one is partially built - if (asWeaponStats[psCBuilding->asWeaps[0].nStat].weaponSubClass == WSC_LAS_SAT) + if (psCBuilding->getWeaponStats(0)->weaponSubClass == WSC_LAS_SAT) { setLasSatExists(true, i); } diff --git a/src/map.cpp b/src/map.cpp index 5cd9bfdbbb1..f573ea3ba93 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -2111,7 +2111,7 @@ static void threatUpdate(int player) for (weapon = 0; weapon < psStruct->numWeaps; weapon++) { - mode |= asWeaponStats[psStruct->asWeaps[weapon].nStat].surfaceToAir; + mode |= psStruct->getWeaponStats(weapon)->surfaceToAir; } if (psStruct->pStructureType->pSensor && psStruct->pStructureType->pSensor->location == LOC_TURRET) // special treatment for sensor turrets { diff --git a/src/multistruct.cpp b/src/multistruct.cpp index 759c0ad8f0b..8234dc8f1f4 100644 --- a/src/multistruct.cpp +++ b/src/multistruct.cpp @@ -228,7 +228,7 @@ bool recvLasSat(NETQUEUE queue) if (psStruct && psObj && psStruct->pStructureType->psWeapStat[0]->weaponSubClass == WSC_LAS_SAT) { // Lassats have just one weapon - unsigned firePause = weaponFirePause(asWeaponStats[psStruct->asWeaps[0].nStat], player); + unsigned firePause = weaponFirePause(*psStruct->getWeaponStats(0), player); unsigned damLevel = PERCENT(psStruct->body, psStruct->structureBody()); if (damLevel < HEAVY_DAMAGE_LEVEL) diff --git a/src/quickjs_backend.cpp b/src/quickjs_backend.cpp index 653cf248272..2c22772f1ef 100644 --- a/src/quickjs_backend.cpp +++ b/src/quickjs_backend.cpp @@ -815,7 +815,7 @@ JSValue convStructure(const STRUCTURE *psStruct, JSContext *ctx) { if (psStruct->asWeaps[i].nStat) { - WEAPON_STATS *psWeap = &asWeaponStats[psStruct->asWeaps[i].nStat]; + WEAPON_STATS *psWeap = psStruct->getWeaponStats(i); aa = aa || psWeap->surfaceToAir & SHOOT_IN_AIR; ga = ga || psWeap->surfaceToAir & SHOOT_ON_GROUND; indirect = indirect || psWeap->movementModel == MM_INDIRECT || psWeap->movementModel == MM_HOMINGINDIRECT; @@ -865,7 +865,7 @@ JSValue convStructure(const STRUCTURE *psStruct, JSContext *ctx) for (int j = 0; j < psStruct->numWeaps; j++) { JSValue weapon = JS_NewObject(ctx); - const WEAPON_STATS *psStats = &asWeaponStats[psStruct->asWeaps[j].nStat]; + const WEAPON_STATS *psStats = psStruct->getWeaponStats(j); QuickJS_DefinePropertyValue(ctx, weapon, "fullname", JS_NewString(ctx, psStats->name.toUtf8().c_str()), JS_PROP_ENUMERABLE); QuickJS_DefinePropertyValue(ctx, weapon, "name", JS_NewString(ctx, psStats->id.toUtf8().c_str()), JS_PROP_ENUMERABLE); // will be changed to contain full name QuickJS_DefinePropertyValue(ctx, weapon, "id", JS_NewString(ctx, psStats->id.toUtf8().c_str()), JS_PROP_ENUMERABLE); diff --git a/src/structure.cpp b/src/structure.cpp index 063206af502..e72864a14f7 100644 --- a/src/structure.cpp +++ b/src/structure.cpp @@ -1553,7 +1553,7 @@ STRUCTURE *buildStructureDir(STRUCTURE_STATS *pStructureType, UDWORD x, UDWORD y psBuilding->asWeaps[0].lastFired = gameTime; } psBuilding->asWeaps[weapon].nStat = pStructureType->psWeapStat[weapon] - asWeaponStats.data(); - psBuilding->asWeaps[weapon].ammo = asWeaponStats[psBuilding->asWeaps[weapon].nStat].upgrade[psBuilding->player].numRounds; + psBuilding->asWeaps[weapon].ammo = psBuilding->getWeaponStats(weapon)->upgrade[psBuilding->player].numRounds; psBuilding->numWeaps++; } } @@ -1570,7 +1570,7 @@ STRUCTURE *buildStructureDir(STRUCTURE_STATS *pStructureType, UDWORD x, UDWORD y psBuilding->asWeaps[0].lastFired = gameTime; } psBuilding->asWeaps[0].nStat = pStructureType->psWeapStat[0] - asWeaponStats.data(); - psBuilding->asWeaps[0].ammo = asWeaponStats[psBuilding->asWeaps[0].nStat].upgrade[psBuilding->player].numRounds; + psBuilding->asWeaps[0].ammo = psBuilding->getWeaponStats(0)->upgrade[psBuilding->player].numRounds; } } @@ -2972,7 +2972,7 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool isMission) /* Check lassat */ if (isLasSat(psStructure->pStructureType) - && gameTime - psStructure->asWeaps[0].lastFired > weaponFirePause(asWeaponStats[psStructure->asWeaps[0].nStat], psStructure->player) + && gameTime - psStructure->asWeaps[0].lastFired > weaponFirePause(*psStructure->getWeaponStats(0), psStructure->player) && psStructure->asWeaps[0].ammo > 0) { triggerEventStructureReady(psStructure); @@ -2985,9 +2985,9 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool isMission) //structures always update their targets for (UDWORD i = 0; i < psStructure->numWeaps; i++) { - bDirect = proj_Direct(&asWeaponStats[psStructure->asWeaps[i].nStat]); + bDirect = proj_Direct(psStructure->getWeaponStats(i)); if (psStructure->asWeaps[i].nStat > 0 && - asWeaponStats[psStructure->asWeaps[i].nStat].weaponSubClass != WSC_LAS_SAT) + psStructure->getWeaponStats(i)->weaponSubClass != WSC_LAS_SAT) { if (aiChooseTarget(psStructure, &psChosenObjs[i], i, true, &tmpOrigin)) { @@ -3022,7 +3022,7 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool isMission) if (psChosenObjs[i] != nullptr && !aiObjectIsProbablyDoomed(psChosenObjs[i], bDirect)) { // get the weapon stat to see if there is a visible turret to rotate - psWStats = &asWeaponStats[psStructure->asWeaps[i].nStat]; + psWStats = psStructure->getWeaponStats(i); //if were going to shoot at something move the turret first then fire when locked on if (psWStats->pMountGraphic == nullptr)//no turret so lock on whatever @@ -6974,7 +6974,7 @@ bool lasSatStructSelected(const STRUCTURE *psStruct) { if ((psStruct->selected || (bMultiPlayer && !isHumanPlayer(psStruct->player))) && psStruct->asWeaps[0].nStat - && (asWeaponStats[psStruct->asWeaps[0].nStat].weaponSubClass == WSC_LAS_SAT)) + && (psStruct->getWeaponStats(0)->weaponSubClass == WSC_LAS_SAT)) { return true; } diff --git a/src/visibility.cpp b/src/visibility.cpp index cd81d4cf98f..0ab0dbe0a07 100644 --- a/src/visibility.cpp +++ b/src/visibility.cpp @@ -526,7 +526,7 @@ int visibleObject(const BASE_OBJECT *psViewer, const BASE_OBJECT *psTarget, bool } if (psTarget->type == OBJ_DROID && ((const DROID*)psTarget)->isVtol() - && asWeaponStats[psStruct->asWeaps[0].nStat].surfaceToAir == SHOOT_IN_AIR) + && psStruct->getWeaponStats(0)->surfaceToAir == SHOOT_IN_AIR) { range = 3 * range / 2; // increase vision range of AA vs VTOL } @@ -964,7 +964,7 @@ bool lineOfFire(const SIMPLE_OBJECT *psViewer, const BASE_OBJECT *psTarget, int } else if (psViewer->type == OBJ_STRUCTURE) { - psStats = &asWeaponStats[((const STRUCTURE *)psViewer)->asWeaps[weapon_slot].nStat]; + psStats = ((const STRUCTURE*)psViewer)->getWeaponStats(weapon_slot); } // 2d distance int distance = iHypot((psTarget->pos - psViewer->pos).xy());