1 #ifndef __OVERHEAD_H
2 #define __OVERHEAD_H
3
4 #include "Debug.h"
5 #include "Soldier_Control.h"
6
7
8 #define MAX_REALTIME_SPEED_VAL 10
9
10
11 // Enums for waiting for mercs to finish codes
12 enum
13 {
14 NO_WAIT_EVENT = 0,
15 WAIT_FOR_MERCS_TO_WALKOFF_SCREEN,
16 WAIT_FOR_MERCS_TO_WALKON_SCREEN,
17 WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO
18 };
19
20
21 // TACTICAL ENGINE STATUS FLAGS
22 struct TacticalTeamType
23 {
24 UINT8 bFirstID;
25 UINT8 bLastID;
26 COLORVAL RadarColor;
27 INT8 bSide;
28 INT8 bMenInSector;
29 INT8 bAwareOfOpposition;
30 INT8 bHuman;
31 SOLDIERTYPE* last_merc_to_radio;
32 };
33
34
35 #define PANIC_BOMBS_HERE 0x01
36 #define PANIC_TRIGGERS_HERE 0x02
37
38 #define NUM_PANIC_TRIGGERS 3
39
40 #define ENEMY_OFFERED_SURRENDER 0x01
41
42 struct TacticalStatusType
43 {
44 UINT32 uiFlags;
45 TacticalTeamType Team[MAXTEAMS];
46 UINT8 ubCurrentTeam;
47 INT16 sSlideTarget;
48 UINT32 uiTimeSinceMercAIStart;
49 INT8 fPanicFlags;
50 UINT8 ubSpottersCalledForBy;
51 SOLDIERTYPE* the_chosen_one;
52 UINT32 uiTimeOfLastInput;
53 UINT32 uiTimeSinceDemoOn;
54 BOOLEAN fCivGroupHostile[ NUM_CIV_GROUPS ];
55 UINT8 ubLastBattleSectorX;
56 UINT8 ubLastBattleSectorY;
57 BOOLEAN fLastBattleWon;
58 BOOLEAN fVirginSector;
59 BOOLEAN fEnemyInSector;
60 BOOLEAN fInterruptOccurred;
61 INT8 bRealtimeSpeed;
62 SOLDIERTYPE* enemy_sighting_on_their_turn_enemy;
63 BOOLEAN fEnemySightingOnTheirTurn;
64 BOOLEAN fAutoBandageMode;
65 UINT8 ubAttackBusyCount;
66 UINT8 ubEngagedInConvFromActionMercID;
67 UINT16 usTactialTurnLimitCounter;
68 BOOLEAN fInTopMessage;
69 UINT8 ubTopMessageType;
70 UINT16 usTactialTurnLimitMax;
71 UINT32 uiTactialTurnLimitClock;
72 BOOLEAN fTactialTurnLimitStartedBeep;
73 INT8 bBoxingState;
74 INT8 bConsNumTurnsNotSeen;
75 UINT8 ubArmyGuysKilled;
76
77 INT16 sPanicTriggerGridNo[NUM_PANIC_TRIGGERS];
78 INT8 bPanicTriggerIsAlarm[NUM_PANIC_TRIGGERS];
79 UINT8 ubPanicTolerance[NUM_PANIC_TRIGGERS];
80 BOOLEAN fAtLeastOneGuyOnMultiSelect;
81 BOOLEAN fKilledEnemyOnAttack;
82 SOLDIERTYPE* enemy_killed_on_attack;
83 INT8 bEnemyKilledOnAttackLevel;
84 UINT16 ubEnemyKilledOnAttackLocation;
85 BOOLEAN fItemsSeenOnAttack;
86 SOLDIERTYPE* items_seen_on_attack_soldier;
87 UINT16 usItemsSeenOnAttackGridNo;
88 BOOLEAN fLockItemLocators;
89 UINT8 ubLastQuoteSaid;
90 UINT8 ubLastQuoteProfileNUm;
91 BOOLEAN fCantGetThrough;
92 INT16 sCantGetThroughGridNo;
93 INT16 sCantGetThroughSoldierGridNo;
94 SOLDIERTYPE* cant_get_through;
95 BOOLEAN fDidGameJustStart;
96 UINT8 ubLastRequesterTargetID;
97 UINT8 ubNumCrowsPossible;
98 BOOLEAN fUnLockUIAfterHiddenInterrupt;
99 INT8 bNumFoughtInBattle[ MAXTEAMS ];
100 UINT32 uiDecayBloodLastUpdate;
101 UINT32 uiTimeSinceLastInTactical;
102 BOOLEAN fHasAGameBeenStarted;
103 INT8 bConsNumTurnsWeHaventSeenButEnemyDoes;
104 BOOLEAN fSomeoneHit;
105 UINT32 uiTimeSinceLastOpplistDecay;
106 SOLDIERTYPE* enemy_killed_on_attack_killer;
107 INT8 bMercArrivingQuoteBeingUsed;
108 BOOLEAN fCountingDownForGuideDescription;
109 INT8 bGuideDescriptionCountDown;
110 UINT8 ubGuideDescriptionToUse;
111 INT8 bGuideDescriptionSectorX;
112 INT8 bGuideDescriptionSectorY;
113 INT8 fEnemyFlags;
114 BOOLEAN fAutoBandagePending;
115 BOOLEAN fHasEnteredCombatModeSinceEntering;
116 BOOLEAN fDontAddNewCrows;
117 UINT16 sCreatureTenseQuoteDelay;
118 UINT32 uiCreatureTenseQuoteLastUpdate;
119 };
120
121
IsOnOurTeam(SOLDIERTYPE const & s)122 static inline bool IsOnOurTeam(SOLDIERTYPE const& s)
123 {
124 return s.bTeam == OUR_TEAM;
125 }
126
127 extern SOLDIERTYPE* g_selected_man;
128
129 extern const char* const gzActionStr[];
130
131 // Soldier List used for all soldier overhead interaction
132 extern SOLDIERTYPE Menptr[TOTAL_SOLDIERS];
133
GetMan(UINT const idx)134 static inline SOLDIERTYPE& GetMan(UINT const idx)
135 {
136 Assert(idx < lengthof(Menptr));
137 return Menptr[idx];
138 }
139
140 typedef UINT8 SoldierID;
141
Soldier2ID(const SOLDIERTYPE * const s)142 static inline SoldierID Soldier2ID(const SOLDIERTYPE* const s)
143 {
144 return s != NULL ? s->ubID : NOBODY;
145 }
146
ID2Soldier(const SoldierID id)147 static inline SOLDIERTYPE* ID2Soldier(const SoldierID id)
148 {
149 return id != NOBODY ? &GetMan(id) : 0;
150 }
151
152 // For temporary use
153 #define SOLDIER2ID(s) (Soldier2ID((s)))
154 #define ID2SOLDIER(i) (ID2Soldier((i)))
155
GetSelectedMan(void)156 static inline SOLDIERTYPE* GetSelectedMan(void)
157 {
158 SOLDIERTYPE* const sel = g_selected_man;
159 Assert(sel == NULL || sel->bActive);
160 return sel;
161 }
162
SetSelectedMan(SOLDIERTYPE * const s)163 static inline void SetSelectedMan(SOLDIERTYPE* const s)
164 {
165 Assert(s == NULL || s->bActive);
166 g_selected_man = s;
167 }
168
169 // MERC SLOTS - A LIST OF ALL ACTIVE MERCS
170 extern SOLDIERTYPE* MercSlots[TOTAL_SOLDIERS];
171 extern UINT32 guiNumMercSlots;
172
173 #define FOR_EACH_MERC(iter) \
174 for (SOLDIERTYPE** iter = MercSlots, \
175 ** const end__##iter = MercSlots + guiNumMercSlots; \
176 iter != end__##iter; \
177 ++iter) \
178 if (Assert(!*iter || (*iter)->bActive), !*iter) continue; else
179
180
181 extern TacticalStatusType gTacticalStatus;
182
IsTeamActive(const UINT team)183 static inline BOOLEAN IsTeamActive(const UINT team)
184 {
185 return gTacticalStatus.Team[team].bMenInSector > 0;
186 }
187
188
189 #define BASE_FOR_EACH_IN_TEAM(type, iter, team) \
190 for (type* iter = &Menptr[gTacticalStatus.Team[(team)].bFirstID], \
191 * const end__##iter = &Menptr[gTacticalStatus.Team[(team)].bLastID + 1]; \
192 iter != end__##iter; \
193 ++iter) \
194 if (!iter->bActive) continue; else
195 #define FOR_EACH_IN_TEAM( iter, team) BASE_FOR_EACH_IN_TEAM( SOLDIERTYPE, iter, (team))
196 #define CFOR_EACH_IN_TEAM(iter, team) BASE_FOR_EACH_IN_TEAM(const SOLDIERTYPE, iter, (team))
197
198 #define BASE_FOR_EACH_SOLDIER(type, iter) \
199 for (type* iter = Menptr; iter != Menptr + MAX_NUM_SOLDIERS; ++iter) \
200 if (!iter->bActive) continue; else
201 #define FOR_EACH_SOLDIER( iter) BASE_FOR_EACH_SOLDIER( SOLDIERTYPE, iter)
202 #define CFOR_EACH_SOLDIER(iter) BASE_FOR_EACH_SOLDIER(const SOLDIERTYPE, iter)
203
204 #define BASE_FOR_EACH_NON_PLAYER_SOLDIER(type, iter) \
205 for (type* iter = &Menptr[gTacticalStatus.Team[ENEMY_TEAM].bFirstID], \
206 * const end__##iter = &Menptr[gTacticalStatus.Team[CIV_TEAM ].bLastID + 1]; \
207 iter != end__##iter; \
208 ++iter) \
209 if (!iter->bActive) continue; else
210 #define FOR_EACH_NON_PLAYER_SOLDIER( iter) BASE_FOR_EACH_NON_PLAYER_SOLDIER( SOLDIERTYPE, iter)
211 #define CFOR_EACH_NON_PLAYER_SOLDIER(iter) BASE_FOR_EACH_NON_PLAYER_SOLDIER(const SOLDIERTYPE, iter)
212
213
214 void InitTacticalEngine(void);
215 void ShutdownTacticalEngine(void);
216
217
218 void InitOverhead();
219 void ShutdownOverhead(void);
220
221 INT16 NewOKDestination(const SOLDIERTYPE* pCurrSoldier, INT16 sGridNo, BOOLEAN fPeopleToo, INT8 bLevel);
222
223 //Simple check to see if a (one-tiled) soldier can occupy a given location on the ground or roof.
224 extern BOOLEAN IsLocationSittable( INT32 iMapIndex, BOOLEAN fOnRoof );
225 extern BOOLEAN IsLocationSittableExcludingPeople( INT32 iMapIndex, BOOLEAN fOnRoof );
226 extern BOOLEAN FlatRoofAboveGridNo( INT32 iMapIndex );
227
228
229 void ExecuteOverhead(void);
230
231 void EndTurn(UINT8 ubNextTeam);
232 void StartPlayerTeamTurn( BOOLEAN fDoBattleSnd, BOOLEAN fEnteringCombatMode );
233
234 enum SelSoldierFlags
235 {
236 SELSOLDIER_NONE = 0,
237 SELSOLDIER_ACKNOWLEDGE = 1U << 0,
238 SELSOLDIER_FORCE_RESELECT = 1U << 1,
239 SELSOLDIER_FROM_UI = 1U << 2
240 };
241 ENUM_BITSET(SelSoldierFlags)
242
243 void SelectSoldier(SOLDIERTYPE* s, SelSoldierFlags flags);
244
245
246 void InternalLocateGridNo(UINT16 sGridNo, BOOLEAN fForce);
247 void LocateGridNo( UINT16 sGridNo );
248 void LocateSoldier(SOLDIERTYPE* s, BOOLEAN fSetLocator);
249
250 void BeginTeamTurn( UINT8 ubTeam );
251 void SlideTo(SOLDIERTYPE* tgt, BOOLEAN fSetLocator);
252 void SlideToLocation(INT16 sDestGridNo);
253
254 void RebuildAllSoldierShadeTables(void);
255 void HandlePlayerTeamMemberDeath( SOLDIERTYPE *pSoldier );
256
257 SOLDIERTYPE* FindNextActiveAndAliveMerc(const SOLDIERTYPE* curr, BOOLEAN fGoodForLessOKLife, BOOLEAN fOnlyRegularMercs);
258 SOLDIERTYPE* FindPrevActiveAndAliveMerc(const SOLDIERTYPE* curr, BOOLEAN fGoodForLessOKLife, BOOLEAN fOnlyRegularMercs);
259
260 void HandleNPCTeamMemberDeath( SOLDIERTYPE *pSoldier );
261
262 BOOLEAN UIOKMoveDestination(const SOLDIERTYPE* pSoldier, UINT16 usMapPos);
263
264 INT16 FindAdjacentGridEx(SOLDIERTYPE* pSoldier, INT16 sGridNo, UINT8* pubDirection, INT16* psAdjustedGridNo, BOOLEAN fForceToPerson, BOOLEAN fDoor);
265 INT16 FindNextToAdjacentGridEx( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 *pubDirection, INT16 *psAdjustedGridNo, BOOLEAN fForceToPerson, BOOLEAN fDoor );
266
267
268 void SelectNextAvailSoldier(const SOLDIERTYPE* s);
269 BOOLEAN TeamMemberNear(INT8 bTeam, INT16 sGridNo, INT32 iRange);
270
271
272 // FUNCTIONS FOR MANIPULATING MERC SLOTS - A LIST OF ALL ACTIVE MERCS
273 void AddMercSlot(SOLDIERTYPE* pSoldier);
274 BOOLEAN RemoveMercSlot( SOLDIERTYPE *pSoldier );
275
276 INT32 AddAwaySlot(SOLDIERTYPE* pSoldier);
277 BOOLEAN RemoveAwaySlot(SOLDIERTYPE* pSoldier);
278 INT32 MoveSoldierFromMercToAwaySlot(SOLDIERTYPE* pSoldier);
279 void MoveSoldierFromAwayToMercSlot(SOLDIERTYPE* pSoldier);
280
281 void EnterCombatMode( UINT8 ubStartingTeam );
282 void ExitCombatMode(void);
283
284 void HandleTeamServices( UINT8 ubTeamNum );
285 void HandlePlayerServices(SOLDIERTYPE&);
286
287 void SetEnemyPresence(void);
288
289 void CycleThroughKnownEnemies(void);
290
291 BOOLEAN CheckForEndOfCombatMode( BOOLEAN fIncrementTurnsNotSeen );
292
293 SOLDIERTYPE* FreeUpAttacker(SOLDIERTYPE* attacker);
294
295 BOOLEAN PlayerTeamFull(void);
296
297 void SetActionToDoOnceMercsGetToLocation(UINT8 ubActionCode, INT8 bNumMercsWaiting);
298
299 void ResetAllMercSpeeds(void);
300
301 BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLEAN fInitialMove, UINT16 usAnimState );
302
303 SOLDIERTYPE* ReduceAttackBusyCount(SOLDIERTYPE* attacker, BOOLEAN fCalledByAttacker);
304
305 void CommonEnterCombatModeCode(void);
306
307 void CheckForPotentialAddToBattleIncrement( SOLDIERTYPE *pSoldier );
308
309 void CencelAllActionsForTimeCompression( void );
310
311 BOOLEAN CheckForEndOfBattle( BOOLEAN fAnEnemyRetreated );
312
313 void AddManToTeam( INT8 bTeam );
314
315 void RemoveManFromTeam( INT8 bTeam );
316
317 void RemoveSoldierFromTacticalSector(SOLDIERTYPE&);
318
319 void MakeCivHostile( SOLDIERTYPE *pSoldier, INT8 bNewSide );
320
321 #define REASON_NORMAL_ATTACK 1
322 #define REASON_EXPLOSION 2
323
324 BOOLEAN ProcessImplicationsOfPCAttack(SOLDIERTYPE* pSoldier, SOLDIERTYPE* pTarget, INT8 bReason);
325
326 INT16 FindAdjacentPunchTarget(const SOLDIERTYPE* pSoldier, const SOLDIERTYPE* pTargetSoldier, INT16* psAdjustedTargetGridNo);
327
328 SOLDIERTYPE * CivilianGroupMemberChangesSides( SOLDIERTYPE * pAttacked );
329 void CivilianGroupChangesSides( UINT8 ubCivilianGroup );
330
331 void CycleVisibleEnemies( SOLDIERTYPE *pSrcSoldier );
332 UINT8 CivilianGroupMembersChangeSidesWithinProximity( SOLDIERTYPE * pAttacked );
333
334 void PauseAITemporarily( void );
335 void PauseAIUntilManuallyUnpaused( void );
336 void UnPauseAI( void );
337
338 void DoPOWPathChecks( void );
339
340 BOOLEAN HostileCiviliansPresent( void );
341 BOOLEAN HostileBloodcatsPresent( void );
342 UINT8 NumPCsInSector( void );
343 UINT8 NumEnemyInSector();
344
345 void SetSoldierNonNeutral( SOLDIERTYPE * pSoldier );
346 void SetSoldierNeutral( SOLDIERTYPE * pSoldier );
347
348 void CaptureTimerCallback(void);
349 SOLDIERTYPE* FindNextActiveSquad(SOLDIERTYPE* pSoldier);
350
351 extern BOOLEAN gfSurrendered;
352 extern BOOLEAN gfKillingGuysForLosingBattle;
353 extern UINT8 gubWaitingForAllMercsToExitCode;
354
355 UINT8 NumCapableEnemyInSector();
356 SOLDIERTYPE* FreeUpAttackerGivenTarget(SOLDIERTYPE* target);
357 SOLDIERTYPE* ReduceAttackBusyGivenTarget(SOLDIERTYPE* target);
358
359 UINT NumberOfMercsOnPlayerTeam(void);
360
361 void InitializeTacticalStatusAtBattleStart(void);
362
363 void MakeCharacterDialogueEventSignalItemLocatorStart(SOLDIERTYPE&, GridNo location);
364
365 void HandleThePlayerBeNotifiedOfSomeoneElseInSector(void);
366
367 bool WildernessSectorWithAllProfiledNPCsNotSpokenWith(INT16 const x, INT16 const y, INT8 const z);
368
369 #endif
370