From 18dcced82a2e9d848818be39b35ba34d45992905 Mon Sep 17 00:00:00 2001 From: Sevenfm Date: Thu, 11 Feb 2021 19:11:54 +0000 Subject: [PATCH] Use TACTICAL_RANGE instead of DAY_VISION_RANGE for AI calculations. Implemented Black cover advance code for AI: try to get closer to enemy using cover if soldier has low CTH or enemy too far for shooting or soldier has high morale or no cover at spot. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8931 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- TacticalAI/AIUtils.cpp | 10 +- TacticalAI/Attacks.cpp | 6 +- TacticalAI/DecideAction.cpp | 182 +++++++++++++++++++++++++++--- TacticalAI/FindLocations.cpp | 28 ++--- TacticalAI/ZombieDecideAction.cpp | 8 +- 5 files changed, 195 insertions(+), 39 deletions(-) diff --git a/TacticalAI/AIUtils.cpp b/TacticalAI/AIUtils.cpp index adbfe711..9168837f 100644 --- a/TacticalAI/AIUtils.cpp +++ b/TacticalAI/AIUtils.cpp @@ -4115,7 +4115,7 @@ UINT8 CountFriendsBlack( SOLDIERTYPE *pSoldier, INT32 sClosestOpponent ) //sFriendClosestOpponent = ClosestKnownOpponent( pFriend, NULL, NULL ); sFriendClosestOpponent = ClosestSeenOpponent( pFriend, NULL, NULL ); if(!TileIsOutOfBounds(sFriendClosestOpponent) && - PythSpacesAway( sClosestOpponent, sFriendClosestOpponent ) < (INT16)DAY_VISION_RANGE / 4 && + PythSpacesAway( sClosestOpponent, sFriendClosestOpponent ) < (INT16)TACTICAL_RANGE / 4 && pFriend->aiData.bAlertStatus == STATUS_BLACK && pFriend->stats.bLife > pFriend->stats.bLifeMax / 2 && ( GetNearestRottingCorpseAIWarning( pFriend->sGridNo ) == 0 && !InLightAtNight(pFriend->sGridNo, pFriend->pathing.bLevel) || @@ -4506,7 +4506,7 @@ UINT8 RedSmokeDanger(INT32 sGridNo, INT8 bLevel) UINT32 uiCnt; INT32 sDist; INT32 sClosestDist; - INT32 sMaxDist = min(gSkillTraitValues.usVOMortarRadius, DAY_VISION_RANGE); + INT32 sMaxDist = min(gSkillTraitValues.usVOMortarRadius, TACTICAL_RANGE); INT32 sClosestSmoke = NOWHERE; UINT8 ubDangerPercent = 0; @@ -5011,7 +5011,7 @@ BOOLEAN AICheckIsSniper(SOLDIERTYPE *pSoldier) return FALSE; }*/ - if ((AIGunRange(pSoldier) > DAY_VISION_RANGE || AICheckHasWeaponOfType(pSoldier, GUN_SN_RIFLE)) && + if ((AIGunRange(pSoldier) > TACTICAL_RANGE || AICheckHasWeaponOfType(pSoldier, GUN_SN_RIFLE)) && AIGunScoped(pSoldier) && pSoldier->stats.bMarksmanship > 90 && gGameOptions.fNewTraitSystem && @@ -5044,7 +5044,7 @@ BOOLEAN AICheckIsMarksman(SOLDIERTYPE *pSoldier) return FALSE; } - if (AIGunRange(pSoldier) >= DAY_VISION_RANGE && + if (AIGunRange(pSoldier) >= TACTICAL_RANGE && (AIGunScoped(pSoldier) || pSoldier->stats.bMarksmanship > 90 || gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT(pSoldier, SNIPER_NT))) { return TRUE; @@ -5633,7 +5633,7 @@ BOOLEAN AICheckShortWeaponRange(SOLDIERTYPE *pSoldier) return TRUE; } - if (AIGunRange(pSoldier) < DAY_VISION_RANGE / 2) + if (AIGunRange(pSoldier) < TACTICAL_RANGE / 2) { return TRUE; } diff --git a/TacticalAI/Attacks.cpp b/TacticalAI/Attacks.cpp index de76b999..c459ea6a 100644 --- a/TacticalAI/Attacks.cpp +++ b/TacticalAI/Attacks.cpp @@ -3929,13 +3929,13 @@ void CheckTossFriendSmoke(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow) bFriendLevel = pFriend->pathing.bLevel; sClosestOpponent = ClosestKnownOpponent(pFriend, NULL, NULL); - if (PythSpacesAway(sSpot, sFriendSpot) <= (INT16)DAY_VISION_RANGE && - PythSpacesAway(sSpot, sFriendSpot) > (INT16)DAY_VISION_RANGE / 4 && + if (PythSpacesAway(sSpot, sFriendSpot) <= (INT16)TACTICAL_RANGE && + PythSpacesAway(sSpot, sFriendSpot) > (INT16)TACTICAL_RANGE / 4 && !InSmoke(sFriendSpot, bFriendLevel) && (!NightLight() || InLightAtNight(sFriendSpot, bFriendLevel)) && !Water(sFriendSpot, bFriendLevel) && !TileIsOutOfBounds(sClosestOpponent) && - PythSpacesAway(sFriendSpot, sClosestOpponent) > (INT16)DAY_VISION_RANGE / 4 && + PythSpacesAway(sFriendSpot, sClosestOpponent) > (INT16)TACTICAL_RANGE / 4 && !ProneSightCoverAtSpot(pFriend, sFriendSpot, TRUE) && //!SightCoverAtSpot(pFriend, sFriendSpot, FALSE) && //!AnyCoverAtSpot(pFriend, sFriendSpot) && diff --git a/TacticalAI/DecideAction.cpp b/TacticalAI/DecideAction.cpp index ab046507..df8f9123 100644 --- a/TacticalAI/DecideAction.cpp +++ b/TacticalAI/DecideAction.cpp @@ -2861,7 +2861,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier) !AICheckIsSniper(pSoldier) && !AICheckIsMachinegunner(pSoldier) && !AICheckIsMortarOperator(pSoldier) && - Chance(100 - min(100, 10 * CountPublicKnownEnemies(pSoldier, pSoldier->sGridNo, DAY_VISION_RANGE))) && + Chance(100 - min(100, 10 * CountPublicKnownEnemies(pSoldier, pSoldier->sGridNo, TACTICAL_RANGE))) && !GuySawEnemy(pSoldier, SEEN_LAST_TURN)) { DebugAI(AI_MSG_INFO, pSoldier, String("check if we can cover friend with smoke")); @@ -3079,11 +3079,11 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier) } // reserve APs to hide if no cover or enemy is close - if (!AnyCoverAtSpot(pSoldier, pSoldier->sGridNo) || PythSpacesAway(pSoldier->sGridNo, BestShot.sTarget) < DAY_VISION_RANGE / 2) + if (!AnyCoverAtSpot(pSoldier, pSoldier->sGridNo) || PythSpacesAway(pSoldier->sGridNo, BestShot.sTarget) < TACTICAL_RANGE / 2) { sReserveAP = APBPConstants[AP_MINIMUM] / 2; } - if (PythSpacesAway(pSoldier->sGridNo, BestShot.sTarget) > DAY_VISION_RANGE || AnyCoverAtSpot(pSoldier, pSoldier->sGridNo) || pSoldier->aiData.bUnderFire) + if (PythSpacesAway(pSoldier->sGridNo, BestShot.sTarget) > TACTICAL_RANGE || AnyCoverAtSpot(pSoldier, pSoldier->sGridNo) || pSoldier->aiData.bUnderFire) { ubMinAuto *= 2; } @@ -3606,7 +3606,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier) RangeChangeDesire(pSoldier) <= 2 && (!NightLight() || InLightAtNight(pSoldier->sGridNo, pSoldier->pathing.bLevel)) && !TileIsOutOfBounds(sClosestOpponent) && - PythSpacesAway(pSoldier->sGridNo, sClosestOpponent) > DAY_VISION_RANGE / 4 && + PythSpacesAway(pSoldier->sGridNo, sClosestOpponent) > TACTICAL_RANGE / 4 && (!fProneSightCover && !AnyCoverAtSpot(pSoldier, pSoldier->sGridNo) || pSoldier->TakenLargeHit()) && (pSoldier->TakenLargeHit() || pSoldier->ShockLevelPercent() > 20 + Random(80))) { @@ -3817,7 +3817,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier) !GuySawEnemy(pSoldier) && !TileIsOutOfBounds(sClosestDisturbance) && //!fSeekClimb && - PythSpacesAway(pSoldier->sGridNo, sClosestDisturbance) < DAY_VISION_RANGE && + PythSpacesAway(pSoldier->sGridNo, sClosestDisturbance) < TACTICAL_RANGE && (pSoldier->aiData.bOrders == STATIONARY || pSoldier->aiData.bOrders == SNIPER || RangeChangeDesire(pSoldier) < 4) && !SoldierToVirtualSoldierLineOfSightTest(pSoldier, sClosestDisturbance, pSoldier->pathing.bLevel, ANIM_STAND, TRUE, CALC_FROM_ALL_DIRS) && CountFriendsBlack(pSoldier, sClosestDisturbance) == 0) @@ -3930,7 +3930,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier) // sevenfm: don't watch when overcrowded and not in a building if (!InARoom(pSoldier->sGridNo, NULL)) { - bWatchPts -= CountNearbyFriends(pSoldier, pSoldier->sGridNo, DAY_VISION_RANGE / 8); + bWatchPts -= CountNearbyFriends(pSoldier, pSoldier->sGridNo, TACTICAL_RANGE / 8); } // sevenfm: don't help if seen enemy recently or under fire @@ -4055,7 +4055,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier) //} BOOLEAN fOvercrowded = FALSE; - if( CountNearbyFriends(pSoldier, pSoldier->sGridNo, DAY_VISION_RANGE/4) > 2 ) + if( CountNearbyFriends(pSoldier, pSoldier->sGridNo, TACTICAL_RANGE / 4) > 2 ) { fOvercrowded = TRUE; } @@ -4465,8 +4465,8 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier) if (fCivilian && //pSoldier->CheckInitialAP() && (pSoldier->aiData.bUnderFire || - !TileIsOutOfBounds(sClosestOpponent) && PythSpacesAway(pSoldier->sGridNo, sClosestOpponent) < DAY_VISION_RANGE / 2)) - //!TileIsOutOfBounds( sClosestNoise ) && PythSpacesAway(pSoldier->sGridNo, sClosestNoise) < DAY_VISION_RANGE / 2) ) + !TileIsOutOfBounds(sClosestOpponent) && PythSpacesAway(pSoldier->sGridNo, sClosestOpponent) < TACTICAL_RANGE / 2)) + //!TileIsOutOfBounds( sClosestNoise ) && PythSpacesAway(pSoldier->sGridNo, sClosestNoise) < TACTICAL_RANGE / 2) ) //CorpseWarning(pSoldier, pSoldier->sGridNo, pSoldier->pathing.bLevel) { DebugAI(AI_MSG_TOPIC, pSoldier, String("[civilians run away]")); @@ -5287,7 +5287,7 @@ INT16 ubMinAPCost; RangeChangeDesire(pSoldier) <= 2 && (!NightLight() || InLightAtNight(pSoldier->sGridNo, pSoldier->pathing.bLevel)) && !TileIsOutOfBounds(sClosestOpponent) && - PythSpacesAway(pSoldier->sGridNo, sClosestOpponent) > DAY_VISION_RANGE / 4 && + PythSpacesAway(pSoldier->sGridNo, sClosestOpponent) > TACTICAL_RANGE / 4 && (!ProneSightCoverAtSpot(pSoldier, pSoldier->sGridNo, FALSE) && !AnyCoverAtSpot(pSoldier, pSoldier->sGridNo) || pSoldier->TakenLargeHit()) && (pSoldier->TakenLargeHit() || pSoldier->ShockLevelPercent() > 20 + Random(80))) { @@ -5953,6 +5953,163 @@ INT16 ubMinAPCost; } } + DebugAI(AI_MSG_TOPIC, pSoldier, String("[Black cover advance]")); + // Black cover advance + if (SoldierAI(pSoldier) && + gfTurnBasedAI && + !pSoldier->bActionPoints == pSoldier->bInitialActionPoints && + pSoldier->bInitialActionPoints > APBPConstants[AP_MINIMUM] && + !gfHiddenInterrupt && + !gTacticalStatus.fInterruptOccurred && + !InARoom(pSoldier->sGridNo, NULL) && + !TileIsOutOfBounds(sClosestOpponent) && + //!InARoom(pSoldier->sGridNo, NULL) && + pSoldier->aiData.bOrders != STATIONARY && + pSoldier->aiData.bOrders != ONGUARD && + !AICheckSpecialRole(pSoldier) && + (ubBestAttackAction == AI_ACTION_NONE || ubBestAttackAction == AI_ACTION_FIRE_GUN && BestAttack.ubChanceToReallyHit < 5 * RangeChangeDesire(pSoldier)) && + AIGunRange(pSoldier) < DAY_VISION_RANGE && + pSoldier->aiData.bAIMorale >= MORALE_CONFIDENT && + (!AnyCoverAtSpot(pSoldier, pSoldier->sGridNo) || !ProneSightCoverAtSpot(pSoldier, pSoldier->sGridNo, FALSE) || AIGunRange(pSoldier) < PythSpacesAway(pSoldier->sGridNo, sClosestOpponent)) && + PythSpacesAway(pSoldier->sGridNo, sClosestOpponent) < MAX_VISION_RANGE && + DetermineMovementMode(pSoldier, AI_ACTION_GET_CLOSER) != CRAWLING && + pSoldier->aiData.bShock < RangeChangeDesire(pSoldier) * 2 && + (AIGunRange(pSoldier) < PythSpacesAway(pSoldier->sGridNo, sClosestOpponent) || + pSoldier->aiData.bLastAttackHit && pSoldier->sLastTarget != NOWHERE || + pSoldier->aiData.bAIMorale == MORALE_FEARLESS || + ubBestAttackAction == AI_ACTION_NONE || + ubBestAttackAction == AI_ACTION_FIRE_GUN && BestAttack.ubChanceToReallyHit == 1 || + !AnyCoverAtSpot(pSoldier, pSoldier->sGridNo))) + { + DebugAI(AI_MSG_INFO, pSoldier, String("find cover advance spot")); + + INT32 sClosestDisturbance = ClosestReachableDisturbance(pSoldier, &fClimb); + + if (!TileIsOutOfBounds(sClosestDisturbance)) + { + DebugAI(AI_MSG_INFO, pSoldier, String("closest reachable disturbance %d", sClosestDisturbance)); + + INT32 sAdvanceSpot = NOWHERE; + + DebugAI(AI_MSG_INFO, pSoldier, String("search for any cover advance spot")); + sAdvanceSpot = FindAdvanceSpot(pSoldier, sClosestDisturbance, AI_ACTION_GET_CLOSER, ADVANCE_SPOT_ANY_COVER, FALSE); + + if (!TileIsOutOfBounds(sAdvanceSpot)) + { + DebugAI(AI_MSG_INFO, pSoldier, String("found cover advance spot %d", sAdvanceSpot)); + + // check that we can reach desired location + pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, sAdvanceSpot, 0, AI_ACTION_GET_CLOSER, 0); + if (pSoldier->aiData.usActionData == sAdvanceSpot) + { + DebugAI(AI_MSG_INFO, pSoldier, String("cover advance spot ok")); + pSoldier->aiData.usActionData = sAdvanceSpot; + + //ScreenMsg(FONT_MCOLOR_LTGREEN, MSG_INTERFACE, L"[%d] found cover advance spot %d", pSoldier->ubID, sAdvanceSpot); + //BeginMultiPurposeLocator(sAdvanceSpot, pSoldier->pathing.bLevel, FALSE); + + return AI_ACTION_GET_CLOSER; + } + else + { + DebugAI(AI_MSG_INFO, pSoldier, String("cannot reach cover advance spot!")); + } + } + else + { + DebugAI(AI_MSG_INFO, pSoldier, String("cannot find cover advance spot")); + + // try to use smoke to cover advance movement + //gubNPCAPBudget = pSoldier->bActionPoints; + gubNPCAPBudget = 0; + gubNPCDistLimit = 0; + + // check path to closest disturbance + if (gfTurnBasedAI && + pSoldier->bActionPoints >= APBPConstants[AP_MINIMUM] && + pSoldier->bActionPoints == pSoldier->bInitialActionPoints && + !TileIsOutOfBounds(sClosestDisturbance) && + RangeChangeDesire(pSoldier) > 3 && + !AICheckIsSniper(pSoldier) && + !AICheckIsMachinegunner(pSoldier) && + pSoldier->aiData.bOrders != STATIONARY && + (pSoldier->aiData.bUnderFire || + pSoldier->aiData.bShock > 0 || + pSoldier->stats.bLife < pSoldier->stats.bLifeMax * 3 / 4 || + CountTeamUnderAttack(pSoldier->bTeam, pSoldier->sGridNo, DAY_VISION_RANGE / 2) > CountNearbyFriends(pSoldier, pSoldier->sGridNo, DAY_VISION_RANGE / 2) / 2 || + CountSeenEnemiesLastTurn(pSoldier) > CountNearbyFriends(pSoldier, pSoldier->sGridNo, DAY_VISION_RANGE / 2)) && + (Chance(SoldierDifficultyLevel(pSoldier) * 10) || Chance(TeamPercentKilled(pSoldier->bTeam)) || Chance(CountTeamUnderAttack(pSoldier->bTeam, pSoldier->sGridNo, DAY_VISION_RANGE / 2))) && + FindBestPath(pSoldier, sClosestDisturbance, pSoldier->pathing.bLevel, RUNNING, COPYROUTE, 0)) + { + INT16 sLoop; + INT32 sCoverSpot = NOWHERE; + + DebugAI(AI_MSG_INFO, pSoldier, String("found path to %d, path size %d ", sClosestDisturbance, pSoldier->pathing.usPathDataSize)); + + sCheckGridNo = pSoldier->sGridNo; + + for (sLoop = pSoldier->pathing.usPathIndex; sLoop < pSoldier->pathing.usPathDataSize; sLoop++) + { + sCheckGridNo = NewGridNo(sCheckGridNo, DirectionInc((UINT8)(pSoldier->pathing.usPathingData[sLoop]))); + + if (!TileIsOutOfBounds(sCheckGridNo) && + PythSpacesAway(pSoldier->sGridNo, sCheckGridNo) < TACTICAL_RANGE / 2 && + PythSpacesAway(pSoldier->sGridNo, sCheckGridNo) > TACTICAL_RANGE / 4 && + !Water(sCheckGridNo, pSoldier->pathing.bLevel) && + !InSmokeNearby(sCheckGridNo, pSoldier->pathing.bLevel) && + !InSmoke(sCheckGridNo, pSoldier->pathing.bLevel) && + (CorpseWarning(pSoldier, sCheckGridNo, pSoldier->pathing.bLevel) || InLightAtNight(sCheckGridNo, pSoldier->pathing.bLevel)) && + SightCoverAtSpot(pSoldier, sCheckGridNo, FALSE)) + { + CheckTossGrenadeAt(pSoldier, &BestThrow, sCheckGridNo, pSoldier->pathing.bLevel, EXPLOSV_SMOKE); + + if (BestThrow.ubPossible) + { + sCoverSpot = sCheckGridNo; + } + } + } + + if (!TileIsOutOfBounds(sCoverSpot)) + { + CheckTossGrenadeAt(pSoldier, &BestThrow, sCoverSpot, pSoldier->pathing.bLevel, EXPLOSV_SMOKE); + + if (BestThrow.ubPossible) + { + DebugAI(AI_MSG_INFO, pSoldier, String("prepare throw at spot %d level %d aimtime %d", BestThrow.sTarget, BestThrow.bTargetLevel, BestThrow.ubAimTime)); + + // if necessary, swap the usItem from holster into the hand position + if (BestThrow.bWeaponIn != HANDPOS) + { + DebugAI(AI_MSG_INFO, pSoldier, String("rearrange pocket")); + RearrangePocket(pSoldier, HANDPOS, BestThrow.bWeaponIn, FOREVER); + } + + // stand up before throwing if needed + if (gAnimControl[pSoldier->usAnimState].ubEndHeight < BestThrow.ubStance && + pSoldier->InternalIsValidStance(AIDirection(pSoldier->sGridNo, BestThrow.sTarget), BestThrow.ubStance)) + { + pSoldier->aiData.usActionData = BestThrow.ubStance; + pSoldier->aiData.bNextAction = AI_ACTION_TOSS_PROJECTILE; + pSoldier->aiData.usNextActionData = BestThrow.sTarget; + pSoldier->aiData.bNextTargetLevel = BestThrow.bTargetLevel; + pSoldier->aiData.bAimTime = BestThrow.ubAimTime; + return AI_ACTION_CHANGE_STANCE; + } + + pSoldier->aiData.usActionData = BestThrow.sTarget; + pSoldier->bTargetLevel = BestThrow.bTargetLevel; + pSoldier->aiData.bAimTime = BestThrow.ubAimTime; + + return(AI_ACTION_TOSS_PROJECTILE); + } + } + } + gubNPCAPBudget = 0; + } + } + } + if ( (pSoldier->bActionPoints == pSoldier->bInitialActionPoints) && (ubBestAttackAction == AI_ACTION_FIRE_GUN) && (pSoldier->aiData.bShock == 0) && @@ -5984,7 +6141,6 @@ INT16 ubMinAPCost; } - DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"LOOK FOR SOME KIND OF COVER BETTER THAN WHAT WE HAVE NOW"); //////////////////////////////////////////////////////////////////////////// // LOOK FOR SOME KIND OF COVER BETTER THAN WHAT WE HAVE NOW @@ -8736,7 +8892,7 @@ INT8 ArmedVehicleDecideActionRed( SOLDIERTYPE *pSoldier) // sevenfm: don't watch when overcrowded and not in a building if ( !InARoom( pSoldier->sGridNo, NULL ) ) { - bWatchPts -= CountNearbyFriends( pSoldier, pSoldier->sGridNo, DAY_VISION_RANGE / 8 ); + bWatchPts -= CountNearbyFriends( pSoldier, pSoldier->sGridNo, TACTICAL_RANGE / 8 ); } // sevenfm: don't help if seen enemy recently or under fire @@ -8806,7 +8962,7 @@ INT8 ArmedVehicleDecideActionRed( SOLDIERTYPE *pSoldier) #endif BOOLEAN fOvercrowded = FALSE; - if ( CountNearbyFriends( pSoldier, pSoldier->sGridNo, DAY_VISION_RANGE / 4 ) > 2 ) + if ( CountNearbyFriends( pSoldier, pSoldier->sGridNo, TACTICAL_RANGE / 4 ) > 2 ) { fOvercrowded = TRUE; } diff --git a/TacticalAI/FindLocations.cpp b/TacticalAI/FindLocations.cpp index a78c4347..0de8a9c9 100644 --- a/TacticalAI/FindLocations.cpp +++ b/TacticalAI/FindLocations.cpp @@ -442,28 +442,28 @@ INT32 CalcCoverValue(SOLDIERTYPE *pMe, INT32 sMyGridNo, INT32 iMyThreat, INT32 i // sevenfm: special calculations for zombies: zombie is very dangerous at close range if (pHim->IsZombie() || !AICheckHasGun(pHim)) { - if (sDist < (INT32)(DAY_VISION_RANGE / 2)) + if (sDist < (INT32)(TACTICAL_RANGE / 2)) { // 100 - 25 - bHisCTGT = 100 - 150 * sDist / DAY_VISION_RANGE; + bHisCTGT = 100 - 150 * sDist / TACTICAL_RANGE; } else { // 25 - 0 - bHisCTGT = 100 * DAY_VISION_RANGE * DAY_VISION_RANGE / (16 * sDist * sDist); + bHisCTGT = 100 * TACTICAL_RANGE * TACTICAL_RANGE / (16 * sDist * sDist); } } // sevenfm: if soldier has no gun, use different calculation if (pMe->IsZombie() || !AICheckHasGun(pMe)) { - if (sDist < (INT32)(DAY_VISION_RANGE / 2)) + if (sDist < (INT32)(TACTICAL_RANGE / 2)) { - bMyCTGT = 100 - 150 * sDist / DAY_VISION_RANGE; + bMyCTGT = 100 - 150 * sDist / TACTICAL_RANGE; } else { - bMyCTGT = 100 * DAY_VISION_RANGE * DAY_VISION_RANGE / (16 * sDist * sDist); + bMyCTGT = 100 * TACTICAL_RANGE * TACTICAL_RANGE / (16 * sDist * sDist); } } } @@ -473,13 +473,13 @@ INT32 CalcCoverValue(SOLDIERTYPE *pMe, INT32 sMyGridNo, INT32 iMyThreat, INT32 i iMyPosValue = bMyCTGT * iMyThreat * iMyAPsLeft; // add penalty to enemy position, bonus to my position if soldier has cover at spot - // max 25% at DAY_VISION_RANGE/2, 0 at zero range + // max 25% at TACTICAL_RANGE / 2, 0 at zero range if( gGameExternalOptions.fAIBetterCover ) { UINT8 ubCoverBonus = 25; - if (sDist < (INT32)(DAY_VISION_RANGE / 2)) + if (sDist < (INT32)(TACTICAL_RANGE / 2)) { - ubCoverBonus = ubCoverBonus * 2 * sDist / DAY_VISION_RANGE; + ubCoverBonus = ubCoverBonus * 2 * sDist / TACTICAL_RANGE; } if (!pHim->IsZombie() && AICheckHasGun(pHim) && AnyCoverFromSpot(sMyGridNo, bMyLevel, sHisGridNo, bHisLevel)) { @@ -536,7 +536,7 @@ INT32 CalcCoverValue(SOLDIERTYPE *pMe, INT32 sMyGridNo, INT32 iMyThreat, INT32 i if (gGameExternalOptions.fAIBetterCover) { if (!AnyCoverFromSpot(sMyGridNo, bMyLevel, sHisGridNo, bHisLevel) && - CountSeenEnemiesLastTurn(pMe) > CountNearbyFriends(pMe, sMyGridNo, DAY_VISION_RANGE / 2)) + CountSeenEnemiesLastTurn(pMe) > CountNearbyFriends(pMe, sMyGridNo, TACTICAL_RANGE / 2)) { iRangeFactor = iRangeFactor * (100 - bHisCTGT * __min(Threat[uiThreatIndex].iAPs, APBPConstants[AP_MAXIMUM]) / APBPConstants[AP_MAXIMUM]) / 100; } @@ -787,7 +787,7 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB // sevenfm: sight test if( gGameExternalOptions.fAIBetterCover ) { - if ( LocationToLocationLineOfSightTest( Threat[uiLoop].sGridNo, Threat[uiLoop].pOpponent->pathing.bLevel, pSoldier->sGridNo, pSoldier->pathing.bLevel, TRUE, DAY_VISION_RANGE * 2, STANDING_LOS_POS, PRONE_LOS_POS ) ) + if ( LocationToLocationLineOfSightTest( Threat[uiLoop].sGridNo, Threat[uiLoop].pOpponent->pathing.bLevel, pSoldier->sGridNo, pSoldier->pathing.bLevel, TRUE, MAX_VISION_RANGE, STANDING_LOS_POS, PRONE_LOS_POS ) ) //if ( SoldierToVirtualSoldierLineOfSightTest( Threat[uiLoop].pOpponent, pSoldier->sGridNo, pSoldier->pathing.bLevel, ANIM_PRONE, TRUE, NO_DISTANCE_LIMIT ) ) { fProneCover = FALSE; @@ -1053,7 +1053,7 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB // sevenfm: sight test if( gGameExternalOptions.fAIBetterCover ) { - if ( LocationToLocationLineOfSightTest( Threat[uiLoop].sGridNo, Threat[uiLoop].pOpponent->pathing.bLevel, sGridNo, pSoldier->pathing.bLevel, TRUE, DAY_VISION_RANGE * 2, STANDING_LOS_POS, PRONE_LOS_POS ) ) + if ( LocationToLocationLineOfSightTest( Threat[uiLoop].sGridNo, Threat[uiLoop].pOpponent->pathing.bLevel, sGridNo, pSoldier->pathing.bLevel, TRUE, MAX_VISION_RANGE, STANDING_LOS_POS, PRONE_LOS_POS ) ) //if ( SoldierToVirtualSoldierLineOfSightTest( Threat[uiLoop].pOpponent, sGridNo, pSoldier->pathing.bLevel, ANIM_PRONE, TRUE, -1 ) != 0 ) { fProneCover = FALSE; @@ -3329,7 +3329,7 @@ INT32 FindAdvanceSpot(SOLDIERTYPE *pSoldier, INT32 sTargetSpot, INT8 bAction, UI } // skip locations too close to target spot - if (PythSpacesAway(sGridNo, sTargetSpot) < (INT16)(DAY_VISION_RANGE / 4)) + if (PythSpacesAway(sGridNo, sTargetSpot) < (INT16)(TACTICAL_RANGE / 4)) { continue; } @@ -3613,7 +3613,7 @@ INT32 FindRetreatSpot(SOLDIERTYPE *pSoldier) // skip if too close to enemy //sClosestOpponent = ClosestKnownOpponent(pSoldier, NULL, NULL); sDistance = PythSpacesAway(sGridNo, sClosestOpponent); - if (sDistance < (INT16)(DAY_VISION_RANGE / 2)) + if (sDistance < (INT16)(TACTICAL_RANGE / 2)) { continue; } diff --git a/TacticalAI/ZombieDecideAction.cpp b/TacticalAI/ZombieDecideAction.cpp index 8bb7a3c7..9ed67fb8 100644 --- a/TacticalAI/ZombieDecideAction.cpp +++ b/TacticalAI/ZombieDecideAction.cpp @@ -691,8 +691,8 @@ INT8 ZombieDecideActionRed(SOLDIERTYPE *pSoldier) // sevenfm: try to advance using sight cover if( gfTurnBasedAI && - PythSpacesAway(pSoldier->sGridNo, sClosestDisturbance) < DAY_VISION_RANGE * 2 && - PythSpacesAway(pSoldier->sGridNo, sClosestDisturbance) > DAY_VISION_RANGE / 4 && + PythSpacesAway(pSoldier->sGridNo, sClosestDisturbance) < TACTICAL_RANGE * 2 && + PythSpacesAway(pSoldier->sGridNo, sClosestDisturbance) > TACTICAL_RANGE / 4 && !SightCoverAtSpot(pSoldier, pSoldier->aiData.usActionData, TRUE)) { INT32 sAdvanceSpot = FindAdvanceSpot(pSoldier, sClosestDisturbance, AI_ACTION_SEEK_OPPONENT, ADVANCE_SPOT_SIGHT_COVER, TRUE); @@ -1169,8 +1169,8 @@ INT8 ZombieDecideActionBlack(SOLDIERTYPE *pSoldier) { // sevenfm: try to advance using sight cover if( gfTurnBasedAI && - PythSpacesAway(pSoldier->sGridNo, sClosestDisturbance) < DAY_VISION_RANGE * 2 && - PythSpacesAway(pSoldier->sGridNo, sClosestDisturbance) > DAY_VISION_RANGE / 4 && + PythSpacesAway(pSoldier->sGridNo, sClosestDisturbance) < TACTICAL_RANGE * 2 && + PythSpacesAway(pSoldier->sGridNo, sClosestDisturbance) > TACTICAL_RANGE / 4 && !SightCoverAtSpot(pSoldier, pSoldier->aiData.usActionData, TRUE)) { DebugAI( AI_MSG_INFO, pSoldier, String("[advance spot]"));