From f06df7741f342b09d2a2040c203a4fd0ee7db0fe Mon Sep 17 00:00:00 2001 From: Kriplo Date: Sun, 25 Aug 2013 07:36:03 +0000 Subject: [PATCH] Brief: //dnl ch61 - Basic support for reducing AI friendly fire. Details: - Friendly fire grids are defined during best shot calculation then AI decide depending of soldier character to fire or take other action. Still in autofire accidentally friendly hits could be higher depending of bullets spreading. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6313 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- Tactical/LOS.cpp | 3 ++ TacticalAI/AIInternals.h | 22 ++++++++++++++ TacticalAI/Attacks.cpp | 59 +++++++++++++++++++++++++++++++++++-- TacticalAI/DecideAction.cpp | 25 ++++++++++++++++ 4 files changed, 107 insertions(+), 2 deletions(-) diff --git a/Tactical/LOS.cpp b/Tactical/LOS.cpp index 71f5a3e7..176701ef 100644 --- a/Tactical/LOS.cpp +++ b/Tactical/LOS.cpp @@ -51,6 +51,7 @@ #include "soldier tile.h" // added by Flugente #include "Sound Control.h" // added by Flugente #include "Soldier Functions.h" // added by Flugente for DoesSoldierWearGasMask(...) +#include "AIInternals.h"//dnl ch61 180813 //forward declarations of common classes to eliminate includes class OBJECTTYPE; @@ -3418,6 +3419,7 @@ UINT8 CalcChanceToGetThrough( BULLET * pBullet ) guiLocalStructureCTH[iNumLocalStructures] = 100; gubLocalStructureNumTimesHit[iNumLocalStructures] = 0; iNumLocalStructures++; + gUnderFire.Add(pStructure->usStructureID, 100);//dnl ch61 241009 } else { @@ -3426,6 +3428,7 @@ UINT8 CalcChanceToGetThrough( BULLET * pBullet ) guiLocalStructureCTH[iNumLocalStructures] = MIN_CHANCE_TO_ACCIDENTALLY_HIT_SOMEONE; gubLocalStructureNumTimesHit[iNumLocalStructures] = 0; iNumLocalStructures++; + gUnderFire.Add(pStructure->usStructureID, MIN_CHANCE_TO_ACCIDENTALLY_HIT_SOMEONE);//dnl ch61 241009 } } } diff --git a/TacticalAI/AIInternals.h b/TacticalAI/AIInternals.h index 12db4b0c..ba8e5799 100644 --- a/TacticalAI/AIInternals.h +++ b/TacticalAI/AIInternals.h @@ -140,11 +140,33 @@ typedef struct INT32 iAttackValue; // relative worthiness of this type of attack INT32 sTarget; // target gridno of this attack INT8 bTargetLevel; // target level of this attack + UINT8 ubFriendlyFireChance; // highest chance to hit someone of our guys //dnl ch61 180813 INT16 ubAPCost; // how many APs the attack will use up INT8 bWeaponIn; // the inv slot of the weapon in question INT8 bScopeMode; // SANDRO: added for scope mode and alternative weapon holding } ATTACKTYPE; +//dnl ch61 180813 +#define MAXUNDERFIRE 100 +class UnderFire +{ +private: + BOOLEAN fEnable; + UINT16 usUnderFireCnt; + UINT16 usUnderFireID[MAXUNDERFIRE]; + UINT8 ubUnderFireCTH[MAXUNDERFIRE]; +public: + UnderFire(void){ Clear(); } + void Clear(void); + void Add(UINT16 usID, UINT8 ubCTH); + void Enable(void){ fEnable=TRUE; } + void Disable(void){ fEnable=FALSE; } + UINT16 GetUnderFireCnt(void){ return(usUnderFireCnt); } + UINT16 Count(INT8 bTeam); + UINT8 Chance(INT8 bTeam); +}; +extern UnderFire gUnderFire; + extern THREATTYPE Threat[MAXMERCS]; extern int ThreatPercent[10]; extern UINT8 SkipCoverCheck; diff --git a/TacticalAI/Attacks.cpp b/TacticalAI/Attacks.cpp index 4763634f..453750f6 100644 --- a/TacticalAI/Attacks.cpp +++ b/TacticalAI/Attacks.cpp @@ -233,9 +233,11 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns //KeepInterfaceGoing(); // calculate chance to get through the opponent's cover (if any) - + //dnl ch61 180813 + gUnderFire.Clear(); + gUnderFire.Enable(); ubChanceToGetThrough = AISoldierToSoldierChanceToGetThrough( pSoldier, pOpponent ); - + gUnderFire.Disable(); // ubChanceToGetThrough = ChanceToGetThrough(pSoldier,pOpponent->sGridNo,NOTFAKE,ACTUAL,TESTWALLS,9999,M9PISTOL,NOT_FOR_LOS); //NumMessage("Chance to get through = ",ubChanceToGetThrough); @@ -494,6 +496,10 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns pBestShot->iAttackValue = iAttackValue; pBestShot->ubAPCost = ubMinAPcost; pBestShot->bScopeMode = bScopeMode; + if(gUnderFire.Count(pSoldier->bTeam))//dnl ch61 180813 + pBestShot->ubFriendlyFireChance = gUnderFire.Chance(pSoldier->bTeam); + else + pBestShot->ubFriendlyFireChance = 0; } } pSoldier->bScopeMode = USE_BEST_SCOPE; // better reset this back @@ -2894,3 +2900,52 @@ FLOAT AICalcRecoilForShot( SOLDIERTYPE *pSoldier, OBJECTTYPE *pWeapon, UINT8 ubS FLOAT AverageRecoil = __max(0, ((FLOAT)sqrt( (FLOAT)(bRecoilX * bRecoilX) + (FLOAT)(bRecoilY * bRecoilY) ) - (gGameCTHConstants.RECOIL_MAX_COUNTER_FORCE * 0.7f) ) ); return AverageRecoil; } + +//dnl ch61 180813 +UnderFire gUnderFire; + +void UnderFire::Clear(void) +{ + usUnderFireCnt = 0; + memset(usUnderFireID, 0, sizeof(usUnderFireID)); + memset(ubUnderFireCTH, 0, sizeof(ubUnderFireCTH)); +} + +void UnderFire::Add(UINT16 usID, UINT8 ubCTH) +{ + if(!fEnable) + return; + if(usUnderFireCnt < MAXUNDERFIRE) + { + for(int i=0; ibTeam == bTeam) + ++cnt; + } + return(cnt); +} + +UINT8 UnderFire::Chance(INT8 bTeam) +{ + UINT8 cth = 0; + for(int i=0; ibTeam == bTeam && ubUnderFireCTH[i] > cth) + cth = ubUnderFireCTH[i]; + } + return(cth); +} diff --git a/TacticalAI/DecideAction.cpp b/TacticalAI/DecideAction.cpp index 3a9f902b..31f5cbca 100644 --- a/TacticalAI/DecideAction.cpp +++ b/TacticalAI/DecideAction.cpp @@ -4420,6 +4420,31 @@ INT16 ubMinAPCost; } } + if(BestShot.ubFriendlyFireChance)//dnl ch61 180813 + { + if(BestShot.ubFriendlyFireChance == 100) + { + if(pSoldier->aiData.bAttitude == AGGRESSIVE) + iChance = 5; + } + else + { + switch(pSoldier->aiData.bAttitude) + { + case DEFENSIVE:iChance = 15;break; + case BRAVESOLO:iChance = 25;break; + case BRAVEAID:iChance = 20;break; + case CUNNINGSOLO:iChance = 35;break; + case CUNNINGAID:iChance = 30;break; + case AGGRESSIVE:iChance = 45;break; + case ATTACKSLAYONLY:iChance = 40;break; + default:iChance = 10;break; + } + } + if(!((INT32)Random(100) < iChance)) + BestShot.ubPossible = FALSE; + } + if (BestShot.ubPossible) { // if the selected opponent is not a threat (unconscious & !serviced)