summaryrefslogtreecommitdiff
path: root/apps/plugins/doom/p_lights.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/doom/p_lights.c')
-rw-r--r--apps/plugins/doom/p_lights.c437
1 files changed, 437 insertions, 0 deletions
diff --git a/apps/plugins/doom/p_lights.c b/apps/plugins/doom/p_lights.c
new file mode 100644
index 0000000000..44d151b7b5
--- /dev/null
+++ b/apps/plugins/doom/p_lights.c
@@ -0,0 +1,437 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Action routines for lighting thinkers
29 * Spawn sector based lighting effects.
30 * Handle lighting linedef types
31 *
32 *-----------------------------------------------------------------------------*/
33
34#include "doomstat.h" //jff 5/18/98
35#include "doomdef.h"
36#include "m_random.h"
37#include "r_main.h"
38#include "p_spec.h"
39#include "p_tick.h"
40
41//////////////////////////////////////////////////////////
42//
43// Lighting action routines, called once per tick
44//
45//////////////////////////////////////////////////////////
46
47//
48// T_FireFlicker()
49//
50// Firelight flicker action routine, called once per tick
51//
52// Passed a fireflicker_t structure containing light levels and timing
53// Returns nothing
54//
55void T_FireFlicker (fireflicker_t* flick)
56{
57 int amount;
58
59 if (--flick->count)
60 return;
61
62 amount = (P_Random(pr_lights)&3)*16;
63
64 if (flick->sector->lightlevel - amount < flick->minlight)
65 flick->sector->lightlevel = flick->minlight;
66 else
67 flick->sector->lightlevel = flick->maxlight - amount;
68
69 flick->count = 4;
70}
71
72//
73// T_LightFlash()
74//
75// Broken light flashing action routine, called once per tick
76//
77// Passed a lightflash_t structure containing light levels and timing
78// Returns nothing
79//
80void T_LightFlash (lightflash_t* flash)
81{
82 if (--flash->count)
83 return;
84
85 if (flash->sector->lightlevel == flash->maxlight)
86 {
87 flash-> sector->lightlevel = flash->minlight;
88 flash->count = (P_Random(pr_lights)&flash->mintime)+1;
89 }
90 else
91 {
92 flash-> sector->lightlevel = flash->maxlight;
93 flash->count = (P_Random(pr_lights)&flash->maxtime)+1;
94 }
95
96}
97
98//
99// T_StrobeFlash()
100//
101// Strobe light flashing action routine, called once per tick
102//
103// Passed a strobe_t structure containing light levels and timing
104// Returns nothing
105//
106void T_StrobeFlash (strobe_t* flash)
107{
108 if (--flash->count)
109 return;
110
111 if (flash->sector->lightlevel == flash->minlight)
112 {
113 flash-> sector->lightlevel = flash->maxlight;
114 flash->count = flash->brighttime;
115 }
116 else
117 {
118 flash-> sector->lightlevel = flash->minlight;
119 flash->count =flash->darktime;
120 }
121}
122
123//
124// T_Glow()
125//
126// Glowing light action routine, called once per tick
127//
128// Passed a glow_t structure containing light levels and timing
129// Returns nothing
130//
131
132void T_Glow(glow_t* g)
133{
134 switch(g->direction)
135 {
136 case -1:
137 // light dims
138 g->sector->lightlevel -= GLOWSPEED;
139 if (g->sector->lightlevel <= g->minlight)
140 {
141 g->sector->lightlevel += GLOWSPEED;
142 g->direction = 1;
143 }
144 break;
145
146 case 1:
147 // light brightens
148 g->sector->lightlevel += GLOWSPEED;
149 if (g->sector->lightlevel >= g->maxlight)
150 {
151 g->sector->lightlevel -= GLOWSPEED;
152 g->direction = -1;
153 }
154 break;
155 }
156}
157
158//////////////////////////////////////////////////////////
159//
160// Sector lighting type spawners
161//
162// After the map has been loaded, each sector is scanned
163// for specials that spawn thinkers
164//
165//////////////////////////////////////////////////////////
166
167//
168// P_SpawnFireFlicker()
169//
170// Spawns a fire flicker lighting thinker
171//
172// Passed the sector that spawned the thinker
173// Returns nothing
174//
175void P_SpawnFireFlicker (sector_t* sector)
176{
177 fireflicker_t* flick;
178
179 // Note that we are resetting sector attributes.
180 // Nothing special about it during gameplay.
181 sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type
182
183 flick = Z_Malloc ( sizeof(*flick), PU_LEVSPEC, 0);
184
185 P_AddThinker (&flick->thinker);
186
187 flick->thinker.function = T_FireFlicker;
188 flick->sector = sector;
189 flick->maxlight = sector->lightlevel;
190 flick->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel)+16;
191 flick->count = 4;
192}
193
194//
195// P_SpawnLightFlash()
196//
197// Spawns a broken light flash lighting thinker
198//
199// Passed the sector that spawned the thinker
200// Returns nothing
201//
202void P_SpawnLightFlash (sector_t* sector)
203{
204 lightflash_t* flash;
205
206 // nothing special about it during gameplay
207 sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type
208
209 flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0);
210
211 P_AddThinker (&flash->thinker);
212
213 flash->thinker.function = T_LightFlash;
214 flash->sector = sector;
215 flash->maxlight = sector->lightlevel;
216
217 flash->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel);
218 flash->maxtime = 64;
219 flash->mintime = 7;
220 flash->count = (P_Random(pr_lights)&flash->maxtime)+1;
221}
222
223//
224// P_SpawnStrobeFlash
225//
226// Spawns a blinking light thinker
227//
228// Passed the sector that spawned the thinker, speed of blinking
229// and whether blinking is to by syncrhonous with other sectors
230//
231// Returns nothing
232//
233void P_SpawnStrobeFlash
234( sector_t* sector,
235 int fastOrSlow,
236 int inSync )
237{
238 strobe_t* flash;
239
240 flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0);
241
242 P_AddThinker (&flash->thinker);
243
244 flash->sector = sector;
245 flash->darktime = fastOrSlow;
246 flash->brighttime = STROBEBRIGHT;
247 flash->thinker.function = T_StrobeFlash;
248 flash->maxlight = sector->lightlevel;
249 flash->minlight = P_FindMinSurroundingLight(sector, sector->lightlevel);
250
251 if (flash->minlight == flash->maxlight)
252 flash->minlight = 0;
253
254 // nothing special about it during gameplay
255 sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type
256
257 if (!inSync)
258 flash->count = (P_Random(pr_lights)&7)+1;
259 else
260 flash->count = 1;
261}
262
263//
264// P_SpawnGlowingLight()
265//
266// Spawns a glowing light (smooth oscillation from min to max) thinker
267//
268// Passed the sector that spawned the thinker
269// Returns nothing
270//
271void P_SpawnGlowingLight(sector_t* sector)
272{
273 glow_t* g;
274
275 g = Z_Malloc( sizeof(*g), PU_LEVSPEC, 0);
276
277 P_AddThinker(&g->thinker);
278
279 g->sector = sector;
280 g->minlight = P_FindMinSurroundingLight(sector,sector->lightlevel);
281 g->maxlight = sector->lightlevel;
282 g->thinker.function = T_Glow;
283 g->direction = -1;
284
285 sector->special &= ~31; //jff 3/14/98 clear non-generalized sector type
286}
287
288//////////////////////////////////////////////////////////
289//
290// Linedef lighting function handlers
291//
292//////////////////////////////////////////////////////////
293
294//
295// EV_StartLightStrobing()
296//
297// Start strobing lights (usually from a trigger)
298//
299// Passed the line that activated the strobing
300// Returns true
301//
302// jff 2/12/98 added int return value, fixed return
303//
304int EV_StartLightStrobing(line_t* line)
305{
306 int secnum;
307 sector_t* sec;
308
309 secnum = -1;
310 // start lights strobing in all sectors tagged same as line
311 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
312 {
313 sec = &sectors[secnum];
314 // if already doing a lighting function, don't start a second
315 if (P_SectorActive(lighting_special,sec)) //jff 2/22/98
316 continue;
317
318 P_SpawnStrobeFlash (sec,SLOWDARK, 0);
319 }
320 return 1;
321}
322
323//
324// EV_TurnTagLightsOff()
325//
326// Turn line's tagged sector's lights to min adjacent neighbor level
327//
328// Passed the line that activated the lights being turned off
329// Returns true
330//
331// jff 2/12/98 added int return value, fixed return
332//
333int EV_TurnTagLightsOff(line_t* line)
334{
335 int j;
336
337 // search sectors for those with same tag as activating line
338
339 // killough 10/98: replaced inefficient search with fast search
340 for (j = -1; (j = P_FindSectorFromLineTag(line,j)) >= 0;)
341 {
342 sector_t *sector = sectors + j, *tsec;
343 int i, min = sector->lightlevel;
344 // find min neighbor light level
345 for (i = 0;i < sector->linecount; i++)
346 if ((tsec = getNextSector(sector->lines[i], sector)) &&
347 tsec->lightlevel < min)
348 min = tsec->lightlevel;
349 sector->lightlevel = min;
350 }
351 return 1;
352}
353
354//
355// EV_LightTurnOn()
356//
357// Turn sectors tagged to line lights on to specified or max neighbor level
358//
359// Passed the activating line, and a level to set the light to
360// If level passed is 0, the maximum neighbor lighting is used
361// Returns true
362//
363// jff 2/12/98 added int return value, fixed return
364//
365int EV_LightTurnOn(line_t *line, int bright)
366{
367 int i;
368
369 // search all sectors for ones with same tag as activating line
370
371 // killough 10/98: replace inefficient search with fast search
372 for (i = -1; (i = P_FindSectorFromLineTag(line,i)) >= 0;)
373 {
374 sector_t *temp, *sector = sectors+i;
375 int j, tbright = bright; //jff 5/17/98 search for maximum PER sector
376
377 // bright = 0 means to search for highest light level surrounding sector
378
379 if (!bright)
380 for (j = 0;j < sector->linecount; j++)
381 if ((temp = getNextSector(sector->lines[j],sector)) &&
382 temp->lightlevel > tbright)
383 tbright = temp->lightlevel;
384
385 sector->lightlevel = tbright;
386
387 //jff 5/17/98 unless compatibility optioned
388 //then maximum near ANY tagged sector
389 if (comp[comp_model])
390 bright = tbright;
391 }
392 return 1;
393}
394
395/* killough 10/98:
396 *
397 * EV_LightTurnOnPartway()
398 *
399 * Turn sectors tagged to line lights on to specified or max neighbor level
400 *
401 * Passed the activating line, and a light level fraction between 0 and 1.
402 * Sets the light to min on 0, max on 1, and interpolates in-between.
403 * Used for doors with gradual lighting effects.
404 *
405 * Returns true
406 */
407
408int EV_LightTurnOnPartway(line_t *line, fixed_t level)
409{
410 int i;
411
412 if (level < 0) // clip at extremes
413 level = 0;
414 if (level > FRACUNIT)
415 level = FRACUNIT;
416
417 // search all sectors for ones with same tag as activating line
418 for (i = -1; (i = P_FindSectorFromLineTag(line,i)) >= 0;)
419 {
420 sector_t *temp, *sector = sectors+i;
421 int j, bright = 0, min = sector->lightlevel;
422
423 for (j = 0; j < sector->linecount; j++)
424 if ((temp = getNextSector(sector->lines[j],sector)))
425 {
426 if (temp->lightlevel > bright)
427 bright = temp->lightlevel;
428 if (temp->lightlevel < min)
429 min = temp->lightlevel;
430 }
431
432 sector->lightlevel = // Set level in-between extremes
433 (level * bright + (FRACUNIT-level) * min) >> FRACBITS;
434 }
435 return 1;
436}
437