1 #include "Timer_Control.h"
2
3 #include "ContentManager.h"
4 #include "Debug.h"
5 #include "GameInstance.h"
6 #include "GamePolicy.h"
7 #include "Handle_Items.h"
8 #include "MapScreen.h"
9 #include "Overhead.h"
10 #include "Soldier_Control.h"
11 #include "WorldDef.h"
12
13 #include <SDL.h>
14 #include <stdexcept>
15
16
17 INT32 giClockTimer = -1;
18 INT32 giTimerDiag = 0;
19
20 UINT32 guiBaseJA2Clock = 0;
21
22 static BOOLEAN gfPauseClock = FALSE;
23
24 const INT32 giTimerIntervals[NUMTIMERS] =
25 {
26 5, // Tactical Overhead
27 20, // NEXTSCROLL
28 200, // Start Scroll
29 200, // Animate tiles
30 1000, // FPS Counter
31 80, // PATH FIND COUNTER
32 150, // CURSOR TIMER
33 300, // RIGHT CLICK FOR MENU
34 300, // LEFT
35 300, // MIDDLE
36 200, // TARGET REFINE TIMER
37 150, // CURSOR/AP FLASH
38 20, // PHYSICS UPDATE
39 100, // FADE ENEMYS
40 20, // STRATEGIC OVERHEAD
41 40, // CYCLE TIME RENDER ITEM COLOR
42 500, // NON GUN TARGET REFINE TIMER
43 250, // IMPROVED CURSOR FLASH
44 500, // 2nd CURSOR FLASH
45 400, // RADARMAP BLINK AND OVERHEAD MAP BLINK SHOUDL BE THE SAME
46 10 // Music Overhead
47 };
48
49 // TIMER COUNTERS
50 INT32 giTimerCounters[NUMTIMERS];
51
52 INT32 giTimerCustomizable = 0;
53 INT32 giTimerTeamTurnUpdate = 0;
54
55 CUSTOMIZABLE_TIMER_CALLBACK gpCustomizableTimerCallback = 0;
56
57 // Clock Callback event ID
58 static SDL_TimerID g_timer;
59
60
61 extern UINT32 guiCompressionStringBaseTime;
62 extern INT32 giFlashHighlightedItemBaseTime;
63 extern INT32 giCompatibleItemBaseTime;
64 extern INT32 giAnimateRouteBaseTime;
65 extern INT32 giPotHeliPathBaseTime;
66 extern UINT32 guiSectorLocatorBaseTime;
67 extern INT32 giCommonGlowBaseTime;
68 extern INT32 giFlashAssignBaseTime;
69 extern INT32 giFlashContractBaseTime;
70 extern UINT32 guiFlashCursorBaseTime;
71 extern INT32 giPotCharPathBaseTime;
72
73
TimeProc(UINT32 const interval,void *)74 static UINT32 TimeProc(UINT32 const interval, void*)
75 {
76 if (!gfPauseClock)
77 {
78 guiBaseJA2Clock += BASETIMESLICE;
79
80 for (UINT32 i = 0; i != NUMTIMERS; i++)
81 {
82 UPDATECOUNTER(i);
83 }
84
85 // Update some specialized countdown timers...
86 UPDATETIMECOUNTER(giTimerTeamTurnUpdate);
87
88 if (gpCustomizableTimerCallback)
89 {
90 UPDATETIMECOUNTER(giTimerCustomizable);
91 }
92
93 #ifndef BOUNDS_CHECKER
94 if (fInMapMode)
95 {
96 // IN Mapscreen, loop through player's team
97 FOR_EACH_IN_TEAM(s, OUR_TEAM)
98 {
99 UPDATETIMECOUNTER(s->PortraitFlashCounter);
100 UPDATETIMECOUNTER(s->PanelAnimateCounter);
101 }
102 }
103 else
104 {
105 // Set update flags for soldiers
106 FOR_EACH_MERC(i)
107 {
108 SOLDIERTYPE* const s = *i;
109 UPDATETIMECOUNTER(s->UpdateCounter);
110 UPDATETIMECOUNTER(s->DamageCounter);
111 UPDATETIMECOUNTER(s->BlinkSelCounter);
112 UPDATETIMECOUNTER(s->PortraitFlashCounter);
113 UPDATETIMECOUNTER(s->AICounter);
114 UPDATETIMECOUNTER(s->FadeCounter);
115 UPDATETIMECOUNTER(s->NextTileCounter);
116 UPDATETIMECOUNTER(s->PanelAnimateCounter);
117 }
118 }
119 #endif
120 }
121
122 return interval;
123 }
124
125
InitializeJA2Clock(void)126 void InitializeJA2Clock(void)
127 {
128 SDL_InitSubSystem(SDL_INIT_TIMER);
129
130 // Init timer delays
131 for (INT32 i = 0; i != NUMTIMERS; ++i)
132 {
133 giTimerCounters[i] = giTimerIntervals[i];
134 }
135
136 INT32 msPerTimeSlice = gamepolicy(ms_per_time_slice);
137 if (msPerTimeSlice <= 0)
138 {
139 throw std::runtime_error("ms_per_time_slice must be a positive integer");
140 }
141 g_timer = SDL_AddTimer(msPerTimeSlice, TimeProc, 0);
142 if (!g_timer) throw std::runtime_error("Could not create timer callback");
143 }
144
145
ShutdownJA2Clock(void)146 void ShutdownJA2Clock(void)
147 {
148 SDL_RemoveTimer(g_timer);
149 }
150
151
PauseTime(BOOLEAN const fPaused)152 void PauseTime(BOOLEAN const fPaused)
153 {
154 gfPauseClock = fPaused;
155 }
156
157
SetCustomizableTimerCallbackAndDelay(INT32 const delay,CUSTOMIZABLE_TIMER_CALLBACK const callback,BOOLEAN const replace)158 void SetCustomizableTimerCallbackAndDelay(INT32 const delay, CUSTOMIZABLE_TIMER_CALLBACK const callback, BOOLEAN const replace)
159 {
160 if (!replace && gpCustomizableTimerCallback)
161 { // Replace callback but call the current callback first
162 gpCustomizableTimerCallback();
163 }
164
165 RESETTIMECOUNTER(giTimerCustomizable, delay);
166 gpCustomizableTimerCallback = callback;
167 }
168
169
CheckCustomizableTimer(void)170 void CheckCustomizableTimer(void)
171 {
172 if (!gpCustomizableTimerCallback) return;
173 if (!TIMECOUNTERDONE(giTimerCustomizable, 0)) return;
174
175 /* Set the callback to a temp variable so we can reset the global variable
176 * before calling the callback, so that if the callback sets up another
177 * instance of the timer, we don't reset it afterwards. */
178 CUSTOMIZABLE_TIMER_CALLBACK const callback = gpCustomizableTimerCallback;
179 gpCustomizableTimerCallback = 0;
180 callback();
181 }
182
183
ResetJA2ClockGlobalTimers(void)184 void ResetJA2ClockGlobalTimers(void)
185 {
186 UINT32 const now = GetJA2Clock();
187
188 guiCompressionStringBaseTime = now;
189 giFlashHighlightedItemBaseTime = now;
190 giCompatibleItemBaseTime = now;
191 giAnimateRouteBaseTime = now;
192 giPotHeliPathBaseTime = now;
193 guiSectorLocatorBaseTime = now;
194
195 giCommonGlowBaseTime = now;
196 giFlashAssignBaseTime = now;
197 giFlashContractBaseTime = now;
198 guiFlashCursorBaseTime = now;
199 giPotCharPathBaseTime = now;
200 }
201