1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
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
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.
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.
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
28 * Action routines for lighting thinkers
29 * Spawn sector based lighting effects.
30 * Handle lighting linedef types
32 *-----------------------------------------------------------------------------*/
34 #include "doomstat.h" //jff 5/18/98
41 //////////////////////////////////////////////////////////
43 // Lighting action routines, called once per tick
45 //////////////////////////////////////////////////////////
50 // Firelight flicker action routine, called once per tick
52 // Passed a fireflicker_t structure containing light levels and timing
55 void T_FireFlicker (fireflicker_t
* flick
)
62 amount
= (P_Random(pr_lights
)&3)*16;
64 if (flick
->sector
->lightlevel
- amount
< flick
->minlight
)
65 flick
->sector
->lightlevel
= flick
->minlight
;
67 flick
->sector
->lightlevel
= flick
->maxlight
- amount
;
75 // Broken light flashing action routine, called once per tick
77 // Passed a lightflash_t structure containing light levels and timing
80 void T_LightFlash (lightflash_t
* flash
)
85 if (flash
->sector
->lightlevel
== flash
->maxlight
)
87 flash
-> sector
->lightlevel
= flash
->minlight
;
88 flash
->count
= (P_Random(pr_lights
)&flash
->mintime
)+1;
92 flash
-> sector
->lightlevel
= flash
->maxlight
;
93 flash
->count
= (P_Random(pr_lights
)&flash
->maxtime
)+1;
101 // Strobe light flashing action routine, called once per tick
103 // Passed a strobe_t structure containing light levels and timing
106 void T_StrobeFlash (strobe_t
* flash
)
111 if (flash
->sector
->lightlevel
== flash
->minlight
)
113 flash
-> sector
->lightlevel
= flash
->maxlight
;
114 flash
->count
= flash
->brighttime
;
118 flash
-> sector
->lightlevel
= flash
->minlight
;
119 flash
->count
=flash
->darktime
;
126 // Glowing light action routine, called once per tick
128 // Passed a glow_t structure containing light levels and timing
132 void T_Glow(glow_t
* g
)
138 g
->sector
->lightlevel
-= GLOWSPEED
;
139 if (g
->sector
->lightlevel
<= g
->minlight
)
141 g
->sector
->lightlevel
+= GLOWSPEED
;
148 g
->sector
->lightlevel
+= GLOWSPEED
;
149 if (g
->sector
->lightlevel
>= g
->maxlight
)
151 g
->sector
->lightlevel
-= GLOWSPEED
;
158 //////////////////////////////////////////////////////////
160 // Sector lighting type spawners
162 // After the map has been loaded, each sector is scanned
163 // for specials that spawn thinkers
165 //////////////////////////////////////////////////////////
168 // P_SpawnFireFlicker()
170 // Spawns a fire flicker lighting thinker
172 // Passed the sector that spawned the thinker
175 void P_SpawnFireFlicker (sector_t
* sector
)
177 fireflicker_t
* flick
;
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
183 flick
= Z_Malloc ( sizeof(*flick
), PU_LEVSPEC
, 0);
185 P_AddThinker (&flick
->thinker
);
187 flick
->thinker
.function
= T_FireFlicker
;
188 flick
->sector
= sector
;
189 flick
->maxlight
= sector
->lightlevel
;
190 flick
->minlight
= P_FindMinSurroundingLight(sector
,sector
->lightlevel
)+16;
195 // P_SpawnLightFlash()
197 // Spawns a broken light flash lighting thinker
199 // Passed the sector that spawned the thinker
202 void P_SpawnLightFlash (sector_t
* sector
)
206 // nothing special about it during gameplay
207 sector
->special
&= ~31; //jff 3/14/98 clear non-generalized sector type
209 flash
= Z_Malloc ( sizeof(*flash
), PU_LEVSPEC
, 0);
211 P_AddThinker (&flash
->thinker
);
213 flash
->thinker
.function
= T_LightFlash
;
214 flash
->sector
= sector
;
215 flash
->maxlight
= sector
->lightlevel
;
217 flash
->minlight
= P_FindMinSurroundingLight(sector
,sector
->lightlevel
);
220 flash
->count
= (P_Random(pr_lights
)&flash
->maxtime
)+1;
224 // P_SpawnStrobeFlash
226 // Spawns a blinking light thinker
228 // Passed the sector that spawned the thinker, speed of blinking
229 // and whether blinking is to by syncrhonous with other sectors
233 void P_SpawnStrobeFlash
240 flash
= Z_Malloc ( sizeof(*flash
), PU_LEVSPEC
, 0);
242 P_AddThinker (&flash
->thinker
);
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
);
251 if (flash
->minlight
== flash
->maxlight
)
254 // nothing special about it during gameplay
255 sector
->special
&= ~31; //jff 3/14/98 clear non-generalized sector type
258 flash
->count
= (P_Random(pr_lights
)&7)+1;
264 // P_SpawnGlowingLight()
266 // Spawns a glowing light (smooth oscillation from min to max) thinker
268 // Passed the sector that spawned the thinker
271 void P_SpawnGlowingLight(sector_t
* sector
)
275 g
= Z_Malloc( sizeof(*g
), PU_LEVSPEC
, 0);
277 P_AddThinker(&g
->thinker
);
280 g
->minlight
= P_FindMinSurroundingLight(sector
,sector
->lightlevel
);
281 g
->maxlight
= sector
->lightlevel
;
282 g
->thinker
.function
= T_Glow
;
285 sector
->special
&= ~31; //jff 3/14/98 clear non-generalized sector type
288 //////////////////////////////////////////////////////////
290 // Linedef lighting function handlers
292 //////////////////////////////////////////////////////////
295 // EV_StartLightStrobing()
297 // Start strobing lights (usually from a trigger)
299 // Passed the line that activated the strobing
302 // jff 2/12/98 added int return value, fixed return
304 int EV_StartLightStrobing(line_t
* line
)
310 // start lights strobing in all sectors tagged same as line
311 while ((secnum
= P_FindSectorFromLineTag(line
,secnum
)) >= 0)
313 sec
= §ors
[secnum
];
314 // if already doing a lighting function, don't start a second
315 if (P_SectorActive(lighting_special
,sec
)) //jff 2/22/98
318 P_SpawnStrobeFlash (sec
,SLOWDARK
, 0);
324 // EV_TurnTagLightsOff()
326 // Turn line's tagged sector's lights to min adjacent neighbor level
328 // Passed the line that activated the lights being turned off
331 // jff 2/12/98 added int return value, fixed return
333 int EV_TurnTagLightsOff(line_t
* line
)
337 // search sectors for those with same tag as activating line
339 // killough 10/98: replaced inefficient search with fast search
340 for (j
= -1; (j
= P_FindSectorFromLineTag(line
,j
)) >= 0;)
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
;
357 // Turn sectors tagged to line lights on to specified or max neighbor level
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
363 // jff 2/12/98 added int return value, fixed return
365 int EV_LightTurnOn(line_t
*line
, int bright
)
369 // search all sectors for ones with same tag as activating line
371 // killough 10/98: replace inefficient search with fast search
372 for (i
= -1; (i
= P_FindSectorFromLineTag(line
,i
)) >= 0;)
374 sector_t
*temp
, *sector
= sectors
+i
;
375 int j
, tbright
= bright
; //jff 5/17/98 search for maximum PER sector
377 // bright = 0 means to search for highest light level surrounding sector
380 for (j
= 0;j
< sector
->linecount
; j
++)
381 if ((temp
= getNextSector(sector
->lines
[j
],sector
)) &&
382 temp
->lightlevel
> tbright
)
383 tbright
= temp
->lightlevel
;
385 sector
->lightlevel
= tbright
;
387 //jff 5/17/98 unless compatibility optioned
388 //then maximum near ANY tagged sector
389 if (comp
[comp_model
])
397 * EV_LightTurnOnPartway()
399 * Turn sectors tagged to line lights on to specified or max neighbor level
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.
408 int EV_LightTurnOnPartway(line_t
*line
, fixed_t level
)
412 if (level
< 0) // clip at extremes
414 if (level
> FRACUNIT
)
417 // search all sectors for ones with same tag as activating line
418 for (i
= -1; (i
= P_FindSectorFromLineTag(line
,i
)) >= 0;)
420 sector_t
*temp
, *sector
= sectors
+i
;
421 int j
, bright
= 0, min
= sector
->lightlevel
;
423 for (j
= 0; j
< sector
->linecount
; j
++)
424 if ((temp
= getNextSector(sector
->lines
[j
],sector
)))
426 if (temp
->lightlevel
> bright
)
427 bright
= temp
->lightlevel
;
428 if (temp
->lightlevel
< min
)
429 min
= temp
->lightlevel
;
432 sector
->lightlevel
= // Set level in-between extremes
433 (level
* bright
+ (FRACUNIT
-level
) * min
) >> FRACBITS
;