mirror of
https://github.com/1dot13/source.git
synced 2026-08-19 14:20:30 +02:00
EstimatePathCostToLocation: safety checks.
Main Red AI: fixed decision weight calculation. Player mercs should avoid moving into gas/fire when in autobandage mode or under AI control. IsLocationSittable, IsLocationSittableExcludingPeople: return FALSE if location on roof does not exist. NWSS: play room effect for first shot only. AI inventory choosing: more variety for mortar shells, improved hand/GL grenade choosing code. Red AI: improved mortar use code: use next action to fire mortar after stepping back. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8920 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -1164,12 +1164,16 @@ void ChooseGrenadesForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bGrena
|
|||||||
// return here in any case
|
// return here in any case
|
||||||
if (itemMortar > 0 )
|
if (itemMortar > 0 )
|
||||||
{
|
{
|
||||||
usItem = PickARandomLaunchable ( itemMortar );
|
// sevenfm: more variety for mortar shells
|
||||||
if ( usItem > 0 )
|
for (int i = 0; i < bGrenades; i++)
|
||||||
{
|
{
|
||||||
CreateItems( usItem, (INT8) (80 + Random(21)), bGrenades, &gTempObject );
|
usItem = PickARandomLaunchable(itemMortar);
|
||||||
gTempObject.fFlags |= OBJECT_UNDROPPABLE;
|
if (usItem > 0)
|
||||||
PlaceObjectInSoldierCreateStruct( pp, &gTempObject );
|
{
|
||||||
|
CreateItems(usItem, (INT8)(80 + Random(21)), 1, &gTempObject);
|
||||||
|
gTempObject.fFlags |= OBJECT_UNDROPPABLE;
|
||||||
|
PlaceObjectInSoldierCreateStruct(pp, &gTempObject);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1214,9 +1218,7 @@ void ChooseGrenadesForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bGrena
|
|||||||
//do this for every 1-2 grenades so that we can get more variety
|
//do this for every 1-2 grenades so that we can get more variety
|
||||||
while ( bGrenades > 0 )
|
while ( bGrenades > 0 )
|
||||||
{
|
{
|
||||||
count = Random(3);
|
count = min(1 + Random(2), bGrenades);
|
||||||
if ( count > bGrenades )
|
|
||||||
count = bGrenades;
|
|
||||||
|
|
||||||
usItem = PickARandomLaunchable ( itemGrenadeLauncher );
|
usItem = PickARandomLaunchable ( itemGrenadeLauncher );
|
||||||
if ( usItem > 0 && count > 0 )
|
if ( usItem > 0 && count > 0 )
|
||||||
@@ -1236,9 +1238,7 @@ void ChooseGrenadesForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bGrena
|
|||||||
//do this for every 1-2 grenades so that we can get more variety
|
//do this for every 1-2 grenades so that we can get more variety
|
||||||
while ( bGrenades > 0 )
|
while ( bGrenades > 0 )
|
||||||
{
|
{
|
||||||
count = Random(3);
|
count = min(1 + Random(2), bGrenades);
|
||||||
if ( count > bGrenades )
|
|
||||||
count = bGrenades;
|
|
||||||
|
|
||||||
usItem = PickARandomItem ( GRENADE, pp->ubSoldierClass, bGrenadeClass, FALSE );
|
usItem = PickARandomItem ( GRENADE, pp->ubSoldierClass, bGrenadeClass, FALSE );
|
||||||
if ( usItem > 0 && count > 0 )
|
if ( usItem > 0 && count > 0 )
|
||||||
|
|||||||
+12
-4
@@ -5343,12 +5343,17 @@ BOOLEAN IsLocationSittable( INT32 iMapIndex, BOOLEAN fOnRoof )
|
|||||||
{
|
{
|
||||||
STRUCTURE *pStructure;
|
STRUCTURE *pStructure;
|
||||||
INT16 sDesiredLevel;
|
INT16 sDesiredLevel;
|
||||||
|
|
||||||
if( WhoIsThere2( iMapIndex, 0 ) != NOBODY )
|
if( WhoIsThere2( iMapIndex, 0 ) != NOBODY )
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
//Locations on roofs without a roof is not possible, so
|
//Locations on roofs without a roof is not possible, so
|
||||||
//we convert the onroof intention to ground.
|
//we convert the onroof intention to ground.
|
||||||
if( fOnRoof && !FlatRoofAboveGridNo( iMapIndex ) )
|
// sevenfm: return FALSE if location on roof does not exist
|
||||||
fOnRoof = FALSE;
|
if (fOnRoof && !FlatRoofAboveGridNo(iMapIndex))
|
||||||
|
return FALSE;
|
||||||
|
//fOnRoof = FALSE;
|
||||||
|
|
||||||
// Check structure database
|
// Check structure database
|
||||||
if( gpWorldLevelData[ iMapIndex ].pStructureHead )
|
if( gpWorldLevelData[ iMapIndex ].pStructureHead )
|
||||||
{
|
{
|
||||||
@@ -5373,8 +5378,11 @@ BOOLEAN IsLocationSittableExcludingPeople( INT32 iMapIndex, BOOLEAN fOnRoof )
|
|||||||
|
|
||||||
//Locations on roofs without a roof is not possible, so
|
//Locations on roofs without a roof is not possible, so
|
||||||
//we convert the onroof intention to ground.
|
//we convert the onroof intention to ground.
|
||||||
if( fOnRoof && !FlatRoofAboveGridNo( iMapIndex ) )
|
// sevenfm: return FALSE if location on roof does not exist
|
||||||
fOnRoof = FALSE;
|
if (fOnRoof && !FlatRoofAboveGridNo(iMapIndex))
|
||||||
|
return FALSE;
|
||||||
|
//fOnRoof = FALSE;
|
||||||
|
|
||||||
// Check structure database
|
// Check structure database
|
||||||
if( gpWorldLevelData[ iMapIndex ].pStructureHead )
|
if( gpWorldLevelData[ iMapIndex ].pStructureHead )
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -3159,7 +3159,7 @@ if(!GridNoOnVisibleWorldTile(iDestination))
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sevenfm: skip gas if not in gas already
|
// sevenfm: skip gas if not in gas already
|
||||||
if (!(s->flags.uiStatusFlags & SOLDIER_PC) &&
|
if ((!(s->flags.uiStatusFlags & SOLDIER_PC) || gTacticalStatus.fAutoBandageMode || s->flags.uiStatusFlags & SOLDIER_PCUNDERAICONTROL) &&
|
||||||
InGasSpot(s, newLoc, bLevel) &&
|
InGasSpot(s, newLoc, bLevel) &&
|
||||||
!InGasSpot(s, s->sGridNo, bLevel))
|
!InGasSpot(s, s->sGridNo, bLevel))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2027,7 +2027,11 @@ void PlayWeaponSound(SOLDIERTYPE *pSoldier, OBJECTTYPE *pObjHand, OBJECTTYPE *pO
|
|||||||
bTerrainType = FLAT_FLOOR;
|
bTerrainType = FLAT_FLOOR;
|
||||||
if (pSector)
|
if (pSector)
|
||||||
ubSectorType = pSector->ubTraversability[THROUGH_STRATEGIC_MOVE];
|
ubSectorType = pSector->ubTraversability[THROUGH_STRATEGIC_MOVE];
|
||||||
if (InARoom(pSoldier->sGridNo, NULL) && pSoldier->pathing.bLevel == 0 && bTerrainType == FLAT_FLOOR && CheckRoof(pSoldier->sGridNo))
|
if (InARoom(pSoldier->sGridNo, NULL) &&
|
||||||
|
pSoldier->pathing.bLevel == 0 &&
|
||||||
|
bTerrainType == FLAT_FLOOR &&
|
||||||
|
CheckRoof(pSoldier->sGridNo) &&
|
||||||
|
pSoldier->bDoBurst <= 1)
|
||||||
fRoom = TRUE;
|
fRoom = TRUE;
|
||||||
if (pSoldier->ubAttackingHand == HANDPOS)
|
if (pSoldier->ubAttackingHand == HANDPOS)
|
||||||
fMainHand = TRUE;
|
fMainHand = TRUE;
|
||||||
|
|||||||
+12
-6
@@ -1913,8 +1913,10 @@ INT16 EstimatePathCostToLocation( SOLDIERTYPE * pSoldier, INT32 sDestGridNo, INT
|
|||||||
{
|
{
|
||||||
// on ground or same building... normal!
|
// on ground or same building... normal!
|
||||||
sPathCost = EstimatePlotPath( pSoldier, sDestGridNo, FALSE, FALSE, FALSE, WALKING, FALSE, FALSE, 0);
|
sPathCost = EstimatePlotPath( pSoldier, sDestGridNo, FALSE, FALSE, FALSE, WALKING, FALSE, FALSE, 0);
|
||||||
*pfClimbingNecessary = FALSE;
|
if (pfClimbingNecessary)
|
||||||
*psClimbGridNo = NOWHERE;
|
*pfClimbingNecessary = FALSE;
|
||||||
|
if (psClimbGridNo)
|
||||||
|
*psClimbGridNo = NOWHERE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1945,8 +1947,10 @@ INT16 EstimatePathCostToLocation( SOLDIERTYPE * pSoldier, INT32 sDestGridNo, INT
|
|||||||
// add in an estimate of getting there after climbing down, *but not on top of roof*
|
// add in an estimate of getting there after climbing down, *but not on top of roof*
|
||||||
sPathCost += (APBPConstants[AP_MOVEMENT_FLAT] + APBPConstants[AP_MODIFIER_WALK]) * PythSpacesAway( sClimbGridNo, sDestGridNo ) / 2;
|
sPathCost += (APBPConstants[AP_MOVEMENT_FLAT] + APBPConstants[AP_MODIFIER_WALK]) * PythSpacesAway( sClimbGridNo, sDestGridNo ) / 2;
|
||||||
}
|
}
|
||||||
*pfClimbingNecessary = TRUE;
|
if (pfClimbingNecessary)
|
||||||
*psClimbGridNo = sClimbGridNo;
|
*pfClimbingNecessary = TRUE;
|
||||||
|
if (psClimbGridNo)
|
||||||
|
*psClimbGridNo = sClimbGridNo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2001,8 +2005,10 @@ INT16 EstimatePathCostToLocation( SOLDIERTYPE * pSoldier, INT32 sDestGridNo, INT
|
|||||||
// estimate walk cost
|
// estimate walk cost
|
||||||
sPathCost += (APBPConstants[AP_MOVEMENT_FLAT] + APBPConstants[AP_MODIFIER_WALK]) * PythSpacesAway( sClimbGridNo, sDestGridNo );
|
sPathCost += (APBPConstants[AP_MOVEMENT_FLAT] + APBPConstants[AP_MODIFIER_WALK]) * PythSpacesAway( sClimbGridNo, sDestGridNo );
|
||||||
}
|
}
|
||||||
*pfClimbingNecessary = TRUE;
|
if (pfClimbingNecessary)
|
||||||
*psClimbGridNo = sClimbGridNo;
|
*pfClimbingNecessary = TRUE;
|
||||||
|
if (psClimbGridNo)
|
||||||
|
*psClimbGridNo = sClimbGridNo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+44
-25
@@ -2752,16 +2752,35 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
|
|||||||
// try behind us, see if there's room to move back
|
// try behind us, see if there's room to move back
|
||||||
sCheckGridNo = NewGridNo(pSoldier->sGridNo, DirectionInc(gOppositeDirection[ubOpponentDir]));
|
sCheckGridNo = NewGridNo(pSoldier->sGridNo, DirectionInc(gOppositeDirection[ubOpponentDir]));
|
||||||
if (OKFallDirection(pSoldier, sCheckGridNo, pSoldier->pathing.bLevel, gOppositeDirection[ubOpponentDir], pSoldier->usAnimState))
|
if (OKFallDirection(pSoldier, sCheckGridNo, pSoldier->pathing.bLevel, gOppositeDirection[ubOpponentDir], pSoldier->usAnimState))
|
||||||
//FindBestPath(pSoldier, sCheckGridNo, pSoldier->pathing.bLevel, DetermineMovementMode(pSoldier, AI_ACTION_GET_CLOSER), COPYROUTE, 0))
|
|
||||||
{
|
{
|
||||||
// sevenfm: check if we can reach this gridno
|
// sevenfm: check if we can reach this gridno
|
||||||
INT32 iPathCost = EstimatePlotPath(pSoldier, sCheckGridNo, FALSE, FALSE, FALSE, DetermineMovementMode(pSoldier, AI_ACTION_GET_CLOSER), pSoldier->bStealthMode, FALSE, 0);
|
INT32 iPathCost = EstimatePlotPath(pSoldier, sCheckGridNo, FALSE, FALSE, FALSE, DetermineMovementMode(pSoldier, AI_ACTION_GET_CLOSER), pSoldier->bStealthMode, FALSE, 0);
|
||||||
if(iPathCost !=0 && iPathCost <= pSoldier->bActionPoints)
|
if (iPathCost != 0 && iPathCost + BestThrow.ubAPCost + GetAPsToLook(pSoldier) + GetAPsCrouch(pSoldier, FALSE) <= pSoldier->bActionPoints)
|
||||||
{
|
{
|
||||||
|
DebugAI(AI_MSG_INFO, pSoldier, String("moving backwards to have more room to deploy mortar"));
|
||||||
pSoldier->aiData.usActionData = sCheckGridNo;
|
pSoldier->aiData.usActionData = sCheckGridNo;
|
||||||
|
|
||||||
|
DebugAI(AI_MSG_INFO, pSoldier, String("prepare next action throw at spot %d level %d aimtime %d", BestThrow.sTarget, BestThrow.bTargetLevel, BestThrow.ubAimTime));
|
||||||
|
|
||||||
|
// if necessary, swap the usItem
|
||||||
|
if (BestThrow.bWeaponIn != HANDPOS)
|
||||||
|
{
|
||||||
|
DebugAI(AI_MSG_INFO, pSoldier, String("rearrange pocket"));
|
||||||
|
RearrangePocket(pSoldier, HANDPOS, BestThrow.bWeaponIn, FOREVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
pSoldier->aiData.usNextActionData = BestThrow.sTarget;
|
||||||
|
pSoldier->aiData.bNextTargetLevel = BestThrow.bTargetLevel;
|
||||||
|
pSoldier->aiData.bAimTime = BestThrow.ubAimTime;
|
||||||
|
|
||||||
|
pSoldier->aiData.bNextAction = AI_ACTION_TOSS_PROJECTILE;
|
||||||
|
|
||||||
return AI_ACTION_GET_CLOSER;
|
return AI_ACTION_GET_CLOSER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// can't fire!
|
||||||
|
BestThrow.ubPossible = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2770,7 +2789,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
|
|||||||
{
|
{
|
||||||
DebugAI(AI_MSG_INFO, pSoldier, String("prepare throw at spot %d level %d aimtime %d", BestThrow.sTarget, BestThrow.bTargetLevel, BestThrow.ubAimTime));
|
DebugAI(AI_MSG_INFO, pSoldier, String("prepare throw at spot %d level %d aimtime %d", BestThrow.sTarget, BestThrow.bTargetLevel, BestThrow.ubAimTime));
|
||||||
|
|
||||||
// if necessary, swap the usItem from holster into the hand position
|
// if necessary, swap the usItem
|
||||||
if (BestThrow.bWeaponIn != HANDPOS)
|
if (BestThrow.bWeaponIn != HANDPOS)
|
||||||
{
|
{
|
||||||
DebugAI(AI_MSG_INFO, pSoldier, String("rearrange pocket"));
|
DebugAI(AI_MSG_INFO, pSoldier, String("rearrange pocket"));
|
||||||
@@ -3856,11 +3875,11 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
|
|||||||
// modify RED movement tendencies according to morale
|
// modify RED movement tendencies according to morale
|
||||||
switch (pSoldier->aiData.bAIMorale)
|
switch (pSoldier->aiData.bAIMorale)
|
||||||
{
|
{
|
||||||
case MORALE_HOPELESS: bSeekPts = -99; bHelpPts = -99; bHidePts = +2; bWatchPts = -99; break;
|
case MORALE_HOPELESS: bSeekPts = -99; bHelpPts = -99; bHidePts += +2; bWatchPts = -99; break;
|
||||||
case MORALE_WORRIED: bSeekPts += -2; bHelpPts += 0; bHidePts += +2; bWatchPts += 1; break;
|
case MORALE_WORRIED: bSeekPts += -2; bHelpPts += 0; bHidePts += +2; bWatchPts += 1; break;
|
||||||
case MORALE_NORMAL: bSeekPts += 0; bHelpPts += 0; bHidePts += 0; bWatchPts += 0; break;
|
case MORALE_NORMAL: bSeekPts += 0; bHelpPts += 0; bHidePts += 0; bWatchPts += 0; break;
|
||||||
case MORALE_CONFIDENT: bSeekPts += +1; bHelpPts += 0; bHidePts += -1; bWatchPts += 0; break;
|
case MORALE_CONFIDENT: bSeekPts += +1; bHelpPts += 0; bHidePts += -1; bWatchPts += 0; break;
|
||||||
case MORALE_FEARLESS: bSeekPts += +1; bHelpPts += 0; bHidePts = -1; bWatchPts += 0; break;
|
case MORALE_FEARLESS: bSeekPts += +1; bHelpPts += 0; bHidePts += -1; bWatchPts += 0; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// modify tendencies according to orders
|
// modify tendencies according to orders
|
||||||
@@ -5490,15 +5509,15 @@ INT16 ubMinAPCost;
|
|||||||
if ( OKFallDirection( pSoldier, sCheckGridNo, pSoldier->pathing.bLevel, gOppositeDirection[ ubOpponentDir ], pSoldier->usAnimState ) )
|
if ( OKFallDirection( pSoldier, sCheckGridNo, pSoldier->pathing.bLevel, gOppositeDirection[ ubOpponentDir ], pSoldier->usAnimState ) )
|
||||||
{
|
{
|
||||||
// sevenfm: check if we can reach this gridno
|
// sevenfm: check if we can reach this gridno
|
||||||
INT32 iPathCost = EstimatePlotPath(pSoldier, sCheckGridNo, FALSE, FALSE, FALSE, DetermineMovementMode(pSoldier, AI_ACTION_GET_CLOSER), pSoldier->bStealthMode, FALSE, 0);
|
INT32 iPathCost = EstimatePlotPath(pSoldier, sCheckGridNo, FALSE, FALSE, FALSE, DetermineMovementMode(pSoldier, AI_ACTION_GET_CLOSER), pSoldier->bStealthMode, FALSE, 0);
|
||||||
if (iPathCost != 0 && iPathCost <= pSoldier->bActionPoints)
|
if (iPathCost != 0 && iPathCost <= pSoldier->bActionPoints)
|
||||||
{
|
{
|
||||||
pSoldier->aiData.usActionData = sCheckGridNo;
|
pSoldier->aiData.usActionData = sCheckGridNo;
|
||||||
return AI_ACTION_GET_CLOSER;
|
return AI_ACTION_GET_CLOSER;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( BestThrow.ubPossible )
|
if ( BestThrow.ubPossible )
|
||||||
{
|
{
|
||||||
@@ -6481,23 +6500,23 @@ L_NEWAIM:
|
|||||||
if (IsGrenadeLauncherAttached(&pSoldier->inv[HANDPOS])) //dnl ch63 240813
|
if (IsGrenadeLauncherAttached(&pSoldier->inv[HANDPOS])) //dnl ch63 240813
|
||||||
{
|
{
|
||||||
DebugAI(AI_MSG_INFO, pSoldier, String("using attached GL"));
|
DebugAI(AI_MSG_INFO, pSoldier, String("using attached GL"));
|
||||||
pSoldier->bWeaponMode = WM_ATTACHED_GL;
|
pSoldier->bWeaponMode = WM_ATTACHED_GL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// stand up before throwing if needed
|
// stand up before throwing if needed
|
||||||
if (gAnimControl[pSoldier->usAnimState].ubEndHeight < BestAttack.ubStance &&
|
if (gAnimControl[pSoldier->usAnimState].ubEndHeight < BestAttack.ubStance &&
|
||||||
pSoldier->InternalIsValidStance(AIDirection(pSoldier->sGridNo, BestAttack.sTarget), BestAttack.ubStance))
|
pSoldier->InternalIsValidStance(AIDirection(pSoldier->sGridNo, BestAttack.sTarget), BestAttack.ubStance))
|
||||||
{
|
{
|
||||||
pSoldier->aiData.usActionData = BestAttack.ubStance;
|
pSoldier->aiData.usActionData = BestAttack.ubStance;
|
||||||
pSoldier->aiData.bNextAction = AI_ACTION_TOSS_PROJECTILE;
|
pSoldier->aiData.bNextAction = AI_ACTION_TOSS_PROJECTILE;
|
||||||
pSoldier->aiData.usNextActionData = BestAttack.sTarget;
|
pSoldier->aiData.usNextActionData = BestAttack.sTarget;
|
||||||
pSoldier->aiData.bNextTargetLevel = BestAttack.bTargetLevel;
|
pSoldier->aiData.bNextTargetLevel = BestAttack.bTargetLevel;
|
||||||
return AI_ACTION_CHANGE_STANCE;
|
return AI_ACTION_CHANGE_STANCE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pSoldier->aiData.usActionData = BestAttack.sTarget;
|
pSoldier->aiData.usActionData = BestAttack.sTarget;
|
||||||
pSoldier->bTargetLevel = BestAttack.bTargetLevel;
|
pSoldier->bTargetLevel = BestAttack.bTargetLevel;
|
||||||
return(AI_ACTION_TOSS_PROJECTILE);
|
return(AI_ACTION_TOSS_PROJECTILE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user