1 #include "Font_Control.h"
2 #include "Lighting.h"
3 #include "Environment.h"
4 #include "RenderWorld.h"
5 #include "Sound_Control.h"
6 #include "Overhead.h"
7 #include "Game_Clock.h"
8 #include "Quests.h"
9 #include "Ambient_Control.h"
10 #include "AIMMembers.h"
11 #include "Strategic_Event_Handler.h"
12 #include "BobbyR.h"
13 #include "Mercs.h"
14 #include "Merc_Hiring.h"
15 #include "Insurance_Contract.h"
16 #include "Strategic_Merc_Handler.h"
17 #include "Game_Events.h"
18 #include "Message.h"
19 #include "OppList.h"
20 #include "Random.h"
21 #include "StrategicMap.h"
22 #include "SoundMan.h"
23 
24 
25 //effects whether or not time of day effects the lighting.  Underground
26 //maps have an ambient light level that is saved in the map, and doesn't change.
27 BOOLEAN gfBasement = FALSE;
28 BOOLEAN gfCaves = FALSE;
29 
30 /*
31 #define DAWNLIGHT_START		( 5 * 60 )
32 #define DAWN_START		( 6 * 60 )
33 #define DAY_START		( 8 * 60 )
34 #define TWILLIGHT_START		( 19 * 60 )
35 #define DUSK_START		( 20 * 60 )
36 #define NIGHT_START		( 22 * 60 )
37 */
38 #define DAWN_START		( 6 * 60 + 47 )		//6:47AM
39 #define DAY_START		( 7 * 60 + 5 )		//7:05AM
40 #define DUSK_START		( 20 * 60 + 57 )	//8:57PM
41 #define NIGHT_START		( 21 * 60 + 15 )	//9:15PM
42 
43 #define DAWN_TO_DAY		(DAY_START-DAWN_START)
44 #define DAY_TO_DUSK		(DUSK_START-DAY_START)
45 #define DUSK_TO_NIGHT		(NIGHT_START-DUSK_START)
46 #define NIGHT_TO_DAWN		(24*60-NIGHT_START+DAWN_START)
47 
48 UINT32 guiEnvWeather = 0;
49 UINT32 guiRainLoop   = NO_SAMPLE;
50 
51 
52 // frame cues for lightning
53 UINT8 ubLightningTable[3][10][2] = {
54 	{
55 		{0, 15},
56 		{1, 0},
57 		{2, 0},
58 		{3, 6},
59 		{4, 0},
60 		{5, 0},
61 		{6, 0},
62 		{7, 0},
63 		{8, 0},
64 		{9, 0}
65 	},
66 
67 	{
68 		{0, 15},
69 		{1, 0},
70 		{2, 0},
71 		{3, 6},
72 		{4, 0},
73 		{5, 15},
74 		{6, 0},
75 		{7, 6},
76 		{8, 0},
77 		{9, 0}
78 	},
79 
80 	{
81 		{0, 15},
82 		{1, 0},
83 		{2, 15},
84 		{3, 0},
85 		{4, 0},
86 		{5, 0},
87 		{6, 0},
88 		{7, 0},
89 		{8, 0},
90 		{9, 0}
91 	}
92 };
93 
94 
95 enum Temperatures
96 {
97 	COOL,
98 	WARM,
99 	HOT
100 };
101 
102 enum TemperatureEvents
103 {
104 	TEMPERATURE_DESERT_COOL,
105 	TEMPERATURE_DESERT_WARM,
106 	TEMPERATURE_DESERT_HOT,
107 	TEMPERATURE_GLOBAL_COOL,
108 	TEMPERATURE_GLOBAL_WARM,
109 	TEMPERATURE_GLOBAL_HOT,
110 };
111 
112 #define DESERT_WARM_START	( 8 * 60 )
113 #define DESERT_HOT_START	( 9 * 60 )
114 #define DESERT_HOT_END		(17 * 60 )
115 #define DESERT_WARM_END		(19 * 60 )
116 
117 #define GLOBAL_WARM_START	( 9 * 60 )
118 #define GLOBAL_HOT_START	(12 * 60 )
119 #define GLOBAL_HOT_END		(14 * 60 )
120 #define GLOBAL_WARM_END		(17 * 60 )
121 
122 #define HOT_DAY_LIGHTLEVEL 2
123 
124 BOOLEAN fTimeOfDayControls=TRUE;
125 UINT32  guiEnvTime=0;
126 UINT32  guiEnvDay=0;
127 UINT8   gubEnvLightValue = 0;
128 BOOLEAN gfDoLighting = FALSE;
129 
130 UINT8   gubDesertTemperature = 0;
131 UINT8   gubGlobalTemperature = 0;
132 
133 // polled by the game to handle time/atmosphere changes from gamescreen
EnvironmentController(BOOLEAN fCheckForLights)134 void EnvironmentController( BOOLEAN fCheckForLights )
135 {
136 	UINT32 uiOldWorldHour;
137 	UINT8  ubLightAdjustFromWeather = 0;
138 
139 
140 	// do none of this stuff in the basement or caves
141 	if( gfBasement || gfCaves )
142 	{
143 		guiEnvWeather	&= (~WEATHER_FORECAST_THUNDERSHOWERS );
144 		guiEnvWeather	&= (~WEATHER_FORECAST_SHOWERS );
145 
146 		if ( guiRainLoop != NO_SAMPLE )
147 		{
148 			SoundStop( guiRainLoop );
149 			guiRainLoop = NO_SAMPLE;
150 		}
151 		return;
152 	}
153 
154 	if(fTimeOfDayControls )
155 	{
156 		uiOldWorldHour = GetWorldHour();
157 
158 		// If hour is different
159 		if ( uiOldWorldHour != guiEnvTime )
160 		{
161 			// Hour change....
162 
163 			guiEnvTime=uiOldWorldHour;
164 		}
165 
166 		//ExecuteStrategicEventsUntilTimeStamp( (UINT16)GetWorldTotalMin( ) );
167 
168 		// Polled weather stuff...
169 		// ONly do indooors
170 		if( !gfBasement && !gfCaves )
171 		{
172 #if 0
173 			if ( guiEnvWeather & ( WEATHER_FORECAST_THUNDERSHOWERS | WEATHER_FORECAST_SHOWERS ) )
174 			{
175 				if ( guiRainLoop == NO_SAMPLE )
176 				{
177 					guiRainLoop	= PlayJA2Ambient( RAIN_1, MIDVOLUME, 0 );
178 				}
179 
180 				// Do lightning if we want...
181 				if ( guiEnvWeather & ( WEATHER_FORECAST_THUNDERSHOWERS ) )
182 				{
183 					EnvDoLightning( );
184 				}
185 
186 			}
187 			else
188 			{
189 				if ( guiRainLoop != NO_SAMPLE )
190 				{
191 					SoundStop( guiRainLoop );
192 					guiRainLoop = NO_SAMPLE;
193 				}
194 			}
195 #endif
196 		}
197 
198 		if ( gfDoLighting && fCheckForLights )
199 		{
200 			// Adjust light level based on weather...
201 			ubLightAdjustFromWeather = GetTimeOfDayAmbientLightLevel();
202 
203 			// ONly do indooors
204 			if( !gfBasement && !gfCaves )
205 			{
206 				// Rain storms....
207 #if 0
208 				if ( guiEnvWeather & ( WEATHER_FORECAST_THUNDERSHOWERS | WEATHER_FORECAST_SHOWERS ) )
209 				{
210 					// Thunder showers.. make darker
211 					if ( guiEnvWeather & ( WEATHER_FORECAST_THUNDERSHOWERS ) )
212 					{
213 						ubLightAdjustFromWeather = (UINT8)(__min( gubEnvLightValue+2, NORMAL_LIGHTLEVEL_NIGHT ));
214 					}
215 					else
216 					{
217 						ubLightAdjustFromWeather = (UINT8)(__min( gubEnvLightValue+1, NORMAL_LIGHTLEVEL_NIGHT ));
218 					}
219 				}
220 #endif
221 			}
222 
223 
224 			LightSetBaseLevel( ubLightAdjustFromWeather );
225 
226 			//Update Merc Lights since the above function modifies it.
227 			HandlePlayerTogglingLightEffects( FALSE );
228 
229 			// Make teams look for all
230 			// AllTeamsLookForAll( FALSE );
231 
232 			// Set global light value
233 			SetRenderFlags(RENDER_FLAG_FULL);
234 			gfDoLighting = FALSE;
235 		}
236 
237 	}
238 
239 }
240 
BuildDayLightLevels()241 void BuildDayLightLevels()
242 {
243 	UINT32 uiLoop, uiHour;
244 
245 	/*
246 	// Dawn; light 12
247 	AddEveryDayStrategicEvent( EVENT_CHANGELIGHTVAL, DAWNLIGHT_START, NORMAL_LIGHTLEVEL_NIGHT - 1 );
248 
249 	// loop from light 12 down to light 4
250 	for (uiLoop = 1; uiLoop < 8; uiLoop++)
251 	{
252 		AddEveryDayStrategicEvent( EVENT_CHANGELIGHTVAL, DAWN_START + 15 * uiLoop,	NORMAL_LIGHTLEVEL_NIGHT - 1 - uiLoop );
253 	}
254 	*/
255 
256 	//Transition from night to day
257 	for( uiLoop = 0; uiLoop < 9; uiLoop++ )
258 	{
259 		AddEveryDayStrategicEvent( EVENT_CHANGELIGHTVAL, DAWN_START + 2 * uiLoop,	NORMAL_LIGHTLEVEL_NIGHT - 1 - uiLoop );
260 	}
261 
262 	// Add events for hot times
263 	AddEveryDayStrategicEvent( EVENT_TEMPERATURE_UPDATE, DESERT_WARM_START, TEMPERATURE_DESERT_WARM );
264 	AddEveryDayStrategicEvent( EVENT_TEMPERATURE_UPDATE, DESERT_HOT_START, TEMPERATURE_DESERT_HOT );
265 	AddEveryDayStrategicEvent( EVENT_TEMPERATURE_UPDATE, DESERT_HOT_END, TEMPERATURE_DESERT_WARM );
266 	AddEveryDayStrategicEvent( EVENT_TEMPERATURE_UPDATE, DESERT_WARM_END, TEMPERATURE_DESERT_COOL );
267 
268 	AddEveryDayStrategicEvent( EVENT_TEMPERATURE_UPDATE, GLOBAL_WARM_START, TEMPERATURE_GLOBAL_WARM );
269 	AddEveryDayStrategicEvent( EVENT_TEMPERATURE_UPDATE, GLOBAL_HOT_START, TEMPERATURE_GLOBAL_HOT );
270 	AddEveryDayStrategicEvent( EVENT_TEMPERATURE_UPDATE, GLOBAL_HOT_END, TEMPERATURE_GLOBAL_WARM );
271 	AddEveryDayStrategicEvent( EVENT_TEMPERATURE_UPDATE, GLOBAL_WARM_END, TEMPERATURE_GLOBAL_COOL );
272 
273 /*
274 	// Twilight; light 5
275 	AddEveryDayStrategicEvent( EVENT_CHANGELIGHTVAL, TWILLIGHT_START, NORMAL_LIGHTLEVEL_DAY + 1 );
276 
277 	// Dusk; loop from light 5 up to 12
278 	for (uiLoop = 1; uiLoop < 8; uiLoop++)
279 	{
280 		AddEveryDayStrategicEvent( EVENT_CHANGELIGHTVAL, DUSK_START + 15 * uiLoop, NORMAL_LIGHTLEVEL_DAY + 1 + uiLoop );
281 	}
282 */
283 
284 	//Transition from day to night
285 	for( uiLoop = 0; uiLoop < 9; uiLoop++ )
286 	{
287 		AddEveryDayStrategicEvent( EVENT_CHANGELIGHTVAL, DUSK_START + 2 * uiLoop,	NORMAL_LIGHTLEVEL_DAY + 1 + uiLoop );
288 	}
289 
290 	//Set up the scheduling for turning lights on and off based on the various types.
291 	uiHour = NIGHT_TIME_LIGHT_START_HOUR == 24 ? 0 : NIGHT_TIME_LIGHT_START_HOUR;
292 	AddEveryDayStrategicEvent( EVENT_TURN_ON_NIGHT_LIGHTS, uiHour * 60, 0 );
293 	uiHour = NIGHT_TIME_LIGHT_END_HOUR == 24 ? 0 : NIGHT_TIME_LIGHT_END_HOUR;
294 	AddEveryDayStrategicEvent( EVENT_TURN_OFF_NIGHT_LIGHTS, uiHour * 60, 0 );
295 	uiHour = PRIME_TIME_LIGHT_START_HOUR == 24 ? 0 : PRIME_TIME_LIGHT_START_HOUR;
296 	AddEveryDayStrategicEvent( EVENT_TURN_ON_PRIME_LIGHTS, uiHour * 60, 0 );
297 	uiHour = PRIME_TIME_LIGHT_END_HOUR == 24 ? 0 : PRIME_TIME_LIGHT_END_HOUR;
298 	AddEveryDayStrategicEvent( EVENT_TURN_OFF_PRIME_LIGHTS, uiHour * 60, 0 );
299 }
300 
BuildDayAmbientSounds()301 void BuildDayAmbientSounds( )
302 {
303 	INT32 cnt;
304 
305 	// Add events!
306 	for ( cnt = 0; cnt < gsNumAmbData; cnt++ )
307 	{
308 		switch( gAmbData[ cnt ].ubTimeCatagory )
309 		{
310 			case AMB_TOD_DAWN:
311 				AddSameDayRangedStrategicEvent( EVENT_AMBIENT, DAWN_START, DAWN_TO_DAY, cnt );
312 				break;
313 			case AMB_TOD_DAY:
314 				AddSameDayRangedStrategicEvent( EVENT_AMBIENT, DAY_START, DAY_TO_DUSK, cnt );
315 				break;
316 			case AMB_TOD_DUSK:
317 				AddSameDayRangedStrategicEvent( EVENT_AMBIENT, DUSK_START, DUSK_TO_NIGHT, cnt );
318 				break;
319 			case AMB_TOD_NIGHT:
320 				AddSameDayRangedStrategicEvent( EVENT_AMBIENT, NIGHT_START, NIGHT_TO_DAWN, cnt );
321 				break;
322 		}
323 
324 	}
325 
326 	guiRainLoop = NO_SAMPLE;
327 
328 }
329 
ForecastDayEvents()330 void ForecastDayEvents( )
331 {
332 	UINT32 uiOldDay;
333 	//UINT32 uiStartTime, uiEndTime;
334 	//UINT8  ubStormIntensity;
335 
336 	// Get current day and see if different
337 	if ( ( uiOldDay = GetWorldDay() ) != guiEnvDay )
338 	{
339 		// It's a new day, forecast weather
340 		guiEnvDay = uiOldDay;
341 
342 		// Set light level changes
343 		//BuildDayLightLevels();
344 
345 		// Build ambient sound queues
346 		BuildDayAmbientSounds( );
347 
348 		// Build weather....
349 
350 		// ATE: Don't forecast if start of game...
351 		//if ( guiEnvDay > 1 )
352 		//{
353 			// Should it rain...?
354 			//if ( Random( 100 ) < 20 )
355 			//{
356 				// Add rain!
357 				// Between 6:00 and 10:00
358 				//uiStartTime = (UINT32)( 360 + Random( 1080 ) );
359 				// Between 5 - 15 miniutes
360 				//uiEndTime		= uiStartTime + ( 5 + Random( 10 ) );
361 
362 				//ubStormIntensity = 0;
363 
364 				// Randomze for a storm!
365 				//if ( Random( 10 ) < 5 )
366 				//{
367 					//ubStormIntensity = 1;
368 				//}
369 
370 				// ATE: Disable RAIN!
371 				//AddSameDayRangedStrategicEvent( EVENT_RAINSTORM, uiStartTime, uiEndTime - uiStartTime, ubStormIntensity );
372 
373 				//AddSameDayStrategicEvent( EVENT_BEGINRAINSTORM, uiStartTime, ubStormIntensity );
374 				//AddSameDayStrategicEvent( EVENT_ENDRAINSTORM, uiEndTime, 0 );
375 			//}
376 		//}
377 	}
378 
379 }
380 
GetTimeOfDayAmbientLightLevel()381 UINT8 GetTimeOfDayAmbientLightLevel()
382 {
383 	if ( SectorTemperature( GetWorldMinutesInDay(), gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) == HOT )
384 	{
385 		return( HOT_DAY_LIGHTLEVEL );
386 	}
387 	else
388 	{
389 		return( gubEnvLightValue );
390 	}
391 }
392 
393 
EnvBeginRainStorm(UINT8 ubIntensity)394 void EnvBeginRainStorm( UINT8 ubIntensity )
395 {
396 	if( !gfBasement && !gfCaves )
397 	{
398 		gfDoLighting = TRUE;
399 		SLOGD("Starting Rain...."  );
400 
401 		if ( ubIntensity == 1 )
402 		{
403 			// Turn on rain storms
404 			guiEnvWeather	|= WEATHER_FORECAST_THUNDERSHOWERS;
405 		}
406 		else
407 		{
408 			guiEnvWeather	|= WEATHER_FORECAST_SHOWERS;
409 		}
410 	}
411 
412 }
413 
EnvEndRainStorm()414 void EnvEndRainStorm( )
415 {
416 	gfDoLighting = TRUE;
417 	SLOGD("Ending Rain...."  );
418 
419 	guiEnvWeather	&= (~WEATHER_FORECAST_THUNDERSHOWERS );
420 	guiEnvWeather	&= (~WEATHER_FORECAST_SHOWERS );
421 }
422 
423 
TurnOnNightLights()424 void TurnOnNightLights()
425 {
426 	FOR_EACH_LIGHT_SPRITE(l)
427 	{
428 		if (l->uiFlags & LIGHT_NIGHTTIME &&
429 			!(l->uiFlags & (LIGHT_SPR_ON | MERC_LIGHT)))
430 		{
431 			LightSpritePower(l, TRUE);
432 		}
433 	}
434 }
435 
436 
TurnOffNightLights()437 void TurnOffNightLights()
438 {
439 	FOR_EACH_LIGHT_SPRITE(l)
440 	{
441 		if (l->uiFlags & LIGHT_NIGHTTIME &&
442 			l->uiFlags & LIGHT_SPR_ON &&
443 			!(l->uiFlags & MERC_LIGHT))
444 		{
445 			LightSpritePower(l, FALSE);
446 		}
447 	}
448 }
449 
450 
TurnOnPrimeLights()451 void TurnOnPrimeLights()
452 {
453 	FOR_EACH_LIGHT_SPRITE(l)
454 	{
455 		if (l->uiFlags & LIGHT_PRIMETIME &&
456 				!(l->uiFlags & (LIGHT_SPR_ON | MERC_LIGHT)))
457 		{
458 			LightSpritePower(l, TRUE);
459 		}
460 	}
461 }
462 
463 
TurnOffPrimeLights()464 void TurnOffPrimeLights()
465 {
466 	FOR_EACH_LIGHT_SPRITE(l)
467 	{
468 		if (l->uiFlags & LIGHT_PRIMETIME &&
469 			l->uiFlags & LIGHT_SPR_ON &&
470 			!(l->uiFlags & MERC_LIGHT))
471 		{
472 			LightSpritePower(l, FALSE);
473 		}
474 	}
475 }
476 
UpdateTemperature(UINT8 ubTemperatureCode)477 void UpdateTemperature( UINT8 ubTemperatureCode )
478 {
479 	switch( ubTemperatureCode )
480 	{
481 		case TEMPERATURE_DESERT_COOL:
482 			gubDesertTemperature = 0;
483 			break;
484 		case TEMPERATURE_DESERT_WARM:
485 			gubDesertTemperature = 1;
486 			break;
487 		case TEMPERATURE_DESERT_HOT:
488 			gubDesertTemperature = 2;
489 			break;
490 		case TEMPERATURE_GLOBAL_COOL:
491 			gubGlobalTemperature = 0;
492 			break;
493 		case TEMPERATURE_GLOBAL_WARM:
494 			gubGlobalTemperature = 1;
495 			break;
496 		case TEMPERATURE_GLOBAL_HOT:
497 			gubGlobalTemperature = 2;
498 			break;
499 	}
500 	gfDoLighting = TRUE;
501 }
502 
SectorTemperature(UINT32 uiTime,INT16 sSectorX,INT16 sSectorY,INT8 bSectorZ)503 INT8 SectorTemperature( UINT32 uiTime, INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ )
504 {
505 	if (bSectorZ > 0)
506 	{
507 		// cool underground
508 		return( 0 );
509 	}
510 	else if ( IsSectorDesert( sSectorX, sSectorY ) ) // is desert
511 	{
512 		return( gubDesertTemperature );
513 	}
514 	else
515 	{
516 		return( gubGlobalTemperature );
517 	}
518 }
519