- new option AI_SAFE_SUPPRESSION adds additional checks for AI to avoid hitting friends when using suppression fire.
- chance to use suppression fire depends on actual chance to hit and SUPPRESSION_EFFECTIVENESS option
- reduced short burst to 2 bullets.
- improved code to use short burst

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8901 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Sevenfm
2020-10-16 17:53:02 +00:00
parent d867051cd6
commit 47c58e79d5
5 changed files with 68 additions and 7 deletions
+1
View File
@@ -2306,6 +2306,7 @@ void LoadGameExternalOptions()
gGameExternalOptions.fAIPathTweaks = iniReader.ReadBoolean("Tactical AI Settings", "AI_PATH_TWEAKS", TRUE);
gGameExternalOptions.fAIDecisionInfo = iniReader.ReadBoolean("Tactical AI Settings", "AI_DECISION_INFO", FALSE);
gGameExternalOptions.fAIShootUnseen = iniReader.ReadBoolean("Tactical AI Settings", "AI_SHOOT_UNSEEN", FALSE);
gGameExternalOptions.fAISafeSuppression = iniReader.ReadBoolean("Tactical AI Settings", "AI_SAFE_SUPPRESSION", TRUE);
}
+1
View File
@@ -1566,6 +1566,7 @@ typedef struct
BOOLEAN fAIPathTweaks;
BOOLEAN fAIDecisionInfo;
BOOLEAN fAIShootUnseen;
BOOLEAN fAISafeSuppression;
} GAME_EXTERNAL_OPTIONS;
+38
View File
@@ -6138,3 +6138,41 @@ UINT8 CountPublicKnownEnemies(SOLDIERTYPE *pSoldier)
return ubNum;
}
// sevenfm: check if suppression is possible (count friends in the fire direction)
BOOLEAN CheckSuppressionDirection(SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, INT8 bTargetLevel)
{
SOLDIERTYPE * pFriend;
UINT8 ubShootingDir;
UINT32 uiLoop;
CHECKF(pSoldier);
CHECKF(!TileIsOutOfBounds(sTargetGridNo));
ubShootingDir = AIDirection(pSoldier->sGridNo, sTargetGridNo);
for (uiLoop = 0; uiLoop < guiNumMercSlots; ++uiLoop)
{
pFriend = MercSlots[uiLoop];
if (pFriend &&
pFriend != pSoldier &&
pFriend->bActive &&
pFriend->bVisible == TRUE &&
pFriend->stats.bLife >= OKLIFE &&
(pFriend->bSide == pSoldier->bSide || CONSIDERED_NEUTRAL(pSoldier, pFriend)) &&
(pFriend->pathing.bLevel == pSoldier->pathing.bLevel || pFriend->pathing.bLevel == bTargetLevel) &&
ubShootingDir == AIDirection(pSoldier->sGridNo, pFriend->sGridNo) &&
PythSpacesAway(pSoldier->sGridNo, pFriend->sGridNo) > 1 &&
PythSpacesAway(pSoldier->sGridNo, pFriend->sGridNo) < 2 * TACTICAL_RANGE &&
(gAnimControl[pFriend->usAnimState].ubHeight == ANIM_STAND || gGameExternalOptions.fAllowTargetHeadAndLegIfProne) &&
//!pFriend->IsCowering() &&
AISoldierToSoldierChanceToGetThrough(pSoldier, pFriend) > 25)
//LocationToLocationLineOfSightTest(pSoldier->sGridNo, pSoldier->pathing.bLevel, pFriend->sGridNo, pFriend->pathing.bLevel, TRUE, NO_DISTANCE_LIMIT))
{
return FALSE;
}
}
return TRUE;
}
+26 -7
View File
@@ -3006,6 +3006,8 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
pSoldier->aiData.bOrders != SNIPER &&
BestShot.ubFriendlyFireChance <= MIN_CHANCE_TO_ACCIDENTALLY_HIT_SOMEONE &&
!AICheckIsFlanking(pSoldier) &&
(Chance(BestShot.ubChanceToReallyHit) || Chance(gGameExternalOptions.sSuppressionEffectiveness)) &&
(!gGameExternalOptions.fAISafeSuppression || CheckSuppressionDirection(pSoldier, BestShot.sTarget, BestShot.bTargetLevel)) &&
!pSoldier->RetreatCounterValue() &&
// check cover
(fAnyCover || // safe position
@@ -6152,12 +6154,20 @@ L_NEWAIM:
}
pSoldier->bDoAutofire--;
if(!UsingNewCTHSystem() && pSoldier->bDoAutofire < 3 && pSoldier->aiData.bAimTime > 0 && pSoldier->inv[BestAttack.bWeaponIn][0]->data.gun.ubGunShotsLeft >= 3)//dnl ch69 130913 let try increase autofire rate for aim cost
//dnl ch69 130913 let try increase autofire rate for aim cost
if(!UsingNewCTHSystem() &&
pSoldier->bDoAutofire < 3 &&
pSoldier->aiData.bAimTime > 0 &&
pSoldier->inv[BestAttack.bWeaponIn][0]->data.gun.ubGunShotsLeft >= 3 &&
Chance(gGameExternalOptions.sSuppressionEffectiveness) &&
(!gGameExternalOptions.fAISafeSuppression || CheckSuppressionDirection(pSoldier, BestShot.sTarget, BestShot.bTargetLevel)))
{
pSoldier->aiData.bAimTime--;
sActualAimAP = CalcAPCostForAiming(pSoldier, BestAttack.sTarget, (INT8)pSoldier->aiData.bAimTime);
goto L_NEWAIM;
}
if (pSoldier->bDoAutofire > 0)
{
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier->bDoAutofire, pSoldier );
@@ -6218,18 +6228,27 @@ L_NEWAIM:
//dnl ch69 140913 return aiming for autofire with halfautofire fix
pSoldier->bDoBurst = 1;
INT16 ubHalfBurstAPs = 256;
if(pSoldier->inv[BestAttack.bWeaponIn][0]->data.gun.ubGunShotsLeft < 4)
if (pSoldier->inv[BestAttack.bWeaponIn][0]->data.gun.ubGunShotsLeft < 4)
{
iChance = 0;
}
else
{
ubHalfBurstAPs = CalcAPsToAutofire(pSoldier->CalcActionPoints(), &pSoldier->inv[BestAttack.bWeaponIn], 4, pSoldier);
if(Weapon[pSoldier->inv[BestAttack.bWeaponIn].usItem].NoSemiAuto)
iChance = 35;
ubHalfBurstAPs = CalcAPsToAutofire(pSoldier->CalcActionPoints(), &pSoldier->inv[BestAttack.bWeaponIn], 2, pSoldier);
if (!CheckSuppressionDirection(pSoldier, BestAttack.sTarget, BestAttack.bTargetLevel))
iChance = 100;
else
iChance = BestAttack.ubChanceToReallyHit / 2;
if (Weapon[pSoldier->inv[BestAttack.bWeaponIn].usItem].NoSemiAuto || pSoldier->aiData.bOppCnt > 1)
iChance += (100 - iChance) / 2;
}
if((INT32)PreRandom(100) < iChance && pSoldier->bActionPoints > (2 * BestAttack.ubAPCost + ubHalfBurstAPs + sActualAimAP))
if(Chance(iChance) && pSoldier->bActionPoints >= (2 * BestAttack.ubAPCost + ubHalfBurstAPs + sActualAimAP))
{
// Try short autofire to enhance chance of hitting
pSoldier->bDoAutofire = 4;
pSoldier->bDoAutofire = 2;
BestAttack.ubAPCost += ubHalfBurstAPs + sActualAimAP;
}
else
+2
View File
@@ -351,6 +351,8 @@ BOOLEAN CorpseMilitiaTeam(ROTTING_CORPSE *pCorpse);
BOOLEAN NorthSpot(INT32 sSpot, INT8 bLevel);
BOOLEAN SoldierAI(SOLDIERTYPE *pSoldier);
BOOLEAN CheckSuppressionDirection(SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, INT8 bTargetLevel);
UINT8 AIDirection(INT32 sSpot1, INT32 sSpot2);
BOOLEAN AIGunScoped(SOLDIERTYPE *pSoldier);