mirror of
https://github.com/1dot13/source.git
synced 2026-09-16 14:47:17 +02:00
AI:
- 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:
@@ -2306,6 +2306,7 @@ void LoadGameExternalOptions()
|
|||||||
gGameExternalOptions.fAIPathTweaks = iniReader.ReadBoolean("Tactical AI Settings", "AI_PATH_TWEAKS", TRUE);
|
gGameExternalOptions.fAIPathTweaks = iniReader.ReadBoolean("Tactical AI Settings", "AI_PATH_TWEAKS", TRUE);
|
||||||
gGameExternalOptions.fAIDecisionInfo = iniReader.ReadBoolean("Tactical AI Settings", "AI_DECISION_INFO", FALSE);
|
gGameExternalOptions.fAIDecisionInfo = iniReader.ReadBoolean("Tactical AI Settings", "AI_DECISION_INFO", FALSE);
|
||||||
gGameExternalOptions.fAIShootUnseen = iniReader.ReadBoolean("Tactical AI Settings", "AI_SHOOT_UNSEEN", FALSE);
|
gGameExternalOptions.fAIShootUnseen = iniReader.ReadBoolean("Tactical AI Settings", "AI_SHOOT_UNSEEN", FALSE);
|
||||||
|
gGameExternalOptions.fAISafeSuppression = iniReader.ReadBoolean("Tactical AI Settings", "AI_SAFE_SUPPRESSION", TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1566,6 +1566,7 @@ typedef struct
|
|||||||
BOOLEAN fAIPathTweaks;
|
BOOLEAN fAIPathTweaks;
|
||||||
BOOLEAN fAIDecisionInfo;
|
BOOLEAN fAIDecisionInfo;
|
||||||
BOOLEAN fAIShootUnseen;
|
BOOLEAN fAIShootUnseen;
|
||||||
|
BOOLEAN fAISafeSuppression;
|
||||||
|
|
||||||
} GAME_EXTERNAL_OPTIONS;
|
} GAME_EXTERNAL_OPTIONS;
|
||||||
|
|
||||||
|
|||||||
@@ -6138,3 +6138,41 @@ UINT8 CountPublicKnownEnemies(SOLDIERTYPE *pSoldier)
|
|||||||
|
|
||||||
return ubNum;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -3006,6 +3006,8 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
|
|||||||
pSoldier->aiData.bOrders != SNIPER &&
|
pSoldier->aiData.bOrders != SNIPER &&
|
||||||
BestShot.ubFriendlyFireChance <= MIN_CHANCE_TO_ACCIDENTALLY_HIT_SOMEONE &&
|
BestShot.ubFriendlyFireChance <= MIN_CHANCE_TO_ACCIDENTALLY_HIT_SOMEONE &&
|
||||||
!AICheckIsFlanking(pSoldier) &&
|
!AICheckIsFlanking(pSoldier) &&
|
||||||
|
(Chance(BestShot.ubChanceToReallyHit) || Chance(gGameExternalOptions.sSuppressionEffectiveness)) &&
|
||||||
|
(!gGameExternalOptions.fAISafeSuppression || CheckSuppressionDirection(pSoldier, BestShot.sTarget, BestShot.bTargetLevel)) &&
|
||||||
!pSoldier->RetreatCounterValue() &&
|
!pSoldier->RetreatCounterValue() &&
|
||||||
// check cover
|
// check cover
|
||||||
(fAnyCover || // safe position
|
(fAnyCover || // safe position
|
||||||
@@ -6152,12 +6154,20 @@ L_NEWAIM:
|
|||||||
}
|
}
|
||||||
|
|
||||||
pSoldier->bDoAutofire--;
|
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--;
|
pSoldier->aiData.bAimTime--;
|
||||||
sActualAimAP = CalcAPCostForAiming(pSoldier, BestAttack.sTarget, (INT8)pSoldier->aiData.bAimTime);
|
sActualAimAP = CalcAPCostForAiming(pSoldier, BestAttack.sTarget, (INT8)pSoldier->aiData.bAimTime);
|
||||||
goto L_NEWAIM;
|
goto L_NEWAIM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pSoldier->bDoAutofire > 0)
|
if (pSoldier->bDoAutofire > 0)
|
||||||
{
|
{
|
||||||
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier->bDoAutofire, pSoldier );
|
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
|
//dnl ch69 140913 return aiming for autofire with halfautofire fix
|
||||||
pSoldier->bDoBurst = 1;
|
pSoldier->bDoBurst = 1;
|
||||||
INT16 ubHalfBurstAPs = 256;
|
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;
|
iChance = 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ubHalfBurstAPs = CalcAPsToAutofire(pSoldier->CalcActionPoints(), &pSoldier->inv[BestAttack.bWeaponIn], 4, pSoldier);
|
ubHalfBurstAPs = CalcAPsToAutofire(pSoldier->CalcActionPoints(), &pSoldier->inv[BestAttack.bWeaponIn], 2, pSoldier);
|
||||||
if(Weapon[pSoldier->inv[BestAttack.bWeaponIn].usItem].NoSemiAuto)
|
|
||||||
iChance = 35;
|
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
|
// Try short autofire to enhance chance of hitting
|
||||||
pSoldier->bDoAutofire = 4;
|
pSoldier->bDoAutofire = 2;
|
||||||
BestAttack.ubAPCost += ubHalfBurstAPs + sActualAimAP;
|
BestAttack.ubAPCost += ubHalfBurstAPs + sActualAimAP;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -351,6 +351,8 @@ BOOLEAN CorpseMilitiaTeam(ROTTING_CORPSE *pCorpse);
|
|||||||
BOOLEAN NorthSpot(INT32 sSpot, INT8 bLevel);
|
BOOLEAN NorthSpot(INT32 sSpot, INT8 bLevel);
|
||||||
BOOLEAN SoldierAI(SOLDIERTYPE *pSoldier);
|
BOOLEAN SoldierAI(SOLDIERTYPE *pSoldier);
|
||||||
|
|
||||||
|
BOOLEAN CheckSuppressionDirection(SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, INT8 bTargetLevel);
|
||||||
|
|
||||||
UINT8 AIDirection(INT32 sSpot1, INT32 sSpot2);
|
UINT8 AIDirection(INT32 sSpot1, INT32 sSpot2);
|
||||||
|
|
||||||
BOOLEAN AIGunScoped(SOLDIERTYPE *pSoldier);
|
BOOLEAN AIGunScoped(SOLDIERTYPE *pSoldier);
|
||||||
|
|||||||
Reference in New Issue
Block a user