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)