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