diff --git a/TacticalAI/AIUtils.cpp b/TacticalAI/AIUtils.cpp index 2ea42f28..d1160f68 100644 --- a/TacticalAI/AIUtils.cpp +++ b/TacticalAI/AIUtils.cpp @@ -4619,6 +4619,61 @@ UINT8 RedSmokeDanger(INT32 sGridNo, INT8 bLevel) return ubDangerPercent; } +BOOLEAN FindClosestVisibleSmoke(SOLDIERTYPE* pSoldier, INT32& sSpot, INT8& bLevel, BOOLEAN fOnlyGas) +{ + CHECKF(pSoldier); + + INT32 sDist; + INT32 sClosestDist = INT32_MAX; + INT32 sCheckSpot; + INT8 bCheckLevel; + + sSpot = NOWHERE; + bLevel = 0; + + //loop through all smoke effects and find closest visible + for ( UINT32 uiCnt = 0; uiCnt < guiNumSmokeEffects; uiCnt++ ) + { + if ( gSmokeEffectData[uiCnt].fAllocated && + !TileIsOutOfBounds(gSmokeEffectData[uiCnt].sGridNo) ) + { + // ignore smoke if not dangerous + if ( fOnlyGas && + gSmokeEffectData[uiCnt].bType != TEARGAS_SMOKE_EFFECT && + gSmokeEffectData[uiCnt].bType != MUSTARDGAS_SMOKE_EFFECT && + gSmokeEffectData[uiCnt].bType != CREATURE_SMOKE_EFFECT ) + { + continue; + } + + sCheckSpot = gSmokeEffectData[uiCnt].sGridNo; + + if ( gSmokeEffectData[uiCnt].bFlags & SMOKE_EFFECT_ON_ROOF ) + bCheckLevel = 1; + else + bCheckLevel = 0; + + sDist = PythSpacesAway(sCheckSpot, pSoldier->sGridNo); + + if ( sDist < DAY_VISION_RANGE && + SoldierToVirtualSoldierLineOfSightTest(pSoldier, sCheckSpot, bCheckLevel, ANIM_PRONE, 0, CALC_FROM_ALL_DIRS) && + (sSpot == NOWHERE || sDist < sClosestDist) ) + { + sClosestDist = sDist; + sSpot = sCheckSpot; + bLevel = bCheckLevel; + } + } + } + + if ( !TileIsOutOfBounds(sSpot) ) + { + return TRUE; + } + + return FALSE; +} + // check if artillery strike was ordered by any team BOOLEAN CheckArtilleryStrike(void) { diff --git a/TacticalAI/DecideAction.cpp b/TacticalAI/DecideAction.cpp index 616e67c1..5a6759ad 100644 --- a/TacticalAI/DecideAction.cpp +++ b/TacticalAI/DecideAction.cpp @@ -1,3 +1,4 @@ +//#pragma optimize("", off) #include "ai.h" #include "AIInternals.h" #include "Isometric Utils.h" @@ -10730,6 +10731,19 @@ INT8 DecideActionWearGasmask(SOLDIERTYPE *pSoldier) //Only put mask on in gas if (bInGas && WearGasMaskIfAvailable(pSoldier)) { bInGas = InGasOrSmoke(pSoldier, pSoldier->sGridNo); } + // Chance to wear gas mask if soldier sees gas nearby + INT32 sSmokeSpot = NOWHERE; + INT8 bSmokeLevel = 0; + + if ( SoldierAI(pSoldier) && + pSoldier->CheckInitialAP() && + !DoesSoldierWearGasMask(pSoldier) && + FindClosestVisibleSmoke(pSoldier, sSmokeSpot, bSmokeLevel, TRUE) && + Chance(30 + SoldierDifficultyLevel(pSoldier) * 10) ) + { + WearGasMaskIfAvailable(pSoldier); + } + return bInGas; } diff --git a/TacticalAI/ai.h b/TacticalAI/ai.h index fc10e142..e6f16d45 100644 --- a/TacticalAI/ai.h +++ b/TacticalAI/ai.h @@ -299,6 +299,7 @@ SoldierID GetClosestMedicSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 // sevenfm: BOOLEAN NightLight(void); BOOLEAN DuskLight(void); +BOOLEAN FindClosestVisibleSmoke(SOLDIERTYPE* pSoldier, INT32& sSpot, INT8& bLevel, BOOLEAN fOnlyGas); BOOLEAN InSmokeNearby(INT32 sGridNo, INT8 bLevel); INT16 MaxNormalVisionDistance( void ); UINT8 MinFlankDirections( SOLDIERTYPE *pSoldier );