Fixed problems with enemy rooftop climbing (by sevenfm)

- Also updated "Water", "DeepWater" and "WaterTooDeepForAttacks" methods: Added bLevel parameter (by sevenfm)
- see: http://thepit.ja-galaxy-forum.com/index.php?t=msg&th=22966&start=0&

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8110 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2016-03-15 12:40:54 +00:00
parent 5bc2bae07e
commit 23d4051473
12 changed files with 118 additions and 154 deletions
+7 -5
View File
@@ -88,7 +88,7 @@ INT8 OKToAttack(SOLDIERTYPE * pSoldier, int target)
if (target == pSoldier->sGridNo)
return(NOSHOOT_MYSELF);
if (WaterTooDeepForAttacks(pSoldier->sGridNo))
if (WaterTooDeepForAttacks(pSoldier->sGridNo, pSoldier->pathing.bLevel))
return(NOSHOOT_WATER);
// make sure a weapon is in hand (FEB.8 ADDITION: tossable items are also OK)
@@ -1688,7 +1688,8 @@ INT16 EstimatePathCostToLocation( SOLDIERTYPE * pSoldier, INT32 sDestGridNo, INT
else
{
sPathCost = PlotPath( pSoldier, sClimbGridNo, FALSE, FALSE, FALSE, WALKING, FALSE, FALSE, 0 );
if (sPathCost != 0)
// sevenfm: check if we are already standing at climb gridno
if (sPathCost != 0 || pSoldier->sGridNo == sClimbGridNo)
{
// add in cost of climbing down
if (fAddCostAfterClimbingUp)
@@ -1731,7 +1732,8 @@ INT16 EstimatePathCostToLocation( SOLDIERTYPE * pSoldier, INT32 sDestGridNo, INT
else
{
sPathCost = PlotPath( pSoldier, sClimbGridNo, FALSE, FALSE, FALSE, WALKING, FALSE, FALSE, 0);
if (sPathCost != 0)
// sevenfm: check if we are already standing at climb gridno
if (sPathCost != 0 || pSoldier->sGridNo == sClimbGridNo)
{
// add in the cost of climbing up or down
if (pSoldier->pathing.bLevel == 0)
@@ -1942,7 +1944,7 @@ INT16 DistanceToClosestFriend( SOLDIERTYPE * pSoldier )
BOOLEAN InWaterGasOrSmoke( SOLDIERTYPE *pSoldier, INT32 sGridNo )
{
if (WaterTooDeepForAttacks( sGridNo ))
if (WaterTooDeepForAttacks( sGridNo, pSoldier->pathing.bLevel ))
{
return(TRUE);
}
@@ -1968,7 +1970,7 @@ BOOLEAN InGasOrSmoke( SOLDIERTYPE *pSoldier, INT32 sGridNo )
INT16 InWaterOrGas(SOLDIERTYPE *pSoldier, INT32 sGridNo)
{
if (WaterTooDeepForAttacks( sGridNo ))
if (WaterTooDeepForAttacks( sGridNo, pSoldier->pathing.bLevel ))
{
return(TRUE);
}
+14 -14
View File
@@ -788,7 +788,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
}
bInWater = Water( pSoldier->sGridNo );
bInWater = Water( pSoldier->sGridNo, pSoldier->pathing.bLevel );
// check if standing in tear gas without a gas mask on, or in smoke
bInGas = InGasOrSmoke( pSoldier, pSoldier->sGridNo );
@@ -1825,7 +1825,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
iChance = 5 * WhatIKnowThatPublicDont(pSoldier,FALSE); // use 5 * for YELLOW alert
// if I actually know something they don't and I ain't swimming (deep water)
if (iChance && !DeepWater( pSoldier->sGridNo ))
if (iChance && !DeepWater( pSoldier->sGridNo, pSoldier->pathing.bLevel ))
{
// CJC: this addition allows for varying difficulty levels for soldier types
@@ -2474,8 +2474,8 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
// determine if we happen to be in water (in which case we're in BIG trouble!)
bInWater = Water( pSoldier->sGridNo );
bInDeepWater = Water( pSoldier->sGridNo );
bInWater = Water( pSoldier->sGridNo, pSoldier->pathing.bLevel );
bInDeepWater = Water( pSoldier->sGridNo, pSoldier->pathing.bLevel );
// check if standing in tear gas without a gas mask on
bInGas = InGasOrSmoke( pSoldier, pSoldier->sGridNo );
@@ -3437,7 +3437,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
if( !TileIsOutOfBounds(tempGridNo) &&
!GuySawEnemyThisTurnOrBefore(pSoldier) &&
!pSoldier->aiData.bUnderFire &&
!Water(pSoldier->sGridNo) &&
!Water(pSoldier->sGridNo, pSoldier->pathing.bLevel) &&
pSoldier->bInitialActionPoints >= APBPConstants[AP_MINIMUM] &&
( PythSpacesAway( pSoldier->sGridNo, tempGridNo ) > MIN_FLANK_DIST_RED ||
!LocationToLocationLineOfSightTest( pSoldier->sGridNo, pSoldier->pathing.bLevel, tempGridNo, pSoldier->pathing.bLevel, TRUE) ) )
@@ -3452,7 +3452,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
// sevenfm: avoid going into water, gas or light
if( !TileIsOutOfBounds(pSoldier->aiData.usActionData) &&
!Water(pSoldier->aiData.usActionData) &&
!Water(pSoldier->aiData.usActionData, pSoldier->pathing.bLevel) &&
!InGas( pSoldier, pSoldier->aiData.usActionData ) &&
!InLightAtNight( pSoldier->aiData.usActionData, pSoldier->pathing.bLevel ) )
{
@@ -4563,8 +4563,8 @@ INT16 ubMinAPCost;
else
{
// determine if we happen to be in water (in which case we're in BIG trouble!)
bInWater = Water( pSoldier->sGridNo );
bInDeepWater = WaterTooDeepForAttacks( pSoldier->sGridNo );
bInWater = Water( pSoldier->sGridNo, pSoldier->pathing.bLevel );
bInDeepWater = WaterTooDeepForAttacks( pSoldier->sGridNo, pSoldier->pathing.bLevel );
// check if standing in tear gas without a gas mask on
bInGas = InGasOrSmoke( pSoldier, pSoldier->sGridNo );
@@ -6716,7 +6716,7 @@ INT8 ZombieDecideActionGreen(SOLDIERTYPE *pSoldier)
return( AI_ACTION_NONE );
}
bInWater = Water( pSoldier->sGridNo );
bInWater = Water( pSoldier->sGridNo, pSoldier->pathing.bLevel );
if ( bInWater && PreRandom( 2 ) )
{
@@ -7174,7 +7174,7 @@ INT8 ZombieDecideActionYellow(SOLDIERTYPE *pSoldier)
iChance = 5 * WhatIKnowThatPublicDont(pSoldier,FALSE); // use 5 * for YELLOW alert
// if I actually know something they don't and I ain't swimming (deep water)
if (iChance && !DeepWater( pSoldier->sGridNo ))
if (iChance && !DeepWater( pSoldier->sGridNo, pSoldier->pathing.bLevel ))
{
// CJC: this addition allows for varying difficulty levels for soldier types
iChance += gbDiff[ DIFF_RADIO_RED_ALERT ][ SoldierDifficultyLevel( pSoldier ) ] / 2;
@@ -7361,8 +7361,8 @@ INT8 ZombieDecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
// determine if we happen to be in water (in which case we're in BIG trouble!)
bInWater = Water( pSoldier->sGridNo );
bInDeepWater = Water( pSoldier->sGridNo );
bInWater = Water( pSoldier->sGridNo, pSoldier->pathing.bLevel );
bInDeepWater = Water( pSoldier->sGridNo, pSoldier->pathing.bLevel );
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"decideactionred: crouch and rest if running out of breath");
////////////////////////////////////////////////////////////////////////
@@ -8053,8 +8053,8 @@ INT8 ZombieDecideActionBlack(SOLDIERTYPE *pSoldier)
ubCanMove = (pSoldier->bActionPoints >= MinPtsToMove(pSoldier));
// determine if we happen to be in water (in which case we're in BIG trouble!)
bInWater = Water( pSoldier->sGridNo );
bInDeepWater = WaterTooDeepForAttacks( pSoldier->sGridNo );
bInWater = Water( pSoldier->sGridNo, pSoldier->pathing.bLevel );
bInDeepWater = WaterTooDeepForAttacks( pSoldier->sGridNo, pSoldier->pathing.bLevel );
// calculate our morale
pSoldier->aiData.bAIMorale = CalcMorale(pSoldier);
+61 -50
View File
@@ -2611,13 +2611,13 @@ INT32 FindFlankingSpot(SOLDIERTYPE *pSoldier, INT32 sPos, INT8 bAction )
}
// sevenfm: don't go into deep water for flanking
if( DeepWater( sGridNo ) )
if( DeepWater( sGridNo, pSoldier->pathing.bLevel ) )
{
continue;
}
// sevenfm: allow water flanking only for CUNNINGSOLO soldiers
if( Water( sGridNo ) && pSoldier->aiData.bAttitude != CUNNINGSOLO )
if( Water( sGridNo, pSoldier->pathing.bLevel ) && pSoldier->aiData.bAttitude != CUNNINGSOLO )
{
continue;
}
@@ -2696,25 +2696,29 @@ INT32 FindFlankingSpot(SOLDIERTYPE *pSoldier, INT32 sPos, INT8 bAction )
return( sBestSpot );
}
//sevenfm: new calculation using FindHeigherLevel
INT32 FindClosestClimbPoint (SOLDIERTYPE *pSoldier, BOOLEAN fClimbUp )
{
INT32 sBestSpot = NOWHERE;
// sevenfm: safety check
if(!pSoldier)
{
return NOWHERE;
}
//DebugMsg( TOPIC_JA2AI , DBG_LEVEL_3 , "FindClosestClimbPoint");
//gubNPCAPBudget = gubNPCAPBudget = __min( gubNPCAPBudget, gubNPCAPBudget - GetAPsToChangeStance( pSoldier, ANIM_STAND ) -1 ); //-1 for turning cost while standing
//NumMessage("Search Range = ",iSearchRange);
//NumMessage("gubNPCAPBudget = ",gubNPCAPBudget);
// 0verhaul: This function is optimized to take advantage of the new climb point info.
if (fClimbUp)
{
// For the climb up case, search the nearby limits for a climb up point and take the closest.
INT32 sGridNo;
static const INT32 iSearchRange = 20;
INT16 sMaxLeft, sMaxRight, sMaxUp, sMaxDown, sXOffset, sYOffset;
UINT8 ubTestDir;
//UINT8 ubTestDir;
INT8 ubClimbDir;
INT32 sClimbSpot;
// determine maximum horizontal limits
sMaxLeft = min( iSearchRange, (pSoldier->sGridNo % MAXCOL));
@@ -2744,7 +2748,6 @@ INT32 FindClosestClimbPoint (SOLDIERTYPE *pSoldier, BOOLEAN fClimbUp )
continue;
}
if ( sGridNo == pSoldier->pathing.sBlackList )
{
continue;
@@ -2756,24 +2759,32 @@ INT32 FindClosestClimbPoint (SOLDIERTYPE *pSoldier, BOOLEAN fClimbUp )
continue;
}
if (gpWorldLevelData[ sGridNo].ubExtFlags[0] & MAPELEMENT_EXT_CLIMBPOINT)
// exclude water tiles
if ( Water( sGridNo, pSoldier->pathing.bLevel ) )
{
// Search for the destination climb point on the roof
for ( ubTestDir = 0; ubTestDir < NUM_WORLD_DIRECTIONS; ubTestDir += 2 )
continue;
}
// check that there's noone at sGridNo at level 0 (this soldier is allowed)
if( WhoIsThere2( sGridNo, 0 ) != NOBODY &&
WhoIsThere2( sGridNo, 0 ) != pSoldier->ubID )
{
continue;
}
if( FindHeigherLevel( pSoldier, sGridNo, pSoldier->ubDirection, &ubClimbDir ) )
{
// ubClimbDir is new direction
// check that there's noone there
sClimbSpot = NewGridNo( sGridNo, DirectionInc( ubClimbDir));
if( WhoIsThere2( sClimbSpot, 1 ) == NOBODY )
{
INT32 sTestGridNo = NewGridNo( sGridNo, DirectionInc( ubTestDir));
// And see if it or the ground location is occupied
if (gpWorldLevelData[ sTestGridNo ].ubExtFlags[1] & MAPELEMENT_EXT_CLIMBPOINT &&
(WhoIsThere2( sTestGridNo, 1 ) == NOBODY) &&
(WhoIsThere2( sGridNo, 0 ) == NOBODY) )
// Good climb point. Is it closer than the previous point?
if( TileIsOutOfBounds(sBestSpot) ||
GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo , sGridNo ) < GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo , sBestSpot ))
{
// Good climb point. Is it closer than the previous point?
if ( GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo , sGridNo ) <
GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo , sBestSpot ))
{
// If not, we have a new winnar!
sBestSpot = sGridNo;
}
// If not, we have a new winnar!
sBestSpot = sGridNo;
}
}
}
@@ -2936,47 +2947,47 @@ INT32 FindBestCoverNearTheGridNo(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubS
}
// sevenfm: new calculation using FindHeigherLevel/FindLowerLevel
INT8 FindDirectionForClimbing( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel )
{
UINT8 ubClimbDir;
INT8 ubClimbDir;
INT32 sClimbSpot;
if (bLevel == 0)
if(!pSoldier)
{
if (gpWorldLevelData[ sGridNo].ubExtFlags[0] & MAPELEMENT_EXT_CLIMBPOINT)
return DIRECTION_IRRELEVANT;
}
if (pSoldier->pathing.bLevel == 0)
{
// check climb up
if( FindHeigherLevel( pSoldier, sGridNo, pSoldier->ubDirection, &ubClimbDir ) )
{
for ( ubClimbDir = 0; ubClimbDir < NUM_WORLD_DIRECTIONS; ubClimbDir += 2 )
// ubClimbDir is new direction
// check that there's noone there
sClimbSpot = NewGridNo( sGridNo, DirectionInc( ubClimbDir));
if( WhoIsThere2( sClimbSpot, 1 ) == NOBODY &&
!Water(sClimbSpot, 1) )
{
sClimbSpot = NewGridNo( sGridNo, DirectionInc( ubClimbDir));
if (gpWorldLevelData[ sClimbSpot].ubExtFlags[1] & MAPELEMENT_EXT_CLIMBPOINT &&
WhoIsThere2( sClimbSpot, 1 ) == NOBODY )
{
return ubClimbDir;
}
return ubClimbDir;
}
}
}
else if (bLevel == 1)
else
{
//CHRISL: If NewInv and wearing a backpack, don't allow climbing
if (UsingNewInventorySystem() == true && pSoldier->inv[BPACKPOCKPOS].exists() == true
//JMich.BackpackClimb
&& ((gGameExternalOptions.sBackpackWeightToClimb == -1) || (INT16)pSoldier->inv[BPACKPOCKPOS].GetWeightOfObjectInStack() + Item[pSoldier->inv[BPACKPOCKPOS].usItem].sBackpackWeightModifier > gGameExternalOptions.sBackpackWeightToClimb)
&& ((gGameExternalOptions.fUseGlobalBackpackSettings == TRUE) || (Item[pSoldier->inv[BPACKPOCKPOS].usItem].fAllowClimbing == FALSE)))
return DIRECTION_IRRELEVANT;
if (gpWorldLevelData[ sGridNo].ubExtFlags[1] & MAPELEMENT_EXT_CLIMBPOINT)
// check climb down
if( FindLowerLevel( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &ubClimbDir ) )
{
for ( ubClimbDir = 0; ubClimbDir< NUM_WORLD_DIRECTIONS; ubClimbDir += 2 )
// ubClimbDir is new direction
sClimbSpot = NewGridNo( sGridNo, DirectionInc( ubClimbDir));
if( WhoIsThere2( sClimbSpot, 0 ) == NOBODY &&
!Water(sClimbSpot, 0) )
{
sClimbSpot = NewGridNo( sGridNo, DirectionInc( ubClimbDir));
if (gpWorldLevelData[ sClimbSpot].ubExtFlags[0] & MAPELEMENT_EXT_CLIMBPOINT &&
WhoIsThere2( sClimbSpot, 0 ) == NOBODY )
{
return ubClimbDir;
}
return ubClimbDir;
}
}
}
return DIRECTION_IRRELEVANT;
}
+2 -2
View File
@@ -82,7 +82,7 @@ int LegalNPCDestination(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubPathMode,
*/
{
// if water's a problem, and gridno is in a water tile (bridges are OK)
if (!ubWaterOK && Water(sGridNo))
if (!ubWaterOK && Water(sGridNo, pSoldier->pathing.bLevel))
return(FALSE);
//Madd: added to prevent people from running into gas and fire
@@ -510,7 +510,7 @@ INT32 InternalGoAsFarAsPossibleTowards(SOLDIERTYPE *pSoldier, INT32 sDesGrid, IN
// don't try to approach go after noises or enemies actually in water
// would be too easy to throw rocks in water, etc. & distract the AI
if (Water(sDesGrid))
if (Water(sDesGrid, pSoldier->pathing.bLevel))
{
return(NOWHERE);
}