mirror of
https://github.com/1dot13/source.git
synced 2026-09-02 14:36:06 +02:00
New option AI_SHOOT_UNSEEN (disabled by default): allow AI to shoot at recently seen/heard enemies (targets that nobody from soldier's team sees currently).
CalcBestShot: - improved hit rate calculation, take into account possible options INCREASE_AIMING_COSTS, FIRST_AIM_READY_COST_DIVISOR - minor code improvements New AI function LOS_Raised checks LOS with forced raised gun status, to get max view distance with scope git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8889 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+2
-1
@@ -2304,7 +2304,8 @@ void LoadGameExternalOptions()
|
|||||||
gGameExternalOptions.fAITacticalRetreat = iniReader.ReadBoolean("Tactical AI Settings", "AI_TACTICAL_RETREAT", FALSE);
|
gGameExternalOptions.fAITacticalRetreat = iniReader.ReadBoolean("Tactical AI Settings", "AI_TACTICAL_RETREAT", FALSE);
|
||||||
gGameExternalOptions.fAIMovementMode = iniReader.ReadBoolean("Tactical AI Settings", "AI_MOVEMENT_MODE", TRUE);
|
gGameExternalOptions.fAIMovementMode = iniReader.ReadBoolean("Tactical AI Settings", "AI_MOVEMENT_MODE", TRUE);
|
||||||
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, false);
|
gGameExternalOptions.fAIDecisionInfo = iniReader.ReadBoolean("Tactical AI Settings", "AI_DECISION_INFO", FALSE);
|
||||||
|
gGameExternalOptions.fAIShootUnseen = iniReader.ReadBoolean("Tactical AI Settings", "AI_SHOOT_UNSEEN", FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1565,6 +1565,7 @@ typedef struct
|
|||||||
BOOLEAN fAIMovementMode;
|
BOOLEAN fAIMovementMode;
|
||||||
BOOLEAN fAIPathTweaks;
|
BOOLEAN fAIPathTweaks;
|
||||||
BOOLEAN fAIDecisionInfo;
|
BOOLEAN fAIDecisionInfo;
|
||||||
|
BOOLEAN fAIShootUnseen;
|
||||||
|
|
||||||
} GAME_EXTERNAL_OPTIONS;
|
} GAME_EXTERNAL_OPTIONS;
|
||||||
|
|
||||||
|
|||||||
+7
-270
@@ -10679,275 +10679,12 @@ FLOAT CalcCounterForceChange( SOLDIERTYPE * pShooter, UINT32 uiCounterForceAccur
|
|||||||
return dDelta;
|
return dDelta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sevenfm: AI function to quickly determine LOS between soldiers, forcing raised gun status to get max view distance
|
||||||
#if 0
|
INT32 LOS_Raised(SOLDIERTYPE * pStartSoldier, SOLDIERTYPE * pEndSoldier, int iTileSightLimit, UINT8 ubAimLocation)
|
||||||
{
|
{
|
||||||
INT32 cntx, cnty;
|
INT32 result;
|
||||||
INT8 bX, bY;
|
gbForceWeaponReady = true;
|
||||||
INT16 sAngleSum = 0;
|
result = SoldierToSoldierLineOfSightTest(pStartSoldier, pEndSoldier, TRUE, iTileSightLimit, ubAimLocation);
|
||||||
INT8 bNumSums = 0;
|
gbForceWeaponReady = false;
|
||||||
INT16 sAngleAv;
|
return result;
|
||||||
BOOLEAN fOkX, fOkY;
|
|
||||||
BOOLEAN fGoodX, fGoodY;
|
|
||||||
|
|
||||||
//OK, center on xy and goforit!
|
|
||||||
for ( cntx = 0; cntx < 3; cntx++ )
|
|
||||||
{
|
|
||||||
bX = bLOSX + ( cntx - 1 );
|
|
||||||
|
|
||||||
// Check for boundry conditions, use same as one before boundary
|
|
||||||
if ( bX < 0 || bX > 4 )
|
|
||||||
{
|
|
||||||
fOkX = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fOkX = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( cnty = 0; cnty < 3; cnty++ )
|
|
||||||
{
|
|
||||||
fGoodX = fGoodY = TRUE;
|
|
||||||
|
|
||||||
bY = bLOSY + ( cnty - 1 );
|
|
||||||
|
|
||||||
if ( bY < 0 || bY > 4 )
|
|
||||||
{
|
|
||||||
fOkY = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fOkY = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( bY < 0 )
|
|
||||||
{
|
|
||||||
if ( fOkX )
|
|
||||||
{
|
|
||||||
bY = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fGoodY = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( bY > 4 )
|
|
||||||
{
|
|
||||||
if ( fOkX )
|
|
||||||
{
|
|
||||||
bY = 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fGoodY = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( bX < 0 )
|
|
||||||
{
|
|
||||||
if ( fOkY )
|
|
||||||
{
|
|
||||||
bX = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fGoodX = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( bX > 4 )
|
|
||||||
{
|
|
||||||
if ( fOkX )
|
|
||||||
{
|
|
||||||
bX = 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fGoodX = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !fGoodX || !fGoodY )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((*(pStructure->pShape))[bX][bY] & AtHeight[ bLOSZ ]) > 0)
|
|
||||||
{
|
|
||||||
// OK, now add angles, but not the center!
|
|
||||||
if ( cntx == 1 && cnty == 1 )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sAngleSum += gsLOSDirLUT[ cntx ][cnty];
|
|
||||||
bNumSums++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Average angle
|
|
||||||
if ( bNumSums > 0)
|
|
||||||
{
|
|
||||||
sAngleAv = sAngleSum / bNumSums;
|
|
||||||
|
|
||||||
// This is our normal in XY plane!
|
|
||||||
// Get unit vector from this
|
|
||||||
*pdNormalX = cos( ( (float)sAngleAv / 180 ) * PI );
|
|
||||||
*pdNormalY = sin( ( (float)sAngleAv / 180 ) * PI );
|
|
||||||
|
|
||||||
// OK done, now determine direction
|
|
||||||
if ( dDeltaX > 0 )
|
|
||||||
{
|
|
||||||
*pdNormalX *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( dDeltaY > 0 )
|
|
||||||
{
|
|
||||||
*pdNormalY *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( bLOSZ == 3 )
|
|
||||||
{
|
|
||||||
// Prependicular
|
|
||||||
*pdNormalX = 0;
|
|
||||||
*pdNormalY = 0;
|
|
||||||
*pdNormalZ = -1;
|
|
||||||
}
|
|
||||||
else if ( bLOSZ > 0 && (((*(pStructure->pShape))[bLOSX][bLOSY] & AtHeight[ bLOSZ +1 ]) ) == 0)
|
|
||||||
{
|
|
||||||
*pdNormalX = 0;
|
|
||||||
*pdNormalY = 0;
|
|
||||||
*pdNormalZ = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*pdNormalZ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return( TRUE );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*pdNormalX = 0;
|
|
||||||
*pdNormalY = 0;
|
|
||||||
|
|
||||||
return( FALSE );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
INT32 cntx, cnty;
|
|
||||||
INT8 bX, bY;
|
|
||||||
INT16 sAngleSum = 0;
|
|
||||||
INT8 bNumSums = 0;
|
|
||||||
INT16 sAngleAv;
|
|
||||||
BOOLEAN fAlongX, fAlongY;
|
|
||||||
|
|
||||||
|
|
||||||
fAlongX = fAlongY = FALSE;
|
|
||||||
|
|
||||||
//1) LOOK ALONG X
|
|
||||||
bX = bLOSX - 1;
|
|
||||||
bY = bLOSY;
|
|
||||||
|
|
||||||
if ( bX >= 0 && bX <= 4 )
|
|
||||||
{
|
|
||||||
if (((*(pStructure->pShape))[bX][bY] & AtHeight[ bLOSZ ]) > 0 )
|
|
||||||
{
|
|
||||||
fAlongX = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bX = bLOSX + 1;
|
|
||||||
bY = bLOSY;
|
|
||||||
|
|
||||||
if ( bX >= 0 && bX <= 4 )
|
|
||||||
{
|
|
||||||
if (((*(pStructure->pShape))[bX][bY] & AtHeight[ bLOSZ ]) > 0 )
|
|
||||||
{
|
|
||||||
fAlongX = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//1) LOOK ALONG Y
|
|
||||||
bX = bLOSX;
|
|
||||||
bY = bLOSY - 1;
|
|
||||||
|
|
||||||
if ( bY >= 0 && bY <= 4 )
|
|
||||||
{
|
|
||||||
if (((*(pStructure->pShape))[bX][bY] & AtHeight[ bLOSZ ]) > 0 )
|
|
||||||
{
|
|
||||||
fAlongY = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bX = bLOSX;
|
|
||||||
bY = bLOSY + 1;
|
|
||||||
|
|
||||||
if ( bY >= 0 && bY <= 4 )
|
|
||||||
{
|
|
||||||
if (((*(pStructure->pShape))[bX][bY] & AtHeight[ bLOSZ ]) > 0 )
|
|
||||||
{
|
|
||||||
fAlongY = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ( fAlongX )
|
|
||||||
{
|
|
||||||
*pdNormalY = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*pdNormalY = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( fAlongY )
|
|
||||||
{
|
|
||||||
*pdNormalX = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*pdNormalX = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// OK done, now determine direction
|
|
||||||
if ( dDeltaX > 0 )
|
|
||||||
{
|
|
||||||
*pdNormalX *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( dDeltaY < 0 )
|
|
||||||
{
|
|
||||||
*pdNormalY *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( bLOSZ < 4 && (((*(pStructure->pShape))[bLOSX][bLOSY] & AtHeight[ bLOSZ +1 ]) ) == 0)
|
|
||||||
{
|
|
||||||
*pdNormalX = 0;
|
|
||||||
*pdNormalY = 0;
|
|
||||||
*pdNormalZ = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*pdNormalZ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( *pdNormalX == 0 && *pdNormalY == 0 && *pdNormalZ == 0 )
|
|
||||||
{
|
|
||||||
return( FALSE );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return( TRUE );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -154,6 +154,8 @@ UINT8 AISoldierToSoldierChanceToGetThrough( SOLDIERTYPE * pStartSoldier, SOLDIER
|
|||||||
UINT8 AISoldierToLocationChanceToGetThrough( SOLDIERTYPE * pStartSoldier, INT32 sGridNo, INT8 bLevel, INT8 bCubeLevel );
|
UINT8 AISoldierToLocationChanceToGetThrough( SOLDIERTYPE * pStartSoldier, INT32 sGridNo, INT8 bLevel, INT8 bCubeLevel );
|
||||||
UINT8 SoldierToLocationChanceToGetThrough( SOLDIERTYPE * pStartSoldier, INT32 sGridNo, INT8 bLevel, INT8 bCubeLevel, UINT8 ubTargetID );
|
UINT8 SoldierToLocationChanceToGetThrough( SOLDIERTYPE * pStartSoldier, INT32 sGridNo, INT8 bLevel, INT8 bCubeLevel, UINT8 ubTargetID );
|
||||||
INT32 SoldierToLocationWindowTest( SOLDIERTYPE * pStartSoldier, INT32 sEndGridNo );
|
INT32 SoldierToLocationWindowTest( SOLDIERTYPE * pStartSoldier, INT32 sEndGridNo );
|
||||||
|
// sevenfm: AI LOS functions
|
||||||
|
INT32 LOS_Raised(SOLDIERTYPE * pStartSoldier, SOLDIERTYPE * pEndSoldier, int iTileSightLimit = CALC_FROM_ALL_DIRS, UINT8 ubAimLocation = LOS_POS);
|
||||||
|
|
||||||
// sevenfm: added start/end LOS heights
|
// sevenfm: added start/end LOS heights
|
||||||
INT32 LocationToLocationLineOfSightTest( INT32 sStartGridNo, INT8 bStartLevel, INT32 sEndGridNo, INT8 bEndLevel, INT8 bAware, int iTileSightLimit, FLOAT dStartPos = STANDING_LOS_POS, FLOAT dEndPos = STANDING_LOS_POS);
|
INT32 LocationToLocationLineOfSightTest( INT32 sStartGridNo, INT8 bStartLevel, INT32 sEndGridNo, INT8 bEndLevel, INT8 bAware, int iTileSightLimit, FLOAT dStartPos = STANDING_LOS_POS, FLOAT dEndPos = STANDING_LOS_POS);
|
||||||
|
|||||||
+72
-58
@@ -171,20 +171,22 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
|
|||||||
UINT32 uiLoop;
|
UINT32 uiLoop;
|
||||||
INT32 iAttackValue, iThreatValue, iHitRate, iBestHitRate, iPercentBetter, iEstDamage, iTrueLastTarget;
|
INT32 iAttackValue, iThreatValue, iHitRate, iBestHitRate, iPercentBetter, iEstDamage, iTrueLastTarget;
|
||||||
UINT16 usTrueState, usTurningCost, usRaiseGunCost;
|
UINT16 usTrueState, usTurningCost, usRaiseGunCost;
|
||||||
INT16 ubAimTime;
|
INT16 sMinAPcost;
|
||||||
INT16 ubMinAPcost;
|
INT16 sRawAPCost;
|
||||||
INT16 ubRawAPCost;
|
INT16 sAimAPCost;
|
||||||
INT16 sBestAPcost;
|
INT16 sBestAPcost;
|
||||||
INT16 ubChanceToHit;
|
INT16 sChanceToHit;
|
||||||
INT16 ubBestAimTime;
|
INT16 sAimTime;
|
||||||
INT16 ubChanceToGetThrough;
|
INT16 sBestAimTime;
|
||||||
INT16 ubBestChanceToGetThrough;
|
INT16 sMaxPossibleAimTime;
|
||||||
|
UINT8 ubChanceToGetThrough;
|
||||||
|
UINT8 ubBestChanceToGetThrough;
|
||||||
UINT8 ubFriendlyFireChance;
|
UINT8 ubFriendlyFireChance;
|
||||||
UINT8 ubBestFriendlyFireChance;
|
UINT8 ubBestFriendlyFireChance;
|
||||||
INT16 ubBestChanceToHit;
|
INT16 sBestChanceToHit;
|
||||||
INT16 sStanceAPcost;
|
INT16 sStanceAPcost;
|
||||||
BOOLEAN fAddingTurningCost, fAddingRaiseGunCost;
|
BOOLEAN fAddingTurningCost, fAddingRaiseGunCost;
|
||||||
UINT8 ubMaxPossibleAimTime, ubStance, ubBestStance, ubChanceToReallyHit;
|
UINT8 ubStance, ubBestStance, ubChanceToReallyHit;
|
||||||
INT8 bScopeMode;
|
INT8 bScopeMode;
|
||||||
SOLDIERTYPE *pOpponent;
|
SOLDIERTYPE *pOpponent;
|
||||||
|
|
||||||
@@ -272,11 +274,18 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
|
|||||||
// sevenfm: determine if we shoot on unseen target for suppression
|
// sevenfm: determine if we shoot on unseen target for suppression
|
||||||
if (bPersonalKnowledge != SEEN_CURRENTLY &&
|
if (bPersonalKnowledge != SEEN_CURRENTLY &&
|
||||||
bPublicKnowledge != SEEN_CURRENTLY &&
|
bPublicKnowledge != SEEN_CURRENTLY &&
|
||||||
!SoldierToSoldierLineOfSightTest(pSoldier, pOpponent, TRUE, CALC_FROM_ALL_DIRS))
|
//!SoldierToSoldierLineOfSightTest(pSoldier, pOpponent, TRUE, CALC_FROM_ALL_DIRS))
|
||||||
|
!LOS_Raised(pSoldier, pOpponent, CALC_FROM_ALL_DIRS))
|
||||||
{
|
{
|
||||||
fSuppression = TRUE;
|
fSuppression = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sevenfm: shooting at unseen opponents is optional
|
||||||
|
if (fSuppression && !gGameExternalOptions.fAIShootUnseen)
|
||||||
|
{
|
||||||
|
continue; // next opponent
|
||||||
|
}
|
||||||
|
|
||||||
// determine enemy location
|
// determine enemy location
|
||||||
if (fSuppression)
|
if (fSuppression)
|
||||||
{
|
{
|
||||||
@@ -309,7 +318,8 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
|
|||||||
// no fire on unseen opponents with throwing knives
|
// no fire on unseen opponents with throwing knives
|
||||||
if ((Item[pSoldier->usAttackingWeapon].usItemClass & IC_THROWING_KNIFE) &&
|
if ((Item[pSoldier->usAttackingWeapon].usItemClass & IC_THROWING_KNIFE) &&
|
||||||
bPersonalKnowledge != SEEN_CURRENTLY &&
|
bPersonalKnowledge != SEEN_CURRENTLY &&
|
||||||
!SoldierToSoldierLineOfSightTest(pSoldier, pOpponent, TRUE, CALC_FROM_ALL_DIRS))
|
//!SoldierToSoldierLineOfSightTest(pSoldier, pOpponent, TRUE, CALC_FROM_ALL_DIRS))
|
||||||
|
!LOS_Raised(pSoldier, pOpponent, CALC_FROM_ALL_DIRS))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -335,7 +345,8 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
|
|||||||
|
|
||||||
// shoot through wall check
|
// shoot through wall check
|
||||||
if( bPersonalKnowledge != SEEN_CURRENTLY &&
|
if( bPersonalKnowledge != SEEN_CURRENTLY &&
|
||||||
!SoldierToSoldierLineOfSightTest(pSoldier, pOpponent, TRUE, CALC_FROM_ALL_DIRS) &&
|
//!SoldierToSoldierLineOfSightTest(pSoldier, pOpponent, TRUE, CALC_FROM_ALL_DIRS) &&
|
||||||
|
!LOS_Raised(pSoldier, pOpponent, CALC_FROM_ALL_DIRS) &&
|
||||||
!SoldierToVirtualSoldierLineOfSightTest(pSoldier, sTarget, bLevel, ANIM_STAND, TRUE, NO_DISTANCE_LIMIT) &&
|
!SoldierToVirtualSoldierLineOfSightTest(pSoldier, sTarget, bLevel, ANIM_STAND, TRUE, NO_DISTANCE_LIMIT) &&
|
||||||
!LocationToLocationLineOfSightTest(pSoldier->sGridNo, pSoldier->pathing.bLevel, sTarget, bLevel, TRUE, NO_DISTANCE_LIMIT) &&
|
!LocationToLocationLineOfSightTest(pSoldier->sGridNo, pSoldier->pathing.bLevel, sTarget, bLevel, TRUE, NO_DISTANCE_LIMIT) &&
|
||||||
!fReturnFire &&
|
!fReturnFire &&
|
||||||
@@ -348,11 +359,11 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
|
|||||||
#ifdef DEBUGATTACKS
|
#ifdef DEBUGATTACKS
|
||||||
DebugAI( String( "%s sees %s at gridno %d\n",pSoldier->GetName(),ExtMen[pOpponent->ubID].GetName(),pOpponent->sGridNo ) );
|
DebugAI( String( "%s sees %s at gridno %d\n",pSoldier->GetName(),ExtMen[pOpponent->ubID].GetName(),pOpponent->sGridNo ) );
|
||||||
#endif
|
#endif
|
||||||
ubMinAPcost = MinAPsToAttack(pSoldier, sTarget, DONTADDTURNCOST, 0);
|
sMinAPcost = MinAPsToAttack(pSoldier, sTarget, DONTADDTURNCOST, 0);
|
||||||
// later will be decide if shoot is possible this here is just best guess so ignore turnover
|
// later will be decide if shoot is possible this here is just best guess so ignore turnover
|
||||||
|
|
||||||
// if we don't have enough APs left to shoot even a snap-shot at this guy
|
// if we don't have enough APs left to shoot even a snap-shot at this guy
|
||||||
if (ubMinAPcost > pSoldier->bActionPoints)
|
if (sMinAPcost > pSoldier->bActionPoints)
|
||||||
continue; // next opponent
|
continue; // next opponent
|
||||||
|
|
||||||
// sevenfm: check CTGT and friendly fire for each stance instead since they can be different
|
// sevenfm: check CTGT and friendly fire for each stance instead since they can be different
|
||||||
@@ -455,13 +466,13 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
|
|||||||
else
|
else
|
||||||
usRaiseGunCost = 0;
|
usRaiseGunCost = 0;
|
||||||
}
|
}
|
||||||
ubRawAPCost = MinAPsToShootOrStab(pSoldier, sTarget, 0, FALSE, 2);
|
sRawAPCost = MinAPsToShootOrStab(pSoldier, sTarget, 0, FALSE, 2);
|
||||||
ubMinAPcost = ubRawAPCost + usTurningCost + sStanceAPcost + usRaiseGunCost;
|
sMinAPcost = sRawAPCost + usTurningCost + sStanceAPcost + usRaiseGunCost;
|
||||||
|
|
||||||
if(pSoldier->bActionPoints - ubMinAPcost >= 0)
|
if(pSoldier->bActionPoints - sMinAPcost >= 0)
|
||||||
{
|
{
|
||||||
// calc next attack's minimum shooting cost (excludes readying & turning & raise gun)
|
// calc next attack's minimum shooting cost (excludes readying & turning & raise gun)
|
||||||
ubMaxPossibleAimTime = CalcAimingLevelsAvailableWithAP(pSoldier, sTarget, pSoldier->bActionPoints - ubMinAPcost);
|
sMaxPossibleAimTime = CalcAimingLevelsAvailableWithAP(pSoldier, sTarget, pSoldier->bActionPoints - sMinAPcost);
|
||||||
|
|
||||||
// sevenfm: check CTGT and friendly fire chance for every stance
|
// sevenfm: check CTGT and friendly fire chance for every stance
|
||||||
gUnderFire.Clear();
|
gUnderFire.Clear();
|
||||||
@@ -476,21 +487,22 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
|
|||||||
// sevenfm: only use this stance if we can hit target and cannot hit friends
|
// sevenfm: only use this stance if we can hit target and cannot hit friends
|
||||||
if (ubChanceToGetThrough > 0 && ubFriendlyFireChance <= MIN_CHANCE_TO_ACCIDENTALLY_HIT_SOMEONE)
|
if (ubChanceToGetThrough > 0 && ubFriendlyFireChance <= MIN_CHANCE_TO_ACCIDENTALLY_HIT_SOMEONE)
|
||||||
{
|
{
|
||||||
for (ubAimTime = 0; ubAimTime <= ubMaxPossibleAimTime; ubAimTime++)
|
for (sAimTime = 0; sAimTime <= sMaxPossibleAimTime; sAimTime++)
|
||||||
{
|
{
|
||||||
ubChanceToHit = AICalcChanceToHitGun(pSoldier, sTarget, ubAimTime, AIM_SHOT_TORSO, bLevel, STANDING);
|
sChanceToHit = AICalcChanceToHitGun(pSoldier, sTarget, sAimTime, AIM_SHOT_TORSO, bLevel, STANDING);
|
||||||
iHitRate = ubChanceToHit * (pSoldier->bActionPoints - (ubMinAPcost - ubRawAPCost)) / (ubRawAPCost + ubAimTime * APBPConstants[AP_CLICK_AIM]);
|
sAimAPCost = CalcAPCostForAiming(pSoldier, sTarget, (INT8)sAimTime);
|
||||||
|
iHitRate = sChanceToHit * (pSoldier->bActionPoints - (sMinAPcost - sRawAPCost)) / (sRawAPCost + sAimAPCost);
|
||||||
// sevenfm: take into account CTGT for every stance
|
// sevenfm: take into account CTGT for every stance
|
||||||
if (iHitRate * ubChanceToGetThrough > iBestHitRate * ubBestChanceToGetThrough ||
|
if (iHitRate * ubChanceToGetThrough > iBestHitRate * ubBestChanceToGetThrough ||
|
||||||
(Item[pSoldier->usAttackingWeapon].usItemClass & IC_THROWING_KNIFE) && ubChanceToHit > ubBestChanceToHit)// rather take best chance for throwing knives
|
(Item[pSoldier->usAttackingWeapon].usItemClass & IC_THROWING_KNIFE) && sChanceToHit > sBestChanceToHit)// rather take best chance for throwing knives
|
||||||
{
|
{
|
||||||
iBestHitRate = iHitRate;
|
iBestHitRate = iHitRate;
|
||||||
ubBestAimTime = ubAimTime;
|
sBestAimTime = sAimTime;
|
||||||
ubBestChanceToHit = ubChanceToHit;
|
sBestChanceToHit = sChanceToHit;
|
||||||
ubBestChanceToGetThrough = ubChanceToGetThrough;
|
ubBestChanceToGetThrough = ubChanceToGetThrough;
|
||||||
ubBestFriendlyFireChance = ubFriendlyFireChance;
|
ubBestFriendlyFireChance = ubFriendlyFireChance;
|
||||||
bScopeMode = pSoldier->bScopeMode;
|
bScopeMode = pSoldier->bScopeMode;
|
||||||
sBestAPcost = ubMinAPcost;
|
sBestAPcost = sMinAPcost;
|
||||||
ubBestStance = ubStance;
|
ubBestStance = ubStance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -526,12 +538,12 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
|
|||||||
else
|
else
|
||||||
usRaiseGunCost = 0;
|
usRaiseGunCost = 0;
|
||||||
}
|
}
|
||||||
ubRawAPCost = MinAPsToShootOrStab(pSoldier, sTarget, 0, FALSE, 2);
|
sRawAPCost = MinAPsToShootOrStab(pSoldier, sTarget, 0, FALSE, 2);
|
||||||
ubMinAPcost = ubRawAPCost + usTurningCost + sStanceAPcost + usRaiseGunCost;
|
sMinAPcost = sRawAPCost + usTurningCost + sStanceAPcost + usRaiseGunCost;
|
||||||
|
|
||||||
if(pSoldier->bActionPoints - ubMinAPcost >= 0)
|
if(pSoldier->bActionPoints - sMinAPcost >= 0)
|
||||||
{
|
{
|
||||||
ubMaxPossibleAimTime = CalcAimingLevelsAvailableWithAP(pSoldier, sTarget, pSoldier->bActionPoints - ubMinAPcost);
|
sMaxPossibleAimTime = CalcAimingLevelsAvailableWithAP(pSoldier, sTarget, pSoldier->bActionPoints - sMinAPcost);
|
||||||
|
|
||||||
// sevenfm: check CTGT and friendly fire chance for every stance
|
// sevenfm: check CTGT and friendly fire chance for every stance
|
||||||
gUnderFire.Clear();
|
gUnderFire.Clear();
|
||||||
@@ -546,20 +558,21 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
|
|||||||
// sevenfm: only use this stance if we can hit target and cannot hit friends
|
// sevenfm: only use this stance if we can hit target and cannot hit friends
|
||||||
if (ubChanceToGetThrough > 0 && ubFriendlyFireChance <= MIN_CHANCE_TO_ACCIDENTALLY_HIT_SOMEONE)
|
if (ubChanceToGetThrough > 0 && ubFriendlyFireChance <= MIN_CHANCE_TO_ACCIDENTALLY_HIT_SOMEONE)
|
||||||
{
|
{
|
||||||
for (ubAimTime = 0; ubAimTime <= ubMaxPossibleAimTime; ubAimTime++)
|
for (sAimTime = 0; sAimTime <= sMaxPossibleAimTime; sAimTime++)
|
||||||
{
|
{
|
||||||
ubChanceToHit = AICalcChanceToHitGun(pSoldier, sTarget, ubAimTime, AIM_SHOT_TORSO, bLevel, CROUCHING);
|
sChanceToHit = AICalcChanceToHitGun(pSoldier, sTarget, sAimTime, AIM_SHOT_TORSO, bLevel, CROUCHING);
|
||||||
iHitRate = ubChanceToHit * (pSoldier->bActionPoints - (ubMinAPcost - ubRawAPCost)) / (ubRawAPCost + ubAimTime * APBPConstants[AP_CLICK_AIM]);
|
sAimAPCost = CalcAPCostForAiming(pSoldier, sTarget, (INT8)sAimTime);
|
||||||
|
iHitRate = sChanceToHit * (pSoldier->bActionPoints - (sMinAPcost - sRawAPCost)) / (sRawAPCost + sAimAPCost);
|
||||||
// sevenfm: take into account CTGT for every stance
|
// sevenfm: take into account CTGT for every stance
|
||||||
if (iHitRate * ubChanceToGetThrough > iBestHitRate * ubBestChanceToGetThrough)
|
if (iHitRate * ubChanceToGetThrough > iBestHitRate * ubBestChanceToGetThrough)
|
||||||
{
|
{
|
||||||
iBestHitRate = iHitRate;
|
iBestHitRate = iHitRate;
|
||||||
ubBestAimTime = ubAimTime;
|
sBestAimTime = sAimTime;
|
||||||
ubBestChanceToHit = ubChanceToHit;
|
sBestChanceToHit = sChanceToHit;
|
||||||
ubBestChanceToGetThrough = ubChanceToGetThrough;
|
ubBestChanceToGetThrough = ubChanceToGetThrough;
|
||||||
ubBestFriendlyFireChance = ubFriendlyFireChance;
|
ubBestFriendlyFireChance = ubFriendlyFireChance;
|
||||||
bScopeMode = pSoldier->bScopeMode;
|
bScopeMode = pSoldier->bScopeMode;
|
||||||
sBestAPcost = ubMinAPcost;
|
sBestAPcost = sMinAPcost;
|
||||||
ubBestStance = ubStance;
|
ubBestStance = ubStance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -589,12 +602,12 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
|
|||||||
GetAPChargeForShootOrStabWRTGunRaises(pSoldier, sTarget, TRUE, &fAddingTurningCost, &fAddingRaiseGunCost, 0);
|
GetAPChargeForShootOrStabWRTGunRaises(pSoldier, sTarget, TRUE, &fAddingTurningCost, &fAddingRaiseGunCost, 0);
|
||||||
usTurningCost = CalculateTurningCost(pSoldier, pSoldier->usAttackingWeapon, fAddingTurningCost);
|
usTurningCost = CalculateTurningCost(pSoldier, pSoldier->usAttackingWeapon, fAddingTurningCost);
|
||||||
usRaiseGunCost = CalculateRaiseGunCost(pSoldier, fAddingRaiseGunCost, sTarget, 0);
|
usRaiseGunCost = CalculateRaiseGunCost(pSoldier, fAddingRaiseGunCost, sTarget, 0);
|
||||||
ubRawAPCost = MinAPsToShootOrStab(pSoldier, sTarget, 0, FALSE, 2);
|
sRawAPCost = MinAPsToShootOrStab(pSoldier, sTarget, 0, FALSE, 2);
|
||||||
ubMinAPcost = ubRawAPCost + usTurningCost + sStanceAPcost + usRaiseGunCost;
|
sMinAPcost = sRawAPCost + usTurningCost + sStanceAPcost + usRaiseGunCost;
|
||||||
|
|
||||||
if (pSoldier->bActionPoints - ubMinAPcost >= 0)
|
if (pSoldier->bActionPoints - sMinAPcost >= 0)
|
||||||
{
|
{
|
||||||
ubMaxPossibleAimTime = CalcAimingLevelsAvailableWithAP(pSoldier, sTarget, pSoldier->bActionPoints - ubMinAPcost);
|
sMaxPossibleAimTime = CalcAimingLevelsAvailableWithAP(pSoldier, sTarget, pSoldier->bActionPoints - sMinAPcost);
|
||||||
|
|
||||||
// sevenfm: check CTGT and friendly fire chance for every stance
|
// sevenfm: check CTGT and friendly fire chance for every stance
|
||||||
gUnderFire.Clear();
|
gUnderFire.Clear();
|
||||||
@@ -609,20 +622,21 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
|
|||||||
// sevenfm: only use this stance if we can hit target and cannot hit friends
|
// sevenfm: only use this stance if we can hit target and cannot hit friends
|
||||||
if (ubChanceToGetThrough > 0 && ubFriendlyFireChance <= MIN_CHANCE_TO_ACCIDENTALLY_HIT_SOMEONE)
|
if (ubChanceToGetThrough > 0 && ubFriendlyFireChance <= MIN_CHANCE_TO_ACCIDENTALLY_HIT_SOMEONE)
|
||||||
{
|
{
|
||||||
for (ubAimTime = 0; ubAimTime <= ubMaxPossibleAimTime; ubAimTime++)
|
for (sAimTime = 0; sAimTime <= sMaxPossibleAimTime; sAimTime++)
|
||||||
{
|
{
|
||||||
ubChanceToHit = AICalcChanceToHitGun(pSoldier, sTarget, ubAimTime, AIM_SHOT_TORSO, bLevel, PRONE);
|
sChanceToHit = AICalcChanceToHitGun(pSoldier, sTarget, sAimTime, AIM_SHOT_TORSO, bLevel, PRONE);
|
||||||
iHitRate = ubChanceToHit * (pSoldier->bActionPoints - (ubMinAPcost - ubRawAPCost)) / (ubRawAPCost + ubAimTime * APBPConstants[AP_CLICK_AIM]);
|
sAimAPCost = CalcAPCostForAiming(pSoldier, sTarget, (INT8)sAimTime);
|
||||||
|
iHitRate = sChanceToHit * (pSoldier->bActionPoints - (sMinAPcost - sRawAPCost)) / (sRawAPCost + sAimAPCost);
|
||||||
// sevenfm: take into account CTGT for every stance
|
// sevenfm: take into account CTGT for every stance
|
||||||
if (iHitRate * ubChanceToGetThrough > iBestHitRate * ubBestChanceToGetThrough)
|
if (iHitRate * ubChanceToGetThrough > iBestHitRate * ubBestChanceToGetThrough)
|
||||||
{
|
{
|
||||||
iBestHitRate = iHitRate;
|
iBestHitRate = iHitRate;
|
||||||
ubBestAimTime = ubAimTime;
|
sBestAimTime = sAimTime;
|
||||||
ubBestChanceToHit = ubChanceToHit;
|
sBestChanceToHit = sChanceToHit;
|
||||||
ubBestChanceToGetThrough = ubChanceToGetThrough;
|
ubBestChanceToGetThrough = ubChanceToGetThrough;
|
||||||
ubBestFriendlyFireChance = ubFriendlyFireChance;
|
ubBestFriendlyFireChance = ubFriendlyFireChance;
|
||||||
bScopeMode = pSoldier->bScopeMode;
|
bScopeMode = pSoldier->bScopeMode;
|
||||||
sBestAPcost = ubMinAPcost;
|
sBestAPcost = sMinAPcost;
|
||||||
ubBestStance = ubStance;
|
ubBestStance = ubStance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -639,7 +653,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
|
|||||||
continue; // next opponent
|
continue; // next opponent
|
||||||
|
|
||||||
// calculate chance to REALLY hit: shoot accurately AND get past cover
|
// calculate chance to REALLY hit: shoot accurately AND get past cover
|
||||||
ubChanceToReallyHit = (UINT8)ceil((ubBestChanceToHit * ubBestChanceToGetThrough) / 100.0f);
|
ubChanceToReallyHit = (UINT8)ceil((sBestChanceToHit * ubBestChanceToGetThrough) / 100.0f);
|
||||||
|
|
||||||
// if we can't REALLY hit at all
|
// if we can't REALLY hit at all
|
||||||
if (ubChanceToReallyHit == 0)
|
if (ubChanceToReallyHit == 0)
|
||||||
@@ -654,7 +668,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
|
|||||||
iThreatValue = CalcManThreatValue(pOpponent, pSoldier->sGridNo, TRUE, pSoldier);
|
iThreatValue = CalcManThreatValue(pOpponent, pSoldier->sGridNo, TRUE, pSoldier);
|
||||||
|
|
||||||
// estimate the damage this shot would do to this opponent
|
// estimate the damage this shot would do to this opponent
|
||||||
iEstDamage = EstimateShotDamage(pSoldier, pOpponent, ubBestChanceToHit);
|
iEstDamage = EstimateShotDamage(pSoldier, pOpponent, sBestChanceToHit);
|
||||||
//NumMessage("SHOT EstDamage = ",iEstDamage);
|
//NumMessage("SHOT EstDamage = ",iEstDamage);
|
||||||
|
|
||||||
// calculate the combined "attack value" for this opponent
|
// calculate the combined "attack value" for this opponent
|
||||||
@@ -752,7 +766,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
|
|||||||
// OOOF! That was a lot of work! But we've got a new best target!
|
// OOOF! That was a lot of work! But we've got a new best target!
|
||||||
pBestShot->ubPossible = TRUE;
|
pBestShot->ubPossible = TRUE;
|
||||||
pBestShot->ubOpponent = pOpponent->ubID;
|
pBestShot->ubOpponent = pOpponent->ubID;
|
||||||
pBestShot->ubAimTime = ubBestAimTime;
|
pBestShot->ubAimTime = sBestAimTime;
|
||||||
pBestShot->ubChanceToReallyHit = ubChanceToReallyHit;
|
pBestShot->ubChanceToReallyHit = ubChanceToReallyHit;
|
||||||
pBestShot->sTarget = sTarget;
|
pBestShot->sTarget = sTarget;
|
||||||
pBestShot->bTargetLevel = bLevel;
|
pBestShot->bTargetLevel = bLevel;
|
||||||
@@ -903,7 +917,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
usGrenade = pSoldier->inv[bPayloadPocket].usItem;
|
usGrenade = pSoldier->inv[bPayloadPocket].usItem;
|
||||||
ubSafetyMargin = (UINT8)(1 + max(Explosive[Item[usGrenade].ubClassIndex].ubRadius, min(TACTICAL_RANGE / 2, Explosive[Item[usGrenade].ubClassIndex].ubFragRange / CELL_X_SIZE)));
|
ubSafetyMargin = (UINT8)(1 + max(Explosive[Item[usGrenade].ubClassIndex].ubRadius, min((UINT8)TACTICAL_RANGE / 2, Explosive[Item[usGrenade].ubClassIndex].ubFragRange / CELL_X_SIZE)));
|
||||||
fMortar = TRUE;
|
fMortar = TRUE;
|
||||||
}
|
}
|
||||||
// if he's got a GL in his hand, make sure he has some type of GRENADE avail.
|
// if he's got a GL in his hand, make sure he has some type of GRENADE avail.
|
||||||
@@ -926,12 +940,12 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
|
|||||||
if(pAttachment->exists())
|
if(pAttachment->exists())
|
||||||
{
|
{
|
||||||
usGrenade = pAttachment->usItem;
|
usGrenade = pAttachment->usItem;
|
||||||
ubSafetyMargin = (UINT8)(1 + max(Explosive[Item[usGrenade].ubClassIndex].ubRadius, min(TACTICAL_RANGE / 2, Explosive[Item[usGrenade].ubClassIndex].ubFragRange / CELL_X_SIZE)));
|
ubSafetyMargin = (UINT8)(1 + max(Explosive[Item[usGrenade].ubClassIndex].ubRadius, min((UINT8)TACTICAL_RANGE / 2, Explosive[Item[usGrenade].ubClassIndex].ubFragRange / CELL_X_SIZE)));
|
||||||
}
|
}
|
||||||
else if((bPayloadPocket=FindAmmoToReload(pSoldier, bPayloadPocket, NO_SLOT)) != NO_SLOT)
|
else if((bPayloadPocket=FindAmmoToReload(pSoldier, bPayloadPocket, NO_SLOT)) != NO_SLOT)
|
||||||
{
|
{
|
||||||
usGrenade = pSoldier->inv[bPayloadPocket].usItem;
|
usGrenade = pSoldier->inv[bPayloadPocket].usItem;
|
||||||
ubSafetyMargin = (UINT8)(1 + max(Explosive[Item[usGrenade].ubClassIndex].ubRadius, min(TACTICAL_RANGE / 2, Explosive[Item[usGrenade].ubClassIndex].ubFragRange / CELL_X_SIZE)));
|
ubSafetyMargin = (UINT8)(1 + max(Explosive[Item[usGrenade].ubClassIndex].ubRadius, min((UINT8)TACTICAL_RANGE / 2, Explosive[Item[usGrenade].ubClassIndex].ubFragRange / CELL_X_SIZE)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -954,7 +968,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
|
|||||||
if (Item[usInHand].usBuddyItem && Item[Item[usInHand].usBuddyItem].usItemClass & IC_EXPLOSV)
|
if (Item[usInHand].usBuddyItem && Item[Item[usInHand].usBuddyItem].usItemClass & IC_EXPLOSV)
|
||||||
{
|
{
|
||||||
usGrenade = Item[usInHand].usBuddyItem;
|
usGrenade = Item[usInHand].usBuddyItem;
|
||||||
ubSafetyMargin = (UINT8)(1 + max(Explosive[Item[usGrenade].ubClassIndex].ubRadius, min(TACTICAL_RANGE / 2, Explosive[Item[usGrenade].ubClassIndex].ubFragRange / CELL_X_SIZE)));
|
ubSafetyMargin = (UINT8)(1 + max(Explosive[Item[usGrenade].ubClassIndex].ubRadius, min((UINT8)TACTICAL_RANGE / 2, Explosive[Item[usGrenade].ubClassIndex].ubFragRange / CELL_X_SIZE)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -975,7 +989,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
|
|||||||
return; // no ammo, can't fire
|
return; // no ammo, can't fire
|
||||||
}
|
}
|
||||||
usGrenade = pSoldier->inv[bPayloadPocket].usItem;
|
usGrenade = pSoldier->inv[bPayloadPocket].usItem;
|
||||||
ubSafetyMargin = (UINT8)(1 + max(Explosive[Item[usGrenade].ubClassIndex].ubRadius, min(TACTICAL_RANGE / 2, Explosive[Item[usGrenade].ubClassIndex].ubFragRange / CELL_X_SIZE)));
|
ubSafetyMargin = (UINT8)(1 + max(Explosive[Item[usGrenade].ubClassIndex].ubRadius, min((UINT8)TACTICAL_RANGE / 2, Explosive[Item[usGrenade].ubClassIndex].ubFragRange / CELL_X_SIZE)));
|
||||||
}
|
}
|
||||||
fRocketLauncher = TRUE;
|
fRocketLauncher = TRUE;
|
||||||
}
|
}
|
||||||
@@ -992,7 +1006,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
|
|||||||
return; // no ammo, can't fire
|
return; // no ammo, can't fire
|
||||||
}
|
}
|
||||||
usGrenade = pSoldier->inv[bPayloadPocket].usItem;
|
usGrenade = pSoldier->inv[bPayloadPocket].usItem;
|
||||||
ubSafetyMargin = (UINT8)(1 + max(Explosive[Item[pSoldier->inv[bPayloadPocket].usItem].ubClassIndex].ubRadius, min(TACTICAL_RANGE / 2, Explosive[Item[pSoldier->inv[bPayloadPocket].usItem].ubClassIndex].ubFragRange / CELL_X_SIZE)));
|
ubSafetyMargin = (UINT8)(1 + max(Explosive[Item[pSoldier->inv[bPayloadPocket].usItem].ubClassIndex].ubRadius, min((UINT8)TACTICAL_RANGE / 2, Explosive[Item[pSoldier->inv[bPayloadPocket].usItem].ubClassIndex].ubFragRange / CELL_X_SIZE)));
|
||||||
fCannon = TRUE;
|
fCannon = TRUE;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1002,7 +1016,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
|
|||||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"calcbestthrow: buddy's got a grenade");
|
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"calcbestthrow: buddy's got a grenade");
|
||||||
bPayloadPocket = HANDPOS;
|
bPayloadPocket = HANDPOS;
|
||||||
usGrenade = pSoldier->inv[bPayloadPocket].usItem;
|
usGrenade = pSoldier->inv[bPayloadPocket].usItem;
|
||||||
ubSafetyMargin = (UINT8)(1 + max(Explosive[Item[usGrenade].ubClassIndex].ubRadius, min(TACTICAL_RANGE / 4, Explosive[Item[usGrenade].ubClassIndex].ubFragRange / CELL_X_SIZE)));
|
ubSafetyMargin = (UINT8)(1 + max(Explosive[Item[usGrenade].ubClassIndex].ubRadius, min((UINT8)TACTICAL_RANGE / 4, Explosive[Item[usGrenade].ubClassIndex].ubFragRange / CELL_X_SIZE)));
|
||||||
|
|
||||||
if ( Item[usGrenade].flare )
|
if ( Item[usGrenade].flare )
|
||||||
{
|
{
|
||||||
@@ -3878,13 +3892,13 @@ void CheckTossFriendSmoke(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
|
|||||||
bFriendLevel = pFriend->pathing.bLevel;
|
bFriendLevel = pFriend->pathing.bLevel;
|
||||||
sClosestOpponent = ClosestKnownOpponent(pFriend, NULL, NULL);
|
sClosestOpponent = ClosestKnownOpponent(pFriend, NULL, NULL);
|
||||||
|
|
||||||
if (PythSpacesAway(sSpot, sFriendSpot) <= DAY_VISION_RANGE &&
|
if (PythSpacesAway(sSpot, sFriendSpot) <= (INT16)DAY_VISION_RANGE &&
|
||||||
PythSpacesAway(sSpot, sFriendSpot) > DAY_VISION_RANGE / 4 &&
|
PythSpacesAway(sSpot, sFriendSpot) > (INT16)DAY_VISION_RANGE / 4 &&
|
||||||
!InSmoke(sFriendSpot, bFriendLevel) &&
|
!InSmoke(sFriendSpot, bFriendLevel) &&
|
||||||
(!NightLight() || InLightAtNight(sFriendSpot, bFriendLevel)) &&
|
(!NightLight() || InLightAtNight(sFriendSpot, bFriendLevel)) &&
|
||||||
!Water(sFriendSpot, bFriendLevel) &&
|
!Water(sFriendSpot, bFriendLevel) &&
|
||||||
!TileIsOutOfBounds(sClosestOpponent) &&
|
!TileIsOutOfBounds(sClosestOpponent) &&
|
||||||
PythSpacesAway(sFriendSpot, sClosestOpponent) > DAY_VISION_RANGE / 4 &&
|
PythSpacesAway(sFriendSpot, sClosestOpponent) > (INT16)DAY_VISION_RANGE / 4 &&
|
||||||
!ProneSightCoverAtSpot(pFriend, sFriendSpot, TRUE) &&
|
!ProneSightCoverAtSpot(pFriend, sFriendSpot, TRUE) &&
|
||||||
//!SightCoverAtSpot(pFriend, sFriendSpot, FALSE) &&
|
//!SightCoverAtSpot(pFriend, sFriendSpot, FALSE) &&
|
||||||
//!AnyCoverAtSpot(pFriend, sFriendSpot) &&
|
//!AnyCoverAtSpot(pFriend, sFriendSpot) &&
|
||||||
|
|||||||
@@ -3033,7 +3033,8 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
|
|||||||
ARMED_VEHICLE(pSoldier) || // tanks don't need cover
|
ARMED_VEHICLE(pSoldier) || // tanks don't need cover
|
||||||
pSoldier->aiData.bUnderFire && (pSoldier->ubPreviousAttackerID == BestShot.ubOpponent || pSoldier->ubNextToPreviousAttackerID == BestShot.ubOpponent || MercPtrs[BestShot.ubOpponent]->sLastTarget == pSoldier->sGridNo) || // return fire
|
pSoldier->aiData.bUnderFire && (pSoldier->ubPreviousAttackerID == BestShot.ubOpponent || pSoldier->ubNextToPreviousAttackerID == BestShot.ubOpponent || MercPtrs[BestShot.ubOpponent]->sLastTarget == pSoldier->sGridNo) || // return fire
|
||||||
Chance((BestShot.ubChanceToReallyHit + 100) / 2) || // 50% chance to fire without cover
|
Chance((BestShot.ubChanceToReallyHit + 100) / 2) || // 50% chance to fire without cover
|
||||||
SoldierToSoldierLineOfSightTest(pSoldier, MercPtrs[BestShot.ubOpponent], TRUE, CALC_FROM_ALL_DIRS)) && // can see target after turning
|
//SoldierToSoldierLineOfSightTest(pSoldier, MercPtrs[BestShot.ubOpponent], TRUE, CALC_FROM_ALL_DIRS)) && // can see target after turning
|
||||||
|
LOS_Raised(pSoldier, MercPtrs[BestShot.ubOpponent], CALC_FROM_ALL_DIRS)) && // can see target after turning
|
||||||
// reduce chance to shoot if target is beyond weapon range
|
// reduce chance to shoot if target is beyond weapon range
|
||||||
(AICheckIsMachinegunner(pSoldier) ||
|
(AICheckIsMachinegunner(pSoldier) ||
|
||||||
ARMED_VEHICLE(pSoldier) ||
|
ARMED_VEHICLE(pSoldier) ||
|
||||||
|
|||||||
Reference in New Issue
Block a user