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