Merge branch 'master' into decideaction

This commit is contained in:
Asdow
2025-12-25 18:58:41 +02:00
853 changed files with 134439 additions and 148932 deletions
+20 -20
View File
@@ -130,20 +130,20 @@ typedef struct
class ATTACKTYPE
{
public:
UINT8 ubPossible; // is this attack form possible
UINT8 ubOpponent; // which soldier is the victim
UINT8 ubPossible; // is this attack form possible
SoldierID ubOpponent; // which soldier is the victim
//CHANGED STRUCTURE VALUE BY GOTTHARD 7/14/07
INT16 ubAimTime; // how many extra APs to spend on aiming
INT16 ubChanceToReallyHit; // chance to hit * chance to get through cover
INT16 ubAimTime; // how many extra APs to spend on aiming
INT16 ubChanceToReallyHit; // chance to hit * chance to get through cover
//END STRUCTURE CHANGE BY GOTTHARD 7/14/07
INT16 ubAPCost; // how many APs the attack will use up
INT32 iAttackValue; // relative worthiness of this type of attack
INT32 sTarget; // target gridno of this attack
INT8 bTargetLevel; // target level of this attack
INT8 bWeaponIn; // the inv slot of the weapon in question
INT8 bScopeMode; // SANDRO: added for scope mode and alternative weapon holding
UINT8 ubStance; // recommended stance for attack
UINT8 ubFriendlyFireChance; // highest chance to hit someone of our guys //dnl ch61 180813
INT16 ubAPCost; // how many APs the attack will use up
INT32 iAttackValue; // relative worthiness of this type of attack
INT32 sTarget; // target gridno of this attack
INT8 bTargetLevel; // target level of this attack
INT8 bWeaponIn; // the inv slot of the weapon in question
INT8 bScopeMode; // SANDRO: added for scope mode and alternative weapon holding
UINT8 ubStance; // recommended stance for attack
UINT8 ubFriendlyFireChance; // highest chance to hit someone of our guys //dnl ch61 180813
ATTACKTYPE(void){ InitAttackType(this); }
void InitAttackType(ATTACKTYPE *pAttack);
@@ -154,14 +154,14 @@ public:
class UnderFire
{
private:
BOOLEAN fEnable;
UINT16 usUnderFireCnt;
UINT16 usUnderFireID[MAXUNDERFIRE];
UINT8 ubUnderFireCTH[MAXUNDERFIRE];
BOOLEAN fEnable;
UINT16 usUnderFireCnt;
SoldierID usUnderFireID[MAXUNDERFIRE];
UINT8 ubUnderFireCTH[MAXUNDERFIRE];
public:
UnderFire(void){ Clear(); fEnable = FALSE; }
void Clear(void);
void Add(UINT16 usID, UINT8 ubCTH);
void Add(SoldierID usID, UINT8 ubCTH);
void Enable(void){ fEnable=TRUE; }
void Disable(void){ fEnable=FALSE; }
UINT16 GetUnderFireCnt(void){ return(usUnderFireCnt); }
@@ -211,7 +211,7 @@ void CreatureDecideAlertStatus( SOLDIERTYPE *pCreature );
// sevenfm:
void CheckTossSelfSmoke(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow);
void CheckTossFriendSmoke(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow);
void CheckTossAt(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow, INT32 sTargetSpot, INT8 bTargetLevel, UINT8 ubOpponentID);
void CheckTossAt(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow, INT32 sTargetSpot, INT8 bTargetLevel, SoldierID ubOpponentID);
INT32 FindTossSpotInDirection(INT32 sSpot, INT8 bLevel, INT32 sTargetSpot, BOOLEAN fCheckAdjacentDirections, BOOLEAN fCheckFarther);
void CheckTossGrenadeAt(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow, INT32 sTargetSpot, INT8 bTargetLevel, UINT8 ubGrenadeType);
@@ -252,7 +252,7 @@ INT32 InternalGoAsFarAsPossibleTowards(SOLDIERTYPE *pSoldier, INT32 sDesGrid, IN
int LegalNPCDestination(SOLDIERTYPE *pSoldier, INT32 sGridno, UINT8 ubPathMode, UINT8 ubWaterOK, UINT8 fFlags);
void LoadWeaponIfNeeded(SOLDIERTYPE *pSoldier);
INT32 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN * pfClimbingNecessary, BOOLEAN * pfReachable );
INT32 NPCConsiderInitiatingConv( SOLDIERTYPE * pNPC, UINT8 * pubDesiredMerc );
INT32 NPCConsiderInitiatingConv( SOLDIERTYPE * pNPC, SoldierID * pubDesiredMerc );
void NPCDoesAct(SOLDIERTYPE *pSoldier);
void NPCDoesNothing(SOLDIERTYPE *pSoldier);
INT8 OKToAttack(SOLDIERTYPE *ptr, int target);
@@ -316,7 +316,7 @@ BOOLEAN GetBestAoEGridNo(SOLDIERTYPE *pSoldier, INT32* pGridNo, INT16 aRadius, U
// Get the ID of the farthest opponent we can see, with an optional minimum range
// puID - ID of the farthest opponent pSoldier can see
// sRange - only return true and give an idea if opponent found is further away than this
BOOLEAN GetFarthestOpponent(SOLDIERTYPE *pSoldier, UINT8* puID, INT16 sRange);
BOOLEAN GetFarthestOpponent(SOLDIERTYPE *pSoldier, SoldierID *puID, INT16 sRange);
// are there more allies than friends in adjacent sectors?
BOOLEAN MoreFriendsThanEnemiesinNearbysectors(UINT8 ausTeam, INT16 aX, INT16 aY, INT8 aZ);
+20 -20
View File
@@ -12,7 +12,7 @@
#include "AIList.h"
#include "Overhead.h"
#include "debug.h"
#include "DEBUG.H"
#include "AIInternals.h"
#include "ai.h"
#include "opplist.h"
@@ -25,11 +25,11 @@
AILIST gAIList[ AI_LIST_SIZE ];
AILIST * gpFirstAIListEntry = NULL;
BOOLEAN SatisfiesAIListConditions( SOLDIERTYPE * pSoldier, UINT8 * pubDoneCount, BOOLEAN fDoRandomChecks );
BOOLEAN SatisfiesAIListConditions( SOLDIERTYPE * pSoldier, UINT16 * pubDoneCount, BOOLEAN fDoRandomChecks );
void ClearAIList( void )
{
UINT8 ubLoop;
UINT16 ubLoop;
for ( ubLoop = 0; ubLoop < AI_LIST_SIZE; ubLoop++ )
{
@@ -47,9 +47,9 @@ void DeleteAIListEntry( AILIST * pEntry )
pEntry->pNext = NULL;
}
UINT8 FindEmptyAIListEntry( void )
SoldierID FindEmptyAIListEntry( void )
{
UINT8 ubLoop;
UINT16 ubLoop;
for ( ubLoop = 0; ubLoop < AI_LIST_SIZE; ubLoop++ )
{
@@ -62,7 +62,7 @@ UINT8 FindEmptyAIListEntry( void )
return( AI_LIST_SIZE );
}
AILIST * CreateNewAIListEntry( UINT8 ubNewEntry, UINT8 ubID, INT8 bPriority )
AILIST * CreateNewAIListEntry( UINT16 ubNewEntry, SoldierID ubID, INT8 bPriority )
{
gAIList[ ubNewEntry ].ubID = ubID;
gAIList[ ubNewEntry ].bPriority = bPriority;
@@ -70,10 +70,10 @@ AILIST * CreateNewAIListEntry( UINT8 ubNewEntry, UINT8 ubID, INT8 bPriority )
return( &(gAIList[ ubNewEntry ]) );
}
UINT8 RemoveFirstAIListEntry( void )
SoldierID RemoveFirstAIListEntry( void )
{
AILIST * pOldFirstEntry;
UINT8 ubID;
AILIST *pOldFirstEntry;
SoldierID ubID;
while ( gpFirstAIListEntry != NULL)
{
@@ -86,7 +86,7 @@ UINT8 RemoveFirstAIListEntry( void )
DeleteAIListEntry( pOldFirstEntry );
// make sure conditions still met
if ( SatisfiesAIListConditions( MercPtrs[ ubID ], NULL, FALSE ) )
if ( SatisfiesAIListConditions( ubID, NULL, FALSE ) )
{
return( ubID );
}
@@ -95,7 +95,7 @@ UINT8 RemoveFirstAIListEntry( void )
return( NOBODY );
}
void RemoveAIListEntryForID( UINT8 ubID )
void RemoveAIListEntryForID( SoldierID ubID )
{
AILIST * pEntry;
AILIST * pPrevEntry;
@@ -124,9 +124,9 @@ void RemoveAIListEntryForID( UINT8 ubID )
// none found, that's okay
}
BOOLEAN InsertIntoAIList( UINT8 ubID, INT8 bPriority )
BOOLEAN InsertIntoAIList( SoldierID ubID, INT8 bPriority )
{
UINT8 ubNewEntry;
SoldierID ubNewEntry;
AILIST * pEntry, * pNewEntry, * pPrevEntry = NULL;
ubNewEntry = FindEmptyAIListEntry();
@@ -179,7 +179,7 @@ BOOLEAN InsertIntoAIList( UINT8 ubID, INT8 bPriority )
return( FALSE );
}
BOOLEAN SatisfiesAIListConditions( SOLDIERTYPE * pSoldier, UINT8 * pubDoneCount, BOOLEAN fDoRandomChecks )
BOOLEAN SatisfiesAIListConditions( SOLDIERTYPE * pSoldier, UINT16 * pubDoneCount, BOOLEAN fDoRandomChecks )
{
if ( (gTacticalStatus.bBoxingState == BOXING) && !BOXER(pSoldier) )
{
@@ -277,15 +277,15 @@ BOOLEAN SatisfiesAIListConditions( SOLDIERTYPE * pSoldier, UINT8 * pubDoneCount,
return( TRUE );
}
BOOLEAN MoveToFrontOfAIList( UINT8 ubID )
BOOLEAN MoveToFrontOfAIList( SoldierID ubID )
{
// we'll have to fake this guy's alert status (in the list) to be the same as the current
// front of the list
INT8 bPriority;
UINT8 ubNewEntry;
AILIST * pNewEntry;
SoldierID ubNewEntry;
AILIST *pNewEntry;
if ( !SatisfiesAIListConditions( MercPtrs[ ubID ], NULL, FALSE ) )
if ( !SatisfiesAIListConditions( ubID, NULL, FALSE ) )
{
// can't do dat!
return( FALSE );
@@ -317,8 +317,8 @@ BOOLEAN BuildAIListForTeam( INT8 bTeam )
BOOLEAN fInsertRet;
SOLDIERTYPE * pSoldier;
BOOLEAN fRet = FALSE;
UINT8 ubCount = 0;
UINT8 ubDoneCount = 0;
UINT16 ubCount = 0;
UINT16 ubDoneCount = 0;
INT8 bPriority;
// this team is being given control so reset their muzzle flashes
+9 -9
View File
@@ -1,18 +1,18 @@
#include "Types.h"
#include "Overhead Types.h"
typedef struct AILIST
{
UINT8 ubID;
INT8 bPriority;
UINT8 ubUnused;
struct AILIST * pNext;
SoldierID ubID;
INT8 bPriority;
UINT8 ubUnused;
struct AILIST *pNext;
} AILIST;
#define MAX_AI_PRIORITY 100
extern void ClearAIList( void );
extern AILIST * CreateNewAIListEntry( UINT8 ubNewEntry, UINT8 ubID, INT8 bAlertStatus );
extern BOOLEAN InsertIntoAIList( UINT8 ubID, INT8 bAlertStatus );
extern UINT8 RemoveFirstAIListEntry( void );
extern AILIST * CreateNewAIListEntry( UINT16 ubNewEntry, SoldierID ubID, INT8 bAlertStatus );
extern BOOLEAN InsertIntoAIList( SoldierID ubID, INT8 bAlertStatus );
extern SoldierID RemoveFirstAIListEntry( void );
extern BOOLEAN BuildAIListForTeam( INT8 bTeam );
extern BOOLEAN MoveToFrontOfAIList( UINT8 ubID );
extern BOOLEAN MoveToFrontOfAIList( SoldierID ubID );
+63 -66
View File
@@ -1,25 +1,25 @@
#include "sgp.h"
#include "ai.h"
#include "Isometric Utils.h"
#include "overhead.h"
#include "Overhead.h"
#include "math.h"
#include "Event Pump.h"
#include "Soldier Control.h"
#include "Overhead Types.h"
#include "opplist.h"
#include "animation control.h"
#include "font control.h"
#include "interface.h"
#include "Animation Control.h"
#include "Font Control.h"
#include "Interface.h"
#include "screenids.h"
#include "worldman.h"
#include "pathai.h"
#include "points.h"
#include "weapons.h"
#include "items.h"
#include "PATHAI.H"
#include "Points.h"
#include "Weapons.h"
#include "Items.h"
#include "Handle Items.h"
#include "AIInternals.h"
#include "animation data.h"
#include "los.h"
#include "Animation Data.h"
#include "LOS.h"
#include "message.h"
#include "TeamTurns.h"
#include "NPC.h"
@@ -30,7 +30,7 @@
#include "Soldier Create.h"
#include "Explosion Control.h"
#include "Interactive Tiles.h"
#include "interface dialogue.h"
#include "interface Dialogue.h"
#include "Vehicles.h"
#include "renderworld.h"
#include "AIList.h"
@@ -39,13 +39,13 @@
#include "physics.h"
#include "GameSettings.h"
#include "Debug Control.h"
#include "interface panels.h"
#include "Interface Panels.h"
#include "Sound Control.h"
#include "civ quotes.h"
#include "Civ Quotes.h"
#include "Quests.h"
#include "Campaign Types.h"
#include "Queen Command.h"
#include "points.h"
#include "Points.h"
#include "Soldier Functions.h" // added by SANDRO
#include "Text.h" // sevenfm
#include "english.h" // sevenfm: for ESC key
@@ -313,7 +313,7 @@ void DebugAI( INT8 bMsgType, SOLDIERTYPE *pSoldier, STR szOutput, bool doLog, IN
sprintf(msg, "");
sprintf(buf, "[%d] (%d)", pSoldier->ubID, pSoldier->sGridNo);
sprintf(buf, "[%d] (%d)", pSoldier->ubID.i, pSoldier->sGridNo);
strcat(msg, buf);
if (pSoldier->ubProfile != NO_PROFILE)
@@ -381,7 +381,7 @@ void DebugAI( INT8 bMsgType, SOLDIERTYPE *pSoldier, STR szOutput, bool doLog, IN
// also log to individual file for selected soldier
if (pSoldier)
{
sprintf(buf, "Logs\\AI_Decisions [%d].txt", pSoldier->ubID);
sprintf(buf, "Logs\\AI_Decisions [%d].txt", pSoldier->ubID.i);
if ((DebugFile = fopen(buf, "a+t")) != NULL)
{
if (bMsgType == AI_MSG_START)
@@ -492,7 +492,7 @@ BOOLEAN InitAI( void )
// remove all individual files
CHAR8 buf[1024];
for (UINT8 cnt = 0; cnt < TOTAL_SOLDIERS; cnt++)
for (UINT16 cnt = 0; cnt < TOTAL_SOLDIERS; cnt++)
{
sprintf(buf, "Logs\\AI_Decisions [%d].txt", cnt);
remove(buf);
@@ -850,12 +850,12 @@ void HandleSoldierAI( SOLDIERTYPE *pSoldier ) // FIXME - this function is named
// display deadlock message
gfUIInDeadlock = TRUE;
gUIDeadlockedSoldier = pSoldier->ubID;
DebugAI( String("DEADLOCK soldier %d action %s ABC %d", pSoldier->ubID, gzActionStr[pSoldier->aiData.bAction], gTacticalStatus.ubAttackBusyCount ) );
DebugAI( String("DEADLOCK soldier %d action %s ABC %d", pSoldier->ubID.i, gzActionStr[pSoldier->aiData.bAction], gTacticalStatus.ubAttackBusyCount ) );
#else
// If we are in beta version, also report message!
#ifdef JA2BETAVERSION
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_ERROR, L"Aborting AI deadlock for %d. Please sent DEBUG.TXT file and SAVE.", pSoldier->ubID );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_ERROR, L"Aborting AI deadlock for %d. Please sent DEBUG.TXT file and SAVE.", pSoldier->ubID.i );
#endif
// just abort
EndAIDeadlock();
@@ -1028,8 +1028,6 @@ void HandleSoldierAI( SOLDIERTYPE *pSoldier ) // FIXME - this function is named
void EndAIGuysTurn( SOLDIERTYPE *pSoldier )
{
UINT8 ubID;
if (gfTurnBasedAI)
{
if (gTacticalStatus.uiFlags & PLAYER_TEAM_DEAD)
@@ -1039,19 +1037,21 @@ void EndAIGuysTurn( SOLDIERTYPE *pSoldier )
}
// search for any player merc to say close call quote
for ( ubID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; ubID <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubID++ )
for ( SoldierID ubID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; ubID <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ++ubID )
{
if ( OK_INSECTOR_MERC( MercPtrs[ ubID ] ) )
SOLDIERTYPE *pMerc = ubID;
if ( OK_INSECTOR_MERC( pMerc ) )
{
if ( MercPtrs[ ubID ]->flags.fCloseCall )
if ( pMerc->flags.fCloseCall )
{
if ( !gTacticalStatus.fSomeoneHit && MercPtrs[ ubID ]->bNumHitsThisTurn == 0 && !(MercPtrs[ ubID ]->usQuoteSaidExtFlags & SOLDIER_QUOTE_SAID_EXT_CLOSE_CALL) && Random( 3 ) == 0 )
if ( !gTacticalStatus.fSomeoneHit && pMerc->bNumHitsThisTurn == 0 && !(pMerc->usQuoteSaidExtFlags & SOLDIER_QUOTE_SAID_EXT_CLOSE_CALL) && Random( 3 ) == 0 )
{
// say close call quote!
TacticalCharacterDialogue( MercPtrs[ ubID ], QUOTE_CLOSE_CALL );
MercPtrs[ ubID ]->usQuoteSaidExtFlags |= SOLDIER_QUOTE_SAID_EXT_CLOSE_CALL;
TacticalCharacterDialogue( pMerc, QUOTE_CLOSE_CALL );
pMerc->usQuoteSaidExtFlags |= SOLDIER_QUOTE_SAID_EXT_CLOSE_CALL;
}
MercPtrs[ ubID ]->flags.fCloseCall = FALSE;
pMerc->flags.fCloseCall = FALSE;
}
}
}
@@ -1093,10 +1093,10 @@ void EndAIGuysTurn( SOLDIERTYPE *pSoldier )
#endif
// find the next AI guy
ubID = RemoveFirstAIListEntry();
SoldierID ubID = RemoveFirstAIListEntry();
if (ubID != NOBODY)
{
StartNPCAI( MercPtrs[ ubID ] );
StartNPCAI( ubID );
return;
}
@@ -1271,14 +1271,13 @@ void StartNPCAI(SOLDIERTYPE *pSoldier)
BOOLEAN DestNotSpokenFor(SOLDIERTYPE *pSoldier, INT32 sGridNo)
{
INT32 cnt;
SOLDIERTYPE *pOurTeam;
cnt = gTacticalStatus.Team[pSoldier->bTeam].bFirstID;
SoldierID cnt = gTacticalStatus.Team[pSoldier->bTeam].bFirstID;
// make a list of all of our team's mercs
for (pOurTeam = MercPtrs[cnt]; cnt <= gTacticalStatus.Team[pSoldier->bTeam].bLastID; cnt++,pOurTeam++)
for ( ; cnt <= gTacticalStatus.Team[pSoldier->bTeam].bLastID; ++cnt )
{
pOurTeam = cnt;
if ( pOurTeam->bActive )
{
if (pOurTeam->sGridNo == sGridNo || pOurTeam->aiData.usActionData == sGridNo)
@@ -1319,12 +1318,12 @@ INT32 FindAdjacentSpotBeside(SOLDIERTYPE *pSoldier, INT32 sGridNo)
return(sCheapestDest);
}
UINT8 GetMostThreateningOpponent( SOLDIERTYPE *pSoldier )
SoldierID GetMostThreateningOpponent( SOLDIERTYPE *pSoldier )
{
UINT32 uiLoop;
INT32 iThreatVal,iMinThreat = 30000;
SOLDIERTYPE *pTargetSoldier;
UINT8 ubTargetSoldier = NOBODY;
UINT32 uiLoop;
INT32 iThreatVal,iMinThreat = 30000;
SOLDIERTYPE *pTargetSoldier;
SoldierID ubTargetSoldier = NOBODY;
// Loop through all mercs
@@ -1408,13 +1407,10 @@ void FreeUpNPCFromPendingAction( SOLDIERTYPE *pSoldier )
}
}
void FreeUpNPCFromAttacking(UINT8 ubID)
void FreeUpNPCFromAttacking(SoldierID ubID)
{
SOLDIERTYPE *pSoldier;
pSoldier = MercPtrs[ubID];
ActionDone(pSoldier);
pSoldier->pathing.bNeedToLook = TRUE;
ActionDone(ubID);
ubID->pathing.bNeedToLook = TRUE;
}
void FreeUpNPCFromLoweringGun( SOLDIERTYPE *pSoldier )
@@ -2017,7 +2013,7 @@ UINT32 GetTankCannonIndex()
{
for ( UINT32 i = 0; i < gMAXITEMS_READ; ++i )
{
if (Item[i].cannon)
if (ItemIsCannon(i))
{
return Item[i].uiIndex;
}
@@ -2046,7 +2042,7 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
UINT16 usHandItem = pSoldier->inv[HANDPOS].usItem;
INT8 bSlot;
UINT16 usSoldierIndex; // added by SANDRO
SoldierID usSoldierIndex; // added by SANDRO
#ifdef TESTAICONTROL
if (gfTurnBasedAI || gTacticalStatus.fAutoBandageMode)
@@ -2368,23 +2364,24 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
// fall through
case AI_ACTION_FIRE_GUN: // shoot at nearby opponent
case AI_ACTION_THROW_KNIFE: // throw knife at nearby opponent
// randomly decide whether to say civ quote
if (Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_GUN )
PossiblyStartEnemyTaunt( pSoldier, TAUNT_FIRE_GUN, pSoldier->ubOppNum );
else if (Item[pSoldier->inv[HANDPOS].usItem].grenadelauncher || Item[pSoldier->inv[HANDPOS].usItem].mortar || Item[pSoldier->inv[HANDPOS].usItem].rocketlauncher )
PossiblyStartEnemyTaunt( pSoldier, TAUNT_FIRE_LAUNCHER, pSoldier->ubOppNum );
else if (pSoldier->aiData.bAction == AI_ACTION_TOSS_PROJECTILE && Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_THROWN && !Item[pSoldier->inv[HANDPOS].usItem].flare )
PossiblyStartEnemyTaunt( pSoldier, TAUNT_THROW_KNIFE, pSoldier->ubOppNum );
else if (pSoldier->aiData.bAction == AI_ACTION_KNIFE_MOVE )
{
if (Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_BLADE )
PossiblyStartEnemyTaunt( pSoldier, TAUNT_CHARGE_BLADE );
else if (Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_PUNCH )
PossiblyStartEnemyTaunt( pSoldier, TAUNT_CHARGE_HTH );
}
case AI_ACTION_THROW_KNIFE: // throw knife at nearby opponent
// randomly decide whether to say civ quote
{
UINT16 usItem = pSoldier->inv[HANDPOS].usItem;
if (Item[usItem].usItemClass == IC_GUN)
PossiblyStartEnemyTaunt(pSoldier, TAUNT_FIRE_GUN, pSoldier->ubOppNum);
else if (ItemIsGrenadeLauncher(usItem) || ItemIsMortar(usItem) || ItemIsRocketLauncher(usItem))
PossiblyStartEnemyTaunt(pSoldier, TAUNT_FIRE_LAUNCHER, pSoldier->ubOppNum);
else if (pSoldier->aiData.bAction == AI_ACTION_TOSS_PROJECTILE && Item[usItem].usItemClass == IC_THROWN && !ItemIsFlare(usItem))
PossiblyStartEnemyTaunt(pSoldier, TAUNT_THROW_KNIFE, pSoldier->ubOppNum);
else if (pSoldier->aiData.bAction == AI_ACTION_KNIFE_MOVE)
{
if (Item[usItem].usItemClass == IC_BLADE)
PossiblyStartEnemyTaunt(pSoldier, TAUNT_CHARGE_BLADE);
else if (Item[usItem].usItemClass == IC_PUNCH)
PossiblyStartEnemyTaunt(pSoldier, TAUNT_CHARGE_HTH);
}
}
// CC, ATE here - I put in some TEMP randomness...
if (!is_networked)
{
@@ -2735,7 +2732,7 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
usSoldierIndex = WhoIsThere2( pSoldier->aiData.usActionData, pSoldier->bTargetLevel);
if ( usSoldierIndex != NOBODY )
{
MercStealFromMerc( pSoldier, MercPtrs[usSoldierIndex] );
MercStealFromMerc( pSoldier, usSoldierIndex );
PossiblyStartEnemyTaunt( pSoldier, TAUNT_STEAL, usSoldierIndex );
}
@@ -2769,7 +2766,7 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
case AI_ACTION_USE_SKILL:
{
UINT8 ubID = WhoIsThere2( pSoldier->aiData.usActionData, 0 );
SoldierID ubID = WhoIsThere2( pSoldier->aiData.usActionData, 0 );
BOOLEAN result = pSoldier->UseSkill(pSoldier->usAISkillUse, pSoldier->aiData.usActionData, ubID);
+87 -95
View File
@@ -2,13 +2,13 @@
#include "Weapons.h"
#include "opplist.h"
#include "Points.h"
#include "PathAI.h"
#include "WorldMan.h"
#include "PATHAI.H"
#include "worldman.h"
#include "AIInternals.h"
#include "Items.h"
#include "message.h"
#include "los.h"
#include "assignments.h"
#include "LOS.h"
#include "Assignments.h"
#include "Soldier Functions.h"
#include "Points.h"
#include "GameSettings.h"
@@ -23,7 +23,7 @@
#include "Vehicles.h" // added by silversurfer
#include "Game Clock.h" // sevenfm
#include "Rotting Corpses.h" // sevenfm
#include "wcheck.h" // sevenfm
#include "WCheck.h" // sevenfm
#include "SmokeEffects.h" // sevenfm
#include "GameInitOptionsScreen.h"
@@ -102,7 +102,7 @@ INT8 OKToAttack(SOLDIERTYPE * pSoldier, int target)
if ( Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_GUN)
{
if ( Item[pSoldier->inv[HANDPOS].usItem].cannon )
if (ItemIsCannon(pSoldier->inv[HANDPOS].usItem))
{
// look for another tank shell ELSEWHERE IN INVENTORY
if ( FindLaunchable( pSoldier, pSoldier->inv[HANDPOS].usItem ) == NO_SLOT )
@@ -830,7 +830,8 @@ INT16 RandomFriendWithin(SOLDIERTYPE *pSoldier)
{
UINT32 uiLoop;
UINT16 usMaxDist;
UINT8 ubFriendCount, ubFriendIDs[MAXMERCS], ubFriendID;
UINT16 ubFriendCount;
SoldierID ubFriendIDs[MAXMERCS], ubFriendID;
UINT8 ubDirection;
UINT8 ubDirsLeft;
BOOLEAN fDirChecked[8];
@@ -1378,7 +1379,7 @@ INT32 ClosestReachableDisturbance(SOLDIERTYPE *pSoldier, BOOLEAN * pfChangeLevel
}
INT32 ClosestKnownOpponent(SOLDIERTYPE *pSoldier, INT32 * psGridNo, INT8 * pbLevel, UINT8 *pubOpponentID)
INT32 ClosestKnownOpponent(SOLDIERTYPE *pSoldier, INT32 * psGridNo, INT8 * pbLevel, SoldierID * pubOpponentID)
{
INT32 *psLastLoc,sGridNo, sClosestOpponent = NOWHERE;
UINT32 uiLoop;
@@ -1703,18 +1704,17 @@ INT32 ClosestPC( SOLDIERTYPE *pSoldier, INT32 * psDistance )
// NOTE: skips EPCs!
UINT8 ubLoop;
SOLDIERTYPE *pTargetSoldier;
INT32 sMinDist = WORLD_MAX;
INT32 sDist;
INT32 sGridNo = NOWHERE;
// Loop through all mercs on player team
ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
SoldierID ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( ; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++)
for ( ; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ++ubLoop)
{
pTargetSoldier = Menptr + ubLoop;
pTargetSoldier = ubLoop;
if (!pTargetSoldier->bActive || !pTargetSoldier->bInSector)
{
@@ -1762,17 +1762,16 @@ INT32 ClosestUnDisguisedPC( SOLDIERTYPE *pSoldier, INT32 * psDistance )
// used by NPCs... find the closest PC
// NOTE: skips EPCs!
UINT8 ubLoop;
SOLDIERTYPE *pTargetSoldier;
INT32 sMinDist = WORLD_MAX;
INT32 sDist;
INT32 sGridNo = NOWHERE;
// Loop through all mercs on player team
ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( ; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++)
SoldierID ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( ; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ++ubLoop )
{
pTargetSoldier = Menptr + ubLoop;
pTargetSoldier = ubLoop;
if (!pTargetSoldier->bActive || !pTargetSoldier->bInSector)
continue;
@@ -2021,7 +2020,6 @@ INT16 EstimatePathCostToLocation( SOLDIERTYPE * pSoldier, INT32 sDestGridNo, INT
BOOLEAN GuySawEnemy( SOLDIERTYPE * pSoldier, UINT8 ubMax )
{
UINT8 ubTeamLoop;
UINT8 ubIDLoop;
SOLDIERTYPE *pOpponent;
for ( ubTeamLoop = 0; ubTeamLoop < MAXTEAMS; ++ubTeamLoop )
@@ -2032,9 +2030,9 @@ BOOLEAN GuySawEnemy( SOLDIERTYPE * pSoldier, UINT8 ubMax )
if ( gTacticalStatus.Team[ ubTeamLoop ].bSide != pSoldier->bSide )
{
// consider guys in this team, which isn't on our side
for ( ubIDLoop = gTacticalStatus.Team[ ubTeamLoop ].bFirstID; ubIDLoop <= gTacticalStatus.Team[ ubTeamLoop ].bLastID; ++ubIDLoop )
for ( SoldierID ubIDLoop = gTacticalStatus.Team[ ubTeamLoop ].bFirstID; ubIDLoop <= gTacticalStatus.Team[ ubTeamLoop ].bLastID; ++ubIDLoop )
{
pOpponent = MercPtrs[ubIDLoop];
pOpponent = ubIDLoop;
// if this merc is inactive, at base, on assignment, or dead
if (!pOpponent)
@@ -2174,15 +2172,14 @@ INT32 ClosestReachableFriendInTrouble(SOLDIERTYPE *pSoldier, BOOLEAN * pfClimbin
INT16 DistanceToClosestFriend( SOLDIERTYPE * pSoldier )
{
// find the distance to the closest person on the same team
UINT8 ubLoop;
SOLDIERTYPE *pTargetSoldier;
INT16 sMinDist = 1000;
INT16 sDist;
// Loop through all mercs on player team
ubLoop = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID;
SoldierID ubLoop = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID;
for ( ; ubLoop <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID; ubLoop++ )
for ( ; ubLoop <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID; ++ubLoop )
{
if (ubLoop == pSoldier->ubID)
{
@@ -2190,7 +2187,7 @@ INT16 DistanceToClosestFriend( SOLDIERTYPE * pSoldier )
continue;
}
pTargetSoldier = Menptr + ubLoop;
pTargetSoldier = ubLoop;
if ( pSoldier->bActive && pSoldier->bInSector )
{
@@ -2799,7 +2796,7 @@ INT16 RoamingRange(SOLDIERTYPE *pSoldier, INT32 * pusFromGridNo)
BOOL OppPosKnown = FALSE;
if (CREATURE_OR_BLOODCAT(pSoldier))
{
if (pSoldier->aiData.bAlertStatus == STATUS_BLACK)
if (pSoldier->aiData.bAlertStatus > STATUS_YELLOW)
{
*pusFromGridNo = pSoldier->sGridNo; // from current position!
return(MAX_ROAMING_RANGE);
@@ -3179,12 +3176,11 @@ INT32 RangeChangeDesire( SOLDIERTYPE * pSoldier )
BOOLEAN ArmySeesOpponents( void )
{
INT32 cnt;
SOLDIERTYPE * pSoldier;
for ( cnt = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID; cnt <= gTacticalStatus.Team[ ENEMY_TEAM ].bLastID; cnt++ )
for ( SoldierID cnt = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID; cnt <= gTacticalStatus.Team[ ENEMY_TEAM ].bLastID; ++cnt )
{
pSoldier = MercPtrs[ cnt ];
pSoldier = cnt;
if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife >= OKLIFE && pSoldier->aiData.bOppCnt > 0 )
{
@@ -3318,7 +3314,7 @@ INT16 AssessTacticalSituation( INT8 bTeam )
BOOLEAN TeamSeesOpponent( INT8 bTeam, SOLDIERTYPE * pOpponent )
{
SOLDIERTYPE * pSoldier;
UINT16 cnt;
SoldierID cnt;
// This assertion can be safely removed, assuming the program does what it should. It simply checks
// whether the "opponent" is on the same team being checked. That should be avoided when calling this
@@ -3328,9 +3324,9 @@ BOOLEAN TeamSeesOpponent( INT8 bTeam, SOLDIERTYPE * pOpponent )
// We're checking Merc/Militia visibility
if (bTeam == OUR_TEAM || bTeam == MILITIA_TEAM )
{
for ( cnt = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; cnt <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; cnt++ )
for ( cnt = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; cnt <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; ++cnt )
{
pSoldier = MercPtrs[ cnt ];
pSoldier = cnt;
if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife >= OKLIFE)
{
@@ -3340,9 +3336,9 @@ BOOLEAN TeamSeesOpponent( INT8 bTeam, SOLDIERTYPE * pOpponent )
return ( TRUE );
}
}
for ( cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++ )
for ( cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; ++cnt )
{
pSoldier = MercPtrs[ cnt ];
pSoldier = cnt;
if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife >= OKLIFE)
{
@@ -3361,9 +3357,9 @@ BOOLEAN TeamSeesOpponent( INT8 bTeam, SOLDIERTYPE * pOpponent )
// Check enemy visibility
else if (bTeam == ENEMY_TEAM)
{
for ( cnt = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID; cnt <= gTacticalStatus.Team[ ENEMY_TEAM ].bLastID; cnt++ )
for ( cnt = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID; cnt <= gTacticalStatus.Team[ ENEMY_TEAM ].bLastID; ++cnt )
{
pSoldier = MercPtrs[ cnt ];
pSoldier = cnt;
if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife >= OKLIFE)
{
@@ -3457,17 +3453,16 @@ INT32 CalcStraightThreatValue( SOLDIERTYPE *pEnemy )
}
// Flugente: get the id of the closest soldier with a specific flag that we can currently see
UINT8 GetClosestFlaggedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam, UINT32 aFlag, BOOLEAN fCheckSight )
SoldierID GetClosestFlaggedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam, UINT32 aFlag, BOOLEAN fCheckSight )
{
UINT8 id = NOBODY;
UINT32 uiLoop;
SoldierID id = NOBODY;
SOLDIERTYPE * pFriend;
INT16 range = aRange;
// go through each soldier, looking for "friends" (soldiers on same team)
for (uiLoop = gTacticalStatus.Team[ auTeam ].bFirstID; uiLoop <= gTacticalStatus.Team[ auTeam ].bLastID; ++uiLoop)
for ( SoldierID uiLoop = gTacticalStatus.Team[ auTeam ].bFirstID; uiLoop <= gTacticalStatus.Team[ auTeam ].bLastID; ++uiLoop)
{
pFriend = MercPtrs[ uiLoop ];
pFriend = uiLoop;
// if this merc is inactive, not in sector, or dead
if (!pFriend)
@@ -3510,17 +3505,16 @@ UINT8 GetClosestFlaggedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 au
}
// get the id of the closest soldier (closer than x tiles) of a specific team that is wounded that we can currently see
UINT8 GetClosestWoundedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam )
SoldierID GetClosestWoundedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam )
{
UINT8 id = NOBODY;
UINT32 uiLoop;
SoldierID id = NOBODY;
SOLDIERTYPE * pFriend;
INT16 range = aRange;
// go through each soldier, looking for "friends" (soldiers on same team)
for (uiLoop = gTacticalStatus.Team[ auTeam ].bFirstID; uiLoop <= gTacticalStatus.Team[ auTeam ].bLastID; ++uiLoop)
for ( SoldierID uiLoop = gTacticalStatus.Team[ auTeam ].bFirstID; uiLoop <= gTacticalStatus.Team[ auTeam ].bLastID; ++uiLoop)
{
pFriend = MercPtrs[ uiLoop ];
pFriend = uiLoop;
// if this merc is inactive, not in sector, or dead
if (!pFriend)
@@ -3559,17 +3553,16 @@ UINT8 GetClosestWoundedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 au
}
// get the id of the closest medic (closer than x tiles) of a specific team
UINT8 GetClosestMedicSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam )
SoldierID GetClosestMedicSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam )
{
UINT8 id = NOBODY;
UINT32 uiLoop;
SoldierID id = NOBODY;
SOLDIERTYPE * pFriend;
INT16 range = aRange;
// go through each soldier, looking for "friends" (soldiers on same team)
for (uiLoop = gTacticalStatus.Team[ auTeam ].bFirstID; uiLoop <= gTacticalStatus.Team[ auTeam ].bLastID; ++uiLoop)
for ( SoldierID uiLoop = gTacticalStatus.Team[ auTeam ].bFirstID; uiLoop <= gTacticalStatus.Team[ auTeam ].bLastID; ++uiLoop)
{
pFriend = MercPtrs[ uiLoop ];
pFriend = uiLoop;
// if this merc is inactive, not in sector, or dead
if (!pFriend)
@@ -3623,20 +3616,20 @@ INT16 MaxNormalVisionDistance( void )
// sevenfm: check friendly soldiers between me and noise gridno
// count only friends that are active and not stationary/onguard/sniper
UINT8 CountFriendsInDirection( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
UINT16 CountFriendsInDirection( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
{
SOLDIERTYPE * pFriend;
UINT8 ubFriendDir, ubMyDir;
UINT8 ubFriends = 0;
UINT16 ubFriends = 0;
CHECKF(pSoldier);
ubMyDir = GetDirectionFromCenterCellXYGridNo(sTargetGridNo, pSoldier->sGridNo);
// Run through each friendly.
for ( UINT8 iCounter = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID ; iCounter <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID ; iCounter ++ )
for ( SoldierID iCounter = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID ; iCounter <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID ; ++iCounter )
{
pFriend = MercPtrs[ iCounter ];
pFriend = iCounter;
ubFriendDir = GetDirectionFromCenterCellXYGridNo(sTargetGridNo, pFriend->sGridNo);
if (pFriend != pSoldier &&
@@ -3656,19 +3649,19 @@ UINT8 CountFriendsInDirection( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
}
// sevenfm: count nearby friend soldiers
UINT8 CountNearbyFriends( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubDistance )
UINT16 CountNearbyFriends( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubDistance )
{
SOLDIERTYPE * pFriend;
UINT8 ubFriendCount = 0;
UINT16 ubFriendCount = 0;
// safety check
if( !pSoldier )
return 0;
// Run through each friendly.
for ( UINT8 iCounter = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID ; iCounter <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID ; iCounter ++ )
for ( SoldierID iCounter = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID ; iCounter <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID ; ++iCounter )
{
pFriend = MercPtrs[ iCounter ];
pFriend = iCounter;
// Make sure that character is alive, not too shocked, and conscious, and of higher experience level
// than the character being suppressed.
if (pFriend != pSoldier && pFriend->bActive && pFriend->stats.bLife >= OKLIFE &&
@@ -3975,9 +3968,9 @@ BOOLEAN WeAttack(INT8 bTeam)
SOLDIERTYPE * pFriend;
// Run through each friendly.
for (UINT8 iCounter = gTacticalStatus.Team[bTeam].bFirstID; iCounter <= gTacticalStatus.Team[bTeam].bLastID; iCounter++)
for ( SoldierID iCounter = gTacticalStatus.Team[bTeam].bFirstID; iCounter <= gTacticalStatus.Team[bTeam].bLastID; ++iCounter )
{
pFriend = MercPtrs[iCounter];
pFriend = iCounter;
if (pFriend &&
pFriend->bActive &&
@@ -3999,9 +3992,9 @@ UINT8 CountNearbyFriendsLastAttackHit( SOLDIERTYPE *pSoldier, INT32 sGridNo, UIN
UINT8 ubFriendCount = 0;
// Run through each friendly.
for ( UINT8 iCounter = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID ; iCounter <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID ; iCounter ++ )
for ( SoldierID iCounter = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID ; iCounter <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID ; ++iCounter )
{
pFriend = MercPtrs[ iCounter ];
pFriend = iCounter;
if (pFriend != pSoldier &&
pFriend->bActive &&
@@ -4039,9 +4032,9 @@ UINT8 CountFriendsFlankSameSpot(SOLDIERTYPE *pSoldier, INT32 sSpot)
}
// Run through each friendly.
for (UINT8 iCounter = gTacticalStatus.Team[pSoldier->bTeam].bFirstID; iCounter <= gTacticalStatus.Team[pSoldier->bTeam].bLastID; iCounter++)
for ( SoldierID iCounter = gTacticalStatus.Team[pSoldier->bTeam].bFirstID; iCounter <= gTacticalStatus.Team[pSoldier->bTeam].bLastID; ++iCounter )
{
pFriend = MercPtrs[iCounter];
pFriend = iCounter;
if (pFriend &&
pFriend != pSoldier &&
@@ -4121,9 +4114,9 @@ UINT8 CountFriendsBlack( SOLDIERTYPE *pSoldier, INT32 sClosestOpponent )
}
// Run through each friendly.
for ( UINT8 iCounter = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID ; iCounter <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID ; iCounter ++ )
for ( SoldierID iCounter = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID ; iCounter <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID ; ++iCounter )
{
pFriend = MercPtrs[ iCounter ];
pFriend = iCounter;
// Make sure that character is alive, not too shocked, and conscious
if (pFriend != pSoldier &&
@@ -4150,19 +4143,19 @@ UINT8 CountFriendsBlack( SOLDIERTYPE *pSoldier, INT32 sClosestOpponent )
}
// count friends under fire or with shock
UINT8 CountTeamUnderAttack(INT8 bTeam, INT32 sGridNo, INT16 sDistance)
UINT16 CountTeamUnderAttack(INT8 bTeam, INT32 sGridNo, INT16 sDistance)
{
SOLDIERTYPE * pFriend;
UINT8 ubFriendCount = 0;
UINT16 ubFriendCount = 0;
// safety check
if (bTeam >= MAXTEAMS)
return 0;
// Run through each friendly.
for (UINT8 iCounter = gTacticalStatus.Team[bTeam].bFirstID; iCounter <= gTacticalStatus.Team[bTeam].bLastID; iCounter++)
for ( SoldierID iCounter = gTacticalStatus.Team[bTeam].bFirstID; iCounter <= gTacticalStatus.Team[bTeam].bLastID; ++iCounter )
{
pFriend = MercPtrs[iCounter];
pFriend = iCounter;
if (pFriend &&
pFriend->bActive &&
@@ -4402,19 +4395,19 @@ BOOLEAN EnemySeenSoldierRecently( SOLDIERTYPE *pSoldier, UINT8 ubMax )
return FALSE;
}
UINT8 CountTeamSeeSoldier( INT8 bTeam, SOLDIERTYPE *pSoldier )
UINT16 CountTeamSeeSoldier( INT8 bTeam, SOLDIERTYPE *pSoldier )
{
SOLDIERTYPE *pFriend;
UINT8 ubFriends = 0;
UINT16 ubFriends = 0;
CHECKF( pSoldier );
if ( bTeam >= MAXTEAMS )
return 0;
for ( UINT16 cnt = gTacticalStatus.Team[bTeam].bFirstID; cnt <= gTacticalStatus.Team[bTeam].bLastID; ++cnt )
for ( SoldierID cnt = gTacticalStatus.Team[bTeam].bFirstID; cnt <= gTacticalStatus.Team[bTeam].bLastID; ++cnt )
{
pFriend = MercPtrs[cnt];
pFriend = cnt;
if ( pFriend->bActive &&
pFriend->bInSector &&
@@ -4851,13 +4844,12 @@ BOOLEAN AnyCoverFromSpot( INT32 sSpot, INT8 bLevel, INT32 sThreatLoc, INT8 bThre
return FALSE;
}
UINT8 CountSeenEnemiesLastTurn( SOLDIERTYPE* pSoldier )
UINT16 CountSeenEnemiesLastTurn( SOLDIERTYPE* pSoldier )
{
CHECKF(pSoldier);
UINT8 ubTeamLoop;
UINT8 ubIDLoop;
UINT8 cnt = 0;
UINT16 cnt = 0;
for( ubTeamLoop = 0; ubTeamLoop < MAXTEAMS; ubTeamLoop++ )
{
@@ -4867,7 +4859,7 @@ UINT8 CountSeenEnemiesLastTurn( SOLDIERTYPE* pSoldier )
if( gTacticalStatus.Team[ ubTeamLoop ].bSide != pSoldier->bSide )
{
// consider guys in this team, which isn't on our side
for( ubIDLoop = gTacticalStatus.Team[ ubTeamLoop ].bFirstID; ubIDLoop <= gTacticalStatus.Team[ ubTeamLoop ].bLastID; ubIDLoop++ )
for( SoldierID ubIDLoop = gTacticalStatus.Team[ ubTeamLoop ].bFirstID; ubIDLoop <= gTacticalStatus.Team[ ubTeamLoop ].bLastID; ++ubIDLoop )
{
// if this guy SAW an enemy recently...
if( pSoldier->aiData.bOppList[ ubIDLoop ] >= SEEN_CURRENTLY &&
@@ -5682,7 +5674,7 @@ BOOLEAN DuskLight(void)
return FALSE;
}
BOOLEAN UsePersonalKnowledge(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
BOOLEAN UsePersonalKnowledge(SOLDIERTYPE *pSoldier, SoldierID ubOpponentID)
{
INT8 bPersonalKnowledge;
INT8 bPublicKnowledge;
@@ -5706,7 +5698,7 @@ BOOLEAN UsePersonalKnowledge(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
return FALSE;
}
INT8 Knowledge(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
INT8 Knowledge(SOLDIERTYPE *pSoldier, SoldierID ubOpponentID)
{
if (!pSoldier || ubOpponentID == NOBODY)
{
@@ -5721,7 +5713,7 @@ INT8 Knowledge(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
return PublicKnowledge(pSoldier->bTeam, ubOpponentID);
}
INT32 KnownLocation(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
INT32 KnownLocation(SOLDIERTYPE *pSoldier, SoldierID ubOpponentID)
{
if (!pSoldier || ubOpponentID == NOBODY)
{
@@ -5736,7 +5728,7 @@ INT32 KnownLocation(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
return KnownPublicLocation(pSoldier->bTeam, ubOpponentID);
}
INT8 KnownLevel(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
INT8 KnownLevel(SOLDIERTYPE *pSoldier, SoldierID ubOpponentID)
{
if (!pSoldier || ubOpponentID == NOBODY)
{
@@ -5751,7 +5743,7 @@ INT8 KnownLevel(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
return KnownPublicLevel(pSoldier->bTeam, ubOpponentID);
}
INT8 PersonalKnowledge(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
INT8 PersonalKnowledge(SOLDIERTYPE *pSoldier, SoldierID ubOpponentID)
{
if (!pSoldier || ubOpponentID == NOBODY)
{
@@ -5761,7 +5753,7 @@ INT8 PersonalKnowledge(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
return pSoldier->aiData.bOppList[ubOpponentID];
}
INT32 KnownPersonalLocation(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
INT32 KnownPersonalLocation(SOLDIERTYPE *pSoldier, SoldierID ubOpponentID)
{
if (!pSoldier || ubOpponentID == NOBODY)
{
@@ -5775,7 +5767,7 @@ INT32 KnownPersonalLocation(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
return gsLastKnownOppLoc[pSoldier->ubID][ubOpponentID];
}
INT8 KnownPersonalLevel(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
INT8 KnownPersonalLevel(SOLDIERTYPE *pSoldier, SoldierID ubOpponentID)
{
if (!pSoldier || ubOpponentID == NOBODY)
{
@@ -5785,7 +5777,7 @@ INT8 KnownPersonalLevel(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID)
return gbLastKnownOppLevel[pSoldier->ubID][ubOpponentID];
}
INT8 PublicKnowledge(UINT8 bTeam, UINT8 ubOpponentID)
INT8 PublicKnowledge(UINT8 bTeam, SoldierID ubOpponentID)
{
if (bTeam >= MAXTEAMS || ubOpponentID == NOBODY)
{
@@ -5795,7 +5787,7 @@ INT8 PublicKnowledge(UINT8 bTeam, UINT8 ubOpponentID)
return gbPublicOpplist[bTeam][ubOpponentID];
}
INT32 KnownPublicLocation(UINT8 bTeam, UINT8 ubOpponentID)
INT32 KnownPublicLocation(UINT8 bTeam, SoldierID ubOpponentID)
{
if (bTeam >= MAXTEAMS || ubOpponentID == NOBODY)
{
@@ -5809,7 +5801,7 @@ INT32 KnownPublicLocation(UINT8 bTeam, UINT8 ubOpponentID)
return gsPublicLastKnownOppLoc[bTeam][ubOpponentID];
}
INT8 KnownPublicLevel(UINT8 bTeam, UINT8 ubOpponentID)
INT8 KnownPublicLevel(UINT8 bTeam, SoldierID ubOpponentID)
{
if (bTeam >= MAXTEAMS || ubOpponentID == NOBODY)
{
@@ -5950,14 +5942,14 @@ INT32 RandomizeOpponentLocation(INT32 sSpot, SOLDIERTYPE *pOpponent, INT16 sMaxD
}
// first call PrepareThreatlist to make threat list
UINT8 ClosestKnownThreatID(SOLDIERTYPE *pSoldier, UINT32 uiThreatCnt)
SoldierID ClosestKnownThreatID(SOLDIERTYPE *pSoldier, UINT32 uiThreatCnt)
{
CHECKF(pSoldier);
UINT32 uiLoop;
INT32 sClosestOpponent = NOWHERE;
INT32 iRange, iClosestRange;
UINT8 ubClosestOpponentID = NOBODY;
SoldierID ubClosestOpponentID = NOBODY;
// use global defined threat list
for (uiLoop = 0; uiLoop < uiThreatCnt; uiLoop++)
@@ -5980,14 +5972,14 @@ UINT8 ClosestKnownThreatID(SOLDIERTYPE *pSoldier, UINT32 uiThreatCnt)
}
// first call PrepareThreatlist to make threat list
UINT8 ClosestSeenThreatID(SOLDIERTYPE *pSoldier, UINT32 uiThreatCnt, UINT8 ubMax)
SoldierID ClosestSeenThreatID(SOLDIERTYPE *pSoldier, UINT32 uiThreatCnt, UINT8 ubMax)
{
CHECKF(pSoldier);
UINT32 uiLoop;
INT32 sClosestOpponent = NOWHERE;
INT32 iRange, iClosestRange;
UINT8 ubClosestOpponentID = NOBODY;
SoldierID ubClosestOpponentID = NOBODY;
// use global defined threat list
for (uiLoop = 0; uiLoop < uiThreatCnt; uiLoop++)
@@ -6110,7 +6102,7 @@ UINT32 PrepareThreatlist(SOLDIERTYPE *pSoldier)
return uiThreatCnt;
}
UINT8 CountPublicKnownEnemies(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 sDistance)
UINT16 CountPublicKnownEnemies(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 sDistance)
{
CHECKF(pSoldier);
@@ -6120,7 +6112,7 @@ UINT8 CountPublicKnownEnemies(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 sDista
INT32 sThreatLoc;
INT8 iThreatLevel;
UINT8 ubNum = 0;
UINT16 ubNum = 0;
// loop through all the enemies
for (uiLoop = 0; uiLoop < guiNumMercSlots; ++uiLoop)
@@ -6164,7 +6156,7 @@ UINT8 CountPublicKnownEnemies(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 sDista
return ubNum;
}
UINT8 CountPublicKnownEnemies(SOLDIERTYPE *pSoldier)
UINT16 CountPublicKnownEnemies(SOLDIERTYPE *pSoldier)
{
CHECKF(pSoldier);
@@ -6174,7 +6166,7 @@ UINT8 CountPublicKnownEnemies(SOLDIERTYPE *pSoldier)
INT32 sThreatLoc;
INT8 iThreatLevel;
UINT8 ubNum = 0;
UINT16 ubNum = 0;
// loop through all the enemies
for (uiLoop = 0; uiLoop < guiNumMercSlots; ++uiLoop)
+86 -91
View File
@@ -3,11 +3,11 @@
#include "opplist.h"
#include "AIInternals.h"
#include "LOS.h"
#include "Physics.h"
#include "physics.h"
#include "Items.h"
#include "Weapons.h"
#include "Spread Burst.h"
#include "overhead.h"
#include "Spread burst.h"
#include "Overhead.h"
#include "SkillCheck.h"
#include "Soldier Profile.h"
#include "Isometric Utils.h"
@@ -63,7 +63,7 @@ void LoadWeaponIfNeeded(SOLDIERTYPE *pSoldier)
usInHand = GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS]);
// if he's got a MORTAR in his hand, make sure he has a MORTARSHELL avail.
if (Item[usInHand].mortar )
if (ItemIsMortar(usInHand))
{
// bPayloadPocket = FindObj( pSoldier, MORTAR_SHELL );
bPayloadPocket = FindLaunchable( pSoldier, usInHand );
@@ -76,7 +76,7 @@ void LoadWeaponIfNeeded(SOLDIERTYPE *pSoldier)
}
}
// if he's got a GL in his hand, make sure he has some type of GRENADE avail.
else if (Item[usInHand].grenadelauncher )
else if (ItemIsGrenadeLauncher(usInHand))
{
bPayloadPocket = FindGLGrenade( pSoldier );
if (bPayloadPocket == NO_SLOT || FindNonSmokeLaunchableAttachment( &pSoldier->inv[HANDPOS],usInHand ) != 0 )
@@ -88,7 +88,7 @@ void LoadWeaponIfNeeded(SOLDIERTYPE *pSoldier)
}
}
// if he's got a RPG7 in his hand, make sure he has some type of RPG avail.
else if (Item[usInHand].rocketlauncher && !Item[usInHand].singleshotrocketlauncher )
else if (ItemIsRocketLauncher(usInHand) && !ItemIsSingleShotRocketLauncher(usInHand))
{
bPayloadPocket = FindLaunchable (pSoldier, usInHand );
if (bPayloadPocket == NO_SLOT)
@@ -96,7 +96,7 @@ void LoadWeaponIfNeeded(SOLDIERTYPE *pSoldier)
return; // no grenades, can't fire
}
}
else if (Item[usInHand].cannon )
else if (ItemIsCannon(usInHand))
{
bPayloadPocket = FindLaunchable( pSoldier, usInHand );
if (bPayloadPocket == NO_SLOT)
@@ -444,7 +444,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
// sevenfm: take into account direction when checking stance
// sevenfm: shoot heavy guns in standing stance only when using hip fire
if (pSoldier->InternalIsValidStance(AIDirection(pSoldier->sGridNo, sTarget), ubStance) &&
(pSoldier->bScopeMode == USE_ALT_WEAPON_HOLD || !Weapon[pSoldier->usAttackingWeapon].HeavyGun || !Item[pSoldier->usAttackingWeapon].twohanded || !gGameExternalOptions.ubAllowAlternativeWeaponHolding))
(pSoldier->bScopeMode == USE_ALT_WEAPON_HOLD || !Weapon[pSoldier->usAttackingWeapon].HeavyGun || !ItemIsTwoHanded(pSoldier->usAttackingWeapon) || !gGameExternalOptions.ubAllowAlternativeWeaponHolding))
{
sStanceAPcost = GetAPsToChangeStance(pSoldier, ubStance);
if(sStanceAPcost)
@@ -716,16 +716,16 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
//dnl ch62 180813 ignore firing into breathless targets if there are targets in better condition
// sevenfm: check that best opponent exists
if (pBestShot->ubOpponent != NOBODY &&
(Menptr[pBestShot->ubOpponent].bCollapsed || Menptr[pBestShot->ubOpponent].bBreathCollapsed) &&
Menptr[pBestShot->ubOpponent].bBreath < OKBREATH
&& Menptr[pBestShot->ubOpponent].bBreath < pOpponent->bBreath)
(pBestShot->ubOpponent->bCollapsed || pBestShot->ubOpponent->bBreathCollapsed) &&
pBestShot->ubOpponent->bBreath < OKBREATH
&& pBestShot->ubOpponent->bBreath < pOpponent->bBreath)
{
iPercentBetter = PERCENT_TO_IGNORE_THREAT;
}
// sevenfm: if best opponent is dying and new opponent is ok, use new opponent
if (pBestShot->ubOpponent != NOBODY &&
Menptr[pBestShot->ubOpponent].stats.bLife < OKLIFE &&
pBestShot->ubOpponent->stats.bLife < OKLIFE &&
pOpponent->stats.bLife >= OKLIFE)
{
iPercentBetter = PERCENT_TO_IGNORE_THREAT;
@@ -735,7 +735,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
// guy is conscious at all
if (iPercentBetter < -PERCENT_TO_IGNORE_THREAT &&
pBestShot->ubOpponent != NOBODY &&
Menptr[pBestShot->ubOpponent].stats.bLife >= OKLIFE)
pBestShot->ubOpponent->stats.bLife >= OKLIFE)
{
// then stick with the older guy as the better target
continue;
@@ -753,7 +753,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot)
// sevenfm: if new opponent is dying and best opponent is ok, ignore new opponent
if (pBestShot->ubOpponent != NOBODY &&
Menptr[pBestShot->ubOpponent].stats.bLife >= OKLIFE &&
pBestShot->ubOpponent->stats.bLife >= OKLIFE &&
pOpponent->stats.bLife < OKLIFE)
{
//DebugShot(pSoldier, String("new opponent is dying, best opponent is ok - skip"));
@@ -839,13 +839,14 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"calcbestthrow");
// September 9, 1998: added code for LAWs (CJC)
UINT8 ubLoop, ubLoop2;
UINT16 ubLoop, ubLoop2;
INT32 iAttackValue;
INT32 iHitRate, iThreatValue, iTotalThreatValue,iOppThreatValue[MAXMERCS];
INT32 sGridNo, sEndGridNo, sFriendTile[MAXMERCS], sOpponentTile[MAXMERCS];
INT8 bFriendLevel[MAXMERCS], bOpponentLevel[MAXMERCS];
INT32 iEstDamage;
UINT8 ubFriendCnt = 0,ubOpponentCnt = 0, ubOpponentID[MAXMERCS];
UINT16 ubFriendCnt = 0, ubOpponentCnt = 0;
SoldierID ubOpponentID[MAXMERCS];
UINT8 ubMaxPossibleAimTime;
INT16 sRawAPCost, sMinAPcost;
UINT8 ubChanceToHit, ubChanceToGetThrough, ubChanceToReallyHit, ubFriendlyFireChance;
@@ -887,7 +888,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
}
// if he's got a MORTAR in his hand, make sure he has a MORTARSHELL avail.
if (Item[usInHand].mortar )
if (ItemIsMortar(usInHand))
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"calcbestthrow: buddy's got a mortar");
bPayloadPocket = FindNonSmokeLaunchable(pSoldier, usInHand);
@@ -911,7 +912,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
fMortar = TRUE;
}
// if he's got a GL in his hand, make sure he has some type of GRENADE avail.
else if (Item[usInHand].grenadelauncher )
else if (ItemIsGrenadeLauncher(usInHand))
{
// use up pocket 2 first, they get left as drop items
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"calcbestthrow: buddy's got a GL");
@@ -943,7 +944,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
}
fGrenadeLauncher = TRUE;
}
else if ( Item[usInHand].rocketlauncher )
else if (ItemIsRocketLauncher(usInHand))
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"calcbestthrow: buddy's got a rocket launcher");
@@ -952,7 +953,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
// put in hand
bPayloadPocket = HANDPOS;//dnl ch63 240813
if (Item[usInHand].singleshotrocketlauncher)
if (ItemIsSingleShotRocketLauncher(usInHand))
{
// sevenfm: for single shot rocket launchers, use buddy item instead
if (Item[usInHand].usBuddyItem && Item[Item[usInHand].usBuddyItem].usItemClass & IC_EXPLOSV)
@@ -983,7 +984,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
}
fRocketLauncher = TRUE;
}
else if (Item[usInHand].cannon )
else if (ItemIsCannon(usInHand))
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"calcbestthrow: buddy's got a tank");
bPayloadPocket = FindNonSmokeLaunchable(pSoldier, usInHand);
@@ -1008,7 +1009,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
usGrenade = pSoldier->inv[bPayloadPocket].usItem;
ubSafetyMargin = (UINT8)(1 + max(Explosive[Item[usGrenade].ubClassIndex].ubRadius, min((UINT8)TACTICAL_RANGE / 4, Explosive[Item[usGrenade].ubClassIndex].ubFragRange / CELL_X_SIZE)));
if ( Item[usGrenade].flare )
if (ItemIsFlare(usGrenade))
{
// JA2Gold: light isn't as nasty as explosives
ubSafetyMargin /= 2;
@@ -1032,7 +1033,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
// use flares only at night
if (usGrenade != NOTHING &&
Item[usGrenade].flare &&
ItemIsFlare(usGrenade) &&
!NightLight())
{
return;
@@ -1121,7 +1122,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
// limit explosives type when attacking zombies
if (usGrenade != NOTHING &&
!Item[usGrenade].flare &&
!ItemIsFlare(usGrenade) &&
Explosive[Item[usGrenade].ubClassIndex].ubType != EXPLOSV_NORMAL &&
Explosive[Item[usGrenade].ubClassIndex].ubType != EXPLOSV_CREATUREGAS &&
Explosive[Item[usGrenade].ubClassIndex].ubType != EXPLOSV_BURNABLEGAS &&
@@ -1143,7 +1144,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
// limit explosives type when attacking robots, vehicles and tanks
if (usGrenade != NOTHING &&
!Item[usGrenade].flare &&
!ItemIsFlare(usGrenade) &&
Explosive[Item[usGrenade].ubClassIndex].ubType != EXPLOSV_NORMAL &&
Explosive[Item[usGrenade].ubClassIndex].ubType != EXPLOSV_CREATUREGAS &&
Explosive[Item[usGrenade].ubClassIndex].ubType != EXPLOSV_BURNABLEGAS &&
@@ -1161,7 +1162,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
// limit explosives type when attacking collapsed enemies
if (usGrenade != NOTHING &&
!Item[usGrenade].flare &&
!ItemIsFlare(usGrenade) &&
Explosive[Item[usGrenade].ubClassIndex].ubType != EXPLOSV_NORMAL &&
Explosive[Item[usGrenade].ubClassIndex].ubType != EXPLOSV_CREATUREGAS &&
Explosive[Item[usGrenade].ubClassIndex].ubType != EXPLOSV_BURNABLEGAS &&
@@ -1173,7 +1174,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
// don't use flare if soldier is in light
if (usGrenade != NOTHING &&
Item[usGrenade].flare &&
ItemIsFlare(usGrenade) &&
InLightAtNight(pOpponent->sGridNo, pOpponent->pathing.bLevel))
{
continue;
@@ -1181,13 +1182,13 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
// don't use flares against opponents on roof
if (usGrenade != NOTHING &&
Item[usGrenade].flare &&
ItemIsFlare(usGrenade) &&
pOpponent->pathing.bLevel > 0)
{
continue;
}
if (Item[usInHand].mortar)
if (ItemIsMortar(usInHand))
{
// active KNOWN opponent, remember where he is so that we DO blow him up!
if (bPersonalKnowledge == SEEN_CURRENTLY ||
@@ -1209,7 +1210,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
continue; // next soldier
}
}
else if (Item[usInHand].rocketlauncher)
else if (ItemIsRocketLauncher(usInHand))
{
if (bPersonalKnowledge == SEEN_CURRENTLY || bPublicKnowledge == SEEN_CURRENTLY)
{
@@ -1231,7 +1232,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
continue;
}
}
else if( Item[usInHand].grenadelauncher )
else if(ItemIsGrenadeLauncher(usInHand))
{
if (bPersonalKnowledge == SEEN_CURRENTLY || bPublicKnowledge == SEEN_CURRENTLY)
{
@@ -1262,7 +1263,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
else if ((bKnowledge == SEEN_THIS_TURN || bKnowledge == SEEN_LAST_TURN || bKnowledge == HEARD_THIS_TURN || bKnowledge == HEARD_LAST_TURN) &&
!TileIsOutOfBounds(KnownLocation(pSoldier, pOpponent->ubID)) &&
CloseEnoughForGrenadeToss(pOpponent->sGridNo, KnownLocation(pSoldier, pOpponent->ubID)) &&
(usGrenade != NOTHING && Item[usGrenade].flare || pSoldier->aiData.bUnderFire || pSoldier->aiData.bShock))
(usGrenade != NOTHING && ItemIsFlare(usGrenade) || pSoldier->aiData.bUnderFire || pSoldier->aiData.bShock))
{
sOpponentTile[ubOpponentCnt] = KnownLocation(pSoldier, pOpponent->ubID);
bOpponentLevel[ubOpponentCnt] = KnownLevel(pSoldier, pOpponent->ubID);
@@ -1299,7 +1300,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
// don't spare non lethal grenades
if (usGrenade != NOTHING &&
(Item[usGrenade].flare ||
(ItemIsFlare(usGrenade) ||
Explosive[Item[usGrenade].ubClassIndex].ubType == EXPLOSV_STUN ||
Explosive[Item[usGrenade].ubClassIndex].ubType == EXPLOSV_SMOKE ||
Explosive[Item[usGrenade].ubClassIndex].ubType == EXPLOSV_TEARGAS ||
@@ -1328,7 +1329,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
// militia always try to spare grenades unless under attack or using flares
if (pSoldier->bTeam == MILITIA_TEAM &&
!pSoldier->aiData.bUnderFire &&
!Item[usGrenade].flare &&
!ItemIsFlare(usGrenade) &&
!fRocketLauncher)
{
fSpare = TRUE;
@@ -1479,7 +1480,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
iThreatValue = iOppThreatValue[ubLoop2];
// estimate how much damage this tossed item would do to him
iEstDamage = EstimateThrowDamage(pSoldier,bPayloadPocket,MercPtrs[ubOpponentID[ubLoop2]],sGridNo);
iEstDamage = EstimateThrowDamage(pSoldier, bPayloadPocket, ubOpponentID[ubLoop2], sGridNo);
if (usOppDist)
{
@@ -1492,7 +1493,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
iTotalThreatValue += (iThreatValue * iEstDamage);
// only count opponents still standing worth shooting at (in range)
if (Menptr[ ubOpponentID[ubLoop2] ].stats.bLife >= OKLIFE)
if (ubOpponentID[ubLoop2]->stats.bLife >= OKLIFE)
{
ubOppsInRange++;
if (usOppDist < 2)
@@ -1563,7 +1564,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
ubChanceToGetThrough = 100 - (UINT8) uiPenalty;
}
}
else if (Item[usInHand].mortar &&
else if (ItemIsMortar(usInHand) &&
usGrenade != NOTHING &&
Explosive[Item[usGrenade].ubClassIndex].ubType == EXPLOSV_NORMAL &&
bOpponentLevel[ubLoop] == 0 &&
@@ -1589,7 +1590,7 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
// this is try to minimize enemies wasting their (few) mortar shells or LAWs
// they won't use them on less than 2 targets as long as half life left
if ((Item[usInHand].mortar || Item[usInHand].rocketlauncher) && (ubOppsInRange < 2) &&
if ((ItemIsMortar(usInHand) || ItemIsRocketLauncher(usInHand)) && (ubOppsInRange < 2) &&
(!gGameExternalOptions.fEnemyTanksDontSpareShells || !ARMED_VEHICLE(pSoldier)) &&
!gGameExternalOptions.fEnemiesDontSpareLaunchables)
{
@@ -1597,9 +1598,9 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
}
// limit RPG use, unless can hit several enemies, shooting at tank or opponent is in a room
if (Item[usInHand].rocketlauncher &&
if (ItemIsRocketLauncher(usInHand) &&
ubOppsInRange < 2 &&
!ARMED_VEHICLE(MercPtrs[ubOpponentID[ubLoop]]) &&
!ARMED_VEHICLE(ubOpponentID[ubLoop]) &&
(!InARoom(sOpponentTile[ubLoop], NULL) || pSoldier->bTeam != ENEMY_TEAM))
{
continue; // next gridno
@@ -1687,11 +1688,11 @@ void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
// this is try to minimize enemies wasting their (limited) toss attacks:
UINT8 ubMinChanceToReallyHit;
if( usGrenade != NOTHING && Item[usGrenade].flare )
if( usGrenade != NOTHING && ItemIsFlare(usGrenade) )
{
ubMinChanceToReallyHit = 30;
}
else if (EXPLOSIVE_GUN(usInHand) && !ARMED_VEHICLE(pSoldier) && (pBestThrow->ubOpponent == NOBODY || !ARMED_VEHICLE(MercPtrs[pBestThrow->ubOpponent])))
else if (EXPLOSIVE_GUN(usInHand) && !ARMED_VEHICLE(pSoldier) && (pBestThrow->ubOpponent == NOBODY || !ARMED_VEHICLE(pBestThrow->ubOpponent)))
{
ubMinChanceToReallyHit = 80;
}
@@ -1916,7 +1917,7 @@ void CalcBestStab(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestStab, BOOLEAN fBladeAt
// guy is conscious at all
if (iPercentBetter < -PERCENT_TO_IGNORE_THREAT &&
pBestStab->ubOpponent != NOBODY &&
Menptr[pBestStab->ubOpponent].stats.bLife >= OKLIFE)
pBestStab->ubOpponent->stats.bLife >= OKLIFE)
{
// then stick with the older guy as the better target
continue;
@@ -1937,12 +1938,12 @@ void CalcBestStab(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestStab, BOOLEAN fBladeAt
// OOOF! That was a lot of work! But we've got a new best target!
pBestStab->ubPossible = TRUE;
pBestStab->ubOpponent = pOpponent->ubID;
pBestStab->ubAimTime = ubBestAimTime;
pBestStab->ubChanceToReallyHit = ubChanceToReallyHit;
pBestStab->sTarget = pOpponent->sGridNo;
pBestStab->bTargetLevel = pOpponent->pathing.bLevel;
pBestStab->iAttackValue = iAttackValue;
pBestStab->ubAPCost = ubMinAPCost + ubBestAimTime;
pBestStab->ubAimTime = ubBestAimTime;
pBestStab->ubChanceToReallyHit = ubChanceToReallyHit;
pBestStab->sTarget = pOpponent->sGridNo;
pBestStab->bTargetLevel = pOpponent->pathing.bLevel;
pBestStab->iAttackValue = iAttackValue;
pBestStab->ubAPCost = ubMinAPCost + ubBestAimTime;
}
}
@@ -2305,11 +2306,12 @@ INT32 EstimateThrowDamage( SOLDIERTYPE *pSoldier, UINT8 ubItemPos, SOLDIERTYPE *
// ubExplosiveIndex = Item[ C1 ].ubClassIndex;
// break;
//default:
if ( Item[pSoldier->inv[ ubItemPos ].usItem].singleshotrocketlauncher )
UINT16 usItem = pSoldier->inv[ubItemPos].usItem;
if (ItemIsSingleShotRocketLauncher(usItem))
ubExplosiveIndex = Item[ C1 ].ubClassIndex;
else if ( Item[pSoldier->inv[ ubItemPos ].usItem].rocketlauncher || Item[pSoldier->inv[ ubItemPos ].usItem].grenadelauncher || Item[pSoldier->inv[ ubItemPos ].usItem].mortar )
else if (ItemIsRocketLauncher(usItem) || ItemIsGrenadeLauncher(usItem) || ItemIsMortar(usItem) )
{
OBJECTTYPE* pAttachment = FindLaunchableAttachment(&pSoldier->inv[ ubItemPos ],pSoldier->inv[ ubItemPos ].usItem ) ;
OBJECTTYPE* pAttachment = FindLaunchableAttachment(&pSoldier->inv[ ubItemPos ],usItem ) ;
if ( pAttachment->exists() )
ubExplosiveIndex = Item[pAttachment->usItem].ubClassIndex;
else
@@ -2331,7 +2333,7 @@ INT32 EstimateThrowDamage( SOLDIERTYPE *pSoldier, UINT8 ubItemPos, SOLDIERTYPE *
// break;
//}
// JA2Gold: added
if ( Item[pSoldier->inv[ubItemPos].usItem].flare )
if (ItemIsFlare(pSoldier->inv[ubItemPos].usItem))
{
return( 5 * ( LightTrueLevel( pOpponent->sGridNo, pOpponent->pathing.bLevel ) - NORMAL_LIGHTLEVEL_DAY ) );
}
@@ -2496,7 +2498,7 @@ INT32 EstimateStabDamage( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, INT16 u
{
if (gGameOptions.fNewTraitSystem)
{
if (!pSoldier->usAttackingWeapon || Item[usItem].brassknuckles)
if (!pSoldier->usAttackingWeapon || ItemIsBrassKnuckles(usItem))
{
// add bonus for martial arts
if (HAS_SKILL_TRAIT(pSoldier, MARTIAL_ARTS_NT))
@@ -2765,13 +2767,13 @@ INT8 CanNPCAttack(SOLDIERTYPE *pSoldier)
RearrangePocket( pSoldier, HANDPOS, bWeaponIn, FOREVER );
// look for another weapon if this one is 1-handed
// if ( (Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass == IC_GUN) && !(Item[ pSoldier->inv[ HANDPOS ].usItem ].fFlags & ITEM_TWO_HANDED ) )
if ( (Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass == IC_GUN) && !(Item[ pSoldier->inv[ HANDPOS ].usItem ].twohanded ) )
if ( (Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass == IC_GUN) && !ItemIsTwoHanded(pSoldier->inv[ HANDPOS ].usItem) )
{
// look for another pistol/SMG if available
// CHRISL: Change final parameter to use dynamic pocket definition
bWeaponIn = FindAIUsableObjClassWithin( pSoldier, IC_WEAPON, BIGPOCKSTART, NUM_INV_SLOTS );
// if (bWeaponIn != NO_SLOT && (Item[ pSoldier->inv[ bWeaponIn ].usItem ].usItemClass == IC_GUN) && !(Item[ pSoldier->inv[ bWeaponIn ].usItem ].fFlags & ITEM_TWO_HANDED ) )
if (bWeaponIn != NO_SLOT && (Item[ pSoldier->inv[ bWeaponIn ].usItem ].usItemClass == IC_GUN) && !(Item[ pSoldier->inv[ bWeaponIn ].usItem ].twohanded ) )
if (bWeaponIn != NO_SLOT && (Item[ pSoldier->inv[ bWeaponIn ].usItem ].usItemClass == IC_GUN) && !ItemIsTwoHanded(pSoldier->inv[ bWeaponIn ].usItem) )
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"cannpcattack: swapping weapon into holster");
RearrangePocket( pSoldier, SECONDHANDPOS, bWeaponIn, FOREVER );
@@ -3415,11 +3417,11 @@ UnderFire gUnderFire;
void UnderFire::Clear(void)
{
usUnderFireCnt = 0;
memset(usUnderFireID, 0, sizeof(usUnderFireID));
memset(usUnderFireID, TOTAL_SOLDIERS, sizeof(usUnderFireID));
memset(ubUnderFireCTH, 0, sizeof(ubUnderFireCTH));
}
void UnderFire::Add(UINT16 usID, UINT8 ubCTH)
void UnderFire::Add(SoldierID usID, UINT8 ubCTH)
{
if (!fEnable)
return;
@@ -3446,7 +3448,7 @@ UINT16 UnderFire::Count(INT8 bTeam)
UINT16 cnt = 0;
for (UINT16 i = 0; i < usUnderFireCnt; i++)
{
if (MercPtrs[usUnderFireID[i]]->bTeam == bTeam)
if (usUnderFireID[i]->bTeam == bTeam)
++cnt;
}
return(cnt);
@@ -3457,7 +3459,7 @@ UINT8 UnderFire::Chance(INT8 bTeam, INT8 bSide, BOOLEAN fCheckNeutral)
UINT8 cth = 0;
for (UINT16 i = 0; i < usUnderFireCnt; i++)
{
if ((MercPtrs[usUnderFireID[i]]->bTeam == bTeam || MercPtrs[usUnderFireID[i]]->bSide == bSide || fCheckNeutral && MercPtrs[usUnderFireID[i]]->aiData.bNeutral) &&
if ((usUnderFireID[i]->bTeam == bTeam || usUnderFireID[i]->bSide == bSide || fCheckNeutral && usUnderFireID[i]->aiData.bNeutral) &&
ubUnderFireCTH[i] > cth)
{
cth = ubUnderFireCTH[i];
@@ -3477,9 +3479,10 @@ UINT8 UnderFire::Chance(INT8 bTeam, INT8 bSide, BOOLEAN fCheckNeutral)
// if an enemy soldier fulfils taboo, make sure to not hit him at all!
BOOLEAN GetBestAoEGridNo(SOLDIERTYPE *pSoldier, INT32* pGridNo, INT16 aRadius, UINT8 uCheckFriends, UINT8 aMinRating, SOLDIER_CONDITION cond, SOLDIER_CONDITION taboo)
{
UINT8 ubLoop, ubLoop2;
UINT16 ubLoop, ubLoop2;
INT32 sGridNo, sFriendTile[MAXMERCS], sOpponentTile[MAXMERCS], sTabooTile[MAXMERCS];
UINT8 ubFriendCnt = 0,ubOpponentCnt = 0, ubTabooCnt = 0, ubOpponentID[MAXMERCS];
UINT16 ubFriendCnt = 0, ubOpponentCnt = 0, ubTabooCnt = 0;
SoldierID ubOpponentID[MAXMERCS];
INT32 bMaxLeft,bMaxRight,bMaxUp,bMaxDown, i, j;
INT8 bPersOL, bPublOL;
SOLDIERTYPE *pFriend;
@@ -3669,7 +3672,7 @@ BOOLEAN GetBestAoEGridNo(SOLDIERTYPE *pSoldier, INT32* pGridNo, INT16 aRadius, U
// Get the ID of the farthest opponent we can see, with an optional minimum range
// puID - ID of the farthest opponent pSoldier can see
// sRange - only return an true and give an idea if opponent found is further away than this
BOOLEAN GetFarthestOpponent(SOLDIERTYPE *pSoldier, UINT8* puID, INT16 sRange)
BOOLEAN GetFarthestOpponent(SOLDIERTYPE *pSoldier, SoldierID *puID, INT16 sRange)
{
INT32 sGridNo;
UINT32 uiLoop;
@@ -3787,23 +3790,19 @@ void CheckTossSelfSmoke(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
// if we can afford the minimum AP cost to throw this tossable item
if (pSoldier->bActionPoints >= ubMinAPcost)
{
INT32 sSpot = pSoldier->sGridNo;
INT8 bLevel = pSoldier->pathing.bLevel;
INT32 sSpot = pSoldier->sGridNo;
INT8 bLevel = pSoldier->pathing.bLevel;
INT32 sTargetSpot = NOWHERE;
INT8 bTargetLevel = bLevel;
INT32 sTargetSpot = NOWHERE;
INT8 bTargetLevel = bLevel;
INT32 sClosestThreat;
UINT8 ubClosestThreatID;
ubClosestThreatID = pSoldier->ubPreviousAttackerID;
INT32 sClosestThreat;
SoldierID ubClosestThreatID = pSoldier->ubPreviousAttackerID;
// try to find good spot for smoke
if (ubClosestThreatID != NOBODY &&
MercPtrs[ubClosestThreatID] &&
!TileIsOutOfBounds(MercPtrs[ubClosestThreatID]->sGridNo))
if (ubClosestThreatID != NOBODY && !TileIsOutOfBounds(ubClosestThreatID->sGridNo))
{
sClosestThreat = MercPtrs[ubClosestThreatID]->sGridNo;
sClosestThreat = ubClosestThreatID->sGridNo;
sTargetSpot = FindTossSpotInDirection(sSpot, bLevel, sClosestThreat, TRUE, TRUE);
}
@@ -3812,11 +3811,9 @@ void CheckTossSelfSmoke(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
{
ubClosestThreatID = ClosestSeenThreatID(pSoldier, uiThreatCnt, SEEN_LAST_TURN);
if (ubClosestThreatID != NOBODY &&
MercPtrs[ubClosestThreatID] &&
!TileIsOutOfBounds(MercPtrs[ubClosestThreatID]->sGridNo))
if (ubClosestThreatID != NOBODY && !TileIsOutOfBounds(ubClosestThreatID->sGridNo))
{
sClosestThreat = MercPtrs[ubClosestThreatID]->sGridNo;
sClosestThreat = ubClosestThreatID->sGridNo;
sTargetSpot = FindTossSpotInDirection(sSpot, bLevel, sClosestThreat, TRUE, TRUE);
}
@@ -3826,11 +3823,9 @@ void CheckTossSelfSmoke(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
{
ubClosestThreatID = ClosestKnownThreatID(pSoldier, uiThreatCnt);
if (ubClosestThreatID != NOBODY &&
MercPtrs[ubClosestThreatID] &&
!TileIsOutOfBounds(MercPtrs[ubClosestThreatID]->sGridNo))
if (ubClosestThreatID != NOBODY && !TileIsOutOfBounds(ubClosestThreatID->sGridNo))
{
sClosestThreat = MercPtrs[ubClosestThreatID]->sGridNo;
sClosestThreat = ubClosestThreatID->sGridNo;
sTargetSpot = FindTossSpotInDirection(sSpot, bLevel, sClosestThreat, TRUE, TRUE);
}
@@ -3892,13 +3887,13 @@ void CheckTossFriendSmoke(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
INT8 bLevel = pSoldier->pathing.bLevel;
// check all friends
SOLDIERTYPE * pFriend;
INT32 sClosestFriendSpot = NOWHERE;
INT8 bClosestFriendLevel = 0;
UINT8 ubClosestFriendID = NOBODY;
SOLDIERTYPE *pFriend;
INT32 sClosestFriendSpot = NOWHERE;
INT8 bClosestFriendLevel = 0;
SoldierID ubClosestFriendID = NOBODY;
INT32 sFriendSpot;
INT8 bFriendLevel;
INT8 bFriendLevel;
INT32 sClosestOpponent;
@@ -3908,9 +3903,9 @@ void CheckTossFriendSmoke(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
UINT8 ubDirection;
// Run through each friendly.
for (UINT8 iCounter = gTacticalStatus.Team[pSoldier->bTeam].bFirstID; iCounter <= gTacticalStatus.Team[pSoldier->bTeam].bLastID; iCounter++)
for ( SoldierID iCounter = gTacticalStatus.Team[pSoldier->bTeam].bFirstID; iCounter <= gTacticalStatus.Team[pSoldier->bTeam].bLastID; ++iCounter)
{
pFriend = MercPtrs[iCounter];
pFriend = iCounter;
// check that friend is alive and needs cover
if (pFriend &&
@@ -4006,7 +4001,7 @@ void CheckTossFriendSmoke(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow)
// check if we can toss grenade at spot, and prepare attack data
// grenade should be in hand
void CheckTossAt(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow, INT32 sTargetSpot, INT8 bTargetLevel, UINT8 ubOpponentID)
void CheckTossAt(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow, INT32 sTargetSpot, INT8 bTargetLevel, SoldierID ubOpponentID)
{
UINT16 usInHand, usGrenade;
INT32 iTossRange;
+11 -11
View File
@@ -1,11 +1,11 @@
#include "types.h"
//#include "soldier control.h"
//#include "Soldier Control.h"
#include "ai.h"
#include "AIInternals.h"
#include "opplist.h"
#include "Items.h"
#include "Rotting Corpses.h"
#include "soldier add.h"
#include "Soldier Add.h"
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
@@ -66,11 +66,11 @@ INT8 gbHuntCallPriority[NUM_CREATURE_CALLS] =
void CreatureCall( SOLDIERTYPE * pCaller )
{
UINT8 ubCallerType=0;
UINT8 ubReceiver;
INT8 bFullPriority;
INT8 bPriority;
SOLDIERTYPE * pReceiver;
UINT16 usDistToCaller;
SoldierID ubReceiver;
INT8 bFullPriority;
INT8 bPriority;
SOLDIERTYPE *pReceiver;
UINT16 usDistToCaller;
// communicate call to all creatures on map through ultrasonics
gTacticalStatus.Team[pCaller->bTeam].bAwareOfOpposition = TRUE;
@@ -121,9 +121,9 @@ void CreatureCall( SOLDIERTYPE * pCaller )
}
for (ubReceiver = gTacticalStatus.Team[ pCaller->bTeam ].bFirstID; ubReceiver <= gTacticalStatus.Team[ pCaller->bTeam ].bLastID; ubReceiver++)
for (ubReceiver = gTacticalStatus.Team[ pCaller->bTeam ].bFirstID; ubReceiver <= gTacticalStatus.Team[ pCaller->bTeam ].bLastID; ++ubReceiver )
{
pReceiver = MercPtrs[ubReceiver];
pReceiver = ubReceiver;
if (pReceiver->bActive && pReceiver->bInSector && (pReceiver->stats.bLife >= OKLIFE) && (pReceiver != pCaller) && (pReceiver->aiData.bAlertStatus < STATUS_BLACK))
{
if (pReceiver->ubBodyType != LARVAE_MONSTER && pReceiver->ubBodyType != INFANT_MONSTER && pReceiver->ubBodyType != QUEENMONSTER)
@@ -1154,8 +1154,8 @@ INT8 CreatureDecideActionBlack( SOLDIERTYPE * pSoldier )
// if the selected opponent is not a threat (unconscious & !serviced)
// (usually, this means all the guys we see our unconscious, but, on
// rare occasions, we may not be able to shoot a healthy guy, too)
if ((Menptr[BestShot.ubOpponent].stats.bLife < OKLIFE) &&
!Menptr[BestShot.ubOpponent].bService)
if ((BestShot.ubOpponent->stats.bLife < OKLIFE) &&
!BestShot.ubOpponent->bService)
{
// if our attitude is NOT aggressive
if (pSoldier->aiData.bAttitude != AGGRESSIVE)
+130 -125
View File
@@ -1,32 +1,32 @@
#include "ai.h"
#include "AIInternals.h"
#include "Isometric utils.h"
#include "Isometric Utils.h"
#include "Points.h"
#include "overhead.h"
#include "Overhead.h"
#include "opplist.h"
#include "items.h"
#include "Items.h"
#include "Weapons.h"
#include "NPC.h"
#include "Soldier Functions.h"
#include "worldman.h"
#include "Scheduling.h"
#include "Message.h"
#include "message.h"
#include "Structure Wrap.h"
#include "Keys.h"
#include "pathai.h"
#include "PATHAI.H"
#include "Render Fun.h"
#include "Boxing.h"
// #include "Air Raid.h"
#include "Soldier Profile.h"
#include "soldier profile type.h"
#include "Soldier macros.h"
#include "los.h"
#include "LOS.h"
#include "Buildings.h"
#include "strategicmap.h"
#include "Quests.h"
#include "Map Screen Interface Map.h"
#include "soldier ani.h"
#include "rotting corpses.h"
#include "Soldier Ani.h"
#include "Rotting Corpses.h"
#include "GameSettings.h"
#include "Dialogue Control.h"
#include "connect.h"
@@ -44,7 +44,7 @@ extern bool gLogDecideActionRed;
extern BOOLEAN gfHiddenInterrupt;
extern BOOLEAN gfUseAlternateQueenPosition;
extern UINT16 PickSoldierReadyAnimation( SOLDIERTYPE *pSoldier, BOOLEAN fEndReady, BOOLEAN fHipStance );
extern void IncrementWatchedLoc(UINT8 ubID, INT32 sGridNo, INT8 bLevel);
extern void IncrementWatchedLoc(UINT16 ubID, INT32 sGridNo, INT8 bLevel);
void LogDecideInfo(SOLDIERTYPE *pSoldier, bool doLog = true);
void LogKnowledgeInfo(SOLDIERTYPE *pSoldier, bool doLog);
INT8 DecideActionWearGasmask(SOLDIERTYPE* pSoldier);
@@ -598,10 +598,10 @@ INT8 DecideActionBoxerEnteringRing(SOLDIERTYPE *pSoldier)
INT8 DecideActionNamedNPC( SOLDIERTYPE * pSoldier )
{
INT32 sDesiredMercLoc;
UINT8 ubDesiredMercDir;
UINT8 ubDesiredMerc;
INT32 sDesiredMercDist;
INT32 sDesiredMercLoc;
UINT8 ubDesiredMercDir;
SoldierID ubDesiredMerc;
INT32 sDesiredMercDist;
#ifdef DEBUGDECISIONS
STR16 tempstr;
#endif
@@ -757,9 +757,9 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
{
// WANNE: This should fix the bug if any merc are still under PC control. This could happen after boxing in SAN MONA.
SOLDIERTYPE *pTeamSoldier;
for (INT8 bLoop=gTacticalStatus.Team[gbPlayerNum].bFirstID; bLoop <= gTacticalStatus.Team[gbPlayerNum].bLastID; bLoop++)
for ( SoldierID bLoop=gTacticalStatus.Team[gbPlayerNum].bFirstID; bLoop <= gTacticalStatus.Team[gbPlayerNum].bLastID; ++bLoop )
{
pTeamSoldier=MercPtrs[bLoop];
pTeamSoldier = bLoop;
if (pTeamSoldier->flags.uiStatusFlags & SOLDIER_PCUNDERAICONTROL)
pTeamSoldier->flags.uiStatusFlags &= (~SOLDIER_PCUNDERAICONTROL);
@@ -930,7 +930,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
// Flugente: if we see one of our buddies in handcuffs, its a clear sign of enemy activity!
if ( gGameExternalOptions.fAllowPrisonerSystem && pSoldier->bTeam == ENEMY_TEAM && !gTacticalStatus.Team[pSoldier->bTeam].bAwareOfOpposition )
{
UINT8 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 20, ENEMY_TEAM, SOLDIER_POW, TRUE );
SoldierID ubPerson = GetClosestFlaggedSoldierID( pSoldier, 20, ENEMY_TEAM, SOLDIER_POW, TRUE );
if ( ubPerson != NOBODY )
{
@@ -942,7 +942,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
// if we are a doctor with medical gear, we might be able to help a wounded ally
if ( pSoldier->CanMedicAI() )
{
UINT8 ubPerson = GetClosestWoundedSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius, pSoldier->bTeam);
SoldierID ubPerson = GetClosestWoundedSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius, pSoldier->bTeam);
// are we ourselves the patient?
if ( ubPerson == pSoldier->ubID )
@@ -959,10 +959,10 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
}
else if ( ubPerson != NOBODY )
{
if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) < 2 )
if ( PythSpacesAway(pSoldier->sGridNo, ubPerson->sGridNo) < 2 )
{
// see if we are facing this person
UINT8 ubDesiredMercDir = GetDirectionFromCenterCellXYGridNo(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo);
UINT8 ubDesiredMercDir = GetDirectionFromCenterCellXYGridNo(pSoldier->sGridNo, ubPerson->sGridNo);
// if not already facing in that direction,
if ( pSoldier->ubDirection != ubDesiredMercDir )
@@ -984,7 +984,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
}
else
{
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, ubPerson->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
@@ -996,13 +996,13 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
// if we are not a medic, but are wounded, seek a medic
else if ( pSoldier->iHealableInjury >= gGameExternalOptions.sEnemyMedicsWoundMinAmount )
{
UINT8 ubPerson = GetClosestMedicSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius / 2, pSoldier->bTeam);
SoldierID ubPerson = GetClosestMedicSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius / 2, pSoldier->bTeam);
if ( ubPerson != NOBODY )
{
if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) > 1 )
if ( PythSpacesAway(pSoldier->sGridNo, ubPerson->sGridNo) > 1 )
{
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, ubPerson->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
@@ -1016,14 +1016,14 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
if ( pSoldier->usSoldierFlagMask & SOLDIER_BODYGUARD )
{
// is VIP still alive?
UINT16 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 100, pSoldier->bTeam, SOLDIER_VIP, FALSE );
SoldierID ubPerson = GetClosestFlaggedSoldierID( pSoldier, 100, pSoldier->bTeam, SOLDIER_VIP, FALSE );
if ( ubPerson != NOBODY )
{
// we want to stay close to him, but still be able to function properly... stay withing a 7-tile radius
if ( SpacesAway( pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo ) > 7 )
if ( SpacesAway( pSoldier->sGridNo, ubPerson->sGridNo ) > 7 )
{
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards( pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0 );
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards( pSoldier, ubPerson->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0 );
if ( !TileIsOutOfBounds( pSoldier->aiData.usActionData ) )
{
@@ -1652,18 +1652,18 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
// Flugente: if we see one of our buddies captured, it is a clear sign of enemy activity!
if ( gGameExternalOptions.fAllowPrisonerSystem && pSoldier->bTeam == ENEMY_TEAM )
{
UINT8 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 20, ENEMY_TEAM, SOLDIER_POW, TRUE );
SoldierID ubPerson = GetClosestFlaggedSoldierID( pSoldier, 20, ENEMY_TEAM, SOLDIER_POW, TRUE );
if ( ubPerson != NOBODY )
{
// if we are close, we can release this guy
// possible only if not handcuffed (binders can be opened, handcuffs not)
if ( !HasItemFlag( (&(MercPtrs[ubPerson]->inv[HANDPOS]))->usItem, HANDCUFFS ) )
if ( !HasItemFlag( (&(ubPerson->inv[HANDPOS]))->usItem, HANDCUFFS ) )
{
if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) < 2 )
if ( PythSpacesAway(pSoldier->sGridNo, ubPerson->sGridNo) < 2 )
{
// see if we are facing this person
UINT8 ubDesiredMercDir = GetDirectionFromCenterCellXYGridNo(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo);
UINT8 ubDesiredMercDir = GetDirectionFromCenterCellXYGridNo(pSoldier->sGridNo, ubPerson->sGridNo);
// if not already facing in that direction,
if ( pSoldier->ubDirection != ubDesiredMercDir )
@@ -1677,7 +1677,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
}
else
{
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, ubPerson->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
@@ -1696,7 +1696,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
// if we are a doctor with medical gear, we might be able to help a wounded ally
if ( pSoldier->CanMedicAI() )
{
UINT8 ubPerson = GetClosestWoundedSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius, pSoldier->bTeam);
SoldierID ubPerson = GetClosestWoundedSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius, pSoldier->bTeam);
// are we ourselves the patient?
if ( ubPerson == pSoldier->ubID )
@@ -1713,10 +1713,10 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
}
else if ( ubPerson != NOBODY )
{
if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) < 2 )
if ( PythSpacesAway(pSoldier->sGridNo, ubPerson->sGridNo) < 2 )
{
// see if we are facing this person
UINT8 ubDesiredMercDir = GetDirectionFromCenterCellXYGridNo(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo);
UINT8 ubDesiredMercDir = GetDirectionFromCenterCellXYGridNo(pSoldier->sGridNo, ubPerson->sGridNo);
// if not already facing in that direction,
if ( pSoldier->ubDirection != ubDesiredMercDir )
@@ -1738,7 +1738,7 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
}
else
{
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, ubPerson->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
@@ -1750,13 +1750,13 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
// if we are not a medic, but are wounded, seek a medic
else if ( pSoldier->iHealableInjury >= gGameExternalOptions.sEnemyMedicsWoundMinAmount )
{
UINT8 ubPerson = GetClosestMedicSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius / 2, pSoldier->bTeam);
SoldierID ubPerson = GetClosestMedicSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius / 2, pSoldier->bTeam);
if ( ubPerson != NOBODY )
{
if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) > 1 )
if ( PythSpacesAway(pSoldier->sGridNo, ubPerson->sGridNo) > 1 )
{
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, ubPerson->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
@@ -1770,14 +1770,14 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
if ( pSoldier->usSoldierFlagMask & SOLDIER_BODYGUARD )
{
// is VIP still alive?
UINT16 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 100, pSoldier->bTeam, SOLDIER_VIP, FALSE );
SoldierID ubPerson = GetClosestFlaggedSoldierID( pSoldier, 100, pSoldier->bTeam, SOLDIER_VIP, FALSE );
if ( ubPerson != NOBODY )
{
// we want to stay close to him, but still be able to function properly... stay withing a 7-tile radius
if ( SpacesAway( pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo ) > 7 )
if ( SpacesAway( pSoldier->sGridNo, ubPerson->sGridNo ) > 7 )
{
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards( pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0 );
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards( pSoldier, ubPerson->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0 );
if ( !TileIsOutOfBounds( pSoldier->aiData.usActionData ) )
{
@@ -2546,32 +2546,35 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
}
// if we're an alerted enemy, and there are panic bombs or a trigger around
if ( (!PTR_CIVILIAN || pSoldier->ubProfile == WARDEN) && ( ( gTacticalStatus.Team[pSoldier->bTeam].bAwareOfOpposition || (pSoldier->ubID == gTacticalStatus.ubTheChosenOne) || (pSoldier->ubProfile == WARDEN) ) &&
(gTacticalStatus.fPanicFlags & (PANIC_BOMBS_HERE | PANIC_TRIGGERS_HERE ) ) ) )
if ( !ENEMYROBOT(pSoldier) )
{
if ( pSoldier->ubProfile == WARDEN && gTacticalStatus.ubTheChosenOne == NOBODY )
if ( (!PTR_CIVILIAN || pSoldier->ubProfile == WARDEN) && ( ( gTacticalStatus.Team[pSoldier->bTeam].bAwareOfOpposition || (pSoldier->ubID == gTacticalStatus.ubTheChosenOne) || (pSoldier->ubProfile == WARDEN) ) &&
(gTacticalStatus.fPanicFlags & (PANIC_BOMBS_HERE | PANIC_TRIGGERS_HERE ) ) ) )
{
PossiblyMakeThisEnemyChosenOne( pSoldier );
if ( pSoldier->ubProfile == WARDEN && gTacticalStatus.ubTheChosenOne == NOBODY )
{
PossiblyMakeThisEnemyChosenOne( pSoldier );
}
// do some special panic AI decision making
bActionReturned = PanicAI(pSoldier,ubCanMove);
// if we decided on an action while in there, we're done
if (bActionReturned != -1)
return(bActionReturned);
}
// do some special panic AI decision making
bActionReturned = PanicAI(pSoldier,ubCanMove);
// if we decided on an action while in there, we're done
if (bActionReturned != -1)
return(bActionReturned);
}
if ( pSoldier->ubProfile != NO_PROFILE )
{
if ( (pSoldier->ubProfile == QUEEN || pSoldier->ubProfile == JOE) && ubCanMove )
if ( pSoldier->ubProfile != NO_PROFILE )
{
if ( gWorldSectorX == 3 && gWorldSectorY == MAP_ROW_P && gbWorldSectorZ == 0 && !gfUseAlternateQueenPosition )
if ( (pSoldier->ubProfile == QUEEN || pSoldier->ubProfile == JOE) && ubCanMove )
{
bActionReturned = HeadForTheStairCase( pSoldier );
if ( bActionReturned != AI_ACTION_NONE )
if ( gWorldSectorX == 3 && gWorldSectorY == MAP_ROW_P && gbWorldSectorZ == 0 && !gfUseAlternateQueenPosition )
{
return( bActionReturned );
bActionReturned = HeadForTheStairCase( pSoldier );
if ( bActionReturned != AI_ACTION_NONE )
{
return( bActionReturned );
}
}
}
}
@@ -2722,15 +2725,16 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
{
DebugAI(AI_MSG_INFO, pSoldier, String("throw possible"), gLogDecideActionRed);
// sevenfm: allow using mortars, grenade launchers, flares and grenades in RED state
if (Item[pSoldier->inv[BestThrow.bWeaponIn].usItem].mortar ||
//Item[pSoldier->inv[ BestThrow.bWeaponIn ].usItem].cannon ||
Item[pSoldier->inv[BestThrow.bWeaponIn].usItem].rocketlauncher ||
Item[pSoldier->inv[BestThrow.bWeaponIn].usItem].grenadelauncher ||
Item[pSoldier->inv[BestThrow.bWeaponIn].usItem].flare ||
Item[pSoldier->inv[BestThrow.bWeaponIn].usItem].usItemClass & IC_GRENADE)
UINT16 usItem = pSoldier->inv[BestThrow.bWeaponIn].usItem;
if (ItemIsMortar(usItem) ||
//Item[usItem].cannon ||
ItemIsRocketLauncher(usItem) ||
ItemIsGrenadeLauncher(usItem) ||
ItemIsFlare(usItem) ||
Item[usItem].usItemClass & IC_GRENADE)
{
// if firing mortar make sure we have room
if (Item[pSoldier->inv[BestThrow.bWeaponIn].usItem].mortar)
if (ItemIsMortar(usItem))
{
DebugAI(AI_MSG_INFO, pSoldier, String("using mortar, check room to deploy"), gLogDecideActionRed);
ubOpponentDir = AIDirection(pSoldier->sGridNo, BestThrow.sTarget);
@@ -2875,7 +2879,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), gLogDecideActionRed);
// start retreating for several turns
if (BestThrow.ubOpponent != NOBODY && !MercPtrs[BestThrow.ubOpponent]->IsFlanking())
if (BestThrow.ubOpponent != NOBODY && !BestThrow.ubOpponent->IsFlanking())
{
DebugAI(AI_MSG_INFO, pSoldier, String("start retreat counter for %d", BestThrow.ubOpponent), gLogDecideActionRed);
MercPtrs[BestThrow.ubOpponent]->RetreatCounterStart(2);
@@ -3032,8 +3036,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
// check valid target
!TileIsOutOfBounds(BestShot.sTarget) &&
BestShot.ubOpponent != NOBODY &&
MercPtrs[BestShot.ubOpponent] &&
Chance(100 - MercPtrs[BestShot.ubOpponent]->ShockLevelPercent() / 2) &&
Chance(100 - BestShot.ubOpponent->ShockLevelPercent() / 2) &&
// check weapon/ammo requirements
IsGunAutofireCapable(&pSoldier->inv[BestShot.bWeaponIn]) &&
GetMagSize(&pSoldier->inv[BestShot.bWeaponIn]) >= gGameExternalOptions.ubAISuppressionMinimumMagSize &&
@@ -3050,16 +3053,16 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
!fCanBeSeen && NightLight() && CountFriendsFlankSameSpot(pSoldier, sClosestOpponent) && Chance(50) ||
ARMED_VEHICLE(pSoldier) || // tanks don't need cover
ENEMYROBOT(pSoldier) || // robots don't try to be in cover
pSoldier->aiData.bUnderFire && (pSoldier->ubPreviousAttackerID == BestShot.ubOpponent || pSoldier->ubNextToPreviousAttackerID == BestShot.ubOpponent || MercPtrs[BestShot.ubOpponent]->sLastTarget == pSoldier->sGridNo) || // return fire
pSoldier->aiData.bUnderFire && (pSoldier->ubPreviousAttackerID == BestShot.ubOpponent || pSoldier->ubNextToPreviousAttackerID == BestShot.ubOpponent || BestShot.ubOpponent->sLastTarget == pSoldier->sGridNo) || // return fire
Chance((BestShot.ubChanceToReallyHit + 100) / 2) || // 50% chance to fire without cover
//SoldierToSoldierLineOfSightTest(pSoldier, MercPtrs[BestShot.ubOpponent], TRUE, CALC_FROM_ALL_DIRS)) && // can see target after turning
LOS_Raised(pSoldier, MercPtrs[BestShot.ubOpponent], CALC_FROM_ALL_DIRS)) && // can see target after turning
//SoldierToSoldierLineOfSightTest(pSoldier, BestShot.ubOpponent, TRUE, CALC_FROM_ALL_DIRS)) && // can see target after turning
LOS_Raised(pSoldier, BestShot.ubOpponent, CALC_FROM_ALL_DIRS)) && // can see target after turning
// reduce chance to shoot if target is beyond weapon range
(AICheckIsMachinegunner(pSoldier) ||
ARMED_VEHICLE(pSoldier) ||
ENEMYROBOT(pSoldier) ||
AnyCoverAtSpot(pSoldier, pSoldier->sGridNo) ||
pSoldier->aiData.bUnderFire && (pSoldier->ubPreviousAttackerID == BestShot.ubOpponent || pSoldier->ubNextToPreviousAttackerID == BestShot.ubOpponent || MercPtrs[BestShot.ubOpponent]->sLastTarget == pSoldier->sGridNo) || // return fire
pSoldier->aiData.bUnderFire && (pSoldier->ubPreviousAttackerID == BestShot.ubOpponent || pSoldier->ubNextToPreviousAttackerID == BestShot.ubOpponent || BestShot.ubOpponent->sLastTarget == pSoldier->sGridNo) || // return fire
Chance(100 * (GunRange(&pSoldier->inv[BestShot.bWeaponIn], pSoldier) / CELL_X_SIZE) / PythSpacesAway(pSoldier->sGridNo, BestShot.sTarget))) &&
// check that we have spare ammo
(fExtraClip || pSoldier->inv[BestShot.bWeaponIn][0]->data.gun.ubGunShotsLeft >= gGameExternalOptions.ubAISuppressionMinimumMagSize))
@@ -3153,7 +3156,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
DebugAI(AI_MSG_INFO, pSoldier, String("Change stance before shooting"), gLogDecideActionRed);
// show "suppression fire" message only if opponent cannot be seen after turning
if (!LOS_Raised(pSoldier, MercPtrs[BestShot.ubOpponent], CALC_FROM_ALL_DIRS))
if (!LOS_Raised(pSoldier, BestShot.ubOpponent, CALC_FROM_ALL_DIRS))
ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_SUPPRESSIONFIRE]);
return(AI_ACTION_CHANGE_STANCE);
@@ -3163,7 +3166,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
pSoldier->aiData.usActionData = BestShot.sTarget;
// show "suppression fire" message only if opponent cannot be seen after turning
if (!LOS_Raised(pSoldier, MercPtrs[BestShot.ubOpponent], CALC_FROM_ALL_DIRS))
if (!LOS_Raised(pSoldier, BestShot.ubOpponent, CALC_FROM_ALL_DIRS))
ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_SUPPRESSIONFIRE]);
DebugAI(AI_MSG_INFO, pSoldier, String("Suppression fire!"), gLogDecideActionRed);
@@ -3297,7 +3300,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
if ( gGameExternalOptions.fAllowPrisonerSystem && pSoldier->bTeam == ENEMY_TEAM )
{
DebugAI(AI_MSG_TOPIC, pSoldier, String("[Free friendly POWs]"), gLogDecideActionRed);
UINT8 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 20, ENEMY_TEAM, SOLDIER_POW, TRUE );
SoldierID ubPerson = GetClosestFlaggedSoldierID( pSoldier, 20, ENEMY_TEAM, SOLDIER_POW, TRUE );
if ( ubPerson != NOBODY )
{
@@ -3305,14 +3308,14 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
// if we are close, we can release this guy
// possible only if not handcuffed (binders can be opened, handcuffs not)
if ( !HasItemFlag( (&(MercPtrs[ubPerson]->inv[HANDPOS]))->usItem, HANDCUFFS ) )
if ( !HasItemFlag( (&(ubPerson->inv[HANDPOS]))->usItem, HANDCUFFS ) )
{
if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) < 2 )
if ( PythSpacesAway(pSoldier->sGridNo, ubPerson->sGridNo) < 2 )
{
DebugAI(AI_MSG_INFO, pSoldier, String("I am close enough to free POW"), gLogDecideActionRed);
// see if we are facing this person
UINT8 ubDesiredMercDir = GetDirectionFromCenterCellXYGridNo(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo);
UINT8 ubDesiredMercDir = GetDirectionFromCenterCellXYGridNo(pSoldier->sGridNo, ubPerson->sGridNo);
// if not already facing in that direction,
if ( pSoldier->ubDirection != ubDesiredMercDir )
@@ -3328,7 +3331,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
}
else
{
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, ubPerson->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
@@ -3350,7 +3353,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
{
DebugAI(AI_MSG_TOPIC, pSoldier, String("[Provide medical aid]"), gLogDecideActionRed);
UINT8 ubPerson = GetClosestWoundedSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius, pSoldier->bTeam);
SoldierID ubPerson = GetClosestWoundedSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius, pSoldier->bTeam);
// are we ourselves the patient?
if ( ubPerson == pSoldier->ubID )
@@ -3372,12 +3375,12 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
{
DebugAI(AI_MSG_INFO, pSoldier, String("Someone else is injured"), gLogDecideActionRed);
if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) < 2 )
if ( PythSpacesAway(pSoldier->sGridNo, ubPerson->sGridNo) < 2 )
{
DebugAI(AI_MSG_INFO, pSoldier, String("Wounded soldier is nearby"), gLogDecideActionRed);
// see if we are facing this person
UINT8 ubDesiredMercDir = GetDirectionFromCenterCellXYGridNo(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo);
UINT8 ubDesiredMercDir = GetDirectionFromCenterCellXYGridNo(pSoldier->sGridNo, ubPerson->sGridNo);
// if not already facing in that direction,
if ( pSoldier->ubDirection != ubDesiredMercDir )
@@ -3403,7 +3406,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
else
{
DebugAI(AI_MSG_INFO, pSoldier, String("Wounded soldier is far"), gLogDecideActionRed);
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, ubPerson->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
@@ -3418,15 +3421,15 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
{
DebugAI(AI_MSG_TOPIC, pSoldier, String("[Seek medical aid]"), gLogDecideActionRed);
UINT8 ubPerson = GetClosestMedicSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius / 2, pSoldier->bTeam);
SoldierID ubPerson = GetClosestMedicSoldierID( pSoldier, gGameExternalOptions.sEnemyMedicsSearchRadius / 2, pSoldier->bTeam);
if ( ubPerson != NOBODY )
{
DebugAI(AI_MSG_INFO, pSoldier, String("Found a medic!"), gLogDecideActionRed);
if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) > 1 )
if ( PythSpacesAway(pSoldier->sGridNo, ubPerson->sGridNo) > 1 )
{
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, ubPerson->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0);
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
@@ -3475,16 +3478,16 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier)
{
DebugAI(AI_MSG_TOPIC, pSoldier, String("[Bodyguard]"), gLogDecideActionRed);
// is VIP still alive?
UINT16 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 100, pSoldier->bTeam, SOLDIER_VIP, FALSE );
SoldierID ubPerson = GetClosestFlaggedSoldierID( pSoldier, 100, pSoldier->bTeam, SOLDIER_VIP, FALSE );
if ( ubPerson != NOBODY )
{
DebugAI(AI_MSG_INFO, pSoldier, String("VIP found"), gLogDecideActionRed);
// we want to stay close to him, but still be able to function properly... stay withing a 7-tile radius
if ( SpacesAway( pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo ) > 7 )
if ( SpacesAway( pSoldier->sGridNo, ubPerson->sGridNo ) > 7 )
{
DebugAI(AI_MSG_INFO, pSoldier, String("Attempt to get close "), gLogDecideActionRed);
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards( pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0 );
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards( pSoldier, ubPerson->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0 );
if ( !TileIsOutOfBounds( pSoldier->aiData.usActionData ) )
{
@@ -5283,13 +5286,16 @@ INT8 DecideActionBlack(SOLDIERTYPE *pSoldier)
// offer surrender?
#ifndef JA2UB
if ( pSoldier->bTeam == ENEMY_TEAM && pSoldier->bVisible == TRUE && !(gTacticalStatus.fEnemyFlags & ENEMY_OFFERED_SURRENDER) && pSoldier->stats.bLife >= pSoldier->stats.bLifeMax / 2 && !ARMED_VEHICLE( pSoldier ) && !ENEMYROBOT( pSoldier ) )
if ( !is_networked ) // No surrender in multiplayer
{
if ( gTacticalStatus.Team[ MILITIA_TEAM ].bMenInSector == 0 && gTacticalStatus.Team[ CREATURE_TEAM ].bMenInSector == 0 && NumPCsInSector() < 4 && gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector >= NumPCsInSector() * 3 )
if ( pSoldier->bTeam == ENEMY_TEAM && pSoldier->bVisible == TRUE && !(gTacticalStatus.fEnemyFlags & ENEMY_OFFERED_SURRENDER) && pSoldier->stats.bLife >= pSoldier->stats.bLifeMax / 2 && !ARMED_VEHICLE( pSoldier ) && !ENEMYROBOT( pSoldier ) )
{
if (gubQuest[QUEST_HELD_IN_ALMA] == QUESTNOTSTARTED || gubQuest[QUEST_HELD_IN_TIXA] == QUESTNOTSTARTED || gubQuest[QUEST_INTERROGATION] == QUESTNOTSTARTED)
if ( gTacticalStatus.Team[ MILITIA_TEAM ].bMenInSector == 0 && gTacticalStatus.Team[ CREATURE_TEAM ].bMenInSector == 0 && NumPCsInSector() < 4 && gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector >= NumPCsInSector() * 3 )
{
return( AI_ACTION_OFFER_SURRENDER );
if (gubQuest[QUEST_HELD_IN_ALMA] == QUESTNOTSTARTED || gubQuest[QUEST_HELD_IN_TIXA] == QUESTNOTSTARTED || gubQuest[QUEST_INTERROGATION] == QUESTNOTSTARTED)
{
return( AI_ACTION_OFFER_SURRENDER );
}
}
}
}
@@ -5646,7 +5652,7 @@ INT8 DecideActionBlack(SOLDIERTYPE *pSoldier)
if (BestThrow.ubPossible)
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"good throw possible");
if ( Item[pSoldier->inv[ BestThrow.bWeaponIn ].usItem].mortar )
if (ItemIsMortar(pSoldier->inv[ BestThrow.bWeaponIn ].usItem))
{
ubOpponentDir = AIDirection(pSoldier->sGridNo, BestThrow.sTarget);
@@ -5906,10 +5912,9 @@ INT8 DecideActionBlack(SOLDIERTYPE *pSoldier)
BOXER(pSoldier) &&
SpacesAway(pSoldier->sGridNo, BestStab.sTarget) > 2 &&
BestStab.ubOpponent != NOBODY &&
MercPtrs[BestStab.ubOpponent] &&
AIDirection(pSoldier->sGridNo, MercPtrs[BestStab.ubOpponent]->sGridNo) != MercPtrs[BestStab.ubOpponent]->ubDirection &&
AIDirection(pSoldier->sGridNo, MercPtrs[BestStab.ubOpponent]->sGridNo) != gOneCDirection[MercPtrs[BestStab.ubOpponent]->ubDirection] &&
AIDirection(pSoldier->sGridNo, MercPtrs[BestStab.ubOpponent]->sGridNo) != gOneCCDirection[MercPtrs[BestStab.ubOpponent]->ubDirection] &&
AIDirection(pSoldier->sGridNo, BestStab.ubOpponent->sGridNo) != BestStab.ubOpponent->ubDirection &&
AIDirection(pSoldier->sGridNo, BestStab.ubOpponent->sGridNo) != gOneCDirection[BestStab.ubOpponent->ubDirection] &&
AIDirection(pSoldier->sGridNo, BestStab.ubOpponent->sGridNo) != gOneCCDirection[BestStab.ubOpponent->ubDirection] &&
pSoldier->bInitialActionPoints >= 2 * MinAPsToAttack(pSoldier, pSoldier->sLastTarget, FALSE, 0, 0) + APBPConstants[AP_MOVEMENT_FLAT] + APBPConstants[AP_MODIFIER_WALK] &&
pSoldier->bActionPoints < BestStab.ubAPCost + MinAPsToAttack(pSoldier, pSoldier->sLastTarget, FALSE, 0, 0))
{
@@ -5923,10 +5928,9 @@ INT8 DecideActionBlack(SOLDIERTYPE *pSoldier)
BOXER(pSoldier) &&
SpacesAway(pSoldier->sGridNo, BestStab.sTarget) > 1 &&
BestStab.ubOpponent != NOBODY &&
MercPtrs[BestStab.ubOpponent] &&
gAnimControl[MercPtrs[BestStab.ubOpponent]->usAnimState].ubEndHeight == ANIM_STAND &&
MercPtrs[BestStab.ubOpponent]->bActionPoints > 0 &&
Chance(EffectiveAgility(MercPtrs[BestStab.ubOpponent], FALSE) * (100 + MercPtrs[BestStab.ubOpponent]->bBreath) * EffectiveWisdom(pSoldier) / (100 * 200)))
gAnimControl[BestStab.ubOpponent->usAnimState].ubEndHeight == ANIM_STAND &&
BestStab.ubOpponent->bActionPoints > 0 &&
Chance(EffectiveAgility(BestStab.ubOpponent, FALSE) * (100 + BestStab.ubOpponent->bBreath) * EffectiveWisdom(pSoldier) / (100 * 200)))
{
// find closest spot around opponent, avoid front direction
UINT8 ubMovementCost;
@@ -5946,7 +5950,7 @@ INT8 DecideActionBlack(SOLDIERTYPE *pSoldier)
if (ubMovementCost < TRAVELCOST_BLOCKED &&
NewOKDestination(pSoldier, sTempGridNo, FALSE, pSoldier->pathing.bLevel) &&
AIDirection(BestStab.sTarget, sTempGridNo) != MercPtrs[BestStab.ubOpponent]->ubDirection)
AIDirection(BestStab.sTarget, sTempGridNo) != BestStab.ubOpponent->ubDirection)
{
sPathCost = PlotPath(pSoldier, sTempGridNo, FALSE, FALSE, FALSE, DetermineMovementMode(pSoldier, AI_ACTION_GET_CLOSER), pSoldier->bStealthMode, pSoldier->bReverse, 0);
if (TileIsOutOfBounds(sBestSpot) || sPathCost < sBestPathCost)
@@ -5984,7 +5988,7 @@ INT8 DecideActionBlack(SOLDIERTYPE *pSoldier)
// SANDRO - added a chance to try to steal merc's gun from hands
else
{
if (AIDetermineStealingWeaponAttempt( pSoldier, MercPtrs[BestStab.ubOpponent] ) == TRUE)
if (AIDetermineStealingWeaponAttempt( pSoldier, BestStab.ubOpponent ) == TRUE)
{
ubBestAttackAction = AI_ACTION_STEAL_MOVE;
DebugAI(AI_MSG_INFO, pSoldier, String("best action = move to steal weapon, iAttackValue = %d", BestStab.iAttackValue));
@@ -6479,7 +6483,7 @@ INT8 DecideActionBlack(SOLDIERTYPE *pSoldier)
}
// SANDRO: more likely to burst when firing from hip
if ( BestAttack.bScopeMode == USE_ALT_WEAPON_HOLD && Item[pSoldier->inv[BestAttack.bWeaponIn].usItem].twohanded )
if ( BestAttack.bScopeMode == USE_ALT_WEAPON_HOLD && ItemIsTwoHanded(pSoldier->inv[BestAttack.bWeaponIn].usItem) )
iChance += 40;
// CHRISL: Changed from a simple flag to two externalized values for more modder control over AI suppression
@@ -6598,7 +6602,7 @@ L_NEWAIM:
}
// SANDRO: more likely to burst when firing from hip
if ( BestAttack.bScopeMode == USE_ALT_WEAPON_HOLD && Item[pSoldier->inv[BestAttack.bWeaponIn].usItem].twohanded )
if ( BestAttack.bScopeMode == USE_ALT_WEAPON_HOLD && ItemIsTwoHanded(pSoldier->inv[BestAttack.bWeaponIn].usItem) )
iChance += 40;
// CHRISL: Changed from a simple flag to two externalized values for more modder control over AI suppression
@@ -7007,13 +7011,11 @@ L_NEWAIM:
{
DebugAI(AI_MSG_TOPIC, pSoldier, String("[Make boxer close if possible]"));
UINT8 ubOpponentID;
SoldierID ubOpponentID;
sClosestOpponent = ClosestKnownOpponent(pSoldier, NULL, NULL, &ubOpponentID);
DebugAI(AI_MSG_INFO, pSoldier, String("boxer: found closest opponent [%d] at %d", ubOpponentID, sClosestOpponent));
if (!TileIsOutOfBounds(sClosestOpponent) &&
ubOpponentID != NOBODY &&
MercPtrs[ubOpponentID])
if ( !TileIsOutOfBounds(sClosestOpponent) && ubOpponentID != NOBODY )
{
if (pSoldier->bActionPoints > 0)
{
@@ -7050,7 +7052,7 @@ L_NEWAIM:
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData) &&
(pSoldier->bBreath < OKBREATH ||
pSoldier->bBreath < pSoldier->bBreathMax &&
pSoldier->bBreath < MercPtrs[ubOpponentID]->bBreath &&
pSoldier->bBreath < ubOpponentID->bBreath &&
Chance((100 - pSoldier->bBreath) * (100 - pSoldier->bBreath) / (2 * 100 * 100))))
{
DebugAI(AI_MSG_INFO, pSoldier, String("boxer: restore breath"));
@@ -7074,7 +7076,7 @@ L_NEWAIM:
}
else if (pSoldier->bBreath < OKBREATH ||
pSoldier->bBreath < pSoldier->bBreathMax &&
(pSoldier->bBreath < MercPtrs[ubOpponentID]->bBreath || !pSoldier->aiData.bLastAttackHit && pSoldier->TakenLargeHit()))
(pSoldier->bBreath < ubOpponentID->bBreath || !pSoldier->aiData.bLastAttackHit && pSoldier->TakenLargeHit()))
{
// maybe move away from opponent
UINT8 ubOpponentDir = AIDirection(pSoldier->sGridNo, sClosestOpponent);
@@ -8581,10 +8583,10 @@ INT8 ArmedVehicleDecideActionRed( SOLDIERTYPE *pSoldier)
if ( BestThrow.ubPossible )
{
// if firing mortar make sure we have room
//if ( Item[pSoldier->inv[ BestThrow.bWeaponIn ].usItem].mortar ) //comm by ddd
if ( Item[pSoldier->inv[BestThrow.bWeaponIn].usItem].mortar
|| Item[pSoldier->inv[BestThrow.bWeaponIn].usItem].grenadelauncher
|| Item[pSoldier->inv[BestThrow.bWeaponIn].usItem].flare )
UINT16 usItem = pSoldier->inv[BestThrow.bWeaponIn].usItem;
if (ItemIsMortar(usItem)
|| ItemIsGrenadeLauncher(usItem)
|| ItemIsFlare(usItem) )
{
ubOpponentDir = GetDirectionFromGridNo( BestThrow.sTarget, pSoldier );
@@ -8756,9 +8758,9 @@ INT8 ArmedVehicleDecideActionRed( SOLDIERTYPE *pSoldier)
//&& Menptr[BestShot.ubOpponent].pathing.bLevel == 0
&& pSoldier->aiData.bOrders != SNIPER &&
BestShot.ubFriendlyFireChance < 5 &&
!MercPtrs[BestShot.ubOpponent]->IsCowering() &&
!BestShot.ubOpponent->IsCowering() &&
!AICheckIsFlanking( pSoldier ) &&
LocationToLocationLineOfSightTest( pSoldier->sGridNo, pSoldier->pathing.bLevel, MercPtrs[BestShot.ubOpponent]->sGridNo, MercPtrs[BestShot.ubOpponent]->pathing.bLevel, TRUE, NO_DISTANCE_LIMIT ) &&
LocationToLocationLineOfSightTest( pSoldier->sGridNo, pSoldier->pathing.bLevel, BestShot.ubOpponent->sGridNo, BestShot.ubOpponent->pathing.bLevel, TRUE, NO_DISTANCE_LIMIT ) &&
//Weapon[pSoldier->inv[BestShot.bWeaponIn].usItem].ubWeaponType == GUN_LMG ) && //Weapon[usInHand].ubWeaponClass == MGCLASS
(fExtraClip || pSoldier->inv[BestShot.bWeaponIn][0]->data.gun.ubGunShotsLeft > gGameExternalOptions.ubAISuppressionMinimumMagSize) )
{
@@ -9758,13 +9760,16 @@ INT8 ArmedVehicleDecideActionBlack( SOLDIERTYPE *pSoldier )
// offer surrender?
#ifndef JA2UB
if ( pSoldier->bTeam == ENEMY_TEAM && pSoldier->bVisible == TRUE && !(gTacticalStatus.fEnemyFlags & ENEMY_OFFERED_SURRENDER) && pSoldier->stats.bLife >= pSoldier->stats.bLifeMax / 2 && !ARMED_VEHICLE( pSoldier ) && !ENEMYROBOT( pSoldier ) )
if ( !is_networked ) // No surrender in multiplayer
{
if ( gTacticalStatus.Team[MILITIA_TEAM].bMenInSector == 0 && gTacticalStatus.Team[CREATURE_TEAM].bMenInSector == 0 && NumPCsInSector( ) < 4 && gTacticalStatus.Team[ENEMY_TEAM].bMenInSector >= NumPCsInSector( ) * 3 )
if ( pSoldier->bTeam == ENEMY_TEAM && pSoldier->bVisible == TRUE && !(gTacticalStatus.fEnemyFlags & ENEMY_OFFERED_SURRENDER) && pSoldier->stats.bLife >= pSoldier->stats.bLifeMax / 2 && !ARMED_VEHICLE( pSoldier ) && !ENEMYROBOT( pSoldier ) )
{
if (gubQuest[QUEST_HELD_IN_ALMA] == QUESTNOTSTARTED || gubQuest[QUEST_HELD_IN_TIXA] == QUESTNOTSTARTED || gubQuest[QUEST_INTERROGATION] == QUESTNOTSTARTED)
if ( gTacticalStatus.Team[MILITIA_TEAM].bMenInSector == 0 && gTacticalStatus.Team[CREATURE_TEAM].bMenInSector == 0 && NumPCsInSector() < 4 && gTacticalStatus.Team[ENEMY_TEAM].bMenInSector >= NumPCsInSector() * 3 )
{
return(AI_ACTION_OFFER_SURRENDER);
if ( gubQuest[QUEST_HELD_IN_ALMA] == QUESTNOTSTARTED || gubQuest[QUEST_HELD_IN_TIXA] == QUESTNOTSTARTED || gubQuest[QUEST_INTERROGATION] == QUESTNOTSTARTED )
{
return(AI_ACTION_OFFER_SURRENDER);
}
}
}
}
@@ -9977,7 +9982,7 @@ INT8 ArmedVehicleDecideActionBlack( SOLDIERTYPE *pSoldier )
if ( BestThrow.ubPossible )
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "good throw possible" );
if ( Item[pSoldier->inv[BestThrow.bWeaponIn].usItem].mortar )
if (ItemIsMortar(pSoldier->inv[BestThrow.bWeaponIn].usItem))
{
ubOpponentDir = (UINT8)GetDirectionFromGridNo( BestThrow.sTarget, pSoldier );
+13 -12
View File
@@ -2,11 +2,11 @@
#include "Isometric Utils.h"
#include "ai.h"
#include "AIInternals.h"
#include "los.h"
#include "LOS.h"
#include "Weapons.h"
#include "Opplist.h"
#include "pathai.h"
#include "items.h"
#include "opplist.h"
#include "PATHAI.H"
#include "Items.h"
#include "World Items.h"
#include "Points.h"
#include "message.h"
@@ -107,7 +107,7 @@ void AICenterXY( INT32 sGridNo, FLOAT * pdX, FLOAT * pdY )
*pdY = (FLOAT) (sYPos * CELL_Y_SIZE + CELL_Y_SIZE / 2);
}
INT8 CalcWorstCTGTForPosition( SOLDIERTYPE * pSoldier, UINT8 ubOppID, INT32 sOppGridNo, INT8 bLevel, INT32 iMyAPsLeft )
INT8 CalcWorstCTGTForPosition( SOLDIERTYPE * pSoldier, SoldierID ubOppID, INT32 sOppGridNo, INT8 bLevel, INT32 iMyAPsLeft )
{
// When considering a gridno for cover, we want to take into account cover if we
// lie down, so we return the LOWEST chance to get through for that location.
@@ -146,7 +146,7 @@ INT8 CalcWorstCTGTForPosition( SOLDIERTYPE * pSoldier, UINT8 ubOppID, INT32 sOpp
return( bWorstCTGT );
}
INT8 CalcAverageCTGTForPosition( SOLDIERTYPE * pSoldier, UINT8 ubOppID, INT32 sOppGridNo, INT8 bLevel, INT32 iMyAPsLeft )
INT8 CalcAverageCTGTForPosition( SOLDIERTYPE * pSoldier, SoldierID ubOppID, INT32 sOppGridNo, INT8 bLevel, INT32 iMyAPsLeft )
{
// When considering a gridno for cover, we want to take into account cover if we
// lie down, so we return the LOWEST chance to get through for that location.
@@ -180,7 +180,7 @@ INT8 CalcAverageCTGTForPosition( SOLDIERTYPE * pSoldier, UINT8 ubOppID, INT32 sO
}
INT8 CalcBestCTGT( SOLDIERTYPE *pSoldier, UINT8 ubOppID, INT32 sOppGridNo, INT8 bLevel, INT32 iMyAPsLeft )
INT8 CalcBestCTGT( SOLDIERTYPE *pSoldier, SoldierID ubOppID, INT32 sOppGridNo, INT8 bLevel, INT32 iMyAPsLeft )
{
// NOTE: CTGT stands for "ChanceToGetThrough..."
@@ -579,7 +579,8 @@ INT32 CalcCoverValue(SOLDIERTYPE *pMe, INT32 sMyGridNo, INT32 iMyThreat, INT32 i
UINT8 NumberOfTeamMatesAdjacent( SOLDIERTYPE * pSoldier, INT32 sGridNo )
{
UINT8 ubLoop, ubCount, ubWhoIsThere;
UINT8 ubLoop, ubCount;
SoldierID ubWhoIsThere;
INT32 sTempGridNo;
ubCount = 0;
@@ -590,7 +591,7 @@ UINT8 NumberOfTeamMatesAdjacent( SOLDIERTYPE * pSoldier, INT32 sGridNo )
if ( sTempGridNo != sGridNo )
{
ubWhoIsThere = WhoIsThere2( sTempGridNo, pSoldier->pathing.bLevel );
if ( ubWhoIsThere != NOBODY && ubWhoIsThere != pSoldier->ubID && MercPtrs[ ubWhoIsThere ]->bTeam == pSoldier->bTeam )
if ( ubWhoIsThere != NOBODY && ubWhoIsThere != pSoldier->ubID && ubWhoIsThere->bTeam == pSoldier->bTeam )
{
ubCount++;
}
@@ -1894,7 +1895,7 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem )
if ( pItem->usItemClass == IC_GUN && (*pObj)[0]->data.objectStatus >= MINIMUM_REQUIRED_STATUS )
{
// maybe this gun has ammo (adjust for whether it is better than ours!)
if ( (*pObj)[0]->data.gun.bGunAmmoStatus < 0 || (*pObj)[0]->data.gun.ubGunShotsLeft == 0 || (Item[pObj->usItem].fingerprintid && (*pObj)[0]->data.ubImprintID != NOBODY && (*pObj)[0]->data.ubImprintID != pSoldier->ubID) )
if ( (*pObj)[0]->data.gun.bGunAmmoStatus < 0 || (*pObj)[0]->data.gun.ubGunShotsLeft == 0 || (ItemHasFingerPrintID(pObj->usItem) && (*pObj)[0]->data.ubImprintID != NO_PROFILE && (*pObj)[0]->data.ubImprintID != pSoldier->ubProfile) )
{
iTempValue = 0;
}
@@ -1935,7 +1936,7 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem )
if (pItem->usItemClass & IC_WEAPON && (*pObj)[0]->data.objectStatus >= MINIMUM_REQUIRED_STATUS )
{
DebugAI(AI_MSG_INFO, pSoldier, String("weapon has good status"));
if ( (pItem->usItemClass & IC_GUN) && ((*pObj)[0]->data.gun.bGunAmmoStatus < 0 || (*pObj)[0]->data.gun.ubGunShotsLeft == 0 || (( Item[pObj->usItem].fingerprintid ) && (*pObj)[0]->data.ubImprintID != NOBODY && (*pObj)[0]->data.ubImprintID != pSoldier->ubID) ) )
if ( (pItem->usItemClass & IC_GUN) && ((*pObj)[0]->data.gun.bGunAmmoStatus < 0 || (*pObj)[0]->data.gun.ubGunShotsLeft == 0 || (ItemHasFingerPrintID(pObj->usItem) && (*pObj)[0]->data.ubImprintID != NO_PROFILE && (*pObj)[0]->data.ubImprintID != pSoldier->ubProfile) ) )
{
// jammed or out of ammo, skip it!
DebugAI(AI_MSG_INFO, pSoldier, String("jammed or out of ammo, skip it!"));
@@ -1986,7 +1987,7 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem )
if ( pItem->usItemClass & IC_WEAPON && (*pObj)[0]->data.objectStatus >= MINIMUM_REQUIRED_STATUS )
{
DebugAI(AI_MSG_INFO, pSoldier, String("gun has good status"));
if ( (pItem->usItemClass & IC_GUN) && ((*pObj)[0]->data.gun.bGunAmmoStatus < 0 || (*pObj)[0]->data.gun.ubGunShotsLeft == 0 || (( Item[pObj->usItem].fingerprintid ) && (*pObj)[0]->data.ubImprintID != NOBODY && (*pObj)[0]->data.ubImprintID != pSoldier->ubID) ) )
if ( (pItem->usItemClass & IC_GUN) && ((*pObj)[0]->data.gun.bGunAmmoStatus < 0 || (*pObj)[0]->data.gun.ubGunShotsLeft == 0 || (ItemHasFingerPrintID(pObj->usItem) && (*pObj)[0]->data.ubImprintID != NO_PROFILE && (*pObj)[0]->data.ubImprintID != pSoldier->ubProfile) ) )
{
// jammed or out of ammo, skip it!
DebugAI(AI_MSG_INFO, pSoldier, String("jammed or out of ammo, skip it!"));
+8 -8
View File
@@ -2,7 +2,7 @@
#include "AIInternals.h"
#include "opplist.h"
#include "Soldier Profile.h"
#include "los.h"
#include "LOS.h"
#include "NPC.h"
#include "Quests.h"
#include "Render Fun.h"
@@ -21,7 +21,6 @@ void CallAvailableEnemiesTo( INT32 sGridNo )
void CallAvailableTeamEnemiesTo( INT32 sGridNo, INT8 bTeam )
{
INT32 iLoop2;
SOLDIERTYPE * pSoldier;
// All enemy teams become aware of a very important "noise" coming from here!
@@ -36,9 +35,10 @@ void CallAvailableTeamEnemiesTo( INT32 sGridNo, INT8 bTeam )
gubPublicNoiseVolume[bTeam] = MAX_MISC_NOISE_DURATION;
// new situation for everyone;
iLoop2 = gTacticalStatus.Team[ bTeam ].bFirstID;
for ( pSoldier = MercPtrs[iLoop2]; iLoop2 <= gTacticalStatus.Team[ bTeam ].bLastID; iLoop2++, pSoldier++ )
SoldierID iLoop2 = gTacticalStatus.Team[ bTeam ].bFirstID;
for ( ; iLoop2 <= gTacticalStatus.Team[ bTeam ].bLastID; ++iLoop2 )
{
pSoldier = iLoop2;
if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife >= OKLIFE)
{
SetNewSituation( pSoldier );
@@ -54,7 +54,6 @@ void CallAvailableKingpinMenTo( INT32 sGridNo )
// like call all enemies, but only affects civgroup KINGPIN guys with
// NO PROFILE
INT32 iLoop2;
SOLDIERTYPE * pSoldier;
// All enemy teams become aware of a very important "noise" coming from here!
@@ -67,9 +66,10 @@ void CallAvailableKingpinMenTo( INT32 sGridNo )
// new situation for everyone...
iLoop2 = gTacticalStatus.Team[ CIV_TEAM ].bFirstID;
for ( pSoldier = MercPtrs[iLoop2]; iLoop2 <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; iLoop2++, pSoldier++ )
SoldierID iLoop2 = gTacticalStatus.Team[ CIV_TEAM ].bFirstID;
for ( ; iLoop2 <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; ++iLoop2 )
{
pSoldier = iLoop2;
if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife >= OKLIFE && pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP && pSoldier->ubProfile == NO_PROFILE)
{
SetNewSituation( pSoldier );
@@ -200,7 +200,7 @@ INT32 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
if (*pbPublOL < NOT_HEARD_OR_SEEN)
{
// calculate how far this noise was, and its relative "importance"
iDistAway = SpacesAway(pSoldier->sGridNo,gsPublicLastKnownOppLoc[pSoldier->bTeam][pTemp->ubID]);
iDistAway = SpacesAway(pSoldier->sGridNo, gsPublicLastKnownOppLoc[pSoldier->bTeam][pTemp->ubID]);
iNoiseValue = (*pbPublOL) * iDistAway; // always a negative number!
if (iNoiseValue > iBestValue)
+39 -38
View File
@@ -4,10 +4,10 @@
#include "ai.h"
#include "AIInternals.h"
#include "Animation Control.h"
#include "pathai.h"
#include "overhead.h"
#include "items.h"
#include "Message.h"
#include "PATHAI.H"
#include "Overhead.h"
#include "Items.h"
#include "message.h"
#include "Buildings.h"
#include "worldman.h"
#include "Assignments.h"
@@ -40,9 +40,9 @@ BOOLEAN FindAutobandageClimbPoint( INT32 sDesiredGridNo, BOOLEAN fClimbUp )
{
// checks for existance of location to climb up to building, not occupied by a medic
BUILDING * pBuilding;
UINT8 ubNumClimbSpots;
UINT8 ubNumClimbSpots;
UINT8 ubLoop;
UINT8 ubWhoIsThere;
SoldierID ubWhoIsThere;
pBuilding = FindBuilding( sDesiredGridNo );
if (!pBuilding)
@@ -55,12 +55,12 @@ BOOLEAN FindAutobandageClimbPoint( INT32 sDesiredGridNo, BOOLEAN fClimbUp )
for ( ubLoop = 0; ubLoop < ubNumClimbSpots; ubLoop++ )
{
ubWhoIsThere = WhoIsThere2( pBuilding->sUpClimbSpots[ ubLoop ], 1 );
if ( ubWhoIsThere != NOBODY && !CanCharacterAutoBandageTeammate( MercPtrs[ ubWhoIsThere ] ) )
if ( ubWhoIsThere != NOBODY && !CanCharacterAutoBandageTeammate( ubWhoIsThere ) )
{
continue;
}
ubWhoIsThere = WhoIsThere2( pBuilding->sDownClimbSpots[ ubLoop ], 0 );
if ( ubWhoIsThere != NOBODY && !CanCharacterAutoBandageTeammate( MercPtrs[ ubWhoIsThere ] ) )
if ( ubWhoIsThere != NOBODY && !CanCharacterAutoBandageTeammate( ubWhoIsThere ) )
{
continue;
}
@@ -72,8 +72,7 @@ BOOLEAN FindAutobandageClimbPoint( INT32 sDesiredGridNo, BOOLEAN fClimbUp )
BOOLEAN FullPatientCheck( SOLDIERTYPE * pPatient )
{
UINT8 cnt;
SOLDIERTYPE * pSoldier;
SOLDIERTYPE * pSoldier;
if ( CanCharacterAutoBandageTeammate( pPatient ) )
{
@@ -90,9 +89,10 @@ BOOLEAN FullPatientCheck( SOLDIERTYPE * pPatient )
else
{
// run though the list of chars on team
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pSoldier++)
SoldierID cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( ; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ++cnt )
{
pSoldier = cnt;
// can this character help out?
if ( CanCharacterAutoBandageTeammate( pSoldier ) == TRUE )
{
@@ -119,17 +119,16 @@ BOOLEAN FullPatientCheck( SOLDIERTYPE * pPatient )
BOOLEAN CanAutoBandage( BOOLEAN fDoFullCheck )
{
// returns false if we should stop being in auto-bandage mode
UINT8 cnt;
UINT8 ubMedics = 0, ubPatients = 0;
UINT16 ubMedics = 0, ubPatients = 0;
SOLDIERTYPE * pSoldier;
static UINT8 ubIDForFullCheck = NOBODY;
static SoldierID ubIDForFullCheck = NOBODY;
// run though the list of chars on team
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pSoldier++)
SoldierID cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( ; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ++cnt)
{
// can this character help out?
if( CanCharacterAutoBandageTeammate( pSoldier ) == TRUE )
if( CanCharacterAutoBandageTeammate( cnt ) == TRUE )
{
// yep, up the number of medics in sector
ubMedics++;
@@ -143,8 +142,9 @@ BOOLEAN CanAutoBandage( BOOLEAN fDoFullCheck )
}
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pSoldier++)
for ( ; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ++cnt )
{
pSoldier = cnt;
// can this character be helped out by a teammate?
if ( CanCharacterBeAutoBandagedByTeammate( pSoldier ) == TRUE )
{
@@ -227,25 +227,26 @@ BOOLEAN CanCharacterBeAutoBandagedByTeammate( SOLDIERTYPE *pSoldier )
INT8 FindBestPatient( SOLDIERTYPE * pSoldier, BOOLEAN * pfDoClimb )
{
UINT8 cnt, cnt2;
INT32 bBestPriority = 0, sBestAdjGridNo = NOWHERE;
INT32 sPatientGridNo = NOWHERE, sBestPatientGridNo = NOWHERE;
INT16 sShortestPath = 1000, sPathCost, sOtherMedicPathCost;
SOLDIERTYPE * pPatient;
SOLDIERTYPE * pBestPatient = NULL;
SOLDIERTYPE * pOtherMedic;
INT8 bPatientPriority;
UINT8 ubDirection;
UINT8 cnt2;
INT32 bBestPriority = 0, sBestAdjGridNo = NOWHERE;
INT32 sPatientGridNo = NOWHERE, sBestPatientGridNo = NOWHERE;
INT16 sShortestPath = 1000, sPathCost, sOtherMedicPathCost;
SOLDIERTYPE * pPatient;
SOLDIERTYPE * pBestPatient = NULL;
SOLDIERTYPE * pOtherMedic;
INT8 bPatientPriority;
UINT8 ubDirection;
INT32 sAdjustedGridNo, sAdjacentGridNo, sOtherAdjacentGridNo;
INT32 sClimbGridNo, sBestClimbGridNo = NOWHERE, sShortestClimbPath = 1000;
BOOLEAN fClimbingNecessary;
INT32 sClimbGridNo, sBestClimbGridNo = NOWHERE, sShortestClimbPath = 1000;
BOOLEAN fClimbingNecessary;
gubGlobalPathFlags = PATH_THROUGH_PEOPLE;
// search for someone who needs aid
cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID;
for ( pPatient = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++,pPatient++)
SoldierID cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID;
for ( ; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; ++cnt )
{
pPatient = cnt;
if ( !(pPatient->bActive) || !(pPatient->bInSector) )
{
continue; // NEXT!!!
@@ -310,7 +311,7 @@ INT8 FindBestPatient( SOLDIERTYPE * pSoldier, BOOLEAN * pfDoClimb )
{
// only switch to this patient if our distance is closer than
// the other medic's
pOtherMedic = MercPtrs[ pPatient->ubAutoBandagingMedic ];
pOtherMedic = pPatient->ubAutoBandagingMedic;
sOtherAdjacentGridNo = FindAdjacentGridEx( pOtherMedic, sPatientGridNo, &ubDirection, &sAdjustedGridNo, FALSE, FALSE );
if (sOtherAdjacentGridNo != -1)
{
@@ -378,8 +379,8 @@ INT8 FindBestPatient( SOLDIERTYPE * pSoldier, BOOLEAN * pfDoClimb )
if (pBestPatient->ubAutoBandagingMedic != NOBODY)
{
// cancel that medic
DebugAI(AI_MSG_INFO, MercPtrs[pBestPatient->ubAutoBandagingMedic], String("CancelAIAction: medic: find patient"));
CancelAIAction( MercPtrs[ pBestPatient->ubAutoBandagingMedic ], TRUE );
DebugAI(AI_MSG_INFO, pBestPatient->ubAutoBandagingMedic, String("CancelAIAction: medic: find patient"));
CancelAIAction( pBestPatient->ubAutoBandagingMedic, TRUE );
}
pBestPatient->ubAutoBandagingMedic = pSoldier->ubID;
*pfDoClimb = FALSE;
@@ -474,13 +475,13 @@ INT8 DecideAutoBandage( SOLDIERTYPE * pSoldier )
BOOLEAN DoctorIsPresent( SOLDIERTYPE * pPatient, BOOLEAN fOnDoctorAssignmentCheck )
{
SOLDIERTYPE * pMedic = NULL;
UINT8 cnt;
INT8 bSlot;
BOOLEAN fDoctorHasBeenFound = FALSE;
cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID;
for ( pMedic = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++,pMedic++)
SoldierID cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID;
for ( ; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; ++cnt )
{
pMedic = cnt;
if ( !(pMedic->bActive) || !(pMedic->bInSector) || ( pMedic->flags.uiStatusFlags & SOLDIER_VEHICLE ) || (pMedic->bAssignment == VEHICLE ) )
{
// is nowhere around!
+26 -19
View File
@@ -1,10 +1,10 @@
#include "ai.h"
#include "AIInternals.h"
#include "Isometric Utils.h"
#include "overhead.h"
#include "Overhead.h"
#include "worldman.h"
#include "pathai.h"
//#include "points.h"
#include "PATHAI.H"
//#include "Points.h"
#include "message.h"
#include "Smell.h"
#include "mapscreen.h"
@@ -516,13 +516,18 @@ INT32 InternalGoAsFarAsPossibleTowards(SOLDIERTYPE *pSoldier, INT32 sDesGrid, IN
#ifdef DEBUGDECISIONS
AIPopMessage("destination Grid # itself not valid, looking around it");
#endif
if ( CREATURE_OR_BLOODCAT( pSoldier ) )
{
// we tried to get close, failed; abort!
pSoldier->pathing.usPathIndex = pSoldier->pathing.usPathDataSize = 0;
return( NOWHERE );
}
else
// Commented out this branch for now because bloodcats are constantly failing to find a legal destination in the previous call to legalNPCDestination
// Following the function calls deep enough ( GoAsFarAsPossibleTowards -> InternalGoAsFarAsPossibleTowards -> LegalNPCDestination -> NewOKDestination -> InternalOkayToAddStructureToWorld -> OkayToAddStructureToTile) shows that the last one fails when checking if we can add bloodcat's structure onto the tile our merc is
// This then results them freezing and staying in place even if they can see our mercs
// The reason I'm leaving the code here instead of simply removing it is because this and the check for adding structures to a tile are really old code,
// which has definitely worked fine at some point. As I'm right now unable to find the real reason for this breaking, I'm just circumventing the issue for now. -Asdow
//if ( CREATURE_OR_BLOODCAT( pSoldier ) )
//{
// // we tried to get close, failed; abort!
// pSoldier->pathing.usPathIndex = pSoldier->pathing.usPathDataSize = 0;
// return( NOWHERE );
//}
//else
{
// else look at the 8 nearest gridnos to sDesGrid for a valid destination
@@ -877,12 +882,14 @@ void HaltMoveForSoldierOutOfPoints(SOLDIERTYPE *pSoldier)
}
}
void SetCivilianDestination(UINT8 ubWho, INT32 sGridNo)
void SetCivilianDestination(SoldierID ubWho, INT32 sGridNo)
{
SOLDIERTYPE *pSoldier;
if ( ubWho == NOBODY )
{
return;
}
pSoldier = MercPtrs[ubWho];
SOLDIERTYPE *pSoldier = ubWho;
/*
// if we control the civilian
@@ -892,12 +899,12 @@ void SetCivilianDestination(UINT8 ubWho, INT32 sGridNo)
// if the destination is different from what he has now
if (pSoldier->aiData.usActionData != sGridNo)
{
// store his new destination
pSoldier->aiData.usActionData = sGridNo;
// store his new destination
pSoldier->aiData.usActionData = sGridNo;
// and cancel any movement in progress that he was still engaged in
pSoldier->aiData.bAction = AI_ACTION_NONE;
pSoldier->aiData.bActionInProgress = FALSE;
// and cancel any movement in progress that he was still engaged in
pSoldier->aiData.bAction = AI_ACTION_NONE;
pSoldier->aiData.bActionInProgress = FALSE;
}
// only set the underEscort flag once you give him a destination
+41 -40
View File
@@ -1,28 +1,28 @@
#include "types.h"
#include "wcheck.h"
#include "overhead.h"
#include "WCheck.h"
#include "Overhead.h"
#include "ai.h"
#include "Soldier Profile.h"
#include "NPC.h"
#include "Isometric Utils.h"
#include "Quests.h"
#include "interface dialogue.h"
#include "interface Dialogue.h"
#include "Game Clock.h"
#include "FileMan.h"
#include "Random.h"
#include "items.h"
#include "interface.h"
#include "random.h"
#include "Items.h"
#include "Interface.h"
#include "Assignments.h"
#include "soldier macros.h"
#include "dialogue control.h"
#include "Soldier macros.h"
#include "Dialogue Control.h"
#include "Strategic Town Loyalty.h"
#include "message.h"
#include "Timer Control.h"
#include "Soldier Add.h"
#include "Soldier Tile.h"
#include "soldier tile.h"
#include "Weapons.h"
#include "meanwhile.h"
#include "Meanwhile.h"
#ifdef JA2TESTVERSION
#include "Quest Debug System.h"
@@ -904,12 +904,12 @@ UINT8 CalcDesireToTalk( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach )
// SANDRO - bonus for communication with people for assertive people
if ( gGameOptions.fNewTraitSystem && bApproach != APPROACH_THREATEN)
{
INT16 id = GetSoldierIDFromMercID( ubMerc );
if ( id > -1 )
SoldierID id = GetSoldierIDFromMercID( ubMerc );
if ( id != NOBODY )
{
if ( DoesMercHavePersonality( MercPtrs[id], CHAR_TRAIT_ASSERTIVE ) )
if ( DoesMercHavePersonality( id, CHAR_TRAIT_ASSERTIVE ) )
iPersonalVal += 50;
else if ( DoesMercHavePersonality( MercPtrs[id], CHAR_TRAIT_MALICIOUS ) )
else if ( DoesMercHavePersonality( id, CHAR_TRAIT_MALICIOUS ) )
iPersonalVal -= 50;
}
}
@@ -1149,7 +1149,7 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
ubLastQuoteRecord = NUM_NPC_QUOTE_RECORDS - 1;
usItemToConsider = pObj->usItem;
if ( Item[ usItemToConsider ].usItemClass == IC_GUN && !Item[usItemToConsider].rocketlauncher )
if ( Item[ usItemToConsider ].usItemClass == IC_GUN && !ItemIsRocketLauncher(usItemToConsider) )
{
UINT8 ubWeaponClass;
@@ -1546,8 +1546,7 @@ BOOLEAN HandleNPCBeingGivenMoneyByPlayer( UINT8 ubNPC, UINT32 uiMoneyAmount, UIN
{
CHAR16 sTempString[ 100 ];
swprintf( sTempString, L"%ld", iCost - uiMoneyAmount - giHospitalTempBalance );
InsertDollarSignInToString( sTempString );
swprintf( sTempString, L"%s", FormatMoney(iCost - uiMoneyAmount - giHospitalTempBalance).data());
// not enough cash
ScreenMsg( FONT_MCOLOR_LTYELLOW,
@@ -2557,11 +2556,13 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
}
}
INT32 NPCConsiderInitiatingConv( SOLDIERTYPE * pNPC, UINT8 * pubDesiredMerc )
INT32 NPCConsiderInitiatingConv( SOLDIERTYPE * pNPC, SoldierID * pubDesiredMerc )
{
INT32 sMyGridNo, sDist, sDesiredMercDist = 100;
UINT8 ubNPC, ubMerc, ubDesiredMerc = NOBODY;
UINT8 ubTalkDesire, ubHighestTalkDesire = 0;
INT32 sMyGridNo, sDist, sDesiredMercDist = 100;
UINT8 ubNPC;
UINT16 ubMerc;
SoldierID ubDesiredMerc = NOBODY;
UINT8 ubTalkDesire, ubHighestTalkDesire = 0;
SOLDIERTYPE * pMerc;
SOLDIERTYPE * pDesiredMerc = NULL;
NPCQuoteInfo * pNPCQuoteInfoArray;
@@ -2907,11 +2908,10 @@ BOOLEAN PCDoesFirstAidOnNPC( UINT8 ubNPC )
void TriggerClosestMercWhoCanSeeNPC( UINT8 ubNPC, NPCQuoteInfo *pQuotePtr )
{
// Loop through all mercs, gather closest mercs who can see and trigger one!
UINT8 ubMercsInSector[ 40 ] = { 0 };
UINT8 ubNumMercs = 0;
UINT8 ubChosenMerc;
SoldierID ubMercsInSector[CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS] = {}; //std::vector would probably be better here
UINT16 ubNumMercs = 0;
UINT16 ubChosenMerc;
SOLDIERTYPE *pTeamSoldier, *pSoldier;
INT32 cnt;
// First get pointer to NPC
pSoldier = FindSoldierByProfileID( ubNPC, FALSE );
@@ -2919,15 +2919,16 @@ void TriggerClosestMercWhoCanSeeNPC( UINT8 ubNPC, NPCQuoteInfo *pQuotePtr )
// Loop through all our guys and randomly say one from someone in our sector
// set up soldier ptr as first element in mercptrs list
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
SoldierID cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
// run through list
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ )
for ( ; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ++cnt )
{
pTeamSoldier = cnt;
// Add guy if he's a candidate...
if ( OK_INSECTOR_MERC( pTeamSoldier ) && pTeamSoldier->aiData.bOppList[ pSoldier->ubID ] == SEEN_CURRENTLY )
{
ubMercsInSector[ ubNumMercs ] = (UINT8)cnt;
ubMercsInSector[ ubNumMercs ] = cnt;
ubNumMercs++;
}
}
@@ -2935,7 +2936,7 @@ void TriggerClosestMercWhoCanSeeNPC( UINT8 ubNPC, NPCQuoteInfo *pQuotePtr )
// If we are > 0
if ( ubNumMercs > 0 )
{
ubChosenMerc = (UINT8)Random( ubNumMercs );
ubChosenMerc = (UINT16)Random( ubNumMercs );
// Post action to close panel
NPCClosePanel( );
@@ -2943,11 +2944,11 @@ void TriggerClosestMercWhoCanSeeNPC( UINT8 ubNPC, NPCQuoteInfo *pQuotePtr )
// If 64, do something special
if ( pQuotePtr->ubTriggerNPCRec == QUOTE_RESPONSE_TO_MIGUEL_SLASH_QUOTE_MERC_OR_RPC_LETGO )
{
TacticalCharacterDialogueWithSpecialEvent( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ], pQuotePtr->ubTriggerNPCRec, DIALOGUE_SPECIAL_EVENT_PCTRIGGERNPC, 57, 6 );
TacticalCharacterDialogueWithSpecialEvent( ubMercsInSector[ ubChosenMerc ], pQuotePtr->ubTriggerNPCRec, DIALOGUE_SPECIAL_EVENT_PCTRIGGERNPC, 57, 6 );
}
else
{
TacticalCharacterDialogue( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ], pQuotePtr->ubTriggerNPCRec );
TacticalCharacterDialogue( ubMercsInSector[ ubChosenMerc ], pQuotePtr->ubTriggerNPCRec );
}
}
@@ -3643,12 +3644,11 @@ BOOLEAN LoadBackupNPCInfoFromSavedGameFile( HWFILE hFile, UINT32 uiSaveGameVersi
void TriggerFriendWithHostileQuote( UINT8 ubNPC )
{
UINT8 ubMercsAvailable[ 40 ] = { 0 };
UINT8 ubNumMercsAvailable = 0, ubChosenMerc;
SOLDIERTYPE * pTeamSoldier;
SOLDIERTYPE * pSoldier;
INT32 cnt;
INT8 bTeam;
UINT16 ubMercsAvailable[CODE_MAXIMUM_NUMBER_OF_PLAYER_MERCS] = { 0 };
UINT16 ubNumMercsAvailable = 0, ubChosenMerc;
SOLDIERTYPE * pTeamSoldier;
SOLDIERTYPE * pSoldier;
INT8 bTeam;
// First get pointer to NPC
pSoldier = FindSoldierByProfileID( ubNPC, FALSE );
@@ -3661,11 +3661,12 @@ void TriggerFriendWithHostileQuote( UINT8 ubNPC )
// Loop through all our guys and find one to yell
// set up soldier ptr as first element in mercptrs list
cnt = gTacticalStatus.Team[ bTeam ].bFirstID;
SoldierID cnt = gTacticalStatus.Team[ bTeam ].bFirstID;
// run through list
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ bTeam ].bLastID; cnt++,pTeamSoldier++ )
for ( ; cnt <= gTacticalStatus.Team[ bTeam ].bLastID; ++cnt )
{
pTeamSoldier = cnt;
// Add guy if he's a candidate...
if ( pTeamSoldier->bActive && pSoldier->bInSector && pTeamSoldier->stats.bLife >= OKLIFE && pTeamSoldier->bBreath >= OKBREATH && pTeamSoldier->aiData.bOppCnt > 0 && pTeamSoldier->ubProfile != NO_PROFILE )
{
@@ -3691,7 +3692,7 @@ void TriggerFriendWithHostileQuote( UINT8 ubNPC )
if (ubNumMercsAvailable > 0)
{
PauseAITemporarily();
ubChosenMerc = (UINT8) Random( ubNumMercsAvailable );
ubChosenMerc = (UINT16) Random( ubNumMercsAvailable );
TriggerNPCWithIHateYouQuote( ubMercsAvailable[ ubChosenMerc ] );
}
else
+10 -9
View File
@@ -1,7 +1,7 @@
#include "AIInternals.h"
#include "ai.h"
#include "pathai.h"
#include "items.h"
#include "PATHAI.H"
#include "Items.h"
#include "World Items.h"
#include "strategicmap.h"
#include "Map Screen Interface Map.h"
@@ -10,15 +10,16 @@
#include "Queen Command.h"
void MakeClosestEnemyChosenOne()
{
UINT32 cnt;
INT16 sPathCost, sShortestPath = 1000;
INT8 bOldKeys = -1;
UINT8 ubClosestEnemy = NOBODY;
UINT32 cnt;
INT16 sPathCost, sShortestPath = 1000;
INT8 bOldKeys = -1;
SoldierID ubClosestEnemy = NOBODY;
SOLDIERTYPE * pSoldier;
INT8 bPanicTrigger;
INT32 sPanicTriggerGridNo;
INT8 bPanicTrigger;
INT32 sPanicTriggerGridNo;
if ( ! (gTacticalStatus.fPanicFlags & PANIC_TRIGGERS_HERE) )
{
@@ -161,7 +162,7 @@ void MakeClosestEnemyChosenOne()
NumMessage("TEST MSG: The chosen one is ",TheChosenOne);
#endif
pSoldier = MercPtrs[gTacticalStatus.ubTheChosenOne];
pSoldier = gTacticalStatus.ubTheChosenOne;
if ( pSoldier->aiData.bAlertStatus < STATUS_RED )
{
pSoldier->aiData.bAlertStatus = STATUS_RED;
+2 -2
View File
@@ -2,8 +2,8 @@
#include "QuestDebug.h"
#include "stdarg.h"
#include "stdio.h"
#include "Debug.h"
#include "Message.h"
#include "DEBUG.H"
#include "message.h"
#define QUEST_DEBUG_FILE "QuestDebug.txt"
+5 -5
View File
@@ -1,12 +1,12 @@
#include "ai.h"
#include "AIInternals.h"
#include "Isometric utils.h"
#include "overhead.h"
#include "soldier add.h"
#include "Soldier Profile Type.h"
#include "Isometric Utils.h"
#include "Overhead.h"
#include "Soldier Add.h"
#include "soldier profile type.h"
#include "Items.h"
#include "Weapons.h"
#include "Soldier Macros.h"
#include "Soldier macros.h"
#include "Soldier Profile.h"
#include "NPC.h"
#include "Render Fun.h"
+10 -10
View File
@@ -1,32 +1,32 @@
#include "ai.h"
#include "AIInternals.h"
#include "Isometric utils.h"
#include "Isometric Utils.h"
#include "Points.h"
#include "overhead.h"
#include "Overhead.h"
#include "opplist.h"
#include "items.h"
#include "Items.h"
#include "Weapons.h"
#include "NPC.h"
#include "Soldier Functions.h"
#include "worldman.h"
#include "Scheduling.h"
#include "Message.h"
#include "message.h"
#include "Structure Wrap.h"
#include "Keys.h"
#include "pathai.h"
#include "PATHAI.H"
#include "Render Fun.h"
#include "Boxing.h"
// #include "Air Raid.h"
#include "Soldier Profile.h"
#include "soldier profile type.h"
#include "Soldier macros.h"
#include "los.h"
#include "LOS.h"
#include "Buildings.h"
#include "strategicmap.h"
#include "Quests.h"
#include "Map Screen Interface Map.h"
#include "soldier ani.h"
#include "rotting corpses.h"
#include "Soldier Ani.h"
#include "Rotting Corpses.h"
#include "GameSettings.h"
#include "Dialogue Control.h"
#include "connect.h"
@@ -571,7 +571,7 @@ INT8 ZombieDecideActionRed(SOLDIERTYPE *pSoldier)
INT8 bInWater, bInDeepWater;
INT8 bSeekPts = 0, bHelpPts = 0, bWatchPts = 0;
BOOLEAN fClimb;
UINT8 ubThreatID = NOBODY;
UINT16 ubThreatID = NOBODY;
INT32 sThreatSpot = NOWHERE;
INT8 bThreatLevel = 0;
@@ -910,7 +910,7 @@ INT8 ZombieDecideActionBlack(SOLDIERTYPE *pSoldier)
INT8 bWeaponIn;
BOOLEAN fClimb;
INT32 iDummy;
UINT8 ubThreatID = NOBODY;
UINT16 ubThreatID = NOBODY;
INT32 sThreatSpot = NOWHERE;
INT8 bThreatLevel = 0;
+29 -29
View File
@@ -171,7 +171,7 @@ void CheckForChangingOrders(SOLDIERTYPE *pSoldier );
INT8 ClosestPanicTrigger( SOLDIERTYPE * pSoldier );
INT32 ClosestKnownOpponent(SOLDIERTYPE *pSoldier, INT32 * psGridNo, INT8 * pbLevel, UINT8 *pubOpponentID = NULL);
INT32 ClosestKnownOpponent(SOLDIERTYPE *pSoldier, INT32 * psGridNo, INT8 * pbLevel, SoldierID *pubOpponentID = NULL);
INT32 ClosestPC( SOLDIERTYPE *pSoldier, INT32 * psDistance );
INT32 ClosestUnDisguisedPC( SOLDIERTYPE *pSoldier, INT32 * psDistance ); // Flugente: like ClosestPC(...), but does not account for covert or not visible mercs
BOOLEAN CanAutoBandage( BOOLEAN fDoFullCheck );
@@ -216,7 +216,7 @@ BOOLEAN FindRoofClimbingPoints( SOLDIERTYPE * pSoldier, INT16 sDesiredSpot );
INT32 FindSpotMaxDistFromOpponents(SOLDIERTYPE *pSoldier);
INT32 FindSweetCoverSpot(SOLDIERTYPE *pSoldier);
void FreeUpNPCFromAttacking(UINT8 ubID);
void FreeUpNPCFromAttacking(SoldierID ubID);
void FreeUpNPCFromPendingAction( SOLDIERTYPE * pSoldier );
void FreeUpNPCFromTurning(SOLDIERTYPE *pSoldier, INT8 bLook);
void FreeUpNPCFromStanceChange(SOLDIERTYPE *pSoldier );
@@ -224,7 +224,7 @@ void FreeUpNPCFromLoweringGun( SOLDIERTYPE *pSoldier );
void FreeUpNPCFromRoofClimb(SOLDIERTYPE *pSoldier );
UINT8 GetClosestOpponent( SOLDIERTYPE *pSoldier );
UINT8 GetMostThreateningOpponent( SOLDIERTYPE *pSoldier );
SoldierID GetMostThreateningOpponent( SOLDIERTYPE *pSoldier );
void HandleSoldierAI( SOLDIERTYPE *pSoldier );
void HandleInitialRedAlert( INT8 bTeam, UINT8 ubCommunicate);
@@ -248,7 +248,7 @@ INT16 RandomFriendWithin(SOLDIERTYPE *pSoldier);
INT16 RoamingRange(SOLDIERTYPE *pSoldier, INT32 *pFromGridNo);
void SetCivilianDestination(UINT8 ubWho, INT32 sGridNo);
void SetCivilianDestination(SoldierID ubWho, INT32 sGridNo);
void SetNewSituation( SOLDIERTYPE * pSoldier );
UINT8 SoldierDifficultyLevel( SOLDIERTYPE * pSoldier );
@@ -267,19 +267,19 @@ INT32 FindFlankingSpot(SOLDIERTYPE *pSoldier, INT32 sPos, INT8 bAction );
BOOLEAN CanClimbFromHere (SOLDIERTYPE * pSoldier, BOOLEAN fUp );
// HEADROCK HAM 3.6: Adding includes for A* cover calculations
INT8 CalcWorstCTGTForPosition( SOLDIERTYPE * pSoldier, UINT8 ubOppID, INT32 sOppGridNo, INT8 bLevel, INT32 iMyAPsLeft );
INT8 CalcBestCTGT( SOLDIERTYPE *pSoldier, UINT8 ubOppID, INT32 sOppGridNo, INT8 bLevel, INT32 iMyAPsLeft );
INT8 CalcAverageCTGTForPosition( SOLDIERTYPE * pSoldier, UINT8 ubOppID, INT32 sOppGridNo, INT8 bLevel, INT32 iMyAPsLeft );
INT8 CalcWorstCTGTForPosition( SOLDIERTYPE * pSoldier, SoldierID ubOppID, INT32 sOppGridNo, INT8 bLevel, INT32 iMyAPsLeft );
INT8 CalcBestCTGT( SOLDIERTYPE *pSoldier, SoldierID ubOppID, INT32 sOppGridNo, INT8 bLevel, INT32 iMyAPsLeft );
INT8 CalcAverageCTGTForPosition( SOLDIERTYPE * pSoldier, SoldierID ubOppID, INT32 sOppGridNo, INT8 bLevel, INT32 iMyAPsLeft );
UINT8 NumberOfTeamMatesAdjacent( SOLDIERTYPE * pSoldier, INT32 sGridNo );
// Flugente: get the id of the closest soldier (coser than x tiles) of a specific team with a specific flag that we can currently see
UINT8 GetClosestFlaggedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam, UINT32 aFlag, BOOLEAN fCheckSight = TRUE );
SoldierID GetClosestFlaggedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam, UINT32 aFlag, BOOLEAN fCheckSight = TRUE );
// get the id of the closest soldier (closer than x tiles) of a specific team that is wounded that we can currently see
UINT8 GetClosestWoundedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam );
SoldierID GetClosestWoundedSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam );
// get the id of the closest medic (closer than x tiles) of a specific team
UINT8 GetClosestMedicSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam );
SoldierID GetClosestMedicSoldierID( SOLDIERTYPE * pSoldier, INT16 aRange, UINT8 auTeam );
// sevenfm:
BOOLEAN NightLight(void);
@@ -287,15 +287,15 @@ BOOLEAN DuskLight(void);
BOOLEAN InSmokeNearby(INT32 sGridNo, INT8 bLevel);
INT16 MaxNormalVisionDistance( void );
UINT8 MinFlankDirections( SOLDIERTYPE *pSoldier );
UINT8 CountFriendsInDirection( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo );
UINT16 CountFriendsInDirection( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo );
BOOLEAN GuySawEnemy( SOLDIERTYPE * pSoldier, UINT8 ubMax = SEEN_3_TURNS_AGO );
UINT8 CountNearbyFriends( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubDistance );
UINT16 CountNearbyFriends( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubDistance );
UINT8 CountNearbyFriendsLastAttackHit( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubDistance );
UINT8 CountFriendsFlankSameSpot(SOLDIERTYPE *pSoldier, INT32 sSpot = NOWHERE);
UINT8 CountFriendsBlack( SOLDIERTYPE *pSoldier, INT32 sClosestOpponent = NOWHERE );
UINT8 CountTeamUnderAttack(INT8 bTeam, INT32 sGridNo, INT16 sDistance);
UINT8 CountPublicKnownEnemies(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 sDistance);
UINT8 CountPublicKnownEnemies(SOLDIERTYPE *pSoldier);
UINT16 CountTeamUnderAttack(INT8 bTeam, INT32 sGridNo, INT16 sDistance);
UINT16 CountPublicKnownEnemies(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 sDistance);
UINT16 CountPublicKnownEnemies(SOLDIERTYPE *pSoldier);
UINT8 SectorCurfew(BOOLEAN fNight);
UINT8 TeamPercentKilled(INT8 bTeam);
@@ -304,15 +304,15 @@ UINT8 ArmyPercentKilled(void);
UINT8 ArmyPercentKilledTolerance(void);
BOOLEAN EnemySeenSoldierRecently( SOLDIERTYPE *pSoldier, UINT8 ubMax = SEEN_3_TURNS_AGO );
UINT8 CountTeamSeeSoldier( INT8 bTeam, SOLDIERTYPE *pSoldier );
UINT16 CountTeamSeeSoldier( INT8 bTeam, SOLDIERTYPE *pSoldier );
BOOLEAN AICheckFriendsNoContact( SOLDIERTYPE *pSoldier );
BOOLEAN AICheckIsFlanking( SOLDIERTYPE *pSoldier );
INT8 CalcMoraleNew(SOLDIERTYPE *pSoldier);
UINT32 PrepareThreatlist(SOLDIERTYPE *pSoldier);
UINT8 ClosestSeenThreatID(SOLDIERTYPE *pSoldier, UINT32 uiThreatCnt, UINT8 ubMax = SEEN_CURRENTLY); // first call PrepareThreatlist to make threat list
UINT8 ClosestKnownThreatID(SOLDIERTYPE *pSoldier, UINT32 uiThreatCnt); // first call PrepareThreatlist to make threat list
SoldierID ClosestSeenThreatID(SOLDIERTYPE *pSoldier, UINT32 uiThreatCnt, UINT8 ubMax = SEEN_CURRENTLY); // first call PrepareThreatlist to make threat list
SoldierID ClosestKnownThreatID(SOLDIERTYPE *pSoldier, UINT32 uiThreatCnt); // first call PrepareThreatlist to make threat list
BOOLEAN ProneSightCoverAtSpot(SOLDIERTYPE *pSoldier, INT32 sSpot, BOOLEAN fUnlimited);
BOOLEAN SightCoverAtSpot(SOLDIERTYPE *pSoldier, INT32 sSpot, BOOLEAN fUnlimited);
@@ -332,7 +332,7 @@ UINT8 TerrainDensity(INT32 sSpot, INT8 bLevel, UINT8 ubDistance, BOOLEAN fGrass)
BOOLEAN FindNearbyExplosiveStructure(INT32 sSpot, INT8 bLevel);
INT16 DistanceToClosestActiveOpponent(SOLDIERTYPE *pSoldier, INT32 sSpot);
BOOLEAN ValidOpponent(SOLDIERTYPE* pSoldier, SOLDIERTYPE* pOpponent);
UINT8 CountSeenEnemiesLastTurn( SOLDIERTYPE *pSoldier );
UINT16 CountSeenEnemiesLastTurn( SOLDIERTYPE *pSoldier );
BOOLEAN FindObstacleNearSpot(INT32 sSpot, INT8 bLevel);
BOOLEAN CheckNPCDestination(SOLDIERTYPE *pSoldier, INT32 sGridNo);
UINT8 SpotDangerLevel(SOLDIERTYPE *pSoldier, INT32 sGridNo);
@@ -383,19 +383,19 @@ BOOLEAN AICheckSpecialRole(SOLDIERTYPE *pSoldier);
// Knowledge functions
// *************************************************************
INT8 Knowledge(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID);
INT32 KnownLocation(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID);
INT8 KnownLevel(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID);
INT8 Knowledge(SOLDIERTYPE *pSoldier, SoldierID ubOpponentID);
INT32 KnownLocation(SOLDIERTYPE *pSoldier, SoldierID ubOpponentID);
INT8 KnownLevel(SOLDIERTYPE *pSoldier, SoldierID ubOpponentID);
BOOLEAN UsePersonalKnowledge(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID);
BOOLEAN UsePersonalKnowledge(SOLDIERTYPE *pSoldier, SoldierID ubOpponentID);
INT8 PersonalKnowledge(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID);
INT32 KnownPersonalLocation(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID);
INT8 KnownPersonalLevel(SOLDIERTYPE *pSoldier, UINT8 ubOpponentID);
INT8 PersonalKnowledge(SOLDIERTYPE *pSoldier, SoldierID ubOpponentID);
INT32 KnownPersonalLocation(SOLDIERTYPE *pSoldier, SoldierID ubOpponentID);
INT8 KnownPersonalLevel(SOLDIERTYPE *pSoldier, SoldierID ubOpponentID);
INT8 PublicKnowledge(UINT8 bTeam, UINT8 ubOpponentID);
INT32 KnownPublicLocation(UINT8 bTeam, UINT8 ubOpponentID);
INT8 KnownPublicLevel(UINT8 bTeam, UINT8 ubOpponentID);
INT8 PublicKnowledge(UINT8 bTeam, SoldierID ubOpponentID);
INT32 KnownPublicLocation(UINT8 bTeam, SoldierID ubOpponentID);
INT8 KnownPublicLevel(UINT8 bTeam, SoldierID ubOpponentID);
#define MAX_FLANKS_RED 25
#define MAX_FLANKS_YELLOW 25