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