mirror of
https://github.com/1dot13/source.git
synced 2026-09-09 14:46:05 +02:00
Enemy soldiers will try to avoid being hit by artillery strike.
FindBestNearbyCover: - penalty to locations in red smoke danger zone - avoid moving into red smoke danger zone if not in red smoke danger already FindNearestUngassedLand: - improved code - try not to move closer to known enemies. - calculate path with correct movement mode FindNearbyDarkerSpot: - improved code - calculate path with correct movement mode FindFlankingSpot: - avoid locations near bombs - avoid moving into red smoke danger zone git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8753 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -48,13 +48,6 @@ enum
|
|||||||
NUM_URGENCY_STATES
|
NUM_URGENCY_STATES
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NOWATER 0
|
|
||||||
#define WATEROK 1
|
|
||||||
|
|
||||||
#define IGNORE_PATH 0
|
|
||||||
#define ENSURE_PATH 1
|
|
||||||
#define ENSURE_PATH_COST 2
|
|
||||||
|
|
||||||
#define DONTFORCE 0
|
#define DONTFORCE 0
|
||||||
#define FORCE 1
|
#define FORCE 1
|
||||||
|
|
||||||
@@ -95,7 +88,6 @@ enum
|
|||||||
#define MAX_THREAT_RANGE 400 // 30 tiles worth
|
#define MAX_THREAT_RANGE 400 // 30 tiles worth
|
||||||
#define MIN_PERCENT_BETTER 5 // 5% improvement in cover is good
|
#define MIN_PERCENT_BETTER 5 // 5% improvement in cover is good
|
||||||
|
|
||||||
|
|
||||||
#define TOSSES_PER_10TURNS 18 // max # of grenades tossable in 10 turns
|
#define TOSSES_PER_10TURNS 18 // max # of grenades tossable in 10 turns
|
||||||
#define SHELLS_PER_10TURNS 13 // max # of shells firable in 10 turns
|
#define SHELLS_PER_10TURNS 13 // max # of shells firable in 10 turns
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include "Game Clock.h" // sevenfm
|
#include "Game Clock.h" // sevenfm
|
||||||
#include "Rotting Corpses.h" // sevenfm
|
#include "Rotting Corpses.h" // sevenfm
|
||||||
#include "wcheck.h" // sevenfm
|
#include "wcheck.h" // sevenfm
|
||||||
|
#include "SmokeEffects.h" // sevenfm
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "GameInitOptionsScreen.h"
|
#include "GameInitOptionsScreen.h"
|
||||||
@@ -4255,6 +4256,266 @@ BOOLEAN FindBombNearby( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubDistance )
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// danger percent based on distance to closest smoke effect
|
||||||
|
UINT8 RedSmokeDanger(INT32 sGridNo, INT8 bLevel)
|
||||||
|
{
|
||||||
|
UINT32 uiCnt;
|
||||||
|
INT32 sDist;
|
||||||
|
INT32 sClosestDist;
|
||||||
|
INT32 sMaxDist = min(gSkillTraitValues.usVOMortarRadius, DAY_VISION_RANGE);
|
||||||
|
INT32 sClosestSmoke = NOWHERE;
|
||||||
|
UINT8 ubDangerPercent = 0;
|
||||||
|
|
||||||
|
if (TileIsOutOfBounds(sGridNo))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gSkillTraitValues.fROAllowArtillery)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no artillery strike danger underground
|
||||||
|
if (gbWorldSectorZ > 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if artillery strike was ordered by any team
|
||||||
|
if (!CheckArtilleryStrike())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no danger when in a building
|
||||||
|
if (bLevel == 0 && CheckRoof(sGridNo))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no danger when in dense terrain
|
||||||
|
if (bLevel == 0 && TerrainDensity(sGridNo, bLevel, 2, FALSE) >= 20)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//loop through all red smoke effects and find closest
|
||||||
|
for (uiCnt = 0; uiCnt < guiNumSmokeEffects; uiCnt++)
|
||||||
|
{
|
||||||
|
if (gSmokeEffectData[uiCnt].fAllocated &&
|
||||||
|
gSmokeEffectData[uiCnt].bType == SIGNAL_SMOKE_EFFECT &&
|
||||||
|
!TileIsOutOfBounds(gSmokeEffectData[uiCnt].sGridNo))
|
||||||
|
{
|
||||||
|
sDist = PythSpacesAway(gSmokeEffectData[uiCnt].sGridNo, sGridNo);
|
||||||
|
|
||||||
|
if (sClosestSmoke == NOWHERE || sDist < sClosestDist)
|
||||||
|
{
|
||||||
|
sClosestDist = sDist;
|
||||||
|
sClosestSmoke = gSmokeEffectData[uiCnt].sGridNo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we found red smoke, calculate danger percent based on distance
|
||||||
|
// 0% at DAY_VISION_RANGE/2, 100% at zero range
|
||||||
|
if (sClosestSmoke != NOWHERE)
|
||||||
|
{
|
||||||
|
ubDangerPercent = 100 * (sMaxDist - min(sMaxDist, sClosestDist)) / sMaxDist;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ubDangerPercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if artillery strike was ordered by any team
|
||||||
|
BOOLEAN CheckArtilleryStrike(void)
|
||||||
|
{
|
||||||
|
UINT32 uiBombIndex;
|
||||||
|
OBJECTTYPE *pObj;
|
||||||
|
|
||||||
|
// search all bombs
|
||||||
|
for (uiBombIndex = 0; uiBombIndex < guiNumWorldBombs; uiBombIndex++)
|
||||||
|
{
|
||||||
|
if (gWorldBombs[uiBombIndex].fExists &&
|
||||||
|
gWorldItems[gWorldBombs[uiBombIndex].iItemIndex].usFlags & WORLD_ITEM_ARMED_BOMB)
|
||||||
|
{
|
||||||
|
pObj = &(gWorldItems[gWorldBombs[uiBombIndex].iItemIndex].object);
|
||||||
|
|
||||||
|
if (pObj && pObj->exists() && (*pObj)[0]->data.ubWireNetworkFlag & ANY_ARTILLERY_FLAG)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN CheckRoof(INT32 sGridNo)
|
||||||
|
{
|
||||||
|
if (FindStructure(sGridNo, STRUCTURE_ROOF) != NULL)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 TerrainDensity(INT32 sSpot, INT8 bLevel, UINT8 ubDistance, BOOLEAN fGrass)
|
||||||
|
{
|
||||||
|
if (TileIsOutOfBounds(sSpot))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
INT16 sMaxLeft, sMaxRight, sMaxUp, sMaxDown, sXOffset, sYOffset;
|
||||||
|
INT32 sCheckSpot = NOWHERE;
|
||||||
|
INT32 sCountSpots = 0;
|
||||||
|
INT32 sCountObstacles = 0;
|
||||||
|
UINT16 usRoom1, usRoom2;
|
||||||
|
|
||||||
|
STRUCTURE *pCurrent;
|
||||||
|
INT16 sDesiredLevel;
|
||||||
|
|
||||||
|
// determine maximum horizontal limits
|
||||||
|
sMaxLeft = min(ubDistance, (sSpot % MAXCOL));
|
||||||
|
sMaxRight = min(ubDistance, MAXCOL - ((sSpot % MAXCOL) + 1));
|
||||||
|
|
||||||
|
// determine maximum vertical limits
|
||||||
|
sMaxUp = min(ubDistance, (sSpot / MAXROW));
|
||||||
|
sMaxDown = min(ubDistance, MAXROW - ((sSpot / MAXROW) + 1));
|
||||||
|
|
||||||
|
// count obstacles
|
||||||
|
for (sYOffset = -sMaxUp; sYOffset <= sMaxDown; sYOffset++)
|
||||||
|
{
|
||||||
|
for (sXOffset = -sMaxLeft; sXOffset <= sMaxRight; sXOffset++)
|
||||||
|
{
|
||||||
|
sCheckSpot = sSpot + sXOffset + (MAXCOL * sYOffset);
|
||||||
|
|
||||||
|
if (TileIsOutOfBounds(sCheckSpot))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InARoom(sSpot, &usRoom1) != InARoom(sCheckSpot, &usRoom2) || usRoom1 != usRoom2)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sCountSpots++;
|
||||||
|
|
||||||
|
if (!IsLocationSittableExcludingPeople(sCheckSpot, bLevel))
|
||||||
|
{
|
||||||
|
sCountObstacles++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fGrass && IsLocationSittableExcludingPeople(sCheckSpot, bLevel))
|
||||||
|
{
|
||||||
|
pCurrent = gpWorldLevelData[sCheckSpot].pStructureHead;
|
||||||
|
|
||||||
|
if (bLevel > 0)
|
||||||
|
sDesiredLevel = STRUCTURE_ON_ROOF;
|
||||||
|
else
|
||||||
|
sDesiredLevel = STRUCTURE_ON_GROUND;
|
||||||
|
|
||||||
|
if (pCurrent != NULL &&
|
||||||
|
pCurrent->sCubeOffset == sDesiredLevel &&
|
||||||
|
pCurrent->pDBStructureRef->pDBStructure->ubArmour == 4) // light vegetation
|
||||||
|
{
|
||||||
|
sCountObstacles++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sCountSpots > 0)
|
||||||
|
return 100 * sCountObstacles / sCountSpots;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
INT16 DistanceToClosestActiveOpponent(SOLDIERTYPE *pSoldier, INT32 sSpot)
|
||||||
|
{
|
||||||
|
INT32 sGridNo;
|
||||||
|
UINT32 uiLoop;
|
||||||
|
INT8 bLevel;
|
||||||
|
SOLDIERTYPE *pOpponent;
|
||||||
|
INT16 sDistance, sClosestDistance = -1;
|
||||||
|
|
||||||
|
if (!pSoldier || TileIsOutOfBounds(sSpot))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// look through this man's personal & public opplists for opponents known
|
||||||
|
for (uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++)
|
||||||
|
{
|
||||||
|
pOpponent = MercSlots[uiLoop];
|
||||||
|
|
||||||
|
// if this merc is inactive, at base, on assignment, or dead
|
||||||
|
if (!pOpponent)
|
||||||
|
{
|
||||||
|
continue; // next merc
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ValidOpponent(pSoldier, pOpponent))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pOpponent->stats.bLife < OKLIFE)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this opponent is unknown personally and publicly
|
||||||
|
if (pSoldier->aiData.bOppList[pOpponent->ubID] == NOT_HEARD_OR_SEEN)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// obtain opponent's location and level
|
||||||
|
sGridNo = gsLastKnownOppLoc[pSoldier->ubID][pOpponent->ubID];
|
||||||
|
bLevel = gbLastKnownOppLevel[pSoldier->ubID][pOpponent->ubID];
|
||||||
|
|
||||||
|
if (TileIsOutOfBounds(sGridNo))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sDistance = PythSpacesAway(sSpot, sGridNo);
|
||||||
|
|
||||||
|
if (sClosestDistance < 0 ||
|
||||||
|
sDistance < sClosestDistance)
|
||||||
|
{
|
||||||
|
sClosestDistance = sDistance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sClosestDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN ValidOpponent(SOLDIERTYPE* pSoldier, SOLDIERTYPE* pOpponent)
|
||||||
|
{
|
||||||
|
if (!pSoldier || !pOpponent)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pOpponent->bActive ||
|
||||||
|
!pOpponent->bInSector ||
|
||||||
|
pOpponent->stats.bLife == 0 ||
|
||||||
|
CONSIDERED_NEUTRAL(pSoldier, pOpponent) ||
|
||||||
|
pSoldier->bSide == pOpponent->bSide ||
|
||||||
|
pSoldier->aiData.bAttitude == ATTACKSLAYONLY && pOpponent->ubProfile != SLAY ||
|
||||||
|
(pOpponent->ubWhatKindOfMercAmI == MERC_TYPE__VEHICLE && GetNumberInVehicle(pOpponent->bVehicleID) == 0) ||
|
||||||
|
gTacticalStatus.bBoxingState == BOXING && (pSoldier->flags.uiStatusFlags & SOLDIER_BOXER) && !(pOpponent->flags.uiStatusFlags & SOLDIER_BOXER) ||
|
||||||
|
pOpponent->ubBodyType == CROW)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
BOOLEAN AnyCoverFromSpot( INT32 sSpot, INT8 bLevel, INT32 sThreatLoc, INT8 bThreatLevel )
|
BOOLEAN AnyCoverFromSpot( INT32 sSpot, INT8 bLevel, INT32 sThreatLoc, INT8 bThreatLevel )
|
||||||
{
|
{
|
||||||
UINT8 ubDirection;
|
UINT8 ubDirection;
|
||||||
|
|||||||
@@ -1084,7 +1084,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
|||||||
|
|
||||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DecideActionGreen: get out of water and gas"));
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DecideActionGreen: get out of water and gas"));
|
||||||
|
|
||||||
if (bInWater || bInGas || FindBombNearby(pSoldier, pSoldier->sGridNo, DAY_VISION_RANGE/8))
|
if (bInWater || bInGas || FindBombNearby(pSoldier, pSoldier->sGridNo, BOMB_DETECTION_RANGE) || RedSmokeDanger(pSoldier->sGridNo, pSoldier->pathing.bLevel))
|
||||||
{
|
{
|
||||||
pSoldier->aiData.usActionData = FindNearestUngassedLand(pSoldier);
|
pSoldier->aiData.usActionData = FindNearestUngassedLand(pSoldier);
|
||||||
|
|
||||||
@@ -1607,7 +1607,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
|||||||
// WHEN IN GAS, GO TO NEAREST REACHABLE SPOT OF UNGASSED LAND
|
// WHEN IN GAS, GO TO NEAREST REACHABLE SPOT OF UNGASSED LAND
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
if ( InGas(pSoldier, pSoldier->sGridNo) || DeepWater( pSoldier->sGridNo, pSoldier->pathing.bLevel ) || FindBombNearby(pSoldier, pSoldier->sGridNo, DAY_VISION_RANGE/8) )
|
if (InGas(pSoldier, pSoldier->sGridNo) || DeepWater(pSoldier->sGridNo, pSoldier->pathing.bLevel) || FindBombNearby(pSoldier, pSoldier->sGridNo, BOMB_DETECTION_RANGE))
|
||||||
{
|
{
|
||||||
pSoldier->aiData.usActionData = FindNearestUngassedLand(pSoldier);
|
pSoldier->aiData.usActionData = FindNearestUngassedLand(pSoldier);
|
||||||
|
|
||||||
@@ -2582,7 +2582,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
|
|||||||
// WHEN IN GAS, GO TO NEAREST REACHABLE SPOT OF UNGASSED LAND
|
// WHEN IN GAS, GO TO NEAREST REACHABLE SPOT OF UNGASSED LAND
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
if (ubCanMove && (bInGas || FindBombNearby(pSoldier, pSoldier->sGridNo, DAY_VISION_RANGE/8)))
|
if (ubCanMove && (bInGas || bInDeepWater || FindBombNearby(pSoldier, pSoldier->sGridNo, BOMB_DETECTION_RANGE) || RedSmokeDanger(pSoldier->sGridNo, pSoldier->pathing.bLevel)))
|
||||||
{
|
{
|
||||||
pSoldier->aiData.usActionData = FindNearestUngassedLand(pSoldier);
|
pSoldier->aiData.usActionData = FindNearestUngassedLand(pSoldier);
|
||||||
|
|
||||||
@@ -4719,7 +4719,7 @@ INT16 ubMinAPCost;
|
|||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// if soldier in water/gas has enough APs left to move at least 1 square
|
// if soldier in water/gas has enough APs left to move at least 1 square
|
||||||
if ( ( bInDeepWater || bInGas || FindBombNearby(pSoldier, pSoldier->sGridNo, DAY_VISION_RANGE/8) ) && ubCanMove)
|
if (ubCanMove && (bInGas || bInDeepWater || FindBombNearby(pSoldier, pSoldier->sGridNo, BOMB_DETECTION_RANGE) || RedSmokeDanger(pSoldier->sGridNo, pSoldier->pathing.bLevel)))
|
||||||
{
|
{
|
||||||
pSoldier->aiData.usActionData = FindNearestUngassedLand(pSoldier);
|
pSoldier->aiData.usActionData = FindNearestUngassedLand(pSoldier);
|
||||||
|
|
||||||
|
|||||||
+147
-47
@@ -423,7 +423,6 @@ INT32 CalcCoverValue(SOLDIERTYPE *pMe, INT32 sMyGridNo, INT32 iMyThreat, INT32 i
|
|||||||
pHim->dYPos = dHisY; // and the 'y'
|
pHim->dYPos = dHisY; // and the 'y'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// these value should be < 1 million each
|
// these value should be < 1 million each
|
||||||
iHisPosValue = bHisCTGT * Threat[uiThreatIndex].iValue * Threat[uiThreatIndex].iAPs;
|
iHisPosValue = bHisCTGT * Threat[uiThreatIndex].iValue * Threat[uiThreatIndex].iAPs;
|
||||||
iMyPosValue = bMyCTGT * iMyThreat * iMyAPsLeft;
|
iMyPosValue = bMyCTGT * iMyThreat * iMyAPsLeft;
|
||||||
@@ -438,7 +437,7 @@ INT32 CalcCoverValue(SOLDIERTYPE *pMe, INT32 sMyGridNo, INT32 iMyThreat, INT32 i
|
|||||||
|
|
||||||
sDist = PythSpacesAway(sMyGridNo, sHisGridNo);
|
sDist = PythSpacesAway(sMyGridNo, sHisGridNo);
|
||||||
|
|
||||||
if( sDist < DAY_VISION_RANGE / 2 )
|
if (sDist < (INT32)(DAY_VISION_RANGE / 2))
|
||||||
{
|
{
|
||||||
ubCoverReduction = ubCoverReduction * 2 * sDist / DAY_VISION_RANGE;
|
ubCoverReduction = ubCoverReduction * 2 * sDist / DAY_VISION_RANGE;
|
||||||
}
|
}
|
||||||
@@ -888,6 +887,9 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB
|
|||||||
{
|
{
|
||||||
iCurrentCoverValue -= abs(iCurrentCoverValue) / (8-ubDiff);
|
iCurrentCoverValue -= abs(iCurrentCoverValue) / (8-ubDiff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sevenfm: penalize locations near red smoke
|
||||||
|
iCurrentCoverValue -= abs(iCurrentCoverValue) * RedSmokeDanger(pSoldier->sGridNo, pSoldier->pathing.bLevel) / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUGCOVER
|
#ifdef DEBUGCOVER
|
||||||
@@ -1027,7 +1029,7 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sevenfm: avoid tiles near bombs
|
// sevenfm: avoid tiles near bombs
|
||||||
if( FindBombNearby(pSoldier, sGridNo, DAY_VISION_RANGE / 8))
|
if (FindBombNearby(pSoldier, sGridNo, BOMB_DETECTION_RANGE))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1046,6 +1048,15 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// avoid moving into red smoke
|
||||||
|
if (gGameExternalOptions.fAIBetterCover &&
|
||||||
|
RedSmokeDanger(sGridNo, pSoldier->pathing.bLevel) &&
|
||||||
|
!RedSmokeDanger(pSoldier->sGridNo, pSoldier->pathing.bLevel))
|
||||||
|
{
|
||||||
|
//DebugCover(pSoldier, String("moving into red smoke, skip"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
iPathCost = gubAIPathCosts[AI_PATHCOST_RADIUS + sXOffset][AI_PATHCOST_RADIUS + sYOffset];
|
iPathCost = gubAIPathCosts[AI_PATHCOST_RADIUS + sXOffset][AI_PATHCOST_RADIUS + sYOffset];
|
||||||
/*
|
/*
|
||||||
// water is OK, if the only good hiding place requires us to get wet, OK
|
// water is OK, if the only good hiding place requires us to get wet, OK
|
||||||
@@ -1134,6 +1145,9 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB
|
|||||||
{
|
{
|
||||||
iCoverValue -= abs(iCoverValue) / (8-ubDiff);
|
iCoverValue -= abs(iCoverValue) / (8-ubDiff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sevenfm: penalize locations near red smoke
|
||||||
|
iCoverValue -= abs(iCoverValue) * RedSmokeDanger(sGridNo, pSoldier->pathing.bLevel) / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( fNight && !( InARoom( sGridNo, NULL ) ) ) // ignore in buildings in case placed there
|
if ( fNight && !( InARoom( sGridNo, NULL ) ) ) // ignore in buildings in case placed there
|
||||||
@@ -1496,6 +1510,12 @@ INT32 FindSpotMaxDistFromOpponents(SOLDIERTYPE *pSoldier)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sevenfm: avoid red smoke
|
||||||
|
if (RedSmokeDanger(sGridNo, pSoldier->pathing.bLevel))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// OK, this place shows potential. How useful is it as cover?
|
// OK, this place shows potential. How useful is it as cover?
|
||||||
//NumMessage("Promising seems gridno #",gridno);
|
//NumMessage("Promising seems gridno #",gridno);
|
||||||
|
|
||||||
@@ -1561,35 +1581,34 @@ INT32 FindSpotMaxDistFromOpponents(SOLDIERTYPE *pSoldier)
|
|||||||
|
|
||||||
INT32 FindNearestUngassedLand(SOLDIERTYPE *pSoldier)
|
INT32 FindNearestUngassedLand(SOLDIERTYPE *pSoldier)
|
||||||
{
|
{
|
||||||
INT32 sGridNo,sClosestLand = NOWHERE,sPathCost,sShortestPath = 1000;
|
INT32 sGridNo, sClosestLand = NOWHERE, sPathCost, sShortestPath = 1000;
|
||||||
INT16 sMaxLeft,sMaxRight,sMaxUp,sMaxDown,sXOffset,sYOffset;
|
INT16 sMaxLeft, sMaxRight, sMaxUp, sMaxDown, sXOffset, sYOffset;
|
||||||
INT32 iSearchRange;
|
INT32 iSearchRange;
|
||||||
|
INT16 sDistance, sOriginalDistance;
|
||||||
|
UINT16 usMovementMode = DetermineMovementMode(pSoldier, AI_ACTION_LEAVE_WATER_GAS);
|
||||||
|
|
||||||
//NameMessage(pSoldier,"looking for nearest reachable land");
|
sOriginalDistance = DistanceToClosestActiveOpponent(pSoldier, pSoldier->sGridNo);
|
||||||
|
|
||||||
// start with a small search area, and expand it if we're unsuccessful
|
// start with a small search area, and expand it if we're unsuccessful
|
||||||
// this should almost never need to search farther than 5 or 10 squares...
|
// this should almost never need to search farther than 5 or 10 squares...
|
||||||
for (iSearchRange = 5; iSearchRange <= 25; iSearchRange += 5)
|
for (iSearchRange = 5; iSearchRange <= 25; iSearchRange += 10)
|
||||||
{
|
{
|
||||||
//NumMessage("Trying iSearchRange = ", iSearchRange);
|
//NumMessage("Trying iSearchRange = ", iSearchRange);
|
||||||
|
|
||||||
// determine maximum horizontal limits
|
// determine maximum horizontal limits
|
||||||
sMaxLeft = min(iSearchRange,(pSoldier->sGridNo % MAXCOL));
|
sMaxLeft = min(iSearchRange, (pSoldier->sGridNo % MAXCOL));
|
||||||
//NumMessage("sMaxLeft = ",sMaxLeft);
|
//NumMessage("sMaxLeft = ",sMaxLeft);
|
||||||
sMaxRight = min(iSearchRange,MAXCOL - ((pSoldier->sGridNo % MAXCOL) + 1));
|
sMaxRight = min(iSearchRange, MAXCOL - ((pSoldier->sGridNo % MAXCOL) + 1));
|
||||||
//NumMessage("sMaxRight = ",sMaxRight);
|
//NumMessage("sMaxRight = ",sMaxRight);
|
||||||
|
|
||||||
// determine maximum vertical limits
|
// determine maximum vertical limits
|
||||||
sMaxUp = min(iSearchRange,(pSoldier->sGridNo / MAXROW));
|
sMaxUp = min(iSearchRange, (pSoldier->sGridNo / MAXROW));
|
||||||
//NumMessage("sMaxUp = ",sMaxUp);
|
//NumMessage("sMaxUp = ",sMaxUp);
|
||||||
sMaxDown = min(iSearchRange,MAXROW - ((pSoldier->sGridNo / MAXROW) + 1));
|
sMaxDown = min(iSearchRange, MAXROW - ((pSoldier->sGridNo / MAXROW) + 1));
|
||||||
//NumMessage("sMaxDown = ",sMaxDown);
|
//NumMessage("sMaxDown = ",sMaxDown);
|
||||||
|
|
||||||
// Call FindBestPath to set flags in all locations that we can
|
// Call FindBestPath to set flags in all locations that we can
|
||||||
// walk into within range. We have to set some things up first...
|
// walk into within range. We have to set some things up first...
|
||||||
|
|
||||||
// set the distance limit of the square region
|
|
||||||
gubNPCDistLimit = (UINT8) iSearchRange;
|
|
||||||
|
|
||||||
// reset the "reachable" flags in the region we're looking at
|
// reset the "reachable" flags in the region we're looking at
|
||||||
for (sYOffset = -sMaxUp; sYOffset <= sMaxDown; sYOffset++)
|
for (sYOffset = -sMaxUp; sYOffset <= sMaxDown; sYOffset++)
|
||||||
@@ -1597,7 +1616,7 @@ INT32 FindNearestUngassedLand(SOLDIERTYPE *pSoldier)
|
|||||||
for (sXOffset = -sMaxLeft; sXOffset <= sMaxRight; sXOffset++)
|
for (sXOffset = -sMaxLeft; sXOffset <= sMaxRight; sXOffset++)
|
||||||
{
|
{
|
||||||
sGridNo = pSoldier->sGridNo + sXOffset + (MAXCOL * sYOffset);
|
sGridNo = pSoldier->sGridNo + sXOffset + (MAXCOL * sYOffset);
|
||||||
if ( !(sGridNo >=0 && sGridNo < WORLD_MAX) )
|
if (!(sGridNo >= 0 && sGridNo < WORLD_MAX))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1606,7 +1625,11 @@ INT32 FindNearestUngassedLand(SOLDIERTYPE *pSoldier)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FindBestPath( pSoldier, GRIDSIZE, pSoldier->pathing.bLevel, DetermineMovementMode( pSoldier, AI_ACTION_LEAVE_WATER_GAS ), COPYREACHABLE, 0 );//dnl ch50 071009
|
gubNPCAPBudget = pSoldier->bActionPoints;
|
||||||
|
gubNPCDistLimit = (UINT8)iSearchRange;
|
||||||
|
FindBestPath(pSoldier, GRIDSIZE, pSoldier->pathing.bLevel, usMovementMode, COPYREACHABLE, 0); //dnl ch50 071009
|
||||||
|
gubNPCAPBudget = 0;
|
||||||
|
gubNPCDistLimit = 0;
|
||||||
|
|
||||||
// Turn off the "reachable" flag for his current location
|
// Turn off the "reachable" flag for his current location
|
||||||
// so we don't consider it
|
// so we don't consider it
|
||||||
@@ -1620,7 +1643,7 @@ INT32 FindNearestUngassedLand(SOLDIERTYPE *pSoldier)
|
|||||||
// calculate the next potential gridno
|
// calculate the next potential gridno
|
||||||
sGridNo = pSoldier->sGridNo + sXOffset + (MAXCOL * sYOffset);
|
sGridNo = pSoldier->sGridNo + sXOffset + (MAXCOL * sYOffset);
|
||||||
//NumMessage("Testing gridno #",gridno);
|
//NumMessage("Testing gridno #",gridno);
|
||||||
if ( !(sGridNo >=0 && sGridNo < WORLD_MAX) )
|
if (!(sGridNo >= 0 && sGridNo < WORLD_MAX))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1631,7 +1654,31 @@ INT32 FindNearestUngassedLand(SOLDIERTYPE *pSoldier)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ignore blacklisted spot
|
// ignore blacklisted spot
|
||||||
if ( sGridNo == pSoldier->pathing.sBlackList )
|
if (sGridNo == pSoldier->pathing.sBlackList)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sevenfm: check for gas
|
||||||
|
if (InGas(pSoldier, sGridNo))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for deep water
|
||||||
|
if (DeepWater(pSoldier->sGridNo, pSoldier->pathing.bLevel))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for bombs nearby
|
||||||
|
if (FindBombNearby(pSoldier, sGridNo, BOMB_DETECTION_RANGE))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for red smoke
|
||||||
|
if (RedSmokeDanger(sGridNo, pSoldier->pathing.bLevel) > 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1642,16 +1689,39 @@ INT32 FindNearestUngassedLand(SOLDIERTYPE *pSoldier)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check for red smoke
|
||||||
|
if (RedSmokeDanger(sGridNo, pSoldier->pathing.bLevel) > 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// CJC: here, unfortunately, we must calculate a path so we have an AP cost
|
// CJC: here, unfortunately, we must calculate a path so we have an AP cost
|
||||||
|
|
||||||
// obviously, we're looking for LAND, so water is out!
|
// obviously, we're looking for LAND, so water is out!
|
||||||
sPathCost = LegalNPCDestination(pSoldier,sGridNo,ENSURE_PATH_COST,NOWATER,0);
|
//sPathCost = LegalNPCDestination(pSoldier,sGridNo,ENSURE_PATH_COST,NOWATER,0);
|
||||||
|
|
||||||
if (!sPathCost)
|
if (!LegalNPCDestination(pSoldier, sGridNo, IGNORE_PATH, NOWATER, 0))
|
||||||
{
|
{
|
||||||
continue; // skip on to the next potential grid
|
continue; // skip on to the next potential grid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sPathCost = PlotPath(pSoldier, sGridNo, FALSE, FALSE, FALSE, usMovementMode, pSoldier->bStealthMode, pSoldier->bReverse, 0);
|
||||||
|
|
||||||
|
// check if spot is reachable
|
||||||
|
if(sPathCost == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sDistance = DistanceToClosestActiveOpponent(pSoldier, pSoldier->sGridNo);
|
||||||
|
|
||||||
|
// penalty if moving closer to enemy
|
||||||
|
if (sDistance >= 0 && sOriginalDistance >= 0 && sDistance < sOriginalDistance)
|
||||||
|
{
|
||||||
|
//sPathCost += APBPConstants[AP_MAXIMUM];
|
||||||
|
sPathCost += (sOriginalDistance - sDistance) * (APBPConstants[AP_MOVEMENT_FLAT] + APBPConstants[AP_MODIFIER_WALK]);
|
||||||
|
}
|
||||||
|
|
||||||
// if this path is shorter than the one to the closest land found so far
|
// if this path is shorter than the one to the closest land found so far
|
||||||
if (sPathCost < sShortestPath)
|
if (sPathCost < sShortestPath)
|
||||||
{
|
{
|
||||||
@@ -1674,49 +1744,47 @@ INT32 FindNearestUngassedLand(SOLDIERTYPE *pSoldier)
|
|||||||
return(sClosestLand);
|
return(sClosestLand);
|
||||||
}
|
}
|
||||||
|
|
||||||
INT32 FindNearbyDarkerSpot( SOLDIERTYPE *pSoldier )
|
INT32 FindNearbyDarkerSpot(SOLDIERTYPE *pSoldier)
|
||||||
{
|
{
|
||||||
INT32 sGridNo, sClosestSpot = NOWHERE, sPathCost;
|
INT32 sGridNo, sClosestSpot = NOWHERE, sPathCost;
|
||||||
INT32 iSpotValue, iBestSpotValue = 1000;
|
INT32 iSpotValue, iBestSpotValue = 1000;
|
||||||
INT16 sMaxLeft,sMaxRight,sMaxUp,sMaxDown,sXOffset,sYOffset;
|
INT16 sMaxLeft, sMaxRight, sMaxUp, sMaxDown, sXOffset, sYOffset;
|
||||||
INT32 iSearchRange;
|
INT32 iSearchRange;
|
||||||
INT8 bLightLevel, bCurrLightLevel, bLightDiff;
|
INT8 bLightLevel, bCurrLightLevel, bLightDiff;
|
||||||
INT32 iRoamRange;
|
INT32 iRoamRange;
|
||||||
INT32 sOrigin;
|
INT32 sOrigin;
|
||||||
|
UINT16 usMovementMode = DetermineMovementMode(pSoldier, AI_ACTION_LEAVE_WATER_GAS);
|
||||||
|
|
||||||
bCurrLightLevel = LightTrueLevel( pSoldier->sGridNo, pSoldier->pathing.bLevel );
|
bCurrLightLevel = LightTrueLevel(pSoldier->sGridNo, pSoldier->pathing.bLevel);
|
||||||
|
|
||||||
iRoamRange = RoamingRange( pSoldier, &sOrigin );
|
iRoamRange = RoamingRange(pSoldier, &sOrigin);
|
||||||
|
|
||||||
// start with a small search area, and expand it if we're unsuccessful
|
// start with a small search area, and expand it if we're unsuccessful
|
||||||
// this should almost never need to search farther than 5 or 10 squares...
|
// this should almost never need to search farther than 5 or 10 squares...
|
||||||
for (iSearchRange = 5; iSearchRange <= 15; iSearchRange += 5)
|
for (iSearchRange = 5; iSearchRange <= 15; iSearchRange += 5)
|
||||||
{
|
{
|
||||||
// determine maximum horizontal limits
|
// determine maximum horizontal limits
|
||||||
sMaxLeft = min(iSearchRange,(pSoldier->sGridNo % MAXCOL));
|
sMaxLeft = min(iSearchRange, (pSoldier->sGridNo % MAXCOL));
|
||||||
//NumMessage("sMaxLeft = ",sMaxLeft);
|
//NumMessage("sMaxLeft = ",sMaxLeft);
|
||||||
sMaxRight = min(iSearchRange,MAXCOL - ((pSoldier->sGridNo % MAXCOL) + 1));
|
sMaxRight = min(iSearchRange, MAXCOL - ((pSoldier->sGridNo % MAXCOL) + 1));
|
||||||
//NumMessage("sMaxRight = ",sMaxRight);
|
//NumMessage("sMaxRight = ",sMaxRight);
|
||||||
|
|
||||||
// determine maximum vertical limits
|
// determine maximum vertical limits
|
||||||
sMaxUp = min(iSearchRange,(pSoldier->sGridNo / MAXROW));
|
sMaxUp = min(iSearchRange, (pSoldier->sGridNo / MAXROW));
|
||||||
//NumMessage("sMaxUp = ",sMaxUp);
|
//NumMessage("sMaxUp = ",sMaxUp);
|
||||||
sMaxDown = min(iSearchRange,MAXROW - ((pSoldier->sGridNo / MAXROW) + 1));
|
sMaxDown = min(iSearchRange, MAXROW - ((pSoldier->sGridNo / MAXROW) + 1));
|
||||||
//NumMessage("sMaxDown = ",sMaxDown);
|
//NumMessage("sMaxDown = ",sMaxDown);
|
||||||
|
|
||||||
// Call FindBestPath to set flags in all locations that we can
|
// Call FindBestPath to set flags in all locations that we can
|
||||||
// walk into within range. We have to set some things up first...
|
// walk into within range. We have to set some things up first...
|
||||||
|
|
||||||
// set the distance limit of the square region
|
|
||||||
gubNPCDistLimit = (UINT8) iSearchRange;
|
|
||||||
|
|
||||||
// reset the "reachable" flags in the region we're looking at
|
// reset the "reachable" flags in the region we're looking at
|
||||||
for (sYOffset = -sMaxUp; sYOffset <= sMaxDown; sYOffset++)
|
for (sYOffset = -sMaxUp; sYOffset <= sMaxDown; sYOffset++)
|
||||||
{
|
{
|
||||||
for (sXOffset = -sMaxLeft; sXOffset <= sMaxRight; sXOffset++)
|
for (sXOffset = -sMaxLeft; sXOffset <= sMaxRight; sXOffset++)
|
||||||
{
|
{
|
||||||
sGridNo = pSoldier->sGridNo + sXOffset + (MAXCOL * sYOffset);
|
sGridNo = pSoldier->sGridNo + sXOffset + (MAXCOL * sYOffset);
|
||||||
if ( !(sGridNo >=0 && sGridNo < WORLD_MAX) )
|
if (!(sGridNo >= 0 && sGridNo < WORLD_MAX))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1725,7 +1793,11 @@ INT32 FindNearbyDarkerSpot( SOLDIERTYPE *pSoldier )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FindBestPath( pSoldier, GRIDSIZE, pSoldier->pathing.bLevel, DetermineMovementMode( pSoldier, AI_ACTION_LEAVE_WATER_GAS ), COPYREACHABLE, 0 );//dnl ch50 071009
|
gubNPCAPBudget = pSoldier->bActionPoints;
|
||||||
|
gubNPCDistLimit = (UINT8)iSearchRange;
|
||||||
|
FindBestPath(pSoldier, GRIDSIZE, pSoldier->pathing.bLevel, usMovementMode, COPYREACHABLE, 0); //dnl ch50 071009
|
||||||
|
gubNPCAPBudget = 0;
|
||||||
|
gubNPCDistLimit = 0;
|
||||||
|
|
||||||
// Turn off the "reachable" flag for his current location
|
// Turn off the "reachable" flag for his current location
|
||||||
// so we don't consider it
|
// so we don't consider it
|
||||||
@@ -1739,7 +1811,7 @@ INT32 FindNearbyDarkerSpot( SOLDIERTYPE *pSoldier )
|
|||||||
// calculate the next potential gridno
|
// calculate the next potential gridno
|
||||||
sGridNo = pSoldier->sGridNo + sXOffset + (MAXCOL * sYOffset);
|
sGridNo = pSoldier->sGridNo + sXOffset + (MAXCOL * sYOffset);
|
||||||
//NumMessage("Testing gridno #",gridno);
|
//NumMessage("Testing gridno #",gridno);
|
||||||
if ( !(sGridNo >=0 && sGridNo < WORLD_MAX) )
|
if (!(sGridNo >= 0 && sGridNo < WORLD_MAX))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1750,7 +1822,18 @@ INT32 FindNearbyDarkerSpot( SOLDIERTYPE *pSoldier )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ignore blacklisted spot
|
// ignore blacklisted spot
|
||||||
if ( sGridNo == pSoldier->pathing.sBlackList )
|
if (sGridNo == pSoldier->pathing.sBlackList)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// require this character to stay within their roam range
|
||||||
|
if (PythSpacesAway(sOrigin, sGridNo) > iRoamRange)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FindBombNearby(pSoldier, sGridNo, BOMB_DETECTION_RANGE))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1761,29 +1844,35 @@ INT32 FindNearbyDarkerSpot( SOLDIERTYPE *pSoldier )
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// require this character to stay within their roam range
|
if (RedSmokeDanger(sGridNo, pSoldier->pathing.bLevel))
|
||||||
if ( PythSpacesAway( sOrigin, sGridNo ) > iRoamRange )
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// screen out anything brighter than our current best spot
|
// screen out anything brighter than our current best spot
|
||||||
bLightLevel = LightTrueLevel( sGridNo, pSoldier->pathing.bLevel );
|
bLightLevel = LightTrueLevel(sGridNo, pSoldier->pathing.bLevel);
|
||||||
|
|
||||||
//bLightDiff = gbLightSighting[0][ bCurrLightLevel ] - gbLightSighting[0][ bLightLevel ];
|
//bLightDiff = gbLightSighting[0][ bCurrLightLevel ] - gbLightSighting[0][ bLightLevel ];
|
||||||
bLightDiff = gGameExternalOptions.ubBrightnessVisionMod[ bCurrLightLevel ] - gGameExternalOptions.ubBrightnessVisionMod[ bLightLevel ];
|
bLightDiff = gGameExternalOptions.ubBrightnessVisionMod[bCurrLightLevel] - gGameExternalOptions.ubBrightnessVisionMod[bLightLevel];
|
||||||
// if the spot is darker than our current location, then bLightDiff > 0
|
// if the spot is darker than our current location, then bLightDiff > 0
|
||||||
// plus ignore differences of just 1 light level
|
// plus ignore differences of just 1 light level
|
||||||
if ( bLightDiff <= 1 )
|
if (bLightDiff <= 1)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CJC: here, unfortunately, we must calculate a path so we have an AP cost
|
// CJC: here, unfortunately, we must calculate a path so we have an AP cost
|
||||||
|
//sPathCost = LegalNPCDestination(pSoldier,sGridNo,ENSURE_PATH_COST,NOWATER,0);
|
||||||
|
|
||||||
sPathCost = LegalNPCDestination(pSoldier,sGridNo,ENSURE_PATH_COST,NOWATER,0);
|
if (!LegalNPCDestination(pSoldier, sGridNo, IGNORE_PATH, NOWATER, 0))
|
||||||
|
{
|
||||||
|
continue; // skip on to the next potential grid
|
||||||
|
}
|
||||||
|
|
||||||
if (!sPathCost)
|
sPathCost = PlotPath(pSoldier, sGridNo, FALSE, FALSE, FALSE, usMovementMode, pSoldier->bStealthMode, pSoldier->bReverse, 0);
|
||||||
|
|
||||||
|
// check if spot is reachable
|
||||||
|
if (sPathCost == 0)
|
||||||
{
|
{
|
||||||
continue; // skip on to the next potential grid
|
continue; // skip on to the next potential grid
|
||||||
}
|
}
|
||||||
@@ -1791,7 +1880,7 @@ INT32 FindNearbyDarkerSpot( SOLDIERTYPE *pSoldier )
|
|||||||
// decrease the "cost" of the spot by the amount of light/darkness
|
// decrease the "cost" of the spot by the amount of light/darkness
|
||||||
iSpotValue = sPathCost * 2 - bLightDiff;
|
iSpotValue = sPathCost * 2 - bLightDiff;
|
||||||
|
|
||||||
if ( iSpotValue < iBestSpotValue )
|
if (iSpotValue < iBestSpotValue)
|
||||||
{
|
{
|
||||||
// remember it instead
|
// remember it instead
|
||||||
iBestSpotValue = iSpotValue;
|
iBestSpotValue = iSpotValue;
|
||||||
@@ -2676,7 +2765,8 @@ INT32 FindFlankingSpot(SOLDIERTYPE *pSoldier, INT32 sPos, INT8 bAction )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sevenfm: don't go into deep water for flanking
|
// sevenfm: don't go into deep water for flanking
|
||||||
if( DeepWater( sGridNo, pSoldier->pathing.bLevel ) )
|
if (DeepWater(sGridNo, pSoldier->pathing.bLevel) &&
|
||||||
|
!DeepWater(pSoldier->sGridNo, pSoldier->pathing.bLevel))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2695,14 +2785,24 @@ INT32 FindFlankingSpot(SOLDIERTYPE *pSoldier, INT32 sPos, INT8 bAction )
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sevenfm: skip buildings if not in building already, because soldiers often run into buildings and stop flanking
|
||||||
|
if (InARoom(sGridNo, NULL) && !InARoom(pSoldier->sGridNo, NULL))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// sevenfm: penalize locations near fresh corpses
|
// sevenfm: penalize locations near fresh corpses
|
||||||
if( GetNearestRottingCorpseAIWarning( sGridNo ) > 0 )
|
if( GetNearestRottingCorpseAIWarning( sGridNo ) > 0 )
|
||||||
{
|
{
|
||||||
sTempDist = sTempDist / 2;
|
sTempDist = sTempDist / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FindBombNearby(pSoldier, sGridNo, BOMB_DETECTION_RANGE))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sevenfm: skip buildings if not in building already, because soldiers often run into buildings and stop flanking
|
if (RedSmokeDanger(sGridNo, pSoldier->pathing.bLevel))
|
||||||
if( InARoom( sGridNo, NULL ) && !InARoom(pSoldier->sGridNo, NULL) )
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -297,6 +297,12 @@ BOOLEAN ProneSightCoverAtSpot( SOLDIERTYPE *pSoldier, INT32 sSpot );
|
|||||||
BOOLEAN SightCoverAtSpot( SOLDIERTYPE *pSoldier, INT32 sSpot );
|
BOOLEAN SightCoverAtSpot( SOLDIERTYPE *pSoldier, INT32 sSpot );
|
||||||
|
|
||||||
BOOLEAN FindBombNearby( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubDistance );
|
BOOLEAN FindBombNearby( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubDistance );
|
||||||
|
UINT8 RedSmokeDanger(INT32 sGridNo, INT8 bLevel);
|
||||||
|
BOOLEAN CheckArtilleryStrike(void);
|
||||||
|
BOOLEAN CheckRoof(INT32 sGridNo);
|
||||||
|
UINT8 TerrainDensity(INT32 sSpot, INT8 bLevel, UINT8 ubDistance, BOOLEAN fGrass);
|
||||||
|
INT16 DistanceToClosestActiveOpponent(SOLDIERTYPE *pSoldier, INT32 sSpot);
|
||||||
|
BOOLEAN ValidOpponent(SOLDIERTYPE* pSoldier, SOLDIERTYPE* pOpponent);
|
||||||
|
|
||||||
BOOLEAN AnyCoverFromSpot( INT32 sSpot, INT8 bLevel, INT32 sThreatLoc, INT8 bThreatLevel );
|
BOOLEAN AnyCoverFromSpot( INT32 sSpot, INT8 bLevel, INT32 sThreatLoc, INT8 bThreatLevel );
|
||||||
UINT8 CountSeenEnemiesLastTurn( SOLDIERTYPE *pSoldier );
|
UINT8 CountSeenEnemiesLastTurn( SOLDIERTYPE *pSoldier );
|
||||||
@@ -320,5 +326,6 @@ BOOLEAN SoldierAI(SOLDIERTYPE *pSoldier);
|
|||||||
|
|
||||||
// sevenfm: distance for tactical AI checks, roughly equal to normal day vision range
|
// sevenfm: distance for tactical AI checks, roughly equal to normal day vision range
|
||||||
#define TACTICAL_RANGE (gGameExternalOptions.ubStraightSightRange * STRAIGHT_RATIO * 2)
|
#define TACTICAL_RANGE (gGameExternalOptions.ubStraightSightRange * STRAIGHT_RATIO * 2)
|
||||||
|
#define BOMB_DETECTION_RANGE (TACTICAL_RANGE / 4)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user