diff --git a/Tactical/DisplayCover.cpp b/Tactical/DisplayCover.cpp index 0d1b6e8d1..d61b06409 100644 --- a/Tactical/DisplayCover.cpp +++ b/Tactical/DisplayCover.cpp @@ -1,4 +1,3 @@ -#include "builddefines.h" #include "types.h" #include "Isometric Utils.h" #include "Overhead.h" @@ -22,19 +21,16 @@ #include "Interface Cursors.h" // added by Flugente for UICursorDefines #include "Rebel Command.h" -//forward declarations of common classes to eliminate includes -class OBJECTTYPE; -class SOLDIERTYPE; //******* Local Defines ************************************************** - struct CoverCell { INT32 sGridNo; - INT8 bOverlayType; + INT8 bOverlayType; + bool onRoof; - CoverCell( ) : sGridNo( NOWHERE ), bOverlayType( INVALID_COVER ) {} + CoverCell( ) : sGridNo( NOWHERE ), bOverlayType( INVALID_COVER ), onRoof( false ) {} }; const UINT8 animArr[3] = { @@ -43,16 +39,12 @@ const UINT8 animArr[3] = { ANIM_STAND }; -// yea way too big... but some bytes more memory is cheap -#define COVER_X_CELLS WORLD_COLS_MAX -#define COVER_Y_CELLS WORLD_ROWS_MAX -#define COVER_Z_CELLS 2 // roof or no roof //****** Local Variables ********************************************* INT16 gsMinCellX, gsMinCellY, gsMaxCellX, gsMaxCellY = -1; -CoverCell gCoverViewArea[ COVER_X_CELLS ][ COVER_Y_CELLS ][ COVER_Z_CELLS ]; +std::vector gCoverViewArea; DWORD guiCoverNextUpdateTime = 0; @@ -73,13 +65,13 @@ void RemoveCoverObjectFromWorld( INT32 sGridNo, UINT16 usGraphic, BOOLEAN fRoof void AddCoverObjectsToViewArea(); void RemoveCoverObjectsFromViewArea(); -void CalculateCover(); -void CalculateCoverFromEnemies(); -void CalculateMines(); -void CalculateTraitRange(); -void CalculateTrackerRange(); -void CalculateFortify(); -void CalculateWeapondata(); +void CalculateCover(); +void CalculateCoverFromEnemies(); +void CalculateMines(); +void CalculateTraitRange(); +void CalculateTrackerRange(); +void CalculateFortify(); +void CalculateWeapondata(); void CalculateCoverFromEnemySoldier(SOLDIERTYPE* pFromSoldier, const INT32& sTargetGridNo, const BOOLEAN& fRoof, INT8& bOverlayType, SOLDIERTYPE* pToSoldier, const BOOLEAN& bFromSoldierCowering, const UINT8& tunnelVision, const INT8 ToSoldierStealth, const INT8 ToSoldierLBeSightAdjustment); @@ -89,7 +81,7 @@ void GetGridNoForViewPort( const INT32& ubX, const INT32& ubY, INT32& sGridNo ); BOOLEAN GridNoOnScreenAndAround( const INT32& sGridNo, const UINT8& ubRadius=2 ); BOOLEAN IsTheRoofVisible( const INT32& sGridNo ); -BOOLEAN HasAdjTile(const INT32& ubX, const INT32& ubY, const INT32& ubZ); +BOOLEAN HasAdjTile(const INT32 startIndex, const bool onRoof); static TileDefines GetOverlayIndex( INT8 bOverlayType ) @@ -337,101 +329,90 @@ void RemoveCoverObjectFromWorld( INT32 sGridNo, UINT16 usGraphic, BOOLEAN fRoof } } -BOOLEAN HasAdjTile( const INT32& ubX, const INT32& ubY, const INT32& ubZ ) -{ - INT32 ubTX, ubTY; - for ( ubTX = ubX-1; ubTX <= ubX+1; ++ubTX ) - { - if ( ubTX < 0 || ubTX > WORLD_COLS ) - { - continue; - } - - for ( ubTY = ubY-1; ubTY <= ubY+1; ++ubTY ) - { - if ( ubTY < 0 || ubTY > WORLD_ROWS ) - { - continue; - } - - if ( gCoverViewArea[ubTX][ubTY][ubZ].bOverlayType > INVALID_COVER && gCoverViewArea[ubTX][ubTY][ubZ].bOverlayType != MAX_COVER && gCoverViewArea[ubTX][ubTY][ubZ].bOverlayType != NO_SEE ) - { - return TRUE; - } - } - } +static BOOLEAN HasAdjTile(const INT32 startIndex, const bool onRoof) +{ + const auto rowLength = 1 + gsMaxCellX - gsMinCellX; + + for ( INT32 ubTY = -1; ubTY <= 1; ++ubTY ) + { + for ( INT32 ubTX = -1; ubTX <= 1; ++ubTX ) + { + const auto i = startIndex + ubTY * rowLength + ubTX; + if ( i > 0 && i < gCoverViewArea.size() ) + { + const auto& cell = gCoverViewArea[i]; + + if ( cell.bOverlayType > INVALID_COVER && cell.bOverlayType != MAX_COVER && cell.bOverlayType != NO_SEE && cell.onRoof == onRoof ) + { + return TRUE; + } + } + } + } return FALSE; } -void AddCoverObjectsToViewArea() +static void AddCoverObjectsToViewArea() { - INT32 ubX, ubY, ubZ; BOOLEAN fChanged = FALSE; + const BOOLEAN fNightTime = NightTime(); - BOOLEAN fNightTime = NightTime( ); - - for ( ubX=gsMinCellX; ubX<=gsMaxCellX; ++ubX ) + INT32 index = 0; + for ( auto& cell : gCoverViewArea ) { - for ( ubY=gsMinCellY; ubY<=gsMaxCellY; ++ubY ) + const auto bOverlayType = cell.bOverlayType; + const auto sGridNo = cell.sGridNo; + const auto onRoof = cell.onRoof; + + if ( bOverlayType != INVALID_COVER && ((bOverlayType != MAX_COVER && bOverlayType != NO_SEE) || HasAdjTile(index, onRoof)) ) { - for ( ubZ=0; ubZbActive == false) + if ( gusSelectedSoldier == NOBODY || gusSelectedSoldier->bActive == false ) return; SOLDIERTYPE* pSoldier = gusSelectedSoldier; @@ -540,17 +559,10 @@ static void CalculateCoverFromEnemies() const INT8 OurSoldierLBESightAdjustment = GetSightAdjustmentBasedOnLBE(pSoldier); - // Loop through the grid and reset cover - for (INT32 ubX = gsMinCellX; ubX <= gsMaxCellX; ++ubX) + // reset cover values + for ( auto& cell : gCoverViewArea ) { - for (INT32 ubY = gsMinCellY; ubY <= gsMaxCellY; ++ubY) - { - for (INT8 ubZ = 0; ubZ < COVER_Z_CELLS; ++ubZ) - { - INT8& bOverlayType = gCoverViewArea[ubX][ubY][ubZ].bOverlayType; - bOverlayType = MAX_COVER; - } - } + cell.bOverlayType = MAX_COVER; } @@ -562,27 +574,27 @@ static void CalculateCoverFromEnemies() bCowering.reserve(TOTAL_SOLDIERS); tunnelVision.reserve(TOTAL_SOLDIERS); - for (UINT32 i = 0; i < guiNumMercSlots; ++i) + for ( UINT32 i = 0; i < guiNumMercSlots; ++i ) { - SOLDIERTYPE *pOpponent = MercSlots[i]; + SOLDIERTYPE* pOpponent = MercSlots[i]; // if this merc is inactive, at base, on assignment, dead, unconscious - if (!pOpponent || pOpponent->stats.bLife < OKLIFE) + if ( !pOpponent || pOpponent->stats.bLife < OKLIFE ) { continue; // next merc } // if this man is neutral / on the same side, he's not an opponent - if (CONSIDERED_NEUTRAL(pSoldier, pOpponent) || (pSoldier->bSide == pOpponent->bSide)) + if ( CONSIDERED_NEUTRAL(pSoldier, pOpponent) || (pSoldier->bSide == pOpponent->bSide) ) { continue; // next merc } - INT8 *pbPersOL = pSoldier->aiData.bOppList + pOpponent->ubID; - INT8 *pbPublOL = gbPublicOpplist[OUR_TEAM] + pOpponent->ubID; + INT8* pbPersOL = pSoldier->aiData.bOppList + pOpponent->ubID; + INT8* pbPublOL = gbPublicOpplist[OUR_TEAM] + pOpponent->ubID; // if this opponent is unknown personally and publicly - if (*pbPersOL != SEEN_CURRENTLY && *pbPublOL != SEEN_CURRENTLY) + if ( *pbPersOL != SEEN_CURRENTLY && *pbPublOL != SEEN_CURRENTLY ) { continue; // next merc } @@ -594,60 +606,34 @@ static void CalculateCoverFromEnemies() // Calculate cover for the whole grid, one opponent at a time. - for (UINT32 i = 0; i < pOpponents.size(); ++i) + for ( UINT32 i = 0; i < pOpponents.size(); ++i ) { - SOLDIERTYPE *pOpponent = pOpponents[i]; + SOLDIERTYPE* pOpponent = pOpponents[i]; const BOOLEAN isCowering = bCowering[i]; const UINT8 tunnelVisionPercentage = tunnelVision[i]; - for (INT32 ubX = gsMinCellX; ubX <= gsMaxCellX; ++ubX) + for ( auto& cell : gCoverViewArea ) { - for (INT32 ubY = gsMinCellY; ubY <= gsMaxCellY; ++ubY) - { - for (INT8 ubZ = 0; ubZ < COVER_Z_CELLS; ++ubZ) - { - INT32& sGridNo = gCoverViewArea[ubX][ubY][ubZ].sGridNo; - if (!GridNoOnScreenAndAround(sGridNo, 2)) - continue; - + INT32& sGridNo = cell.sGridNo; + INT8& bOverlayType = cell.bOverlayType; + bool& onRoof = cell.onRoof; - INT8& bOverlayType = gCoverViewArea[ubX][ubY][ubZ].bOverlayType; - - if (IsTheRoofVisible(sGridNo)) - { - // do not show stuff on ground if roof is shown - if (ubZ == I_GROUND_LEVEL) - { - bOverlayType = INVALID_COVER; - continue; - } - } - else - { - // do not show stuff on roofs if ground is shown - if (ubZ == I_ROOF_LEVEL) - { - bOverlayType = INVALID_COVER; - continue; - } - } - - - if (!NewOKDestination(pSoldier, sGridNo, false, ubZ)) - continue; + if ( !GridNoOnScreenAndAround(sGridNo, 2) ) + continue; + onRoof = IsTheRoofVisible(sGridNo); + if ( !NewOKDestination(pSoldier, sGridNo, false, onRoof) ) + continue; - //Skip cover calculation if there already is no cover. - if (bOverlayType == NO_COVER) - { - continue; - } - else - { - CalculateCoverFromEnemySoldier(pOpponent, sGridNo, ubZ, bOverlayType, pSoldier, isCowering, tunnelVisionPercentage, OurSoldierStealth, OurSoldierLBESightAdjustment); - } - } + //Skip cover calculation if there already is no cover. + if ( bOverlayType == NO_COVER ) + { + continue; + } + else + { + CalculateCoverFromEnemySoldier(pOpponent, sGridNo, onRoof, bOverlayType, pSoldier, isCowering, tunnelVisionPercentage, OurSoldierStealth, OurSoldierLBESightAdjustment); } } } @@ -662,75 +648,53 @@ static void CalculateCoverFromEnemies() void CalculateCover() { - INT32 ubX, ubY; - INT8 ubZ; - SOLDIERTYPE* pSoldier; - - if (gusSelectedSoldier == NOBODY || gusSelectedSoldier->bActive == false) + if ( gusSelectedSoldier == NOBODY || gusSelectedSoldier->bActive == false ) return; - pSoldier = gusSelectedSoldier; + SOLDIERTYPE* pSoldier = gusSelectedSoldier; - for (ubX = gsMinCellX; ubX <= gsMaxCellX; ++ubX) + for ( auto& cell : gCoverViewArea ) { - for (ubY = gsMinCellY; ubY <= gsMaxCellY; ++ubY) - { - for (ubZ = 0; ubZ < COVER_Z_CELLS; ++ubZ) - { - INT32& sGridNo = gCoverViewArea[ubX][ubY][ubZ].sGridNo; - - if (!GridNoOnScreenAndAround(sGridNo, 2)) - continue; - - if (IsTheRoofVisible(sGridNo)) - { - // do not show stuff on ground if roof is shown - if (ubZ == I_GROUND_LEVEL) - continue; - } - else - { - // do not show stuff on roofs if ground is shown - if (ubZ == I_ROOF_LEVEL) - continue; - } + INT32& sGridNo = cell.sGridNo; + INT8& bOverlayType = cell.bOverlayType; + bool& onRoof = cell.onRoof; - if (!NewOKDestination(pSoldier, sGridNo, false, ubZ)) - continue; + if ( !GridNoOnScreenAndAround(sGridNo, 2) ) + continue; - INT8& bOverlayType = gCoverViewArea[ubX][ubY][ubZ].bOverlayType; + onRoof = IsTheRoofVisible(sGridNo); + if ( !NewOKDestination(pSoldier, sGridNo, false, onRoof) ) + continue; - // reset cover value - bOverlayType = MAX_COVER; - if (gTacticalStatus.fAtLeastOneGuyOnMultiSelect) // view of selected mercs + // reset cover value + bOverlayType = MAX_COVER; + if ( gTacticalStatus.fAtLeastOneGuyOnMultiSelect ) // view of selected mercs + { + // OK, loop through all guys who are 'multi-selected' and + SoldierID cnt = gTacticalStatus.Team[gbPlayerNum].bFirstID; + for ( ; cnt <= gTacticalStatus.Team[gbPlayerNum].bLastID; ++cnt ) + { + pSoldier = cnt; + if ( pSoldier->bActive && pSoldier->bInSector ) { - // OK, loop through all guys who are 'multi-selected' and - SoldierID cnt = gTacticalStatus.Team[gbPlayerNum].bFirstID; - for ( ; cnt <= gTacticalStatus.Team[gbPlayerNum].bLastID; ++cnt ) + if ( pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED ) { - pSoldier = cnt; - if (pSoldier->bActive && pSoldier->bInSector) - { - if (pSoldier->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED) - { - CalculateCoverFromSoldier(pSoldier, sGridNo, ubZ, bOverlayType); - - // if the tile is already NO_COVER, there's no need to continue - if (NO_COVER == bOverlayType) - break; - } - } + CalculateCoverFromSoldier(pSoldier, sGridNo, onRoof, bOverlayType); + + // if the tile is already NO_COVER, there's no need to continue + if ( NO_COVER == bOverlayType ) + break; } } - else // single view from your merc - { - CalculateCoverFromSoldier(pSoldier, sGridNo, ubZ, bOverlayType); - } - - // we use different enums for our merc's sight to avoid confusing inverse sight - bOverlayType = MAX_SEE - bOverlayType; } } + else // single view from your merc + { + CalculateCoverFromSoldier(pSoldier, sGridNo, onRoof, bOverlayType); + } + + // we use different enums for our merc's sight to avoid confusing inverse sight + bOverlayType = MAX_SEE - bOverlayType; } AddCoverObjectsToViewArea(); @@ -739,7 +703,7 @@ void CalculateCover() void CalculateCoverFromSoldier( SOLDIERTYPE* pFromSoldier, const INT32& sTargetGridNo, const BOOLEAN& fRoof, INT8& bOverlayType, SOLDIERTYPE* pToSoldier ) { - UINT16 usSightLimit = pFromSoldier->GetMaxDistanceVisible(sTargetGridNo, (INT8)fRoof, CALC_FROM_WANTED_DIR); + const UINT16 usSightLimit = pFromSoldier->GetMaxDistanceVisible(sTargetGridNo, (INT8)fRoof, CALC_FROM_WANTED_DIR); for ( int i = 0; ibInSector ) + + if ( gusSelectedSoldier == NOBODY || !GetSoldier(&pSoldier, gusSelectedSoldier) || !pSoldier->bInSector ) return; // if we want to detect hostile mines and we have an metal detector in our hands, allow seeking @@ -1192,57 +1150,38 @@ void CalculateMines() else return; } - - const INT32& sSelectedSoldierGridNo = gusSelectedSoldier->sGridNo; - - for ( ubX=gsMinCellX; ubX<=gsMaxCellX; ++ubX ) - { - for ( ubY=gsMinCellY; ubY<=gsMaxCellY; ++ubY ) - { - for ( ubZ=0; ubZ 4 ) - continue; - } + const INT32& sSelectedSoldierGridNo = gusSelectedSoldier->sGridNo; - if ( !NewOKDestination( pSoldier, sGridNo, false, ubZ ) ) - continue; + for ( auto& cell : gCoverViewArea ) + { + INT32& sGridNo = cell.sGridNo; + INT8& bOverlayType = cell.bOverlayType; + bool& onRoof = cell.onRoof; - INT8& bOverlayType = gCoverViewArea[ubX][ubY][ubZ].bOverlayType; + if ( !GridNoOnScreenAndAround(sGridNo, 2) ) + continue; - bOverlayType = INVALID_COVER; + onRoof = IsTheRoofVisible(sGridNo); + if ( !NewOKDestination(pSoldier, sGridNo, false, onRoof) ) + continue; - DetermineMineDisplayInTile( sGridNo, ubZ, bOverlayType, fWithMineDetector ); - } + // if we are looking for hostile mines, but the tile is out of our' detectors range, skip looking for mines + if ( gubDrawMode == MINES_DRAW_DETECT_ENEMY && fWithMineDetector ) + { + if ( PythSpacesAway(sSelectedSoldierGridNo, sGridNo) > 4 ) + continue; } + + bOverlayType = INVALID_COVER; + DetermineMineDisplayInTile(sGridNo, onRoof, bOverlayType, fWithMineDetector); } AddMinesObjectsToViewArea(); } -void DetermineMineDisplayInTile( INT32 sGridNo, INT8 bLevel, INT8& bOverlayType, BOOLEAN fWithMineDetector ) +void DetermineMineDisplayInTile( const INT32 sGridNo, const INT8 bLevel, INT8& bOverlayType, const BOOLEAN fWithMineDetector ) { // if there is a bomb at that grid and level, and it isn't disabled for (UINT32 uiWorldBombIndex = 0; uiWorldBombIndex < guiNumWorldBombs; ++uiWorldBombIndex) @@ -1418,102 +1357,79 @@ void SetGridNoForTraitDisplay( INT32 sGridNo ) void CalculateTraitRange() { - INT32 ubX, ubY; - INT8 ubZ; SOLDIERTYPE* pSoldier; - - if ( gusSelectedSoldier == NOBODY || !GetSoldier( &pSoldier, gusSelectedSoldier ) || !pSoldier->bInSector ) + + if ( gusSelectedSoldier == NOBODY || !GetSoldier(&pSoldier, gusSelectedSoldier) || !pSoldier->bInSector ) return; UINT16 range1 = 0; UINT16 range2 = 0; switch ( usDisplayTrait ) { - case RADIO_OPERATOR_NT: + case RADIO_OPERATOR_NT: { // we 'mark' the map position with which we called the menu, so that the player sees where he is targetting - } break; - case VARIOUSSKILLS: + case VARIOUSSKILLS: { range1 = gGameExternalOptions.usSpotterRange; range2 = gGameExternalOptions.usSpotterRange * 2; } break; - default: - return; + default: + return; } - + const INT32& sSelectedSoldierGridNo = gusSelectedSoldier->sGridNo; - - for ( ubX=gsMinCellX; ubX<=gsMaxCellX; ++ubX ) + + + for ( auto& cell : gCoverViewArea ) { - for ( ubY=gsMinCellY; ubY<=gsMaxCellY; ++ubY ) - { - for ( ubZ=0; ubZ WORLD_COLS ) + for ( INT32 ubTX = -1; ubTX <= 1; ++ubTX ) { - continue; - } + const auto i = startIndex + ubTY * rowLength + ubTX; - for ( ubTY = ubY-1; ubTY <= ubY+1; ++ubTY ) - { - if ( ubTY < 0 || ubTY > WORLD_ROWS ) + if ( i > 0 && i < gCoverViewArea.size() ) { - continue; - } + const auto& cell = gCoverViewArea[i]; - INT8& bOverlayType = gCoverViewArea[ubTX][ubTY][ubZ].bOverlayType; - - if ( bOverlayType == TRAIT_1 || bOverlayType == TRAIT_2 ) - { - return TRUE; + if ( (cell.bOverlayType == TRAIT_1 || cell.bOverlayType == TRAIT_2) && cell.bOverlayType != NO_SEE && cell.onRoof == onRoof ) + { + return TRUE; + } } } } - - return FALSE; } - - // ----------------------------- tracker display after this ---------------------------------------- // added by Flugente @@ -1567,107 +1474,84 @@ static BOOLEAN TraitTileHasAdjTile( const INT32& ubX, const INT32& ubY, const IN //******* Local Function Prototypes *********************************** -void AddTrackerObjectsToViewArea( ); +void AddTrackerObjectsToViewArea( ); -void CalculateTrackerRange( ) +void CalculateTrackerRange() { - INT32 ubX, ubY; - INT8 ubZ; SOLDIERTYPE* pSoldier; - - if ( gusSelectedSoldier == NOBODY || !GetSoldier( &pSoldier, gusSelectedSoldier ) || !pSoldier->bInSector ) + + if ( gusSelectedSoldier == NOBODY || !GetSoldier(&pSoldier, gusSelectedSoldier) || !pSoldier->bInSector ) return; - FLOAT trackerskill = (FLOAT)(NUM_SKILL_TRAITS( pSoldier, SURVIVAL_NT ) * gSkillTraitValues.usSVTrackerAbility + pSoldier->GetBackgroundValue( BG_TRACKER_ABILITY )) / 100.0f; - + const FLOAT trackerskill = (FLOAT)(NUM_SKILL_TRAITS(pSoldier, SURVIVAL_NT) * gSkillTraitValues.usSVTrackerAbility + pSoldier->GetBackgroundValue(BG_TRACKER_ABILITY)) / 100.0f; + if ( trackerskill < 0.01f ) return; - UINT16 range = gSkillTraitValues.usSVTrackerMaxRange * trackerskill; + const UINT16 range = gSkillTraitValues.usSVTrackerMaxRange * trackerskill; const INT32& sSelectedSoldierGridNo = gusSelectedSoldier->sGridNo; - - for ( ubX = gsMinCellX; ubX <= gsMaxCellX; ++ubX ) + + for ( auto& cell : gCoverViewArea ) { - for ( ubY = gsMinCellY; ubY <= gsMaxCellY; ++ubY ) - { - for ( ubZ = 0; ubZ WORLD_COLS ) + for ( INT32 ubTX = -1; ubTX <= 1; ++ubTX ) { - continue; - } + const auto i = startIndex + ubTY * rowLength + ubTX; - for ( ubTY = ubY - 1; ubTY <= ubY + 1; ++ubTY ) - { - if ( ubTY < 0 || ubTY > WORLD_ROWS ) + if ( i > 0 && i < gCoverViewArea.size() ) { - continue; - } + const auto& cell = gCoverViewArea[i]; + const auto bOverlayType = cell.bOverlayType; - INT8& bOverlayType = gCoverViewArea[ubTX][ubTY][ubZ].bOverlayType; - - if ( bOverlayType == TRACKS_VERYOLD || bOverlayType == TRACKS_OLD || bOverlayType == TRACKS_RECENT || bOverlayType == TRACKS_BLOOD ) - { - return TRUE; + if ( bOverlayType == TRACKS_VERYOLD || bOverlayType == TRACKS_OLD || bOverlayType == TRACKS_RECENT || bOverlayType == TRACKS_BLOOD ) + { + return TRUE; + } } } } return FALSE; + } -void CalculateFortify( ) +void CalculateFortify() { // simply get all fortified gridnos and colour them - auto vec = GetAllForticationGridNo(); + const auto vec = GetAllForticationGridNo(); - auto itend = vec.end(); - for (auto it = vec.begin(); it != itend; ++it) + for ( auto it = vec.begin(); it != vec.end(); ++it ) { - INT16 sX, sY; - ConvertGridNoToXY( (*it).first, &sX, &sY ); + const auto sGridNo = (*it).first; + const auto bOverlayType = (*it).second.first; + const auto onRoof = (*it).second.second; - gCoverViewArea[sX][sY][(*it).second.second].bOverlayType = (*it).second.first; + for ( auto& cell : gCoverViewArea ) // Linear search for matching GridNo + { + if ( cell.sGridNo == sGridNo ) + { + cell.bOverlayType = bOverlayType; + cell.onRoof = onRoof; + } + } } - - if ( gsMaxCellY < 0 ) - return; - INT32 ubX, ubY, ubZ; - BOOLEAN fChanged = FALSE; - BOOLEAN fNightTime = NightTime( ); + BOOLEAN fChanged = FALSE; + const BOOLEAN fNightTime = NightTime(); - for ( ubX = gsMinCellX; ubX <= gsMaxCellX; ++ubX ) + for ( auto& cell : gCoverViewArea ) { - for ( ubY = gsMinCellY; ubY <= gsMaxCellY; ++ubY ) + const auto bOverlayType = cell.bOverlayType; + const auto sGridNo = cell.sGridNo; + const auto onRoof = cell.onRoof; + + if ( bOverlayType != INVALID_COVER ) { - for ( ubZ = 0; ubZbInSector ) + if ( gusSelectedSoldier == NOBODY || !GetSoldier(&pSoldier, gusSelectedSoldier) || !pSoldier->bInSector ) return; - BOOLEAN guninhand = WeaponInHand( pSoldier ); - - INT32 sSelectedSoldierGridNo = gusSelectedSoldier->sGridNo; + const BOOLEAN guninhand = WeaponInHand(pSoldier); + const INT32 sSelectedSoldierGridNo = gusSelectedSoldier->sGridNo; - if ( TileIsOutOfBounds( sSelectedSoldierGridNo ) ) + if ( TileIsOutOfBounds(sSelectedSoldierGridNo) ) return; //Get the gridno the cursor is at - INT32 sMouseGridNo = NOWHERE; - GetMouseMapPos( &sMouseGridNo ); + INT32 sMouseGridNo = NOWHERE; + GetMouseMapPos(&sMouseGridNo); // depending on whether we have a grenade fire or a bomb to plant, different gridnos are relevant for explosives INT32 explosivetargetgridno = NOWHERE; // grenade cursor is stored in gsPhysicsImpactPointGridNo, we have to check whether that's valid, and whether we use that cursor right now BOOLEAN tosscursorisvalid = FALSE; - if ( !TileIsOutOfBounds( gsPhysicsImpactPointGridNo ) && (guiNewUICursor == GOOD_THROW_UICURSOR || guiNewUICursor == BAD_THROW_UICURSOR) ) + if ( !TileIsOutOfBounds(gsPhysicsImpactPointGridNo) && (guiNewUICursor == GOOD_THROW_UICURSOR || guiNewUICursor == BAD_THROW_UICURSOR) ) { tosscursorisvalid = TRUE; explosivetargetgridno = gsPhysicsImpactPointGridNo; } - else if ( !TileIsOutOfBounds( sMouseGridNo ) && (guiNewUICursor == PLACE_BOMB_GREY_UICURSOR || guiNewUICursor == PLACE_BOMB_RED_UICURSOR) ) + else if ( !TileIsOutOfBounds(sMouseGridNo) && (guiNewUICursor == PLACE_BOMB_GREY_UICURSOR || guiNewUICursor == PLACE_BOMB_RED_UICURSOR) ) { - tosscursorisvalid = TRUE; + tosscursorisvalid = TRUE; - explosivetargetgridno = sMouseGridNo; + explosivetargetgridno = sMouseGridNo; } UINT16 gunrange = 0; @@ -1806,24 +1683,24 @@ void CalculateWeapondata() if ( &pSoldier->inv[HANDPOS] && Item[(pSoldier->inv[HANDPOS]).usItem].usItemClass & IC_WEAPON ) { - pObjPlatform = pSoldier->GetUsedWeapon( &pSoldier->inv[HANDPOS] ); + pObjPlatform = pSoldier->GetUsedWeapon(&pSoldier->inv[HANDPOS]); if ( pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO ) { - pObjUsed = FindAttachment_GrenadeLauncher( &pSoldier->inv[HANDPOS] ); + pObjUsed = FindAttachment_GrenadeLauncher(&pSoldier->inv[HANDPOS]); } else { pObjUsed = pObjPlatform; } - gunrange = GunRange( pObjUsed, pSoldier ) / CELL_X_SIZE; - laserrange = GetBestLaserRange( pObjPlatform ) / CELL_X_SIZE; + gunrange = GunRange(pObjUsed, pSoldier) / CELL_X_SIZE; + laserrange = GetBestLaserRange(pObjPlatform) / CELL_X_SIZE; if ( Item[pObjUsed->usItem].usItemClass & IC_LAUNCHER ) { - OBJECTTYPE *pAttachment = FindLaunchableAttachment( pObjPlatform, pObjUsed->usItem ); - + OBJECTTYPE* pAttachment = FindLaunchableAttachment(pObjPlatform, pObjUsed->usItem); + if ( pAttachment ) { explosionradius = Explosive[Item[pAttachment->usItem].ubClassIndex].ubRadius; @@ -1842,90 +1719,69 @@ void CalculateWeapondata() fragrange = Explosive[Item[pObjUsed->usItem].ubClassIndex].ubFragRange / 10; } - + // we have to store and later reset the soldier's target level INT8 bTempTargetLevel = pSoldier->bTargetLevel; - for ( ubX = gsMinCellX; ubX <= gsMaxCellX; ++ubX ) + + for ( auto& cell : gCoverViewArea ) { - for ( ubY = gsMinCellY; ubY <= gsMaxCellY; ++ubY ) - { - for ( ubZ = 0; ubZ 0 && PythSpacesAway( explosivetargetgridno, sGridNo ) <= explosionradius ) - gCoverViewArea[ubX][ubY][ubZ].bOverlayType = NO_COVER; - else if ( tosscursorisvalid && fragrange > 0 && PythSpacesAway( explosivetargetgridno, sGridNo ) <= fragrange ) - gCoverViewArea[ubX][ubY][ubZ].bOverlayType = MIN_COVER; - else - { - if ( GetDirectionToGridNoFromGridNo( sSelectedSoldierGridNo, sGridNo ) != pSoldier->ubDirection ) - continue; + if ( tosscursorisvalid && explosionradius > 0 && PythSpacesAway(explosivetargetgridno, sGridNo) <= explosionradius ) + bOverlayType = NO_COVER; + else if ( tosscursorisvalid && fragrange > 0 && PythSpacesAway(explosivetargetgridno, sGridNo) <= fragrange ) + bOverlayType = MIN_COVER; + else + { + if ( GetDirectionToGridNoFromGridNo(sSelectedSoldierGridNo, sGridNo) != pSoldier->ubDirection ) + continue; - if ( guninhand && gunrange > 0 && PythSpacesAway( sSelectedSoldierGridNo, sGridNo ) <= gunrange ) - { - pSoldier->bTargetLevel = ubZ; - UINT32 uiHitChance = CalcChanceToHitGun( pSoldier, sGridNo, (INT8)(pSoldier->aiData.bShownAimTime), pSoldier->bAimShotLocation ); - - if ( uiHitChance > 75 ) - gCoverViewArea[ubX][ubY][ubZ].bOverlayType = MAX_COVER; - else if ( uiHitChance > 50 ) - gCoverViewArea[ubX][ubY][ubZ].bOverlayType = MED_COVER; - else if ( uiHitChance > 25 ) - gCoverViewArea[ubX][ubY][ubZ].bOverlayType = MIN_COVER; - else if ( uiHitChance > 0 ) - gCoverViewArea[ubX][ubY][ubZ].bOverlayType = NO_COVER; - } - } + if ( guninhand && gunrange > 0 && PythSpacesAway(sSelectedSoldierGridNo, sGridNo) <= gunrange ) + { + pSoldier->bTargetLevel = onRoof; + UINT32 uiHitChance = CalcChanceToHitGun(pSoldier, sGridNo, (INT8)(pSoldier->aiData.bShownAimTime), pSoldier->bAimShotLocation); + + if ( uiHitChance > 75 ) + bOverlayType = MAX_COVER; + else if ( uiHitChance > 50 ) + bOverlayType = MED_COVER; + else if ( uiHitChance > 25 ) + bOverlayType = MIN_COVER; + else if ( uiHitChance > 0 ) + bOverlayType = NO_COVER; } } } // important: reset target level to what it really was pSoldier->bTargetLevel = bTempTargetLevel; - - BOOLEAN fChanged = FALSE; - BOOLEAN fNightTime = NightTime( ); - for ( ubX = gsMinCellX; ubX <= gsMaxCellX; ++ubX ) + BOOLEAN fChanged = FALSE; + const BOOLEAN fNightTime = NightTime(); + + for ( auto& cell : gCoverViewArea ) { - for ( ubY = gsMinCellY; ubY <= gsMaxCellY; ++ubY ) + if ( cell.bOverlayType != INVALID_COVER ) { - for ( ubZ = 0; ubZ