diff --git a/TacticalAI/AIUtils.cpp b/TacticalAI/AIUtils.cpp index 88933e6f0..e6ef7acb6 100644 --- a/TacticalAI/AIUtils.cpp +++ b/TacticalAI/AIUtils.cpp @@ -3908,11 +3908,11 @@ INT8 CalcMoraleNew(SOLDIERTYPE *pSoldier) bMoraleCategory++; } - // limit AI morale depending on morale and suppression shock - if( pSoldier->aiData.bShock ) - { - bMoraleCategory = min(bMoraleCategory, (20 + pSoldier->aiData.bMorale - 20 * min(3, pSoldier->aiData.bShock / 5)) / 20); - } + // limit AI morale when soldier is under heavy fire + if (pSoldier->ShockLevelPercent() > 75) + bMoraleCategory = min(bMoraleCategory, MORALE_NORMAL); + else if (pSoldier->ShockLevelPercent() > 50) + bMoraleCategory = min(bMoraleCategory, MORALE_CONFIDENT); // prevent hopeless morale when not under attack if (bMoraleCategory == MORALE_HOPELESS && !pSoldier->aiData.bUnderFire) @@ -3920,15 +3920,53 @@ INT8 CalcMoraleNew(SOLDIERTYPE *pSoldier) bMoraleCategory = MORALE_WORRIED; } - // if adjustments made it outside the allowed limits - if (bMoraleCategory < MORALE_HOPELESS) - bMoraleCategory = MORALE_HOPELESS; - else if (bMoraleCategory > MORALE_FEARLESS) - bMoraleCategory = MORALE_FEARLESS; + // check limits + bMoraleCategory = max(bMoraleCategory, MORALE_HOPELESS); + bMoraleCategory = min(bMoraleCategory, MORALE_FEARLESS); return(bMoraleCategory); } +BOOLEAN AICheckSpecialRole(SOLDIERTYPE *pSoldier) +{ + if (AICheckIsSniper(pSoldier) || AICheckIsMachinegunner(pSoldier) || AICheckIsMortarOperator(pSoldier) || AICheckIsRadioOperator(pSoldier) || AICheckIsCommander(pSoldier)) + return TRUE; + + return FALSE; +} + +BOOLEAN WeAttack(INT8 bTeam) +{ + if (bTeam >= MAXTEAMS) + { + return FALSE; + } + + if (bTeam != ENEMY_TEAM) + { + return FALSE; + } + + // check that every soldier has SEEKENEMY order + SOLDIERTYPE * pFriend; + + // Run through each friendly. + for (UINT8 iCounter = gTacticalStatus.Team[bTeam].bFirstID; iCounter <= gTacticalStatus.Team[bTeam].bLastID; iCounter++) + { + pFriend = MercPtrs[iCounter]; + + if (pFriend && + pFriend->bActive && + pFriend->stats.bLife >= OKLIFE && + pFriend->aiData.bOrders != SEEKENEMY) + { + return FALSE; + } + } + + return TRUE; +} + UINT8 CountNearbyFriendsLastAttackHit( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubDistance ) { CHECKF(pSoldier); diff --git a/TacticalAI/ai.h b/TacticalAI/ai.h index 3951c23ef..33d059d7d 100644 --- a/TacticalAI/ai.h +++ b/TacticalAI/ai.h @@ -351,6 +351,7 @@ BOOLEAN CorpseMilitiaTeam(ROTTING_CORPSE *pCorpse); BOOLEAN NorthSpot(INT32 sSpot, INT8 bLevel); BOOLEAN SoldierAI(SOLDIERTYPE *pSoldier); +BOOLEAN WeAttack(INT8 bTeam); BOOLEAN CheckSuppressionDirection(SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, INT8 bTargetLevel); UINT8 AIDirection(INT32 sSpot1, INT32 sSpot2); @@ -379,6 +380,8 @@ BOOLEAN AICheckIsGLOperator(SOLDIERTYPE *pSoldier); BOOLEAN AICheckIsOfficer(SOLDIERTYPE *pSoldier); BOOLEAN AICheckIsCommander(SOLDIERTYPE *pSoldier); +BOOLEAN AICheckSpecialRole(SOLDIERTYPE *pSoldier); + // ************************************************************* // Knowledge functions // *************************************************************