mirror of
https://github.com/1dot13/source.git
synced 2026-08-05 14:00:23 +02:00
AI improvements (by Sevenfm):
Bugfixes: - Fix: Watched Locations system (never worked in 1.13) - Fix: LineOfSight test with NO_DISTANCE_LIMIT (stopped on trees previously) AI/tactical improvements: - EstimateThrowDamage additionally calculates damage from fragments (important for AI to use frag grenades with low main damage and many fragments) - EstimateThrowDamage correctly adds IndoorModifier - Additional checks for RED suppression (check that the soldier will not shoot his friends, check that he has extra clip to reload weapon, check that target is not cowering, don't suppress when flanking) - ClosestReachableDisturbance will use general noise only if cannot find any enemy - Allow RED seeking in prone stance if we haven't seen enemy for several turns Flanking improvements: - allow YELLOW flanking for CLOSEPATROL at night - better YELLOW/RED flanking start/stop conditions - better RED AI behavior when finished flanking (try to reach flanking spot) - allow RED flanking for CLOSEPATROL soldiers when at night, overcrowded or no other flanking soldiers yet Optional AI improvements: AI_EXTRA_SUPPRESSION - AI will use suppression fire more often in RED state (set minimum AI CTH to 1) AI_NEW_MORALE - Better dynamic morale calculation depending on tactical situation. - Additional min/max limits for AI morale - Disabled HOPELESS morale for soldiers without guns (they can pick up weapon or attack with hands sometimes) AI_BETTER_COVER - Additional checks for line of sight, fresh corpses and overcrowded locations AI_EXTRA_FLANKING - Allow flanking for BRAVEAID/BRAVESOLO git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8006 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
#include "Buildings.h"
|
||||
#include "GameSettings.h"
|
||||
#include "Soldier Profile.h"
|
||||
#include "rotting corpses.h" // sevenfm
|
||||
#endif
|
||||
|
||||
|
||||
@@ -567,6 +568,11 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB
|
||||
UINT8 ubLightPercentDifference;
|
||||
BOOLEAN fNight;
|
||||
|
||||
// sevenfm
|
||||
UINT8 ubNearbyFriends;
|
||||
BOOLEAN fProneCover;
|
||||
UINT8 ubDiff = SoldierDifficultyLevel( pSoldier );
|
||||
|
||||
// There's no cover when boxing!
|
||||
if (gTacticalStatus.bBoxingState == BOXING)
|
||||
{
|
||||
@@ -628,7 +634,6 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB
|
||||
case AGGRESSIVE: iSearchRange -= 2; break;
|
||||
}*/
|
||||
|
||||
|
||||
// maximum search range is 1 tile / 8 pts of wisdom
|
||||
if (iSearchRange > (pSoldier->stats.bWisdom / 8))
|
||||
{
|
||||
@@ -787,6 +792,9 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB
|
||||
iCurrentCoverValue = 0;
|
||||
iCurrentScale = 0;
|
||||
|
||||
// sevenfm: sight cover
|
||||
fProneCover = TRUE;
|
||||
|
||||
// for every opponent that threatens, consider this spot's cover vs. him
|
||||
for (uiLoop = 0; uiLoop < uiThreatCnt; uiLoop++)
|
||||
{
|
||||
@@ -796,6 +804,14 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB
|
||||
// add this opponent's cover value to our current total cover value
|
||||
iCurrentCoverValue += CalcCoverValue(pSoldier,pSoldier->sGridNo,iMyThreatValue,pSoldier->bActionPoints,uiLoop,Threat[uiLoop].iOrigRange,morale,&iCurrentScale);
|
||||
}
|
||||
// sevenfm: sight test
|
||||
if( gGameExternalOptions.fAIBetterCover )
|
||||
{
|
||||
if ( SoldierToVirtualSoldierLineOfSightTest( Threat[uiLoop].pOpponent, pSoldier->sGridNo, pSoldier->pathing.bLevel, ANIM_PRONE, TRUE, -1 ) != 0 )
|
||||
{
|
||||
fProneCover = FALSE;
|
||||
}
|
||||
}
|
||||
//sprintf(tempstr,"iCurrentCoverValue after opponent %d is now %d",iLoop,iCurrentCoverValue);
|
||||
//PopMessage(tempstr);
|
||||
}
|
||||
@@ -812,6 +828,28 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB
|
||||
iCurrentCoverValue += (iCurrentCoverValue / 10) * NumberOfTeamMatesAdjacent( pSoldier, pSoldier->sGridNo );
|
||||
}
|
||||
|
||||
if( gGameExternalOptions.fAIBetterCover )
|
||||
{
|
||||
// sevenfm: when defending (range change <= 3), prefer locations with sight cover
|
||||
if( RangeChangeDesire(pSoldier) < 4 )
|
||||
{
|
||||
if( fProneCover )
|
||||
{
|
||||
iCurrentCoverValue += abs(iCurrentCoverValue) / __max(2, 2*RangeChangeDesire(pSoldier));
|
||||
}
|
||||
}
|
||||
|
||||
// sevenfm: check for nearby friends, add bonus/penalty
|
||||
ubNearbyFriends = __min(5, CountNearbyFriendlies( pSoldier, pSoldier->sGridNo, 5 ));
|
||||
iCurrentCoverValue -= ubNearbyFriends * abs(iCurrentCoverValue) / (10-ubDiff);
|
||||
|
||||
// sevenfm: penalize locations with fresh corpses
|
||||
if(GetNearestRottingCorpseAIWarning( pSoldier->sGridNo ) > 0)
|
||||
{
|
||||
iCurrentCoverValue -= abs(iCurrentCoverValue) / (8-ubDiff);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUGCOVER
|
||||
// AINumMessage("Search Range = ",iSearchRange);
|
||||
#endif
|
||||
@@ -976,6 +1014,9 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB
|
||||
iCoverValue = 0;
|
||||
iCoverScale = 0;
|
||||
|
||||
// sevenfm: check sight cover
|
||||
fProneCover = TRUE;
|
||||
|
||||
// for every opponent that threatens, consider this spot's cover vs. him
|
||||
for (uiLoop = 0; uiLoop < uiThreatCnt; uiLoop++)
|
||||
{
|
||||
@@ -989,6 +1030,15 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB
|
||||
uiLoop,iThreatRange,morale,&iCoverScale);
|
||||
}
|
||||
|
||||
// sevenfm: sight test
|
||||
if( gGameExternalOptions.fAIBetterCover )
|
||||
{
|
||||
if ( SoldierToVirtualSoldierLineOfSightTest( Threat[uiLoop].pOpponent, sGridNo, pSoldier->pathing.bLevel, ANIM_PRONE, TRUE, -1 ) != 0 )
|
||||
{
|
||||
fProneCover = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//sprintf(tempstr,"iCoverValue after opponent %d is now %d",iLoop,iCoverValue);
|
||||
//PopMessage(tempstr);
|
||||
}
|
||||
@@ -1005,6 +1055,26 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB
|
||||
iCoverValue += (iCoverValue / 10) * NumberOfTeamMatesAdjacent( pSoldier, sGridNo );
|
||||
}
|
||||
|
||||
if( gGameExternalOptions.fAIBetterCover )
|
||||
{
|
||||
// sevenfm: when defending (range change <= 3), prefer locations with sight cover
|
||||
if( RangeChangeDesire(pSoldier) < 4 )
|
||||
{
|
||||
if( fProneCover )
|
||||
iCoverValue += abs(iCoverValue) / __max(2, 2*RangeChangeDesire(pSoldier));
|
||||
}
|
||||
|
||||
// sevenfm: check for nearby friends in 10 radius, add bonus/penalty 10%
|
||||
ubNearbyFriends = __min(5, CountNearbyFriendlies( pSoldier, sGridNo, 5 ));
|
||||
iCoverValue -= ubNearbyFriends * abs(iCoverValue) / (10-ubDiff);
|
||||
|
||||
// sevenfm: penalize locations with fresh corpses
|
||||
if(GetNearestRottingCorpseAIWarning( sGridNo ) > 0)
|
||||
{
|
||||
iCoverValue -= abs(iCoverValue) / (8-ubDiff);
|
||||
}
|
||||
}
|
||||
|
||||
if ( fNight && !( InARoom( sGridNo, NULL ) ) ) // ignore in buildings in case placed there
|
||||
{
|
||||
// reduce cover at nighttime based on how bright the light is at that location
|
||||
@@ -2545,11 +2615,16 @@ INT32 FindFlankingSpot(SOLDIERTYPE *pSoldier, INT32 sPos, INT8 bAction )
|
||||
continue;
|
||||
}
|
||||
|
||||
// sevenfm: skip water tiles
|
||||
if( Water( sGridNo ) )
|
||||
// sevenfm: allow water flanking only for CUNNINGSOLO soldiers
|
||||
if( Water( sGridNo ) && pSoldier->aiData.bAttitude != CUNNINGSOLO )
|
||||
{
|
||||
continue;
|
||||
//sTempDist = sTempDist/2;
|
||||
}
|
||||
|
||||
// sevenfm: penalize locations near fresh corpses
|
||||
if( GetNearestRottingCorpseAIWarning( sGridNo ) > 0 )
|
||||
{
|
||||
sTempDist = sTempDist / 2;
|
||||
}
|
||||
|
||||
// sevenfm: skip buildings if not in building already, because soldiers often run into buildings and stop flanking
|
||||
@@ -2571,6 +2646,11 @@ INT32 FindFlankingSpot(SOLDIERTYPE *pSoldier, INT32 sPos, INT8 bAction )
|
||||
{
|
||||
sTempDist = sTempDist / 2;
|
||||
}
|
||||
// sevenfm: try to flank closer to vision distance limit for faster flanking
|
||||
if( PythSpacesAway( sGridNo, sPos) > sDistanceVisible + 10 )
|
||||
{
|
||||
sTempDist = sTempDist / 2;
|
||||
}
|
||||
|
||||
if ( bAction == AI_ACTION_FLANK_LEFT )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user