diff --git a/src/action.cpp b/src/action.cpp index 8c000884d3f..0c3097a895d 100644 --- a/src/action.cpp +++ b/src/action.cpp @@ -167,21 +167,21 @@ bool actionInRange(const DROID *psDroid, const BASE_OBJECT *psObj, int weapon_sl } const unsigned compIndex = psDroid->asWeaps[weapon_slot].nStat; - ASSERT_OR_RETURN(false, compIndex < numWeaponStats, "Invalid range referenced for numWeaponStats, %d > %d", compIndex, numWeaponStats); - const WEAPON_STATS *psStats = asWeaponStats + compIndex; + ASSERT_OR_RETURN(false, compIndex < asWeaponStats.size(), "Invalid range referenced for numWeaponStats, %d > %zu", compIndex, asWeaponStats.size()); + const WEAPON_STATS *psStats = &asWeaponStats[compIndex]; const int dx = (SDWORD)psDroid->pos.x - (SDWORD)psObj->pos.x; const int dy = (SDWORD)psDroid->pos.y - (SDWORD)psObj->pos.y; const int radSq = dx * dx + dy * dy; - const int longRange = proj_GetLongRange(psStats, psDroid->player); - const int shortRange = proj_GetShortRange(psStats, psDroid->player); + const int longRange = proj_GetLongRange(*psStats, psDroid->player); + const int shortRange = proj_GetShortRange(*psStats, psDroid->player); int rangeSq = 0; switch (psDroid->secondaryOrder & DSS_ARANGE_MASK) { case DSS_ARANGE_OPTIMUM: - if (!useLongWithOptimum && weaponShortHit(psStats, psDroid->player) > weaponLongHit(psStats, psDroid->player)) + if (!useLongWithOptimum && weaponShortHit(*psStats, psDroid->player) > weaponLongHit(*psStats, psDroid->player)) { rangeSq = shortRange * shortRange; } @@ -206,7 +206,7 @@ bool actionInRange(const DROID *psDroid, const BASE_OBJECT *psObj, int weapon_sl if (radSq <= rangeSq) { /* check min range */ - const int minrange = proj_GetMinRange(psStats, psDroid->player); + const int minrange = proj_GetMinRange(*psStats, psDroid->player); if (radSq >= minrange * minrange || !proj_Direct(psStats)) { return true; @@ -239,7 +239,7 @@ static bool actionInsideMinRange(DROID *psDroid, BASE_OBJECT *psObj, WEAPON_STAT const int dx = psDroid->pos.x - psObj->pos.x; const int dy = psDroid->pos.y - psObj->pos.y; const int radSq = dx * dx + dy * dy; - const int minRange = proj_GetMinRange(psStats, psDroid->player); + const int minRange = proj_GetMinRange(*psStats, psDroid->player); const int rangeSq = minRange * minRange; // check min range @@ -304,7 +304,7 @@ void actionAlignTurret(BASE_OBJECT *psObj, int weapon_slot) /* returns true if on target */ bool actionTargetTurret(BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, WEAPON *psWeapon) { - WEAPON_STATS *psWeapStats = asWeaponStats + psWeapon->nStat; + WEAPON_STATS *psWeapStats = &asWeaponStats[psWeapon->nStat]; uint16_t tRotation, tPitch; uint16_t targetRotation; int32_t rotationTolerance = 0; @@ -391,7 +391,7 @@ bool actionTargetTurret(BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, WEAPON * bool onTarget = abs(angleDelta(targetRotation - (tRotation + psAttacker->rot.direction))) <= rotationTolerance; /* Set muzzle pitch if not repairing or outside minimum range */ - const int minRange = proj_GetMinRange(psWeapStats, psAttacker->player); + const int minRange = proj_GetMinRange(*psWeapStats, psAttacker->player); if (!bRepair && (unsigned)objPosDiffSq(psAttacker, psTarget) > minRange * minRange && proj_Direct(psWeapStats)) { /* get target distance */ @@ -634,7 +634,7 @@ void actionSanity(DROID *psDroid) // clear the target if it has died for (int i = 0; i < MAX_WEAPONS; i++) { - bDirect = proj_Direct(asWeaponStats + psDroid->asWeaps[i].nStat); + bDirect = proj_Direct(getWeaponStats(psDroid, i)); if (psDroid->psActionTarget[i] && (avoidOverkill ? aiObjectIsProbablyDoomed(psDroid->psActionTarget[i], bDirect) : psDroid->psActionTarget[i]->died)) { syncDebugObject(psDroid->psActionTarget[i], '-'); @@ -681,7 +681,7 @@ void actionUpdateDroid(DROID *psDroid) CHECK_DROID(psDroid); - PROPULSION_STATS *psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + PROPULSION_STATS *psPropStats = getPropulsionStats(psDroid); ASSERT_OR_RETURN(, psPropStats != nullptr, "Invalid propulsion stats pointer"); bool secHoldActive = secondaryGetState(psDroid, DSO_HALTTYPE) == DSS_HALT_HOLD; @@ -738,7 +738,7 @@ void actionUpdateDroid(DROID *psDroid) { BASE_OBJECT *psTemp = nullptr; - WEAPON_STATS *const psWeapStats = &asWeaponStats[psDroid->asWeaps[i].nStat]; + WEAPON_STATS *const psWeapStats = getWeaponStats(psDroid, i); if (psDroid->asWeaps[i].nStat > 0 && psWeapStats->rotate && IS_TIME_TO_CHECK_FOR_NEW_TARGET(psDroid) @@ -838,7 +838,7 @@ void actionUpdateDroid(DROID *psDroid) BASE_OBJECT *psTemp = nullptr; //I moved psWeapStats flag update there - WEAPON_STATS *const psWeapStats = &asWeaponStats[psDroid->asWeaps[i].nStat]; + WEAPON_STATS *const psWeapStats = getWeaponStats(psDroid, i); if (!psDroid->isVtol() && psDroid->asWeaps[i].nStat > 0 && psWeapStats->rotate @@ -876,7 +876,7 @@ void actionUpdateDroid(DROID *psDroid) bHasTarget = false; for (unsigned i = 0; i < psDroid->numWeaps; ++i) { - bDirect = proj_Direct(asWeaponStats + psDroid->asWeaps[i].nStat); + bDirect = proj_Direct(getWeaponStats(psDroid, i)); blockingWall = nullptr; // Does this weapon have a target? if (psDroid->psActionTarget[i] != nullptr) @@ -927,7 +927,7 @@ void actionUpdateDroid(DROID *psDroid) for (unsigned i = 0; i < psDroid->numWeaps; ++i) { const unsigned compIndex = psDroid->asWeaps[i].nStat; - const WEAPON_STATS *psStats = asWeaponStats + compIndex; + const WEAPON_STATS *psStats = &asWeaponStats[compIndex]; wallBlocked = false; // has weapon a target? is target valid? @@ -1071,7 +1071,7 @@ void actionUpdateDroid(DROID *psDroid) && actionVisibleTarget(psDroid, psActionTarget, i) && actionInRange(psDroid, psActionTarget, i)) { - WEAPON_STATS *const psWeapStats = &asWeaponStats[psDroid->asWeaps[i].nStat]; + WEAPON_STATS *const psWeapStats = getWeaponStats(psDroid, i); WEAPON_EFFECT weapEffect = psWeapStats->weaponEffect; blockingWall = visGetBlockingWall(psDroid, psActionTarget); @@ -1226,7 +1226,7 @@ void actionUpdateDroid(DROID *psDroid) && validTarget(psDroid, psDroid->psActionTarget[0], i)) { //I moved psWeapStats flag update there - psWeapStats = &asWeaponStats[psDroid->asWeaps[i].nStat]; + psWeapStats = getWeaponStats(psDroid, i); if (actionVisibleTarget(psDroid, psDroid->psActionTarget[0], i)) { if (actionInRange(psDroid, psDroid->psActionTarget[0], i)) @@ -1278,7 +1278,7 @@ void actionUpdateDroid(DROID *psDroid) else if (psWeapStats) { // if the vtol is far enough away head for the target again - const int maxRange = proj_GetLongRange(psWeapStats, psDroid->player); + const int maxRange = proj_GetLongRange(*psWeapStats, psDroid->player); if (rangeSq > maxRange * maxRange) { // don't do another attack run if already heading for the target @@ -1325,7 +1325,7 @@ void actionUpdateDroid(DROID *psDroid) && actionVisibleTarget(psDroid, psDroid->psActionTarget[0], i)) { bool chaseBloke = false; - WEAPON_STATS *const psWeapStats = &asWeaponStats[psDroid->asWeaps[i].nStat]; + WEAPON_STATS *const psWeapStats = getWeaponStats(psDroid, i); const bool actionIsInRange = actionInRange(psDroid, psDroid->psActionTarget[0], i); if (psWeapStats->rotate) { @@ -1403,7 +1403,7 @@ void actionUpdateDroid(DROID *psDroid) /* Stopped moving but haven't reached the target - possibly move again */ //'hack' to make the droid to check the primary turrent instead of all - WEAPON_STATS *const psWeapStats = &asWeaponStats[psDroid->asWeaps[0].nStat]; + WEAPON_STATS *const psWeapStats = getWeaponStats(psDroid, 0); if (order->type == DORDER_ATTACKTARGET && secHoldActive) { @@ -1969,7 +1969,7 @@ void actionUpdateDroid(DROID *psDroid) { Vector2i diff = (psDroid->pos - order->psObj->pos).xy(); //Consider .shortRange here - int rangeSq = asWeaponStats[psDroid->asWeaps[0].nStat].upgrade[psDroid->player].maxRange / 2; // move close to sensor + int rangeSq = getWeaponStats(psDroid, 0)->upgrade[psDroid->player].maxRange / 2; // move close to sensor rangeSq = rangeSq * rangeSq; if (dot(diff, diff) < rangeSq) { @@ -2063,7 +2063,7 @@ void actionUpdateDroid(DROID *psDroid) { BASE_OBJECT *psTemp = nullptr; - WEAPON_STATS *const psWeapStats = &asWeaponStats[psDroid->asWeaps[i].nStat]; + WEAPON_STATS *const psWeapStats = getWeaponStats(psDroid, i); if (psDroid->asWeaps[i].nStat > 0 && psWeapStats->rotate && secondaryGetState(psDroid, DSO_ATTACK_LEVEL) == DSS_ALEV_ALWAYS && IS_TIME_TO_CHECK_FOR_NEW_TARGET(psDroid) diff --git a/src/ai.cpp b/src/ai.cpp index 0ad2a5f79c1..9e1a775de0e 100644 --- a/src/ai.cpp +++ b/src/ai.cpp @@ -94,8 +94,8 @@ static int aiDroidRange(DROID *psDroid, int weapon_slot) } else { - WEAPON_STATS *psWStats = psDroid->asWeaps[weapon_slot].nStat + asWeaponStats; - longRange = proj_GetLongRange(psWStats, psDroid->player); + WEAPON_STATS *psWStats = getWeaponStats(psDroid, weapon_slot); + longRange = proj_GetLongRange(*psWStats, psDroid->player); } return longRange; @@ -110,9 +110,9 @@ static bool aiStructHasRange(STRUCTURE *psStruct, BASE_OBJECT *psTarget, int wea return false; } - WEAPON_STATS *psWStats = psStruct->asWeaps[weapon_slot].nStat + asWeaponStats; + WEAPON_STATS *psWStats = &asWeaponStats[psStruct->asWeaps[weapon_slot].nStat]; - int longRange = proj_GetLongRange(psWStats, psStruct->player); + int longRange = proj_GetLongRange(*psWStats, psStruct->player); return objPosDiffSq(psStruct, psTarget) < longRange * longRange && lineOfFire(psStruct, psTarget, weapon_slot, true); } @@ -166,10 +166,10 @@ bool aiShutdown() /** Search the global list of sensors for a possible target for psObj. */ static BASE_OBJECT *aiSearchSensorTargets(BASE_OBJECT *psObj, int weapon_slot, WEAPON_STATS *psWStats, TARGET_ORIGIN *targetOrigin) { - int longRange = proj_GetLongRange(psWStats, psObj->player); + int longRange = proj_GetLongRange(*psWStats, psObj->player); int tarDist = longRange * longRange; bool foundCB = false; - int minDist = proj_GetMinRange(psWStats, psObj->player) * proj_GetMinRange(psWStats, psObj->player); + int minDist = proj_GetMinRange(*psWStats, psObj->player) * proj_GetMinRange(*psWStats, psObj->player); BASE_OBJECT *psTarget = nullptr; if (targetOrigin) @@ -197,15 +197,16 @@ static BASE_OBJECT *aiSearchSensorTargets(BASE_OBJECT *psObj, int weapon_slot, W { continue; } + const auto sensorType = getSensorStats(psDroid)->type; // Artillery should not fire at objects observed by VTOL CB/Strike sensors. - if (asSensorStats[psDroid->asBits[COMP_SENSOR]].type == VTOL_CB_SENSOR || - asSensorStats[psDroid->asBits[COMP_SENSOR]].type == VTOL_INTERCEPT_SENSOR || + if (sensorType == VTOL_CB_SENSOR || + sensorType == VTOL_INTERCEPT_SENSOR || objRadarDetector((BASE_OBJECT *)psDroid)) { continue; } psTemp = psDroid->psActionTarget[0]; - isCB = asSensorStats[psDroid->asBits[COMP_SENSOR]].type == INDIRECT_CB_SENSOR; + isCB = sensorType == INDIRECT_CB_SENSOR; //isRD = objRadarDetector((BASE_OBJECT *)psDroid); } else if (psSensor->type == OBJ_STRUCTURE) @@ -292,7 +293,7 @@ static SDWORD targetAttackWeight(BASE_OBJECT *psTarget, BASE_OBJECT *psAttacker, { psAttackerDroid = (DROID *)psAttacker; - attackerWeapon = (WEAPON_STATS *)(asWeaponStats + psAttackerDroid->asWeaps[weapon_slot].nStat); + attackerWeapon = getWeaponStats(psAttackerDroid, weapon_slot); //check if this droid is assigned to a commander bCmdAttached = hasCommander(psAttackerDroid); @@ -334,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 = (WEAPON_STATS *)(&asWeaponStats[((STRUCTURE *)psAttacker)->asWeaps[weapon_slot].nStat]); } else /* feature */ { @@ -357,7 +358,7 @@ static SDWORD targetAttackWeight(BASE_OBJECT *psTarget, BASE_OBJECT *psAttacker, bEmpWeap = (attackerWeapon->weaponSubClass == WSC_EMP); int dist = iHypot((psAttacker->pos - psTarget->pos).xy()); - bool tooClose = (unsigned)dist <= proj_GetMinRange(attackerWeapon, psAttacker->player); + bool tooClose = (unsigned)dist <= proj_GetMinRange(*attackerWeapon, psAttacker->player); if (tooClose) { dist = objSensorRange(psAttacker); // If object is too close to fire at, consider it to be at maximum range. @@ -419,8 +420,8 @@ static SDWORD targetAttackWeight(BASE_OBJECT *psTarget, BASE_OBJECT *psAttacker, } /* Now calculate the overall weight */ - attackWeight = asWeaponModifier[weaponEffect][(asPropulsionStats + targetDroid->asBits[COMP_PROPULSION])->propulsionType] // Our weapon's effect against target - + asWeaponModifierBody[weaponEffect][(asBodyStats + targetDroid->asBits[COMP_BODY])->size] + attackWeight = asWeaponModifier[weaponEffect][getPropulsionStats(targetDroid)->propulsionType] // Our weapon's effect against target + + asWeaponModifierBody[weaponEffect][getBodyStats(targetDroid)->size] + WEIGHT_DIST_TILE_DROID * objSensorRange(psAttacker) / TILE_UNITS - WEIGHT_DIST_TILE_DROID * dist / TILE_UNITS // farther droids are less attractive + WEIGHT_HEALTH_DROID * damageRatio / 100 // we prefer damaged droids @@ -501,9 +502,9 @@ static SDWORD targetAttackWeight(BASE_OBJECT *psTarget, BASE_OBJECT *psAttacker, { /* indirect firing units have slow reload times, so give the target a chance to die, * and give a different unit a chance to get in range, too. */ - if (weaponROF(attackerWeapon, psAttacker->player) < TARGET_DOOMED_SLOW_RELOAD_T) + if (weaponROF(*attackerWeapon, psAttacker->player) < TARGET_DOOMED_SLOW_RELOAD_T) { - debug(LOG_NEVER, "Not killing unit - doomed. My ROF: %i (%s)", weaponROF(attackerWeapon, psAttacker->player), getStatsName(attackerWeapon)); + debug(LOG_NEVER, "Not killing unit - doomed. My ROF: %i (%s)", weaponROF(*attackerWeapon, psAttacker->player), getStatsName(attackerWeapon)); return noTarget; } attackWeight /= TARGET_DOOMED_PENALTY_F; @@ -582,15 +583,14 @@ int aiBestNearestTarget(DROID *psDroid, BASE_OBJECT **ppsObj, int weapon_slot, i ++numDroidNearestTargetChecksThisFrame; // Check if we have a CB target to begin with - if (!proj_Direct(asWeaponStats + psDroid->asWeaps[weapon_slot].nStat)) + WEAPON_STATS* psWStats = getWeaponStats(psDroid, weapon_slot); + if (!proj_Direct(psWStats)) { - WEAPON_STATS *psWStats = psDroid->asWeaps[weapon_slot].nStat + asWeaponStats; - bestTarget = aiSearchSensorTargets((BASE_OBJECT *)psDroid, weapon_slot, psWStats, &tmpOrigin); bestMod = targetAttackWeight(bestTarget, (BASE_OBJECT *)psDroid, weapon_slot); } - weaponEffect = (asWeaponStats + psDroid->asWeaps[weapon_slot].nStat)->weaponEffect; + weaponEffect = psWStats->weaponEffect; electronic = electronicDroid(psDroid); @@ -726,7 +726,7 @@ int aiBestNearestTarget(DROID *psDroid, BASE_OBJECT **ppsObj, int weapon_slot, i // See if target is blocked by a wall; only affects direct weapons // Ignore friendly walls here - if (proj_Direct(asWeaponStats + psDroid->asWeaps[weapon_slot].nStat) + if (proj_Direct(psWStats) && targetStructure && !aiCheckAlliances(psDroid->player, targetStructure->player)) { @@ -887,8 +887,8 @@ 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 = psObj->asWeaps[weapon_slot].nStat + asWeaponStats; - int longRange = proj_GetLongRange(psWStats, psObj->player); + WEAPON_STATS *psWStats = &asWeaponStats[psObj->asWeaps[weapon_slot].nStat]; + int longRange = proj_GetLongRange(*psWStats, psObj->player); // see if there is a target from the command droids psTarget = nullptr; @@ -1267,7 +1267,7 @@ bool validTarget(BASE_OBJECT const *psObject, BASE_OBJECT const *psTarget, int w switch (psTarget->type) { case OBJ_DROID: - if (asPropulsionTypes[asPropulsionStats[((const DROID *)psTarget)->asBits[COMP_PROPULSION]].propulsionType].travel == AIR) + if (asPropulsionTypes[getPropulsionStats((const DROID*)psTarget)->propulsionType].travel == AIR) { if (((const DROID *)psTarget)->sMove.Status != MOVEINACTIVE) { @@ -1302,7 +1302,7 @@ bool validTarget(BASE_OBJECT const *psObject, BASE_OBJECT const *psTarget, int w // Can't attack without a weapon if (((const DROID *)psObject)->numWeaps != 0 && ((const DROID *)psObject)->asWeaps[weapon_slot].nStat != 0) { - surfaceToAir = asWeaponStats[((const DROID *)psObject)->asWeaps[weapon_slot].nStat].surfaceToAir; + surfaceToAir = getWeaponStats((const DROID*)psObject, weapon_slot)->surfaceToAir; if (((surfaceToAir & SHOOT_IN_AIR) && bTargetInAir) || ((surfaceToAir & SHOOT_ON_GROUND) && !bTargetInAir)) { return true; diff --git a/src/bucket3d.cpp b/src/bucket3d.cpp index 986b355fa4b..571dc9aa425 100644 --- a/src/bucket3d.cpp +++ b/src/bucket3d.cpp @@ -35,6 +35,7 @@ #include "effects.h" #include "miscimd.h" #include "profiling.h" +#include "droid.h" #include @@ -196,7 +197,7 @@ static SDWORD bucketCalculateZ(RENDER_TYPE objectType, void *pObject, const glm: position.z = -(psSimpObj->pos.y); position.y = psSimpObj->pos.z; - psBStats = asBodyStats + psDroid->asBits[COMP_BODY]; + psBStats = getBodyStats(psDroid); droidSize = psBStats->pIMD->radius; z = pie_RotateProjectWithPerspective(&position, perspectiveViewMatrix, &pixel) - (droidSize * 2); diff --git a/src/combat.cpp b/src/combat.cpp index 4c0ba41d734..829b95d697c 100644 --- a/src/combat.cpp +++ b/src/combat.cpp @@ -62,8 +62,8 @@ bool combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in /* Get the stats for the weapon */ compIndex = psWeap->nStat; - ASSERT_OR_RETURN(false , compIndex < numWeaponStats, "Invalid range referenced for numWeaponStats, %d > %d", compIndex, numWeaponStats); - psStats = asWeaponStats + compIndex; + ASSERT_OR_RETURN(false , compIndex < asWeaponStats.size(), "Invalid range referenced for numWeaponStats, %d > %zu", compIndex, asWeaponStats.size()); + psStats = &asWeaponStats[compIndex]; // check valid weapon/prop combination if (!validTarget(psAttacker, psTarget, weapon_slot)) @@ -76,7 +76,7 @@ bool combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in // See if reloadable weapon. if (psStats->upgrade[psAttacker->player].reloadTime) { - unsigned reloadTime = psWeap->lastFired + weaponReloadTime(psStats, psAttacker->player); + unsigned reloadTime = psWeap->lastFired + weaponReloadTime(*psStats, psAttacker->player); if (psWeap->ammo == 0) // Out of ammo? { fireTime = std::max(fireTime, reloadTime); // Have to wait for weapon to reload before firing. @@ -94,7 +94,7 @@ bool combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in } /* See when the weapon last fired to control it's rate of fire */ - firePause = weaponFirePause(psStats, psAttacker->player); + firePause = weaponFirePause(*psStats, psAttacker->player); firePause = std::max(firePause, 1u); // Don't shoot infinitely many shots at once. fireTime = std::max(fireTime, psWeap->lastFired + firePause); @@ -138,8 +138,8 @@ bool combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in /* Now see if the target is in range - also check not too near */ int dist = iHypot(deltaPos.xy()); - longRange = proj_GetLongRange(psStats, psAttacker->player); - shortRange = proj_GetShortRange(psStats, psAttacker->player); + longRange = proj_GetLongRange(*psStats, psAttacker->player); + shortRange = proj_GetShortRange(*psStats, psAttacker->player); int min_angle = 0; // Calculate angle for indirect shots @@ -162,16 +162,16 @@ bool combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in } int baseHitChance = 0; - const int min_range = proj_GetMinRange(psStats, psAttacker->player); + const int min_range = proj_GetMinRange(*psStats, psAttacker->player); if (dist <= shortRange && dist >= min_range) { // get weapon chance to hit in the short range - baseHitChance = weaponShortHit(psStats, psAttacker->player); + baseHitChance = weaponShortHit(*psStats, psAttacker->player); } else if (dist <= longRange && dist >= min_range) { // get weapon chance to hit in the long range - baseHitChance = weaponLongHit(psStats, psAttacker->player); + baseHitChance = weaponLongHit(*psStats, psAttacker->player); } else { @@ -237,7 +237,7 @@ bool combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in DROID *psDroid = castDroid(psTarget); int32_t flightTime; - if (proj_Direct(psStats) || dist <= proj_GetMinRange(psStats, psAttacker->player)) + if (proj_Direct(psStats) || dist <= proj_GetMinRange(*psStats, psAttacker->player)) { flightTime = dist * GAME_TICKS_PER_SEC / psStats->flightSpeed; } @@ -376,7 +376,7 @@ int objArmour(const BASE_OBJECT *psObj, WEAPON_CLASS weaponClass) int armour = 0; if (psObj->type == OBJ_DROID) { - armour = bodyArmour(asBodyStats + ((const DROID *)psObj)->asBits[COMP_BODY], psObj->player, weaponClass); + armour = bodyArmour(*getBodyStats((const DROID*)psObj), psObj->player, weaponClass); } else if (psObj->type == OBJ_STRUCTURE && weaponClass == WC_KINETIC && ((const STRUCTURE *)psObj)->status != SS_BEING_BUILT) { @@ -506,7 +506,7 @@ unsigned int objGuessFutureDamage(WEAPON_STATS *psStats, unsigned int player, BA return 0; // Hard to destroy the ground. The armour on the mud is very strong and blocks all damage. } - damage = calcDamage(weaponDamage(psStats, player), psStats->weaponEffect, psTarget); + damage = calcDamage(weaponDamage(*psStats, player), psStats->weaponEffect, psTarget); // apply game difficulty setting damage = modifyForDifficultyLevel(damage, psTarget->player != selectedPlayer); diff --git a/src/component.cpp b/src/component.cpp index a101bade38e..50fa8af32e3 100644 --- a/src/component.cpp +++ b/src/component.cpp @@ -444,7 +444,7 @@ static bool displayCompObj(DROID *psDroid, bool bButton, const glm::mat4& modelM } /* get propulsion stats */ - psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + psPropStats = getPropulsionStats(psDroid); ASSERT_OR_RETURN(didDrawSomething, psPropStats != nullptr, "invalid propulsion stats pointer"); //set pieflag for button object or ingame object @@ -531,8 +531,9 @@ static bool displayCompObj(DROID *psDroid, bool bButton, const glm::mat4& modelM } /* Render animation effects based on movement or lack thereof, if any */ - psMoveAnim = asBodyStats[psDroid->asBits[COMP_BODY]].ppMoveIMDList[psDroid->asBits[COMP_PROPULSION]]; - psStillAnim = asBodyStats[psDroid->asBits[COMP_BODY]].ppStillIMDList[psDroid->asBits[COMP_PROPULSION]]; + const auto* bodyStats = getBodyStats(psDroid); + psMoveAnim = bodyStats->ppMoveIMDList[psDroid->asBits[COMP_PROPULSION]]; + psStillAnim = bodyStats->ppStillIMDList[psDroid->asBits[COMP_PROPULSION]]; if (!bButton && psMoveAnim && psDroid->sMove.Status != MOVEINACTIVE) { iIMDShape *displayModel = psMoveAnim->displayModel(); diff --git a/src/component.h b/src/component.h index 4da06a4dfa6..fee30e9376b 100644 --- a/src/component.h +++ b/src/component.h @@ -83,32 +83,32 @@ void drawMuzzleFlash(WEAPON sWeap, iIMDShape *weaponImd, iIMDShape *flashImd, PI #define PART_IMD(STATS,DROID,COMPONENT,PLAYER) (STATS[DROID->asBits[COMPONENT]].pIMD) /* Get the chassis imd */ -#define BODY_IMD(DROID,PLAYER) (asBodyStats[DROID->asBits[COMP_BODY]].pIMD) +#define BODY_IMD(DROID,PLAYER) (getBodyStats(DROID)->pIMD) /* Get the brain imd - NOTE: Unused!*/ -#define BRAIN_IMD(DROID,PLAYER) (asBrainStats[DROID->asBits[COMP_BRAIN]].pIMD) +#define BRAIN_IMD(DROID,PLAYER) (getBrainStats(DROID)->pIMD) /* Get the weapon imd */ -#define WEAPON_IMD(DROID,WEAPON_NUM) (asWeaponStats[DROID->asWeaps[WEAPON_NUM].nStat].pIMD) +#define WEAPON_IMD(DROID,WEAPON_NUM) (getWeaponStats(DROID, WEAPON_NUM)->pIMD) /* Get the propulsion imd THIS IS A LITTLE MORE COMPLICATED NOW!*/ //#define PROPULSION_IMD(DROID,PLAYER) (asPropulsionStats[DROID->asBits[COMP_PROPULSION]].pIMD[PLAYER]) /* Get the sensor imd */ -#define SENSOR_IMD(DROID,PLAYER) (asSensorStats[DROID->asBits[COMP_SENSOR]].pIMD) +#define SENSOR_IMD(DROID,PLAYER) (getSensorStats(DROID)->pIMD) /* Get an ECM imd!?! */ -#define ECM_IMD(DROID,PLAYER) (asECMStats[DROID->asBits[COMP_ECM]].pIMD) +#define ECM_IMD(DROID,PLAYER) (getECMStats(DROID)->pIMD) /* Get an Repair imd!?! */ -#define REPAIR_IMD(DROID,PLAYER) (asRepairStats[DROID->asBits[COMP_REPAIRUNIT]].pIMD) +#define REPAIR_IMD(DROID,PLAYER) (getRepairStats(DROID)->pIMD) /* Get a construct imd */ -#define CONSTRUCT_IMD(DROID,PLAYER) (asConstructStats[DROID->asBits[COMP_CONSTRUCT]].pIMD) +#define CONSTRUCT_IMD(DROID,PLAYER) (getConstructStats(DROID)->pIMD) /* Get a weapon mount imd*/ -#define WEAPON_MOUNT_IMD(DROID,WEAPON_NUM) (asWeaponStats[DROID->asWeaps[WEAPON_NUM].nStat].pMountGraphic) +#define WEAPON_MOUNT_IMD(DROID,WEAPON_NUM) (getWeaponStats(DROID, WEAPON_NUM)->pMountGraphic) /* Get a sensor mount imd*/ -#define SENSOR_MOUNT_IMD(DROID,PLAYER) (asSensorStats[DROID->asBits[COMP_SENSOR]].pMountGraphic) +#define SENSOR_MOUNT_IMD(DROID,PLAYER) (getSensorStats(DROID)->pMountGraphic) /* Get a construct mount imd*/ -#define CONSTRUCT_MOUNT_IMD(DROID,PLAYER) (asConstructStats[DROID->asBits[COMP_CONSTRUCT]].pMountGraphic) +#define CONSTRUCT_MOUNT_IMD(DROID,PLAYER) (getConstructStats(DROID)->pMountGraphic) /* Get a ecm mount imd*/ -#define ECM_MOUNT_IMD(DROID,PLAYER) (asECMStats[DROID->asBits[COMP_ECM]].pMountGraphic) +#define ECM_MOUNT_IMD(DROID,PLAYER) (getECMStats(DROID)->pMountGraphic) /* Get a repair mount imd*/ -#define REPAIR_MOUNT_IMD(DROID,PLAYER) (asRepairStats[DROID->asBits[COMP_REPAIRUNIT]].pMountGraphic) +#define REPAIR_MOUNT_IMD(DROID,PLAYER) (getRepairStats(DROID)->pMountGraphic) /* Get a muzzle flash pie*/ -#define MUZZLE_FLASH_PIE(DROID,WEAPON_NUM) (asWeaponStats[DROID->asWeaps[WEAPON_NUM].nStat].pMuzzleGraphic) +#define MUZZLE_FLASH_PIE(DROID,WEAPON_NUM) (getWeaponStats(DROID, WEAPON_NUM)->pMuzzleGraphic) #endif // __INCLUDED_SRC_COMPONENT_H__ diff --git a/src/data.cpp b/src/data.cpp index 9176ca9c680..fe8da7af675 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -147,7 +147,7 @@ static bool bufferSBODYLoad(const char *fileName, void **ppData) WzConfig ini(fileName, WzConfig::ReadOnlyAndRequired); calcDataHash(ini, DATA_SBODY); - if (!loadBodyStats(ini) || !allocComponentList(COMP_BODY, numBodyStats)) + if (!loadBodyStats(ini) || !allocComponentList(COMP_BODY, asBodyStats.size())) { return false; } @@ -170,7 +170,7 @@ static bool bufferSWEAPONLoad(const char *fileName, void **ppData) calcDataHash(ini, DATA_SWEAPON); if (!loadWeaponStats(ini) - || !allocComponentList(COMP_WEAPON, numWeaponStats)) + || !allocComponentList(COMP_WEAPON, asWeaponStats.size())) { return false; } @@ -187,7 +187,7 @@ static bool bufferSCONSTRLoad(const char *fileName, void **ppData) calcDataHash(ini, DATA_SCONSTR); if (!loadConstructStats(ini) - || !allocComponentList(COMP_CONSTRUCT, numConstructStats)) + || !allocComponentList(COMP_CONSTRUCT, asConstructStats.size())) { return false; } @@ -204,7 +204,7 @@ static bool bufferSECMLoad(const char *fileName, void **ppData) calcDataHash(ini, DATA_SECM); if (!loadECMStats(ini) - || !allocComponentList(COMP_ECM, numECMStats)) + || !allocComponentList(COMP_ECM, asECMStats.size())) { return false; } @@ -220,7 +220,7 @@ static bool bufferSPROPLoad(const char *fileName, void **ppData) WzConfig ini(fileName, WzConfig::ReadOnlyAndRequired); calcDataHash(ini, DATA_SPROP); - if (!loadPropulsionStats(ini) || !allocComponentList(COMP_PROPULSION, numPropulsionStats)) + if (!loadPropulsionStats(ini) || !allocComponentList(COMP_PROPULSION, asPropulsionStats.size())) { return false; } @@ -236,7 +236,7 @@ static bool bufferSSENSORLoad(const char *fileName, void **ppData) calcDataHash(ini, DATA_SSENSOR); if (!loadSensorStats(ini) - || !allocComponentList(COMP_SENSOR, numSensorStats)) + || !allocComponentList(COMP_SENSOR, asSensorStats.size())) { return false; } @@ -252,7 +252,7 @@ static bool bufferSREPAIRLoad(const char *fileName, void **ppData) WzConfig ini(fileName, WzConfig::ReadOnlyAndRequired); calcDataHash(ini, DATA_SREPAIR); - if (!loadRepairStats(ini) || !allocComponentList(COMP_REPAIRUNIT, numRepairStats)) + if (!loadRepairStats(ini) || !allocComponentList(COMP_REPAIRUNIT, asRepairStats.size())) { return false; } @@ -268,7 +268,7 @@ static bool bufferSBRAINLoad(const char *fileName, void **ppData) WzConfig ini(fileName, WzConfig::ReadOnlyAndRequired); calcDataHash(ini, DATA_SBRAIN); - if (!loadBrainStats(ini) || !allocComponentList(COMP_BRAIN, numBrainStats)) + if (!loadBrainStats(ini) || !allocComponentList(COMP_BRAIN, asBrainStats.size())) { return false; } diff --git a/src/design.cpp b/src/design.cpp index 32ff2788bef..eb117b3b741 100644 --- a/src/design.cpp +++ b/src/design.cpp @@ -469,49 +469,49 @@ static ComponentIterator componentIterator(COMPONENT_STATS *psStats, unsigned si static ComponentIterator bodyIterator() { ASSERT(selectedPlayer < MAX_PLAYERS, "selectedPlayer: %" PRIu32 "", selectedPlayer); - return componentIterator(asBodyStats, sizeof(*asBodyStats), apCompLists[selectedPlayer][COMP_BODY], numBodyStats); + return componentIterator(asBodyStats.data(), sizeof(BODY_STATS), apCompLists[selectedPlayer][COMP_BODY], asBodyStats.size()); } static ComponentIterator weaponIterator() { ASSERT(selectedPlayer < MAX_PLAYERS, "selectedPlayer: %" PRIu32 "", selectedPlayer); - return componentIterator(asWeaponStats, sizeof(*asWeaponStats), apCompLists[selectedPlayer][COMP_WEAPON], numWeaponStats); + return componentIterator(asWeaponStats.data(), sizeof(WEAPON_STATS), apCompLists[selectedPlayer][COMP_WEAPON], asWeaponStats.size()); } static ComponentIterator propulsionIterator() { ASSERT(selectedPlayer < MAX_PLAYERS, "selectedPlayer: %" PRIu32 "", selectedPlayer); - return componentIterator(asPropulsionStats, sizeof(*asPropulsionStats), apCompLists[selectedPlayer][COMP_PROPULSION], numPropulsionStats); + return componentIterator(asPropulsionStats.data(), sizeof(PROPULSION_STATS), apCompLists[selectedPlayer][COMP_PROPULSION], asPropulsionStats.size()); } static ComponentIterator sensorIterator() { ASSERT(selectedPlayer < MAX_PLAYERS, "selectedPlayer: %" PRIu32 "", selectedPlayer); - return componentIterator(asSensorStats, sizeof(SENSOR_STATS), apCompLists[selectedPlayer][COMP_SENSOR], numSensorStats); + return componentIterator(asSensorStats.data(), sizeof(SENSOR_STATS), apCompLists[selectedPlayer][COMP_SENSOR], asSensorStats.size()); } static ComponentIterator ecmIterator() { ASSERT(selectedPlayer < MAX_PLAYERS, "selectedPlayer: %" PRIu32 "", selectedPlayer); - return componentIterator(asECMStats, sizeof(ECM_STATS), apCompLists[selectedPlayer][COMP_ECM], numECMStats); + return componentIterator(asECMStats.data(), sizeof(ECM_STATS), apCompLists[selectedPlayer][COMP_ECM], asECMStats.size()); } static ComponentIterator constructorIterator() { ASSERT(selectedPlayer < MAX_PLAYERS, "selectedPlayer: %" PRIu32 "", selectedPlayer); - return componentIterator(asConstructStats, sizeof(CONSTRUCT_STATS), apCompLists[selectedPlayer][COMP_CONSTRUCT], numConstructStats); + return componentIterator(asConstructStats.data(), sizeof(CONSTRUCT_STATS), apCompLists[selectedPlayer][COMP_CONSTRUCT], asConstructStats.size()); } static ComponentIterator repairIterator() { ASSERT(selectedPlayer < MAX_PLAYERS, "selectedPlayer: %" PRIu32 "", selectedPlayer); - return componentIterator(asRepairStats, sizeof(REPAIR_STATS), apCompLists[selectedPlayer][COMP_REPAIRUNIT], numRepairStats); + return componentIterator(asRepairStats.data(), sizeof(REPAIR_STATS), apCompLists[selectedPlayer][COMP_REPAIRUNIT], asRepairStats.size()); } static ComponentIterator brainIterator() { ASSERT(selectedPlayer < MAX_PLAYERS, "selectedPlayer: %" PRIu32 "", selectedPlayer); - return componentIterator(asBrainStats, sizeof(BRAIN_STATS), apCompLists[selectedPlayer][COMP_BRAIN], numBrainStats); + return componentIterator(asBrainStats.data(), sizeof(BRAIN_STATS), apCompLists[selectedPlayer][COMP_BRAIN], asBrainStats.size()); } static ComponentIterator concatIterators(std::vector iterators) @@ -559,11 +559,11 @@ static uint32_t findMaxPropulsionSpeed(TYPE_OF_TERRAIN terrainType) ); } -static uint32_t findMaxWeaponAttribute(std::function attributeGetter) +static uint32_t findMaxWeaponAttribute(std::function attributeGetter) { return findMax( weaponIterator(), - [=](COMPONENT_STATS &stats) { return attributeGetter((WEAPON_STATS *)&stats, selectedPlayer); } + [=](COMPONENT_STATS &stats) { return attributeGetter((WEAPON_STATS&)stats, selectedPlayer); } ); } @@ -571,7 +571,7 @@ static uint32_t getDesignMaxBodyArmour(WEAPON_CLASS weaponClass) { return findMax( bodyIterator(), - [=](COMPONENT_STATS &stats) { return bodyArmour((BODY_STATS *)&stats, selectedPlayer, weaponClass); } + [=](COMPONENT_STATS &stats) { return bodyArmour((BODY_STATS&)stats, selectedPlayer, weaponClass); } ); } @@ -579,7 +579,7 @@ static uint32_t getDesignMaxEngineOutput() { return findMax( bodyIterator(), - [=](COMPONENT_STATS &stats) { return bodyPower((BODY_STATS *)&stats, selectedPlayer); } + [=](COMPONENT_STATS &stats) { return bodyPower((BODY_STATS&)stats, selectedPlayer); } ); } @@ -601,7 +601,7 @@ static uint32_t getDesignMaxSensorRange() { return findMax( sensorIterator(), - [=](COMPONENT_STATS &stats) { return sensorRange((SENSOR_STATS *)&stats, selectedPlayer); } + [=](COMPONENT_STATS &stats) { return sensorRange((SENSOR_STATS&)stats, selectedPlayer); } ); } @@ -609,7 +609,7 @@ static uint32_t getDesignMaxEcmRange() { return findMax( ecmIterator(), - [=](COMPONENT_STATS &stats) { return ecmRange((ECM_STATS *)&stats, selectedPlayer); } + [=](COMPONENT_STATS &stats) { return ecmRange((ECM_STATS&)stats, selectedPlayer); } ); } @@ -617,7 +617,7 @@ static uint32_t getDesignMaxBuildPoints() { return findMax( constructorIterator(), - [=](COMPONENT_STATS &stats) { return constructorPoints((CONSTRUCT_STATS *)&stats, selectedPlayer); } + [=](COMPONENT_STATS &stats) { return constructorPoints((CONSTRUCT_STATS&)stats, selectedPlayer); } ); } @@ -1202,7 +1202,7 @@ static void intSetDesignMode(DES_COMPMODE newCompMode, bool forceRefresh) widgSetButtonState(psWScreen, IDDES_SYSTEMFORM, WBUT_LOCK); widgSetButtonState(psWScreen, IDDES_SYSTEMBUTTON, WBUT_CLICKLOCK); widgReveal(psWScreen, IDDES_SYSTEMFORM); - intSetSystemForm((COMPONENT_STATS *)(asWeaponStats + sCurrDesign.asWeaps[0])); // in case previous was a different slot + intSetSystemForm((COMPONENT_STATS *)(&asWeaponStats[sCurrDesign.asWeaps[0]])); // in case previous was a different slot break; case IDES_BODY: compList = intAddComponentForm(); @@ -1217,7 +1217,7 @@ static void intSetDesignMode(DES_COMPMODE newCompMode, bool forceRefresh) widgSetButtonState(psWScreen, IDDES_PROPFORM, WBUT_LOCK); widgSetButtonState(psWScreen, IDDES_PROPBUTTON, WBUT_CLICKLOCK); widgReveal(psWScreen, IDDES_PROPFORM); - intSetPropulsionForm(asPropulsionStats + sCurrDesign.asParts[COMP_PROPULSION]); + intSetPropulsionForm(&asPropulsionStats[sCurrDesign.asParts[COMP_PROPULSION]]); break; case IDES_TURRET_A: compList = intAddComponentForm(); @@ -1227,7 +1227,7 @@ static void intSetDesignMode(DES_COMPMODE newCompMode, bool forceRefresh) widgSetButtonState(psWScreen, IDDES_SYSTEMFORM, WBUT_LOCK); widgSetButtonState(psWScreen, IDDES_WPABUTTON, WBUT_CLICKLOCK); widgReveal(psWScreen, IDDES_SYSTEMFORM); - intSetSystemForm((COMPONENT_STATS *)(asWeaponStats + sCurrDesign.asWeaps[1])); // in case previous was a different slot + intSetSystemForm((COMPONENT_STATS *)(&asWeaponStats[sCurrDesign.asWeaps[1]])); // in case previous was a different slot // Stop the button flashing intSetButtonFlash(IDDES_WPABUTTON, false); break; @@ -1239,7 +1239,7 @@ static void intSetDesignMode(DES_COMPMODE newCompMode, bool forceRefresh) widgSetButtonState(psWScreen, IDDES_SYSTEMFORM, WBUT_LOCK); widgSetButtonState(psWScreen, IDDES_WPBBUTTON, WBUT_CLICKLOCK); widgReveal(psWScreen, IDDES_SYSTEMFORM); - intSetSystemForm((COMPONENT_STATS *)(asWeaponStats + sCurrDesign.asWeaps[2])); // in case previous was a different slot + intSetSystemForm((COMPONENT_STATS *)(&asWeaponStats[sCurrDesign.asWeaps[2]])); // in case previous was a different slot // Stop the button flashing intSetButtonFlash(IDDES_WPBBUTTON, false); break; @@ -1257,30 +1257,30 @@ intChooseSystemStats(DROID_TEMPLATE *psTemplate) { case DROID_COMMAND: compIndex = psTemplate->asParts[COMP_BRAIN]; - ASSERT_OR_RETURN(nullptr, compIndex < numBrainStats, "Invalid range referenced for numBrainStats, %d > %d", compIndex, numBrainStats); - psStats = (COMPONENT_STATS *)(asBrainStats + compIndex); + ASSERT_OR_RETURN(nullptr, compIndex < asBrainStats.size(), "Invalid range referenced for numBrainStats, %d > %zu", compIndex, asBrainStats.size()); + psStats = (COMPONENT_STATS *)(&asBrainStats[compIndex]); break; case DROID_SENSOR: compIndex = psTemplate->asParts[COMP_SENSOR]; - ASSERT_OR_RETURN(nullptr, compIndex < numSensorStats, "Invalid range referenced for numSensorStats, %d > %d", compIndex, numSensorStats); - psStats = (COMPONENT_STATS *)(asSensorStats + compIndex); + ASSERT_OR_RETURN(nullptr, compIndex < asSensorStats.size(), "Invalid range referenced for numSensorStats, %d > %zu", compIndex, asSensorStats.size()); + psStats = (COMPONENT_STATS *)(&asSensorStats[compIndex]); break; case DROID_ECM: compIndex = psTemplate->asParts[COMP_ECM]; - ASSERT_OR_RETURN(nullptr, compIndex < numECMStats, "Invalid range referenced for numECMStats, %d > %d", compIndex, numECMStats); - psStats = (COMPONENT_STATS *)(asECMStats + compIndex); + ASSERT_OR_RETURN(nullptr, compIndex < asECMStats.size(), "Invalid range referenced for numECMStats, %d > %zu", compIndex, asECMStats.size()); + psStats = (COMPONENT_STATS *)(&asECMStats[compIndex]); break; case DROID_CONSTRUCT: case DROID_CYBORG_CONSTRUCT: compIndex = psTemplate->asParts[COMP_CONSTRUCT]; - ASSERT_OR_RETURN(nullptr, compIndex < numConstructStats, "Invalid range referenced for numConstructStats, %d > %d", compIndex, numConstructStats); - psStats = (COMPONENT_STATS *)(asConstructStats + compIndex); + ASSERT_OR_RETURN(nullptr, compIndex < asConstructStats.size(), "Invalid range referenced for numConstructStats, %d > %zu", compIndex, asConstructStats.size()); + psStats = (COMPONENT_STATS *)(&asConstructStats[compIndex]); break; case DROID_REPAIR: case DROID_CYBORG_REPAIR: compIndex = psTemplate->asParts[COMP_REPAIRUNIT]; - ASSERT_OR_RETURN(nullptr, compIndex < numRepairStats, "Invalid range referenced for numRepairStats, %d > %d", compIndex, numRepairStats); - psStats = (COMPONENT_STATS *)(asRepairStats + compIndex); + ASSERT_OR_RETURN(nullptr, compIndex < asRepairStats.size(), "Invalid range referenced for numRepairStats, %d > %zu", compIndex, asRepairStats.size()); + psStats = (COMPONENT_STATS *)(&asRepairStats[compIndex]); break; case DROID_WEAPON: case DROID_PERSON: @@ -1288,8 +1288,8 @@ intChooseSystemStats(DROID_TEMPLATE *psTemplate) case DROID_CYBORG_SUPER: case DROID_DEFAULT: compIndex = psTemplate->asWeaps[0]; - ASSERT_OR_RETURN(nullptr, compIndex < numWeaponStats, "Invalid range referenced for numWeaponStats, %d > %d", compIndex, numWeaponStats); - psStats = (COMPONENT_STATS *)(asWeaponStats + compIndex); + ASSERT_OR_RETURN(nullptr, compIndex < asWeaponStats.size(), "Invalid range referenced for numWeaponStats, %d > %zu", compIndex, asWeaponStats.size()); + psStats = (COMPONENT_STATS *)(&asWeaponStats[compIndex]); break; default: debug(LOG_ERROR, "unrecognised droid type"); @@ -1366,8 +1366,8 @@ const char *GetDefaultTemplateName(DROID_TEMPLATE *psTemplate) } compIndex = psTemplate->asParts[COMP_BODY]; - ASSERT_OR_RETURN("", compIndex < numBodyStats, "Invalid range referenced for numBodyStats, %d > %d", compIndex, numBodyStats); - psStats = (COMPONENT_STATS *)(asBodyStats + compIndex); + ASSERT_OR_RETURN("", compIndex < asBodyStats.size(), "Invalid range referenced for numBodyStats, %d > %zu", compIndex, asBodyStats.size()); + psStats = (COMPONENT_STATS *)(&asBodyStats[compIndex]); if (psTemplate->asParts[COMP_BODY] != 0) { checkStringLength(aCurrName, getLocalizedStatsName(psStats)); @@ -1376,8 +1376,8 @@ const char *GetDefaultTemplateName(DROID_TEMPLATE *psTemplate) } compIndex = psTemplate->asParts[COMP_PROPULSION]; - ASSERT_OR_RETURN("", compIndex < numPropulsionStats, "Invalid range referenced for numPropulsionStats, %d > %d", compIndex, numPropulsionStats); - psStats = (COMPONENT_STATS *)(asPropulsionStats + compIndex); + ASSERT_OR_RETURN("", compIndex < asPropulsionStats.size(), "Invalid range referenced for numPropulsionStats, %d > %zu", compIndex, asPropulsionStats.size()); + psStats = (COMPONENT_STATS *)(&asPropulsionStats[compIndex]); if (psTemplate->asParts[COMP_PROPULSION] != 0) { checkStringLength(aCurrName, getLocalizedStatsName(psStats)); @@ -1413,10 +1413,10 @@ static void intSetDesignStats(DROID_TEMPLATE *psTemplate) intSetSystemForm(psStats); /* Set the body stats */ - intSetBodyStats(asBodyStats + psTemplate->asParts[COMP_BODY]); + intSetBodyStats(&asBodyStats[psTemplate->asParts[COMP_BODY]]); /* Set the propulsion stats */ - intSetPropulsionForm(asPropulsionStats + psTemplate->asParts[COMP_PROPULSION]); + intSetPropulsionForm(&asPropulsionStats[psTemplate->asParts[COMP_PROPULSION]]); /* Set the name in the edit box */ intSetEditBoxTextFromTemplate(psTemplate); @@ -1616,7 +1616,7 @@ static bool intSetSystemForm(COMPONENT_STATS *psStats) sBarInit.pTip = _("Build Points"); sBarInit.iRange = findMax( repairIterator(), - [=](COMPONENT_STATS &stats) { return repairPoints((REPAIR_STATS *)&stats, selectedPlayer); } + [=](COMPONENT_STATS &stats) { return repairPoints((REPAIR_STATS&)stats, selectedPlayer); } ); systemForm->attach(std::make_shared(&sBarInit)); @@ -2030,7 +2030,7 @@ static bool intAddComponentButtons(ListTabWidget *compList, ComponentIterator co //check if the current Template propulsion has been set if (sCurrDesign.asParts[COMP_PROPULSION]) { - PROPULSION_STATS *psPropStats = asPropulsionStats + sCurrDesign.asParts[COMP_PROPULSION]; + PROPULSION_STATS *psPropStats = &asPropulsionStats[sCurrDesign.asParts[COMP_PROPULSION]]; ASSERT_OR_RETURN(false, psPropStats != nullptr, "invalid propulsion stats pointer"); bVTOL |= asPropulsionTypes[psPropStats->propulsionType].travel == AIR; @@ -2263,7 +2263,7 @@ static void intSetSensorStats(SENSOR_STATS *psStats) ASSERT_OR_RETURN(, psStats->hasType(STAT_SENSOR), "stats have wrong type"); /* range */ - widgSetBarSize(psWScreen, IDDES_SENSORRANGE, sensorRange(psStats, selectedPlayer)); + widgSetBarSize(psWScreen, IDDES_SENSORRANGE, sensorRange(*psStats, selectedPlayer)); /* weight */ widgSetBarSize(psWScreen, IDDES_SYSTEMSWEIGHT, psStats->weight); } @@ -2277,7 +2277,7 @@ static void intSetSensorShadowStats(SENSOR_STATS *psStats) { /* range */ widgSetMinorBarSize(psWScreen, IDDES_SENSORRANGE, - sensorRange(psStats, (UBYTE)selectedPlayer)); + sensorRange(*psStats, (UBYTE)selectedPlayer)); widgSetMinorBarSize(psWScreen, IDDES_SYSTEMSWEIGHT, psStats->weight); } @@ -2297,7 +2297,7 @@ static void intSetECMStats(ECM_STATS *psStats) ASSERT_OR_RETURN(, psStats->hasType(STAT_ECM), "stats have wrong type"); /* range */ - widgSetBarSize(psWScreen, IDDES_ECMPOWER, ecmRange(psStats, selectedPlayer)); + widgSetBarSize(psWScreen, IDDES_ECMPOWER, ecmRange(*psStats, selectedPlayer)); /* weight */ widgSetBarSize(psWScreen, IDDES_SYSTEMSWEIGHT, psStats->weight); } @@ -2310,7 +2310,7 @@ static void intSetECMShadowStats(ECM_STATS *psStats) if (psStats) { /* power */ - widgSetMinorBarSize(psWScreen, IDDES_ECMPOWER, ecmRange(psStats, (UBYTE)selectedPlayer)); + widgSetMinorBarSize(psWScreen, IDDES_ECMPOWER, ecmRange(*psStats, (UBYTE)selectedPlayer)); /* weight */ widgSetMinorBarSize(psWScreen, IDDES_SYSTEMSWEIGHT, psStats->weight); } @@ -2331,7 +2331,7 @@ static void intSetConstructStats(CONSTRUCT_STATS *psStats) /* power */ widgSetBarSize(psWScreen, IDDES_CONSTPOINTS, - constructorPoints(psStats, (UBYTE)selectedPlayer)); + constructorPoints(*psStats, (UBYTE)selectedPlayer)); /* weight */ widgSetBarSize(psWScreen, IDDES_SYSTEMSWEIGHT, psStats->weight); } @@ -2346,7 +2346,7 @@ static void intSetConstructShadowStats(CONSTRUCT_STATS *psStats) { /* power */ widgSetMinorBarSize(psWScreen, IDDES_CONSTPOINTS, - constructorPoints(psStats, (UBYTE)selectedPlayer)); + constructorPoints(*psStats, (UBYTE)selectedPlayer)); /* weight */ widgSetMinorBarSize(psWScreen, IDDES_SYSTEMSWEIGHT, psStats->weight); } @@ -2366,7 +2366,7 @@ static void intSetRepairStats(REPAIR_STATS *psStats) /* power */ widgSetBarSize(psWScreen, IDDES_REPAIRPOINTS, - repairPoints(psStats, (UBYTE)selectedPlayer)); + repairPoints(*psStats, (UBYTE)selectedPlayer)); /* weight */ widgSetBarSize(psWScreen, IDDES_SYSTEMSWEIGHT, psStats->weight); } @@ -2381,7 +2381,7 @@ static void intSetRepairShadowStats(REPAIR_STATS *psStats) { /* power */ widgSetMinorBarSize(psWScreen, IDDES_REPAIRPOINTS, - repairPoints(psStats, (UBYTE)selectedPlayer)); + repairPoints(*psStats, (UBYTE)selectedPlayer)); /* weight */ widgSetMinorBarSize(psWScreen, IDDES_SYSTEMSWEIGHT, psStats->weight); } @@ -2401,11 +2401,11 @@ static void intSetWeaponStats(WEAPON_STATS *psStats) ASSERT_OR_RETURN(, psStats->hasType(STAT_WEAPON), "stats have wrong type"); /* range */ - widgSetBarSize(psWScreen, IDDES_WEAPRANGE, proj_GetLongRange(psStats, selectedPlayer)); + widgSetBarSize(psWScreen, IDDES_WEAPRANGE, proj_GetLongRange(*psStats, selectedPlayer)); /* rate of fire */ - widgSetBarSize(psWScreen, IDDES_WEAPROF, weaponROF(psStats, (SBYTE)selectedPlayer)); + widgSetBarSize(psWScreen, IDDES_WEAPROF, weaponROF(*psStats, (SBYTE)selectedPlayer)); /* damage */ - widgSetBarSize(psWScreen, IDDES_WEAPDAMAGE, (UWORD)weaponDamage(psStats, + widgSetBarSize(psWScreen, IDDES_WEAPDAMAGE, (UWORD)weaponDamage(*psStats, (UBYTE)selectedPlayer)); /* weight */ widgSetBarSize(psWScreen, IDDES_SYSTEMSWEIGHT, psStats->weight); @@ -2419,12 +2419,12 @@ static void intSetWeaponShadowStats(WEAPON_STATS *psStats) if (psStats) { /* range */ - widgSetMinorBarSize(psWScreen, IDDES_WEAPRANGE, proj_GetLongRange(psStats, selectedPlayer)); + widgSetMinorBarSize(psWScreen, IDDES_WEAPRANGE, proj_GetLongRange(*psStats, selectedPlayer)); /* rate of fire */ - widgSetMinorBarSize(psWScreen, IDDES_WEAPROF, weaponROF(psStats, (SBYTE)selectedPlayer)); + widgSetMinorBarSize(psWScreen, IDDES_WEAPROF, weaponROF(*psStats, (SBYTE)selectedPlayer)); /* damage */ widgSetMinorBarSize(psWScreen, IDDES_WEAPDAMAGE, (UWORD)weaponDamage( - psStats, (UBYTE)selectedPlayer)); + *psStats, (UBYTE)selectedPlayer)); /* weight */ widgSetMinorBarSize(psWScreen, IDDES_SYSTEMSWEIGHT, psStats->weight); } @@ -2451,11 +2451,11 @@ static void intSetBodyStats(BODY_STATS *psStats) /* armour */ //do kinetic armour - widgSetBarSize(psWScreen, IDDES_BODYARMOUR_K, bodyArmour(psStats, selectedPlayer, WC_KINETIC)); + widgSetBarSize(psWScreen, IDDES_BODYARMOUR_K, bodyArmour(*psStats, selectedPlayer, WC_KINETIC)); //do heat armour - widgSetBarSize(psWScreen, IDDES_BODYARMOUR_H, bodyArmour(psStats, selectedPlayer, WC_HEAT)); + widgSetBarSize(psWScreen, IDDES_BODYARMOUR_H, bodyArmour(*psStats, selectedPlayer, WC_HEAT)); /* power */ - widgSetBarSize(psWScreen, IDDES_BODYPOWER, bodyPower(psStats, selectedPlayer)); + widgSetBarSize(psWScreen, IDDES_BODYPOWER, bodyPower(*psStats, selectedPlayer)); /* weight */ widgSetBarSize(psWScreen, IDDES_BODYWEIGHT, psStats->weight); @@ -2475,11 +2475,11 @@ static void intSetBodyShadowStats(BODY_STATS *psStats) if (psStats) { /* armour - kinetic*/ - widgSetMinorBarSize(psWScreen, IDDES_BODYARMOUR_K, bodyArmour(psStats, selectedPlayer, WC_KINETIC)); + widgSetMinorBarSize(psWScreen, IDDES_BODYARMOUR_K, bodyArmour(*psStats, selectedPlayer, WC_KINETIC)); //armour - heat - widgSetMinorBarSize(psWScreen, IDDES_BODYARMOUR_H, bodyArmour(psStats, selectedPlayer, WC_HEAT)); + widgSetMinorBarSize(psWScreen, IDDES_BODYARMOUR_H, bodyArmour(*psStats, selectedPlayer, WC_HEAT)); /* power */ - widgSetMinorBarSize(psWScreen, IDDES_BODYPOWER, bodyPower(psStats, selectedPlayer)); + widgSetMinorBarSize(psWScreen, IDDES_BODYPOWER, bodyPower(*psStats, selectedPlayer)); /* weight */ widgSetMinorBarSize(psWScreen, IDDES_BODYWEIGHT, psStats->weight); } @@ -2531,7 +2531,7 @@ static void setTemplateStat(DROID_TEMPLATE *psTemplate, COMPONENT_STATS *psStats { case COMP_BODY: { auto stats = (BODY_STATS *)psStats; - psTemplate->asParts[COMP_BODY] = stats - asBodyStats; + psTemplate->asParts[COMP_BODY] = stats - asBodyStats.data(); if (!intCheckValidWeaponForProp(psTemplate)) { clearTurret(); @@ -2545,8 +2545,8 @@ static void setTemplateStat(DROID_TEMPLATE *psTemplate, COMPONENT_STATS *psStats case COMP_BRAIN: { auto stats = (BRAIN_STATS *)psStats; clearTurret(); - psTemplate->asParts[COMP_BRAIN] = stats - asBrainStats; - psTemplate->asWeaps[0] = stats->psWeaponStat - asWeaponStats; + psTemplate->asParts[COMP_BRAIN] = stats - asBrainStats.data(); + psTemplate->asWeaps[0] = stats->psWeaponStat - asWeaponStats.data(); psTemplate->numWeaps = 1; break; } @@ -2557,29 +2557,29 @@ static void setTemplateStat(DROID_TEMPLATE *psTemplate, COMPONENT_STATS *psStats { clearTurret(); } - psTemplate->asParts[COMP_PROPULSION] = stats - asPropulsionStats; + psTemplate->asParts[COMP_PROPULSION] = stats - asPropulsionStats.data(); break; } case COMP_REPAIRUNIT: clearTurret(); - psTemplate->asParts[COMP_REPAIRUNIT] = (REPAIR_STATS *)psStats - asRepairStats; + psTemplate->asParts[COMP_REPAIRUNIT] = (REPAIR_STATS *)psStats - asRepairStats.data(); break; case COMP_ECM: clearTurret(); - psTemplate->asParts[COMP_ECM] = (ECM_STATS *)psStats - asECMStats; + psTemplate->asParts[COMP_ECM] = (ECM_STATS *)psStats - asECMStats.data(); break; case COMP_SENSOR: clearTurret(); - psTemplate->asParts[COMP_SENSOR] = (SENSOR_STATS *)psStats - asSensorStats; + psTemplate->asParts[COMP_SENSOR] = (SENSOR_STATS *)psStats - asSensorStats.data(); break; case COMP_CONSTRUCT: clearTurret(); - psTemplate->asParts[COMP_CONSTRUCT] = (CONSTRUCT_STATS *)psStats - asConstructStats; + psTemplate->asParts[COMP_CONSTRUCT] = (CONSTRUCT_STATS *)psStats - asConstructStats.data(); break; case COMP_WEAPON: { clearNonWeapons(); int i = desCompMode == IDES_TURRET_A? 1 : desCompMode == IDES_TURRET_B? 2 : 0; - psTemplate->asWeaps[i] = (WEAPON_STATS *)psStats - asWeaponStats; + psTemplate->asWeaps[i] = (WEAPON_STATS *)psStats - asWeaponStats.data(); psTemplate->numWeaps = std::max(psTemplate->numWeaps, i + 1); break; } @@ -2650,7 +2650,7 @@ static UDWORD intCalcSpeed(TYPE_OF_TERRAIN type, PROPULSION_STATS *psProp) return 0; } } - UDWORD droidSpeed = calcDroidSpeed(calcDroidBaseSpeed(&psTempl, weight, selectedPlayer), type, psProp - asPropulsionStats, 0); + UDWORD droidSpeed = calcDroidSpeed(calcDroidBaseSpeed(&psTempl, weight, selectedPlayer), type, psProp - asPropulsionStats.data(), 0); return droidSpeed; } @@ -2796,13 +2796,13 @@ bool intValidTemplate(DROID_TEMPLATE *psTempl, const char *newName, bool complai { ASSERT_PLAYER_OR_RETURN(false, player); - ASSERT_OR_RETURN(false, psTempl->asParts[COMP_BODY] < numBodyStats, "Invalid range referenced for numBodyStats, %d > %d", psTempl->asParts[COMP_BODY], numBodyStats); - ASSERT_OR_RETURN(false, psTempl->asParts[COMP_BRAIN] < numBrainStats, "Invalid range referenced for numBrainStats, %d > %d", psTempl->asParts[COMP_BRAIN], numBrainStats); - ASSERT_OR_RETURN(false, psTempl->asParts[COMP_PROPULSION] < numPropulsionStats, "Invalid range referenced for numPropulsionStats, %d > %d", psTempl->asParts[COMP_PROPULSION], numPropulsionStats); - ASSERT_OR_RETURN(false, psTempl->asParts[COMP_REPAIRUNIT] < numRepairStats, "Invalid range referenced for numRepairStats, %d > %d", psTempl->asParts[COMP_REPAIRUNIT], numRepairStats); - ASSERT_OR_RETURN(false, psTempl->asParts[COMP_ECM] < numECMStats, "Invalid range referenced for numECMStats, %d > %d", psTempl->asParts[COMP_ECM], numECMStats); - ASSERT_OR_RETURN(false, psTempl->asParts[COMP_SENSOR] < numSensorStats, "Invalid range referenced for numSensorStats, %d > %d", psTempl->asParts[COMP_SENSOR], numSensorStats); - ASSERT_OR_RETURN(false, psTempl->asParts[COMP_CONSTRUCT] < numConstructStats, "Invalid range referenced for numConstructStats, %d > %d", psTempl->asParts[COMP_CONSTRUCT], numConstructStats); + ASSERT_OR_RETURN(false, psTempl->asParts[COMP_BODY] < asBodyStats.size(), "Invalid range referenced for numBodyStats, %d > %zu", psTempl->asParts[COMP_BODY], asBodyStats.size()); + ASSERT_OR_RETURN(false, psTempl->asParts[COMP_BRAIN] < asBrainStats.size(), "Invalid range referenced for numBrainStats, %d > %zu", psTempl->asParts[COMP_BRAIN], asBrainStats.size()); + ASSERT_OR_RETURN(false, psTempl->asParts[COMP_PROPULSION] < asPropulsionStats.size(), "Invalid range referenced for numPropulsionStats, %d > %zu", psTempl->asParts[COMP_PROPULSION], asPropulsionStats.size()); + ASSERT_OR_RETURN(false, psTempl->asParts[COMP_REPAIRUNIT] < asRepairStats.size(), "Invalid range referenced for numRepairStats, %d > %zu", psTempl->asParts[COMP_REPAIRUNIT], asRepairStats.size()); + ASSERT_OR_RETURN(false, psTempl->asParts[COMP_ECM] < asECMStats.size(), "Invalid range referenced for numECMStats, %d > %zu", psTempl->asParts[COMP_ECM], asECMStats.size()); + ASSERT_OR_RETURN(false, psTempl->asParts[COMP_SENSOR] < asSensorStats.size(), "Invalid range referenced for numSensorStats, %d > %zu", psTempl->asParts[COMP_SENSOR], asSensorStats.size()); + ASSERT_OR_RETURN(false, psTempl->asParts[COMP_CONSTRUCT] < asConstructStats.size(), "Invalid range referenced for numConstructStats, %d > %zu", psTempl->asParts[COMP_CONSTRUCT], asConstructStats.size()); code_part level = complain ? LOG_ERROR : LOG_NEVER; int bodysize = asBodyStats[psTempl->asParts[COMP_BODY]].size; @@ -2811,7 +2811,7 @@ bool intValidTemplate(DROID_TEMPLATE *psTempl, const char *newName, bool complai if (psTempl->asParts[COMP_BRAIN] != 0) { psTempl->numWeaps = 1; - psTempl->asWeaps[0] = asBrainStats[psTempl->asParts[COMP_BRAIN]].psWeaponStat - asWeaponStats; + psTempl->asWeaps[0] = asBrainStats[psTempl->asParts[COMP_BRAIN]].psWeaponStat - asWeaponStats.data(); } /* Check all the components have been set */ @@ -2842,7 +2842,7 @@ bool intValidTemplate(DROID_TEMPLATE *psTempl, const char *newName, bool complai // Check the weapons for (int i = 0; i < psTempl->numWeaps; i++) { - ASSERT_OR_RETURN(false, psTempl->asWeaps[i] < numWeaponStats, "Invalid range referenced for numWeaponStats, %d > %d", psTempl->asWeaps[i], numWeaponStats); + ASSERT_OR_RETURN(false, psTempl->asWeaps[i] < asWeaponStats.size(), "Invalid range referenced for numWeaponStats, %d > %zu", psTempl->asWeaps[i], asWeaponStats.size()); int weaponSize = asWeaponStats[psTempl->asWeaps[i]].weaponSize; @@ -3230,7 +3230,7 @@ void intProcessDesign(UDWORD id) desCompID = id; /* Update the propulsion stats as the droid weight will have changed */ - intSetPropulsionStats(asPropulsionStats + sCurrDesign.asParts[COMP_PROPULSION]); + intSetPropulsionStats(&asPropulsionStats[sCurrDesign.asParts[COMP_PROPULSION]]); /*Update the Power bar stats as the power to build will have changed */ intSetDesignPower(&sCurrDesign); @@ -3569,7 +3569,7 @@ void intProcessDesign(UDWORD id) case IDES_SYSTEM: case IDES_TURRET: - if ((asBodyStats + sCurrDesign.asParts[COMP_BODY])->weaponSlots > 1 && + if (asBodyStats[sCurrDesign.asParts[COMP_BODY]].weaponSlots > 1 && sCurrDesign.numWeaps == 1 && sCurrDesign.asParts[COMP_BRAIN] == 0) { debug(LOG_GUI, "intProcessDesign: First weapon selected, doing next."); @@ -3582,7 +3582,7 @@ void intProcessDesign(UDWORD id) } break; case IDES_TURRET_A: - if ((asBodyStats + sCurrDesign.asParts[COMP_BODY])->weaponSlots > 2) + if (asBodyStats[sCurrDesign.asParts[COMP_BODY]].weaponSlots > 2) { debug(LOG_GUI, "intProcessDesign: Second weapon selected, doing next."); intSetDesignMode(IDES_TURRET_B); @@ -3847,8 +3847,8 @@ void runTemplateShadowStats(UDWORD id) if (psTempl && psTempl != &sCurrDesign) { /* Now set the bar graphs for the stats */ - intSetBodyShadowStats(asBodyStats + psTempl->asParts[COMP_BODY]); - intSetPropulsionShadowStats(asPropulsionStats + psTempl->asParts[COMP_PROPULSION]); + intSetBodyShadowStats(&asBodyStats[psTempl->asParts[COMP_BODY]]); + intSetPropulsionShadowStats(&asPropulsionStats[psTempl->asParts[COMP_PROPULSION]]); //only set the system shadow bar if the same type of droid COMPONENT_STATS *psStats = nullptr; DROID_TYPE templType = droidTemplateType(psTempl); @@ -3859,27 +3859,27 @@ void runTemplateShadowStats(UDWORD id) { case DROID_WEAPON: compIndex = psTempl->asWeaps[0]; - ASSERT_OR_RETURN(, compIndex < numWeaponStats, "Invalid range referenced for numWeaponStats, %d > %d", compIndex, numWeaponStats); + ASSERT_OR_RETURN(, compIndex < asWeaponStats.size(), "Invalid range referenced for numWeaponStats, %d > %zu", compIndex, asWeaponStats.size()); psStats = &asWeaponStats[compIndex]; break; case DROID_SENSOR: compIndex = psTempl->asParts[COMP_SENSOR]; - ASSERT_OR_RETURN(, compIndex < numSensorStats, "Invalid range referenced for numSensorStats, %d > %d", compIndex, numSensorStats); + ASSERT_OR_RETURN(, compIndex < asSensorStats.size(), "Invalid range referenced for numSensorStats, %d > %zu", compIndex, asSensorStats.size()); psStats = &asSensorStats[compIndex]; break; case DROID_ECM: compIndex = psTempl->asParts[COMP_ECM]; - ASSERT_OR_RETURN(, compIndex < numECMStats, "Invalid range referenced for numECMStats, %d > %d", compIndex, numECMStats); + ASSERT_OR_RETURN(, compIndex < asECMStats.size(), "Invalid range referenced for numECMStats, %d > %zu", compIndex, asECMStats.size()); psStats = &asECMStats[compIndex]; break; case DROID_CONSTRUCT: compIndex = psTempl->asParts[COMP_CONSTRUCT]; - ASSERT_OR_RETURN(, compIndex < numConstructStats, "Invalid range referenced for numConstructStats, %d > %d", compIndex, numConstructStats); + ASSERT_OR_RETURN(, compIndex < asConstructStats.size(), "Invalid range referenced for numConstructStats, %d > %zu", compIndex, asConstructStats.size()); psStats = &asConstructStats[compIndex]; break; case DROID_REPAIR: compIndex = psTempl->asParts[COMP_REPAIRUNIT]; - ASSERT_OR_RETURN(, compIndex < numRepairStats, "Invalid range referenced for numRepairStats, %d > %d", compIndex, numRepairStats); + ASSERT_OR_RETURN(, compIndex < asRepairStats.size(), "Invalid range referenced for numRepairStats, %d > %zu", compIndex, asRepairStats.size()); psStats = &asRepairStats[compIndex]; break; default: diff --git a/src/display.cpp b/src/display.cpp index a351910d0ed..5ea1f21b57d 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -1722,7 +1722,7 @@ static void dealWithLMBDroid(DROID *psDroid, SELECTION_TYPE selection) if ((psCurr->droidType == DROID_WEAPON) && (psCurr->selected) && (psCurr->asWeaps[0].nStat > 0) && - ((!proj_Direct(asWeaponStats + psCurr->asWeaps[0].nStat)) || + ((!proj_Direct(getWeaponStats(psCurr, 0))) || psCurr->isVtol()) && droidSensorDroidWeapon((BASE_OBJECT *)psDroid, psCurr)) { @@ -2608,7 +2608,7 @@ static SELECTION_TYPE establishSelection(UDWORD _selectedPlayer) switch (psDominant->droidType) { case DROID_WEAPON: - if (proj_Direct(asWeaponStats + psDominant->asWeaps[0].nStat)) + if (proj_Direct(getWeaponStats(psDominant, 0))) { selectionClass = SC_DROID_DIRECT; } diff --git a/src/display3d.cpp b/src/display3d.cpp index b3638ba0f86..4bfd4169149 100644 --- a/src/display3d.cpp +++ b/src/display3d.cpp @@ -1771,7 +1771,7 @@ bool clipDroidOnScreen(DROID *psDroid, const glm::mat4 &perspectiveViewModelMatr { /* Get its absolute dimensions */ // NOTE: This only takes into account body, but is "good enough" - const BODY_STATS *psBStats = asBodyStats + psDroid->asBits[COMP_BODY]; + const BODY_STATS *psBStats = getBodyStats(psDroid); const iIMDShape * pIMD = (psBStats != nullptr) ? psBStats->pIMD->displayModel() : nullptr; return clipShapeOnScreen(pIMD, perspectiveViewModelMatrix, overdrawScreenPoints); @@ -3751,7 +3751,7 @@ static void drawDroidCmndNo(DROID *psDroid) void calcScreenCoords(DROID *psDroid, const glm::mat4 &perspectiveViewMatrix) { /* Get it's absolute dimensions */ - const BODY_STATS *psBStats = asBodyStats + psDroid->asBits[COMP_BODY]; + const BODY_STATS *psBStats = getBodyStats(psDroid); Vector3i origin; Vector2i center(0, 0); int wsRadius = 22; // World space radius, 22 = magic minimum @@ -4220,8 +4220,8 @@ static void showWeaponRange(BASE_OBJECT *psObj) { DROID *psDroid = (DROID *)psObj; const int compIndex = psDroid->asWeaps[0].nStat; // weapon_slot - ASSERT_OR_RETURN(, compIndex < numWeaponStats, "Invalid range referenced for numWeaponStats, %d > %d", compIndex, numWeaponStats); - psStats = asWeaponStats + compIndex; + ASSERT_OR_RETURN(, compIndex < asWeaponStats.size(), "Invalid range referenced for numWeaponStats, %d > %zu", compIndex, asWeaponStats.size()); + psStats = &asWeaponStats[compIndex]; } else { @@ -4232,8 +4232,8 @@ static void showWeaponRange(BASE_OBJECT *psObj) } psStats = psStruct->pStructureType->psWeapStat[0]; } - const unsigned weaponRange = proj_GetLongRange(psStats, psObj->player); - const unsigned minRange = proj_GetMinRange(psStats, psObj->player); + const unsigned weaponRange = proj_GetLongRange(*psStats, psObj->player); + const unsigned minRange = proj_GetMinRange(*psStats, psObj->player); showEffectCircle(psObj->pos, weaponRange, 40, EFFECT_EXPLOSION, EXPLOSION_TYPE_SMALL); if (minRange > 0) { @@ -4412,7 +4412,7 @@ static void addConstructionLine(DROID *psDroid, STRUCTURE *psStructure, const gl auto deltaPlayer = Vector3f(0,0,0); auto pt0 = Vector3f(psDroid->pos.x, psDroid->pos.z + 24, -psDroid->pos.y) + deltaPlayer; - int constructPoints = constructorPoints(asConstructStats + psDroid->asBits[COMP_CONSTRUCT], psDroid->player); + int constructPoints = constructorPoints(*getConstructStats(psDroid), psDroid->player); int amount = 800 * constructPoints * (graphicsTime - psDroid->actionStarted) / GAME_TICKS_PER_SEC; Vector3i each; diff --git a/src/droid.cpp b/src/droid.cpp index 81ec3a6564e..1b5e1d7c1f0 100644 --- a/src/droid.cpp +++ b/src/droid.cpp @@ -176,7 +176,7 @@ int droidReloadBar(const BASE_OBJECT *psObj, const WEAPON *psWeap, int weapon_sl { return -1; } - psStats = asWeaponStats + psWeap->nStat; + psStats = &asWeaponStats[psWeap->nStat]; /* Justifiable only when greater than a one second reload or intra salvo time */ bSalvo = (psStats->upgrade[psObj->player].numRounds > 1); @@ -195,7 +195,7 @@ int droidReloadBar(const BASE_OBJECT *psObj, const WEAPON *psWeap, int weapon_sl else { firingStage = gameTime - psWeap->lastFired; - interval = bSalvo ? weaponReloadTime(psStats, psObj->player) : weaponFirePause(psStats, psObj->player); + interval = bSalvo ? weaponReloadTime(*psStats, psObj->player) : weaponFirePause(*psStats, psObj->player); } if (firingStage < interval && interval > 0) { @@ -247,7 +247,7 @@ void addDroidDeathAnimationEffect(DROID *psDroid) { iIMDShape *strImd = psShapeBody->objanimpie[ANIM_EVENT_DYING]->displayModel(); /* get propulsion stats */ - PROPULSION_STATS *psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + PROPULSION_STATS *psPropStats = getPropulsionStats(psDroid); if (psPropStats && psPropStats->propulsionType == PROPULSION_TYPE_PROPELLOR) { // FIXME: change when adding submarines to the game @@ -1093,7 +1093,7 @@ bool droidUpdateBuild(DROID *psDroid) } ASSERT_OR_RETURN(false, psStruct->type == OBJ_STRUCTURE, "target is not a structure"); - ASSERT_OR_RETURN(false, psDroid->asBits[COMP_CONSTRUCT] < numConstructStats, "Invalid construct pointer for unit"); + ASSERT_OR_RETURN(false, psDroid->asBits[COMP_CONSTRUCT] < asConstructStats.size(), "Invalid construct pointer for unit"); // First check the structure hasn't been completed by another droid if (psStruct->status == SS_BUILT) @@ -1120,8 +1120,7 @@ bool droidUpdateBuild(DROID *psDroid) return false; } - unsigned constructPoints = constructorPoints(asConstructStats + psDroid-> - asBits[COMP_CONSTRUCT], psDroid->player); + unsigned constructPoints = constructorPoints(*getConstructStats(psDroid), psDroid->player); unsigned pointsToAdd = constructPoints * (gameTime - psDroid->actionStarted) / GAME_TICKS_PER_SEC; @@ -1144,7 +1143,7 @@ bool droidUpdateDemolishing(DROID *psDroid) STRUCTURE *psStruct = (STRUCTURE *)psDroid->order.psObj; ASSERT_OR_RETURN(false, psStruct->type == OBJ_STRUCTURE, "target is not a structure"); - int constructRate = 5 * constructorPoints(asConstructStats + psDroid->asBits[COMP_CONSTRUCT], psDroid->player); + int constructRate = 5 * constructorPoints(*getConstructStats(psDroid), psDroid->player); int pointsToAdd = gameTimeAdjustedAverage(constructRate); structureDemolish(psStruct, psDroid, pointsToAdd); @@ -1173,12 +1172,12 @@ bool droidUpdateRestore(DROID *psDroid) ASSERT_OR_RETURN(false, psDroid->asWeaps[0].nStat > 0, "Droid doesn't have any weapons"); unsigned compIndex = psDroid->asWeaps[0].nStat; - ASSERT_OR_RETURN(false, compIndex < numWeaponStats, "Invalid range referenced for numWeaponStats, %u > %u", compIndex, numWeaponStats); + ASSERT_OR_RETURN(false, compIndex < asWeaponStats.size(), "Invalid range referenced for numWeaponStats, %u > %zu", compIndex, asWeaponStats.size()); WEAPON_STATS *psStats = &asWeaponStats[compIndex]; ASSERT_OR_RETURN(false, psStats->weaponSubClass == WSC_ELECTRONIC, "unit's weapon is not EW"); - unsigned restorePoints = calcDamage(weaponDamage(psStats, psDroid->player), + unsigned restorePoints = calcDamage(weaponDamage(*psStats, psDroid->player), psStats->weaponEffect, (BASE_OBJECT *)psStruct); unsigned pointsToAdd = restorePoints * (gameTime - psDroid->actionStarted) / @@ -1255,7 +1254,7 @@ bool droidUpdateRepair(DROID *psDroid) STRUCTURE *psStruct = (STRUCTURE *)psDroid->psActionTarget[0]; ASSERT_OR_RETURN(false, psStruct->type == OBJ_STRUCTURE, "target is not a structure"); - int iRepairRate = constructorPoints(asConstructStats + psDroid->asBits[COMP_CONSTRUCT], psDroid->player); + int iRepairRate = constructorPoints(*getConstructStats(psDroid), psDroid->player); /* add points to structure */ structureRepair(psStruct, psDroid, iRepairRate); @@ -1277,14 +1276,15 @@ static bool droidUpdateDroidRepairBase(DROID *psRepairDroid, DROID *psDroidToRep { CHECK_DROID(psRepairDroid); - int iRepairRateNumerator = repairPoints(asRepairStats + psRepairDroid->asBits[COMP_REPAIRUNIT], psRepairDroid->player); + const auto* repairStats = getRepairStats(psRepairDroid); + int iRepairRateNumerator = repairPoints(*repairStats, psRepairDroid->player); int iRepairRateDenominator = 1; //if self repair then add repair points depending on the time delay for the stat if (psRepairDroid == psDroidToRepair) { iRepairRateNumerator *= GAME_TICKS_PER_SEC; - iRepairRateDenominator *= (asRepairStats + psRepairDroid->asBits[COMP_REPAIRUNIT])->time; + iRepairRateDenominator *= repairStats->time; } int iPointsToAdd = gameTimeAdjustedAverage(iRepairRateNumerator, iRepairRateDenominator); @@ -1358,11 +1358,11 @@ DROID_TYPE droidTemplateType(const DROID_TEMPLATE *psTemplate) { type = DROID_COMMAND; } - else if ((asSensorStats + psTemplate->asParts[COMP_SENSOR])->location == LOC_TURRET) + else if (asSensorStats[psTemplate->asParts[COMP_SENSOR]].location == LOC_TURRET) { type = DROID_SENSOR; } - else if ((asECMStats + psTemplate->asParts[COMP_ECM])->location == LOC_TURRET) + else if (asECMStats[psTemplate->asParts[COMP_ECM]].location == LOC_TURRET) { type = DROID_ECM; } @@ -1370,7 +1370,7 @@ DROID_TYPE droidTemplateType(const DROID_TEMPLATE *psTemplate) { type = DROID_CONSTRUCT; } - else if ((asRepairStats + psTemplate->asParts[COMP_REPAIRUNIT])->location == LOC_TURRET) + else if (asRepairStats[psTemplate->asParts[COMP_REPAIRUNIT]].location == LOC_TURRET) { type = DROID_REPAIR; } @@ -1423,7 +1423,7 @@ static unsigned calcUpgradeSum(const uint8_t (&asParts)[DROID_MAXCOMP], int numW // asWeaps[i] > 0 check only needed for droids, not templates. if (asWeaps[i] > 0) { - ASSERT(asWeaps[i] < numWeaponStats, "Invalid weapon stat index (%" PRIu32 ", numWeaponStats: %" PRIu32 ") (player: %d)", asWeaps[i], numWeaponStats, player); + ASSERT(asWeaps[i] < asWeaponStats.size(), "Invalid weapon stat index (%" PRIu32 ", numWeaponStats: %zu) (player: %d)", asWeaps[i], asWeaponStats.size(), player); sum += func(asWeaponStats[asWeaps[i]].upgrade[player]); } } @@ -1526,7 +1526,7 @@ static UDWORD calcDroidBaseBody(DROID *psDroid) UDWORD calcDroidBaseSpeed(const DROID_TEMPLATE *psTemplate, UDWORD weight, UBYTE player) { unsigned speed = asPropulsionTypes[asPropulsionStats[psTemplate->asParts[COMP_PROPULSION]].propulsionType].powerRatioMult * - bodyPower(&asBodyStats[psTemplate->asParts[COMP_BODY]], player) / MAX(1, weight); + bodyPower(asBodyStats[psTemplate->asParts[COMP_BODY]], player) / MAX(1, weight); // reduce the speed of medium/heavy VTOLs if (asPropulsionStats[psTemplate->asParts[COMP_PROPULSION]].propulsionType == PROPULSION_TYPE_LIFT) @@ -1783,7 +1783,7 @@ void droidSetBits(const DROID_TEMPLATE *pTemplate, DROID *psDroid) if (inc < pTemplate->numWeaps) { psDroid->asWeaps[inc].nStat = pTemplate->asWeaps[inc]; - psDroid->asWeaps[inc].ammo = (asWeaponStats + psDroid->asWeaps[inc].nStat)->upgrade[psDroid->player].numRounds; + psDroid->asWeaps[inc].ammo = getWeaponStats(psDroid, inc)->upgrade[psDroid->player].numRounds; } psDroid->asWeaps[inc].usedAmmo = 0; } @@ -2211,8 +2211,8 @@ struct rankMap unsigned int getDroidLevel(unsigned int experience, uint8_t player, uint8_t brainComponent) { unsigned int numKills = experience / 65536; - ASSERT_OR_RETURN(0, brainComponent < numBrainStats, "Invalid brainComponent: %u", (unsigned)brainComponent); - const BRAIN_STATS *psStats = asBrainStats + brainComponent; + ASSERT_OR_RETURN(0, brainComponent < asBrainStats.size(), "Invalid brainComponent: %u", (unsigned)brainComponent); + const BRAIN_STATS *psStats = &asBrainStats[brainComponent]; ASSERT_OR_RETURN(0, player < MAX_PLAYERS, "Invalid player: %u", (unsigned)player); auto &vec = psStats->upgrade[player].rankThresholds; ASSERT_OR_RETURN(0, vec.size() > 0, "rankThreshold was empty?"); @@ -2467,7 +2467,7 @@ static bool ThreatInRange(SDWORD player, SDWORD range, SDWORD rangeX, SDWORD ran } //if VTOLs are excluded, skip them - if (!bVTOLs && ((asPropulsionStats[psDroid->asBits[COMP_PROPULSION]].propulsionType == PROPULSION_TYPE_LIFT) || psDroid->isTransporter())) + if (!bVTOLs && ((getPropulsionStats(psDroid)->propulsionType == PROPULSION_TYPE_LIFT) || psDroid->isTransporter())) { continue; } @@ -2693,7 +2693,7 @@ bool electronicDroid(const DROID *psDroid) CHECK_DROID(psDroid); //use slot 0 for now - if (psDroid->numWeaps > 0 && asWeaponStats[psDroid->asWeaps[0].nStat].weaponSubClass == WSC_ELECTRONIC) + if (psDroid->numWeaps > 0 && getWeaponStats(psDroid, 0)->weaponSubClass == WSC_ELECTRONIC) { return true; } @@ -2777,14 +2777,14 @@ bool isTransporter(DROID_TEMPLATE const *psTemplate) //access functions for vtols bool DROID::isVtol() const { - return asPropulsionStats[asBits[COMP_PROPULSION]].propulsionType == PROPULSION_TYPE_LIFT + return getPropulsionStats(this)->propulsionType == PROPULSION_TYPE_LIFT && !isTransporter(); } /* returns true if the droid has lift propulsion and is moving */ bool DROID::isFlying() const { - return (asPropulsionStats + asBits[COMP_PROPULSION])->propulsionType == PROPULSION_TYPE_LIFT + return getPropulsionStats(this)->propulsionType == PROPULSION_TYPE_LIFT && (sMove.Status != MOVEINACTIVE || isTransporter()); } @@ -2804,7 +2804,7 @@ bool vtolEmpty(const DROID *psDroid) for (int i = 0; i < psDroid->numWeaps; i++) { - if (asWeaponStats[psDroid->asWeaps[i].nStat].vtolAttackRuns > 0 && + if (getWeaponStats(psDroid, i)->vtolAttackRuns > 0 && psDroid->asWeaps[i].usedAmmo < getNumAttackRuns(psDroid, i)) { return false; @@ -2830,7 +2830,7 @@ bool vtolFull(const DROID *psDroid) for (int i = 0; i < psDroid->numWeaps; i++) { - if (asWeaponStats[psDroid->asWeaps[i].nStat].vtolAttackRuns > 0 && + if (getWeaponStats(psDroid, i)->vtolAttackRuns > 0 && psDroid->asWeaps[i].usedAmmo > 0) { return false; @@ -2959,13 +2959,14 @@ bool allVtolsRearmed(const DROID *psDroid) UWORD getNumAttackRuns(const DROID *psDroid, int weapon_slot) { ASSERT_OR_RETURN(0, psDroid->isVtol(), "not a VTOL Droid"); + const auto* weaponStats = getWeaponStats(psDroid, weapon_slot); // if weapon is a salvo weapon, then number of shots that can be fired = vtolAttackRuns * numRounds - if (asWeaponStats[psDroid->asWeaps[weapon_slot].nStat].upgrade[psDroid->player].reloadTime) + if (weaponStats->upgrade[psDroid->player].reloadTime) { - return asWeaponStats[psDroid->asWeaps[weapon_slot].nStat].upgrade[psDroid->player].numRounds - * asWeaponStats[psDroid->asWeaps[weapon_slot].nStat].vtolAttackRuns; + return weaponStats->upgrade[psDroid->player].numRounds + * weaponStats->vtolAttackRuns; } - return asWeaponStats[psDroid->asWeaps[weapon_slot].nStat].vtolAttackRuns; + return weaponStats->vtolAttackRuns; } /*Checks a vtol for being fully armed and fully repaired to see if ready to @@ -2998,7 +2999,7 @@ bool vtolHappy(const DROID *psDroid) //check full complement of ammo for (int i = 0; i < psDroid->numWeaps; ++i) { - if (asWeaponStats[psDroid->asWeaps[i].nStat].vtolAttackRuns > 0 + if (getWeaponStats(psDroid, i)->vtolAttackRuns > 0 && psDroid->asWeaps[i].usedAmmo != 0) { return false; @@ -3015,7 +3016,7 @@ void updateVtolAttackRun(DROID *psDroid, int weapon_slot) { if (psDroid->numWeaps > 0) { - if (asWeaponStats[psDroid->asWeaps[weapon_slot].nStat].vtolAttackRuns > 0) + if (getWeaponStats(psDroid, weapon_slot)->vtolAttackRuns > 0) { ++psDroid->asWeaps[weapon_slot].usedAmmo; if (psDroid->asWeaps[weapon_slot].usedAmmo == getNumAttackRuns(psDroid, weapon_slot)) @@ -3074,8 +3075,8 @@ bool droidSensorDroidWeapon(const BASE_OBJECT *psObj, const DROID *psDroid) return false; } compIndex = ((const DROID *)psObj)->asBits[COMP_SENSOR]; - ASSERT_OR_RETURN(false, compIndex < numSensorStats, "Invalid range referenced for numSensorStats, %d > %d", compIndex, numSensorStats); - psStats = asSensorStats + compIndex; + ASSERT_OR_RETURN(false, compIndex < asSensorStats.size(), "Invalid range referenced for numSensorStats, %d > %zu", compIndex, asSensorStats.size()); + psStats = &asSensorStats[compIndex]; break; case OBJ_STRUCTURE: psStats = ((const STRUCTURE *)psObj)->pStructureType->pSensor; @@ -3115,7 +3116,7 @@ bool droidSensorDroidWeapon(const BASE_OBJECT *psObj, const DROID *psDroid) } // Check indirect weapon droid with standard/CB/radar detector sensor - if (!proj_Direct(asWeaponStats + psDroid->asWeaps[0].nStat)) + if (!proj_Direct(getWeaponStats(psDroid, 0))) { if ((psStats->type == STANDARD_SENSOR || psStats->type == INDIRECT_CB_SENSOR || psStats->type == SUPER_SENSOR /*|| psStats->type == RADAR_DETECTOR_SENSOR*/) && !(psObj->type == OBJ_DROID && ((const DROID*)psObj)->droidType == DROID_COMMAND)) @@ -3134,8 +3135,9 @@ bool cbSensorDroid(const DROID *psDroid) { return false; } - if (asSensorStats[psDroid->asBits[COMP_SENSOR]].type == VTOL_CB_SENSOR - || asSensorStats[psDroid->asBits[COMP_SENSOR]].type == INDIRECT_CB_SENSOR) + const auto sensorType = getSensorStats(psDroid)->type; + if (sensorType == VTOL_CB_SENSOR + || sensorType == INDIRECT_CB_SENSOR) { return true; } @@ -3150,9 +3152,10 @@ bool standardSensorDroid(const DROID *psDroid) { return false; } - if (asSensorStats[psDroid->asBits[COMP_SENSOR]].type == VTOL_INTERCEPT_SENSOR - || asSensorStats[psDroid->asBits[COMP_SENSOR]].type == STANDARD_SENSOR - || asSensorStats[psDroid->asBits[COMP_SENSOR]].type == SUPER_SENSOR) + const auto sensorType = getSensorStats(psDroid)->type; + if (sensorType == VTOL_INTERCEPT_SENSOR + || sensorType == STANDARD_SENSOR + || sensorType == SUPER_SENSOR) { return true; } @@ -3275,21 +3278,21 @@ DROID *giftSingleDroid(DROID *psD, UDWORD to, bool electronic, Vector2i pos) adjustDroidCount(psD, 1); // the new player may have different default sensor/ecm/repair components - if ((asSensorStats + psD->asBits[COMP_SENSOR])->location == LOC_DEFAULT) + if (getSensorStats(psD)->location == LOC_DEFAULT) { if (psD->asBits[COMP_SENSOR] != aDefaultSensor[psD->player]) { psD->asBits[COMP_SENSOR] = aDefaultSensor[psD->player]; } } - if ((asECMStats + psD->asBits[COMP_ECM])->location == LOC_DEFAULT) + if (getECMStats(psD)->location == LOC_DEFAULT) { if (psD->asBits[COMP_ECM] != aDefaultECM[psD->player]) { psD->asBits[COMP_ECM] = aDefaultECM[psD->player]; } } - if ((asRepairStats + psD->asBits[COMP_REPAIRUNIT])->location == LOC_DEFAULT) + if (getRepairStats(psD)->location == LOC_DEFAULT) { if (psD->asBits[COMP_REPAIRUNIT] != aDefaultRepair[psD->player]) { @@ -3358,7 +3361,7 @@ DROID *giftSingleDroid(DROID *psD, UDWORD to, bool electronic, Vector2i pos) int16_t DROID::droidResistance() const { CHECK_DROID(this); - const BODY_STATS *psStats = asBodyStats + asBits[COMP_BODY]; + const BODY_STATS *psStats = &asBodyStats[asBits[COMP_BODY]]; int res = experience / (65536 / MAX(1, psStats->upgrade[player].resistance)); // ensure resistance is a base minimum res = MAX(res, psStats->upgrade[player].resistance); @@ -3376,7 +3379,7 @@ bool checkValidWeaponForProp(const DROID_TEMPLATE *psTemplate) PROPULSION_STATS *psPropStats; //check propulsion stat for vtol - psPropStats = asPropulsionStats + psTemplate->asParts[COMP_PROPULSION]; + psPropStats = &asPropulsionStats[psTemplate->asParts[COMP_PROPULSION]]; ASSERT_OR_RETURN(false, psPropStats != nullptr, "invalid propulsion stats pointer"); @@ -3389,7 +3392,7 @@ bool checkValidWeaponForProp(const DROID_TEMPLATE *psTemplate) if (asPropulsionTypes[psPropStats->propulsionType].travel == AIR) { //check weapon stat for indirect - if (!proj_Direct(asWeaponStats + psTemplate->asWeaps[0]) + if (!proj_Direct(&asWeaponStats[psTemplate->asWeaps[0]]) || !asWeaponStats[psTemplate->asWeaps[0]].vtolAttackRuns) { return false; @@ -3544,7 +3547,7 @@ void checkDroid(const DROID *droid, const char *const location, const char *func int droidSqDist(const DROID *psDroid, const BASE_OBJECT *psObj) { - PROPULSION_STATS *psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + PROPULSION_STATS *psPropStats = getPropulsionStats(psDroid); if (!fpathCheck(psDroid->pos, psObj->pos, psPropStats->propulsionType)) { diff --git a/src/droid.h b/src/droid.h index b8c925789bf..480544d286c 100644 --- a/src/droid.h +++ b/src/droid.h @@ -29,7 +29,6 @@ #include "objectdef.h" #include "stats.h" -#include "visibility.h" #include "selection.h" #include "objmem.h" @@ -296,6 +295,9 @@ void droidSetPosition(DROID *psDroid, int x, int y); /// Return a percentage of how fully armed the object is, or -1 if N/A. int droidReloadBar(const BASE_OBJECT *psObj, const WEAPON *psWeap, int weapon_slot); +// from visibility.h +extern int objSensorRange(const BASE_OBJECT* psObj); + static inline int droidSensorRange(const DROID *psDroid) { return objSensorRange((const BASE_OBJECT *)psDroid); @@ -306,42 +308,42 @@ static inline int droidSensorRange(const DROID *psDroid) */ static inline BODY_STATS *getBodyStats(const DROID *psDroid) { - return asBodyStats + psDroid->asBits[COMP_BODY]; + return &asBodyStats[psDroid->asBits[COMP_BODY]]; } static inline BRAIN_STATS *getBrainStats(const DROID *psDroid) { - return asBrainStats + psDroid->asBits[COMP_BRAIN]; + return &asBrainStats[psDroid->asBits[COMP_BRAIN]]; } static inline PROPULSION_STATS *getPropulsionStats(const DROID *psDroid) { - return asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + return &asPropulsionStats[psDroid->asBits[COMP_PROPULSION]]; } static inline SENSOR_STATS *getSensorStats(const DROID *psDroid) { - return asSensorStats + psDroid->asBits[COMP_SENSOR]; + return &asSensorStats[psDroid->asBits[COMP_SENSOR]]; } static inline ECM_STATS *getECMStats(const DROID *psDroid) { - return asECMStats + psDroid->asBits[COMP_ECM]; + return &asECMStats[psDroid->asBits[COMP_ECM]]; } static inline REPAIR_STATS *getRepairStats(const DROID *psDroid) { - return asRepairStats + psDroid->asBits[COMP_REPAIRUNIT]; + return &asRepairStats[psDroid->asBits[COMP_REPAIRUNIT]]; } static inline CONSTRUCT_STATS *getConstructStats(const DROID *psDroid) { - return asConstructStats + psDroid->asBits[COMP_CONSTRUCT]; + return &asConstructStats[psDroid->asBits[COMP_CONSTRUCT]]; } static inline WEAPON_STATS *getWeaponStats(const DROID *psDroid, int weapon_slot) { - return asWeaponStats + psDroid->asWeaps[weapon_slot].nStat; + return &asWeaponStats[psDroid->asWeaps[weapon_slot].nStat]; } static inline Rotation getInterpolatedWeaponRotation(const DROID *psDroid, int weaponSlot, uint32_t time) diff --git a/src/fpath.cpp b/src/fpath.cpp index 6fbdf0d1061..a33f4bea350 100644 --- a/src/fpath.cpp +++ b/src/fpath.cpp @@ -429,10 +429,11 @@ FPATH_RETVAL fpathDroidRoute(DROID *psDroid, SDWORD tX, SDWORD tY, FPATH_MOVETYP Position startPos = psDroid->pos; Position endPos = Position(tX, tY, 0); StructureBounds dstStructure = getStructureBounds(worldTile(endPos.xy())->psObject); - startPos = findNonblockingPosition(startPos, getPropulsionStats(psDroid)->propulsionType, psDroid->player, moveType); + const auto droidPropulsionType = getPropulsionStats(psDroid)->propulsionType; + startPos = findNonblockingPosition(startPos, droidPropulsionType, psDroid->player, moveType); if (!dstStructure.valid()) // If there's a structure over the destination, ignore it, otherwise pathfind from somewhere around the obstruction. { - endPos = findNonblockingPosition(endPos, getPropulsionStats(psDroid)->propulsionType, psDroid->player, moveType); + endPos = findNonblockingPosition(endPos, droidPropulsionType, psDroid->player, moveType); } objTrace(psDroid->id, "Want to go to (%d, %d) -> (%d, %d), going (%d, %d) -> (%d, %d)", map_coord(psDroid->pos.x), map_coord(psDroid->pos.y), map_coord(tX), map_coord(tY), map_coord(startPos.x), map_coord(startPos.y), map_coord(endPos.x), map_coord(endPos.y)); switch (psDroid->order.type) diff --git a/src/game.cpp b/src/game.cpp index 7b726bfc24c..6628a334728 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -5872,16 +5872,16 @@ static nlohmann::json writeDroid(const DROID *psCurr, bool onMission, int &count droidObj["droidType"] = psCurr->droidType; droidObj["weapons"] = psCurr->numWeaps; nlohmann::json partsObj = nlohmann::json::object(); - partsObj["body"] = (asBodyStats + psCurr->asBits[COMP_BODY])->id; - partsObj["propulsion"] = (asPropulsionStats + psCurr->asBits[COMP_PROPULSION])->id; - partsObj["brain"] = (asBrainStats + psCurr->asBits[COMP_BRAIN])->id; - partsObj["repair"] = (asRepairStats + psCurr->asBits[COMP_REPAIRUNIT])->id; - partsObj["ecm"] = (asECMStats + psCurr->asBits[COMP_ECM])->id; - partsObj["sensor"] = (asSensorStats + psCurr->asBits[COMP_SENSOR])->id; - partsObj["construct"] = (asConstructStats + psCurr->asBits[COMP_CONSTRUCT])->id; + partsObj["body"] = getBodyStats(psCurr)->id; + partsObj["propulsion"] = getPropulsionStats(psCurr)->id; + partsObj["brain"] = getBrainStats(psCurr)->id; + partsObj["repair"] = getRepairStats(psCurr)->id; + partsObj["ecm"] = getECMStats(psCurr)->id; + partsObj["sensor"] = getSensorStats(psCurr)->id; + partsObj["construct"] = getConstructStats(psCurr)->id; for (int j = 0; j < psCurr->numWeaps; j++) { - partsObj["weapon/" + WzString::number(j + 1).toStdString()] = (asWeaponStats + psCurr->asWeaps[j].nStat)->id; + partsObj["weapon/" + WzString::number(j + 1).toStdString()] = getWeaponStats(psCurr, j)->id; } droidObj["parts"] = partsObj; droidObj["moveStatus"] = psCurr->sMove.Status; @@ -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), asWeaponStats[psCurr->asWeaps[j].nStat].id); if (psCurr->asWeaps[j].nStat > 0) { ini.setValue("ammo/" + WzString::number(j), psCurr->asWeaps[j].ammo); @@ -7336,72 +7336,72 @@ static bool writeCompListFile(const char *pFileName) for (int player = 0; player < MAX_PLAYERS; player++) { ini.beginGroup("player_" + WzString::number(player)); - for (int i = 0; i < numBodyStats; i++) + for (int i = 0; i < asBodyStats.size(); i++) { - COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asBodyStats + i); + COMPONENT_STATS *psStats = (COMPONENT_STATS *)(&asBodyStats[i]); const int state = apCompLists[player][COMP_BODY][i]; if (state != UNAVAILABLE) { ini.setValue(psStats->id, state); } } - for (int i = 0; i < numWeaponStats; i++) + for (int i = 0; i < asWeaponStats.size(); i++) { - COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asWeaponStats + i); + COMPONENT_STATS *psStats = (COMPONENT_STATS *)(&asWeaponStats[i]); const int state = apCompLists[player][COMP_WEAPON][i]; if (state != UNAVAILABLE) { ini.setValue(psStats->id, state); } } - for (int i = 0; i < numConstructStats; i++) + for (int i = 0; i < asConstructStats.size(); i++) { - COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asConstructStats + i); + COMPONENT_STATS *psStats = (COMPONENT_STATS *)(&asConstructStats[i]); const int state = apCompLists[player][COMP_CONSTRUCT][i]; if (state != UNAVAILABLE) { ini.setValue(psStats->id, state); } } - for (int i = 0; i < numECMStats; i++) + for (int i = 0; i < asECMStats.size(); i++) { - COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asECMStats + i); + COMPONENT_STATS *psStats = (COMPONENT_STATS *)(&asECMStats[i]); const int state = apCompLists[player][COMP_ECM][i]; if (state != UNAVAILABLE) { ini.setValue(psStats->id, state); } } - for (int i = 0; i < numPropulsionStats; i++) + for (int i = 0; i < asPropulsionStats.size(); i++) { - COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asPropulsionStats + i); + COMPONENT_STATS *psStats = (COMPONENT_STATS *)(&asPropulsionStats[i]); const int state = apCompLists[player][COMP_PROPULSION][i]; if (state != UNAVAILABLE) { ini.setValue(psStats->id, state); } } - for (int i = 0; i < numSensorStats; i++) + for (int i = 0; i < asSensorStats.size(); i++) { - COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asSensorStats + i); + COMPONENT_STATS *psStats = (COMPONENT_STATS *)(&asSensorStats[i]); const int state = apCompLists[player][COMP_SENSOR][i]; if (state != UNAVAILABLE) { ini.setValue(psStats->id, state); } } - for (int i = 0; i < numRepairStats; i++) + for (int i = 0; i < asRepairStats.size(); i++) { - COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asRepairStats + i); + COMPONENT_STATS *psStats = (COMPONENT_STATS *)(&asRepairStats[i]); const int state = apCompLists[player][COMP_REPAIRUNIT][i]; if (state != UNAVAILABLE) { ini.setValue(psStats->id, state); } } - for (int i = 0; i < numBrainStats; i++) + for (int i = 0; i < asBrainStats.size(); i++) { - COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asBrainStats + i); + COMPONENT_STATS *psStats = (COMPONENT_STATS *)(&asBrainStats[i]); const int state = apCompLists[player][COMP_BRAIN][i]; if (state != UNAVAILABLE) { diff --git a/src/init.cpp b/src/init.cpp index c7afabd639a..92e188e62d0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -190,7 +190,6 @@ static const char* versionedModsPath(MODS_PATHS type) static bool InitialiseGlobals() { frontendInitVars(); // Initialise frontend globals and statics. - statsInitVars(); structureInitVars(); if (!messageInitVars()) { diff --git a/src/keybind.cpp b/src/keybind.cpp index 3949be9a495..fc5e4ad2735 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(asWeaponStats[psCurr->asWeaps[0].nStat], psCurr->player); psCurr->asWeaps[0].lastFired -= firePause; CONPRINTF("%s", _("Selected buildings instantly recharged!")); diff --git a/src/map.cpp b/src/map.cpp index 978b9da226b..4ef31120c35 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -2093,7 +2093,7 @@ static void threatUpdate(int player) } for (weapon = 0; weapon < psDroid->numWeaps; weapon++) { - mode |= asWeaponStats[psDroid->asWeaps[weapon].nStat].surfaceToAir; + mode |= getWeaponStats(psDroid, weapon)->surfaceToAir; } if (psDroid->droidType == DROID_SENSOR) // special treatment for sensor turrets, no multiweapon support { diff --git a/src/mapgrid.cpp b/src/mapgrid.cpp index 9525e846562..21fea2acc5b 100644 --- a/src/mapgrid.cpp +++ b/src/mapgrid.cpp @@ -215,7 +215,7 @@ struct ConditionDroidCandidateForRepair if (obj->type != OBJ_DROID) return false; const DROID *psDroid = (const DROID*) obj; const bool isOwnOrAlly = psDroid->player == player || aiCheckAlliances(psDroid->player, player); - const bool isVTOL = asPropulsionStats[psDroid->asBits[COMP_PROPULSION]].propulsionType == PROPULSION_TYPE_LIFT; + const bool isVTOL = getPropulsionStats(psDroid)->propulsionType == PROPULSION_TYPE_LIFT; // either it's a ground unit, or it's a VTOL on ground const bool isOnGround = (!isVTOL) || (isVTOL && (psDroid->sMove.Status == MOVEINACTIVE && psDroid->sMove.iVertSpeed == 0)); // Note: no check for droidIsDamaged(psDroid) this is intentional diff --git a/src/mechanics.cpp b/src/mechanics.cpp index f2e8bb21eca..35b7f0aa3d2 100644 --- a/src/mechanics.cpp +++ b/src/mechanics.cpp @@ -172,35 +172,35 @@ void makeAllAvailable() for (i = 0; i < MAX_PLAYERS; i++) { - for (comp = 0; comp < numWeaponStats; comp++) + for (comp = 0; comp < asWeaponStats.size(); comp++) { apCompLists[i][COMP_WEAPON][comp] = AVAILABLE; } - for (comp = 0; comp < numBodyStats; comp++) + for (comp = 0; comp < asBodyStats.size(); comp++) { apCompLists[i][COMP_BODY][comp] = AVAILABLE; } - for (comp = 0; comp < numPropulsionStats; comp++) + for (comp = 0; comp < asPropulsionStats.size(); comp++) { apCompLists[i][COMP_PROPULSION][comp] = AVAILABLE; } - for (comp = 0; comp < numSensorStats; comp++) + for (comp = 0; comp < asSensorStats.size(); comp++) { apCompLists[i][COMP_SENSOR][comp] = AVAILABLE; } - for (comp = 0; comp < numECMStats; comp++) + for (comp = 0; comp < asECMStats.size(); comp++) { apCompLists[i][COMP_ECM][comp] = AVAILABLE; } - for (comp = 0; comp < numConstructStats; comp++) + for (comp = 0; comp < asConstructStats.size(); comp++) { apCompLists[i][COMP_CONSTRUCT][comp] = AVAILABLE; } - for (comp = 0; comp < numBrainStats; comp++) + for (comp = 0; comp < asBrainStats.size(); comp++) { apCompLists[i][COMP_BRAIN][comp] = AVAILABLE; } - for (comp = 0; comp < numRepairStats; comp++) + for (comp = 0; comp < asRepairStats.size(); comp++) { apCompLists[i][COMP_REPAIRUNIT][comp] = AVAILABLE; } diff --git a/src/move.cpp b/src/move.cpp index 4c90155ad3e..3fc1984e65e 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -260,19 +260,20 @@ static void moveShuffleDroid(DROID *psDroid, Vector2i s) rvx = svy; // 90° to the... left? rvy = -svx; + const auto droidPropType = getPropulsionStats(psDroid)->propulsionType; // check for blocking tiles if (fpathBlockingTile(map_coord((SDWORD)psDroid->pos.x + lvx), - map_coord((SDWORD)psDroid->pos.y + lvy), getPropulsionStats(psDroid)->propulsionType)) + map_coord((SDWORD)psDroid->pos.y + lvy), droidPropType)) { leftClear = false; } else if (fpathBlockingTile(map_coord((SDWORD)psDroid->pos.x + rvx), - map_coord((SDWORD)psDroid->pos.y + rvy), getPropulsionStats(psDroid)->propulsionType)) + map_coord((SDWORD)psDroid->pos.y + rvy), droidPropType)) { rightClear = false; } else if (fpathBlockingTile(map_coord((SDWORD)psDroid->pos.x + svx), - map_coord((SDWORD)psDroid->pos.y + svy), getPropulsionStats(psDroid)->propulsionType)) + map_coord((SDWORD)psDroid->pos.y + svy), droidPropType)) { frontClear = false; } @@ -350,7 +351,7 @@ static void moveShuffleDroid(DROID *psDroid, Vector2i s) void moveStopDroid(DROID *psDroid) { CHECK_DROID(psDroid); - PROPULSION_STATS *psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + PROPULSION_STATS* psPropStats = getPropulsionStats(psDroid); ASSERT_OR_RETURN(, psPropStats != nullptr, "invalid propulsion stats pointer"); if (psPropStats->propulsionType == PROPULSION_TYPE_LIFT) @@ -553,7 +554,7 @@ static SDWORD moveObjRadius(const BASE_OBJECT *psObj) } else { - const BODY_STATS *psBdyStats = &asBodyStats[psDroid->asBits[COMP_BODY]]; + const BODY_STATS *psBdyStats = getBodyStats(psDroid); switch (psBdyStats->size) { case SIZE_LIGHT: @@ -1152,7 +1153,7 @@ static Vector2i moveGetObstacleVector(DROID *psDroid, Vector2i dest) { int32_t numObst = 0, distTot = 0; Vector2i dir(0, 0); - PROPULSION_STATS *psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + PROPULSION_STATS *psPropStats = getPropulsionStats(psDroid); ASSERT_OR_RETURN(dir, psPropStats, "invalid propulsion stats pointer"); int ourMaxSpeed = psPropStats->maxSpeed; @@ -1193,7 +1194,7 @@ static Vector2i moveGetObstacleVector(DROID *psDroid, Vector2i dest) continue; } - PROPULSION_STATS *obstaclePropStats = asPropulsionStats + psObstacle->asBits[COMP_PROPULSION]; + PROPULSION_STATS *obstaclePropStats = getPropulsionStats(psObstacle); int obstacleMaxSpeed = obstaclePropStats->maxSpeed; int obstacleRadius = moveObjRadius(psObstacle); int totalRadius = ourRadius + obstacleRadius; @@ -1317,7 +1318,7 @@ SDWORD moveCalcDroidSpeed(DROID *psDroid) // NOTE: This screws up since the transporter is offscreen still (on a mission!), and we are trying to find terrainType of a tile (that is offscreen!) if (psDroid->droidType == DROID_SUPERTRANSPORTER && missionIsOffworld()) { - PROPULSION_STATS *propulsion = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + PROPULSION_STATS *propulsion = getPropulsionStats(psDroid); speed = propulsion->maxSpeed; } else @@ -1344,7 +1345,7 @@ SDWORD moveCalcDroidSpeed(DROID *psDroid) { if (psDroid->asWeaps[0].nStat > 0 && psDroid->asWeaps[0].lastFired + FOM_MOVEPAUSE > gameTime) { - psWStats = asWeaponStats + psDroid->asWeaps[0].nStat; + psWStats = getWeaponStats(psDroid, 0); if (!psWStats->fireOnMove) { speed = 0; @@ -1572,7 +1573,7 @@ static void moveUpdateGroundModel(DROID *psDroid, SDWORD speed, uint16_t directi return; } - psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + psPropStats = getPropulsionStats(psDroid); spinSpeed = psDroid->baseSpeed * psPropStats->spinSpeed; turnSpeed = psDroid->baseSpeed * psPropStats->turnSpeed; spinAngle = DEG(psPropStats->spinAngle); @@ -1636,7 +1637,7 @@ static void moveUpdatePersonModel(DROID *psDroid, SDWORD speed, uint16_t directi return; } - psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + psPropStats = getPropulsionStats(psDroid); spinSpeed = psDroid->baseSpeed * psPropStats->spinSpeed; turnSpeed = psDroid->baseSpeed * psPropStats->turnSpeed; @@ -1733,7 +1734,7 @@ static void moveUpdateVtolModel(DROID *psDroid, SDWORD speed, uint16_t direction return; } - psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + psPropStats = getPropulsionStats(psDroid); spinSpeed = DEG(psPropStats->spinSpeed); turnSpeed = DEG(psPropStats->turnSpeed); @@ -1866,9 +1867,9 @@ static void movePlayDroidMoveAudio(DROID *psDroid) if ((psDroid != nullptr) && (psDroid->visibleForLocalDisplay())) { - PROPULSION_STATS *psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + PROPULSION_STATS *psPropStats = getPropulsionStats(psDroid); ASSERT_OR_RETURN(, psPropStats != nullptr, "Invalid propulsion stats pointer"); - iPropType = asPropulsionStats[(psDroid)->asBits[COMP_PROPULSION]].propulsionType; + iPropType = psPropStats->propulsionType; psPropType = &asPropulsionTypes[iPropType]; /* play specific wheeled and transporter or stats-specified noises */ @@ -1926,7 +1927,7 @@ static void movePlayAudio(DROID *psDroid, bool bStarted, bool bStoppedBefore, SD AUDIO_CALLBACK pAudioCallback = nullptr; /* get prop stats */ - psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + psPropStats = getPropulsionStats(psDroid); ASSERT_OR_RETURN(, psPropStats != nullptr, "Invalid propulsion stats pointer"); propType = psPropStats->propulsionType; psPropType = &asPropulsionTypes[propType]; @@ -2075,7 +2076,7 @@ void moveUpdateDroid(DROID *psDroid) CHECK_DROID(psDroid); - psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + psPropStats = getPropulsionStats(psDroid); ASSERT_OR_RETURN(, psPropStats != nullptr, "Invalid propulsion stats pointer"); // If the droid has been attacked by an EMP weapon, it is temporarily disabled diff --git a/src/multistruct.cpp b/src/multistruct.cpp index c83aba92a84..759c0ad8f0b 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(asWeaponStats[psStruct->asWeaps[0].nStat], player); unsigned damLevel = PERCENT(psStruct->body, psStruct->structureBody()); if (damLevel < HEAVY_DAMAGE_LEVEL) diff --git a/src/oprint.cpp b/src/oprint.cpp index 7ce34d946ca..68a0a0d1b9d 100644 --- a/src/oprint.cpp +++ b/src/oprint.cpp @@ -164,10 +164,10 @@ static void printWeaponInfo(const WEAPON_STATS *psStats) printComponentInfo((const COMPONENT_STATS *)psStats); CONPRINTF(" sRng %d lRng %d mRng %d %s\n" " sHt %d lHt %d pause %d dam %d\n", - proj_GetShortRange(psStats, selectedPlayer), proj_GetLongRange(psStats, selectedPlayer), proj_GetMinRange(psStats, selectedPlayer), + proj_GetShortRange(*psStats, selectedPlayer), proj_GetLongRange(*psStats, selectedPlayer), proj_GetMinRange(*psStats, selectedPlayer), proj_Direct(psStats) ? "direct" : "indirect", - weaponShortHit(psStats, selectedPlayer), weaponLongHit(psStats, selectedPlayer), weaponFirePause(psStats, selectedPlayer), - weaponDamage(psStats, selectedPlayer)); + weaponShortHit(*psStats, selectedPlayer), weaponLongHit(*psStats, selectedPlayer), weaponFirePause(*psStats, selectedPlayer), + weaponDamage(*psStats, selectedPlayer)); if (selectedPlayer < MAX_PLAYERS) { CONPRINTF(" rad %d radDam %d\n" @@ -203,7 +203,7 @@ void printDroidInfo(const DROID *psDroid) if (psDroid->asWeaps[0].nStat > 0) { - printWeaponInfo(asWeaponStats + psDroid->asWeaps[0].nStat); + printWeaponInfo(getWeaponStats(psDroid, 0)); } for (int i = 0; i < COMP_NUMCOMPONENTS; ++i) @@ -214,7 +214,7 @@ void printDroidInfo(const DROID *psDroid) if (psDroid->asBits[i] > 0) { CONPRINTF("%s", "Body: "); - psBdyStats = asBodyStats + psDroid->asBits[i]; + psBdyStats = &asBodyStats[psDroid->asBits[i]]; printComponentInfo((COMPONENT_STATS *)psBdyStats); } else @@ -228,7 +228,7 @@ void printDroidInfo(const DROID *psDroid) if (psDroid->asBits[i] > 0) { CONPRINTF("%s", "Prop: "); - psPropStats = asPropulsionStats + psDroid->asBits[i]; + psPropStats = &asPropulsionStats[psDroid->asBits[i]]; printComponentInfo((COMPONENT_STATS *)psPropStats); } else @@ -240,10 +240,10 @@ void printDroidInfo(const DROID *psDroid) if (psDroid->asBits[i] > 0) { CONPRINTF("%s", "ECM: "); - psECMStats = asECMStats + psDroid->asBits[i]; + psECMStats = &asECMStats[psDroid->asBits[i]]; printComponentInfo((COMPONENT_STATS *)psECMStats); CONPRINTF(" range %d loc %d imd %p\n", - ecmRange(psECMStats, psDroid->player), psECMStats->location, + ecmRange(*psECMStats, psDroid->player), psECMStats->location, static_cast(psECMStats->pMountGraphic)); } else @@ -255,10 +255,10 @@ void printDroidInfo(const DROID *psDroid) if (psDroid->asBits[i] > 0) { CONPRINTF("%s", "Sensor: "); - psSensStats = asSensorStats + psDroid->asBits[i]; + psSensStats = &asSensorStats[psDroid->asBits[i]]; printComponentInfo((COMPONENT_STATS *)psSensStats); CONPRINTF(" rng %d loc %d imd %p\n", - sensorRange(psSensStats, psDroid->player), + sensorRange(*psSensStats, psDroid->player), psSensStats->location, static_cast(psSensStats->pMountGraphic)); } else @@ -270,10 +270,10 @@ void printDroidInfo(const DROID *psDroid) if (psDroid->asBits[i] > 0) { CONPRINTF("%s", "Construct: "); - psConstStats = asConstructStats + psDroid->asBits[i]; + psConstStats = &asConstructStats[psDroid->asBits[i]]; printComponentInfo((COMPONENT_STATS *)psConstStats); CONPRINTF(" cPnts %d imd %p\n", - constructorPoints(psConstStats, psDroid->player), + constructorPoints(*psConstStats, psDroid->player), static_cast(psConstStats->pMountGraphic)); } break; @@ -281,10 +281,10 @@ void printDroidInfo(const DROID *psDroid) if (psDroid->asBits[i] > 0) { CONPRINTF("%s", "Repair: "); - psRepairStats = asRepairStats + psDroid->asBits[i]; + psRepairStats = getRepairStats(psDroid); printComponentInfo((COMPONENT_STATS *)psRepairStats); CONPRINTF(" repPnts %d loc %d imd %p\n", - repairPoints(psRepairStats, psDroid->player), + repairPoints(*psRepairStats, psDroid->player), psRepairStats->location, static_cast(psRepairStats->pMountGraphic)); } diff --git a/src/order.cpp b/src/order.cpp index c4f44e3f5f9..f9397a208f2 100644 --- a/src/order.cpp +++ b/src/order.cpp @@ -415,7 +415,7 @@ void orderUpdateDroid(DROID *psDroid) SDWORD xdiff, ydiff; bool bAttack; SDWORD xoffset, yoffset; - const WEAPON_STATS *psWeapStats = &asWeaponStats[psDroid->asWeaps[0].nStat]; + const WEAPON_STATS *psWeapStats = getWeaponStats(psDroid, 0); // clear the target if it has died if (psDroid->order.psObj && psDroid->order.psObj->died) { @@ -1368,7 +1368,7 @@ void orderDroidBase(DROID *psDroid, DROID_ORDER_DATA *psOrder) { UDWORD iFactoryDistSq; STRUCTURE *psFactory; - const PROPULSION_STATS *psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + const PROPULSION_STATS *psPropStats = getPropulsionStats(psDroid); const Vector3i rPos(psOrder->pos, 0); syncDebugDroid(psDroid, '-'); syncDebug("%d ordered %s", psDroid->id, getDroidOrderName(psOrder->type)); @@ -2683,10 +2683,11 @@ DroidOrder chooseOrderObj(DROID *psDroid, BASE_OBJECT *psObj, bool altOrder) && psObj->player != psDroid->player && !aiCheckAlliances(psObj->player , psDroid->player)) { + const auto sensorType = getSensorStats(psDroid)->type; //check for standard sensor or VTOL intercept sensor - if (asSensorStats[psDroid->asBits[COMP_SENSOR]].type == STANDARD_SENSOR - || asSensorStats[psDroid->asBits[COMP_SENSOR]].type == VTOL_INTERCEPT_SENSOR - || asSensorStats[psDroid->asBits[COMP_SENSOR]].type == SUPER_SENSOR) + if (sensorType == STANDARD_SENSOR + || sensorType == VTOL_INTERCEPT_SENSOR + || sensorType == SUPER_SENSOR) { // a sensor droid observing an object order = DroidOrder(DORDER_OBSERVE, psObj); @@ -2728,7 +2729,7 @@ DroidOrder chooseOrderObj(DROID *psDroid, BASE_OBJECT *psObj, bool altOrder) (psDroid->droidType == DROID_WEAPON || psDroid->droidType == DROID_CYBORG || psDroid->droidType == DROID_CYBORG_SUPER) && - proj_Direct(asWeaponStats + psDroid->asWeaps[0].nStat)) + proj_Direct(getWeaponStats(psDroid, 0))) { order = DroidOrder(DORDER_GUARD, psObj); assignSensorTarget(psObj); @@ -2826,7 +2827,7 @@ DroidOrder chooseOrderObj(DROID *psDroid, BASE_OBJECT *psObj, bool altOrder) else if ((psDroid->droidType == DROID_WEAPON || psDroid->droidType == DROID_CYBORG || psDroid->droidType == DROID_CYBORG_SUPER) - && proj_Direct(asWeaponStats + psDroid->asWeaps[0].nStat)) + && proj_Direct(getWeaponStats(psDroid, 0))) { order = DroidOrder(DORDER_GUARD, psObj); } @@ -3086,9 +3087,9 @@ bool secondarySupported(const DROID *psDroid, SECONDARY_ORDER sec) { for (unsigned i = 0; i < psDroid->numWeaps; ++i) { - const WEAPON_STATS *weaponStats = asWeaponStats + psDroid->asWeaps[i].nStat; + const WEAPON_STATS *weaponStats = getWeaponStats(psDroid, i); - if (proj_GetLongRange(weaponStats, psDroid->player) == proj_GetShortRange(weaponStats, psDroid->player)) + if (proj_GetLongRange(*weaponStats, psDroid->player) == proj_GetShortRange(*weaponStats, psDroid->player)) { supported = false; } diff --git a/src/projectile.cpp b/src/projectile.cpp index 06307feca16..bda26effa02 100644 --- a/src/projectile.cpp +++ b/src/projectile.cpp @@ -428,7 +428,7 @@ bool proj_SendProjectileAngled(WEAPON *psWeap, SIMPLE_OBJECT *psAttacker, int pl { WEAPON_STATS *psStats = &asWeaponStats[psWeap->nStat]; - ASSERT_OR_RETURN(false, psWeap->nStat < numWeaponStats, "Invalid range referenced for numWeaponStats, %d > %d", psWeap->nStat, numWeaponStats); + ASSERT_OR_RETURN(false, psWeap->nStat < asWeaponStats.size(), "Invalid range referenced for numWeaponStats, %d > %zu", psWeap->nStat, asWeaponStats.size()); ASSERT_OR_RETURN(false, psStats != nullptr, "Invalid weapon stats"); ASSERT_OR_RETURN(false, psTarget == nullptr || !psTarget->died, "Aiming at dead target!"); @@ -894,10 +894,10 @@ static void proj_InFlightFunc(PROJECTILE *psProj) setProjectileDestination(psProj, closestCollisionObject); // We hit something. // Buildings and terrain cannot be penetrated and we need a penetrating weapon, and projectile should not have already travelled further than 1.25 * maximum range. - if (closestCollisionObject != nullptr && closestCollisionObject->type == OBJ_DROID && psStats->penetrate && currentDistance < static_cast(1.25 * proj_GetLongRange(psStats, psProj->player))) + if (closestCollisionObject != nullptr && closestCollisionObject->type == OBJ_DROID && psStats->penetrate && currentDistance < static_cast(1.25 * proj_GetLongRange(*psStats, psProj->player))) { WEAPON asWeap; - asWeap.nStat = psStats - asWeaponStats; + asWeap.nStat = psStats - asWeaponStats.data(); // Assume we damaged the chosen target psProj->psDamaged.push_back(closestCollisionObject); @@ -910,7 +910,7 @@ static void proj_InFlightFunc(PROJECTILE *psProj) return; } - if (currentDistance * 100 >= proj_GetLongRange(psStats, psProj->player) * psStats->distanceExtensionFactor) + if (currentDistance * 100 >= proj_GetLongRange(*psStats, psProj->player) * psStats->distanceExtensionFactor) { // We've travelled our maximum range. psProj->state = PROJ_IMPACT; @@ -930,14 +930,14 @@ static void proj_InFlightFunc(PROJECTILE *psProj) { case WSC_FLAME: posFlip.z -= 8; // Why? - effectGiveAuxVar(PERCENT(currentDistance, proj_GetLongRange(psStats, psProj->player))); + effectGiveAuxVar(PERCENT(currentDistance, proj_GetLongRange(*psStats, psProj->player))); addEffect(&posFlip, EFFECT_EXPLOSION, EXPLOSION_TYPE_FLAMETHROWER, false, nullptr, 0, effectTime); break; case WSC_COMMAND: case WSC_ELECTRONIC: case WSC_EMP: posFlip.z -= 8; // Why? - effectGiveAuxVar(PERCENT(currentDistance, proj_GetLongRange(psStats, psProj->player)) / 2); + effectGiveAuxVar(PERCENT(currentDistance, proj_GetLongRange(*psStats, psProj->player)) / 2); addEffect(&posFlip, EFFECT_EXPLOSION, EXPLOSION_TYPE_LASER, false, nullptr, 0, effectTime); break; case WSC_ROCKET: @@ -993,7 +993,7 @@ static void proj_radiusSweep(PROJECTILE *psObj, WEAPON_STATS *psStats, Vector3i switch (psCurr->type) { case OBJ_DROID: - bTargetInAir = asPropulsionTypes[asPropulsionStats[((DROID *)psCurr)->asBits[COMP_PROPULSION]].propulsionType].travel == AIR && ((DROID *)psCurr)->sMove.Status != MOVEINACTIVE; + bTargetInAir = asPropulsionTypes[getPropulsionStats((DROID*)psCurr)->propulsionType].travel == AIR && ((DROID *)psCurr)->sMove.Status != MOVEINACTIVE; useSphere = true; break; case OBJ_STRUCTURE: @@ -1018,7 +1018,7 @@ static void proj_radiusSweep(PROJECTILE *psObj, WEAPON_STATS *psStats, Vector3i continue; // Target out of range. } // The psCurr will get damaged, at this point. - unsigned damage = calcDamage(weaponRadDamage(psStats, psObj->player), psStats->weaponEffect, psCurr); + unsigned damage = calcDamage(weaponRadDamage(*psStats, psObj->player), psStats->weaponEffect, psCurr); debug(LOG_ATTACK, "Damage to object %d, player %d : %u", psCurr->id, psCurr->player, damage); if (bMultiPlayer && psObj->psSource != nullptr && psCurr->type != OBJ_FEATURE) { @@ -1190,7 +1190,7 @@ static void proj_ImpactFunc(PROJECTILE *psObj) { // If we did enough `damage' to capture the target if (electronicDamage(psObj->psDest, - calcDamage(weaponDamage(psStats, psObj->player), psStats->weaponEffect, psObj->psDest), + calcDamage(weaponDamage(*psStats, psObj->player), psStats->weaponEffect, psObj->psDest), psObj->player)) { switch (psObj->psSource->type) @@ -1215,7 +1215,7 @@ static void proj_ImpactFunc(PROJECTILE *psObj) else { // Calculate the damage the weapon does to its target - unsigned int damage = calcDamage(weaponDamage(psStats, psObj->player), psStats->weaponEffect, psObj->psDest); + unsigned int damage = calcDamage(weaponDamage(*psStats, psObj->player), psStats->weaponEffect, psObj->psDest); // If we are in a multi-player game and the attacker is our responsibility if (bMultiPlayer && psObj->psSource) @@ -1445,7 +1445,7 @@ static void proj_checkPeriodicalDamage(PROJECTILE *psProj) psCurr->periodicalDamageStart = gameTime; psCurr->periodicalDamage = 0; // Reset periodical damage done this tick. } - unsigned damageRate = calcDamage(weaponPeriodicalDamage(psStats, psProj->player), psStats->periodicalDamageWeaponEffect, psCurr); + unsigned damageRate = calcDamage(weaponPeriodicalDamage(*psStats, psProj->player), psStats->periodicalDamageWeaponEffect, psCurr); debug(LOG_NEVER, "Periodical damage of %d per second to object %d, player %d\n", damageRate, psCurr->id, psCurr->player); struct DAMAGE sDamage = { @@ -1490,24 +1490,24 @@ bool proj_Direct(const WEAPON_STATS *psStats) ASSERT_OR_RETURN(retVal, player >= 0 && player < MAX_PLAYERS, "Invalid player: %" PRIu32 "", player); // return the maximum range for a weapon -int proj_GetLongRange(const WEAPON_STATS *psStats, int player) +int proj_GetLongRange(const WEAPON_STATS& psStats, int player) { ASSERT_PLAYER_OR_RETURN(0, player); - return psStats->upgrade[player].maxRange; + return psStats.upgrade[player].maxRange; } // return the minimum range for a weapon -int proj_GetMinRange(const WEAPON_STATS *psStats, int player) +int proj_GetMinRange(const WEAPON_STATS& psStats, int player) { ASSERT_PLAYER_OR_RETURN(0, player); - return psStats->upgrade[player].minRange; + return psStats.upgrade[player].minRange; } // return the short range for a weapon -int proj_GetShortRange(const WEAPON_STATS *psStats, int player) +int proj_GetShortRange(const WEAPON_STATS& psStats, int player) { ASSERT_PLAYER_OR_RETURN(0, player); - return psStats->upgrade[player].shortRange; + return psStats.upgrade[player].shortRange; } /***************************************************************************/ @@ -1572,8 +1572,8 @@ UDWORD calcDamage(UDWORD baseDamage, WEAPON_EFFECT weaponEffect, const BASE_OBJE } else if (psTarget->type == OBJ_DROID) { - const int propulsion = (asPropulsionStats + ((const DROID *)psTarget)->asBits[COMP_PROPULSION])->propulsionType; - const int body = (asBodyStats + ((const DROID *)psTarget)->asBits[COMP_BODY])->size; + const int propulsion = getPropulsionStats((const DROID*)psTarget)->propulsionType; + const int body = getBodyStats((const DROID*)psTarget)->size; damage += baseDamage * (asWeaponModifier[weaponEffect][propulsion] - 100); damage += baseDamage * (asWeaponModifierBody[weaponEffect][body] - 100); } @@ -1760,7 +1760,7 @@ int establishTargetHeight(BASE_OBJECT const *psTarget) case OBJ_DROID: { DROID const *psDroid = (DROID const *)psTarget; - unsigned int height = asBodyStats[psDroid->asBits[COMP_BODY]].pIMD->max.y - asBodyStats[psDroid->asBits[COMP_BODY]].pIMD->min.y; + unsigned int height = getBodyStats(psDroid)->pIMD->max.y - getBodyStats(psDroid)->pIMD->min.y; unsigned int utilityHeight = 0, yMax = 0, yMin = 0; // Temporaries for addition of utility's height to total height // VTOL's don't have pIMD either it seems... @@ -1774,37 +1774,46 @@ int establishTargetHeight(BASE_OBJECT const *psTarget) case DROID_WEAPON: if (psDroid->numWeaps > 0) { + const auto* weaponImd = getWeaponStats(psDroid, 0)->pIMD; // Don't do this for Barbarian Propulsions as they don't possess a turret (and thus have pIMD == NULL) - if ((asWeaponStats[psDroid->asWeaps[0].nStat]).pIMD == nullptr) + if (weaponImd == nullptr) { return height; } - yMax = (asWeaponStats[psDroid->asWeaps[0].nStat]).pIMD->max.y; - yMin = (asWeaponStats[psDroid->asWeaps[0].nStat]).pIMD->min.y; + yMax = weaponImd->max.y; + yMin = weaponImd->min.y; } break; case DROID_SENSOR: - yMax = (asSensorStats[psDroid->asBits[COMP_SENSOR]]).pIMD->max.y; - yMin = (asSensorStats[psDroid->asBits[COMP_SENSOR]]).pIMD->min.y; + { + const auto* sensorImd = getSensorStats(psDroid)->pIMD; + yMax = sensorImd->max.y; + yMin = sensorImd->min.y; break; - + } case DROID_ECM: - yMax = (asECMStats[psDroid->asBits[COMP_ECM]]).pIMD->max.y; - yMin = (asECMStats[psDroid->asBits[COMP_ECM]]).pIMD->min.y; + { + const auto* ecmImd = getECMStats(psDroid)->pIMD; + yMax = ecmImd->max.y; + yMin = ecmImd->min.y; break; - + } case DROID_CONSTRUCT: - yMax = (asConstructStats[psDroid->asBits[COMP_CONSTRUCT]]).pIMD->max.y; - yMin = (asConstructStats[psDroid->asBits[COMP_CONSTRUCT]]).pIMD->min.y; + { + const auto* constructImd = getConstructStats(psDroid)->pIMD; + yMax = constructImd->max.y; + yMin = constructImd->min.y; break; - + } case DROID_REPAIR: - yMax = (asRepairStats[psDroid->asBits[COMP_REPAIRUNIT]]).pIMD->max.y; - yMin = (asRepairStats[psDroid->asBits[COMP_REPAIRUNIT]]).pIMD->min.y; + { + const auto repairImd = getRepairStats(psDroid)->pIMD; + yMax = repairImd->max.y; + yMin = repairImd->min.y; break; - + } case DROID_PERSON: //TODO:add person 'state'checks here(stand, knee, crouch, prone etc) case DROID_CYBORG: diff --git a/src/projectile.h b/src/projectile.h index 5b1a37f2bb6..25656ac3776 100644 --- a/src/projectile.h +++ b/src/projectile.h @@ -73,13 +73,13 @@ bool proj_SendProjectileAngled(WEAPON *psWeap, SIMPLE_OBJECT *psAttacker, int pl bool proj_Direct(const WEAPON_STATS *psStats); /** Return the maximum range for a weapon. */ -int proj_GetLongRange(const WEAPON_STATS *psStats, int player); +int proj_GetLongRange(const WEAPON_STATS& psStats, int player); /** Return the minimum range for a weapon. */ -int proj_GetMinRange(const WEAPON_STATS *psStats, int player); +int proj_GetMinRange(const WEAPON_STATS& psStats, int player); /** Return the short range for a weapon. */ -int proj_GetShortRange(const WEAPON_STATS *psStats, int player); +int proj_GetShortRange(const WEAPON_STATS& psStats, int player); UDWORD calcDamage(UDWORD baseDamage, WEAPON_EFFECT weaponEffect, const BASE_OBJECT *psTarget); bool gfxVisible(const PROJECTILE *psObj); diff --git a/src/quickjs_backend.cpp b/src/quickjs_backend.cpp index cc6bfef312b..58ec21de735 100644 --- a/src/quickjs_backend.cpp +++ b/src/quickjs_backend.cpp @@ -819,7 +819,7 @@ JSValue convStructure(const STRUCTURE *psStruct, JSContext *ctx) aa = aa || psWeap->surfaceToAir & SHOOT_IN_AIR; ga = ga || psWeap->surfaceToAir & SHOOT_ON_GROUND; indirect = indirect || psWeap->movementModel == MM_INDIRECT || psWeap->movementModel == MM_HOMINGINDIRECT; - range = MAX(proj_GetLongRange(psWeap, psStruct->player), range); + range = MAX(proj_GetLongRange(*psWeap, psStruct->player), range); } } JSValue value = convObj(psStruct, ctx); @@ -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 = &asWeaponStats[psStruct->asWeaps[j].nStat]; 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); @@ -962,18 +962,18 @@ JSValue convDroid(const DROID *psDroid, JSContext *ctx) bool ga = false; bool indirect = false; int range = -1; - const BODY_STATS *psBodyStats = &asBodyStats[psDroid->asBits[COMP_BODY]]; + const BODY_STATS *psBodyStats = getBodyStats(psDroid); for (int i = 0; i < psDroid->numWeaps; i++) { if (psDroid->asWeaps[i].nStat) { - ASSERT(psDroid->asWeaps[i].nStat < numWeaponStats, "Invalid nStat (%d) referenced for asWeaps[%d]; numWeaponStats (%d); droid: \"%s\" (numWeaps: %u)", psDroid->asWeaps[i].nStat, i, numWeaponStats, psDroid->aName, psDroid->numWeaps); - WEAPON_STATS *psWeap = &asWeaponStats[psDroid->asWeaps[i].nStat]; + ASSERT(psDroid->asWeaps[i].nStat < asWeaponStats.size(), "Invalid nStat (%d) referenced for asWeaps[%d]; numWeaponStats (%zu); droid: \"%s\" (numWeaps: %u)", psDroid->asWeaps[i].nStat, i, asWeaponStats.size(), psDroid->aName, psDroid->numWeaps); + WEAPON_STATS *psWeap = getWeaponStats(psDroid, 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; - range = MAX(proj_GetLongRange(psWeap, psDroid->player), range); + range = MAX(proj_GetLongRange(*psWeap, psDroid->player), range); } } DROID_TYPE type = psDroid->droidType; @@ -1020,8 +1020,8 @@ JSValue convDroid(const DROID *psDroid, JSContext *ctx) QuickJS_DefinePropertyValue(ctx, value, "experience", JS_NewFloat64(ctx, (double)psDroid->experience / 65536.0), JS_PROP_ENUMERABLE); QuickJS_DefinePropertyValue(ctx, value, "health", JS_NewFloat64(ctx, 100.0 / (double)psDroid->originalBody * (double)psDroid->body), JS_PROP_ENUMERABLE); - QuickJS_DefinePropertyValue(ctx, value, "body", JS_NewString(ctx, asBodyStats[psDroid->asBits[COMP_BODY]].id.toUtf8().c_str()), JS_PROP_ENUMERABLE); - QuickJS_DefinePropertyValue(ctx, value, "propulsion", JS_NewString(ctx, asPropulsionStats[psDroid->asBits[COMP_PROPULSION]].id.toUtf8().c_str()), JS_PROP_ENUMERABLE); + QuickJS_DefinePropertyValue(ctx, value, "body", JS_NewString(ctx, getBodyStats(psDroid)->id.toUtf8().c_str()), JS_PROP_ENUMERABLE); + QuickJS_DefinePropertyValue(ctx, value, "propulsion", JS_NewString(ctx, getPropulsionStats(psDroid)->id.toUtf8().c_str()), JS_PROP_ENUMERABLE); QuickJS_DefinePropertyValue(ctx, value, "armed", JS_NewFloat64(ctx, 0.0), JS_PROP_ENUMERABLE); // deprecated! JSValue weaponlist = JS_NewArray(ctx); @@ -1029,7 +1029,7 @@ JSValue convDroid(const DROID *psDroid, JSContext *ctx) { int armed = droidReloadBar(psDroid, &psDroid->asWeaps[j], j); JSValue weapon = JS_NewObject(ctx); - const WEAPON_STATS *psStats = asWeaponStats + psDroid->asWeaps[j].nStat; + const WEAPON_STATS *psStats = getWeaponStats(psDroid, 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); @@ -1117,17 +1117,17 @@ JSValue convTemplate(const DROID_TEMPLATE *psTempl, JSContext *ctx) QuickJS_DefinePropertyValue(ctx, value, "power", JS_NewUint32(ctx, calcTemplatePower(psTempl)), JS_PROP_ENUMERABLE); // deprecated, use cost below QuickJS_DefinePropertyValue(ctx, value, "cost", JS_NewUint32(ctx, calcTemplatePower(psTempl)), JS_PROP_ENUMERABLE); QuickJS_DefinePropertyValue(ctx, value, "droidType", JS_NewInt32(ctx, psTempl->droidType), JS_PROP_ENUMERABLE); - QuickJS_DefinePropertyValue(ctx, value, "body", JS_NewString(ctx, (asBodyStats + psTempl->asParts[COMP_BODY])->id.toUtf8().c_str()), JS_PROP_ENUMERABLE); - QuickJS_DefinePropertyValue(ctx, value, "propulsion", JS_NewString(ctx, (asPropulsionStats + psTempl->asParts[COMP_PROPULSION])->id.toUtf8().c_str()), JS_PROP_ENUMERABLE); - QuickJS_DefinePropertyValue(ctx, value, "brain", JS_NewString(ctx, (asBrainStats + psTempl->asParts[COMP_BRAIN])->id.toUtf8().c_str()), JS_PROP_ENUMERABLE); - QuickJS_DefinePropertyValue(ctx, value, "repair", JS_NewString(ctx, (asRepairStats + psTempl->asParts[COMP_REPAIRUNIT])->id.toUtf8().c_str()), JS_PROP_ENUMERABLE); - QuickJS_DefinePropertyValue(ctx, value, "ecm", JS_NewString(ctx, (asECMStats + psTempl->asParts[COMP_ECM])->id.toUtf8().c_str()), JS_PROP_ENUMERABLE); - QuickJS_DefinePropertyValue(ctx, value, "sensor", JS_NewString(ctx, (asSensorStats + psTempl->asParts[COMP_SENSOR])->id.toUtf8().c_str()), JS_PROP_ENUMERABLE); - QuickJS_DefinePropertyValue(ctx, value, "construct", JS_NewString(ctx, (asConstructStats + psTempl->asParts[COMP_CONSTRUCT])->id.toUtf8().c_str()), JS_PROP_ENUMERABLE); + QuickJS_DefinePropertyValue(ctx, value, "body", JS_NewString(ctx, asBodyStats[psTempl->asParts[COMP_BODY]].id.toUtf8().c_str()), JS_PROP_ENUMERABLE); + QuickJS_DefinePropertyValue(ctx, value, "propulsion", JS_NewString(ctx, asPropulsionStats[psTempl->asParts[COMP_PROPULSION]].id.toUtf8().c_str()), JS_PROP_ENUMERABLE); + QuickJS_DefinePropertyValue(ctx, value, "brain", JS_NewString(ctx, asBrainStats[psTempl->asParts[COMP_BRAIN]].id.toUtf8().c_str()), JS_PROP_ENUMERABLE); + QuickJS_DefinePropertyValue(ctx, value, "repair", JS_NewString(ctx, asRepairStats[psTempl->asParts[COMP_REPAIRUNIT]].id.toUtf8().c_str()), JS_PROP_ENUMERABLE); + QuickJS_DefinePropertyValue(ctx, value, "ecm", JS_NewString(ctx, asECMStats[psTempl->asParts[COMP_ECM]].id.toUtf8().c_str()), JS_PROP_ENUMERABLE); + QuickJS_DefinePropertyValue(ctx, value, "sensor", JS_NewString(ctx, asSensorStats[psTempl->asParts[COMP_SENSOR]].id.toUtf8().c_str()), JS_PROP_ENUMERABLE); + QuickJS_DefinePropertyValue(ctx, value, "construct", JS_NewString(ctx, asConstructStats[psTempl->asParts[COMP_CONSTRUCT]].id.toUtf8().c_str()), JS_PROP_ENUMERABLE); JSValue weaponlist = JS_NewArray(ctx); for (int j = 0; j < psTempl->numWeaps; j++) { - JS_DefinePropertyValueUint32(ctx, weaponlist, j, JS_NewString(ctx, (asWeaponStats + psTempl->asWeaps[j])->id.toUtf8().c_str()), JS_PROP_ENUMERABLE); + JS_DefinePropertyValueUint32(ctx, weaponlist, j, JS_NewString(ctx, asWeaponStats[psTempl->asWeaps[j]].id.toUtf8().c_str()), JS_PROP_ENUMERABLE); } QuickJS_DefinePropertyValue(ctx, value, "weapons", weaponlist, JS_PROP_ENUMERABLE); return value; diff --git a/src/research.cpp b/src/research.cpp index 932ce14bee4..bba638f8e82 100644 --- a/src/research.cpp +++ b/src/research.cpp @@ -988,17 +988,17 @@ void researchResult(UDWORD researchIndex, UBYTE player, bool bDisplay, STRUCTURE int compInc = componentResult->index; makeComponentAvailable(apCompLists[player][type][compInc]); //check for default sensor - if (type == COMP_SENSOR && (asSensorStats + compInc)->location == LOC_DEFAULT) + if (type == COMP_SENSOR && asSensorStats[compInc].location == LOC_DEFAULT) { aDefaultSensor[player] = compInc; } //check for default ECM - else if (type == COMP_ECM && (asECMStats + compInc)->location == LOC_DEFAULT) + else if (type == COMP_ECM && asECMStats[compInc].location == LOC_DEFAULT) { aDefaultECM[player] = compInc; } //check for default Repair - else if (type == COMP_REPAIRUNIT && (asRepairStats + compInc)->location == LOC_DEFAULT) + else if (type == COMP_REPAIRUNIT && asRepairStats[compInc].location == LOC_DEFAULT) { aDefaultRepair[player] = compInc; enableSelfRepair(player); diff --git a/src/selection.cpp b/src/selection.cpp index dda06912255..4fac5ec05a4 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -94,11 +94,11 @@ static bool selTrue(DROID *droid) } static bool selProp(DROID *droid, PROPULSION_TYPE prop) { - return asPropulsionStats[droid->asBits[COMP_PROPULSION]].propulsionType == prop && !selTransporter(droid); + return getPropulsionStats(droid)->propulsionType == prop && !selTransporter(droid); } static bool selPropArmed(DROID *droid, PROPULSION_TYPE prop) { - return asPropulsionStats[droid->asBits[COMP_PROPULSION]].propulsionType == prop && vtolFull(droid) && !selTransporter(droid); + return getPropulsionStats(droid)->propulsionType == prop && vtolFull(droid) && !selTransporter(droid); } static bool selType(DROID *droid, DROID_TYPE type) { @@ -110,7 +110,7 @@ static bool selCombat(DROID *droid) } static bool selCombatLand(DROID *droid) { - PROPULSION_TYPE type = asPropulsionStats[droid->asBits[COMP_PROPULSION]].propulsionType; + PROPULSION_TYPE type = getPropulsionStats(droid)->propulsionType; return droid->asWeaps[0].nStat > 0 && (type == PROPULSION_TYPE_WHEELED || type == PROPULSION_TYPE_HALF_TRACKED || type == PROPULSION_TYPE_TRACKED || @@ -119,7 +119,7 @@ static bool selCombatLand(DROID *droid) } static bool selCombatCyborg(DROID *droid) { - PROPULSION_TYPE type = asPropulsionStats[droid->asBits[COMP_PROPULSION]].propulsionType; + PROPULSION_TYPE type = getPropulsionStats(droid)->propulsionType; return droid->asWeaps[0].nStat > 0 && type == PROPULSION_TYPE_LEGGED; } static bool selDamaged(DROID *droid) diff --git a/src/stats.cpp b/src/stats.cpp index 871b8e5c581..d8f624ffac1 100644 --- a/src/stats.cpp +++ b/src/stats.cpp @@ -47,14 +47,14 @@ #define DEFAULT_DROID_RESISTANCE 150 /* The stores for the different stats */ -BODY_STATS *asBodyStats; -BRAIN_STATS *asBrainStats; -PROPULSION_STATS *asPropulsionStats; -SENSOR_STATS *asSensorStats; -ECM_STATS *asECMStats; -REPAIR_STATS *asRepairStats; -WEAPON_STATS *asWeaponStats; -CONSTRUCT_STATS *asConstructStats; +std::vector asBodyStats; +std::vector asBrainStats; +std::vector asPropulsionStats; +std::vector asSensorStats; +std::vector asECMStats; +std::vector asRepairStats; +std::vector asWeaponStats; +std::vector asConstructStats; std::vector asPropulsionTypes; static int *asTerrainTable; @@ -62,16 +62,6 @@ static int *asTerrainTable; WEAPON_MODIFIER asWeaponModifier[WE_NUMEFFECTS][PROPULSION_TYPE_NUM]; WEAPON_MODIFIER asWeaponModifierBody[WE_NUMEFFECTS][SIZE_NUM]; -/* The number of different stats stored */ -UDWORD numBodyStats; -UDWORD numBrainStats; -UDWORD numPropulsionStats; -UDWORD numSensorStats; -UDWORD numECMStats; -UDWORD numRepairStats; -UDWORD numWeaponStats; -UDWORD numConstructStats; - //stores for each players component states - can be either UNAVAILABLE, REDUNDANT, FOUND or AVAILABLE UBYTE *apCompLists[MAX_PLAYERS][COMP_NUMCOMPONENTS]; @@ -105,46 +95,26 @@ static void deallocTerrainTable() *******************************************************************************/ /* Macro to allocate memory for a set of stats */ -#define ALLOC_STATS(numEntries, list, listSize, type) \ +#define ALLOC_STATS(numEntries, list, type) \ ASSERT((numEntries) < ~STAT_MASK + 1, "Number of stats entries too large for " #type);\ - if ((list)) delete [] (list); \ - (list) = new type[numEntries]; \ - (listSize) = (numEntries); \ + if (!list.empty()) list.clear(); \ + list.resize(numEntries); \ return true -/*Macro to Deallocate stats*/ -#define STATS_DEALLOC(list, listSize) \ - delete [] (list); \ - listSize = 0; \ - (list) = NULL - -void statsInitVars() -{ - /* The number of different stats stored */ - numBodyStats = 0; - numBrainStats = 0; - numPropulsionStats = 0; - numSensorStats = 0; - numECMStats = 0; - numRepairStats = 0; - numWeaponStats = 0; - numConstructStats = 0; -} - /*Deallocate all the stats assigned from input data*/ bool statsShutDown() { lookupStatPtr.clear(); lookupCompStatPtr.clear(); - STATS_DEALLOC(asWeaponStats, numWeaponStats); - STATS_DEALLOC(asBrainStats, numBrainStats); - STATS_DEALLOC(asPropulsionStats, numPropulsionStats); - STATS_DEALLOC(asRepairStats, numRepairStats); - STATS_DEALLOC(asConstructStats, numConstructStats); - STATS_DEALLOC(asECMStats, numECMStats); - STATS_DEALLOC(asSensorStats, numSensorStats); - STATS_DEALLOC(asBodyStats, numBodyStats); + asWeaponStats.clear(); + asBrainStats.clear(); + asPropulsionStats.clear(); + asRepairStats.clear(); + asConstructStats.clear(); + asECMStats.clear(); + asSensorStats.clear(); + asBodyStats.clear(); deallocPropulsionTypes(); deallocTerrainTable(); @@ -158,44 +128,44 @@ bool statsShutDown() /* Allocate Weapon stats */ bool statsAllocWeapons(UDWORD numStats) { - ALLOC_STATS(numStats, asWeaponStats, numWeaponStats, WEAPON_STATS); + ALLOC_STATS(numStats, asWeaponStats, WEAPON_STATS); } /* Allocate Body Stats */ bool statsAllocBody(UDWORD numStats) { - ALLOC_STATS(numStats, asBodyStats, numBodyStats, BODY_STATS); + ALLOC_STATS(numStats, asBodyStats, BODY_STATS); } /* Allocate Brain Stats */ bool statsAllocBrain(UDWORD numStats) { - ALLOC_STATS(numStats, asBrainStats, numBrainStats, BRAIN_STATS); + ALLOC_STATS(numStats, asBrainStats, BRAIN_STATS); } /* Allocate Propulsion Stats */ bool statsAllocPropulsion(UDWORD numStats) { - ALLOC_STATS(numStats, asPropulsionStats, numPropulsionStats, PROPULSION_STATS); + ALLOC_STATS(numStats, asPropulsionStats, PROPULSION_STATS); } /* Allocate Sensor Stats */ bool statsAllocSensor(UDWORD numStats) { - ALLOC_STATS(numStats, asSensorStats, numSensorStats, SENSOR_STATS); + ALLOC_STATS(numStats, asSensorStats, SENSOR_STATS); } /* Allocate Ecm Stats */ bool statsAllocECM(UDWORD numStats) { - ALLOC_STATS(numStats, asECMStats, numECMStats, ECM_STATS); + ALLOC_STATS(numStats, asECMStats, ECM_STATS); } /* Allocate Repair Stats */ bool statsAllocRepair(UDWORD numStats) { - ALLOC_STATS(numStats, asRepairStats, numRepairStats, REPAIR_STATS); + ALLOC_STATS(numStats, asRepairStats, REPAIR_STATS); } /* Allocate Construct Stats */ bool statsAllocConstruct(UDWORD numStats) { - ALLOC_STATS(numStats, asConstructStats, numConstructStats, CONSTRUCT_STATS); + ALLOC_STATS(numStats, asConstructStats, CONSTRUCT_STATS); } /******************************************************************************* @@ -652,12 +622,12 @@ bool loadBodyStats(WzConfig &ini) // separate function // allocate space - for (int numStats = 0; numStats < numBodyStats; ++numStats) + for (int numStats = 0; numStats < asBodyStats.size(); ++numStats) { BODY_STATS *psBodyStat = &asBodyStats[numStats]; - psBodyStat->ppIMDList.resize(numPropulsionStats * NUM_PROP_SIDES, nullptr); - psBodyStat->ppMoveIMDList.resize(numPropulsionStats * NUM_PROP_SIDES, nullptr); - psBodyStat->ppStillIMDList.resize(numPropulsionStats * NUM_PROP_SIDES, nullptr); + psBodyStat->ppIMDList.resize(asPropulsionStats.size() * NUM_PROP_SIDES, nullptr); + psBodyStat->ppMoveIMDList.resize(asPropulsionStats.size() * NUM_PROP_SIDES, nullptr); + psBodyStat->ppStillIMDList.resize(asPropulsionStats.size() * NUM_PROP_SIDES, nullptr); } for (size_t i = 0; i < list.size(); ++i) { @@ -673,7 +643,7 @@ bool loadBodyStats(WzConfig &ini) } ini.beginGroup("propulsionExtraModels"); //get the body stats - for (numStats = 0; numStats < numBodyStats; ++numStats) + for (numStats = 0; numStats < asBodyStats.size(); ++numStats) { psBodyStat = &asBodyStats[numStats]; if (list[i].compare(psBodyStat->id) == 0) @@ -681,7 +651,7 @@ bool loadBodyStats(WzConfig &ini) break; } } - if (numStats == numBodyStats) // not found + if (numStats == asBodyStats.size()) // not found { debug(LOG_FATAL, "Invalid body name %s", list[i].toUtf8().c_str()); return false; @@ -689,7 +659,7 @@ bool loadBodyStats(WzConfig &ini) std::vector keys = ini.childKeys(); for (size_t j = 0; j < keys.size(); j++) { - for (numStats = 0; numStats < numPropulsionStats; numStats++) + for (numStats = 0; numStats < asPropulsionStats.size(); numStats++) { PROPULSION_STATS *psPropulsionStat = &asPropulsionStats[numStats]; if (keys[j].compare(psPropulsionStat->id) == 0) @@ -697,7 +667,7 @@ bool loadBodyStats(WzConfig &ini) break; } } - if (numStats == numPropulsionStats) + if (numStats == asPropulsionStats.size()) { debug(LOG_FATAL, "Invalid propulsion name %s", keys[j].toUtf8().c_str()); return false; @@ -764,7 +734,7 @@ bool loadBrainStats(WzConfig &ini) int weapon = getCompFromName(COMP_WEAPON, ini.value("turret").toWzString()); if (weapon >= 0) { - psStats->psWeaponStat = asWeaponStats + weapon; + psStats->psWeaponStat = &asWeaponStats[weapon]; } else { @@ -1688,88 +1658,88 @@ bool getWeaponClass(const WzString& weaponClassStr, WEAPON_CLASS *weaponClass) ASSERT_OR_RETURN(retVal, player >= 0 && player < MAX_PLAYERS, "Invalid player: %" PRIu32 "", player); /*Access functions for the upgradeable stats of a weapon*/ -int weaponFirePause(const WEAPON_STATS *psStats, int player) +int weaponFirePause(const WEAPON_STATS& psStats, int player) { ASSERT_PLAYER_OR_RETURN(0, player); - return psStats->upgrade[player].firePause; + return psStats.upgrade[player].firePause; } /* Reload time is reduced for weapons with salvo fire */ -int weaponReloadTime(const WEAPON_STATS *psStats, int player) +int weaponReloadTime(const WEAPON_STATS& psStats, int player) { ASSERT_PLAYER_OR_RETURN(0, player); - return psStats->upgrade[player].reloadTime; + return psStats.upgrade[player].reloadTime; } -int weaponLongHit(const WEAPON_STATS *psStats, int player) +int weaponLongHit(const WEAPON_STATS& psStats, int player) { ASSERT_PLAYER_OR_RETURN(0, player); - return psStats->upgrade[player].hitChance; + return psStats.upgrade[player].hitChance; } -int weaponShortHit(const WEAPON_STATS *psStats, int player) +int weaponShortHit(const WEAPON_STATS& psStats, int player) { ASSERT_PLAYER_OR_RETURN(0, player); - return psStats->upgrade[player].shortHitChance; + return psStats.upgrade[player].shortHitChance; } -int weaponDamage(const WEAPON_STATS *psStats, int player) +int weaponDamage(const WEAPON_STATS& psStats, int player) { ASSERT_PLAYER_OR_RETURN(0, player); - return psStats->upgrade[player].damage; + return psStats.upgrade[player].damage; } -int weaponRadDamage(const WEAPON_STATS *psStats, int player) +int weaponRadDamage(const WEAPON_STATS& psStats, int player) { ASSERT_PLAYER_OR_RETURN(0, player); - return psStats->upgrade[player].radiusDamage; + return psStats.upgrade[player].radiusDamage; } -int weaponPeriodicalDamage(const WEAPON_STATS *psStats, int player) +int weaponPeriodicalDamage(const WEAPON_STATS& psStats, int player) { ASSERT_PLAYER_OR_RETURN(0, player); - return psStats->upgrade[player].periodicalDamage; + return psStats.upgrade[player].periodicalDamage; } -int sensorRange(const SENSOR_STATS *psStats, int player) +int sensorRange(const SENSOR_STATS& psStats, int player) { ASSERT_PLAYER_OR_RETURN(0, player); - return psStats->upgrade[player].range; + return psStats.upgrade[player].range; } -int ecmRange(const ECM_STATS *psStats, int player) +int ecmRange(const ECM_STATS& psStats, int player) { ASSERT_PLAYER_OR_RETURN(0, player); - return psStats->upgrade[player].range; + return psStats.upgrade[player].range; } -int repairPoints(const REPAIR_STATS *psStats, int player) +int repairPoints(const REPAIR_STATS& psStats, int player) { ASSERT_PLAYER_OR_RETURN(0, player); - return psStats->upgrade[player].repairPoints; + return psStats.upgrade[player].repairPoints; } -int constructorPoints(const CONSTRUCT_STATS *psStats, int player) +int constructorPoints(const CONSTRUCT_STATS& psStats, int player) { ASSERT_PLAYER_OR_RETURN(0, player); - return psStats->upgrade[player].constructPoints; + return psStats.upgrade[player].constructPoints; } -int bodyPower(const BODY_STATS *psStats, int player) +int bodyPower(const BODY_STATS& psStats, int player) { ASSERT_PLAYER_OR_RETURN(0, player); - return psStats->upgrade[player].power; + return psStats.upgrade[player].power; } -int bodyArmour(const BODY_STATS *psStats, int player, WEAPON_CLASS weaponClass) +int bodyArmour(const BODY_STATS& psStats, int player, WEAPON_CLASS weaponClass) { ASSERT_PLAYER_OR_RETURN(0, player); switch (weaponClass) { case WC_KINETIC: - return psStats->upgrade[player].armour; + return psStats.upgrade[player].armour; case WC_HEAT: - return psStats->upgrade[player].thermal; + return psStats.upgrade[player].thermal; case WC_NUM_WEAPON_CLASSES: break; } @@ -1778,17 +1748,17 @@ int bodyArmour(const BODY_STATS *psStats, int player, WEAPON_CLASS weaponClass) } //calculates the weapons ROF based on the fire pause and the salvos -int weaponROF(const WEAPON_STATS *psStat, int player) +int weaponROF(const WEAPON_STATS& psStat, int player) { ASSERT_PLAYER_OR_RETURN(0, player); int rof = 0; // if there are salvos if (player >= 0 - && psStat->upgrade[player].numRounds - && psStat->upgrade[player].reloadTime != 0) + && psStat.upgrade[player].numRounds + && psStat.upgrade[player].reloadTime != 0) { // Rounds per salvo multiplied with the number of salvos per minute - rof = psStat->upgrade[player].numRounds * 60 * GAME_TICKS_PER_SEC / weaponReloadTime(psStat, player); + rof = psStat.upgrade[player].numRounds * 60 * GAME_TICKS_PER_SEC / weaponReloadTime(psStat, player); } if (rof == 0) @@ -1838,8 +1808,8 @@ SENSOR_STATS *objActiveRadar(const BASE_OBJECT *psObj) return nullptr; } compIndex = ((const DROID *)psObj)->asBits[COMP_SENSOR]; - ASSERT_OR_RETURN(nullptr, compIndex < numSensorStats, "Invalid range referenced for numSensorStats, %d > %d", compIndex, numSensorStats); - psStats = asSensorStats + compIndex; + ASSERT_OR_RETURN(nullptr, compIndex < asSensorStats.size(), "Invalid range referenced for numSensorStats, %d > %zu", compIndex, asSensorStats.size()); + psStats = &asSensorStats[compIndex]; break; case OBJ_STRUCTURE: psStats = ((const STRUCTURE *)psObj)->pStructureType->pSensor; diff --git a/src/stats.h b/src/stats.h index 56ac4b78606..b8cb9232933 100644 --- a/src/stats.h +++ b/src/stats.h @@ -26,6 +26,7 @@ #include "lib/framework/wzconfig.h" #include +#include #include "objectdef.h" @@ -35,31 +36,20 @@ */ /* The stores for the different stats */ -extern BODY_STATS *asBodyStats; -extern BRAIN_STATS *asBrainStats; -extern PROPULSION_STATS *asPropulsionStats; -extern SENSOR_STATS *asSensorStats; -extern ECM_STATS *asECMStats; -extern REPAIR_STATS *asRepairStats; -extern WEAPON_STATS *asWeaponStats; -extern CONSTRUCT_STATS *asConstructStats; +extern std::vector asBodyStats; +extern std::vector asBrainStats; +extern std::vector asPropulsionStats; +extern std::vector asSensorStats; +extern std::vector asECMStats; +extern std::vector asRepairStats; +extern std::vector asWeaponStats; +extern std::vector asConstructStats; extern std::vector asPropulsionTypes; //used to hold the modifiers cross refd by weapon effect and propulsion type extern WEAPON_MODIFIER asWeaponModifier[WE_NUMEFFECTS][PROPULSION_TYPE_NUM]; extern WEAPON_MODIFIER asWeaponModifierBody[WE_NUMEFFECTS][SIZE_NUM]; -/* The number of different stats stored */ -extern UDWORD numBodyStats; -extern UDWORD numBrainStats; -extern UDWORD numPropulsionStats; -extern UDWORD numSensorStats; -extern UDWORD numECMStats; -extern UDWORD numRepairStats; -extern UDWORD numWeaponStats; -extern UDWORD numConstructStats; -extern UDWORD numTerrainTypes; - //stores for each players component states - see below extern UBYTE *apCompLists[MAX_PLAYERS][COMP_NUMCOMPONENTS]; @@ -221,25 +211,23 @@ bool getPropulsionType(const char *typeName, PROPULSION_TYPE *type); */ extern const StringToEnumMap map_WEAPON_EFFECT; -WZ_DECL_PURE int weaponROF(const WEAPON_STATS *psStat, int player); -WZ_DECL_PURE int weaponFirePause(const WEAPON_STATS *psStats, int player); -WZ_DECL_PURE int weaponReloadTime(const WEAPON_STATS *psStats, int player); -WZ_DECL_PURE int weaponShortHit(const WEAPON_STATS *psStats, int player); -WZ_DECL_PURE int weaponLongHit(const WEAPON_STATS *psStats, int player); -WZ_DECL_PURE int weaponDamage(const WEAPON_STATS *psStats, int player); -WZ_DECL_PURE int weaponRadDamage(const WEAPON_STATS *psStats, int player); -WZ_DECL_PURE int weaponPeriodicalDamage(const WEAPON_STATS *psStats, int player); -WZ_DECL_PURE int sensorRange(const SENSOR_STATS *psStats, int player); -WZ_DECL_PURE int ecmRange(const ECM_STATS *psStats, int player); -WZ_DECL_PURE int repairPoints(const REPAIR_STATS *psStats, int player); -WZ_DECL_PURE int constructorPoints(const CONSTRUCT_STATS *psStats, int player); -WZ_DECL_PURE int bodyPower(const BODY_STATS *psStats, int player); -WZ_DECL_PURE int bodyArmour(const BODY_STATS *psStats, int player, WEAPON_CLASS weaponClass); +WZ_DECL_PURE int weaponROF(const WEAPON_STATS& psStat, int player); +WZ_DECL_PURE int weaponFirePause(const WEAPON_STATS& psStats, int player); +WZ_DECL_PURE int weaponReloadTime(const WEAPON_STATS& psStats, int player); +WZ_DECL_PURE int weaponShortHit(const WEAPON_STATS& psStats, int player); +WZ_DECL_PURE int weaponLongHit(const WEAPON_STATS& psStats, int player); +WZ_DECL_PURE int weaponDamage(const WEAPON_STATS& psStats, int player); +WZ_DECL_PURE int weaponRadDamage(const WEAPON_STATS& psStats, int player); +WZ_DECL_PURE int weaponPeriodicalDamage(const WEAPON_STATS& psStats, int player); +WZ_DECL_PURE int sensorRange(const SENSOR_STATS& psStats, int player); +WZ_DECL_PURE int ecmRange(const ECM_STATS& psStats, int player); +WZ_DECL_PURE int repairPoints(const REPAIR_STATS& psStats, int player); +WZ_DECL_PURE int constructorPoints(const CONSTRUCT_STATS& psStats, int player); +WZ_DECL_PURE int bodyPower(const BODY_STATS& psStats, int player); +WZ_DECL_PURE int bodyArmour(const BODY_STATS& psStats, int player, WEAPON_CLASS weaponClass); WZ_DECL_PURE bool objHasWeapon(const BASE_OBJECT *psObj); -void statsInitVars(); - bool getWeaponEffect(const WzString& weaponEffect, WEAPON_EFFECT *effect); /*returns the weapon effect string based on the enum passed in */ const char *getWeaponEffect(WEAPON_EFFECT effect); diff --git a/src/structure.cpp b/src/structure.cpp index e334615634a..78e2a178e41 100644 --- a/src/structure.cpp +++ b/src/structure.cpp @@ -569,7 +569,7 @@ bool loadStructureStats(WzConfig &ini) int ecm = getCompFromName(COMP_ECM, ini.value("ecmID", "ZNULLECM").toWzString()); if (ecm >= 0) { - psStats->pECM = asECMStats + ecm; + psStats->pECM = &asECMStats[ecm]; } else { @@ -579,7 +579,7 @@ bool loadStructureStats(WzConfig &ini) int sensor = getCompFromName(COMP_SENSOR, ini.value("sensorID", "ZNULLSENSOR").toWzString()); if (sensor >= 0) { - psStats->pSensor = asSensorStats + sensor; + psStats->pSensor = &asSensorStats[sensor]; } else { @@ -601,7 +601,7 @@ bool loadStructureStats(WzConfig &ini) int weapon = getCompFromName(COMP_WEAPON, weaponsID); if (weapon >= 0) { - WEAPON_STATS *pWeap = asWeaponStats + weapon; + WEAPON_STATS *pWeap = &asWeaponStats[weapon]; psStats->psWeapStat[j] = pWeap; } else @@ -1552,8 +1552,8 @@ STRUCTURE *buildStructureDir(STRUCTURE_STATS *pStructureType, UDWORD x, UDWORD y { psBuilding->asWeaps[0].lastFired = gameTime; } - psBuilding->asWeaps[weapon].nStat = pStructureType->psWeapStat[weapon] - asWeaponStats; - psBuilding->asWeaps[weapon].ammo = (asWeaponStats + psBuilding->asWeaps[weapon].nStat)->upgrade[psBuilding->player].numRounds; + psBuilding->asWeaps[weapon].nStat = pStructureType->psWeapStat[weapon] - asWeaponStats.data(); + psBuilding->asWeaps[weapon].ammo = asWeaponStats[psBuilding->asWeaps[weapon].nStat].upgrade[psBuilding->player].numRounds; psBuilding->numWeaps++; } } @@ -1569,8 +1569,8 @@ STRUCTURE *buildStructureDir(STRUCTURE_STATS *pStructureType, UDWORD x, UDWORD y { psBuilding->asWeaps[0].lastFired = gameTime; } - psBuilding->asWeaps[0].nStat = pStructureType->psWeapStat[0] - asWeaponStats; - psBuilding->asWeaps[0].ammo = (asWeaponStats + psBuilding->asWeaps[0].nStat)->upgrade[psBuilding->player].numRounds; + psBuilding->asWeaps[0].nStat = pStructureType->psWeapStat[0] - asWeaponStats.data(); + psBuilding->asWeaps[0].ammo = asWeaponStats[psBuilding->asWeaps[0].nStat].upgrade[psBuilding->player].numRounds; } } @@ -1884,7 +1884,7 @@ STRUCTURE *buildBlueprint(STRUCTURE_STATS const *psStats, Vector3i pos, uint16_t // give defensive structures a weapon if (psStats->psWeapStat[0]) { - blueprint->asWeaps[0].nStat = psStats->psWeapStat[0] - asWeaponStats; + blueprint->asWeaps[0].nStat = psStats->psWeapStat[0] - asWeaponStats.data(); } // things with sensors or ecm (or repair facilities) need these set, even if they have no official weapon blueprint->numWeaps = 0; @@ -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(asWeaponStats[psStructure->asWeaps[0].nStat], psStructure->player) && psStructure->asWeaps[0].ammo > 0) { triggerEventStructureReady(psStructure); @@ -2985,7 +2985,7 @@ 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(&asWeaponStats[psStructure->asWeaps[i].nStat]); if (psStructure->asWeaps[i].nStat > 0 && asWeaponStats[psStructure->asWeaps[i].nStat].weaponSubClass != WSC_LAS_SAT) { @@ -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 = &asWeaponStats[psStructure->asWeaps[i].nStat]; //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 @@ -3441,7 +3441,7 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool isMission) { // set rearm value to no runs made psDroid->asWeaps[i].usedAmmo = 0; - psDroid->asWeaps[i].ammo = asWeaponStats[psDroid->asWeaps[i].nStat].upgrade[psDroid->player].numRounds; + psDroid->asWeaps[i].ammo = getWeaponStats(psDroid, i)->upgrade[psDroid->player].numRounds; psDroid->asWeaps[i].lastFired = 0; } objTrace(psDroid->id, "fully loaded"); @@ -3451,7 +3451,7 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool isMission) for (unsigned i = 0; i < psDroid->numWeaps; i++) // rearm one weapon at a time { // Make sure it's a rearmable weapon (and so we don't divide by zero) - if (psDroid->asWeaps[i].usedAmmo > 0 && asWeaponStats[psDroid->asWeaps[i].nStat].upgrade[psDroid->player].numRounds > 0) + if (psDroid->asWeaps[i].usedAmmo > 0 && getWeaponStats(psDroid, i)->upgrade[psDroid->player].numRounds > 0) { // Do not "simplify" this formula. // It is written this way to prevent rounding errors. @@ -3462,7 +3462,7 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool isMission) if (ammoToAddThisTime) { // reset ammo and lastFired - psDroid->asWeaps[i].ammo = asWeaponStats[psDroid->asWeaps[i].nStat].upgrade[psDroid->player].numRounds; + psDroid->asWeaps[i].ammo = getWeaponStats(psDroid, i)->upgrade[psDroid->player].numRounds; psDroid->asWeaps[i].lastFired = 0; break; } @@ -3825,10 +3825,10 @@ void structureUpdate(STRUCTURE *psBuilding, bool bMission) } /*since self repair, then add half repair points depending on the time delay for the stat*/ - iPointsToAdd = (repairPoints(asRepairStats + aDefaultRepair[ - psBuilding->player], psBuilding->player) / 4) * ((gameTime - - psBuilding->lastResistance) / (asRepairStats + - aDefaultRepair[psBuilding->player])->time); + iPointsToAdd = (repairPoints(asRepairStats[aDefaultRepair[ + psBuilding->player]], psBuilding->player) / 4) * ((gameTime - + psBuilding->lastResistance) / asRepairStats[ + aDefaultRepair[psBuilding->player]].time); //add the blue flashing effect for multiPlayer if (bMultiPlayer && ONEINTEN && !bMission) @@ -4378,7 +4378,7 @@ bool validLocation(BASE_STATS *psStats, Vector2i pos, uint16_t direction, unsign } else if (psTemplate != nullptr) { - PROPULSION_STATS *psPropStats = asPropulsionStats + psTemplate->asParts[COMP_PROPULSION]; + PROPULSION_STATS *psPropStats = &asPropulsionStats[psTemplate->asParts[COMP_PROPULSION]]; if (fpathBlockingTile(b.map.x, b.map.y, psPropStats->propulsionType)) { @@ -5349,7 +5349,7 @@ static unsigned int countAssignedDroids(const STRUCTURE *psStructure) && psCurr->order.psObj->id == psStructure->id && psCurr->player == psStructure->player) { - const MOVEMENT_MODEL weapontype = asWeaponStats[psCurr->asWeaps[0].nStat].movementModel; + const MOVEMENT_MODEL weapontype = getWeaponStats(psCurr, 0)->movementModel; if (weapontype == MM_INDIRECT || weapontype == MM_HOMINGINDIRECT @@ -5523,7 +5523,7 @@ bool validTemplateForFactory(const DROID_TEMPLATE *psTemplate, STRUCTURE *psFact } //check for VTOL droid else if (psTemplate->asParts[COMP_PROPULSION] && - ((asPropulsionStats + psTemplate->asParts[COMP_PROPULSION])->propulsionType == PROPULSION_TYPE_LIFT)) + (asPropulsionStats[psTemplate->asParts[COMP_PROPULSION]].propulsionType == PROPULSION_TYPE_LIFT)) { if (psFactory->pStructureType->type != REF_VTOL_FACTORY) { @@ -5549,7 +5549,7 @@ bool validTemplateForFactory(const DROID_TEMPLATE *psTemplate, STRUCTURE *psFact else if (psFactory->pStructureType->type == REF_VTOL_FACTORY) { if (!psTemplate->asParts[COMP_PROPULSION] || - ((asPropulsionStats + psTemplate->asParts[COMP_PROPULSION])->propulsionType != PROPULSION_TYPE_LIFT)) + (asPropulsionStats[psTemplate->asParts[COMP_PROPULSION]].propulsionType != PROPULSION_TYPE_LIFT)) { debug(level, "Can only build vtol in vtol factory, not in %s.", objInfo(psFactory)); return false; @@ -5803,7 +5803,7 @@ void factoryReward(UBYTE losingPlayer, UBYTE rewardPlayer) ASSERT_OR_RETURN(, rewardPlayer < MAX_PLAYERS, "Invalid rewardPlayer id %d", (int)rewardPlayer); //search through the propulsions first - for (unsigned inc = 0; inc < numPropulsionStats; inc++) + for (unsigned inc = 0; inc < asPropulsionStats.size(); inc++) { if (apCompLists[losingPlayer][COMP_PROPULSION][inc] == AVAILABLE && apCompLists[rewardPlayer][COMP_PROPULSION][inc] != AVAILABLE) @@ -5825,7 +5825,7 @@ void factoryReward(UBYTE losingPlayer, UBYTE rewardPlayer) } //haven't found a propulsion - look for a body - for (unsigned inc = 0; inc < numBodyStats; inc++) + for (unsigned inc = 0; inc < asBodyStats.size(); inc++) { if (apCompLists[losingPlayer][COMP_BODY][inc] == AVAILABLE && apCompLists[rewardPlayer][COMP_BODY][inc] != AVAILABLE) @@ -5847,7 +5847,7 @@ void factoryReward(UBYTE losingPlayer, UBYTE rewardPlayer) } //haven't found a body - look for a weapon - for (unsigned inc = 0; inc < numWeaponStats; inc++) + for (unsigned inc = 0; inc < asWeaponStats.size(); inc++) { if (apCompLists[losingPlayer][COMP_WEAPON][inc] == AVAILABLE && apCompLists[rewardPlayer][COMP_WEAPON][inc] != AVAILABLE) @@ -5885,7 +5885,7 @@ void repairFacilityReward(UBYTE losingPlayer, UBYTE rewardPlayer) ASSERT_OR_RETURN(, rewardPlayer < MAX_PLAYERS, "Invalid rewardPlayer id %d", (int)rewardPlayer); //search through the repair stats - for (unsigned inc = 0; inc < numRepairStats; inc++) + for (unsigned inc = 0; inc < asRepairStats.size(); inc++) { if (apCompLists[losingPlayer][COMP_REPAIRUNIT][inc] == AVAILABLE && apCompLists[rewardPlayer][COMP_REPAIRUNIT][inc] != AVAILABLE) @@ -6520,10 +6520,11 @@ bool structSensorDroidWeapon(const STRUCTURE *psStruct, const DROID *psDroid) //Added a safety check: Only units with weapons can be assigned. if (psDroid->numWeaps > 0) { + const auto* weaponStats = getWeaponStats(psDroid, 0); //Standard Sensor Tower + indirect weapon droid (non VTOL) //else if (structStandardSensor(psStruct) && (psDroid->numWeaps && if (structStandardSensor(psStruct) && (psDroid->asWeaps[0].nStat > 0 && - !proj_Direct(asWeaponStats + psDroid->asWeaps[0].nStat)) && + !proj_Direct(weaponStats)) && !psDroid->isVtol()) { return true; @@ -6531,7 +6532,7 @@ bool structSensorDroidWeapon(const STRUCTURE *psStruct, const DROID *psDroid) //CB Sensor Tower + indirect weapon droid (non VTOL) //if (structCBSensor(psStruct) && (psDroid->numWeaps && else if (structCBSensor(psStruct) && (psDroid->asWeaps[0].nStat > 0 && - !proj_Direct(asWeaponStats + psDroid->asWeaps[0].nStat)) && + !proj_Direct(weaponStats)) && !psDroid->isVtol()) { return true; diff --git a/src/template.cpp b/src/template.cpp index e2e237c80e7..ead20666db4 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -404,40 +404,40 @@ nlohmann::json saveTemplateCommon(const DROID_TEMPLATE *psCurr) case DROID_DEFAULT: templateObj["type"] = "DROID"; break; default: ASSERT(false, "No such droid type \"%d\" for %s", psCurr->droidType, psCurr->name.toUtf8().c_str()); } - ASSERT(psCurr->asParts[COMP_BODY] < numBodyStats, "asParts[COMP_BODY] (%d) exceeds numBodyStats (%" PRIu32 ")", (int)psCurr->asParts[COMP_BODY], numBodyStats); - templateObj["body"] = (asBodyStats + psCurr->asParts[COMP_BODY])->id; - ASSERT(psCurr->asParts[COMP_PROPULSION] < numPropulsionStats, "asParts[COMP_PROPULSION] (%d) exceeds numPropulsionStats (%" PRIu32 ")", (int)psCurr->asParts[COMP_PROPULSION], numPropulsionStats); - templateObj["propulsion"] = (asPropulsionStats + psCurr->asParts[COMP_PROPULSION])->id; + ASSERT(psCurr->asParts[COMP_BODY] < asBodyStats.size(), "asParts[COMP_BODY] (%d) exceeds numBodyStats (%zu)", (int)psCurr->asParts[COMP_BODY], asBodyStats.size()); + templateObj["body"] = asBodyStats[psCurr->asParts[COMP_BODY]].id; + ASSERT(psCurr->asParts[COMP_PROPULSION] < asPropulsionStats.size(), "asParts[COMP_PROPULSION] (%d) exceeds numPropulsionStats (%zu)", (int)psCurr->asParts[COMP_PROPULSION], asPropulsionStats.size()); + templateObj["propulsion"] = asPropulsionStats[psCurr->asParts[COMP_PROPULSION]].id; if (psCurr->asParts[COMP_BRAIN] != 0) { - ASSERT(psCurr->asParts[COMP_BRAIN] < numBrainStats, "asParts[COMP_BRAIN] (%d) exceeds numBrainStats (%" PRIu32 ")", (int)psCurr->asParts[COMP_BRAIN], numBrainStats); - templateObj["brain"] = (asBrainStats + psCurr->asParts[COMP_BRAIN])->id; + ASSERT(psCurr->asParts[COMP_BRAIN] < asBrainStats.size(), "asParts[COMP_BRAIN] (%d) exceeds numBrainStats (%zu)", (int)psCurr->asParts[COMP_BRAIN], asBrainStats.size()); + templateObj["brain"] = asBrainStats[psCurr->asParts[COMP_BRAIN]].id; } - if ((asRepairStats + psCurr->asParts[COMP_REPAIRUNIT])->location == LOC_TURRET) // avoid auto-repair... + if (asRepairStats[psCurr->asParts[COMP_REPAIRUNIT]].location == LOC_TURRET) // avoid auto-repair... { - ASSERT(psCurr->asParts[COMP_REPAIRUNIT] < numRepairStats, "asParts[COMP_REPAIRUNIT] (%d) exceeds numRepairStats (%" PRIu32 ")", (int)psCurr->asParts[COMP_REPAIRUNIT], numRepairStats); - templateObj["repair"] = (asRepairStats + psCurr->asParts[COMP_REPAIRUNIT])->id; + ASSERT(psCurr->asParts[COMP_REPAIRUNIT] < asRepairStats.size(), "asParts[COMP_REPAIRUNIT] (%d) exceeds numRepairStats (%zu)", (int)psCurr->asParts[COMP_REPAIRUNIT], asRepairStats.size()); + templateObj["repair"] = asRepairStats[psCurr->asParts[COMP_REPAIRUNIT]].id; } - if ((asECMStats + psCurr->asParts[COMP_ECM])->location == LOC_TURRET) + if (asECMStats[psCurr->asParts[COMP_ECM]].location == LOC_TURRET) { - ASSERT(psCurr->asParts[COMP_ECM] < numECMStats, "asParts[COMP_ECM] (%d) exceeds numECMStats (%" PRIu32 ")", (int)psCurr->asParts[COMP_ECM], numECMStats); - templateObj["ecm"] = (asECMStats + psCurr->asParts[COMP_ECM])->id; + ASSERT(psCurr->asParts[COMP_ECM] < asECMStats.size(), "asParts[COMP_ECM] (%d) exceeds numECMStats (%zu)", (int)psCurr->asParts[COMP_ECM], asECMStats.size()); + templateObj["ecm"] = asECMStats[psCurr->asParts[COMP_ECM]].id; } - if ((asSensorStats + psCurr->asParts[COMP_SENSOR])->location == LOC_TURRET) + if (asSensorStats[psCurr->asParts[COMP_SENSOR]].location == LOC_TURRET) { - ASSERT(psCurr->asParts[COMP_SENSOR] < numSensorStats, "asParts[COMP_SENSOR] (%d) exceeds numSensorStats (%" PRIu32 ")", (int)psCurr->asParts[COMP_SENSOR], numSensorStats); - templateObj["sensor"] = (asSensorStats + psCurr->asParts[COMP_SENSOR])->id; + ASSERT(psCurr->asParts[COMP_SENSOR] < asSensorStats.size(), "asParts[COMP_SENSOR] (%d) exceeds numSensorStats (%zu)", (int)psCurr->asParts[COMP_SENSOR], asSensorStats.size()); + templateObj["sensor"] = asSensorStats[psCurr->asParts[COMP_SENSOR]].id; } if (psCurr->asParts[COMP_CONSTRUCT] != 0) { - ASSERT(psCurr->asParts[COMP_CONSTRUCT] < numConstructStats, "asParts[COMP_CONSTRUCT] (%d) exceeds numConstructStats (%" PRIu32 ")", (int)psCurr->asParts[COMP_CONSTRUCT], numConstructStats); - templateObj["construct"] = (asConstructStats + psCurr->asParts[COMP_CONSTRUCT])->id; + ASSERT(psCurr->asParts[COMP_CONSTRUCT] < asConstructStats.size(), "asParts[COMP_CONSTRUCT] (%d) exceeds numConstructStats (%zu)", (int)psCurr->asParts[COMP_CONSTRUCT], asConstructStats.size()); + templateObj["construct"] = asConstructStats[psCurr->asParts[COMP_CONSTRUCT]].id; } nlohmann::json weapons = nlohmann::json::array(); for (int j = 0; j < psCurr->numWeaps; j++) { - ASSERT(psCurr->asWeaps[j] < numWeaponStats, "psCurr->asWeaps[%d] (%d) exceeds numWeaponStats (%" PRIu32 ")", j, (int)psCurr->asWeaps[j], numWeaponStats); - weapons.push_back((asWeaponStats + psCurr->asWeaps[j])->id); + ASSERT(psCurr->asWeaps[j] < asWeaponStats.size(), "psCurr->asWeaps[%d] (%d) exceeds numWeaponStats (%zu)", j, (int)psCurr->asWeaps[j], asWeaponStats.size()); + weapons.push_back(asWeaponStats[psCurr->asWeaps[j]].id); } if (!weapons.empty()) { @@ -743,7 +743,7 @@ bool templateIsIDF(const DROID_TEMPLATE *psTemplate) return false; } - if (proj_Direct(psTemplate->asWeaps[0] + asWeaponStats)) + if (proj_Direct(&asWeaponStats[psTemplate->asWeaps[0]])) { return false; } @@ -799,14 +799,14 @@ std::vector fillTemplateList(STRUCTURE *psFactory) } //check the factory can cope with this sized body - if (((asBodyStats + psCurr->asParts[COMP_BODY])->size <= iCapacity)) + if (asBodyStats[psCurr->asParts[COMP_BODY]].size <= iCapacity) { pList.push_back(psCurr); } else if (bMultiPlayer && (iCapacity == SIZE_HEAVY)) { // Special case for Super heavy bodyies (Super Transporter) - if ((asBodyStats + psCurr->asParts[COMP_BODY])->size == SIZE_SUPER_HEAVY) + if (asBodyStats[psCurr->asParts[COMP_BODY]].size == SIZE_SUPER_HEAVY) { pList.push_back(psCurr); } diff --git a/src/transporter.cpp b/src/transporter.cpp index 0795d648169..23703a6d48f 100644 --- a/src/transporter.cpp +++ b/src/transporter.cpp @@ -1121,7 +1121,7 @@ int transporterSpaceRequired(const DROID *psDroid) { // all droids are the same weight for campaign games. // TODO - move this into a droid flag - return bMultiPlayer ? (asBodyStats + psDroid->asBits[COMP_BODY])->size + 1 : 1; + return bMultiPlayer ? getBodyStats(psDroid)->size + 1 : 1; } /*sets which list of droids to use for the transporter interface*/ diff --git a/src/visibility.cpp b/src/visibility.cpp index 4a68397777e..bf339682204 100644 --- a/src/visibility.cpp +++ b/src/visibility.cpp @@ -960,15 +960,15 @@ bool lineOfFire(const SIMPLE_OBJECT *psViewer, const BASE_OBJECT *psTarget, int if (psViewer->type == OBJ_DROID) { - psStats = asWeaponStats + ((const DROID *)psViewer)->asWeaps[weapon_slot].nStat; + psStats = getWeaponStats((const DROID*)psViewer, weapon_slot); } else if (psViewer->type == OBJ_STRUCTURE) { - psStats = asWeaponStats + ((const STRUCTURE *)psViewer)->asWeaps[weapon_slot].nStat; + psStats = &asWeaponStats[((const STRUCTURE *)psViewer)->asWeaps[weapon_slot].nStat]; } // 2d distance int distance = iHypot((psTarget->pos - psViewer->pos).xy()); - int range = proj_GetLongRange(psStats, psViewer->player); + int range = proj_GetLongRange(*psStats, psViewer->player); if (proj_Direct(psStats)) { /** direct shots could collide with ground **/ diff --git a/src/visibility.h b/src/visibility.h index b4387dfab2f..19e1de94808 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -24,6 +24,7 @@ #include "objectdef.h" #include "raycast.h" #include "stats.h" +#include "droid.h" #define LINE_OF_FIRE_MINIMUM 5 @@ -76,16 +77,16 @@ static inline bool visObjInRange(const BASE_OBJECT *psObj1, const BASE_OBJECT *p // If we have ECM, use this for range instead. Otherwise, the sensor's range will be used for // jamming range, which we do not want. Rather limit ECM unit sensor range to jammer range. -static inline int objSensorRange(const BASE_OBJECT *psObj) +inline int objSensorRange(const BASE_OBJECT *psObj) { if (psObj->type == OBJ_DROID) { - const int ecmrange = asECMStats[((const DROID *)psObj)->asBits[COMP_ECM]].upgrade[psObj->player].range; + const int ecmrange = getECMStats((const DROID*)psObj)->upgrade[psObj->player].range; if (ecmrange > 0) { return ecmrange; } - return asSensorStats[((const DROID *)psObj)->asBits[COMP_SENSOR]].upgrade[psObj->player].range; + return getSensorStats((const DROID*)psObj)->upgrade[psObj->player].range; } else if (psObj->type == OBJ_STRUCTURE) { @@ -103,7 +104,7 @@ static inline int objJammerPower(const BASE_OBJECT *psObj) { if (psObj->type == OBJ_DROID) { - return asECMStats[((const DROID *)psObj)->asBits[COMP_ECM]].upgrade[psObj->player].range; + return getECMStats((const DROID *)psObj)->upgrade[psObj->player].range; } else if (psObj->type == OBJ_STRUCTURE) { diff --git a/src/warcam.cpp b/src/warcam.cpp index 4ec0f480f8f..bb54a9350cd 100644 --- a/src/warcam.cpp +++ b/src/warcam.cpp @@ -563,7 +563,7 @@ static void updateCameraAcceleration(UBYTE update) */ const int angle = 90 - abs((playerPos.r.x / 182) % 90); - const PROPULSION_STATS *psPropStats = &asPropulsionStats[trackingCamera.target->asBits[COMP_PROPULSION]]; + const PROPULSION_STATS *psPropStats = getPropulsionStats(trackingCamera.target); if (psPropStats->propulsionType == PROPULSION_TYPE_LIFT) { @@ -675,7 +675,7 @@ static void updateCameraRotationAcceleration(UBYTE update) SDWORD xPos = 0, yPos = 0, zPos = 0; bTooLow = false; - psPropStats = asPropulsionStats + trackingCamera.target->asBits[COMP_PROPULSION]; + psPropStats = getPropulsionStats(trackingCamera.target); if (psPropStats->propulsionType == PROPULSION_TYPE_LIFT) { int droidHeight, difHeight, droidMapHeight; @@ -838,7 +838,7 @@ static bool camTrackCamera() /* Update the acceleration,velocity and rotation of the camera for rotation */ /* You can track roll as well (z axis) but it makes you ill and looks like a flight sim, so for now just pitch and orientation */ - psPropStats = asPropulsionStats + trackingCamera.target->asBits[COMP_PROPULSION]; + psPropStats = getPropulsionStats(trackingCamera.target); if (psPropStats->propulsionType == PROPULSION_TYPE_LIFT) { bFlying = true; diff --git a/src/wzapi.cpp b/src/wzapi.cpp index 24ccb093e99..5e459286f57 100644 --- a/src/wzapi.cpp +++ b/src/wzapi.cpp @@ -1577,7 +1577,7 @@ optional wzapi::pickStructLocation(WZAPI_PARAMS(const DROID *psDro Vector2i offset(psStat->baseWidth * (TILE_UNITS / 2), psStat->baseBreadth * (TILE_UNITS / 2)); - PROPULSION_TYPE propType = (psDroid) ? asPropulsionStats[psDroid->asBits[COMP_PROPULSION]].propulsionType : PROPULSION_TYPE_WHEELED; + PROPULSION_TYPE propType = (psDroid) ? getPropulsionStats(psDroid)->propulsionType : PROPULSION_TYPE_WHEELED; // save a lot of typing... checks whether a position is valid #define LOC_OK(_x, _y) (tileOnMap(_x, _y) && \ @@ -1651,7 +1651,7 @@ optional wzapi::pickStructLocation(WZAPI_PARAMS(const DROID *psDro bool wzapi::droidCanReach(WZAPI_PARAMS(const DROID *psDroid, int x, int y)) { SCRIPT_ASSERT(false, context, psDroid, "No valid droid provided"); - const PROPULSION_STATS *psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION]; + const PROPULSION_STATS* psPropStats = getPropulsionStats(psDroid); return fpathCheck(psDroid->pos, Vector3i(world_coord(x), world_coord(y), 0), psPropStats->propulsionType); } @@ -1664,7 +1664,7 @@ bool wzapi::propulsionCanReach(WZAPI_PARAMS(std::string propulsionName, int x1, { int propulsionIndex = getCompFromName(COMP_PROPULSION, WzString::fromUtf8(propulsionName)); SCRIPT_ASSERT(false, context, propulsionIndex > 0, "No such propulsion: %s", propulsionName.c_str()); - const PROPULSION_STATS *psPropStats = asPropulsionStats + propulsionIndex; + const PROPULSION_STATS *psPropStats = &asPropulsionStats[propulsionIndex]; return fpathCheck(Vector3i(world_coord(x1), world_coord(y1), 0), Vector3i(world_coord(x2), world_coord(y2), 0), psPropStats->propulsionType); } @@ -2320,7 +2320,7 @@ nlohmann::json wzapi::getWeaponInfo(WZAPI_PARAMS(std::string weaponName)) WZAPI_ { int weaponIndex = getCompFromName(COMP_WEAPON, WzString::fromUtf8(weaponName)); SCRIPT_ASSERT(nlohmann::json(), context, weaponIndex >= 0, "No such weapon: %s", weaponName.c_str()); - WEAPON_STATS *psStats = asWeaponStats + weaponIndex; + WEAPON_STATS *psStats = &asWeaponStats[weaponIndex]; nlohmann::json result = nlohmann::json::object(); result["id"] = weaponName; result["name"] = psStats->name; @@ -3397,8 +3397,8 @@ bool wzapi::setUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::string& nam syncDebug("stats[p%d,t%d,%s,i%d] = %d", player, type, name.c_str(), index, value); if (type == COMP_BODY) { - SCRIPT_ASSERT(false, context, index < numBodyStats, "Bad index"); - BODY_STATS *psStats = asBodyStats + index; + SCRIPT_ASSERT(false, context, index < asBodyStats.size(), "Bad index"); + BODY_STATS *psStats = &asBodyStats[index]; if (name == "HitPoints") { psStats->upgrade[player].hitpoints = value; @@ -3434,8 +3434,8 @@ bool wzapi::setUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::string& nam } else if (type == COMP_BRAIN) { - SCRIPT_ASSERT(false, context, index < numBrainStats, "Bad index"); - BRAIN_STATS *psStats = asBrainStats + index; + SCRIPT_ASSERT(false, context, index < asBrainStats.size(), "Bad index"); + BRAIN_STATS *psStats = &asBrainStats[index]; if (name == "BaseCommandLimit") { psStats->upgrade[player].maxDroids = value; @@ -3472,8 +3472,8 @@ bool wzapi::setUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::string& nam } else if (type == COMP_SENSOR) { - SCRIPT_ASSERT(false, context, index < numSensorStats, "Bad index"); - SENSOR_STATS *psStats = asSensorStats + index; + SCRIPT_ASSERT(false, context, index < asSensorStats.size(), "Bad index"); + SENSOR_STATS *psStats = &asSensorStats[index]; if (name == "Range") { psStats->upgrade[player].range = value; @@ -3497,8 +3497,8 @@ bool wzapi::setUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::string& nam } else if (type == COMP_ECM) { - SCRIPT_ASSERT(false, context, index < numECMStats, "Bad index"); - ECM_STATS *psStats = asECMStats + index; + SCRIPT_ASSERT(false, context, index < asECMStats.size(), "Bad index"); + ECM_STATS *psStats = &asECMStats[index]; if (name == "Range") { psStats->upgrade[player].range = value; @@ -3522,8 +3522,8 @@ bool wzapi::setUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::string& nam } else if (type == COMP_PROPULSION) { - SCRIPT_ASSERT(false, context, index < numPropulsionStats, "Bad index"); - PROPULSION_STATS *psStats = asPropulsionStats + index; + SCRIPT_ASSERT(false, context, index < asPropulsionStats.size(), "Bad index"); + PROPULSION_STATS *psStats = &asPropulsionStats[index]; if (name == "HitPoints") { psStats->upgrade[player].hitpoints = value; @@ -3546,8 +3546,8 @@ bool wzapi::setUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::string& nam } else if (type == COMP_CONSTRUCT) { - SCRIPT_ASSERT(false, context, index < numConstructStats, "Bad index"); - CONSTRUCT_STATS *psStats = asConstructStats + index; + SCRIPT_ASSERT(false, context, index < asConstructStats.size(), "Bad index"); + CONSTRUCT_STATS *psStats = &asConstructStats[index]; if (name == "ConstructorPoints") { psStats->upgrade[player].constructPoints = value; @@ -3569,8 +3569,8 @@ bool wzapi::setUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::string& nam } else if (type == COMP_REPAIRUNIT) { - SCRIPT_ASSERT(false, context, index < numRepairStats, "Bad index"); - REPAIR_STATS *psStats = asRepairStats + index; + SCRIPT_ASSERT(false, context, index < asRepairStats.size(), "Bad index"); + REPAIR_STATS *psStats = &asRepairStats[index]; if (name == "RepairPoints") { psStats->upgrade[player].repairPoints = value; @@ -3592,8 +3592,8 @@ bool wzapi::setUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::string& nam } else if (type == COMP_WEAPON) { - SCRIPT_ASSERT(false, context, index < numWeaponStats, "Bad index"); - WEAPON_STATS *psStats = asWeaponStats + index; + SCRIPT_ASSERT(false, context, index < asWeaponStats.size(), "Bad index"); + WEAPON_STATS *psStats = &asWeaponStats[index]; if (name == "MaxRange") { psStats->upgrade[player].maxRange = value; @@ -3744,8 +3744,8 @@ nlohmann::json wzapi::getUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::s { if (type == COMP_BODY) { - SCRIPT_ASSERT(nlohmann::json(), context, index < numBodyStats, "Bad index"); - const BODY_STATS *psStats = asBodyStats + index; + SCRIPT_ASSERT(nlohmann::json(), context, index < asBodyStats.size(), "Bad index"); + const BODY_STATS *psStats = &asBodyStats[index]; if (name == "HitPoints") { return psStats->upgrade[player].hitpoints; @@ -3777,8 +3777,8 @@ nlohmann::json wzapi::getUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::s } else if (type == COMP_BRAIN) { - SCRIPT_ASSERT(nlohmann::json(), context, index < numBrainStats, "Bad index"); - const BRAIN_STATS *psStats = asBrainStats + index; + SCRIPT_ASSERT(nlohmann::json(), context, index < asBrainStats.size(), "Bad index"); + const BRAIN_STATS *psStats = &asBrainStats[index]; if (name == "BaseCommandLimit") { return psStats->upgrade[player].maxDroids; @@ -3812,8 +3812,8 @@ nlohmann::json wzapi::getUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::s } else if (type == COMP_SENSOR) { - SCRIPT_ASSERT(nlohmann::json(), context, index < numSensorStats, "Bad index"); - const SENSOR_STATS *psStats = asSensorStats + index; + SCRIPT_ASSERT(nlohmann::json(), context, index < asSensorStats.size(), "Bad index"); + const SENSOR_STATS *psStats = &asSensorStats[index]; if (name == "Range") { return psStats->upgrade[player].range; @@ -3833,8 +3833,8 @@ nlohmann::json wzapi::getUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::s } else if (type == COMP_ECM) { - SCRIPT_ASSERT(nlohmann::json(), context, index < numECMStats, "Bad index"); - const ECM_STATS *psStats = asECMStats + index; + SCRIPT_ASSERT(nlohmann::json(), context, index < asECMStats.size(), "Bad index"); + const ECM_STATS *psStats = &asECMStats[index]; if (name == "Range") { return psStats->upgrade[player].range; @@ -3854,8 +3854,8 @@ nlohmann::json wzapi::getUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::s } else if (type == COMP_PROPULSION) { - SCRIPT_ASSERT(nlohmann::json(), context, index < numPropulsionStats, "Bad index"); - const PROPULSION_STATS *psStats = asPropulsionStats + index; + SCRIPT_ASSERT(nlohmann::json(), context, index < asPropulsionStats.size(), "Bad index"); + const PROPULSION_STATS *psStats = &asPropulsionStats[index]; if (name == "HitPoints") { return psStats->upgrade[player].hitpoints; @@ -3875,8 +3875,8 @@ nlohmann::json wzapi::getUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::s } else if (type == COMP_CONSTRUCT) { - SCRIPT_ASSERT(nlohmann::json(), context, index < numConstructStats, "Bad index"); - const CONSTRUCT_STATS *psStats = asConstructStats + index; + SCRIPT_ASSERT(nlohmann::json(), context, index < asConstructStats.size(), "Bad index"); + const CONSTRUCT_STATS *psStats = &asConstructStats[index]; if (name == "ConstructorPoints") { return psStats->upgrade[player].constructPoints; @@ -3896,8 +3896,8 @@ nlohmann::json wzapi::getUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::s } else if (type == COMP_REPAIRUNIT) { - SCRIPT_ASSERT(nlohmann::json(), context, index < numRepairStats, "Bad index"); - const REPAIR_STATS *psStats = asRepairStats + index; + SCRIPT_ASSERT(nlohmann::json(), context, index < asRepairStats.size(), "Bad index"); + const REPAIR_STATS *psStats = &asRepairStats[index]; if (name == "RepairPoints") { return psStats->upgrade[player].repairPoints; @@ -3917,8 +3917,8 @@ nlohmann::json wzapi::getUpgradeStats(WZAPI_BASE_PARAMS(int player, const std::s } else if (type == COMP_WEAPON) { - SCRIPT_ASSERT(nlohmann::json(), context, index < numWeaponStats, "Bad index"); - const WEAPON_STATS *psStats = asWeaponStats + index; + SCRIPT_ASSERT(nlohmann::json(), context, index < asWeaponStats.size(), "Bad index"); + const WEAPON_STATS *psStats = &asWeaponStats[index]; if (name == "MaxRange") { return psStats->upgrade[player].maxRange; @@ -4061,9 +4061,9 @@ std::vector wzapi::getUpgradesObject() //== * ```Body``` Droid bodies GameEntityRuleContainer bodybase; - for (unsigned j = 0; j < numBodyStats; j++) + for (unsigned j = 0; j < asBodyStats.size(); j++) { - BODY_STATS *psStats = asBodyStats + j; + BODY_STATS *psStats = &asBodyStats[j]; GameEntityRules body(i, j, { {"HitPoints", COMP_BODY}, {"HitPointPct", COMP_BODY}, @@ -4078,9 +4078,9 @@ std::vector wzapi::getUpgradesObject() //== * ```Sensor``` Sensor turrets GameEntityRuleContainer sensorbase; - for (unsigned j = 0; j < numSensorStats; j++) + for (unsigned j = 0; j < asSensorStats.size(); j++) { - SENSOR_STATS *psStats = asSensorStats + j; + SENSOR_STATS *psStats = &asSensorStats[j]; GameEntityRules sensor(i, j, { {"HitPoints", COMP_SENSOR}, {"HitPointPct", COMP_SENSOR}, @@ -4092,9 +4092,9 @@ std::vector wzapi::getUpgradesObject() //== * ```Propulsion``` Propulsions GameEntityRuleContainer propbase; - for (unsigned j = 0; j < numPropulsionStats; j++) + for (unsigned j = 0; j < asPropulsionStats.size(); j++) { - PROPULSION_STATS *psStats = asPropulsionStats + j; + PROPULSION_STATS *psStats = &asPropulsionStats[j]; GameEntityRules v(i, j, { {"HitPoints", COMP_PROPULSION}, {"HitPointPct", COMP_PROPULSION}, @@ -4106,9 +4106,9 @@ std::vector wzapi::getUpgradesObject() //== * ```ECM``` ECM (Electronic Counter-Measure) turrets GameEntityRuleContainer ecmbase; - for (unsigned j = 0; j < numECMStats; j++) + for (unsigned j = 0; j < asECMStats.size(); j++) { - ECM_STATS *psStats = asECMStats + j; + ECM_STATS *psStats = &asECMStats[j]; GameEntityRules ecm(i, j, { {"Range", COMP_ECM}, {"HitPoints", COMP_ECM}, @@ -4120,9 +4120,9 @@ std::vector wzapi::getUpgradesObject() //== * ```Repair``` Repair turrets (not used, incidentally, for repair centers) GameEntityRuleContainer repairbase; - for (unsigned j = 0; j < numRepairStats; j++) + for (unsigned j = 0; j < asRepairStats.size(); j++) { - REPAIR_STATS *psStats = asRepairStats + j; + REPAIR_STATS *psStats = &asRepairStats[j]; GameEntityRules repair(i, j, { {"RepairPoints", COMP_REPAIRUNIT}, {"HitPoints", COMP_REPAIRUNIT}, @@ -4134,9 +4134,9 @@ std::vector wzapi::getUpgradesObject() //== * ```Construct``` Constructor turrets (eg for trucks) GameEntityRuleContainer conbase; - for (unsigned j = 0; j < numConstructStats; j++) + for (unsigned j = 0; j < asConstructStats.size(); j++) { - CONSTRUCT_STATS *psStats = asConstructStats + j; + CONSTRUCT_STATS *psStats = &asConstructStats[j]; GameEntityRules con(i, j, { {"ConstructorPoints", COMP_CONSTRUCT}, {"HitPoints", COMP_CONSTRUCT}, @@ -4152,9 +4152,9 @@ std::vector wzapi::getUpgradesObject() //== kills are required for this brain to level up to the next rank. To alter this from scripts, you must //== set the entire array at once. Setting each item in the array will not work at the moment. GameEntityRuleContainer brainbase; - for (unsigned j = 0; j < numBrainStats; j++) + for (unsigned j = 0; j < asBrainStats.size(); j++) { - BRAIN_STATS *psStats = asBrainStats + j; + BRAIN_STATS *psStats = &asBrainStats[j]; GameEntityRules br(i, j, { {"BaseCommandLimit", COMP_BRAIN}, {"CommandLimitByLevel", COMP_BRAIN}, @@ -4168,9 +4168,9 @@ std::vector wzapi::getUpgradesObject() //== * ```Weapon``` Weapon turrets GameEntityRuleContainer wbase; - for (unsigned j = 0; j < numWeaponStats; j++) + for (unsigned j = 0; j < asWeaponStats.size(); j++) { - WEAPON_STATS *psStats = asWeaponStats + j; + WEAPON_STATS *psStats = &asWeaponStats[j]; GameEntityRules weap(i, j, { {"MaxRange", COMP_WEAPON}, {"ShortRange", COMP_WEAPON}, @@ -4245,9 +4245,9 @@ nlohmann::json wzapi::constructStatsObject() { //== * ```Body``` Droid bodies nlohmann::json bodybase = nlohmann::json::object(); - for (int j = 0; j < numBodyStats; j++) + for (int j = 0; j < asBodyStats.size(); j++) { - BODY_STATS *psStats = asBodyStats + j; + BODY_STATS *psStats = &asBodyStats[j]; nlohmann::json body = register_common(psStats); body["Power"] = psStats->base.power; body["Armour"] = psStats->base.armour; @@ -4262,9 +4262,9 @@ nlohmann::json wzapi::constructStatsObject() //== * ```Sensor``` Sensor turrets nlohmann::json sensorbase = nlohmann::json::object(); - for (int j = 0; j < numSensorStats; j++) + for (int j = 0; j < asSensorStats.size(); j++) { - SENSOR_STATS *psStats = asSensorStats + j; + SENSOR_STATS *psStats = &asSensorStats[j]; nlohmann::json sensor = register_common(psStats); sensor["Range"] = psStats->base.range; sensorbase[psStats->name.toUtf8()] = std::move(sensor); @@ -4273,9 +4273,9 @@ nlohmann::json wzapi::constructStatsObject() //== * ```ECM``` ECM (Electronic Counter-Measure) turrets nlohmann::json ecmbase = nlohmann::json::object(); - for (int j = 0; j < numECMStats; j++) + for (int j = 0; j < asECMStats.size(); j++) { - ECM_STATS *psStats = asECMStats + j; + ECM_STATS *psStats = &asECMStats[j]; nlohmann::json ecm = register_common(psStats); ecm["Range"] = psStats->base.range; ecmbase[psStats->name.toUtf8()] = std::move(ecm); @@ -4284,9 +4284,9 @@ nlohmann::json wzapi::constructStatsObject() //== * ```Propulsion``` Propulsions nlohmann::json propbase = nlohmann::json::object(); - for (int j = 0; j < numPropulsionStats; j++) + for (int j = 0; j < asPropulsionStats.size(); j++) { - PROPULSION_STATS *psStats = asPropulsionStats + j; + PROPULSION_STATS *psStats = &asPropulsionStats[j]; nlohmann::json v = register_common(psStats); v["HitpointPctOfBody"] = psStats->base.hitpointPctOfBody; v["MaxSpeed"] = psStats->maxSpeed; @@ -4302,9 +4302,9 @@ nlohmann::json wzapi::constructStatsObject() //== * ```Repair``` Repair turrets (not used, incidentally, for repair centers) nlohmann::json repairbase = nlohmann::json::object(); - for (int j = 0; j < numRepairStats; j++) + for (int j = 0; j < asRepairStats.size(); j++) { - REPAIR_STATS *psStats = asRepairStats + j; + REPAIR_STATS *psStats = &asRepairStats[j]; nlohmann::json repair = register_common(psStats); repair["RepairPoints"] = psStats->base.repairPoints; repairbase[psStats->name.toUtf8()] = std::move(repair); @@ -4313,9 +4313,9 @@ nlohmann::json wzapi::constructStatsObject() //== * ```Construct``` Constructor turrets (eg for trucks) nlohmann::json conbase = nlohmann::json::object(); - for (int j = 0; j < numConstructStats; j++) + for (int j = 0; j < asConstructStats.size(); j++) { - CONSTRUCT_STATS *psStats = asConstructStats + j; + CONSTRUCT_STATS *psStats = &asConstructStats[j]; nlohmann::json con = register_common(psStats); con["ConstructorPoints"] = psStats->base.constructPoints; conbase[psStats->name.toUtf8()] = std::move(con); @@ -4324,9 +4324,9 @@ nlohmann::json wzapi::constructStatsObject() //== * ```Brain``` Brains nlohmann::json brainbase = nlohmann::json::object(); - for (int j = 0; j < numBrainStats; j++) + for (int j = 0; j < asBrainStats.size(); j++) { - BRAIN_STATS *psStats = asBrainStats + j; + BRAIN_STATS *psStats = &asBrainStats[j]; nlohmann::json br = register_common(psStats); br["BaseCommandLimit"] = psStats->base.maxDroids; br["CommandLimitByLevel"] = psStats->base.maxDroidsMult; @@ -4348,9 +4348,9 @@ nlohmann::json wzapi::constructStatsObject() //== * ```Weapon``` Weapon turrets nlohmann::json wbase = nlohmann::json::object(); - for (int j = 0; j < numWeaponStats; j++) + for (int j = 0; j < asWeaponStats.size(); j++) { - WEAPON_STATS *psStats = asWeaponStats + j; + WEAPON_STATS *psStats = &asWeaponStats[j]; nlohmann::json weap = register_common(psStats); weap["MaxRange"] = psStats->base.maxRange; weap["ShortRange"] = psStats->base.shortRange; diff --git a/src/wzscriptdebug.cpp b/src/wzscriptdebug.cpp index a867f730f64..740b82d1888 100644 --- a/src/wzscriptdebug.cpp +++ b/src/wzscriptdebug.cpp @@ -2650,7 +2650,7 @@ void WZScriptDebugger::selected(const BASE_OBJECT *psObj) { if (psObj->asWeaps[i].nStat > 0) { - WEAPON_STATS *psWeap = asWeaponStats + psObj->asWeaps[i].nStat; + WEAPON_STATS *psWeap = &asWeaponStats[psObj->asWeaps[i].nStat]; auto component = componentToString(psWeap, psObj->player); component["Ammo"] = psObj->asWeaps[i].ammo; component["Last fired time"] = psObj->asWeaps[i].lastFired; @@ -2694,13 +2694,13 @@ void WZScriptDebugger::selected(const BASE_OBJECT *psObj) selectedObjectDetails["Move pause time"] = psDroid->sMove.pauseTime; selectedObjectDetails["Move shuffle start"] = psDroid->sMove.shuffleStart; selectedObjectDetails["Move vert speed"] = psDroid->sMove.iVertSpeed; - selectedObjectDetails["Body"] = componentToString(asBodyStats + psDroid->asBits[COMP_BODY], psObj->player); - selectedObjectDetails["Brain"] = componentToString(asBrainStats + psDroid->asBits[COMP_BRAIN], psObj->player); - selectedObjectDetails["Propulsion"] = componentToString(asPropulsionStats + psDroid->asBits[COMP_PROPULSION], psObj->player); - selectedObjectDetails["ECM"] = componentToString(asECMStats + psDroid->asBits[COMP_ECM], psObj->player); - selectedObjectDetails["Sensor"] = componentToString(asSensorStats + psDroid->asBits[COMP_SENSOR], psObj->player); - selectedObjectDetails["Construct"] = componentToString(asConstructStats + psDroid->asBits[COMP_CONSTRUCT], psObj->player); - selectedObjectDetails["Repair"] = componentToString(asRepairStats + psDroid->asBits[COMP_REPAIRUNIT], psObj->player); + selectedObjectDetails["Body"] = componentToString(getBodyStats(psDroid), psObj->player); + selectedObjectDetails["Brain"] = componentToString(getBrainStats(psDroid), psObj->player); + selectedObjectDetails["Propulsion"] = componentToString(getPropulsionStats(psDroid), psObj->player); + selectedObjectDetails["ECM"] = componentToString(getECMStats(psDroid), psObj->player); + selectedObjectDetails["Sensor"] = componentToString(getSensorStats(psDroid), psObj->player); + selectedObjectDetails["Construct"] = componentToString(getConstructStats(psDroid), psObj->player); + selectedObjectDetails["Repair"] = componentToString(getRepairStats(psDroid), psObj->player); } else if (psObj->type == OBJ_STRUCTURE) {