mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-13 14:10:42 +00:00
831 lines
19 KiB
C++
831 lines
19 KiB
C++
//-----------------------------------------------------------------------------
|
|
//
|
|
// Copyright 1993-1996 id Software
|
|
// Copyright 1994-1996 Raven Software
|
|
// Copyright 1999-2016 Randy Heit
|
|
// Copyright 2002-2016 Christoph Oelckers
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see http://www.gnu.org/licenses/
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// DESCRIPTION:
|
|
// Handle Sector base lighting effects.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
#include "templates.h"
|
|
#include "m_random.h"
|
|
|
|
#include "doomdef.h"
|
|
#include "p_local.h"
|
|
#include "p_spec.h"
|
|
|
|
#include "p_lnspec.h"
|
|
#include "doomstat.h"
|
|
#include "p_maputl.h"
|
|
#include "g_levellocals.h"
|
|
#include "maploader/maploader.h"
|
|
#include "p_spec_thinkers.h"
|
|
|
|
// State.
|
|
#include "serializer.h"
|
|
|
|
static FRandom pr_flicker ("Flicker");
|
|
static FRandom pr_lightflash ("LightFlash");
|
|
static FRandom pr_strobeflash ("StrobeFlash");
|
|
static FRandom pr_fireflicker ("FireFlicker");
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
IMPLEMENT_CLASS(DLighting, false, false)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// FIRELIGHT FLICKER
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
IMPLEMENT_CLASS(DFireFlicker, false, false)
|
|
|
|
void DFireFlicker::Serialize(FSerializer &arc)
|
|
{
|
|
Super::Serialize (arc);
|
|
arc("count", m_Count)
|
|
("maxlight", m_MaxLight)
|
|
("minlight", m_MinLight);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// T_FireFlicker
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DFireFlicker::Tick ()
|
|
{
|
|
int amount;
|
|
|
|
if (--m_Count == 0)
|
|
{
|
|
amount = (pr_fireflicker() & 3) << 4;
|
|
|
|
// [RH] Shouldn't this be (m_MaxLight - amount < m_MinLight)?
|
|
if (m_Sector->lightlevel - amount < m_MinLight)
|
|
m_Sector->SetLightLevel(m_MinLight);
|
|
else
|
|
m_Sector->SetLightLevel(m_MaxLight - amount);
|
|
|
|
m_Count = 4;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// P_SpawnFireFlicker
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DFireFlicker::Construct(sector_t *sector)
|
|
{
|
|
Super::Construct(sector);
|
|
m_MaxLight = sector->lightlevel;
|
|
m_MinLight = sector_t::ClampLight(FindMinSurroundingLight(sector, sector->lightlevel) + 16);
|
|
m_Count = 4;
|
|
}
|
|
|
|
void DFireFlicker::Construct(sector_t *sector, int upper, int lower)
|
|
{
|
|
Super::Construct(sector);
|
|
m_MaxLight = sector_t::ClampLight(upper);
|
|
m_MinLight = sector_t::ClampLight(lower);
|
|
m_Count = 4;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// [RH] flickering light like Hexen's
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
IMPLEMENT_CLASS(DFlicker, false, false)
|
|
|
|
void DFlicker::Serialize(FSerializer &arc)
|
|
{
|
|
Super::Serialize (arc);
|
|
arc("count", m_Count)
|
|
("maxlight", m_MaxLight)
|
|
("minlight", m_MinLight);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DFlicker::Tick ()
|
|
{
|
|
if (m_Count)
|
|
{
|
|
m_Count--;
|
|
}
|
|
else if (m_Sector->lightlevel == m_MaxLight)
|
|
{
|
|
m_Sector->SetLightLevel(m_MinLight);
|
|
m_Count = (pr_flicker()&7)+1;
|
|
}
|
|
else
|
|
{
|
|
m_Sector->SetLightLevel(m_MaxLight);
|
|
m_Count = (pr_flicker()&31)+1;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DFlicker::Construct(sector_t *sector, int upper, int lower)
|
|
{
|
|
Super::Construct(sector);
|
|
m_MaxLight = sector_t::ClampLight(upper);
|
|
m_MinLight = sector_t::ClampLight(lower);
|
|
sector->lightlevel = m_MaxLight;
|
|
m_Count = (pr_flicker()&64)+1;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// BROKEN LIGHT FLASHING
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
IMPLEMENT_CLASS(DLightFlash, false, false)
|
|
|
|
void DLightFlash::Serialize(FSerializer &arc)
|
|
{
|
|
Super::Serialize (arc);
|
|
arc("count", m_Count)
|
|
("maxlight", m_MaxLight)
|
|
("minlight", m_MinLight)
|
|
("maxtime", m_MaxTime)
|
|
("mintime", m_MinTime);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// T_LightFlash
|
|
// Do flashing lights.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DLightFlash::Tick ()
|
|
{
|
|
if (--m_Count == 0)
|
|
{
|
|
if (m_Sector->lightlevel == m_MaxLight)
|
|
{
|
|
m_Sector->SetLightLevel(m_MinLight);
|
|
m_Count = (pr_lightflash() & m_MinTime) + 1;
|
|
}
|
|
else
|
|
{
|
|
m_Sector->SetLightLevel(m_MaxLight);
|
|
m_Count = (pr_lightflash() & m_MaxTime) + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// P_SpawnLightFlash
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DLightFlash::Construct(sector_t *sector)
|
|
{
|
|
Super::Construct(sector);
|
|
// Find light levels like Doom.
|
|
m_MaxLight = sector->lightlevel;
|
|
m_MinLight = FindMinSurroundingLight (sector, sector->lightlevel);
|
|
m_MaxTime = 64;
|
|
m_MinTime = 7;
|
|
m_Count = (pr_lightflash() & m_MaxTime) + 1;
|
|
}
|
|
|
|
void DLightFlash::Construct (sector_t *sector, int min, int max)
|
|
{
|
|
Super::Construct(sector);
|
|
// Use specified light levels.
|
|
m_MaxLight = sector_t::ClampLight(max);
|
|
m_MinLight = sector_t::ClampLight(min);
|
|
m_MaxTime = 64;
|
|
m_MinTime = 7;
|
|
m_Count = (pr_lightflash() & m_MaxTime) + 1;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// STROBE LIGHT FLASHING
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
IMPLEMENT_CLASS(DStrobe, false, false)
|
|
|
|
void DStrobe::Serialize(FSerializer &arc)
|
|
{
|
|
Super::Serialize (arc);
|
|
arc("count", m_Count)
|
|
("maxlight", m_MaxLight)
|
|
("minlight", m_MinLight)
|
|
("darktime", m_DarkTime)
|
|
("brighttime", m_BrightTime);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// T_StrobeFlash
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DStrobe::Tick ()
|
|
{
|
|
if (--m_Count == 0)
|
|
{
|
|
if (m_Sector->lightlevel == m_MinLight)
|
|
{
|
|
m_Sector->SetLightLevel(m_MaxLight);
|
|
m_Count = m_BrightTime;
|
|
}
|
|
else
|
|
{
|
|
m_Sector->SetLightLevel(m_MinLight);
|
|
m_Count = m_DarkTime;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Hexen-style constructor
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DStrobe::Construct(sector_t *sector, int upper, int lower, int utics, int ltics)
|
|
{
|
|
Super::Construct(sector);
|
|
m_DarkTime = ltics;
|
|
m_BrightTime = utics;
|
|
m_MaxLight = sector_t::ClampLight(upper);
|
|
m_MinLight = sector_t::ClampLight(lower);
|
|
m_Count = 1; // Hexen-style is always in sync
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Doom-style constructor
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DStrobe::Construct(sector_t *sector, int utics, int ltics, bool inSync)
|
|
{
|
|
Super::Construct(sector);
|
|
m_DarkTime = ltics;
|
|
m_BrightTime = utics;
|
|
|
|
m_MaxLight = sector->lightlevel;
|
|
m_MinLight = FindMinSurroundingLight (sector, sector->lightlevel);
|
|
|
|
if (m_MinLight == m_MaxLight)
|
|
m_MinLight = 0;
|
|
|
|
m_Count = inSync ? 1 : (pr_strobeflash() & 7) + 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Spawn glowing light
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
IMPLEMENT_CLASS(DGlow, false, false)
|
|
|
|
void DGlow::Serialize(FSerializer &arc)
|
|
{
|
|
Super::Serialize (arc);
|
|
arc("direction", m_Direction)
|
|
("maxlight", m_MaxLight)
|
|
("minlight", m_MinLight);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DGlow::Tick ()
|
|
{
|
|
const int GLOWSPEED = 8;
|
|
int newlight = m_Sector->lightlevel;
|
|
|
|
switch (m_Direction)
|
|
{
|
|
case -1:
|
|
// DOWN
|
|
newlight -= GLOWSPEED;
|
|
if (newlight <= m_MinLight)
|
|
{
|
|
newlight += GLOWSPEED;
|
|
m_Direction = 1;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
// UP
|
|
newlight += GLOWSPEED;
|
|
if (newlight >= m_MaxLight)
|
|
{
|
|
newlight -= GLOWSPEED;
|
|
m_Direction = -1;
|
|
}
|
|
break;
|
|
}
|
|
m_Sector->SetLightLevel(newlight);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DGlow::Construct(sector_t *sector)
|
|
{
|
|
Super::Construct(sector);
|
|
m_MinLight = FindMinSurroundingLight (sector, sector->lightlevel);
|
|
m_MaxLight = sector->lightlevel;
|
|
m_Direction = -1;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// [RH] More glowing light, this time appropriate for Hexen-ish uses.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
IMPLEMENT_CLASS(DGlow2, false, false)
|
|
|
|
void DGlow2::Serialize(FSerializer &arc)
|
|
{
|
|
Super::Serialize (arc);
|
|
arc("end", m_End)
|
|
("maxtics", m_MaxTics)
|
|
("oneshot", m_OneShot)
|
|
("start", m_Start)
|
|
("tics", m_Tics);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DGlow2::Tick ()
|
|
{
|
|
if (m_Tics++ >= m_MaxTics)
|
|
{
|
|
if (m_OneShot)
|
|
{
|
|
m_Sector->SetLightLevel(m_End);
|
|
Destroy ();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
int temp = m_Start;
|
|
m_Start = m_End;
|
|
m_End = temp;
|
|
m_Tics -= m_MaxTics;
|
|
}
|
|
}
|
|
|
|
m_Sector->SetLightLevel(((m_End - m_Start) * m_Tics) / m_MaxTics + m_Start);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DGlow2::Construct(sector_t *sector, int start, int end, int tics, bool oneshot)
|
|
{
|
|
Super::Construct(sector);
|
|
m_Start = sector_t::ClampLight(start);
|
|
m_End = sector_t::ClampLight(end);
|
|
m_MaxTics = tics;
|
|
m_Tics = -1;
|
|
m_OneShot = oneshot;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// [RH] Phased lighting ala Hexen, but implemented without the help of the Hexen source
|
|
// The effect is a little different, but close enough, I feel.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
IMPLEMENT_CLASS(DPhased, false, false)
|
|
|
|
void DPhased::Serialize(FSerializer &arc)
|
|
{
|
|
Super::Serialize (arc);
|
|
arc("baselevel", m_BaseLevel)
|
|
("phase", m_Phase);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DPhased::Tick ()
|
|
{
|
|
const int steps = 12;
|
|
|
|
if (m_Phase < steps)
|
|
m_Sector->SetLightLevel( ((255 - m_BaseLevel) * m_Phase) / steps + m_BaseLevel);
|
|
else if (m_Phase < 2*steps)
|
|
m_Sector->SetLightLevel( ((255 - m_BaseLevel) * (2*steps - m_Phase - 1) / steps
|
|
+ m_BaseLevel));
|
|
else
|
|
m_Sector->SetLightLevel(m_BaseLevel);
|
|
|
|
if (m_Phase == 0)
|
|
m_Phase = 63;
|
|
else
|
|
m_Phase--;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int DPhased::PhaseHelper (sector_t *sector, int index, int light, sector_t *prev)
|
|
{
|
|
if (!sector || sector->validcount == validcount)
|
|
{
|
|
return index;
|
|
}
|
|
else
|
|
{
|
|
DPhased *l;
|
|
int baselevel = sector->lightlevel ? sector->lightlevel : light;
|
|
sector->validcount = validcount;
|
|
|
|
if (index == 0)
|
|
{
|
|
l = this;
|
|
m_BaseLevel = baselevel;
|
|
}
|
|
else
|
|
l = Level->CreateThinker<DPhased> (sector, baselevel);
|
|
|
|
int numsteps = PhaseHelper (sector->NextSpecialSector (
|
|
sector->special == LightSequenceSpecial1 ?
|
|
LightSequenceSpecial2 : LightSequenceSpecial1, prev),
|
|
index + 1, l->m_BaseLevel, sector);
|
|
l->m_Phase = ((numsteps - index - 1) * 64) / numsteps;
|
|
|
|
sector->special = 0;
|
|
|
|
return numsteps;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DPhased::Propagate()
|
|
{
|
|
validcount++;
|
|
PhaseHelper (m_Sector, 0, 0, nullptr);
|
|
}
|
|
|
|
void DPhased::Construct (sector_t *sector, int baselevel, int phase)
|
|
{
|
|
Super::Construct(sector);
|
|
m_BaseLevel = baselevel;
|
|
m_Phase = phase;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void FLevelLocals::EV_StartLightFlickering(int tag, int upper, int lower)
|
|
{
|
|
int secnum;
|
|
auto it = GetSectorTagIterator(tag);
|
|
while ((secnum = it.Next()) >= 0)
|
|
{
|
|
CreateThinker<DFlicker>(§ors[secnum], upper, lower);
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Start strobing lights (usually from a trigger)
|
|
// [RH] Made it more configurable.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void FLevelLocals::EV_StartLightStrobing(int tag, int upper, int lower, int utics, int ltics)
|
|
{
|
|
int secnum;
|
|
auto it = GetSectorTagIterator(tag);
|
|
while ((secnum = it.Next()) >= 0)
|
|
{
|
|
sector_t *sec = §ors[secnum];
|
|
if (sec->lightingdata)
|
|
continue;
|
|
|
|
CreateThinker<DStrobe>(sec, upper, lower, utics, ltics);
|
|
}
|
|
}
|
|
|
|
void FLevelLocals::EV_StartLightStrobing(int tag, int utics, int ltics)
|
|
{
|
|
int secnum;
|
|
auto it = GetSectorTagIterator(tag);
|
|
while ((secnum = it.Next()) >= 0)
|
|
{
|
|
sector_t *sec = §ors[secnum];
|
|
if (sec->lightingdata)
|
|
continue;
|
|
|
|
CreateThinker<DStrobe>(sec, utics, ltics, false);
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// TURN LINE'S TAG LIGHTS OFF
|
|
// [RH] Takes a tag instead of a line
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void FLevelLocals::EV_TurnTagLightsOff(int tag)
|
|
{
|
|
int secnum;
|
|
auto it = GetSectorTagIterator(tag);
|
|
while ((secnum = it.Next()) >= 0)
|
|
{
|
|
sector_t *sector = §ors[secnum];
|
|
int min = sector->lightlevel;
|
|
|
|
for (auto ln : sector->Lines)
|
|
{
|
|
sector_t *tsec = getNextSector(ln, sector);
|
|
if (!tsec)
|
|
continue;
|
|
if (tsec->lightlevel < min)
|
|
min = tsec->lightlevel;
|
|
}
|
|
sector->SetLightLevel(min);
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// TURN LINE'S TAG LIGHTS ON
|
|
// [RH] Takes a tag instead of a line
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void FLevelLocals::EV_LightTurnOn(int tag, int bright)
|
|
{
|
|
int secnum;
|
|
auto it = GetSectorTagIterator(tag);
|
|
while ((secnum = it.Next()) >= 0)
|
|
{
|
|
sector_t *sector = §ors[secnum];
|
|
int tbright = bright; //jff 5/17/98 search for maximum PER sector
|
|
|
|
// bright = -1 means to search ([RH] Not 0)
|
|
// for highest light level
|
|
// surrounding sector
|
|
if (bright < 0)
|
|
{
|
|
for (auto ln : sector->Lines)
|
|
{
|
|
sector_t *temp = getNextSector(ln, sector);
|
|
|
|
if (!temp)
|
|
continue;
|
|
|
|
if (temp->lightlevel > tbright)
|
|
tbright = temp->lightlevel;
|
|
}
|
|
}
|
|
sector->SetLightLevel(tbright);
|
|
|
|
//jff 5/17/98 unless compatibility optioned
|
|
//then maximum near ANY tagged sector
|
|
if (i_compatflags & COMPATF_LIGHT)
|
|
{
|
|
bright = tbright;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// killough 10/98
|
|
//
|
|
// EV_LightTurnOnPartway
|
|
//
|
|
// Turn sectors tagged to line lights on to specified or max neighbor level
|
|
//
|
|
// Passed the tag of sector(s) to light and a light level fraction between 0 and 1.
|
|
// Sets the light to min on 0, max on 1, and interpolates in-between.
|
|
// Used for doors with gradual lighting effects.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void FLevelLocals::EV_LightTurnOnPartway(int tag, double frac)
|
|
{
|
|
frac = clamp(frac, 0., 1.);
|
|
|
|
// Search all sectors for ones with same tag as activating line
|
|
int secnum;
|
|
auto it = GetSectorTagIterator(tag);
|
|
while ((secnum = it.Next()) >= 0)
|
|
{
|
|
sector_t *temp, *sector = §ors[secnum];
|
|
int bright = 0, min = sector->lightlevel;
|
|
|
|
for (auto ln : sector->Lines)
|
|
{
|
|
if ((temp = getNextSector(ln, sector)) != nullptr)
|
|
{
|
|
if (temp->lightlevel > bright)
|
|
{
|
|
bright = temp->lightlevel;
|
|
}
|
|
if (temp->lightlevel < min)
|
|
{
|
|
min = temp->lightlevel;
|
|
}
|
|
}
|
|
}
|
|
sector->SetLightLevel(int(frac * bright + (1 - frac) * min));
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// [RH] New function to adjust tagged sectors' light levels
|
|
// by a relative amount. Light levels are clipped to
|
|
// be within range for sector_t::light
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void FLevelLocals::EV_LightChange(int tag, int value)
|
|
{
|
|
int secnum;
|
|
auto it = GetSectorTagIterator(tag);
|
|
while ((secnum = it.Next()) >= 0)
|
|
{
|
|
sectors[secnum].SetLightLevel(sectors[secnum].lightlevel + value);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void FLevelLocals::EV_StartLightGlowing(int tag, int upper, int lower, int tics)
|
|
{
|
|
int secnum;
|
|
|
|
// If tics is non-positive, then we can't really do anything.
|
|
if (tics <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (upper < lower)
|
|
{
|
|
int temp = upper;
|
|
upper = lower;
|
|
lower = temp;
|
|
}
|
|
|
|
auto it = GetSectorTagIterator(tag);
|
|
while ((secnum = it.Next()) >= 0)
|
|
{
|
|
sector_t *sec = §ors[secnum];
|
|
if (sec->lightingdata)
|
|
continue;
|
|
|
|
CreateThinker<DGlow2>(sec, upper, lower, tics, false);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void FLevelLocals::EV_StartLightFading(int tag, int value, int tics)
|
|
{
|
|
int secnum;
|
|
auto it = GetSectorTagIterator(tag);
|
|
while ((secnum = it.Next()) >= 0)
|
|
{
|
|
sector_t *sec = §ors[secnum];
|
|
if (sec->lightingdata)
|
|
continue;
|
|
|
|
if (tics <= 0)
|
|
{
|
|
sec->SetLightLevel(value);
|
|
}
|
|
else
|
|
{
|
|
// No need to fade if lightlevel is already at desired value.
|
|
if (sec->lightlevel == value)
|
|
continue;
|
|
|
|
CreateThinker<DGlow2>(sec, sec->lightlevel, value, tics, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//============================================================================
|
|
//
|
|
// EV_StopLightEffect
|
|
//
|
|
// Stops a lighting effect that is currently running in a sector.
|
|
//
|
|
//============================================================================
|
|
|
|
void FLevelLocals::EV_StopLightEffect (int tag)
|
|
{
|
|
auto iterator = GetThinkerIterator<DLighting>(NAME_None, STAT_LIGHT);
|
|
DLighting *effect;
|
|
|
|
while ((effect = iterator.Next()) != nullptr)
|
|
{
|
|
if (SectorHasTag(effect->GetSector(), tag))
|
|
{
|
|
effect->Destroy();
|
|
}
|
|
}
|
|
}
|
|
|
|
|