#include "types.h" #include "Isometric Utils.h" #include "Animation Control.h" #include "Overhead.h" #include "random.h" #include "Points.h" extern BOOLEAN gfTurnBasedAI; #define MAX_DIST 160 // 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 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 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 #define NOWATER 0 #define WATEROK 1 #define DONTADDTURNCOST 0 #define ADDTURNCOST 1 enum { URGENCY_LOW = 0, URGENCY_MED, URGENCY_HIGH, NUM_URGENCY_STATES }; #define NOWATER 0 #define WATEROK 1 #define IGNORE_PATH 0 #define ENSURE_PATH 1 #define ENSURE_PATH_COST 2 #define DONTFORCE 0 #define FORCE 1 #define MAX_ROAMING_RANGE WORLD_COLS #define PTR_CIV_OR_MILITIA ( PTR_CIVILIAN || (pSoldier->bTeam == MILITIA_TEAM) ) #define REALTIME_AI_DELAY (10000 + Random( 1000 )) #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 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 ACTION_TIMEOUT_CYCLES 50 // # failed cycles through AI #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 SEE_THRU_COVER_THRESHOLD 5 // min chance to get through #undef min #define min(a,b) ((a) < (b) ? (a) : (b)) #undef max #define max(a,b) ((a) > (b) ? (a) : (b)) typedef struct { SOLDIERTYPE * pOpponent; INT16 sGridNo; INT32 iValue; INT32 iAPs; INT32 iCertainty; INT32 iOrigRange; } THREATTYPE; // define for bAimTime for bursting #define BURSTING 20 #define AUTOFIRING 21 typedef struct { 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 INT16 sTarget; // target gridno 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 } ATTACKTYPE; extern THREATTYPE Threat[MAXMERCS]; extern int ThreatPercent[10]; extern UINT8 SkipCoverCheck; extern INT8 GameOption[MAXGAMEOPTIONS]; typedef enum { SEARCH_GENERAL_ITEMS, SEARCH_AMMO, SEARCH_WEAPONS } ItemSearchReasons; // go as far as possible flags #define FLAG_CAUTIOUS 0x01 #define FLAG_STOPSHORT 0x02 #define STOPSHORTDIST 5 INT16 AdvanceToFiringRange( SOLDIERTYPE * pSoldier, INT16 sClosestOpponent ); BOOLEAN AimingGun(SOLDIERTYPE *pSoldier); void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUnseen); void CalcBestStab(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestStab, BOOLEAN fBladeAttack); void CalcBestThrow(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow); void CalcTentacleAttack(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestStab ); INT16 CalcSpreadBurst( SOLDIERTYPE * pSoldier, INT16 sFirstTarget, INT8 bTargetLevel ); INT32 CalcManThreatValue(SOLDIERTYPE *pSoldier, INT16 sMyGrid, UINT8 ubReduceForCover, SOLDIERTYPE * pMe ); INT8 CanNPCAttack(SOLDIERTYPE *pSoldier); void CheckIfTossPossible(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestThrow); BOOLEAN ClimbingNecessary( SOLDIERTYPE * pSoldier, INT16 sDestGridNo, INT8 bDestLevel ); INT8 ClosestPanicTrigger( SOLDIERTYPE * pSoldier ); INT16 ClosestReachableDisturbance(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK, BOOLEAN * pfChangeLevel ); INT16 ClosestReachableFriendInTrouble(SOLDIERTYPE *pSoldier, BOOLEAN * pfClimbingNecessary); INT16 ClosestSeenOpponent(SOLDIERTYPE *pSoldier, INT16 * psGridNo, INT8 * pbLevel); void CreatureCall( SOLDIERTYPE * pCaller ); INT8 CreatureDecideAction( SOLDIERTYPE * pCreature ); void CreatureDecideAlertStatus( SOLDIERTYPE *pCreature ); INT8 CrowDecideAction( SOLDIERTYPE * pSoldier ); void DecideAlertStatus( SOLDIERTYPE *pSoldier ); INT8 DecideAutoBandage( SOLDIERTYPE * pSoldier ); UINT16 DetermineMovementMode( SOLDIERTYPE * pSoldier, INT8 bAction ); INT32 EstimateShotDamage(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, UINT8 ubChanceToHit); INT32 EstimateStabDamage(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, UINT8 ubChanceToHit, BOOLEAN fBladeAttack); INT32 EstimateThrowDamage(SOLDIERTYPE *pSoldier, UINT8 ubItemPos, SOLDIERTYPE *pOpponent, INT16 sGridno); INT16 EstimatePathCostToLocation( SOLDIERTYPE * pSoldier, INT16 sDestGridNo, INT8 bDestLevel, BOOLEAN fAddCostAfterClimbingUp, BOOLEAN * pfClimbingNecessary, INT16 * psClimbGridNo ); BOOLEAN FindBetterSpotForItem( SOLDIERTYPE * pSoldier, INT8 bSlot ); INT16 FindClosestClimbPointAvailableToAI( SOLDIERTYPE * pSoldier, INT16 sStartGridNo, INT16 sDesiredGridNo, BOOLEAN fClimbUp ); INT16 FindRouteBackOntoMap( SOLDIERTYPE * pSoldier, INT16 sDestGridNo ); INT16 FindClosestBoxingRingSpot( SOLDIERTYPE * pSoldier, BOOLEAN fInRing ); INT16 GetInterveningClimbingLocation( SOLDIERTYPE * pSoldier, INT16 sDestGridNo, INT8 bDestLevel, BOOLEAN * pfClimbingNecessary ); UINT8 GetTraversalQuoteActionID( INT8 bDirection ); INT16 GoAsFarAsPossibleTowards(SOLDIERTYPE *pSoldier, INT16 sDesGrid, INT8 bAction); INT8 HeadForTheStairCase( SOLDIERTYPE * pSoldier ); BOOLEAN InGas( SOLDIERTYPE *pSoldier, INT16 sGridNo ); BOOLEAN InGasOrSmoke( SOLDIERTYPE *pSoldier, INT16 sGridNo ); BOOLEAN InWaterGasOrSmoke( SOLDIERTYPE *pSoldier, INT16 sGridNo ); void InitAttackType(ATTACKTYPE *pAttack); INT16 InternalGoAsFarAsPossibleTowards(SOLDIERTYPE *pSoldier, INT16 sDesGrid, INT8 bReserveAPs, INT8 bAction, INT8 fFlags ); int LegalNPCDestination(SOLDIERTYPE *pSoldier, INT16 sGridno, UINT8 ubPathMode, UINT8 ubWaterOK, UINT8 fFlags); void LoadWeaponIfNeeded(SOLDIERTYPE *pSoldier); INT16 MostImportantNoiseHeard( SOLDIERTYPE *pSoldier, INT32 *piRetValue, BOOLEAN * pfClimbingNecessary, BOOLEAN * pfReachable ); INT16 NPCConsiderInitiatingConv( SOLDIERTYPE * pNPC, UINT8 * pubDesiredMerc ); void NPCDoesAct(SOLDIERTYPE *pSoldier); void NPCDoesNothing(SOLDIERTYPE *pSoldier); INT8 OKToAttack(SOLDIERTYPE *ptr, int target); BOOLEAN NeedToRadioAboutPanicTrigger( void ); INT8 PointPatrolAI(SOLDIERTYPE *pSoldier); void PossiblyMakeThisEnemyChosenOne( SOLDIERTYPE * pSoldier ); INT8 RandomPointPatrolAI(SOLDIERTYPE *pSoldier); INT32 RangeChangeDesire( SOLDIERTYPE * pSoldier ); UINT16 RealtimeDelay( SOLDIERTYPE * pSoldier ); void RearrangePocket(SOLDIERTYPE *pSoldier, INT8 bPocket1, INT8 bPocket2, UINT8 bPermanent); void RTHandleAI( SOLDIERTYPE * pSoldier ); UINT16 RunAway( SOLDIERTYPE * pSoldier ); INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ); UINT8 ShootingStanceChange( SOLDIERTYPE * pSoldier, ATTACKTYPE * pAttack, INT8 bDesiredDirection ); UINT8 StanceChange( SOLDIERTYPE * pSoldier, UINT8 ubAttackAPCost ); INT16 TrackScent( SOLDIERTYPE * pSoldier ); void RefreshAI(SOLDIERTYPE *pSoldier); BOOLEAN InLightAtNight( INT16 sGridNo, INT8 bLevel ); INT16 FindNearbyDarkerSpot( SOLDIERTYPE *pSoldier ); BOOLEAN ArmySeesOpponents( void ); void CheckIfShotPossible(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN suppressionFire); INT16 FindBestCoverNearTheGridNo(SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubSearchRadius ); INT8 FindDirectionForClimbing( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bLevel);