mirror of
https://github.com/1dot13/source.git
synced 2026-09-02 14:36:06 +02:00
AI and tactics improvements (by Sevenfm):
New options: AI_YELLOW_FLANKING - yellow flanking is disabled by default IMPROVED_TACTICAL_UI - use name color to show soldier's status (disguised, drunk) Removed obsolete options: SHOW_COVER_INDICATOR SHOW_ENEMY_RANK_ICON SHOW_ENEMY_AWARENESS Fixes and improvements: - collapsed enemies should not taunt - if soldier is unconscious, he can't see anything or anybody - ClosestReachableDisturbance - performance improvement - allow InternalGoAsFarAsPossibleTowards to jump over fences git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8226 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+21
-15
@@ -948,6 +948,7 @@ INT32 ClosestReachableDisturbance(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK,
|
||||
INT8 *pbPersOL,*pbPublOL;
|
||||
INT32 sClimbGridNo;
|
||||
SOLDIERTYPE * pOpp;
|
||||
INT32 sDistToEnemy, sDistToClosestEnemy = 10000;
|
||||
|
||||
// sevenfm: safety check
|
||||
if ( pfChangeLevel )
|
||||
@@ -1034,23 +1035,28 @@ INT32 ClosestReachableDisturbance(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK,
|
||||
continue;
|
||||
}
|
||||
|
||||
iPathCost = EstimatePathCostToLocation( pSoldier, sGridNo, bLevel, FALSE, &fClimbingNecessary, &sClimbGridNo );
|
||||
|
||||
// if we can get there and it's first reachable enemy or closer than other known enemies
|
||||
if( iPathCost != 0 &&
|
||||
(TileIsOutOfBounds(sClosestDisturbance) || iPathCost < iShortestPath) )
|
||||
// sevenfm: if we found reachable enemy, check other enemies only if they are closer
|
||||
sDistToEnemy = PythSpacesAway( pSoldier->sGridNo, sGridNo );
|
||||
if (sDistToEnemy < sDistToClosestEnemy || TileIsOutOfBounds(sClosestDisturbance) )
|
||||
{
|
||||
if (fClimbingNecessary)
|
||||
{
|
||||
sClosestDisturbance = sClimbGridNo;
|
||||
}
|
||||
else
|
||||
{
|
||||
sClosestDisturbance = sGridNo;
|
||||
}
|
||||
iPathCost = EstimatePathCostToLocation( pSoldier, sGridNo, bLevel, FALSE, &fClimbingNecessary, &sClimbGridNo );
|
||||
|
||||
iShortestPath = iPathCost;
|
||||
fClosestClimbingNecessary = fClimbingNecessary;
|
||||
// if we can get there and it's first reachable enemy or closer than other known enemies
|
||||
if (iPathCost != 0 && (TileIsOutOfBounds(sClosestDisturbance) || iPathCost < iShortestPath))
|
||||
{
|
||||
if (fClimbingNecessary)
|
||||
{
|
||||
sClosestDisturbance = sClimbGridNo;
|
||||
}
|
||||
else
|
||||
{
|
||||
sClosestDisturbance = sGridNo;
|
||||
}
|
||||
|
||||
sDistToClosestEnemy = sDistToEnemy;
|
||||
iShortestPath = iPathCost;
|
||||
fClosestClimbingNecessary = fClimbingNecessary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2097,12 +2097,13 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
||||
}
|
||||
|
||||
// possibly start YELLOW flanking
|
||||
if ( ( pSoldier->aiData.bAttitude == CUNNINGAID || pSoldier->aiData.bAttitude == CUNNINGSOLO ) &&
|
||||
if( gGameExternalOptions.fAIYellowFlanking &&
|
||||
( pSoldier->aiData.bAttitude == CUNNINGAID || pSoldier->aiData.bAttitude == CUNNINGSOLO ) &&
|
||||
pSoldier->bTeam == ENEMY_TEAM &&
|
||||
( CountFriendsInDirection( pSoldier, sNoiseGridNo ) > 0 || NightTime() ) &&
|
||||
( pSoldier->aiData.bOrders == SEEKENEMY ||
|
||||
pSoldier->aiData.bOrders == FARPATROL ||
|
||||
pSoldier->aiData.bOrders == CLOSEPATROL && NightTime() ) )
|
||||
pSoldier->aiData.bOrders == CLOSEPATROL && NightTime() ))
|
||||
{
|
||||
INT8 action = AI_ACTION_SEEK_NOISE;
|
||||
INT16 dist = PythSpacesAway ( pSoldier->sGridNo, sNoiseGridNo );
|
||||
@@ -9555,12 +9556,13 @@ INT8 ArmedVehicleDecideActionYellow( SOLDIERTYPE *pSoldier )
|
||||
#endif
|
||||
|
||||
// possibly start YELLOW flanking
|
||||
if ( (pSoldier->aiData.bAttitude == CUNNINGAID || pSoldier->aiData.bAttitude == CUNNINGSOLO) &&
|
||||
pSoldier->bTeam == ENEMY_TEAM &&
|
||||
(CountFriendsInDirection( pSoldier, sNoiseGridNo ) > 0 || NightTime( )) &&
|
||||
(pSoldier->aiData.bOrders == SEEKENEMY ||
|
||||
pSoldier->aiData.bOrders == FARPATROL ||
|
||||
pSoldier->aiData.bOrders == CLOSEPATROL && NightTime( )) )
|
||||
if( gGameExternalOptions.fAIYellowFlanking &&
|
||||
(pSoldier->aiData.bAttitude == CUNNINGAID || pSoldier->aiData.bAttitude == CUNNINGSOLO) &&
|
||||
pSoldier->bTeam == ENEMY_TEAM &&
|
||||
(CountFriendsInDirection( pSoldier, sNoiseGridNo ) > 0 || NightTime( )) &&
|
||||
(pSoldier->aiData.bOrders == SEEKENEMY ||
|
||||
pSoldier->aiData.bOrders == FARPATROL ||
|
||||
pSoldier->aiData.bOrders == CLOSEPATROL && NightTime( )) )
|
||||
{
|
||||
INT8 action = AI_ACTION_SEEK_NOISE;
|
||||
INT16 dist = PythSpacesAway( pSoldier->sGridNo, sNoiseGridNo );
|
||||
|
||||
+15
-54
@@ -517,27 +517,8 @@ INT32 InternalGoAsFarAsPossibleTowards(SOLDIERTYPE *pSoldier, INT32 sDesGrid, IN
|
||||
|
||||
fPathFlags = 0;
|
||||
if ( CREATURE_OR_BLOODCAT( pSoldier ) )
|
||||
{ /*
|
||||
if ( PythSpacesAway( pSoldier->sGridNo, sDesGrid ) <= PATH_CLOSE_RADIUS )
|
||||
{
|
||||
// then do a limited range path search and see if we can get there
|
||||
gubNPCDistLimit = 10;
|
||||
if ( !LegalNPCDestination( pSoldier, sDesGrid, ENSURE_PATH, NOWATER, fPathFlags) )
|
||||
{
|
||||
gubNPCDistLimit = 0;
|
||||
return( NOWHERE );
|
||||
}
|
||||
else
|
||||
{
|
||||
// allow attempt to path without 'good enough' flag on
|
||||
gubNPCDistLimit = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*/
|
||||
{
|
||||
fPathFlags = PATH_CLOSE_GOOD_ENOUGH;
|
||||
//}
|
||||
}
|
||||
|
||||
// first step: try to find an OK destination at or near the desired gridno
|
||||
@@ -634,13 +615,15 @@ INT32 InternalGoAsFarAsPossibleTowards(SOLDIERTYPE *pSoldier, INT32 sDesGrid, IN
|
||||
// we'll only go as far along the plotted route as is within our
|
||||
// permitted roaming range, and we'll stop as soon as we're down to <= 5 APs
|
||||
|
||||
sTempDest = pSoldier->sGridNo;
|
||||
|
||||
for (sLoop = 0; sLoop < (pSoldier->pathing.usPathDataSize - pSoldier->pathing.usPathIndex); sLoop++)
|
||||
{
|
||||
// what is the next gridno in the path?
|
||||
|
||||
//sTempDest = NewGridNo( sGoToGrid,DirectionInc( (INT16) (pSoldier->pathing.usPathingData[sLoop] + 1) ) );
|
||||
sTempDest = NewGridNo( sGoToGrid,DirectionInc( (UINT8) (pSoldier->pathing.usPathingData[sLoop]) ) );
|
||||
//NumMessage("sTempDest = ",sTempDest);
|
||||
//sTempDest = NewGridNo( sGoToGrid,DirectionInc( (UINT8) (pSoldier->pathing.usPathingData[sLoop]) ) );
|
||||
sTempDest = NewGridNo( sTempDest,DirectionInc( (UINT8) (pSoldier->pathing.usPathingData[sLoop]) ) );
|
||||
|
||||
// this should NEVER be out of bounds
|
||||
if (sTempDest == sGoToGrid)
|
||||
@@ -679,13 +662,6 @@ INT32 InternalGoAsFarAsPossibleTowards(SOLDIERTYPE *pSoldier, INT32 sDesGrid, IN
|
||||
break; // quit here, sGoToGrid is where we are going
|
||||
}
|
||||
|
||||
// if this gridno is NOT a legal NPC destination
|
||||
// DONT'T test path again - that would replace the traced path! - Ian
|
||||
// NOTE: It's OK to go *THROUGH* water to try and get to the destination!
|
||||
if (!LegalNPCDestination(pSoldier,sTempDest,IGNORE_PATH,WATEROK,0))
|
||||
break; // quit here, sGoToGrid is where we are going
|
||||
|
||||
|
||||
// CAN'T CALL PathCost() HERE! IT CALLS findBestPath() and overwrites
|
||||
// pathRouteToGo !!! Gotta calculate the cost ourselves - Ian
|
||||
//
|
||||
@@ -696,31 +672,6 @@ INT32 InternalGoAsFarAsPossibleTowards(SOLDIERTYPE *pSoldier, INT32 sDesGrid, IN
|
||||
// if we're just starting the "costing" process (first gridno)
|
||||
if (sLoop == 0)
|
||||
{
|
||||
/*
|
||||
// first, add any additional costs - such as intermediate animations, etc.
|
||||
switch(pSoldier->anitype[pSoldier->anim])
|
||||
{
|
||||
// in theory, no NPC should ever be in one of these animations as
|
||||
// things stand (they don't medic anyone), but leave it for robustness
|
||||
case START_AID :
|
||||
case GIVING_AID : sAnimCost = APBPConstants[AP_STOP_FIRST_AID];
|
||||
break;
|
||||
|
||||
case TWISTOMACH :
|
||||
case COLLAPSED : sAnimCost = APBPConstants[AP_GET_UP];
|
||||
break;
|
||||
|
||||
case TWISTBACK :
|
||||
case UNCONSCIOUS : sAnimCost = (APBPConstants[AP_ROLL_OVER] + APBPConstants[AP_GET_UP]);
|
||||
break;
|
||||
|
||||
default : sAnimCost = 0;
|
||||
}
|
||||
|
||||
// this is our first cost
|
||||
sAPCost += sAnimCost;
|
||||
*/
|
||||
|
||||
if (pSoldier->usUIMovementMode == RUNNING)
|
||||
{
|
||||
sAPCost += GetAPsStartRun( pSoldier ); // changed by SANDRO
|
||||
@@ -733,6 +684,16 @@ INT32 InternalGoAsFarAsPossibleTowards(SOLDIERTYPE *pSoldier, INT32 sDesGrid, IN
|
||||
bAPsLeft = pSoldier->bActionPoints - sAPCost;
|
||||
}
|
||||
|
||||
// if this gridno is NOT a legal NPC destination
|
||||
// DONT'T test path again - that would replace the traced path! - Ian
|
||||
// NOTE: It's OK to go *THROUGH* water to try and get to the destination!
|
||||
// sevenfm: jump over fence code - if current gridno is not legal destination, check next gridno
|
||||
if (!LegalNPCDestination(pSoldier,sTempDest,IGNORE_PATH,WATEROK,0))
|
||||
{
|
||||
// break;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if after this, we have <= 5 APs remaining, that's far enough, break out
|
||||
// (the idea is to preserve APs so we can crouch or react if
|
||||
// necessary, and benefit from the carry-over next turn if not needed)
|
||||
|
||||
Reference in New Issue
Block a user