Merged New Inventory Project into main branch

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@1871 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
lalien
2008-03-08 15:15:25 +00:00
parent e16d166277
commit 43ca24dda8
649 changed files with 93359 additions and 82507 deletions
+57 -57
View File
@@ -9,32 +9,32 @@
extern BOOLEAN gfTurnBasedAI;
#define MAX_DIST 160
// THIS IS AN ITEM # - AND FOR NOW JUST COMPLETELY FAKE...
// THIS IS AN ITEM # - AND FOR NOW JUST COMPLETELY FAKE...
#define MAX_TOSS_SEARCH_DIST 1 // must throw within this of opponent
#define NPC_TOSS_SAFETY_MARGIN 4 // all friends must be this far away
#define MAX_TOSS_SEARCH_DIST 1 // must throw within this of opponent
#define NPC_TOSS_SAFETY_MARGIN 4 // all friends must be this far away
#define ACTING_ON_SCHEDULE( p ) ( (p)->fAIFlags & AI_CHECK_SCHEDULE )
#define ACTING_ON_SCHEDULE( p ) ( (p)->aiData.fAIFlags & AI_CHECK_SCHEDULE )
// the AI should try to have this many APs before climbing a roof, if possible
#define AI_AP_CLIMBROOF 15
#define TEMPORARILY 0
#define FOREVER 1
#define TEMPORARILY 0
#define FOREVER 1
#define IGNORE_PATH 0
#define ENSURE_PATH 1
#define ENSURE_PATH_COST 2
#define IGNORE_PATH 0
#define ENSURE_PATH 1
#define ENSURE_PATH_COST 2
//Kris: November 10, 1997
//Please don't change this value from 10. It will invalidate all of the maps and soldiers.
#define MAXPATROLGRIDS 10
//Kris: November 10, 1997
//Please don't change this value from 10. It will invalidate all of the maps and soldiers.
#define MAXPATROLGRIDS 10
#define NOWATER 0
#define WATEROK 1
#define NOWATER 0
#define WATEROK 1
#define DONTADDTURNCOST 0
#define ADDTURNCOST 1
#define ADDTURNCOST 1
enum
{
@@ -44,17 +44,17 @@ enum
NUM_URGENCY_STATES
};
#define NOWATER 0
#define WATEROK 1
#define NOWATER 0
#define WATEROK 1
#define IGNORE_PATH 0
#define ENSURE_PATH 1
#define ENSURE_PATH_COST 2
#define IGNORE_PATH 0
#define ENSURE_PATH 1
#define ENSURE_PATH_COST 2
#define DONTFORCE 0
#define FORCE 1
#define DONTFORCE 0
#define FORCE 1
#define MAX_ROAMING_RANGE WORLD_COLS
#define MAX_ROAMING_RANGE WORLD_COLS
#define PTR_CIV_OR_MILITIA ( PTR_CIVILIAN || (pSoldier->bTeam == MILITIA_TEAM) )
@@ -62,40 +62,40 @@ enum
#define REALTIME_CIV_AI_DELAY ( 1000 * (gTacticalStatus.Team[ MILITIA_TEAM ].bMenInSector + gTacticalStatus.Team[ CIV_TEAM ].bMenInSector) + 5000 + 2000 * Random( 3 ) )
#define REALTIME_CREATURE_AI_DELAY ( 10000 + 1000 * Random( 3 ) )
//#define PLAYINGMODE 0
//#define CAMPAIGNLENGTH 1
//#define LASTUSABLESLOT 2
//#define RANDOMMERCS 3
//#define AVAILABLEMERCS 4
//#define HIRINGKNOWLEDGE 5
//#define EQUIPMENTLEVEL 6
//#define ENEMYTEAMSIZE 7
#define ENEMYDIFFICULTY 8 // this is being used in this module
//#define FOG_OF_WAR 9
//#define TURNLENGTH 10
//#define INCREASEDAP 11
//#define BLOODSTAINS 12
//#define STARTINGBALANCE 13
#define MAXGAMEOPTIONS 14
//#define PLAYINGMODE 0
//#define CAMPAIGNLENGTH 1
//#define LASTUSABLESLOT 2
//#define RANDOMMERCS 3
//#define AVAILABLEMERCS 4
//#define HIRINGKNOWLEDGE 5
//#define EQUIPMENTLEVEL 6
//#define ENEMYTEAMSIZE 7
#define ENEMYDIFFICULTY 8 // this is being used in this module
//#define FOG_OF_WAR 9
//#define TURNLENGTH 10
//#define INCREASEDAP 11
//#define BLOODSTAINS 12
//#define STARTINGBALANCE 13
#define MAXGAMEOPTIONS 14
#define NOSHOOT_WAITABIT -1
#define NOSHOOT_WATER -2
#define NOSHOOT_MYSELF -3
#define NOSHOOT_HURT -4
#define NOSHOOT_NOAMMO -5
#define NOSHOOT_NOLOAD -6
#define NOSHOOT_NOWEAPON -7
#define NOSHOOT_WAITABIT -1
#define NOSHOOT_WATER -2
#define NOSHOOT_MYSELF -3
#define NOSHOOT_HURT -4
#define NOSHOOT_NOAMMO -5
#define NOSHOOT_NOLOAD -6
#define NOSHOOT_NOWEAPON -7
#define PERCENT_TO_IGNORE_THREAT 50 // any less, use threat value
#define PERCENT_TO_IGNORE_THREAT 50 // any less, use threat value
#define ACTION_TIMEOUT_CYCLES 50 // # failed cycles through AI
#define MAX_THREAT_RANGE 400 // 30 tiles worth
#define MAX_THREAT_RANGE 400 // 30 tiles worth
#define MIN_PERCENT_BETTER 5 // 5% improvement in cover is good
#define TOSSES_PER_10TURNS 18 // max # of grenades tossable in 10 turns
#define SHELLS_PER_10TURNS 13 // max # of shells firable in 10 turns
#define TOSSES_PER_10TURNS 18 // max # of grenades tossable in 10 turns
#define SHELLS_PER_10TURNS 13 // max # of shells firable in 10 turns
#define SEE_THRU_COVER_THRESHOLD 5 // min chance to get through
#define SEE_THRU_COVER_THRESHOLD 5 // min chance to get through
#undef min
#define min(a,b) ((a) < (b) ? (a) : (b))
@@ -119,15 +119,15 @@ typedef struct
typedef struct
{
UINT8 ubPossible; // is this attack form possible? T/F
UINT8 ubOpponent; // which soldier is the victim?
UINT8 ubPossible; // is this attack form possible? T/F
UINT8 ubOpponent; // which soldier is the victim?
UINT8 ubAimTime; // how many extra APs to spend on aiming
UINT8 ubChanceToReallyHit; // chance to hit * chance to get through cover
INT32 iAttackValue; // relative worthiness of this type of attack
UINT8 ubChanceToReallyHit; // chance to hit * chance to get through cover
INT32 iAttackValue; // relative worthiness of this type of attack
INT16 sTarget; // target gridno of this attack
INT8 bTargetLevel; // target level of this attack
INT8 bTargetLevel; // target level of this attack
UINT8 ubAPCost; // how many APs the attack will use up
INT8 bWeaponIn; // the inv slot of the weapon in question
INT8 bWeaponIn; // the inv slot of the weapon in question
} ATTACKTYPE;
extern THREATTYPE Threat[MAXMERCS];
@@ -226,5 +226,5 @@ void CheckIfShotPossible(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN s
INT16 FindBestCoverNearTheGridNo(SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubSearchRadius );
INT8 FindDirectionForClimbing( INT16 sGridNo, INT8 bLevel);
INT8 FindDirectionForClimbing( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bLevel);
+589 -589
View File
File diff suppressed because it is too large Load Diff
+362 -353
View File
File diff suppressed because it is too large Load Diff
+351 -351
View File
File diff suppressed because it is too large Load Diff
+186 -194
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+42 -42
View File
@@ -35,13 +35,13 @@ void CallAvailableEnemiesTo( INT16 sGridNo )
iLoop2 = gTacticalStatus.Team[ iLoop ].bFirstID;
for ( pSoldier = MercPtrs[iLoop2]; iLoop2 <= gTacticalStatus.Team[ iLoop ].bLastID; iLoop2++, pSoldier++ )
{
if (pSoldier->bActive && pSoldier->bInSector && pSoldier->bLife >= OKLIFE)
if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife >= OKLIFE)
{
SetNewSituation( pSoldier );
WearGasMaskIfAvailable( pSoldier );
}
}
}
}
@@ -69,7 +69,7 @@ void CallAvailableTeamEnemiesTo( INT16 sGridno, INT8 bTeam )
iLoop2 = gTacticalStatus.Team[ bTeam ].bFirstID;
for ( pSoldier = MercPtrs[iLoop2]; iLoop2 <= gTacticalStatus.Team[ bTeam ].bLastID; iLoop2++, pSoldier++ )
{
if (pSoldier->bActive && pSoldier->bInSector && pSoldier->bLife >= OKLIFE)
if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife >= OKLIFE)
{
SetNewSituation( pSoldier );
WearGasMaskIfAvailable( pSoldier );
@@ -82,7 +82,7 @@ void CallAvailableTeamEnemiesTo( INT16 sGridno, INT8 bTeam )
void CallAvailableKingpinMenTo( INT16 sGridNo )
{
// like call all enemies, but only affects civgroup KINGPIN guys with
// like call all enemies, but only affects civgroup KINGPIN guys with
// NO PROFILE
INT32 iLoop2;
@@ -101,7 +101,7 @@ void CallAvailableKingpinMenTo( INT16 sGridNo )
iLoop2 = gTacticalStatus.Team[ CIV_TEAM ].bFirstID;
for ( pSoldier = MercPtrs[iLoop2]; iLoop2 <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; iLoop2++, pSoldier++ )
{
if (pSoldier->bActive && pSoldier->bInSector && pSoldier->bLife >= OKLIFE && pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP && pSoldier->ubProfile == NO_PROFILE)
if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife >= OKLIFE && pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP && pSoldier->ubProfile == NO_PROFILE)
{
SetNewSituation( pSoldier );
}
@@ -120,7 +120,7 @@ void CallEldinTo( INT16 sGridNo )
{
// new situation for Eldin
pSoldier = FindSoldierByProfileID( ELDIN, FALSE );
if ( pSoldier && pSoldier->bActive && pSoldier->bInSector && pSoldier->bLife >= OKLIFE && (pSoldier->bAlertStatus == STATUS_GREEN || pSoldier->ubNoiseVolume < (MAX_MISC_NOISE_DURATION / 2) ) )
if ( pSoldier && pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife >= OKLIFE && (pSoldier->aiData.bAlertStatus == STATUS_GREEN || pSoldier->aiData.ubNoiseVolume < (MAX_MISC_NOISE_DURATION / 2) ) )
{
if ( SoldierTo3DLocationLineOfSightTest( pSoldier, sGridNo, 0, 0, TRUE ) )
{
@@ -130,15 +130,15 @@ void CallEldinTo( INT16 sGridNo )
}
else
{
pSoldier->sNoiseGridno = sGridNo;
pSoldier->ubNoiseVolume = MAX_MISC_NOISE_DURATION;
pSoldier->bAlertStatus = STATUS_RED;
if ( (pSoldier->bAction != AI_ACTION_GET_CLOSER) || CheckFact( FACT_MUSEUM_ALARM_WENT_OFF, 0 ) == FALSE )
pSoldier->aiData.sNoiseGridno = sGridNo;
pSoldier->aiData.ubNoiseVolume = MAX_MISC_NOISE_DURATION;
pSoldier->aiData.bAlertStatus = STATUS_RED;
if ( (pSoldier->aiData.bAction != AI_ACTION_GET_CLOSER) || CheckFact( FACT_MUSEUM_ALARM_WENT_OFF, 0 ) == FALSE )
{
CancelAIAction( pSoldier, TRUE );
pSoldier->bNextAction = AI_ACTION_GET_CLOSER;
pSoldier->usNextActionData = sGridNo;
RESETTIMECOUNTER( pSoldier->AICounter, 100 );
pSoldier->aiData.bNextAction = AI_ACTION_GET_CLOSER;
pSoldier->aiData.usNextActionData = sGridNo;
RESETTIMECOUNTER( pSoldier->timeCounters.AICounter, 100 );
}
// otherwise let AI handle this normally
// SetNewSituation( pSoldier );
@@ -164,7 +164,7 @@ INT16 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
INT8 bBestLevel = 0;
INT16 sClimbingGridNo;
BOOLEAN fClimbingNecessary = FALSE;
SOLDIERTYPE * pTemp;
SOLDIERTYPE * pTemp;
pubNoiseVolume = &gubPublicNoiseVolume[pSoldier->bTeam];
psNoiseGridNo = &gsPublicNoiseGridno[pSoldier->bTeam];
@@ -173,7 +173,7 @@ INT16 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
psLastLoc = gsLastKnownOppLoc[pSoldier->ubID];
// hang pointers at start of this guy's personal and public opponent opplists
pbPersOL = pSoldier->bOppList;
pbPersOL = pSoldier->aiData.bOppList;
pbPublOL = gbPublicOpplist[pSoldier->bTeam];
// look through this man's personal & public opplists for opponents heard
@@ -182,14 +182,14 @@ INT16 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
pTemp = MercSlots[ uiLoop ];
// if this merc is inactive, at base, on assignment, or dead
if (!pTemp || !pTemp->bLife)
continue; // next merc
if (!pTemp || !pTemp->stats.bLife)
continue; // next merc
// if this merc is neutral/on same side, he's not an opponent
if ( CONSIDERED_NEUTRAL( pSoldier, pTemp ) || (pSoldier->bSide == pTemp->bSide))
continue; // next merc
continue; // next merc
pbPersOL = pSoldier->bOppList + pTemp->ubID;
pbPersOL = pSoldier->aiData.bOppList + pTemp->ubID;
pbPublOL = gbPublicOpplist[pSoldier->bTeam] + pTemp->ubID;
psLastLoc = gsLastKnownOppLoc[pSoldier->ubID] + pTemp->ubID;
pbLastLevel = gbLastKnownOppLevel[pSoldier->ubID] + pTemp->ubID;
@@ -199,7 +199,7 @@ INT16 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
{
// calculate how far this noise was, and its relative "importance"
iDistAway = SpacesAway(pSoldier->sGridNo,*psLastLoc);
iNoiseValue = (*pbPersOL) * iDistAway; // always a negative number!
iNoiseValue = (*pbPersOL) * iDistAway; // always a negative number!
if (iNoiseValue > iBestValue)
{
@@ -214,7 +214,7 @@ INT16 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
{
// calculate how far this noise was, and its relative "importance"
iDistAway = SpacesAway(pSoldier->sGridNo,gsPublicLastKnownOppLoc[pSoldier->bTeam][pTemp->ubID]);
iNoiseValue = (*pbPublOL) * iDistAway; // always a negative number!
iNoiseValue = (*pbPublOL) * iDistAway; // always a negative number!
if (iNoiseValue > iBestValue)
{
@@ -227,26 +227,26 @@ INT16 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
}
// if any "misc. noise" was also heard recently
if (pSoldier->sNoiseGridno != NOWHERE)
if (pSoldier->aiData.sNoiseGridno != NOWHERE)
{
if ( pSoldier->bNoiseLevel != pSoldier->bLevel || PythSpacesAway( pSoldier->sGridNo, pSoldier->sNoiseGridno ) >= 6 || SoldierTo3DLocationLineOfSightTest( pSoldier, pSoldier->sNoiseGridno, pSoldier->bNoiseLevel, 0, FALSE, NO_DISTANCE_LIMIT ) == 0 )
if ( pSoldier->bNoiseLevel != pSoldier->pathing.bLevel || PythSpacesAway( pSoldier->sGridNo, pSoldier->aiData.sNoiseGridno ) >= 6 || SoldierTo3DLocationLineOfSightTest( pSoldier, pSoldier->aiData.sNoiseGridno, pSoldier->bNoiseLevel, 0, FALSE, NO_DISTANCE_LIMIT ) == 0 )
{
// calculate how far this noise was, and its relative "importance"
iDistAway = SpacesAway(pSoldier->sGridNo,pSoldier->sNoiseGridno);
iNoiseValue = ((pSoldier->ubNoiseVolume / 2) - 6) * iDistAway;
iDistAway = SpacesAway(pSoldier->sGridNo,pSoldier->aiData.sNoiseGridno);
iNoiseValue = ((pSoldier->aiData.ubNoiseVolume / 2) - 6) * iDistAway;
if (iNoiseValue > iBestValue)
{
iBestValue = iNoiseValue;
sBestGridNo = pSoldier->sNoiseGridno;
sBestGridNo = pSoldier->aiData.sNoiseGridno;
bBestLevel = pSoldier->bNoiseLevel;
}
}
else
{
// we are there or near
pSoldier->sNoiseGridno = NOWHERE; // wipe it out, not useful anymore
pSoldier->ubNoiseVolume = 0;
pSoldier->aiData.sNoiseGridno = NOWHERE; // wipe it out, not useful anymore
pSoldier->aiData.ubNoiseVolume = 0;
}
}
@@ -254,11 +254,11 @@ INT16 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
// if any recent PUBLIC "misc. noise" is also known
if ( (pSoldier->bTeam != CIV_TEAM) || ( pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP ) )
{
if (*psNoiseGridNo != NOWHERE)
{
// if we are NOT there (at the noise gridno)
if ( *pbNoiseLevel != pSoldier->bLevel || PythSpacesAway( pSoldier->sGridNo, *psNoiseGridNo ) >= 6 || SoldierTo3DLocationLineOfSightTest( pSoldier, *psNoiseGridNo, *pbNoiseLevel, 0, FALSE, NO_DISTANCE_LIMIT ) == 0 )
if ( *pbNoiseLevel != pSoldier->pathing.bLevel || PythSpacesAway( pSoldier->sGridNo, *psNoiseGridNo ) >= 6 || SoldierTo3DLocationLineOfSightTest( pSoldier, *psNoiseGridNo, *pbNoiseLevel, 0, FALSE, NO_DISTANCE_LIMIT ) == 0 )
{
// calculate how far this noise was, and its relative "importance"
iDistAway = SpacesAway(pSoldier->sGridNo,*psNoiseGridNo);
@@ -280,14 +280,14 @@ INT16 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
*pfReachable = TRUE;
// make civs not walk to noises outside their room if on close patrol/onguard
if ( pSoldier->bOrders <= CLOSEPATROL && (pSoldier->bTeam == CIV_TEAM || pSoldier->ubProfile != NO_PROFILE ) )
if ( pSoldier->aiData.bOrders <= CLOSEPATROL && (pSoldier->bTeam == CIV_TEAM || pSoldier->ubProfile != NO_PROFILE ) )
{
UINT8 ubRoom, ubNewRoom;
// any other combo uses the default of ubRoom == 0, set above
if ( InARoom( pSoldier->usPatrolGrid[0], &ubRoom ) )
if ( InARoom( pSoldier->aiData.sPatrolGrid[0], &ubRoom ) )
{
if ( !InARoom( pSoldier->usPatrolGrid[0], &ubNewRoom ) || ubRoom != ubNewRoom )
if ( !InARoom( pSoldier->aiData.sPatrolGrid[0], &ubNewRoom ) || ubRoom != ubNewRoom )
{
*pfReachable = FALSE;
}
@@ -296,7 +296,7 @@ INT16 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
if ( *pfReachable )
{
// if there is a climb involved then we should store the location
// if there is a climb involved then we should store the location
// of where we have to climb to instead
sClimbingGridNo = GetInterveningClimbingLocation( pSoldier, sBestGridNo, bBestLevel, &fClimbingNecessary );
if ( fClimbingNecessary )
@@ -315,7 +315,7 @@ INT16 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN
else
{
fClimbingNecessary = FALSE;
}
}
}
}
@@ -346,14 +346,14 @@ INT16 WhatIKnowThatPublicDont(SOLDIERTYPE *pSoldier, UINT8 ubInSightOnly)
SOLDIERTYPE * pTemp;
// if merc knows of a more important misc. noise than his team does
if (!(CREATURE_OR_BLOODCAT( pSoldier )) && (pSoldier->ubNoiseVolume > gubPublicNoiseVolume[pSoldier->bTeam]))
if (!(CREATURE_OR_BLOODCAT( pSoldier )) && (pSoldier->aiData.ubNoiseVolume > gubPublicNoiseVolume[pSoldier->bTeam]))
{
// the difference in volume is added to the "new info" total
ubTotal += pSoldier->ubNoiseVolume - gubPublicNoiseVolume[pSoldier->bTeam];
ubTotal += pSoldier->aiData.ubNoiseVolume - gubPublicNoiseVolume[pSoldier->bTeam];
}
// hang pointers at start of this guy's personal and public opponent opplists
pbPersOL = &(pSoldier->bOppList[0]);
pbPersOL = &(pSoldier->aiData.bOppList[0]);
pbPublOL = &(gbPublicOpplist[pSoldier->bTeam][0]);
// for every opponent
@@ -365,20 +365,20 @@ INT16 WhatIKnowThatPublicDont(SOLDIERTYPE *pSoldier, UINT8 ubInSightOnly)
for (uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++)
{
pTemp = MercSlots[ uiLoop ];
// if this merc is inactive, at base, on assignment, or dead
if (!pTemp)
{
continue; // next merc
continue; // next merc
}
// if this merc is neutral/on same side, he's not an opponent
if ( CONSIDERED_NEUTRAL( pSoldier, pTemp ) || (pSoldier->bSide == pTemp->bSide))
{
continue; // next merc
continue; // next merc
}
pbPersOL = pSoldier->bOppList + pTemp->ubID;
pbPersOL = pSoldier->aiData.bOppList + pTemp->ubID;
pbPublOL = gbPublicOpplist[pSoldier->bTeam] + pTemp->ubID;
+32 -27
View File
@@ -3,7 +3,7 @@
#else
#include "types.h"
#include "wcheck.h"
#include "Soldier Control.h"
#include "Soldier Functions.h"
#include "ai.h"
#include "AIInternals.h"
@@ -17,10 +17,15 @@
#include "Assignments.h"
#endif
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
class SOLDIERTYPE;
extern BOOLEAN gfAutoBandageFailed;
//
// This file contains code devoted to the player AI-controlled medical system. Maybe it
// This file contains code devoted to the player AI-controlled medical system. Maybe it
// can be used or adapted for the enemies too...
//
@@ -78,8 +83,8 @@ BOOLEAN FullPatientCheck( SOLDIERTYPE * pPatient )
return( TRUE );
}
if ( pPatient->bLevel != 0 )
{ // look for a clear spot for jumping up
if ( pPatient->pathing.bLevel != 0 )
{ // look for a clear spot for jumping up
// special "closest" search that ignores climb spots IF they are occupied by non-medics
return( FindAutobandageClimbPoint( pPatient->sGridNo, TRUE ) );
@@ -94,14 +99,14 @@ BOOLEAN FullPatientCheck( SOLDIERTYPE * pPatient )
if ( CanCharacterAutoBandageTeammate( pSoldier ) == TRUE )
{
// can this guy path to the patient?
if ( pSoldier->bLevel == 0 )
if ( pSoldier->pathing.bLevel == 0 )
{
// do a regular path check
if ( FindBestPath( pSoldier, pPatient->sGridNo, 0, WALKING, NO_COPYROUTE, PATH_THROUGH_PEOPLE ) )
{
return( TRUE );
}
}
}
else
{
// if on different levels, assume okay
@@ -189,13 +194,13 @@ BOOLEAN CanCharacterAutoBandageTeammate( SOLDIERTYPE *pSoldier )
// can this soldier autobandage others in sector
{
// if the soldier isn't active or in sector, we have problems..leave
if ( !(pSoldier->bActive) || !(pSoldier->bInSector) || ( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) || (pSoldier->bAssignment == VEHICLE ) )
if ( !(pSoldier->bActive) || !(pSoldier->bInSector) || ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) || (pSoldier->bAssignment == VEHICLE ) )
{
return( FALSE );
}
// they must have oklife or more, not be collapsed, have some level of medical competence, and have a med kit of some sort
if ( (pSoldier->bLife >= OKLIFE) && !(pSoldier->bCollapsed) && (pSoldier->bMedical > 0) && (FindObjClass( pSoldier, IC_MEDKIT ) != NO_SLOT) )
if ( (pSoldier->stats.bLife >= OKLIFE) && !(pSoldier->bCollapsed) && (pSoldier->stats.bMedical > 0) && (FindObjClass( pSoldier, IC_MEDKIT ) != NO_SLOT) )
{
return( TRUE );
}
@@ -208,12 +213,12 @@ BOOLEAN CanCharacterAutoBandageTeammate( SOLDIERTYPE *pSoldier )
BOOLEAN CanCharacterBeAutoBandagedByTeammate( SOLDIERTYPE *pSoldier )
{
// if the soldier isn't active or in sector, we have problems..leave
if ( !(pSoldier->bActive) || !(pSoldier->bInSector) || ( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) || (pSoldier->bAssignment == VEHICLE ) )
if ( !(pSoldier->bActive) || !(pSoldier->bInSector) || ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) || (pSoldier->bAssignment == VEHICLE ) )
{
return( FALSE );
}
if ( (pSoldier->bLife > 0) && (pSoldier->bBleeding > 0) )
if ( (pSoldier->stats.bLife > 0) && (pSoldier->bBleeding > 0) )
{
// someone's bleeding and not being given first aid!
return( TRUE );
@@ -248,13 +253,13 @@ INT8 FindBestPatient( SOLDIERTYPE * pSoldier, BOOLEAN * pfDoClimb )
continue; // NEXT!!!
}
if (pPatient->bLife > 0 && pPatient->bBleeding && pPatient->ubServiceCount == 0)
if (pPatient->stats.bLife > 0 && pPatient->bBleeding && pPatient->ubServiceCount == 0)
{
if (pPatient->bLife < OKLIFE)
if (pPatient->stats.bLife < OKLIFE)
{
bPatientPriority = 3;
}
else if (pPatient->bLife < OKLIFE * 2)
else if (pPatient->stats.bLife < OKLIFE * 2)
{
bPatientPriority = 2;
}
@@ -265,7 +270,7 @@ INT8 FindBestPatient( SOLDIERTYPE * pSoldier, BOOLEAN * pfDoClimb )
if (bPatientPriority >= bBestPriority)
{
if ( !ClimbingNecessary( pSoldier, pPatient->sGridNo, pPatient->bLevel ) )
if ( !ClimbingNecessary( pSoldier, pPatient->sGridNo, pPatient->pathing.bLevel ) )
{
sPatientGridNo = pPatient->sGridNo;
@@ -276,7 +281,7 @@ INT8 FindBestPatient( SOLDIERTYPE * pSoldier, BOOLEAN * pfDoClimb )
for ( cnt2 = 0; cnt2 < NUM_WORLD_DIRECTIONS; cnt2++ )
{
sPatientGridNo = pPatient->sGridNo + DirectionInc( cnt2 );
if ( WhoIsThere2( sPatientGridNo, pPatient->bLevel ) == pPatient->ubID )
if ( WhoIsThere2( sPatientGridNo, pPatient->pathing.bLevel ) == pPatient->ubID )
{
// patient is also here, try this location
sAdjacentGridNo = FindAdjacentGridEx( pSoldier, sPatientGridNo, &ubDirection, &sAdjustedGridNo, FALSE, FALSE );
@@ -353,7 +358,7 @@ INT8 FindBestPatient( SOLDIERTYPE * pSoldier, BOOLEAN * pfDoClimb )
{
sClimbGridNo = NOWHERE;
// see if guy on another building etc and we need to climb somewhere
sPathCost = EstimatePathCostToLocation( pSoldier, pPatient->sGridNo, pPatient->bLevel, FALSE, &fClimbingNecessary, &sClimbGridNo );
sPathCost = EstimatePathCostToLocation( pSoldier, pPatient->sGridNo, pPatient->pathing.bLevel, FALSE, &fClimbingNecessary, &sClimbGridNo );
// if we can get there
if ( sPathCost != 0 && fClimbingNecessary && sPathCost < sShortestClimbPath )
{
@@ -381,19 +386,19 @@ INT8 FindBestPatient( SOLDIERTYPE * pSoldier, BOOLEAN * pfDoClimb )
*pfDoClimb = FALSE;
if ( CardinalSpacesAway( pSoldier->sGridNo, sBestPatientGridNo ) == 1 )
{
pSoldier->usActionData = sBestPatientGridNo;
pSoldier->aiData.usActionData = sBestPatientGridNo;
return( AI_ACTION_GIVE_AID );
}
else
{
pSoldier->usActionData = sBestAdjGridNo;
pSoldier->aiData.usActionData = sBestAdjGridNo;
return( AI_ACTION_GET_CLOSER );
}
}
else if (sBestClimbGridNo != NOWHERE )
{
*pfDoClimb = TRUE;
pSoldier->usActionData = sBestClimbGridNo;
pSoldier->aiData.usActionData = sBestClimbGridNo;
return( AI_ACTION_MOVE_TO_CLIMB );
}
else
@@ -408,7 +413,7 @@ INT8 DecideAutoBandage( SOLDIERTYPE * pSoldier )
BOOLEAN fDoClimb;
if (pSoldier->bMedical == 0 || pSoldier->ubServicePartner != NOBODY)
if (pSoldier->stats.bMedical == 0 || pSoldier->ubServicePartner != NOBODY)
{
// don't/can't make decision
return( AI_ACTION_NONE );
@@ -424,7 +429,7 @@ INT8 DecideAutoBandage( SOLDIERTYPE * pSoldier )
if (pSoldier->bBleeding)
{
// heal self first!
pSoldier->usActionData = pSoldier->sGridNo;
pSoldier->aiData.usActionData = pSoldier->sGridNo;
if (bSlot != HANDPOS)
{
pSoldier->bSlotItemTakenFrom = bSlot;
@@ -443,9 +448,9 @@ INT8 DecideAutoBandage( SOLDIERTYPE * pSoldier )
return( AI_ACTION_GIVE_AID );
}
// pSoldier->usActionData = FindClosestPatient( pSoldier );
pSoldier->bAction = FindBestPatient( pSoldier, &fDoClimb );
if (pSoldier->bAction != AI_ACTION_NONE)
// pSoldier->aiData.usActionData = FindClosestPatient( pSoldier );
pSoldier->aiData.bAction = FindBestPatient( pSoldier, &fDoClimb );
if (pSoldier->aiData.bAction != AI_ACTION_NONE)
{
pSoldier->usUIMovementMode = RUNNING;
if (bSlot != HANDPOS)
@@ -454,9 +459,9 @@ INT8 DecideAutoBandage( SOLDIERTYPE * pSoldier )
SwapObjs( pSoldier, HANDPOS, bSlot, TRUE );
}
return( pSoldier->bAction );
return( pSoldier->aiData.bAction );
}
// do nothing
return( AI_ACTION_NONE );
}
return( AI_ACTION_NONE );
}
+289 -284
View File
File diff suppressed because it is too large Load Diff
+143 -139
View File
@@ -1,14 +1,14 @@
#ifdef PRECOMPILEDHEADERS
#include "AI All.h"
#include "interface items.h"
#else
#include "types.h"
#include "wcheck.h"
#include "overhead.h"
#include "ai.h"
#include "Soldier Profile.h"
#include "Soldier Control.h"
#include "NPC.h"
#include "Isometric Utils.h"
#include "Quests.h"
@@ -49,6 +49,11 @@
#include "Campaign Types.h"
#endif
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
class SOLDIERTYPE;
#define NUM_CIVQUOTE_SECTORS 20
#define MINERS_CIV_QUOTE_INDEX 16
@@ -148,13 +153,13 @@ NPCQuoteInfo * LoadQuoteFile( UINT8 ubNPC )
// If we are the queen....
if ( ubNPC == QUEEN )
{
sprintf( zFileName, "NPCData\\%03d.npc", gubAlternateNPCFileNumsForQueenMeanwhiles[ GetMeanwhileID( ) ] );
sprintf( zFileName, "NPCData\\%03d.npc", gubAlternateNPCFileNumsForQueenMeanwhiles[ GetMeanwhileID( ) ] );
}
// If we are elliot....
if ( ubNPC == ELLIOT )
{
sprintf( zFileName, "NPCData\\%03d.npc", gubAlternateNPCFileNumsForElliotMeanwhiles[ GetMeanwhileID( ) ] );
sprintf( zFileName, "NPCData\\%03d.npc", gubAlternateNPCFileNumsForElliotMeanwhiles[ GetMeanwhileID( ) ] );
}
}
@@ -174,7 +179,7 @@ NPCQuoteInfo * LoadQuoteFile( UINT8 ubNPC )
pFileData = NULL;
}
}
FileClose( hFile );
//<SB> check for Russian script & make a runtime conversion of it to International :D
// just offset ptr 4 bytes backward
@@ -189,7 +194,7 @@ NPCQuoteInfo * LoadQuoteFile( UINT8 ubNPC )
return( pFileData );
}
void RevertToOriginalQuoteFile( UINT8 ubNPC )
void RevertToOriginalQuoteFile( UINT8 ubNPC )
{
if ( gpBackupNPCQuoteInfoArray[ ubNPC ] && gpNPCQuoteInfoArray[ubNPC] )
{
@@ -221,7 +226,7 @@ BOOLEAN EnsureQuoteFileLoaded( UINT8 ubNPC )
if ( ubNPC >= FIRST_RPC && ubNPC < FIRST_NPC )
{
if (gMercProfiles[ ubNPC ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED)
if (gMercProfiles[ ubNPC ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED)
{
// recruited
if ( gpBackupNPCQuoteInfoArray[ ubNPC ] == NULL )
@@ -255,7 +260,7 @@ BOOLEAN EnsureQuoteFileLoaded( UINT8 ubNPC )
if ( ubNPC != NO_PROFILE )
{
SOLDIERTYPE * pNull = NULL;
pNull->bLife = 0; // crash!
pNull->stats.bLife = 0; // crash!
}
#else
@@ -279,7 +284,7 @@ BOOLEAN EnsureQuoteFileLoaded( UINT8 ubNPC )
{
// crash!
SOLDIERTYPE * pNull = NULL;
pNull->bLife = 0;
pNull->stats.bLife = 0;
}
}
@@ -401,7 +406,7 @@ NPCQuoteInfo * LoadCivQuoteFile( UINT8 ubIndex )
pFileData = NULL;
}
}
FileClose( hFile );
return( pFileData );
@@ -470,7 +475,7 @@ void ShutdownNPCQuotes( void )
MemFree( gpBackupNPCQuoteInfoArray[ ubLoop ] );
gpBackupNPCQuoteInfoArray[ ubLoop ] = NULL;
}
}
@@ -589,7 +594,7 @@ UINT8 CalcDesireToTalk( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach )
else
{
iEffectiveLeadership = ((INT32) pMercProfile->bLeadership) * pMercProfile->usApproachFactor[bApproach - 1] / 100;
iApproachVal = pNPCProfile->ubApproachVal[bApproach - 1] * iEffectiveLeadership / 50;
iApproachVal = pNPCProfile->ubApproachVal[bApproach - 1] * iEffectiveLeadership / 50;
}
// NB if town attachment is less than 100% then we should make personal value proportionately more important!
if ( pNPCProfile->bTownAttachment < 100 )
@@ -613,7 +618,7 @@ UINT8 CalcDesireToTalk( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach )
void ApproachedForFirstTime( MERCPROFILESTRUCT * pNPCProfile, INT8 bApproach )
{
UINT8 ubLoop;
UINT8 ubLoop;
UINT32 uiTemp;
pNPCProfile->bApproached |= gbFirstApproachFlags[bApproach - 1];
@@ -630,7 +635,7 @@ void ApproachedForFirstTime( MERCPROFILESTRUCT * pNPCProfile, INT8 bApproach )
UINT8 NPCConsiderTalking( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT8 ubRecord, NPCQuoteInfo * pNPCQuoteInfoArray, NPCQuoteInfo ** ppResultQuoteInfo, UINT8 *pubQuoteNum )
{
// This function returns the opinion level required of the "most difficult" quote
// This function returns the opinion level required of the "most difficult" quote
// that the NPC is willing to say to the merc. It can also provide the quote #.
MERCPROFILESTRUCT * pNPCProfile=NULL;
NPCQuoteInfo * pNPCQuoteInfo=NULL;
@@ -767,7 +772,7 @@ UINT8 NPCConsiderTalking( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT8 ubRec
else
{
if (ppResultQuoteInfo)
{
{
(*ppResultQuoteInfo) = NULL;
}
if ( pubQuoteNum )
@@ -780,7 +785,7 @@ UINT8 NPCConsiderTalking( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT8 ubRec
UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE * pObj, NPCQuoteInfo * pNPCQuoteInfoArray, NPCQuoteInfo ** ppResultQuoteInfo, UINT8 *pubQuoteNum )
{
// This function returns the opinion level required of the "most difficult" quote
// This function returns the opinion level required of the "most difficult" quote
// that the NPC is willing to say to the merc. It can also provide the quote #.
MERCPROFILESTRUCT * pNPCProfile;
NPCQuoteInfo * pNPCQuoteInfo;
@@ -832,7 +837,7 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
case MONEY:
case SILVER:
case GOLD:
if (pObj->ItemData.Money.uiMoneyAmount < LARGE_AMOUNT_MONEY)
if ((*pObj)[0]->data.money.uiMoneyAmount < LARGE_AMOUNT_MONEY)
{
SetFactTrue( FACT_SMALL_AMOUNT_OF_MONEY );
}
@@ -845,12 +850,12 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
case WINE:
case BEER:
usItemToConsider = ALCOHOL;
break;
break;
default:
break;
}
if (pObj->ItemData.Generic.bStatus[0] < 50)
if ((*pObj)[0]->data.objectStatus < 50)
{
SetFactTrue( FACT_ITEM_POOR_CONDITION );
}
@@ -874,14 +879,14 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
case DARREN:
if (usItemToConsider == MONEY && pNPCQuoteInfo->sActionData == NPC_ACTION_DARREN_GIVEN_CASH)
{
if (pObj->ItemData.Money.uiMoneyAmount < 1000)
if ((*pObj)[0]->data.money.uiMoneyAmount < 1000)
{
// refuse, bet too low - record 15
(*ppResultQuoteInfo) = &pNPCQuoteInfoArray[15];
(*pubQuoteNum) = 15;
return( (*ppResultQuoteInfo)->ubOpinionRequired );
}
else if (pObj->ItemData.Money.uiMoneyAmount > 5000)
else if ((*pObj)[0]->data.money.uiMoneyAmount > 5000)
{
// refuse, bet too high - record 16
(*ppResultQuoteInfo) = &pNPCQuoteInfoArray[16];
@@ -905,7 +910,7 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
*/
// record amount of bet
gMercProfiles[ DARREN ].iBalance = pObj->ItemData.Money.uiMoneyAmount;
gMercProfiles[ DARREN ].iBalance = (*pObj)[0]->data.money.uiMoneyAmount;
SetFactFalse( FACT_DARREN_EXPECTING_MONEY );
// if never fought before, use record 17
@@ -916,7 +921,7 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
(*ppResultQuoteInfo) = &pNPCQuoteInfoArray[17];
(*pubQuoteNum) = 17;
}
else
else
{
// find Kingpin, if he's in his house, invoke the script to move him to the bar
SOLDIERTYPE * pKingpin;
@@ -944,22 +949,22 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
}
}
return( (*ppResultQuoteInfo)->ubOpinionRequired );
}
}
break;
case ANGEL:
case ANGEL:
if (usItemToConsider == MONEY && pNPCQuoteInfo->sActionData == NPC_ACTION_ANGEL_GIVEN_CASH)
{
if (pObj->ItemData.Money.uiMoneyAmount < Item[LEATHER_JACKET_W_KEVLAR].usPrice)
if ((*pObj)[0]->data.money.uiMoneyAmount < Item[LEATHER_JACKET_W_KEVLAR].usPrice)
{
// refuse, bet too low - record 8
(*ppResultQuoteInfo) = &pNPCQuoteInfoArray[8];
(*pubQuoteNum) = 8;
return( (*ppResultQuoteInfo)->ubOpinionRequired );
}
else if (pObj->ItemData.Money.uiMoneyAmount > Item[LEATHER_JACKET_W_KEVLAR].usPrice)
else if ((*pObj)[0]->data.money.uiMoneyAmount > Item[LEATHER_JACKET_W_KEVLAR].usPrice)
{
// refuse, bet too high - record 9
(*ppResultQuoteInfo) = &pNPCQuoteInfoArray[9];
@@ -983,15 +988,15 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
// say quote about not catering to women!
(*ppResultQuoteInfo) = &pNPCQuoteInfoArray[5];
(*pubQuoteNum) = 5;
return( (*ppResultQuoteInfo)->ubOpinionRequired );
return( (*ppResultQuoteInfo)->ubOpinionRequired );
}
switch( pObj->ItemData.Money.uiMoneyAmount )
switch( (*pObj)[0]->data.money.uiMoneyAmount )
{
case 100:
case 200: // Carla
if ( CheckFact( FACT_CARLA_AVAILABLE, 0 ) )
{
gMercProfiles[ MADAME ].bNPCData += (INT8) (pObj->ItemData.Money.uiMoneyAmount / 100);
gMercProfiles[ MADAME ].bNPCData += (INT8) ((*pObj)[0]->data.money.uiMoneyAmount / 100);
TriggerNPCRecord( MADAME, 16 );
}
else
@@ -1006,7 +1011,7 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
case 1000: // Cindy
if ( CheckFact( FACT_CINDY_AVAILABLE, 0 ) )
{
gMercProfiles[ MADAME ].bNPCData += (INT8) (pObj->ItemData.Money.uiMoneyAmount / 500);
gMercProfiles[ MADAME ].bNPCData += (INT8) ((*pObj)[0]->data.money.uiMoneyAmount / 500);
TriggerNPCRecord( MADAME, 17 );
}
else
@@ -1021,7 +1026,7 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
case 600: // Bambi
if ( CheckFact( FACT_BAMBI_AVAILABLE, 0 ) )
{
gMercProfiles[ MADAME ].bNPCData += (INT8) (pObj->ItemData.Money.uiMoneyAmount / 300);
gMercProfiles[ MADAME ].bNPCData += (INT8) ((*pObj)[0]->data.money.uiMoneyAmount / 300);
TriggerNPCRecord( MADAME, 18 );
}
else
@@ -1033,10 +1038,10 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
}
break;
case 400:
case 800: // Maria?
case 800: // Maria?
if ( gubQuest[ QUEST_RESCUE_MARIA ] == QUESTINPROGRESS )
{
gMercProfiles[ MADAME ].bNPCData += (INT8) (pObj->ItemData.Money.uiMoneyAmount / 400);
gMercProfiles[ MADAME ].bNPCData += (INT8) ((*pObj)[0]->data.money.uiMoneyAmount / 400);
TriggerNPCRecord( MADAME, 19 );
break;
}
@@ -1081,8 +1086,8 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
if ( CheckFact( FACT_VINCE_EXPECTING_MONEY, ubNPC ) == FALSE && gMercProfiles[ ubNPC ].iBalance < 0 && pNPCQuoteInfo->sActionData != NPC_ACTION_DONT_ACCEPT_ITEM )
{
// increment balance
gMercProfiles[ ubNPC ].iBalance += (INT32) pObj->ItemData.Money.uiMoneyAmount;
gMercProfiles[ ubNPC ].uiTotalCostToDate += pObj->ItemData.Money.uiMoneyAmount;
gMercProfiles[ ubNPC ].iBalance += (INT32) (*pObj)[0]->data.money.uiMoneyAmount;
gMercProfiles[ ubNPC ].uiTotalCostToDate += (*pObj)[0]->data.money.uiMoneyAmount;
if ( gMercProfiles[ ubNPC ].iBalance > 0 )
{
gMercProfiles[ ubNPC ].iBalance = 0;
@@ -1099,13 +1104,13 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
else
{
(*ppResultQuoteInfo) = &pNPCQuoteInfoArray[ 7 ];
}
}
return( (*ppResultQuoteInfo)->ubOpinionRequired );
}
else
{
// handle the player giving NPC some money
HandleNPCBeingGivenMoneyByPlayer( ubNPC, pObj->ItemData.Money.uiMoneyAmount, pubQuoteNum );
HandleNPCBeingGivenMoneyByPlayer( ubNPC, (*pObj)[0]->data.money.uiMoneyAmount, pubQuoteNum );
(*ppResultQuoteInfo) = &pNPCQuoteInfoArray[ *pubQuoteNum ];
return( (*ppResultQuoteInfo)->ubOpinionRequired );
}
@@ -1113,7 +1118,7 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
else
{
// handle the player giving NPC some money
HandleNPCBeingGivenMoneyByPlayer( ubNPC, pObj->ItemData.Money.uiMoneyAmount, pubQuoteNum );
HandleNPCBeingGivenMoneyByPlayer( ubNPC, (*pObj)[0]->data.money.uiMoneyAmount, pubQuoteNum );
(*ppResultQuoteInfo) = &pNPCQuoteInfoArray[ *pubQuoteNum ];
return( (*ppResultQuoteInfo)->ubOpinionRequired );
}
@@ -1122,7 +1127,7 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
case KINGPIN:
if ( usItemToConsider == MONEY && gubQuest[ QUEST_KINGPIN_MONEY ] == QUESTINPROGRESS )
{
HandleNPCBeingGivenMoneyByPlayer( ubNPC, pObj->ItemData.Money.uiMoneyAmount, pubQuoteNum );
HandleNPCBeingGivenMoneyByPlayer( ubNPC, (*pObj)[0]->data.money.uiMoneyAmount, pubQuoteNum );
(*ppResultQuoteInfo) = &pNPCQuoteInfoArray[ *pubQuoteNum ];
return( (*ppResultQuoteInfo)->ubOpinionRequired );
}
@@ -1133,8 +1138,8 @@ UINT8 NPCConsiderReceivingItemFromMerc( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE *
if ( gMercProfiles[ ubNPC ].iBalance < 0 && pNPCQuoteInfo->sActionData != NPC_ACTION_DONT_ACCEPT_ITEM )
{
// increment balance
gMercProfiles[ ubNPC ].iBalance += (INT32) pObj->ItemData.Money.uiMoneyAmount;
gMercProfiles[ ubNPC ].uiTotalCostToDate += pObj->ItemData.Money.uiMoneyAmount;
gMercProfiles[ ubNPC ].iBalance += (INT32) (*pObj)[0]->data.money.uiMoneyAmount;
gMercProfiles[ ubNPC ].uiTotalCostToDate += (*pObj)[0]->data.money.uiMoneyAmount;
if ( gMercProfiles[ ubNPC ].iBalance > 0 )
{
gMercProfiles[ ubNPC ].iBalance = 0;
@@ -1168,7 +1173,7 @@ BOOLEAN HandleNPCBeingGivenMoneyByPlayer( UINT8 ubNPC, UINT32 uiMoneyAmount, UIN
INT32 iCost;
iCost = (INT32) CalcMedicalCost( ubNPC );
// check amount of money
if ( (INT32)uiMoneyAmount + giHospitalTempBalance + giHospitalRefund >= iCost )
{
@@ -1181,7 +1186,7 @@ BOOLEAN HandleNPCBeingGivenMoneyByPlayer( UINT8 ubNPC, UINT32 uiMoneyAmount, UIN
{
*pQuoteValue = 25;
}
if ( giHospitalRefund > 0 )
{
giHospitalRefund = __max( 0, giHospitalRefund - iCost + uiMoneyAmount );
@@ -1196,7 +1201,7 @@ BOOLEAN HandleNPCBeingGivenMoneyByPlayer( UINT8 ubNPC, UINT32 uiMoneyAmount, UIN
InsertDollarSignInToString( sTempString );
// not enough cash
ScreenMsg( FONT_MCOLOR_LTYELLOW,
ScreenMsg( FONT_MCOLOR_LTYELLOW,
MSG_INTERFACE,
Message[ STR_NEED_TO_GIVE_MONEY ],
gMercProfiles[ ubNPC ].zNickname,
@@ -1206,7 +1211,7 @@ BOOLEAN HandleNPCBeingGivenMoneyByPlayer( UINT8 ubNPC, UINT32 uiMoneyAmount, UIN
}
}
break;
case KINGPIN:
case KINGPIN:
if ( (INT32) uiMoneyAmount < -gMercProfiles[ KINGPIN ].iBalance )
{
*pQuoteValue = 9;
@@ -1275,7 +1280,7 @@ UINT8 NPCConsiderQuote( UINT8 ubNPC, UINT8 ubMerc, UINT8 ubApproach, UINT8 ubQuo
{
pNPCProfile = &(gMercProfiles[ubNPC]);
}
// How much do we want to talk with this merc?
uiDay = GetWorldDay();
@@ -1306,7 +1311,7 @@ UINT8 NPCConsiderQuote( UINT8 ubNPC, UINT8 ubMerc, UINT8 ubApproach, UINT8 ubQuo
NpcRecordLogging( ubApproach, "Quest(%d:'%S') Must be in Progress, status is %d. %s", pNPCQuoteInfo->ubQuest, QuestDescText[ pNPCQuoteInfo->ubQuest ], gubQuest[pNPCQuoteInfo->ubQuest], (gubQuest[pNPCQuoteInfo->ubQuest] != QUESTINPROGRESS) ? "False, return" : "True" );
#endif
if (pNPCQuoteInfo->ubQuest > QUEST_DONE_NUM)
if (pNPCQuoteInfo->ubQuest > QUEST_DONE_NUM)
{
if (gubQuest[pNPCQuoteInfo->ubQuest - QUEST_DONE_NUM] != QUESTDONE)
{
@@ -1336,7 +1341,7 @@ UINT8 NPCConsiderQuote( UINT8 ubNPC, UINT8 ubMerc, UINT8 ubApproach, UINT8 ubQuo
#ifdef JA2TESTVERSION
//Add entry to the quest debug file
NpcRecordLogging( ubApproach, "Fact (%d:'%S') Must be True, status is %s", pNPCQuoteInfo->usFactMustBeTrue, FactDescText[pNPCQuoteInfo->usFactMustBeTrue], (fTrue == FALSE) ? "False, returning" : "True" );
#endif
#endif
if (fTrue == FALSE)
{
return( FALSE );
@@ -1353,17 +1358,17 @@ UINT8 NPCConsiderQuote( UINT8 ubNPC, UINT8 ubMerc, UINT8 ubApproach, UINT8 ubQuo
//Add entry to the quest debug file
NpcRecordLogging( ubApproach, "Fact(%d:'%S') Must be False status is %s", pNPCQuoteInfo->usFactMustBeFalse, FactDescText[pNPCQuoteInfo->usFactMustBeFalse], (fTrue == TRUE) ? "True, return" : "FALSE" );
#endif
if (fTrue == TRUE)
{
return( FALSE );
}
}
// check for required approach
// since the "I hate you" code triggers the record, triggering has to work properly
// with the other value that is stored!
// with the other value that is stored!
if ( pNPCQuoteInfo->ubApproachRequired || !(ubApproach == APPROACH_FRIENDLY || ubApproach == APPROACH_DIRECT || ubApproach == TRIGGER_NPC ) )
{
#ifdef JA2TESTVERSION
@@ -1526,10 +1531,10 @@ void ResetOncePerConvoRecordsForAllNPCsInLoadedSector( void )
for ( ubLoop = FIRST_RPC; ubLoop < GASTON; ubLoop++ )
{
if ( gMercProfiles[ ubLoop ].sSectorX == gWorldSectorX &&
gMercProfiles[ ubLoop ].sSectorY == gWorldSectorY &&
if ( gMercProfiles[ ubLoop ].sSectorX == gWorldSectorX &&
gMercProfiles[ ubLoop ].sSectorY == gWorldSectorY &&
gMercProfiles[ ubLoop ].bSectorZ == gbWorldSectorZ &&
gpNPCQuoteInfoArray[ ubLoop ] != NULL )
gpNPCQuoteInfoArray[ ubLoop ] != NULL )
{
ResetOncePerConvoRecordsForNPC( ubLoop );
}
@@ -1556,7 +1561,7 @@ void ReturnItemToPlayerIfNecessary( UINT8 ubMerc, INT8 bApproach, UINT32 uiAppro
{
InternalBeginItemPointer( pSoldier, pObj, NO_SLOT );
}
DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 );
DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 );
}
}
@@ -1597,14 +1602,14 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
}
// make sure civ is awake now
pNPC->fAIFlags &= (~AI_ASLEEP);
pNPC->aiData.fAIFlags &= (~AI_ASLEEP);
}
if (EnsureQuoteFileLoaded( ubNPC ) == FALSE)
{
// error!!!
if ( fAttemptingToGiveItem )
if ( fAttemptingToGiveItem )
{
ReturnItemToPlayerIfNecessary( ubMerc, bApproach, uiApproachData, NULL );
}
@@ -1630,7 +1635,7 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
// turn the NPC to face us
// this '1' value is a dummy....
NPCDoAction( ubNPC, NPC_ACTION_TURN_TO_FACE_NEAREST_MERC, 1 );
if (pProfile->ubLastDateSpokenTo > 0)
{
uiDay = GetWorldDay();
@@ -1640,7 +1645,7 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
if (pQuotePtr != NULL)
{
// converse using this approach instead!
if ( fAttemptingToGiveItem )
if ( fAttemptingToGiveItem )
{
ReturnItemToPlayerIfNecessary( ubMerc, bApproach, uiApproachData, NULL );
}
@@ -1653,7 +1658,7 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
else
{
// say nothing!
if ( fAttemptingToGiveItem )
if ( fAttemptingToGiveItem )
{
ReturnItemToPlayerIfNecessary( ubMerc, bApproach, uiApproachData, NULL );
}
@@ -1667,7 +1672,7 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
if (pQuotePtr != NULL)
{
// converse using this approach instead!
if ( fAttemptingToGiveItem )
if ( fAttemptingToGiveItem )
{
ReturnItemToPlayerIfNecessary( ubMerc, bApproach, uiApproachData, NULL );
}
@@ -1679,7 +1684,7 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
if (pQuotePtr != NULL)
{
// converse using this approach instead!
if ( fAttemptingToGiveItem )
if ( fAttemptingToGiveItem )
{
ReturnItemToPlayerIfNecessary( ubMerc, bApproach, uiApproachData, NULL );
}
@@ -1815,7 +1820,7 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
{
ubQuoteNum = QUOTE_GETLOST;
}
else
else
{
ubQuoteNum = QUOTE_RECRUIT_NO;
pProfile->bRecruitDefaultResponseUsedRecently = TRUE;
@@ -1825,7 +1830,7 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
ubQuoteNum = QUOTE_GIVEITEM_NO;
/*
CC - now handled below
CC - now handled below
*/
break;
case TRIGGER_NPC:
@@ -1884,13 +1889,13 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
if ( pQuotePtr->sActionData <= -NPC_ACTION_TURN_TO_FACE_NEAREST_MERC )
{
pSoldier = FindSoldierByProfileID( ubNPC, FALSE );
ZEROTIMECOUNTER( pSoldier->AICounter );
if (pSoldier->bNextAction == AI_ACTION_WAIT)
ZEROTIMECOUNTER( pSoldier->timeCounters.AICounter );
if (pSoldier->aiData.bNextAction == AI_ACTION_WAIT)
{
pSoldier->bNextAction = AI_ACTION_NONE;
pSoldier->usNextActionData = 0;
pSoldier->aiData.bNextAction = AI_ACTION_NONE;
pSoldier->aiData.usNextActionData = 0;
}
NPCDoAction( ubNPC, (UINT16) -(pQuotePtr->sActionData), ubRecordNum );
NPCDoAction( ubNPC, (UINT16) -(pQuotePtr->sActionData), ubRecordNum );
}
if (pQuotePtr->ubQuoteNum != NO_QUOTE)
{
@@ -1923,13 +1928,12 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
// Is this one of us?
if ( pSoldier->bTeam == gbPlayerNum )
{
INT8 bSlot;
bSlot = FindExactObj( pSoldier, pObj );
if (bSlot != NO_SLOT)
{
RemoveObjs( &(pSoldier->inv[bSlot]), pObj->ubNumberOfObjects );
DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 );
for (int x = INV_START_POS; x < NUM_INV_SLOTS; ++x) {
if (&(pSoldier->inv[x]) == pObj) {
DeleteObj(&pSoldier->inv[x]);
DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 );
break;
}
}
}
else
@@ -2046,29 +2050,29 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
TalkingMenuGiveItem( ubNPC, &(pSoldier->inv[ bInvPos ] ), bInvPos );
}
}
}
// Action before movement?
if ( pQuotePtr->sActionData < 0 && pQuotePtr->sActionData > -NPC_ACTION_TURN_TO_FACE_NEAREST_MERC )
{
pSoldier = FindSoldierByProfileID( ubNPC, FALSE );
ZEROTIMECOUNTER( pSoldier->AICounter );
if (pSoldier->bNextAction == AI_ACTION_WAIT)
ZEROTIMECOUNTER( pSoldier->timeCounters.AICounter );
if (pSoldier->aiData.bNextAction == AI_ACTION_WAIT)
{
pSoldier->bNextAction = AI_ACTION_NONE;
pSoldier->usNextActionData = 0;
pSoldier->aiData.bNextAction = AI_ACTION_NONE;
pSoldier->aiData.usNextActionData = 0;
}
NPCDoAction( ubNPC, (UINT16) -(pQuotePtr->sActionData), ubRecordNum );
NPCDoAction( ubNPC, (UINT16) -(pQuotePtr->sActionData), ubRecordNum );
}
else if ( pQuotePtr->usGoToGridno == NO_MOVE && pQuotePtr->sActionData > 0 )
{
pSoldier = FindSoldierByProfileID( ubNPC, FALSE );
ZEROTIMECOUNTER( pSoldier->AICounter );
if (pSoldier->bNextAction == AI_ACTION_WAIT)
ZEROTIMECOUNTER( pSoldier->timeCounters.AICounter );
if (pSoldier->aiData.bNextAction == AI_ACTION_WAIT)
{
pSoldier->bNextAction = AI_ACTION_NONE;
pSoldier->usNextActionData = 0;
pSoldier->aiData.bNextAction = AI_ACTION_NONE;
pSoldier->aiData.usNextActionData = 0;
}
NPCDoAction( ubNPC, (UINT16) (pQuotePtr->sActionData), ubRecordNum );
NPCDoAction( ubNPC, (UINT16) (pQuotePtr->sActionData), ubRecordNum );
}
// Movement?
@@ -2077,10 +2081,10 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
pSoldier = FindSoldierByProfileID( ubNPC, FALSE );
// stupid hack CC
if (pSoldier && ubNPC == KYLE)
if (pSoldier && ubNPC == KYLE)
{
// make sure he has keys
pSoldier->bHasKeys = TRUE;
pSoldier->flags.bHasKeys = TRUE;
}
if (pSoldier && pSoldier->sGridNo == pQuotePtr->usGoToGridno )
{
@@ -2091,10 +2095,10 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
else
{
// turn off cowering
if ( pNPC->uiStatusFlags & SOLDIER_COWERING)
if ( pNPC->flags.uiStatusFlags & SOLDIER_COWERING)
{
//pNPC->uiStatusFlags &= ~SOLDIER_COWERING;
EVENT_InitNewSoldierAnim( pNPC, STANDING, 0 , FALSE );
//pNPC->flags.uiStatusFlags &= ~SOLDIER_COWERING;
pNPC->EVENT_InitNewSoldierAnim( STANDING, 0 , FALSE );
}
pSoldier->ubQuoteRecord = ubRecordNum + 1; // add 1 so that the value is guaranteed nonzero
@@ -2133,14 +2137,14 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
}
}
// Ian says it is okay to take this out!
// Ian says it is okay to take this out!
/*
if (bApproach == APPROACH_ENEMY_NPC_QUOTE)
{
NPCClosePanel();
}
*/
}
break;
}
@@ -2165,7 +2169,7 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData
}
// return item?
if ( fAttemptingToGiveItem )
if ( fAttemptingToGiveItem )
{
ReturnItemToPlayerIfNecessary( ubMerc, bApproach, uiApproachData, pQuotePtr );
}
@@ -2210,10 +2214,10 @@ INT16 NPCConsiderInitiatingConv( SOLDIERTYPE * pNPC, UINT8 * pubDesiredMerc )
}
// if they're not visible, don't think about it
if (pNPC->bOppList[ubMerc] != SEEN_CURRENTLY)
if (pNPC->aiData.bOppList[ubMerc] != SEEN_CURRENTLY)
{
continue;
}
}
// what's the opinion required for the highest-opinion quote that we would
// say to this merc
@@ -2255,14 +2259,14 @@ INT16 NPCConsiderInitiatingConv( SOLDIERTYPE * pNPC, UINT8 * pubDesiredMerc )
UINT8 NPCTryToInitiateConv( SOLDIERTYPE * pNPC )
{ // assumes current action is ACTION_APPROACH_MERC
if (pNPC->bAction != AI_ACTION_APPROACH_MERC)
if (pNPC->aiData.bAction != AI_ACTION_APPROACH_MERC)
{
return( AI_ACTION_NONE );
}
if (PythSpacesAway( pNPC->sGridNo, MercPtrs[pNPC->usActionData]->sGridNo ) < CONVO_DIST)
if (PythSpacesAway( pNPC->sGridNo, MercPtrs[pNPC->aiData.usActionData]->sGridNo ) < CONVO_DIST)
{
// initiate conversation!
Converse( pNPC->ubProfile, MercPtrs[pNPC->usActionData]->ubProfile, NPC_INITIATING_CONV, 0 );
Converse( pNPC->ubProfile, MercPtrs[pNPC->aiData.usActionData]->ubProfile, NPC_INITIATING_CONV, 0 );
// after talking, wait a while before moving anywhere else
return( AI_ACTION_WAIT );
}
@@ -2327,9 +2331,9 @@ void NPCReachedDestination( SOLDIERTYPE * pNPC, BOOLEAN fAlreadyThere )
if (pNPC->bTeam == gbPlayerNum)
{
// the "under ai control" flag was set temporarily; better turn it off now
pNPC->uiStatusFlags &= (~SOLDIER_PCUNDERAICONTROL);
pNPC->flags.uiStatusFlags &= (~SOLDIER_PCUNDERAICONTROL);
// make damn sure the AI_HANDLE_EVERY_FRAME flag is turned off
pNPC->fAIFlags &= (AI_HANDLE_EVERY_FRAME);
pNPC->aiData.fAIFlags &= (AI_HANDLE_EVERY_FRAME);
}
ubNPC = pNPC->ubProfile;
@@ -2351,7 +2355,7 @@ void NPCReachedDestination( SOLDIERTYPE * pNPC, BOOLEAN fAlreadyThere )
if ( pQuotePtr->sActionData > 0)
{
NPCDoAction( ubNPC, (UINT16) pQuotePtr->sActionData, ubQuoteRecord );
}
}
}
for ( ubLoop = 0; ubLoop < NUM_NPC_QUOTE_RECORDS; ubLoop++ )
@@ -2363,12 +2367,12 @@ void NPCReachedDestination( SOLDIERTYPE * pNPC, BOOLEAN fAlreadyThere )
{
if (fAlreadyThere)
{
TriggerNPCRecord( ubNPC, ubLoop );
TriggerNPCRecord( ubNPC, ubLoop );
}
else
{
// trigger this quote
TriggerNPCRecordImmediately( ubNPC, ubLoop );
TriggerNPCRecordImmediately( ubNPC, ubLoop );
}
return;
}
@@ -2409,12 +2413,12 @@ void TriggerNPCRecordImmediately( UINT8 ubTriggerNPC, UINT8 ubTriggerNPCRec )
// Check if we have a quote to trigger...
NPCQuoteInfo *pQuotePtr;
BOOLEAN fDisplayDialogue = TRUE;
if (EnsureQuoteFileLoaded( ubTriggerNPC ) == FALSE)
{
// error!!!
return;
}
}
pQuotePtr = &(gpNPCQuoteInfoArray[ ubTriggerNPC ][ ubTriggerNPCRec ]);
if ( pQuotePtr->ubQuoteNum == IRRELEVANT )
{
@@ -2447,7 +2451,7 @@ void PCsNearNPC( UINT8 ubNPC )
{
// error!!!
return;
}
}
pNPCQuoteInfoArray = gpNPCQuoteInfoArray[ubNPC];
// see what this triggers...
@@ -2487,7 +2491,7 @@ BOOLEAN PCDoesFirstAidOnNPC( UINT8 ubNPC )
{
// error!!!
return( FALSE );
}
}
pNPCQuoteInfoArray = gpNPCQuoteInfoArray[ubNPC];
// Get ptr to NPC
@@ -2523,19 +2527,19 @@ void TriggerClosestMercWhoCanSeeNPC( UINT8 ubNPC, NPCQuoteInfo *pQuotePtr )
SOLDIERTYPE *pTeamSoldier, *pSoldier;
INT32 cnt;
// First get pointer to NPC
// First get pointer to NPC
pSoldier = FindSoldierByProfileID( ubNPC, FALSE );
// 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;
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
// run through list
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ )
{
// Add guy if he's a candidate...
if ( OK_INSECTOR_MERC( pTeamSoldier ) && pTeamSoldier->bOppList[ pSoldier->ubID ] == SEEN_CURRENTLY )
if ( OK_INSECTOR_MERC( pTeamSoldier ) && pTeamSoldier->aiData.bOppList[ pSoldier->ubID ] == SEEN_CURRENTLY )
{
ubMercsInSector[ ubNumMercs ] = (UINT8)cnt;
ubNumMercs++;
@@ -2576,7 +2580,7 @@ BOOLEAN TriggerNPCWithIHateYouQuote( UINT8 ubTriggerNPC )
// error!!!
return( FALSE );
}
pNPCQuoteInfoArray = gpNPCQuoteInfoArray[ubTriggerNPC];
for ( ubLoop = 0; ubLoop < NUM_NPC_QUOTE_RECORDS; ubLoop++ )
@@ -2608,7 +2612,7 @@ BOOLEAN NPCHasUnusedRecordWithGivenApproach( UINT8 ubNPC, UINT8 ubApproach )
// error!!!
return( FALSE );
}
pNPCQuoteInfoArray = gpNPCQuoteInfoArray[ubNPC];
for ( ubLoop = 0; ubLoop < NUM_NPC_QUOTE_RECORDS; ubLoop++ )
@@ -2636,7 +2640,7 @@ BOOLEAN NPCHasUnusedHostileRecord( UINT8 ubNPC, UINT8 ubApproach )
// error!!!
return( FALSE );
}
pNPCQuoteInfoArray = gpNPCQuoteInfoArray[ubNPC];
for ( ubLoop = 0; ubLoop < NUM_NPC_QUOTE_RECORDS; ubLoop++ )
@@ -2673,7 +2677,7 @@ BOOLEAN NPCWillingToAcceptItem( UINT8 ubNPC, UINT8 ubMerc, OBJECTTYPE * pObj )
// error!!!
return( FALSE );
}
pNPCQuoteInfoArray = gpNPCQuoteInfoArray[ubNPC];
ubOpinion = NPCConsiderReceivingItemFromMerc( ubNPC, ubMerc, pObj, pNPCQuoteInfoArray, &pQuotePtr, &ubQuoteNum );
@@ -2699,7 +2703,7 @@ BOOLEAN GetInfoForAbandoningEPC( UINT8 ubNPC, UINT16 * pusQuoteNum, UINT16 * pus
// error!!!
return( FALSE );
}
pNPCQuoteInfoArray = gpNPCQuoteInfoArray[ubNPC];
for ( ubLoop = 0; ubLoop < NUM_NPC_QUOTE_RECORDS; ubLoop++ )
@@ -2728,7 +2732,7 @@ BOOLEAN TriggerNPCWithGivenApproach( UINT8 ubTriggerNPC, UINT8 ubApproach, BOOLE
// error!!!
return( FALSE );
}
pNPCQuoteInfoArray = gpNPCQuoteInfoArray[ubTriggerNPC];
for ( ubLoop = 0; ubLoop < NUM_NPC_QUOTE_RECORDS; ubLoop++ )
@@ -2768,7 +2772,7 @@ BOOLEAN SaveNPCInfoToSaveGameFile( HWFILE hFile )
//Loop through all the NPC quotes
for( cnt=0; cnt<NUM_PROFILES; cnt++)
{
//if there is a npc qutoe
//if there is a npc qutoe
if( gpNPCQuoteInfoArray[ cnt ] )
{
//save a byte specify that there is an npc quote saved
@@ -2798,7 +2802,7 @@ BOOLEAN SaveNPCInfoToSaveGameFile( HWFILE hFile )
for( cnt = 0; cnt < NUM_CIVQUOTE_SECTORS; cnt++)
{
//if there is a civ quote
//if there is a civ quote
if( gpCivQuoteInfoArray[ cnt ] )
{
//save a byte specify that there is an npc quote saved
@@ -2839,7 +2843,7 @@ BOOLEAN LoadNPCInfoFromSavedGameFile( HWFILE hFile, UINT32 uiSaveGameVersion )
// If we are trying to restore a saved game prior to version 44, use the
// MAX_NUM_SOLDIERS, else use NUM_PROFILES. Dave used the wrong define!
// MAX_NUM_SOLDIERS, else use NUM_PROFILES. Dave used the wrong define!
if( uiSaveGameVersion >= 44 )
uiNumberToLoad = NUM_PROFILES;
else
@@ -2863,7 +2867,7 @@ BOOLEAN LoadNPCInfoFromSavedGameFile( HWFILE hFile, UINT32 uiSaveGameVersion )
gpNPCQuoteInfoArray[ cnt ] = NULL;
}
//if there is a npc quote
//if there is a npc quote
if( ubLoadQuote )
{
//if there is no memory allocated
@@ -3011,7 +3015,7 @@ BOOLEAN SaveBackupNPCInfoToSaveGameFile( HWFILE hFile )
//Loop through all the NPC quotes
for( cnt=0; cnt<NUM_PROFILES; cnt++)
{
//if there is a npc qutoe
//if there is a npc qutoe
if( gpBackupNPCQuoteInfoArray[ cnt ] )
{
//save a byte specify that there is an npc quote saved
@@ -3069,7 +3073,7 @@ BOOLEAN LoadBackupNPCInfoFromSavedGameFile( HWFILE hFile, UINT32 uiSaveGameVersi
gpBackupNPCQuoteInfoArray[ cnt ] = NULL;
}
//if there is a npc quote
//if there is a npc quote
if( ubLoadQuote )
{
//if there is no memory allocated
@@ -3107,7 +3111,7 @@ void TriggerFriendWithHostileQuote( UINT8 ubNPC )
INT32 cnt;
INT8 bTeam;
// First get pointer to NPC
// First get pointer to NPC
pSoldier = FindSoldierByProfileID( ubNPC, FALSE );
if (!pSoldier)
{
@@ -3118,19 +3122,19 @@ 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;
cnt = gTacticalStatus.Team[ bTeam ].bFirstID;
// run through list
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ bTeam ].bLastID; cnt++,pTeamSoldier++ )
{
// Add guy if he's a candidate...
if ( pTeamSoldier->bActive && pSoldier->bInSector && pTeamSoldier->bLife >= OKLIFE && pTeamSoldier->bBreath >= OKBREATH && pTeamSoldier->bOppCnt > 0 && pTeamSoldier->ubProfile != NO_PROFILE )
if ( pTeamSoldier->bActive && pSoldier->bInSector && pTeamSoldier->stats.bLife >= OKLIFE && pTeamSoldier->bBreath >= OKBREATH && pTeamSoldier->aiData.bOppCnt > 0 && pTeamSoldier->ubProfile != NO_PROFILE )
{
if ( bTeam == CIV_TEAM && pSoldier->ubCivilianGroup != NON_CIV_GROUP && pTeamSoldier->ubCivilianGroup != pSoldier->ubCivilianGroup )
{
continue;
}
if ( ! ( gMercProfiles[ pTeamSoldier->ubProfile ].ubMiscFlags & PROFILE_MISC_FLAG_SAID_HOSTILE_QUOTE ) )
{
ubMercsAvailable[ ubNumMercsAvailable ] = pTeamSoldier->ubProfile;
@@ -3144,7 +3148,7 @@ void TriggerFriendWithHostileQuote( UINT8 ubNPC )
{
CivilianGroupMemberChangesSides( pSoldier );
}
if (ubNumMercsAvailable > 0)
{
PauseAITemporarily();
@@ -3171,7 +3175,7 @@ UINT8 ActionIDForMovementRecord( UINT8 ubNPC, UINT8 ubRecord )
// error!!!
return( FALSE );
}
pNPCQuoteInfoArray = gpNPCQuoteInfoArray[ ubNPC ];
pQuotePtr = &( pNPCQuoteInfoArray[ ubRecord ] );
@@ -3198,7 +3202,7 @@ UINT8 ActionIDForMovementRecord( UINT8 ubNPC, UINT8 ubRecord )
void HandleNPCChangesForTacticalTraversal( SOLDIERTYPE * pSoldier )
{
if ( !pSoldier || pSoldier->ubProfile == NO_PROFILE || (pSoldier->fAIFlags & AI_CHECK_SCHEDULE) )
if ( !pSoldier || pSoldier->ubProfile == NO_PROFILE || (pSoldier->aiData.fAIFlags & AI_CHECK_SCHEDULE) )
{
return;
}
@@ -3209,7 +3213,7 @@ void HandleNPCChangesForTacticalTraversal( SOLDIERTYPE * pSoldier )
gMercProfiles[pSoldier->ubProfile].sSectorX++;
// Call to change the NPC's Sector Location
ChangeNpcToDifferentSector( pSoldier->ubProfile,
ChangeNpcToDifferentSector( pSoldier->ubProfile,
gMercProfiles[pSoldier->ubProfile].sSectorX,
gMercProfiles[pSoldier->ubProfile].sSectorY,
gMercProfiles[pSoldier->ubProfile].bSectorZ );
@@ -3218,7 +3222,7 @@ void HandleNPCChangesForTacticalTraversal( SOLDIERTYPE * pSoldier )
gMercProfiles[pSoldier->ubProfile].sSectorY++;
// Call to change the NPC's Sector Location
ChangeNpcToDifferentSector( pSoldier->ubProfile,
ChangeNpcToDifferentSector( pSoldier->ubProfile,
gMercProfiles[pSoldier->ubProfile].sSectorX,
gMercProfiles[pSoldier->ubProfile].sSectorY,
gMercProfiles[pSoldier->ubProfile].bSectorZ );
@@ -3227,7 +3231,7 @@ void HandleNPCChangesForTacticalTraversal( SOLDIERTYPE * pSoldier )
gMercProfiles[pSoldier->ubProfile].sSectorX--;
// Call to change the NPC's Sector Location
ChangeNpcToDifferentSector( pSoldier->ubProfile,
ChangeNpcToDifferentSector( pSoldier->ubProfile,
gMercProfiles[pSoldier->ubProfile].sSectorX,
gMercProfiles[pSoldier->ubProfile].sSectorY,
gMercProfiles[pSoldier->ubProfile].bSectorZ );
@@ -3236,7 +3240,7 @@ void HandleNPCChangesForTacticalTraversal( SOLDIERTYPE * pSoldier )
gMercProfiles[pSoldier->ubProfile].sSectorY--;
// Call to change the NPC's Sector Location
ChangeNpcToDifferentSector( pSoldier->ubProfile,
ChangeNpcToDifferentSector( pSoldier->ubProfile,
gMercProfiles[pSoldier->ubProfile].sSectorX,
gMercProfiles[pSoldier->ubProfile].sSectorY,
gMercProfiles[pSoldier->ubProfile].bSectorZ );
@@ -3328,7 +3332,7 @@ void ToggleNPCRecordDisplay( void )
void UpdateDarrelScriptToGoTo( SOLDIERTYPE * pSoldier )
{
// change destination in Darrel record 10 to go to a gridno adjacent to the
// change destination in Darrel record 10 to go to a gridno adjacent to the
// soldier's gridno, and destination in record 11
INT16 sAdjustedGridNo;
UINT8 ubDummyDirection;
@@ -3352,7 +3356,7 @@ void UpdateDarrelScriptToGoTo( SOLDIERTYPE * pSoldier )
return;
}
}
EnsureQuoteFileLoaded( DARREL );
gpNPCQuoteInfoArray[ DARREL ][ 10 ].usGoToGridno = sAdjustedGridNo;
gpNPCQuoteInfoArray[ DARREL ][ 11 ].sRequiredGridno = -(sAdjustedGridNo);
@@ -3415,7 +3419,7 @@ INT8 ConsiderCivilianQuotes( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ, BOO
// error!!!
return( -1 );
}
pCivQuoteInfoArray = gpCivQuoteInfoArray[ bCivQuoteSectorIndex ];
for ( bLoop = 0; bLoop < NUM_NPC_QUOTE_RECORDS; bLoop++ )
+5 -5
View File
@@ -24,7 +24,7 @@
#define NPC_TALK_RADIUS 4
#define TURN_UI_OFF 65000
#define TURN_UI_ON 65001
#define TURN_UI_ON 65001
#define SPECIAL_TURN_UI_OFF 65002
#define SPECIAL_TURN_UI_ON 65003
@@ -54,18 +54,18 @@ typedef struct
UINT8 ubFirstDay; // first day quote can be said
UINT8 ubLastDay; // last day quote can be said
UINT8 ubApproachRequired; // must use this approach to generate quote
UINT8 ubOpinionRequired; // opinion needed for this quote 13 bytes
UINT8 ubOpinionRequired; // opinion needed for this quote 13 bytes
// quote to say (if any)
UINT8 ubQuoteNum; // this is the quote to say
UINT8 ubNumQuotes; // total # of quotes to say 15 bytes
UINT8 ubNumQuotes; // total # of quotes to say 15 bytes
// actions
UINT8 ubStartQuest;
UINT8 ubEndQuest;
UINT8 ubTriggerNPC;
UINT8 ubTriggerNPCRec;
UINT8 ubFiller; // 20 bytes
UINT8 ubFiller; // 20 bytes
UINT16 usSetFactTrue;
UINT16 usGiftItem; // item NPC gives to merc after saying quote
UINT16 usGoToGridno;
@@ -203,7 +203,7 @@ BOOLEAN GetInfoForAbandoningEPC( UINT8 ubNPC, UINT16 * pusQuoteNum, UINT16 * pus
BOOLEAN RecordHasDialogue( UINT8 ubNPC, UINT8 ubRecord );
INT8 ConsiderCivilianQuotes( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ, BOOLEAN fSetAsUsed );
INT8 ConsiderCivilianQuotes( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ, BOOLEAN fSetAsUsed );
void ResetOncePerConvoRecordsForNPC( UINT8 ubNPC );
+62 -62
View File
@@ -50,15 +50,15 @@ void MakeClosestEnemyChosenOne()
}
// if this merc is unconscious, or dead
if (pSoldier->bLife < OKLIFE)
if (pSoldier->stats.bLife < OKLIFE)
{
continue; // next soldier
continue; // next soldier
}
// if this guy's too tired to go
if (pSoldier->bBreath < OKBREATH)
{
continue; // next soldier
continue; // next soldier
}
if ( gWorldSectorX == TIXA_SECTOR_X && gWorldSectorY == TIXA_SECTOR_Y )
@@ -78,21 +78,21 @@ void MakeClosestEnemyChosenOne()
}
// if this guy is in battle with opponent(s)
if (pSoldier->bOppCnt > 0)
if (pSoldier->aiData.bOppCnt > 0)
{
continue; // next soldier
continue; // next soldier
}
// if this guy is still in serious shock
if (pSoldier->bShock > 2)
if (pSoldier->aiData.bShock > 2)
{
continue; // next soldier
continue; // next soldier
}
if ( pSoldier->bLevel != 0 )
if ( pSoldier->pathing.bLevel != 0 )
{
// screw having guys on the roof go for panic triggers!
continue; // next soldier
continue; // next soldier
}
bPanicTrigger = ClosestPanicTrigger( pSoldier );
@@ -109,27 +109,27 @@ void MakeClosestEnemyChosenOne()
}
// remember whether this guy had keys before
//bOldKeys = pSoldier->bHasKeys;
//bOldKeys = pSoldier->flags.bHasKeys;
// give him keys to see if with them he can get to the panic trigger
pSoldier->bHasKeys = (pSoldier->bHasKeys << 1) | 1;
pSoldier->flags.bHasKeys = (pSoldier->flags.bHasKeys << 1) | 1;
// we now path directly to the panic trigger
// if he can't get to a spot where he could get at the panic trigger
/*
if ( FindAdjacentGridEx( pSoldier, gTacticalStatus.sPanicTriggerGridno, &ubDirection, &sAdjSpot, FALSE, FALSE ) == -1 )
{
pSoldier->bHasKeys = bOldKeys;
continue; // next merc
pSoldier->flags.bHasKeys = bOldKeys;
continue; // next merc
}
*/
// ok, this enemy appears to be eligible
// FindAdjacentGrid set HandGrid for us. If we aren't at that spot already
// FindAdjacentGrid set HandGrid for us. If we aren't at that spot already
if (pSoldier->sGridNo != sPanicTriggerGridNo)
{
// get the AP cost for this enemy to go to target position
@@ -141,7 +141,7 @@ void MakeClosestEnemyChosenOne()
}
// set his keys value back to what it was before this hack
pSoldier->bHasKeys = (pSoldier->bHasKeys >> 1 );
pSoldier->flags.bHasKeys = (pSoldier->flags.bHasKeys >> 1 );
// if he can get there (or is already there!)
if (sPathCost || (pSoldier->sGridNo == sPanicTriggerGridNo))
@@ -159,21 +159,21 @@ void MakeClosestEnemyChosenOne()
// if we found have an eligible enemy, make him our "chosen one"
if (ubClosestEnemy < TOTAL_SOLDIERS)
{
gTacticalStatus.ubTheChosenOne = ubClosestEnemy; // flag him as the chosen one
gTacticalStatus.ubTheChosenOne = ubClosestEnemy; // flag him as the chosen one
#ifdef TESTVERSION
NumMessage("TEST MSG: The chosen one is ",TheChosenOne);
#endif
pSoldier = MercPtrs[gTacticalStatus.ubTheChosenOne];
if ( pSoldier->bAlertStatus < STATUS_RED )
if ( pSoldier->aiData.bAlertStatus < STATUS_RED )
{
pSoldier->bAlertStatus = STATUS_RED;
pSoldier->aiData.bAlertStatus = STATUS_RED;
CheckForChangingOrders( pSoldier );
}
SetNewSituation( pSoldier ); // set new situation for the chosen one
pSoldier->bHasKeys = (pSoldier->bHasKeys << 1) | 1; // cheat and give him keys to every door
//pSoldier->bHasKeys = TRUE;
SetNewSituation( pSoldier ); // set new situation for the chosen one
pSoldier->flags.bHasKeys = (pSoldier->flags.bHasKeys << 1) | 1; // cheat and give him keys to every door
//pSoldier->flags.bHasKeys = TRUE;
}
#ifdef TESTVERSION
else
@@ -194,7 +194,7 @@ void PossiblyMakeThisEnemyChosenOne( SOLDIERTYPE * pSoldier )
return;
}
if ( pSoldier->bLevel != 0 )
if ( pSoldier->pathing.bLevel != 0 )
{
// screw having guys on the roof go for panic triggers!
return;
@@ -216,8 +216,8 @@ void PossiblyMakeThisEnemyChosenOne( SOLDIERTYPE * pSoldier )
return;
}
//bOldKeys = pSoldier->bHasKeys;
pSoldier->bHasKeys = (pSoldier->bHasKeys << 1) | 1;
//bOldKeys = pSoldier->flags.bHasKeys;
pSoldier->flags.bHasKeys = (pSoldier->flags.bHasKeys << 1) | 1;
// if he can't get to a spot where he could get at the panic trigger
iAPCost = AP_PULL_TRIGGER;
@@ -226,23 +226,23 @@ void PossiblyMakeThisEnemyChosenOne( SOLDIERTYPE * pSoldier )
iPathCost = PlotPath( pSoldier, sPanicTriggerGridNo, FALSE, FALSE, FALSE, RUNNING, FALSE, FALSE, 0);
if (iPathCost == 0)
{
//pSoldier->bHasKeys = bOldKeys;
pSoldier->bHasKeys = (pSoldier->bHasKeys >> 1);
//pSoldier->flags.bHasKeys = bOldKeys;
pSoldier->flags.bHasKeys = (pSoldier->flags.bHasKeys >> 1);
return;
}
iAPCost += iPathCost;
}
if ( iAPCost <= CalcActionPoints( pSoldier ) * 2)
if ( iAPCost <= pSoldier->CalcActionPoints( ) * 2)
{
// go!!!
gTacticalStatus.ubTheChosenOne = pSoldier->ubID;
return;
}
// else return keys to normal
//pSoldier->bHasKeys = bOldKeys;
pSoldier->bHasKeys = (pSoldier->bHasKeys >> 1);
//pSoldier->flags.bHasKeys = bOldKeys;
pSoldier->flags.bHasKeys = (pSoldier->flags.bHasKeys >> 1);
}
@@ -278,9 +278,9 @@ INT8 PanicAI(SOLDIERTYPE *pSoldier, UINT8 ubCanMove)
// blow up all the PANIC bombs!
return(AI_ACTION_USE_DETONATOR);
}
else // otherwise, wait a turn
else // otherwise, wait a turn
{
pSoldier->usActionData = NOWHERE;
pSoldier->aiData.usActionData = NOWHERE;
return(AI_ACTION_NONE);
}
}
@@ -305,12 +305,12 @@ INT8 PanicAI(SOLDIERTYPE *pSoldier, UINT8 ubCanMove)
// if not standing on the panic trigger
if (pSoldier->sGridNo != sPanicTriggerGridNo)
{
// determine whether we can still get there
// determine whether we can still get there
iPathCost = PlotPath( pSoldier, sPanicTriggerGridNo, FALSE, FALSE, FALSE, RUNNING, FALSE, FALSE, 0);
if (iPathCost != 0)
{
fFoundRoute = TRUE;
}
}
}
else
{
@@ -324,15 +324,15 @@ INT8 PanicAI(SOLDIERTYPE *pSoldier, UINT8 ubCanMove)
/*
*** COMMENTED OUT BECAUSE WE DON'T HAVE SUPPORT ROUTINES YET
// make sure it's not in water (those triggers can't be pulled)
if (Water(Terrain(gTacticalStatus.sHandGrid),Structure(gTacticalStatus.sHandGrid)))
// make sure it's not in water (those triggers can't be pulled)
if (Water(Terrain(gTacticalStatus.sHandGrid),Structure(gTacticalStatus.sHandGrid)))
{
#ifdef BETAVERSION
PopMessage("BAD SCENARIO DESIGN: Enemies can't use this panic trigger!");
PopMessage("BAD SCENARIO DESIGN: Enemies can't use this panic trigger!");
#endif
gTacticalStatus.ubTheChosenOne = NOBODY; // strip him of his Chosen One status
// don't bother replacing him either, the next won't have more luck!
return(-1);
gTacticalStatus.ubTheChosenOne = NOBODY; // strip him of his Chosen One status
// don't bother replacing him either, the next won't have more luck!
return(-1);
}
*/
@@ -347,23 +347,23 @@ INT8 PanicAI(SOLDIERTYPE *pSoldier, UINT8 ubCanMove)
if (pSoldier->bActionPoints >= AP_PULL_TRIGGER)
{
// blow up the all the PANIC bombs (or just the journal)
pSoldier->usActionData = sPanicTriggerGridNo;
pSoldier->aiData.usActionData = sPanicTriggerGridNo;
#ifdef TESTVERSION
sprintf(tempstr,"TEST MSG: %s - PULLS PANIC TRIGGER at grid %d",
pSoldier->name,pSoldier->usActionData);
pSoldier->name,pSoldier->aiData.usActionData);
PopMessage(tempstr);
#endif
return(AI_ACTION_PULL_TRIGGER);
}
else // otherwise, wait a turn
else // otherwise, wait a turn
{
pSoldier->usActionData = NOWHERE;
pSoldier->aiData.usActionData = NOWHERE;
return(AI_ACTION_NONE);
}
}
else // we are NOT at the HandGrid spot
else // we are NOT at the HandGrid spot
{
// if we can move at least 1 square's worth
if (ubCanMove)
@@ -372,39 +372,39 @@ INT8 PanicAI(SOLDIERTYPE *pSoldier, UINT8 ubCanMove)
// animations don't allow trigger-pulling from water, so we won't!
if (LegalNPCDestination(pSoldier,sPanicTriggerGridNo,ENSURE_PATH,NOWATER,0))
{
pSoldier->usActionData = sPanicTriggerGridNo;
pSoldier->bPathStored = TRUE;
pSoldier->aiData.usActionData = sPanicTriggerGridNo;
pSoldier->pathing.bPathStored = TRUE;
#ifdef DEBUGDECISIONS
sprintf(tempstr,"%s - GETTING CLOSER to PANIC TRIGGER at grid %d (Trigger at %d)", pSoldier->name,pSoldier->usActionData,sPanicTriggerGridNo);
sprintf(tempstr,"%s - GETTING CLOSER to PANIC TRIGGER at grid %d (Trigger at %d)", pSoldier->name,pSoldier->aiData.usActionData,sPanicTriggerGridNo);
AIPopMessage(tempstr);
#endif
return(AI_ACTION_GET_CLOSER);
}
else // Oh oh, the chosen one can't get to the trigger!
else // Oh oh, the chosen one can't get to the trigger!
{
#ifdef TESTVERSION
PopMessage("TEST MSG: Oh oh! !legalDest - ChosenOne can't get to the trigger!");
PopMessage("TEST MSG: Oh oh! !legalDest - ChosenOne can't get to the trigger!");
#endif
gTacticalStatus.ubTheChosenOne = NOBODY; // strip him of his Chosen One status
MakeClosestEnemyChosenOne(); // and replace him!
gTacticalStatus.ubTheChosenOne = NOBODY; // strip him of his Chosen One status
MakeClosestEnemyChosenOne(); // and replace him!
}
}
else // can't move, wait 1 turn
else // can't move, wait 1 turn
{
pSoldier->usActionData = NOWHERE;
pSoldier->aiData.usActionData = NOWHERE;
return(AI_ACTION_NONE);
}
}
}
else // Oh oh, the chosen one can't get to the trigger!
else // Oh oh, the chosen one can't get to the trigger!
{
#ifdef TESTVERSION
PopMessage("TEST MSG: Oh oh! !adjacentFound - ChosenOne can't get to the trigger!");
PopMessage("TEST MSG: Oh oh! !adjacentFound - ChosenOne can't get to the trigger!");
#endif
gTacticalStatus.ubTheChosenOne = NOBODY; // strip him of his Chosen One status
MakeClosestEnemyChosenOne(); // and replace him!
MakeClosestEnemyChosenOne(); // and replace him!
}
}
}
@@ -428,13 +428,13 @@ INT8 ClosestPanicTrigger( SOLDIERTYPE * pSoldier )
INT8 bClosestTrigger = -1;
UINT32 uiPercentEnemiesKilled;
uiPercentEnemiesKilled = (UINT32)( 100 * (UINT32)(gTacticalStatus.ubArmyGuysKilled) / (UINT32)( gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector + gTacticalStatus.ubArmyGuysKilled ) );
uiPercentEnemiesKilled = (UINT32)( 100 * (UINT32)(gTacticalStatus.ubArmyGuysKilled) / (UINT32)( gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector + gTacticalStatus.ubArmyGuysKilled ) );
for ( bLoop = 0; bLoop < NUM_PANIC_TRIGGERS; bLoop++ )
{
if ( gTacticalStatus.sPanicTriggerGridNo[ bLoop ] != NOWHERE )
{
if ( gTacticalStatus.ubPanicTolerance[ bLoop ] > uiPercentEnemiesKilled )
{
// not yet... not yet...
@@ -496,7 +496,7 @@ BOOLEAN NeedToRadioAboutPanicTrigger( void )
}
uiPercentEnemiesKilled = (UINT32)( 100 * (UINT32)(gTacticalStatus.ubArmyGuysKilled) / (UINT32)( gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector + gTacticalStatus.ubArmyGuysKilled ) );
uiPercentEnemiesKilled = (UINT32)( 100 * (UINT32)(gTacticalStatus.ubArmyGuysKilled) / (UINT32)( gTacticalStatus.Team[ ENEMY_TEAM ].bMenInSector + gTacticalStatus.ubArmyGuysKilled ) );
for ( bLoop = 0; bLoop < NUM_PANIC_TRIGGERS; bLoop++ )
{
@@ -517,7 +517,7 @@ BOOLEAN NeedToRadioAboutPanicTrigger( void )
INT8 HeadForTheStairCase( SOLDIERTYPE * pSoldier )
{
UNDERGROUND_SECTORINFO * pBasementInfo;
pBasementInfo = FindUnderGroundSector( 3, MAP_ROW_P, 1 );
if ( pBasementInfo && pBasementInfo->uiTimeCurrentSectorWasLastLoaded != 0 && ( pBasementInfo->ubNumElites + pBasementInfo->ubNumTroops + pBasementInfo->ubNumAdmins ) < 5 )
{
@@ -532,7 +532,7 @@ INT8 HeadForTheStairCase( SOLDIERTYPE * pSoldier )
{
if ( LegalNPCDestination( pSoldier, STAIRCASE_GRIDNO, ENSURE_PATH, WATEROK, 0 ) )
{
pSoldier->usActionData = STAIRCASE_GRIDNO;
pSoldier->aiData.usActionData = STAIRCASE_GRIDNO;
return( AI_ACTION_GET_CLOSER );
}
}
+4 -4
View File
@@ -91,15 +91,15 @@ void QuestDebugFileMsg( UINT8 ubQuoteType, UINT8 ubPriority, STR pStringA, ...)
static UINT32 uiLineNumber = 1;
HWFILE hFile;
UINT32 uiByteWritten;
va_list argptr;
char TempString[1024];
char DestString[1024];
va_list argptr;
char TempString[1024];
char DestString[1024];
TempString[0] = '\0';
DestString[0] = '\0';
va_start(argptr, pStringA); // Set up variable argument pointer
va_start(argptr, pStringA); // Set up variable argument pointer
vsprintf(TempString, pStringA, argptr); // process gprintf string (get output str)
va_end(argptr);
+49 -49
View File
@@ -34,7 +34,7 @@ INT8 RTPlayerDecideAction( SOLDIERTYPE * pSoldier )
#ifdef DEBUGDECISIONS
STR tempstr;
sprintf(tempstr,"DecideAction: selected action %d, actionData %d\n\n",bAction,pSoldier->usActionData);
sprintf(tempstr,"DecideAction: selected action %d, actionData %d\n\n",bAction,pSoldier->aiData.usActionData);
DebugAI( tempstr );
#endif
@@ -64,7 +64,7 @@ INT8 RTDecideAction(SOLDIERTYPE *pSoldier)
gMercProfiles[ pSoldier->ubProfile ].ubMiscFlags3 &= (~PROFILE_MISC_FLAG3_HANDLE_DONE_TRAVERSAL);
pSoldier->ubQuoteActionID = 0;
// wait a tiny bit
pSoldier->usActionData = 100;
pSoldier->aiData.usActionData = 100;
return( AI_ACTION_WAIT );
}
@@ -74,17 +74,17 @@ INT8 RTDecideAction(SOLDIERTYPE *pSoldier)
UINT16 RealtimeDelay( SOLDIERTYPE * pSoldier )
{
if ( PTR_CIV_OR_MILITIA && !(pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP ) )
if ( PTR_CIV_OR_MILITIA && !(pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP ) )
{
return( (UINT16) REALTIME_CIV_AI_DELAY );
}
else if ( CREATURE_OR_BLOODCAT( pSoldier ) && !( pSoldier->bHunting ) )
else if ( CREATURE_OR_BLOODCAT( pSoldier ) && !( pSoldier->aiData.bHunting ) )
{
return( (UINT16) REALTIME_CREATURE_AI_DELAY );
}
else
{
if ( pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP )
{
UINT8 ubRoom;
@@ -107,8 +107,8 @@ void RTHandleAI( SOLDIERTYPE * pSoldier )
INT32 iLoop;
#endif
if ((pSoldier->bAction != AI_ACTION_NONE) && pSoldier->bActionInProgress)
{
if ((pSoldier->aiData.bAction != AI_ACTION_NONE) && pSoldier->aiData.bActionInProgress)
{
// if action should remain in progress
if (ActionInProgress(pSoldier))
{
@@ -117,16 +117,16 @@ void RTHandleAI( SOLDIERTYPE * pSoldier )
#endif
// let it continue
return;
}
}
}
// if man has nothing to do
if (pSoldier->bAction == AI_ACTION_NONE)
if (pSoldier->aiData.bAction == AI_ACTION_NONE)
{
if (pSoldier->bNextAction == AI_ACTION_NONE)
if (pSoldier->aiData.bNextAction == AI_ACTION_NONE)
{
// make sure this flag is turned off (it already should be!)
pSoldier->bActionInProgress = FALSE;
pSoldier->aiData.bActionInProgress = FALSE;
// truly nothing to do!
RefreshAI( pSoldier );
@@ -147,123 +147,123 @@ void RTHandleAI( SOLDIERTYPE * pSoldier )
// The only reason we would NEED to reinitialize it here is if I've
// incorrectly set pathStored to TRUE in a process that doesn't end up
// calling NewDest()
pSoldier->bPathStored = FALSE;
pSoldier->pathing.bPathStored = FALSE;
// decide on the next action
#ifdef AI_PROFILING
for (iLoop = 0; iLoop < 1000; iLoop++)
#endif
{
if (pSoldier->bNextAction != AI_ACTION_NONE)
if (pSoldier->aiData.bNextAction != AI_ACTION_NONE)
{
if ( pSoldier->bNextAction == AI_ACTION_END_COWER_AND_MOVE )
if ( pSoldier->aiData.bNextAction == AI_ACTION_END_COWER_AND_MOVE )
{
if ( pSoldier->uiStatusFlags & SOLDIER_COWERING )
if ( pSoldier->flags.uiStatusFlags & SOLDIER_COWERING )
{
pSoldier->bAction = AI_ACTION_STOP_COWERING;
pSoldier->usActionData = ANIM_STAND;
pSoldier->aiData.bAction = AI_ACTION_STOP_COWERING;
pSoldier->aiData.usActionData = ANIM_STAND;
}
else if ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight < ANIM_STAND )
{
// stand up!
pSoldier->bAction = AI_ACTION_CHANGE_STANCE;
pSoldier->usActionData = ANIM_STAND;
pSoldier->aiData.bAction = AI_ACTION_CHANGE_STANCE;
pSoldier->aiData.usActionData = ANIM_STAND;
}
else
{
pSoldier->bAction = AI_ACTION_NONE;
pSoldier->aiData.bAction = AI_ACTION_NONE;
}
if ( pSoldier->sGridNo == pSoldier->usNextActionData )
if ( pSoldier->sGridNo == pSoldier->aiData.usNextActionData )
{
// no need to walk after this
pSoldier->bNextAction = AI_ACTION_NONE;
pSoldier->usNextActionData = NOWHERE;
pSoldier->aiData.bNextAction = AI_ACTION_NONE;
pSoldier->aiData.usNextActionData = NOWHERE;
}
else
{
pSoldier->bNextAction = AI_ACTION_WALK;
pSoldier->aiData.bNextAction = AI_ACTION_WALK;
// leave next-action-data as is since that's where we want to go
}
}
else
{
// do the next thing we have to do...
pSoldier->bAction = pSoldier->bNextAction;
pSoldier->usActionData = pSoldier->usNextActionData;
pSoldier->bTargetLevel = pSoldier->bNextTargetLevel;
pSoldier->bNextAction = AI_ACTION_NONE;
pSoldier->usNextActionData = 0;
pSoldier->bNextTargetLevel = 0;
pSoldier->aiData.bAction = pSoldier->aiData.bNextAction;
pSoldier->aiData.usActionData = pSoldier->aiData.usNextActionData;
pSoldier->bTargetLevel = pSoldier->aiData.bNextTargetLevel;
pSoldier->aiData.bNextAction = AI_ACTION_NONE;
pSoldier->aiData.usNextActionData = 0;
pSoldier->aiData.bNextTargetLevel = 0;
}
if (pSoldier->bAction == AI_ACTION_PICKUP_ITEM)
if (pSoldier->aiData.bAction == AI_ACTION_PICKUP_ITEM)
{
// the item pool index was stored in the special data field
pSoldier->uiPendingActionData1 = pSoldier->iNextActionSpecialData;
pSoldier->aiData.uiPendingActionData1 = pSoldier->iNextActionSpecialData;
}
}
else if ( pSoldier->sAbsoluteFinalDestination != NOWHERE )
{
if ( ACTING_ON_SCHEDULE( pSoldier ) )
{
pSoldier->bAction = AI_ACTION_SCHEDULE_MOVE;
pSoldier->aiData.bAction = AI_ACTION_SCHEDULE_MOVE;
}
else
{
pSoldier->bAction = AI_ACTION_WALK;
pSoldier->aiData.bAction = AI_ACTION_WALK;
}
pSoldier->usActionData = pSoldier->sAbsoluteFinalDestination;
pSoldier->aiData.usActionData = pSoldier->sAbsoluteFinalDestination;
}
else
{
if (!(gTacticalStatus.uiFlags & ENGAGED_IN_CONV))
{
pSoldier->bAction = RTDecideAction( pSoldier );
pSoldier->aiData.bAction = RTDecideAction( pSoldier );
}
}
}
// if he chose to continue doing nothing
if (pSoldier->bAction == AI_ACTION_NONE)
if (pSoldier->aiData.bAction == AI_ACTION_NONE)
{
#ifdef RECORDNET
fprintf(NetDebugFile,"\tMOVED BECOMING TRUE: Chose to do nothing, guynum %d\n",pSoldier->ubID);
#endif
// do a standard wait before doing anything else!
pSoldier->bAction = AI_ACTION_WAIT;
//if (PTR_CIVILIAN && pSoldier->bAlertStatus != STATUS_BLACK)
if ( PTR_CIV_OR_MILITIA && !(pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP ) )
pSoldier->aiData.bAction = AI_ACTION_WAIT;
//if (PTR_CIVILIAN && pSoldier->aiData.bAlertStatus != STATUS_BLACK)
if ( PTR_CIV_OR_MILITIA && !(pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP ) )
{
pSoldier->usActionData = (UINT16) REALTIME_CIV_AI_DELAY;
pSoldier->aiData.usActionData = (UINT16) REALTIME_CIV_AI_DELAY;
}
else if ( CREATURE_OR_BLOODCAT( pSoldier ) && !( pSoldier->bHunting ) )
else if ( CREATURE_OR_BLOODCAT( pSoldier ) && !( pSoldier->aiData.bHunting ) )
{
pSoldier->usActionData = (UINT16) REALTIME_CREATURE_AI_DELAY;
pSoldier->aiData.usActionData = (UINT16) REALTIME_CREATURE_AI_DELAY;
}
else
{
pSoldier->usActionData = (UINT16) REALTIME_AI_DELAY;
pSoldier->aiData.usActionData = (UINT16) REALTIME_AI_DELAY;
if ( pSoldier->ubCivilianGroup == KINGPIN_CIV_GROUP )
{
UINT8 ubRoom;
if ( InARoom( pSoldier->sGridNo, &ubRoom ) && IN_BROTHEL( ubRoom ) )
{
pSoldier->usActionData /= 3;
pSoldier->aiData.usActionData /= 3;
}
}
}
}
else if (pSoldier->bAction == AI_ACTION_ABSOLUTELY_NONE)
else if (pSoldier->aiData.bAction == AI_ACTION_ABSOLUTELY_NONE)
{
pSoldier->bAction = AI_ACTION_NONE;
pSoldier->aiData.bAction = AI_ACTION_NONE;
}
}
}
// to get here, we MUST have an action selected, but not in progress...
NPCDoesAct(pSoldier);
// perform the chosen action
pSoldier->bActionInProgress = ExecuteAction(pSoldier); // if started, mark us as busy
pSoldier->aiData.bActionInProgress = ExecuteAction(pSoldier); // if started, mark us as busy
}
+66 -4
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Version="8.00"
Name="TacticalAI_2005Express"
ProjectGUID="{27A49DAF-3F5A-4FF2-B943-9559F0B63032}"
RootNamespace="TacticalAI_2005Express"
@@ -39,7 +39,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D &quot;_CRT_SECURE_NO_DEPRECATE&quot;&#x0D;&#x0A;"
AdditionalOptions="/D &quot;_CRT_SECURE_NO_DEPRECATE&quot;"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;"
MinimalRebuild="true"
@@ -103,7 +103,6 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D &quot;_CRT_SECURE_NO_DEPRECATE&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;"
RuntimeLibrary="0"
RuntimeTypeInfo="false"
@@ -139,6 +138,69 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="MapEditor|Win32"
OutputDirectory="MapEditor"
IntermediateDirectory="MapEditor"
ConfigurationType="4"
InheritedPropertySheets="..\ja2_2005Express.vsprops;..\ja2_2005ExpressEditor.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
+11 -11
View File
@@ -25,8 +25,8 @@ enum CreatureCalls
NUM_CREATURE_CALLS
} ;
#define DONTFORCE 0
#define FORCE 1
#define DONTFORCE 0
#define FORCE 1
// ANY NEW ACTIONS ADDED - UPDATE OVERHEAD.C ARRAY WITH ACTION'S STRING VALUE
#define FIRST_MOVEMENT_ACTION AI_ACTION_RANDOM_PATROL
@@ -81,7 +81,7 @@ typedef enum
AI_ACTION_WAIT, // RT: don't do anything for a certain length of time
AI_ACTION_PENDING_ACTION, // RT: wait for pending action (pickup, door open, etc) to finish
AI_ACTION_DROP_ITEM, // duh
AI_ACTION_COWER, // for civilians: cower in fear and stay there!
AI_ACTION_COWER, // for civilians: cower in fear and stay there!
AI_ACTION_STOP_COWERING, // stop cowering
AI_ACTION_OPEN_OR_CLOSE_DOOR, // schedule-provoked; open or close door
@@ -131,12 +131,12 @@ enum QuoteActionType
#define IS_NEW_SITUATION 2
#define DIFF_ENEMY_EQUIP_MOD 0
#define DIFF_ENEMY_TO_HIT_MOD 1
#define DIFF_ENEMY_INTERRUPT_MOD 2
#define DIFF_RADIO_RED_ALERT 3
#define DIFF_MAX_COVER_RANGE 4
#define MAX_DIFF_PARMS 5 // how many different difficulty variables?
#define DIFF_ENEMY_EQUIP_MOD 0
#define DIFF_ENEMY_TO_HIT_MOD 1
#define DIFF_ENEMY_INTERRUPT_MOD 2
#define DIFF_RADIO_RED_ALERT 3
#define DIFF_MAX_COVER_RANGE 4
#define MAX_DIFF_PARMS 5 // how many different difficulty variables?
extern INT8 gbDiff[MAX_DIFF_PARMS][5];
@@ -171,7 +171,7 @@ INT16 DistanceToClosestFriend( SOLDIERTYPE * pSoldier );
void EndAIDeadlock(void);
void EndAIGuysTurn( SOLDIERTYPE *pSoldier );
INT8 ExecuteAction(SOLDIERTYPE *pSoldier);
INT8 ExecuteAction(SOLDIERTYPE *pSoldier);
INT16 FindAdjacentSpotBeside(SOLDIERTYPE *pSoldier, INT16 sGridno);
INT16 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *pPercentBetter);
@@ -179,7 +179,7 @@ INT16 FindClosestDoor( SOLDIERTYPE * pSoldier );
INT16 FindNearbyPointOnEdgeOfMap( SOLDIERTYPE * pSoldier, INT8 * pbDirection );
INT16 FindNearestEdgePoint( INT16 sGridNo );
//Kris: Added these as I need specific searches on certain sides.
//Kris: Added these as I need specific searches on certain sides.
enum
{
NORTH_EDGEPOINT_SEARCH,