1 /*
2 LIGHTSOURCE.C
3 
4 	Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
5 	and the "Aleph One" developers.
6 
7 	This program is free software; you can redistribute it and/or modify
8 	it under the terms of the GNU General Public License as published by
9 	the Free Software Foundation; either version 3 of the License, or
10 	(at your option) any later version.
11 
12 	This program is distributed in the hope that it will be useful,
13 	but WITHOUT ANY WARRANTY; without even the implied warranty of
14 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 	GNU General Public License for more details.
16 
17 	This license is contained in the file "COPYING",
18 	which is included with this source code; it is available online at
19 	http://www.gnu.org/licenses/gpl.html
20 
21 Wednesday, February 1, 1995 4:21:43 AM  (Jason')
22 
23 Monday, March 6, 1995 9:41:50 PM  (Jason')
24 	nearly finished; looking toward cataclysm.  we need a good interface for editing intensities:
25 	a _normal_light only has two intensities, but each is found three places.
26 Thursday, April 27, 1995 11:00:36 AM  (Jason')
27 	functions with zero periods are skipped.
28 Tuesday, June 13, 1995 6:13:29 PM  (Jason)
29 	support for phases greater than a light�s initial period
30 Monday, July 10, 1995 5:20:26 PM  (Jason)
31 	stateless (six phase) lights.
32 
33 June 2, 2000 (Loren Petrich):
34 	Added fallback for absent lights
35 
36 July 1, 2000 (Loren Petrich):
37 	Modified light accessors to be more C++-like
38 
39 Aug 29, 2000 (Loren Petrich):
40 	Added packing routines for the light data; also moved old light stuff (M1) here
41 
42 Jul 3, 2002 (Loren Petrich):
43 	Added support for Pfhortran Procedure: light_activated
44 */
45 
46 #include "cseries.h"
47 
48 #include "map.h"
49 #include "lightsource.h"
50 #include "Packing.h"
51 
52 //MH: Lua scripting
53 #include "lua_script.h"
54 
55 /* ---------- globals */
56 
57 // Turned the list of lights into a variable array;
58 // took over their maximum number as how many of them
59 
60 vector<light_data> LightList;
61 
62 // struct light_data *lights = NULL;
63 
64 /* ---------- private prototypes */
65 
66 static void rephase_light(short light_index);
67 
68 // LP: "static" removed
69 static struct lighting_function_specification *get_lighting_function_specification(
70 	struct static_light_data *data, short state);
71 
72 static _fixed lighting_function_dispatch(short function_index, _fixed initial_intensity,
73 	_fixed final_intensity, short phase, short period);
74 
75 /* ---------- structures */
76 
77 struct light_definition
78 {
79 	// it remains unclear where these sounds should come from
80 	short on_sound, off_sound;
81 
82 	struct static_light_data defaults;
83 };
84 
85 /* ---------- globals */
86 
87 struct light_definition light_definitions[NUMBER_OF_LIGHT_TYPES]=
88 {
89 	// _normal_light
90 	{
91 		NONE, NONE, // on, off sound
92 		{
93 			_normal_light, // type
94 			FLAG(_light_is_initially_active)|FLAG(_light_has_slaved_intensities), 0, // flags, phase
95 
96 			{_constant_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE, 0}, // primary_active
97 			{_constant_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE, 0}, // secondary_active
98 			{_smooth_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE, 0}, // becoming_active
99 
100 			{_constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0}, // primary_inactive
101 			{_constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0}, // secondary_inactive
102 			{_smooth_lighting_function, TICKS_PER_SECOND, 0, 0, 0}, // becoming_inactive
103 		}
104 	},
105 
106 	// _strobe_light
107 	{
108 		NONE, NONE, // on, off sound
109 		{
110 			_normal_light, // type
111 			FLAG(_light_is_initially_active)|FLAG(_light_has_slaved_intensities), 0, // flags, phase
112 
113 			{_constant_lighting_function, TICKS_PER_SECOND/2, 0, FIXED_ONE, 0}, // primary_active
114 			{_constant_lighting_function, TICKS_PER_SECOND/2, 0, FIXED_ONE_HALF, 0}, // secondary_active
115 			{_smooth_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE_HALF, 0}, // becoming_active
116 
117 			{_constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0}, // primary_inactive
118 			{_constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0}, // secondary_inactive
119 			{_smooth_lighting_function, TICKS_PER_SECOND, 0, 0, 0}, // becoming_inactive
120 		}
121 	},
122 
123 	// _lava_light
124 	{
125 		NONE, NONE, // on, off sound
126 		{
127 			_normal_light, // type
128 			FLAG(_light_is_initially_active)|FLAG(_light_has_slaved_intensities), 0, // flags, phase
129 
130 			{_smooth_lighting_function, 10*TICKS_PER_SECOND, 0, FIXED_ONE, 0}, // primary_active
131 			{_smooth_lighting_function, 10*TICKS_PER_SECOND, 0, 0, 0}, // secondary_active
132 			{_smooth_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE_HALF, 0}, // becoming_active
133 
134 			{_constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0}, // primary_inactive
135 			{_constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0}, // secondary_inactive
136 			{_smooth_lighting_function, TICKS_PER_SECOND, 0, 0, 0}, // becoming_inactive
137 		}
138 	},
139 };
140 
141 static light_definition *get_light_definition(
142 	const short type);
143 
144 /* ---------- code */
145 
146 
get_light_data(const size_t light_index)147 light_data *get_light_data(
148 	const size_t light_index)
149 {
150 	struct light_data *light = GetMemberWithBounds(lights,light_index,MAXIMUM_LIGHTS_PER_MAP);
151 
152 	if (!light) return NULL;
153 	if (!SLOT_IS_USED(light)) return NULL;
154 
155 	return light;
156 }
157 
158 // LP change: moved down here because it uses light definitions
get_light_definition(const short type)159 light_definition *get_light_definition(
160 	const short type)
161 {
162 	return GetMemberWithBounds(light_definitions,type,NUMBER_OF_LIGHT_TYPES);
163 }
164 
new_light(struct static_light_data * data)165 short new_light(
166 	struct static_light_data *data)
167 {
168 	int light_index;
169 	struct light_data *light;
170 
171 	// LP change: idiot-proofing
172 	if (!data) return NONE;
173 
174 	for (light_index= 0, light= lights; light_index<short(MAXIMUM_LIGHTS_PER_MAP); ++light_index, ++light)
175 	{
176 		if (SLOT_IS_FREE(light))
177 		{
178 			light->static_data= *data;
179 //			light->flags= 0;
180 			MARK_SLOT_AS_USED(light);
181 
182 			light->intensity= 0;
183 			change_light_state(light_index, LIGHT_IS_INITIALLY_ACTIVE(data) ? _light_secondary_active : _light_secondary_inactive);
184 			light->intensity= light->final_intensity;
185 			change_light_state(light_index, LIGHT_IS_INITIALLY_ACTIVE(data) ? _light_primary_active : _light_primary_inactive);
186 					light->phase= data->phase;
187 			rephase_light(light_index);
188 
189 			light->intensity= lighting_function_dispatch(get_lighting_function_specification(&light->static_data, light->state)->function,
190 				light->initial_intensity, light->final_intensity, light->phase, light->period);
191 
192 			break;
193 		}
194 	}
195 	if (light_index == short(MAXIMUM_LIGHTS_PER_MAP)) light_index = NONE;
196 
197 	return light_index;
198 }
199 
get_defaults_for_light_type(short type)200 struct static_light_data *get_defaults_for_light_type(
201 	short type)
202 {
203 	struct light_definition *definition= get_light_definition(type);
204 	// LP addition: idiot-proofing
205 	if (!definition) return NULL;
206 
207 	return &definition->defaults;
208 }
209 
update_lights(void)210 void update_lights(
211 	void)
212 {
213 	int light_index;
214 	struct light_data *light;
215 
216 	for (light_index= 0, light= lights; light_index<short(MAXIMUM_LIGHTS_PER_MAP); ++light_index, ++light)
217 	{
218 		if (SLOT_IS_USED(light))
219 		{
220 			/* update light phase; if we�ve overflowed our period change to the next state */
221 			light->phase+= 1;
222 			rephase_light(light_index);
223 
224 			/* calculate and remember intensity for this ii, fi, phase, period */
225 			light->intensity= lighting_function_dispatch(get_lighting_function_specification(&light->static_data, light->state)->function,
226 				light->initial_intensity, light->final_intensity, light->phase, light->period);
227 		}
228 	}
229 }
230 
get_light_status(size_t light_index)231 bool get_light_status(
232 	size_t light_index)
233 {
234 	struct light_data *light= get_light_data(light_index);
235 	// LP change: idiot-proofing
236 	if (!light) return false;
237 
238 	bool status;
239 
240 	switch (light->state)
241 	{
242 		case _light_becoming_active:
243 		case _light_primary_active:
244 		case _light_secondary_active:
245 			status= true;
246 			break;
247 
248 		case _light_becoming_inactive:
249 		case _light_primary_inactive:
250 		case _light_secondary_inactive:
251 			status= false;
252 			break;
253 
254 		default:
255 			vhalt(csprintf(temporary, "what is light state #%d?", light->state));
256 			break;
257 	}
258 
259 	return status;
260 }
261 
set_light_status(size_t light_index,bool new_status)262 bool set_light_status(
263 	size_t light_index,
264 	bool new_status)
265 {
266 	struct light_data *light= get_light_data(light_index);
267 	// LP change: idiot-proofing
268 	if (!light) return false;
269 
270 	bool old_status= get_light_status(light_index);
271 	bool changed= false;
272 
273 	if ((new_status&&!old_status) || (!new_status&&old_status))
274 	{
275 		if (!LIGHT_IS_STATELESS(light))
276 		{
277 			change_light_state(light_index, new_status ? _light_becoming_active : _light_becoming_inactive);
278 			assert(light_index == static_cast<size_t>(static_cast<short>(light_index)));
279                         //MH: Lua script hook
280                         L_Call_Light_Activated(light_index);
281 			assume_correct_switch_position(_panel_is_light_switch, static_cast<short>(light_index), new_status);
282 			changed= true;
283 		}
284 	}
285 
286 	return changed;
287 }
288 
set_tagged_light_statuses(short tag,bool new_status)289 bool set_tagged_light_statuses(
290 	short tag,
291 	bool new_status)
292 {
293 	bool changed= false;
294 
295 	if (tag)
296 	{
297 		int light_index;
298 		struct light_data *light;
299 
300 		for (light_index= 0, light= lights; light_index<short(MAXIMUM_LIGHTS_PER_MAP); ++light_index, ++light)
301 		{
302 			if (light->static_data.tag==tag)
303 			{
304 				if (set_light_status(light_index, new_status))
305 				{
306 					changed= true;
307 				}
308 			}
309 		}
310 	}
311 
312 	return changed;
313 }
314 
get_light_intensity(size_t light_index)315 _fixed get_light_intensity(
316 	size_t light_index)
317 {
318 	// LP change: idiot-proofing / fallback
319 	light_data *light = get_light_data(light_index);
320 	if (!light) return 0;	// Blackness
321 
322 	return light->intensity;
323 }
324 
325 /* ---------- private code */
326 
327 /* given a state, initialize .phase, .period, .initial_intensity, and .final_intensity */
change_light_state(size_t light_index,short new_state)328 void change_light_state(
329 	size_t light_index,
330 	short new_state)
331 {
332 	struct light_data *light= get_light_data(light_index);
333 	// LP change: idiot-proofing
334 	if (!light) return;
335 	struct lighting_function_specification *function= get_lighting_function_specification(&light->static_data, new_state);
336 
337 	light->phase= 0;
338 	light->period= function->period + global_random()%(function->delta_period+1);
339 
340 	light->initial_intensity= light->intensity;
341 	light->final_intensity= function->intensity + global_random()%(function->delta_intensity+1);
342 
343 	light->state= new_state;
344 }
345 
get_lighting_function_specification(struct static_light_data * data,short state)346 static struct lighting_function_specification *get_lighting_function_specification(
347 	struct static_light_data *data,
348 	short state)
349 {
350 	struct lighting_function_specification *function;
351 
352 	switch (state)
353 	{
354 		case _light_becoming_active: function= &data->becoming_active; break;
355 		case _light_primary_active: function= &data->primary_active; break;
356 		case _light_secondary_active: function= &data->secondary_active; break;
357 		case _light_becoming_inactive: function= &data->becoming_inactive; break;
358 		case _light_primary_inactive: function= &data->primary_inactive; break;
359 		case _light_secondary_inactive: function= &data->secondary_inactive; break;
360 		default: vhalt(csprintf(temporary, "what is light state #%d?", state));
361 	}
362 
363 	return function;
364 }
365 
rephase_light(short light_index)366 static void rephase_light(
367 	short light_index)
368 {
369 	struct light_data *light= get_light_data(light_index);
370 	// LP change: idiot-proofing
371 	if (!light) return;
372 	short phase= light->phase;
373 
374 	while (phase>=light->period)
375 	{
376 		short new_state;
377 
378 		phase-= light->period;
379 
380 		switch (light->state)
381 		{
382 			case _light_becoming_active: new_state= _light_primary_active; break;
383 			case _light_primary_active: new_state= _light_secondary_active; break;
384 			case _light_secondary_active: new_state= LIGHT_IS_STATELESS(light) ? _light_becoming_inactive : _light_primary_active; break;
385 			case _light_becoming_inactive: new_state= _light_primary_inactive; break;
386 			case _light_primary_inactive: new_state= _light_secondary_inactive; break;
387 			case _light_secondary_inactive: new_state= LIGHT_IS_STATELESS(light) ? _light_becoming_active : _light_primary_inactive; break;
388 			default: vhalt(csprintf(temporary, "what is light state #%d?", light->state));
389 		}
390 
391 		change_light_state(light_index, new_state);
392 	}
393 	light->phase= phase;
394 }
395 
396 /* ---------- lighting functions */
397 
398 static _fixed constant_lighting_proc(_fixed initial_intensity, _fixed final_intensity, short phase, short period);
399 static _fixed linear_lighting_proc(_fixed initial_intensity, _fixed final_intensity, short phase, short period);
400 static _fixed smooth_lighting_proc(_fixed initial_intensity, _fixed final_intensity, short phase, short period);
401 static _fixed flicker_lighting_proc(_fixed initial_intensity, _fixed final_intensity, short phase, short period);
402 static _fixed random_lighting_proc(_fixed initial_intensity, _fixed final_intensity, short phase, short period);
403 static _fixed fluorescent_lighting_proc(_fixed initial_intensity, _fixed final_intensity, short phase, short period);
404 
405 typedef _fixed (*lighting_function)(_fixed initial_intensity, _fixed final_intensity,
406 	short phase, short period);
407 
408 static lighting_function lighting_functions[NUMBER_OF_LIGHTING_FUNCTIONS]=
409 {
410 	constant_lighting_proc,
411 	linear_lighting_proc,
412 	smooth_lighting_proc,
413 	flicker_lighting_proc,
414 	random_lighting_proc,
415 	fluorescent_lighting_proc,
416 };
417 
lighting_function_dispatch(short function_index,_fixed initial_intensity,_fixed final_intensity,short phase,short period)418 static _fixed lighting_function_dispatch(
419 	short function_index,
420 	_fixed initial_intensity,
421 	_fixed final_intensity,
422 	short phase,
423 	short period)
424 {
425 	assert(function_index>=0 && function_index<NUMBER_OF_LIGHTING_FUNCTIONS);
426 
427 	return lighting_functions[function_index](initial_intensity, final_intensity, phase, period);
428 }
429 
constant_lighting_proc(_fixed initial_intensity,_fixed final_intensity,short phase,short period)430 static _fixed constant_lighting_proc(
431 	_fixed initial_intensity,
432 	_fixed final_intensity,
433 	short phase,
434 	short period)
435 {
436 	(void) (initial_intensity);
437 	(void) (phase);
438 	(void) (period);
439 
440 	return final_intensity;
441 }
442 
linear_lighting_proc(_fixed initial_intensity,_fixed final_intensity,short phase,short period)443 static _fixed linear_lighting_proc(
444 	_fixed initial_intensity,
445 	_fixed final_intensity,
446 	short phase,
447 	short period)
448 {
449 	return initial_intensity + ((final_intensity-initial_intensity)*phase)/period;
450 }
451 
smooth_lighting_proc(_fixed initial_intensity,_fixed final_intensity,short phase,short period)452 static _fixed smooth_lighting_proc(
453 	_fixed initial_intensity,
454 	_fixed final_intensity,
455 	short phase,
456 	short period)
457 {
458 	return initial_intensity + (((final_intensity-initial_intensity)*(cosine_table[(phase*HALF_CIRCLE)/period+HALF_CIRCLE]+TRIG_MAGNITUDE))>>(TRIG_SHIFT+1));
459 }
460 
flicker_lighting_proc(_fixed initial_intensity,_fixed final_intensity,short phase,short period)461 static _fixed flicker_lighting_proc(
462 	_fixed initial_intensity,
463 	_fixed final_intensity,
464 	short phase,
465 	short period)
466 {
467 	_fixed smooth_intensity= smooth_lighting_proc(initial_intensity, final_intensity, phase, period);
468 	_fixed delta= final_intensity-smooth_intensity;
469 
470 	return smooth_intensity + (delta ? global_random()%delta : 0);
471 }
472 
random_lighting_proc(_fixed initial_intensity,_fixed final_intensity,short phase,short period)473 static _fixed random_lighting_proc(
474 	_fixed initial_intensity,
475 	_fixed final_intensity,
476 	short phase,
477 	short period)
478 {
479 	_fixed delta;
480 	if (final_intensity > initial_intensity)
481 	{
482 		delta = final_intensity - initial_intensity;
483 		return initial_intensity + (delta ? global_random()%delta : 0);
484 	} else {
485 		delta = initial_intensity - final_intensity;
486 		return final_intensity + (delta ? global_random()%delta : 0);
487 	}
488 }
489 
490 // should the probability of final_intensity increase with phase?
fluorescent_lighting_proc(_fixed initial_intensity,_fixed final_intensity,short phase,short period)491 static _fixed fluorescent_lighting_proc(
492 	_fixed initial_intensity,
493 	_fixed final_intensity,
494 	short phase,
495 	short period)
496 {
497 	return (global_random()%2 ? final_intensity : initial_intensity);
498 }
499 
unpack_old_light_data(uint8 * Stream,old_light_data * Objects,size_t Count)500 uint8 *unpack_old_light_data(uint8 *Stream, old_light_data* Objects, size_t Count)
501 {
502 	uint8* S = Stream;
503 	old_light_data* ObjPtr = Objects;
504 
505 	for (size_t k = 0; k < Count; k++, ObjPtr++)
506 	{
507 		StreamToValue(S,ObjPtr->flags);
508 
509 		StreamToValue(S,ObjPtr->type);
510 		StreamToValue(S,ObjPtr->mode);
511 		StreamToValue(S,ObjPtr->phase);
512 
513 		StreamToValue(S,ObjPtr->minimum_intensity);
514 		StreamToValue(S,ObjPtr->maximum_intensity);
515 		StreamToValue(S,ObjPtr->period);
516 
517 		StreamToValue(S,ObjPtr->intensity);
518 
519 		S += 5*2;
520 	}
521 
522 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_old_light_data));
523 	return S;
524 }
525 
pack_old_light_data(uint8 * Stream,old_light_data * Objects,size_t Count)526 uint8 *pack_old_light_data(uint8 *Stream, old_light_data* Objects, size_t Count)
527 {
528 	uint8* S = Stream;
529 	old_light_data* ObjPtr = Objects;
530 
531 	for (size_t k = 0; k < Count; k++, ObjPtr++)
532 	{
533 		ValueToStream(S,ObjPtr->flags);
534 
535 		ValueToStream(S,ObjPtr->type);
536 		ValueToStream(S,ObjPtr->mode);
537 		ValueToStream(S,ObjPtr->phase);
538 
539 		ValueToStream(S,ObjPtr->minimum_intensity);
540 		ValueToStream(S,ObjPtr->maximum_intensity);
541 		ValueToStream(S,ObjPtr->period);
542 
543 		ValueToStream(S,ObjPtr->intensity);
544 
545 		S += 5*2;
546 	}
547 
548 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_old_light_data));
549 	return S;
550 }
551 
StreamToLightSpec(uint8 * & S,lighting_function_specification & Object)552 static void StreamToLightSpec(uint8* &S, lighting_function_specification& Object)
553 {
554 	StreamToValue(S,Object.function);
555 
556 	StreamToValue(S,Object.period);
557 	StreamToValue(S,Object.delta_period);
558 	StreamToValue(S,Object.intensity);
559 	StreamToValue(S,Object.delta_intensity);
560 }
561 
LightSpecToStream(uint8 * & S,lighting_function_specification & Object)562 static void LightSpecToStream(uint8* &S, lighting_function_specification& Object)
563 {
564 	ValueToStream(S,Object.function);
565 
566 	ValueToStream(S,Object.period);
567 	ValueToStream(S,Object.delta_period);
568 	ValueToStream(S,Object.intensity);
569 	ValueToStream(S,Object.delta_intensity);
570 }
571 
572 
unpack_static_light_data(uint8 * Stream,static_light_data * Objects,size_t Count)573 uint8 *unpack_static_light_data(uint8 *Stream, static_light_data* Objects, size_t Count)
574 {
575 	uint8* S = Stream;
576 	static_light_data* ObjPtr = Objects;
577 
578 	for (size_t k = 0; k < Count; k++, ObjPtr++)
579 	{
580 		StreamToValue(S,ObjPtr->type);
581 		StreamToValue(S,ObjPtr->flags);
582 		StreamToValue(S,ObjPtr->phase);
583 
584 		StreamToLightSpec(S,ObjPtr->primary_active);
585 		StreamToLightSpec(S,ObjPtr->secondary_active);
586 		StreamToLightSpec(S,ObjPtr->becoming_active);
587 		StreamToLightSpec(S,ObjPtr->primary_inactive);
588 		StreamToLightSpec(S,ObjPtr->secondary_inactive);
589 		StreamToLightSpec(S,ObjPtr->becoming_inactive);
590 
591 		StreamToValue(S,ObjPtr->tag);
592 
593 		S += 4*2;
594 	}
595 
596 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_static_light_data));
597 	return S;
598 }
599 
pack_static_light_data(uint8 * Stream,static_light_data * Objects,size_t Count)600 uint8 *pack_static_light_data(uint8 *Stream, static_light_data* Objects, size_t Count)
601 {
602 	uint8* S = Stream;
603 	static_light_data* ObjPtr = Objects;
604 
605 	for (size_t k = 0; k < Count; k++, ObjPtr++)
606 	{
607 		ValueToStream(S,ObjPtr->type);
608 		ValueToStream(S,ObjPtr->flags);
609 		ValueToStream(S,ObjPtr->phase);
610 
611 		LightSpecToStream(S,ObjPtr->primary_active);
612 		LightSpecToStream(S,ObjPtr->secondary_active);
613 		LightSpecToStream(S,ObjPtr->becoming_active);
614 		LightSpecToStream(S,ObjPtr->primary_inactive);
615 		LightSpecToStream(S,ObjPtr->secondary_inactive);
616 		LightSpecToStream(S,ObjPtr->becoming_inactive);
617 
618 		ValueToStream(S,ObjPtr->tag);
619 
620 		S += 4*2;
621 	}
622 
623 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_static_light_data));
624 	return S;
625 }
626 
627 
unpack_light_data(uint8 * Stream,light_data * Objects,size_t Count)628 uint8 *unpack_light_data(uint8 *Stream, light_data* Objects, size_t Count)
629 {
630 	uint8* S = Stream;
631 	light_data* ObjPtr = Objects;
632 
633 	for (size_t k = 0; k < Count; k++, ObjPtr++)
634 	{
635 		StreamToValue(S,ObjPtr->flags);
636 		StreamToValue(S,ObjPtr->state);
637 
638 		StreamToValue(S,ObjPtr->intensity);
639 
640 		StreamToValue(S,ObjPtr->phase);
641 		StreamToValue(S,ObjPtr->period);
642 		StreamToValue(S,ObjPtr->initial_intensity);
643 		StreamToValue(S,ObjPtr->final_intensity);
644 
645 		S += 4*2;
646 
647 		S = unpack_static_light_data(S,&ObjPtr->static_data,1);
648 	}
649 
650 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_light_data));
651 	return S;
652 }
653 
pack_light_data(uint8 * Stream,light_data * Objects,size_t Count)654 uint8 *pack_light_data(uint8 *Stream, light_data* Objects, size_t Count)
655 {
656 	uint8* S = Stream;
657 	light_data* ObjPtr = Objects;
658 
659 	for (size_t k = 0; k < Count; k++, ObjPtr++)
660 	{
661 		ValueToStream(S,ObjPtr->flags);
662 		ValueToStream(S,ObjPtr->state);
663 
664 		ValueToStream(S,ObjPtr->intensity);
665 
666 		ValueToStream(S,ObjPtr->phase);
667 		ValueToStream(S,ObjPtr->period);
668 		ValueToStream(S,ObjPtr->initial_intensity);
669 		ValueToStream(S,ObjPtr->final_intensity);
670 
671 		S += 4*2;
672 
673 		S = pack_static_light_data(S,&ObjPtr->static_data,1);
674 	}
675 
676 	assert((S - Stream) == static_cast<ptrdiff_t>(Count*SIZEOF_light_data));
677 	return S;
678 }
679 
FixIntensity(lighting_function_specification & LightState,old_light_data & OldLight)680 static void FixIntensity(lighting_function_specification& LightState, old_light_data& OldLight)
681 {
682 	if (LightState.intensity > 0)
683 	{
684 		LightState.intensity = OldLight.maximum_intensity;
685 	} else {
686 		LightState.intensity = OldLight.minimum_intensity;
687 	}
688 }
689 
690 static_light_data old_light_definitions[NUMBER_OF_OLD_LIGHTS] =
691 {
692 	// _light_is_normal
693 	{
694 		_normal_light,
695 		FLAG(_light_is_initially_active)|FLAG(_light_has_slaved_intensities), 0,
696 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
697 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
698 		{ _constant_lighting_function, 1, 0, FIXED_ONE, 0 },
699 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0 },
700 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0 },
701 		{ _constant_lighting_function, 1, 0, FIXED_ONE, 0 }
702 	},
703 
704 	// _light_is_rheostat
705 	{
706 		_normal_light,
707 		FLAG(_light_is_initially_active)|FLAG(_light_has_slaved_intensities), 0,
708 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
709 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
710 		{ _smooth_lighting_function, 3 * TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
711 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0 },
712 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0 },
713 		{ _smooth_lighting_function, 3 * TICKS_PER_SECOND, 0, 0, 0 }
714 	},
715 
716 	// _light_is_flourescent
717 	{
718 		_normal_light,
719 		FLAG(_light_is_initially_active)|FLAG(_light_has_slaved_intensities), 0,
720 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
721 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
722 		{ _fluorescent_lighting_function, 3 * TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
723 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0 },
724 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0 },
725 		{ _constant_lighting_function, 1, 0, 0, 0 }
726 	},
727 
728 	// _light_is_strobe
729 	{
730 		_normal_light,
731 		FLAG(_light_is_initially_active)|FLAG(_light_has_slaved_intensities), 0,
732 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
733 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0 },
734 		{ _constant_lighting_function, 1, 0, FIXED_ONE, 0 },
735 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0 },
736 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
737 		{ _constant_lighting_function, 1, 0, 0, 0 }
738 	},
739 
740 	// _light_flickers
741 	{
742 		_normal_light,
743 		FLAG(_light_is_initially_active)|FLAG(_light_has_slaved_intensities), 0,
744 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
745 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
746 		{ _flicker_lighting_function, 3 * TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
747 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0 },
748 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0 },
749 		{ _constant_lighting_function, 1, 0, 0, 0 }
750 	},
751 
752 	// _light_pulsates
753 	{
754 		_normal_light,
755 		FLAG(_light_is_initially_active)|FLAG(_light_has_slaved_intensities), 0,
756 		{ _smooth_lighting_function, 2*TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
757 		{ _smooth_lighting_function, 2*TICKS_PER_SECOND-1, 0, 0, 0 },
758 		{ _smooth_lighting_function, 2*TICKS_PER_SECOND-1, 0, FIXED_ONE, 0 },
759 
760 		{ _smooth_lighting_function, 2*TICKS_PER_SECOND, 0, 0, 0 },
761 		{ _smooth_lighting_function, 2*TICKS_PER_SECOND-1, 0, FIXED_ONE, 0 },
762 		{ _smooth_lighting_function, 2*TICKS_PER_SECOND, 0, 0, 0 }
763 	},
764 
765 	// _light_is_annoying
766 	{
767 		_normal_light,
768 		FLAG(_light_is_initially_active)|FLAG(_light_has_slaved_intensities), 0,
769 		{ _random_lighting_function, 2, 1, FIXED_ONE, 0 },
770 		{ _constant_lighting_function, 2, 0, 0, 0 },
771 		{ _random_lighting_function, 1, 0, FIXED_ONE, 0 },
772 
773 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0 },
774 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0 },
775 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0 }
776 	},
777 
778 	// _light_is_energy_efficient
779 	{
780 		_normal_light,
781 		FLAG(_light_is_initially_active)|FLAG(_light_has_slaved_intensities), 0,
782 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
783 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
784 		{ _linear_lighting_function, 2 * TICKS_PER_SECOND, 0, FIXED_ONE, 0 },
785 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0 },
786 		{ _constant_lighting_function, TICKS_PER_SECOND, 0, 0, 0 },
787 		{ _linear_lighting_function, 2 * TICKS_PER_SECOND, 0, 0, 0 }
788 	}
789 };
790 
convert_old_light_data_to_new(static_light_data * NewLights,old_light_data * OldLights,int Count)791 void convert_old_light_data_to_new(static_light_data* NewLights, old_light_data* OldLights, int Count)
792 {
793 	// LP: code taken from game_wad.c and somewhat modified
794 
795 	old_light_data *OldLtPtr = OldLights;
796 	static_light_data *NewLtPtr = NewLights;
797 
798 	for (int k = 0; k < Count; k++, OldLtPtr++, NewLtPtr++)
799 	{
800 		obj_copy(*NewLtPtr, old_light_definitions[OldLtPtr->type]);
801 		FixIntensity(NewLtPtr->primary_active, *OldLtPtr);
802 		FixIntensity(NewLtPtr->secondary_active, *OldLtPtr);
803 		FixIntensity(NewLtPtr->becoming_active, *OldLtPtr);
804 		FixIntensity(NewLtPtr->primary_inactive, *OldLtPtr);
805 		FixIntensity(NewLtPtr->secondary_inactive, *OldLtPtr);
806 		FixIntensity(NewLtPtr->becoming_inactive, *OldLtPtr);
807 
808 		if (OldLtPtr->type == _light_is_strobe)
809 		{
810 			NewLtPtr->primary_active.period = OldLtPtr->period / 4 + 1;
811 			NewLtPtr->secondary_active.period = OldLtPtr->period / 4 + 1;
812 			NewLtPtr->primary_inactive.period = OldLtPtr->period / 4 + 1;
813 			NewLtPtr->secondary_inactive.period = OldLtPtr->period / 4 + 1;
814 		}
815 
816 		switch (OldLtPtr->mode)
817 		{
818 		case _light_mode_on:
819 		case _light_mode_turning_on:
820 			SET_FLAG(NewLtPtr->flags,FLAG(_light_is_initially_active),1);
821 			break;
822 		case _light_mode_off:
823 		default:
824 			SET_FLAG(NewLtPtr->flags,FLAG(_light_is_initially_active),0);
825 			break;
826 		}
827 	}
828 }
829 
830