mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 21:11:39 +00:00
- moved a large batch of code from p_spec.cpp and a few other files into the maploader folder.
This commit is contained in:
parent
0a6b6173de
commit
4d55c28b60
9 changed files with 1579 additions and 1406 deletions
|
@ -1074,6 +1074,7 @@ set (PCH_SOURCES
|
|||
hwrenderer/utility/hw_shaderpatcher.cpp
|
||||
hwrenderer/utility/hw_vrmodes.cpp
|
||||
maploader/edata.cpp
|
||||
maploader/specials.cpp
|
||||
maploader/maploader.cpp
|
||||
maploader/slopes.cpp
|
||||
maploader/glnodes.cpp
|
||||
|
|
1309
src/maploader/specials.cpp
Normal file
1309
src/maploader/specials.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -106,7 +106,7 @@ void F3DFloor::UpdateColormap(FColormap &map)
|
|||
// Add one 3D floor to the sector
|
||||
//
|
||||
//==========================================================================
|
||||
static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flags, int alpha)
|
||||
void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flags, int alpha)
|
||||
{
|
||||
F3DFloor* ffloor;
|
||||
unsigned i;
|
||||
|
@ -778,156 +778,6 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Creates all 3D floors defined by one linedef
|
||||
//
|
||||
//==========================================================================
|
||||
int MapLoader::Set3DFloor(line_t * line, int param, int param2, int alpha)
|
||||
{
|
||||
int s;
|
||||
int flags;
|
||||
int tag = line->args[0];
|
||||
sector_t * sec = line->frontsector, *ss;
|
||||
|
||||
auto itr = Level->GetSectorTagIterator(tag);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
{
|
||||
ss = &Level->sectors[s];
|
||||
|
||||
if (param == 0)
|
||||
{
|
||||
flags = FF_EXISTS | FF_RENDERALL | FF_SOLID | FF_INVERTSECTOR;
|
||||
alpha = 255;
|
||||
for (auto l: sec->Lines)
|
||||
{
|
||||
if (l->special == Sector_SetContents && l->frontsector == sec)
|
||||
{
|
||||
alpha = clamp<int>(l->args[1], 0, 100);
|
||||
if (l->args[2] & 1) flags &= ~FF_SOLID;
|
||||
if (l->args[2] & 2) flags |= FF_SEETHROUGH;
|
||||
if (l->args[2] & 4) flags |= FF_SHOOTTHROUGH;
|
||||
if (l->args[2] & 8) flags |= FF_ADDITIVETRANS;
|
||||
if (alpha != 100) flags |= FF_TRANSLUCENT;//|FF_BOTHPLANES|FF_ALLSIDES;
|
||||
if (l->args[0])
|
||||
{
|
||||
// Yes, Vavoom's 3D-floor definitions suck!
|
||||
// The content list changed in r1783 of Vavoom to be unified
|
||||
// among all its supported games, so it has now ten different
|
||||
// values instead of just five.
|
||||
static uint32_t vavoomcolors[] = { VC_EMPTY,
|
||||
VC_WATER, VC_LAVA, VC_NUKAGE, VC_SLIME, VC_HELLSLIME,
|
||||
VC_BLOOD, VC_SLUDGE, VC_HAZARD, VC_BOOMWATER };
|
||||
flags |= FF_SWIMMABLE | FF_BOTHPLANES | FF_ALLSIDES | FF_FLOOD;
|
||||
|
||||
l->frontsector->Colormap.FadeColor = vavoomcolors[l->args[0]] & VC_COLORMASK;
|
||||
l->frontsector->Colormap.FogDensity = 0;
|
||||
}
|
||||
alpha = (alpha * 255) / 100;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (param == 4)
|
||||
{
|
||||
flags = FF_EXISTS | FF_RENDERPLANES | FF_INVERTPLANES | FF_NOSHADE | FF_FIX;
|
||||
if (param2 & 1) flags |= FF_SEETHROUGH; // marker for allowing missing texture checks
|
||||
alpha = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
static const int defflags[] = { 0,
|
||||
FF_SOLID,
|
||||
FF_SWIMMABLE | FF_BOTHPLANES | FF_ALLSIDES | FF_SHOOTTHROUGH | FF_SEETHROUGH,
|
||||
FF_SHOOTTHROUGH | FF_SEETHROUGH,
|
||||
};
|
||||
|
||||
flags = defflags[param & 3] | FF_EXISTS | FF_RENDERALL;
|
||||
|
||||
if (param & 4) flags |= FF_ALLSIDES | FF_BOTHPLANES;
|
||||
if (param & 16) flags ^= FF_SEETHROUGH;
|
||||
if (param & 32) flags ^= FF_SHOOTTHROUGH;
|
||||
|
||||
if (param2 & 1) flags |= FF_NOSHADE;
|
||||
if (param2 & 2) flags |= FF_DOUBLESHADOW;
|
||||
if (param2 & 4) flags |= FF_FOG;
|
||||
if (param2 & 8) flags |= FF_THINFLOOR;
|
||||
if (param2 & 16) flags |= FF_UPPERTEXTURE;
|
||||
if (param2 & 32) flags |= FF_LOWERTEXTURE;
|
||||
if (param2 & 64) flags |= FF_ADDITIVETRANS | FF_TRANSLUCENT;
|
||||
// if flooding is used the floor must be non-solid and is automatically made shootthrough and seethrough
|
||||
if ((param2 & 128) && !(flags & FF_SOLID)) flags |= FF_FLOOD | FF_SEETHROUGH | FF_SHOOTTHROUGH;
|
||||
if (param2 & 512) flags |= FF_FADEWALLS;
|
||||
if (param2&1024) flags |= FF_RESET;
|
||||
FTextureID tex = line->sidedef[0]->GetTexture(side_t::top);
|
||||
if (!tex.Exists() && alpha < 255)
|
||||
{
|
||||
alpha = -tex.GetIndex();
|
||||
}
|
||||
alpha = clamp(alpha, 0, 255);
|
||||
if (alpha == 0) flags &= ~(FF_RENDERALL | FF_BOTHPLANES | FF_ALLSIDES);
|
||||
else if (alpha != 255) flags |= FF_TRANSLUCENT;
|
||||
|
||||
}
|
||||
P_Add3DFloor(ss, sec, line, flags, alpha);
|
||||
}
|
||||
// To be 100% safe this should be done even if the alpha by texture value isn't used.
|
||||
if (!line->sidedef[0]->GetTexture(side_t::top).isValid())
|
||||
line->sidedef[0]->SetTexture(side_t::top, FNullTextureID());
|
||||
return 1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Spawns 3D floors
|
||||
//
|
||||
//==========================================================================
|
||||
void MapLoader::Spawn3DFloors ()
|
||||
{
|
||||
static int flagvals[] = {512, 2+512, 512+1024};
|
||||
|
||||
for (auto &line : Level->lines)
|
||||
{
|
||||
switch(line.special)
|
||||
{
|
||||
case ExtraFloor_LightOnly:
|
||||
if (line.args[1] < 0 || line.args[1] > 2) line.args[1] = 0;
|
||||
if (line.args[0] != 0)
|
||||
Set3DFloor(&line, 3, flagvals[line.args[1]], 0);
|
||||
break;
|
||||
|
||||
case Sector_Set3DFloor:
|
||||
// The flag high-byte/line id is only needed in Hexen format.
|
||||
// UDMF can set both of these parameters without any restriction of the usable values.
|
||||
// In Doom format the translators can take full integers for the tag and the line ID always is the same as the tag.
|
||||
if (Level->maptype == MAPTYPE_HEXEN)
|
||||
{
|
||||
if (line.args[1]&8)
|
||||
{
|
||||
Level->tagManager.AddLineID(line.Index(), line.args[4]);
|
||||
}
|
||||
else
|
||||
{
|
||||
line.args[0]+=256*line.args[4];
|
||||
line.args[4]=0;
|
||||
}
|
||||
}
|
||||
Set3DFloor(&line, line.args[1]&~8, line.args[2], line.args[3]);
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
line.special=0;
|
||||
line.args[0] = line.args[1] = line.args[2] = line.args[3] = line.args[4] = 0;
|
||||
}
|
||||
|
||||
for (auto &sec : Level->sectors)
|
||||
{
|
||||
P_Recalculate3DFloors(&sec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -136,4 +136,6 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
|
|||
secplane_t P_FindFloorPlane(sector_t * sector, const DVector3 &pos);
|
||||
int P_Find3DFloor(sector_t * sec, const DVector3 &pos, bool above, bool floor, double &cmpz);
|
||||
|
||||
void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flags, int alpha);
|
||||
|
||||
#endif
|
186
src/p_lights.cpp
186
src/p_lights.cpp
|
@ -38,6 +38,7 @@
|
|||
#include "p_maputl.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "maploader/maploader.h"
|
||||
#include "p_spec_thinkers.h"
|
||||
|
||||
// State.
|
||||
#include "serializer.h"
|
||||
|
@ -48,132 +49,6 @@ static FRandom pr_strobeflash ("StrobeFlash");
|
|||
static FRandom pr_fireflicker ("FireFlicker");
|
||||
|
||||
|
||||
class DFireFlicker : public DLighting
|
||||
{
|
||||
DECLARE_CLASS(DFireFlicker, DLighting)
|
||||
public:
|
||||
DFireFlicker(sector_t *sector);
|
||||
DFireFlicker(sector_t *sector, int upper, int lower);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick();
|
||||
protected:
|
||||
int m_Count;
|
||||
int m_MaxLight;
|
||||
int m_MinLight;
|
||||
private:
|
||||
DFireFlicker();
|
||||
};
|
||||
|
||||
class DFlicker : public DLighting
|
||||
{
|
||||
DECLARE_CLASS(DFlicker, DLighting)
|
||||
public:
|
||||
DFlicker(sector_t *sector, int upper, int lower);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick();
|
||||
protected:
|
||||
int m_Count;
|
||||
int m_MaxLight;
|
||||
int m_MinLight;
|
||||
private:
|
||||
DFlicker();
|
||||
};
|
||||
|
||||
class DLightFlash : public DLighting
|
||||
{
|
||||
DECLARE_CLASS(DLightFlash, DLighting)
|
||||
public:
|
||||
DLightFlash(sector_t *sector);
|
||||
DLightFlash(sector_t *sector, int min, int max);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick();
|
||||
protected:
|
||||
int m_Count;
|
||||
int m_MaxLight;
|
||||
int m_MinLight;
|
||||
int m_MaxTime;
|
||||
int m_MinTime;
|
||||
private:
|
||||
DLightFlash();
|
||||
};
|
||||
|
||||
class DStrobe : public DLighting
|
||||
{
|
||||
DECLARE_CLASS(DStrobe, DLighting)
|
||||
public:
|
||||
DStrobe(sector_t *sector, int utics, int ltics, bool inSync);
|
||||
DStrobe(sector_t *sector, int upper, int lower, int utics, int ltics);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick();
|
||||
protected:
|
||||
int m_Count;
|
||||
int m_MinLight;
|
||||
int m_MaxLight;
|
||||
int m_DarkTime;
|
||||
int m_BrightTime;
|
||||
private:
|
||||
DStrobe();
|
||||
};
|
||||
|
||||
class DGlow : public DLighting
|
||||
{
|
||||
DECLARE_CLASS(DGlow, DLighting)
|
||||
public:
|
||||
DGlow(sector_t *sector);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick();
|
||||
protected:
|
||||
int m_MinLight;
|
||||
int m_MaxLight;
|
||||
int m_Direction;
|
||||
private:
|
||||
DGlow();
|
||||
};
|
||||
|
||||
// [RH] Glow from Light_Glow and Light_Fade specials
|
||||
class DGlow2 : public DLighting
|
||||
{
|
||||
DECLARE_CLASS(DGlow2, DLighting)
|
||||
public:
|
||||
DGlow2(sector_t *sector, int start, int end, int tics, bool oneshot);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick();
|
||||
protected:
|
||||
int m_Start;
|
||||
int m_End;
|
||||
int m_MaxTics;
|
||||
int m_Tics;
|
||||
bool m_OneShot;
|
||||
private:
|
||||
DGlow2();
|
||||
};
|
||||
|
||||
// [RH] Phased light thinker
|
||||
class DPhased : public DLighting
|
||||
{
|
||||
DECLARE_CLASS(DPhased, DLighting)
|
||||
public:
|
||||
DPhased(sector_t *sector);
|
||||
DPhased(sector_t *sector, int baselevel, int phase);
|
||||
// These are for internal use only but the Create template needs access to them.
|
||||
DPhased();
|
||||
DPhased(sector_t *sector, int baselevel);
|
||||
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick();
|
||||
protected:
|
||||
uint8_t m_BaseLevel;
|
||||
uint8_t m_Phase;
|
||||
private:
|
||||
int PhaseHelper(sector_t *sector, int index, int light, sector_t *prev);
|
||||
};
|
||||
|
||||
#define GLOWSPEED 8
|
||||
#define STROBEBRIGHT 5
|
||||
#define FASTDARK 15
|
||||
#define SLOWDARK TICRATE
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
|
@ -694,6 +569,7 @@ void DGlow::Serialize(FSerializer &arc)
|
|||
|
||||
void DGlow::Tick ()
|
||||
{
|
||||
const int GLOWSPEED = 8;
|
||||
int newlight = m_Sector->lightlevel;
|
||||
|
||||
switch (m_Direction)
|
||||
|
@ -998,61 +874,3 @@ void EV_StopLightEffect (int tag)
|
|||
}
|
||||
|
||||
|
||||
void MapLoader::SpawnLights(sector_t *sector)
|
||||
{
|
||||
switch (sector->special)
|
||||
{
|
||||
case Light_Phased:
|
||||
Create<DPhased>(sector, 48, 63 - (sector->lightlevel & 63));
|
||||
break;
|
||||
|
||||
// [RH] Hexen-like phased lighting
|
||||
case LightSequenceStart:
|
||||
Create<DPhased>(sector);
|
||||
break;
|
||||
|
||||
case dLight_Flicker:
|
||||
Create<DLightFlash>(sector);
|
||||
break;
|
||||
|
||||
case dLight_StrobeFast:
|
||||
Create<DStrobe>(sector, STROBEBRIGHT, FASTDARK, false);
|
||||
break;
|
||||
|
||||
case dLight_StrobeSlow:
|
||||
Create<DStrobe>(sector, STROBEBRIGHT, SLOWDARK, false);
|
||||
break;
|
||||
|
||||
case dLight_Strobe_Hurt:
|
||||
Create<DStrobe>(sector, STROBEBRIGHT, FASTDARK, false);
|
||||
break;
|
||||
|
||||
case dLight_Glow:
|
||||
Create<DGlow>(sector);
|
||||
break;
|
||||
|
||||
case dLight_StrobeSlowSync:
|
||||
Create<DStrobe>(sector, STROBEBRIGHT, SLOWDARK, true);
|
||||
break;
|
||||
|
||||
case dLight_StrobeFastSync:
|
||||
Create<DStrobe>(sector, STROBEBRIGHT, FASTDARK, true);
|
||||
break;
|
||||
|
||||
case dLight_FireFlicker:
|
||||
Create<DFireFlicker>(sector);
|
||||
break;
|
||||
|
||||
case dScroll_EastLavaDamage:
|
||||
Create<DStrobe>(sector, STROBEBRIGHT, FASTDARK, false);
|
||||
break;
|
||||
|
||||
case sLight_Strobe_Hurt:
|
||||
Create<DStrobe>(sector, STROBEBRIGHT, FASTDARK, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
141
src/p_pusher.cpp
141
src/p_pusher.cpp
|
@ -36,49 +36,11 @@
|
|||
#include "d_player.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "actorinlines.h"
|
||||
#include "p_spec_thinkers.h"
|
||||
#include "maploader/maploader.h"
|
||||
|
||||
CVAR(Bool, var_pushers, true, CVAR_SERVERINFO);
|
||||
|
||||
// phares 3/20/98: added new model of Pushers for push/pull effects
|
||||
|
||||
class DPusher : public DThinker
|
||||
{
|
||||
DECLARE_CLASS (DPusher, DThinker)
|
||||
HAS_OBJECT_POINTERS
|
||||
public:
|
||||
enum EPusher
|
||||
{
|
||||
p_push,
|
||||
p_pull,
|
||||
p_wind,
|
||||
p_current
|
||||
};
|
||||
|
||||
DPusher ();
|
||||
DPusher (EPusher type, line_t *l, int magnitude, int angle, AActor *source, int affectee);
|
||||
void Serialize(FSerializer &arc);
|
||||
int CheckForSectorMatch (EPusher type, int tag);
|
||||
void ChangeValues (int magnitude, int angle)
|
||||
{
|
||||
DAngle ang = angle * (360. / 256.);
|
||||
m_PushVec = ang.ToVector(magnitude);
|
||||
m_Magnitude = magnitude;
|
||||
}
|
||||
|
||||
void Tick ();
|
||||
|
||||
protected:
|
||||
EPusher m_Type;
|
||||
TObjPtr<AActor*> m_Source;// Point source if point pusher
|
||||
DVector2 m_PushVec;
|
||||
double m_Magnitude; // Vector strength for point pusher
|
||||
double m_Radius; // Effective radius for point pusher
|
||||
int m_Affectee; // Number of affected sector
|
||||
|
||||
friend bool PIT_PushThing (AActor *thing);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DPusher, false, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(DPusher)
|
||||
|
@ -334,95 +296,10 @@ void DPusher::Tick ()
|
|||
}
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
//
|
||||
// P_GetPushThing() returns a pointer to an MT_PUSH or MT_PULL thing,
|
||||
// NULL otherwise.
|
||||
|
||||
AActor *MapLoader::GetPushThing (int s)
|
||||
void AdjustPusher(int tag, int magnitude, int angle, bool wind)
|
||||
{
|
||||
AActor* thing;
|
||||
sector_t* sec;
|
||||
|
||||
sec = &Level->sectors[s];
|
||||
thing = sec->thinglist;
|
||||
|
||||
while (thing &&
|
||||
thing->GetClass()->TypeName != NAME_PointPusher &&
|
||||
thing->GetClass()->TypeName != NAME_PointPuller)
|
||||
{
|
||||
thing = thing->snext;
|
||||
}
|
||||
return thing;
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
//
|
||||
// Initialize the sectors where pushers are present
|
||||
//
|
||||
|
||||
void MapLoader::SpawnPushers ()
|
||||
{
|
||||
line_t *l = &Level->lines[0];
|
||||
int s;
|
||||
|
||||
for (unsigned i = 0; i < Level->lines.Size(); i++, l++)
|
||||
{
|
||||
switch (l->special)
|
||||
{
|
||||
case Sector_SetWind: // wind
|
||||
{
|
||||
auto itr = Level->GetSectorTagIterator(l->args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
Create<DPusher>(DPusher::p_wind, l->args[3] ? l : nullptr, l->args[1], l->args[2], nullptr, s);
|
||||
l->special = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case Sector_SetCurrent: // current
|
||||
{
|
||||
auto itr = Level->GetSectorTagIterator(l->args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
Create<DPusher>(DPusher::p_current, l->args[3] ? l : nullptr, l->args[1], l->args[2], nullptr, s);
|
||||
l->special = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case PointPush_SetForce: // push/pull
|
||||
if (l->args[0]) { // [RH] Find thing by sector
|
||||
auto itr = Level->GetSectorTagIterator(l->args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
{
|
||||
AActor *thing = GetPushThing (s);
|
||||
if (thing) { // No MT_P* means no effect
|
||||
// [RH] Allow narrowing it down by tid
|
||||
if (!l->args[1] || l->args[1] == thing->tid)
|
||||
Create<DPusher> (DPusher::p_push, l->args[3] ? l : NULL, l->args[2],
|
||||
0, thing, s);
|
||||
}
|
||||
}
|
||||
} else { // [RH] Find thing by tid
|
||||
AActor *thing;
|
||||
auto iterator = Level->GetActorIterator(l->args[1]);
|
||||
|
||||
while ( (thing = iterator.Next ()) )
|
||||
{
|
||||
if (thing->GetClass()->TypeName == NAME_PointPusher ||
|
||||
thing->GetClass()->TypeName == NAME_PointPuller)
|
||||
{
|
||||
Create<DPusher> (DPusher::p_push, l->args[3] ? l : NULL, l->args[2], 0, thing, thing->Sector->Index());
|
||||
}
|
||||
}
|
||||
}
|
||||
l->special = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AdjustPusher (int tag, int magnitude, int angle, bool wind)
|
||||
{
|
||||
DPusher::EPusher type = wind? DPusher::p_wind : DPusher::p_current;
|
||||
DPusher::EPusher type = wind ? DPusher::p_wind : DPusher::p_current;
|
||||
|
||||
// Find pushers already attached to the sector, and change their parameters.
|
||||
TArray<FThinkerCollection> Collection;
|
||||
|
@ -430,17 +307,17 @@ void AdjustPusher (int tag, int magnitude, int angle, bool wind)
|
|||
TThinkerIterator<DPusher> iterator;
|
||||
FThinkerCollection collect;
|
||||
|
||||
while ( (collect.Obj = iterator.Next ()) )
|
||||
while ((collect.Obj = iterator.Next()))
|
||||
{
|
||||
if ((collect.RefNum = ((DPusher *)collect.Obj)->CheckForSectorMatch (type, tag)) >= 0)
|
||||
if ((collect.RefNum = ((DPusher *)collect.Obj)->CheckForSectorMatch(type, tag)) >= 0)
|
||||
{
|
||||
((DPusher *)collect.Obj)->ChangeValues (magnitude, angle);
|
||||
Collection.Push (collect);
|
||||
((DPusher *)collect.Obj)->ChangeValues(magnitude, angle);
|
||||
Collection.Push(collect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t numcollected = Collection.Size ();
|
||||
size_t numcollected = Collection.Size();
|
||||
int secnum;
|
||||
|
||||
// Now create pushers for any sectors that don't already have them.
|
||||
|
@ -455,7 +332,7 @@ void AdjustPusher (int tag, int magnitude, int angle, bool wind)
|
|||
}
|
||||
if (i == numcollected)
|
||||
{
|
||||
Create<DPusher> (type, nullptr, magnitude, angle, nullptr, secnum);
|
||||
Create<DPusher>(type, nullptr, magnitude, angle, nullptr, secnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
265
src/p_scroll.cpp
265
src/p_scroll.cpp
|
@ -63,50 +63,7 @@
|
|||
#include "r_data/r_interpolate.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "maploader/maploader.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// killough 3/7/98: Add generalized scroll effects
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class DScroller : public DThinker
|
||||
{
|
||||
DECLARE_CLASS (DScroller, DThinker)
|
||||
HAS_OBJECT_POINTERS
|
||||
public:
|
||||
|
||||
DScroller(EScroll type, double dx, double dy, sector_t *control, sector_t *sec, side_t *side, int accel, EScrollPos scrollpos = EScrollPos::scw_all);
|
||||
DScroller (double dx, double dy, const line_t *l, sector_t *control, int accel, EScrollPos scrollpos = EScrollPos::scw_all);
|
||||
void OnDestroy() override;
|
||||
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick ();
|
||||
|
||||
bool AffectsWall (side_t * wall) const { return m_Side == wall; }
|
||||
side_t *GetWall () const { return m_Side; }
|
||||
sector_t *GetSector() const { return m_Sector; }
|
||||
void SetRate (double dx, double dy) { m_dx = dx; m_dy = dy; }
|
||||
bool IsType (EScroll type) const { return type == m_Type; }
|
||||
EScrollPos GetScrollParts() const { return m_Parts; }
|
||||
|
||||
protected:
|
||||
EScroll m_Type; // Type of scroll effect
|
||||
double m_dx, m_dy; // (dx,dy) scroll speeds
|
||||
sector_t *m_Sector; // Affected sector
|
||||
side_t *m_Side; // ... or side
|
||||
sector_t *m_Controller; // Control sector (nullptr if none) used to control scrolling
|
||||
double m_LastHeight; // Last known height of control sector
|
||||
double m_vdx, m_vdy; // Accumulated velocity if accelerative
|
||||
int m_Accel; // Whether it's accelerative
|
||||
EScrollPos m_Parts; // Which parts of a sidedef are being scrolled?
|
||||
TObjPtr<DInterpolation*> m_Interpolations[3];
|
||||
|
||||
private:
|
||||
DScroller ()
|
||||
{
|
||||
}
|
||||
};
|
||||
#include "p_spec_thinkers.h"
|
||||
|
||||
IMPLEMENT_CLASS(DScroller, false, true)
|
||||
|
||||
|
@ -412,221 +369,6 @@ DScroller::DScroller (double dx, double dy, const line_t *l, sector_t * control,
|
|||
}
|
||||
}
|
||||
|
||||
// Amount (dx,dy) vector linedef is shifted right to get scroll amount
|
||||
#define SCROLL_SHIFT 5
|
||||
#define SCROLLTYPE(i) EScrollPos(((i) <= 0) || ((i) & ~7) ? 7 : (i))
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Initialize the scrollers
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MapLoader::SpawnScrollers()
|
||||
{
|
||||
line_t *l = &Level->lines[0];
|
||||
side_t *side;
|
||||
TArray<int> copyscrollers;
|
||||
|
||||
for (auto &line : Level->lines)
|
||||
{
|
||||
if (line.special == Sector_CopyScroller)
|
||||
{
|
||||
// don't allow copying the scroller if the sector has the same tag as it would just duplicate it.
|
||||
if (!Level->SectorHasTag(line.frontsector, line.args[0]))
|
||||
{
|
||||
copyscrollers.Push(line.Index());
|
||||
}
|
||||
line.special = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < Level->lines.Size(); i++, l++)
|
||||
{
|
||||
double dx; // direction and speed of scrolling
|
||||
double dy;
|
||||
sector_t *control = nullptr;
|
||||
int accel = 0; // no control sector or acceleration
|
||||
int special = l->special;
|
||||
|
||||
// Check for undefined parameters that are non-zero and output messages for them.
|
||||
// We don't report for specials we don't understand.
|
||||
FLineSpecial *spec = P_GetLineSpecialInfo(special);
|
||||
if (spec != nullptr)
|
||||
{
|
||||
int max = spec->map_args;
|
||||
for (unsigned arg = max; arg < countof(l->args); ++arg)
|
||||
{
|
||||
if (l->args[arg] != 0)
|
||||
{
|
||||
Printf("Line %d (type %d:%s), arg %u is %d (should be 0)\n",
|
||||
i, special, spec->name, arg+1, l->args[arg]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// killough 3/7/98: Types 245-249 are same as 250-254 except that the
|
||||
// first side's sector's heights cause scrolling when they change, and
|
||||
// this linedef controls the direction and speed of the scrolling. The
|
||||
// most complicated linedef since donuts, but powerful :)
|
||||
//
|
||||
// killough 3/15/98: Add acceleration. Types 214-218 are the same but
|
||||
// are accelerative.
|
||||
|
||||
// [RH] Assume that it's a scroller and zero the line's special.
|
||||
l->special = 0;
|
||||
|
||||
dx = dy = 0; // Shut up, GCC
|
||||
|
||||
if (special == Scroll_Ceiling ||
|
||||
special == Scroll_Floor ||
|
||||
special == Scroll_Texture_Model)
|
||||
{
|
||||
if (l->args[1] & 3)
|
||||
{
|
||||
// if 1, then displacement
|
||||
// if 2, then accelerative (also if 3)
|
||||
control = l->sidedef[0]->sector;
|
||||
if (l->args[1] & 2)
|
||||
accel = 1;
|
||||
}
|
||||
if (special == Scroll_Texture_Model || l->args[1] & 4)
|
||||
{
|
||||
// The line housing the special controls the
|
||||
// direction and speed of scrolling.
|
||||
dx = l->Delta().X / 32.;
|
||||
dy = l->Delta().Y / 32.;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The speed and direction are parameters to the special.
|
||||
dx = (l->args[3] - 128) / 32.;
|
||||
dy = (l->args[4] - 128) / 32.;
|
||||
}
|
||||
}
|
||||
|
||||
switch (special)
|
||||
{
|
||||
int s;
|
||||
|
||||
case Scroll_Ceiling:
|
||||
{
|
||||
auto itr = Level->GetSectorTagIterator(l->args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
{
|
||||
Create<DScroller>(EScroll::sc_ceiling, -dx, dy, control, &Level->sectors[s], nullptr, accel);
|
||||
}
|
||||
for (unsigned j = 0; j < copyscrollers.Size(); j++)
|
||||
{
|
||||
line_t *line = &Level->lines[copyscrollers[j]];
|
||||
|
||||
if (line->args[0] == l->args[0] && (line->args[1] & 1))
|
||||
{
|
||||
Create<DScroller>(EScroll::sc_ceiling, -dx, dy, control, line->frontsector, nullptr, accel);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Scroll_Floor:
|
||||
if (l->args[2] != 1)
|
||||
{ // scroll the floor texture
|
||||
auto itr = Level->GetSectorTagIterator(l->args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
{
|
||||
Create<DScroller> (EScroll::sc_floor, -dx, dy, control, &Level->sectors[s], nullptr, accel);
|
||||
}
|
||||
for(unsigned j = 0;j < copyscrollers.Size(); j++)
|
||||
{
|
||||
line_t *line = &Level->lines[copyscrollers[j]];
|
||||
|
||||
if (line->args[0] == l->args[0] && (line->args[1] & 2))
|
||||
{
|
||||
Create<DScroller>(EScroll::sc_floor, -dx, dy, control, line->frontsector, nullptr, accel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (l->args[2] > 0)
|
||||
{ // carry objects on the floor
|
||||
auto itr = Level->GetSectorTagIterator(l->args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
{
|
||||
Create<DScroller> (EScroll::sc_carry, dx, dy, control, &Level->sectors[s], nullptr, accel);
|
||||
}
|
||||
for(unsigned j = 0;j < copyscrollers.Size(); j++)
|
||||
{
|
||||
line_t *line = &Level->lines[copyscrollers[j]];
|
||||
|
||||
if (line->args[0] == l->args[0] && (line->args[1] & 4))
|
||||
{
|
||||
Create<DScroller> (EScroll::sc_carry, dx, dy, control, line->frontsector, nullptr, accel);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// killough 3/1/98: scroll wall according to linedef
|
||||
// (same direction and speed as scrolling floors)
|
||||
case Scroll_Texture_Model:
|
||||
{
|
||||
auto itr = Level->GetLineIdIterator(l->args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
{
|
||||
if (s != (int)i)
|
||||
Create<DScroller>(dx, dy, &Level->lines[s], control, accel);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Scroll_Texture_Offsets:
|
||||
// killough 3/2/98: scroll according to sidedef offsets
|
||||
side = Level->lines[i].sidedef[0];
|
||||
Create<DScroller> (EScroll::sc_side, -side->GetTextureXOffset(side_t::mid),
|
||||
side->GetTextureYOffset(side_t::mid), nullptr, nullptr, side, accel, SCROLLTYPE(l->args[0]));
|
||||
break;
|
||||
|
||||
case Scroll_Texture_Left:
|
||||
l->special = special; // Restore the special, for compat_useblocking's benefit.
|
||||
side = Level->lines[i].sidedef[0];
|
||||
Create<DScroller> (EScroll::sc_side, l->args[0] / 64., 0, nullptr, nullptr, side, accel, SCROLLTYPE(l->args[1]));
|
||||
break;
|
||||
|
||||
case Scroll_Texture_Right:
|
||||
l->special = special;
|
||||
side = Level->lines[i].sidedef[0];
|
||||
Create<DScroller> (EScroll::sc_side, -l->args[0] / 64., 0, nullptr, nullptr, side, accel, SCROLLTYPE(l->args[1]));
|
||||
break;
|
||||
|
||||
case Scroll_Texture_Up:
|
||||
l->special = special;
|
||||
side = Level->lines[i].sidedef[0];
|
||||
Create<DScroller> (EScroll::sc_side, 0, l->args[0] / 64., nullptr, nullptr, side, accel, SCROLLTYPE(l->args[1]));
|
||||
break;
|
||||
|
||||
case Scroll_Texture_Down:
|
||||
l->special = special;
|
||||
side = Level->lines[i].sidedef[0];
|
||||
Create<DScroller> (EScroll::sc_side, 0, -l->args[0] / 64., nullptr, nullptr, side, accel, SCROLLTYPE(l->args[1]));
|
||||
break;
|
||||
|
||||
case Scroll_Texture_Both:
|
||||
side = Level->lines[i].sidedef[0];
|
||||
if (l->args[0] == 0) {
|
||||
dx = (l->args[1] - l->args[2]) / 64.;
|
||||
dy = (l->args[4] - l->args[3]) / 64.;
|
||||
Create<DScroller> (EScroll::sc_side, dx, dy, nullptr, nullptr, side, accel);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// [RH] It wasn't a scroller after all, so restore the special.
|
||||
l->special = special;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Modify a wall scroller
|
||||
|
@ -733,8 +475,3 @@ void SetScroller (FLevelLocals *Level, int tag, EScroll type, double dx, double
|
|||
Create<DScroller> (type, dx, dy, nullptr, &Level->sectors[i], nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void MapLoader::CreateScroller(EScroll type, double dx, double dy, sector_t *affectee, int accel, EScrollPos scrollpos)
|
||||
{
|
||||
Create<DScroller>(type, dx, dy, nullptr, affectee, nullptr, accel, scrollpos);
|
||||
}
|
||||
|
|
676
src/p_spec.cpp
676
src/p_spec.cpp
|
@ -98,7 +98,7 @@
|
|||
#include "p_setup.h"
|
||||
|
||||
#include "c_console.h"
|
||||
#include "maploader/maploader.h"
|
||||
#include "p_spec_thinkers.h"
|
||||
|
||||
static FRandom pr_playerinspecialsector ("PlayerInSpecialSector");
|
||||
|
||||
|
@ -709,25 +709,6 @@ CUSTOM_CVAR (Bool, forcewater, false, CVAR_ARCHIVE|CVAR_SERVERINFO)
|
|||
}
|
||||
}
|
||||
|
||||
class DLightTransfer : public DThinker
|
||||
{
|
||||
DECLARE_CLASS (DLightTransfer, DThinker)
|
||||
|
||||
DLightTransfer() {}
|
||||
public:
|
||||
DLightTransfer (sector_t *srcSec, int target, bool copyFloor);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick ();
|
||||
|
||||
protected:
|
||||
void DoTransfer (int level, int target, bool floor);
|
||||
|
||||
sector_t *Source;
|
||||
int TargetTag;
|
||||
bool CopyFloor;
|
||||
short LastLight;
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DLightTransfer, false, false)
|
||||
|
||||
void DLightTransfer::Serialize(FSerializer &arc)
|
||||
|
@ -795,31 +776,6 @@ void DLightTransfer::DoTransfer (int llevel, int target, bool floor)
|
|||
}
|
||||
|
||||
|
||||
class DWallLightTransfer : public DThinker
|
||||
{
|
||||
enum
|
||||
{
|
||||
WLF_SIDE1=1,
|
||||
WLF_SIDE2=2,
|
||||
WLF_NOFAKECONTRAST=4
|
||||
};
|
||||
|
||||
DECLARE_CLASS (DWallLightTransfer, DThinker)
|
||||
DWallLightTransfer() {}
|
||||
public:
|
||||
DWallLightTransfer (sector_t *srcSec, int target, uint8_t flags);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick ();
|
||||
|
||||
protected:
|
||||
void DoTransfer (short level, int target, uint8_t flags);
|
||||
|
||||
sector_t *Source;
|
||||
int TargetID;
|
||||
short LastLight;
|
||||
uint8_t Flags;
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(DWallLightTransfer, false, false)
|
||||
|
||||
void DWallLightTransfer::Serialize(FSerializer &arc)
|
||||
|
@ -900,611 +856,6 @@ void DWallLightTransfer::DoTransfer (short lightlevel, int target, uint8_t flags
|
|||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Portals
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Upper stacks go in the top sector. Lower stacks go in the bottom sector.
|
||||
|
||||
void MapLoader::SetupFloorPortal (AActor *point)
|
||||
{
|
||||
auto it = Level->GetActorIterator(NAME_LowerStackLookOnly, point->tid);
|
||||
sector_t *Sector = point->Sector;
|
||||
auto skyv = it.Next();
|
||||
if (skyv != nullptr)
|
||||
{
|
||||
skyv->target = point;
|
||||
if (Sector->GetAlpha(sector_t::floor) == 1.)
|
||||
Sector->SetAlpha(sector_t::floor, clamp(point->args[0], 0, 255) / 255.);
|
||||
|
||||
Sector->Portals[sector_t::floor] = P_GetStackPortal(skyv, sector_t::floor);
|
||||
}
|
||||
}
|
||||
|
||||
void MapLoader::SetupCeilingPortal (AActor *point)
|
||||
{
|
||||
auto it = Level->GetActorIterator(NAME_UpperStackLookOnly, point->tid);
|
||||
sector_t *Sector = point->Sector;
|
||||
auto skyv = it.Next();
|
||||
if (skyv != nullptr)
|
||||
{
|
||||
skyv->target = point;
|
||||
if (Sector->GetAlpha(sector_t::ceiling) == 1.)
|
||||
Sector->SetAlpha(sector_t::ceiling, clamp(point->args[0], 0, 255) / 255.);
|
||||
|
||||
Sector->Portals[sector_t::ceiling] = P_GetStackPortal(skyv, sector_t::ceiling);
|
||||
}
|
||||
}
|
||||
|
||||
void MapLoader::SetupPortals()
|
||||
{
|
||||
auto it = Level->GetThinkerIterator<AActor>(NAME_StackPoint);
|
||||
AActor *pt;
|
||||
TArray<AActor *> points;
|
||||
|
||||
while ((pt = it.Next()))
|
||||
{
|
||||
FName nm = pt->GetClass()->TypeName;
|
||||
if (nm == NAME_UpperStackLookOnly)
|
||||
{
|
||||
SetupFloorPortal(pt);
|
||||
}
|
||||
else if (nm == NAME_LowerStackLookOnly)
|
||||
{
|
||||
SetupCeilingPortal(pt);
|
||||
}
|
||||
pt->special1 = 0;
|
||||
points.Push(pt);
|
||||
}
|
||||
// the semantics here are incredibly lax so the final setup can only be done once all portals have been created,
|
||||
// because later stackpoints will happily overwrite info in older ones, if there are multiple links.
|
||||
for (auto &s : Level->sectorPortals)
|
||||
{
|
||||
if (s.mType == PORTS_STACKEDSECTORTHING && s.mSkybox)
|
||||
{
|
||||
for (auto &ss : Level->sectorPortals)
|
||||
{
|
||||
if (ss.mType == PORTS_STACKEDSECTORTHING && ss.mSkybox == s.mSkybox->target)
|
||||
{
|
||||
s.mPartner = unsigned((&ss) - &Level->sectorPortals[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Now we can finally set the displacement and delete the stackpoint reference.
|
||||
for (auto &s : Level->sectorPortals)
|
||||
{
|
||||
if (s.mType == PORTS_STACKEDSECTORTHING && s.mSkybox)
|
||||
{
|
||||
s.mDisplacement = s.mSkybox->Pos() - s.mSkybox->target->Pos();
|
||||
s.mSkybox = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapLoader::SetPortal(sector_t *sector, int plane, unsigned pnum, double alpha)
|
||||
{
|
||||
// plane: 0=floor, 1=ceiling, 2=both
|
||||
if (plane > 0)
|
||||
{
|
||||
if (sector->GetPortalType(sector_t::ceiling) == PORTS_SKYVIEWPOINT)
|
||||
{
|
||||
sector->Portals[sector_t::ceiling] = pnum;
|
||||
if (sector->GetAlpha(sector_t::ceiling) == 1.)
|
||||
sector->SetAlpha(sector_t::ceiling, alpha);
|
||||
|
||||
if (Level->sectorPortals[pnum].mFlags & PORTSF_SKYFLATONLY)
|
||||
sector->SetTexture(sector_t::ceiling, skyflatnum);
|
||||
}
|
||||
}
|
||||
if (plane == 2 || plane == 0)
|
||||
{
|
||||
if (sector->GetPortalType(sector_t::floor) == PORTS_SKYVIEWPOINT)
|
||||
{
|
||||
sector->Portals[sector_t::floor] = pnum;
|
||||
}
|
||||
if (sector->GetAlpha(sector_t::floor) == 1.)
|
||||
sector->SetAlpha(sector_t::floor, alpha);
|
||||
|
||||
if (Level->sectorPortals[pnum].mFlags & PORTSF_SKYFLATONLY)
|
||||
sector->SetTexture(sector_t::floor, skyflatnum);
|
||||
}
|
||||
}
|
||||
|
||||
void MapLoader::CopyPortal(int sectortag, int plane, unsigned pnum, double alpha, bool tolines)
|
||||
{
|
||||
int s;
|
||||
auto itr = Level->GetSectorTagIterator(sectortag);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
{
|
||||
SetPortal(&Level->sectors[s], plane, pnum, alpha);
|
||||
}
|
||||
|
||||
for (auto &line : Level->lines)
|
||||
{
|
||||
// Check if this portal needs to be copied to other sectors
|
||||
// This must be done here to ensure that it gets done only after the portal is set up
|
||||
if (line.special == Sector_SetPortal &&
|
||||
line.args[1] == 1 &&
|
||||
(line.args[2] == plane || line.args[2] == 3) &&
|
||||
line.args[3] == sectortag)
|
||||
{
|
||||
if (line.args[0] == 0)
|
||||
{
|
||||
SetPortal(line.frontsector, plane, pnum, alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto itr = Level->GetSectorTagIterator(line.args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
{
|
||||
SetPortal(&Level->sectors[s], plane, pnum, alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tolines && line.special == Sector_SetPortal &&
|
||||
line.args[1] == 5 &&
|
||||
line.args[3] == sectortag)
|
||||
{
|
||||
if (line.args[0] == 0)
|
||||
{
|
||||
line.portaltransferred = pnum;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto itr = Level->GetLineIdIterator(line.args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
{
|
||||
Level->lines[s].portaltransferred = pnum;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MapLoader::SpawnPortal(line_t *line, int sectortag, int plane, int bytealpha, int linked)
|
||||
{
|
||||
if (plane < 0 || plane > 2 || (linked && plane == 2)) return;
|
||||
for (auto &oline : Level->lines)
|
||||
{
|
||||
// We must look for the reference line with a linear search unless we want to waste the line ID for it
|
||||
// which is not a good idea.
|
||||
if (oline.special == Sector_SetPortal &&
|
||||
oline.args[0] == sectortag &&
|
||||
oline.args[1] == linked &&
|
||||
oline.args[2] == plane &&
|
||||
oline.args[3] == 1)
|
||||
{
|
||||
// beware of overflows.
|
||||
DVector2 pos1 = line->v1->fPos() + line->Delta() / 2;
|
||||
DVector2 pos2 = oline.v1->fPos() + oline.Delta() / 2;
|
||||
unsigned pnum = P_GetPortal(linked ? PORTS_LINKEDPORTAL : PORTS_PORTAL, plane, line->frontsector, oline.frontsector, pos2 - pos1);
|
||||
CopyPortal(sectortag, plane, pnum, bytealpha / 255., false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This searches the viewpoint's sector
|
||||
// for a skybox line special, gets its tag and transfers the skybox to all tagged sectors.
|
||||
void MapLoader::SpawnSkybox(AActor *origin)
|
||||
{
|
||||
sector_t *Sector = origin->Sector;
|
||||
if (Sector == NULL)
|
||||
{
|
||||
Printf("Sector not initialized for SkyCamCompat\n");
|
||||
origin->Sector = Sector = P_PointInSector(origin->Pos());
|
||||
}
|
||||
if (Sector)
|
||||
{
|
||||
for(auto refline : Sector->Lines)
|
||||
{
|
||||
if (refline->special == Sector_SetPortal && refline->args[1] == 2)
|
||||
{
|
||||
// We found the setup linedef for this skybox, so let's use it for our init.
|
||||
unsigned pnum = P_GetSkyboxPortal(origin);
|
||||
CopyPortal(refline->args[0], refline->args[2], pnum, 0, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// P_SetSectorDamage
|
||||
//
|
||||
// Sets damage properties for one sector. Allows combination of original specials with explicit use of the damage properties
|
||||
//
|
||||
|
||||
static void SetupSectorDamage(sector_t *sector, int damage, int interval, int leakchance, FName type, int flags)
|
||||
{
|
||||
// Only set if damage is not yet initialized. This ensures that UDMF takes precedence over sector specials.
|
||||
if (sector->damageamount == 0)
|
||||
{
|
||||
sector->damageamount = damage;
|
||||
sector->damageinterval = MAX(1, interval);
|
||||
sector->leakydamage = leakchance;
|
||||
sector->damagetype = type;
|
||||
sector->Flags = (sector->Flags & ~SECF_DAMAGEFLAGS) | (flags & SECF_DAMAGEFLAGS);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_InitSectorSpecial
|
||||
//
|
||||
// Sets up everything derived from 'sector->special' for one sector
|
||||
// ('fromload' is necessary to allow conversion upon savegame load.)
|
||||
//
|
||||
|
||||
void MapLoader::InitSectorSpecial(sector_t *sector, int special)
|
||||
{
|
||||
// [RH] All secret sectors are marked with a BOOM-ish bitfield
|
||||
if (sector->special & SECRET_MASK)
|
||||
{
|
||||
sector->Flags |= SECF_SECRET | SECF_WASSECRET;
|
||||
Level->total_secrets++;
|
||||
}
|
||||
if (sector->special & FRICTION_MASK)
|
||||
{
|
||||
sector->Flags |= SECF_FRICTION;
|
||||
}
|
||||
if (sector->special & PUSH_MASK)
|
||||
{
|
||||
sector->Flags |= SECF_PUSH;
|
||||
}
|
||||
if ((sector->special & DAMAGE_MASK) == 0x100)
|
||||
{
|
||||
SetupSectorDamage(sector, 5, 32, 0, NAME_Fire, 0);
|
||||
}
|
||||
else if ((sector->special & DAMAGE_MASK) == 0x200)
|
||||
{
|
||||
SetupSectorDamage(sector, 10, 32, 0, NAME_Slime, 0);
|
||||
}
|
||||
else if ((sector->special & DAMAGE_MASK) == 0x300)
|
||||
{
|
||||
SetupSectorDamage(sector, 20, 32, 5, NAME_Slime, 0);
|
||||
}
|
||||
sector->special &= 0xff;
|
||||
|
||||
// [RH] Normal DOOM special or BOOM specialized?
|
||||
bool keepspecial = false;
|
||||
SpawnLights(sector);
|
||||
switch (sector->special)
|
||||
{
|
||||
case dLight_Strobe_Hurt:
|
||||
SetupSectorDamage(sector, 20, 32, 5, NAME_Slime, 0);
|
||||
break;
|
||||
|
||||
case dDamage_Hellslime:
|
||||
SetupSectorDamage(sector, 10, 32, 0, NAME_Slime, 0);
|
||||
break;
|
||||
|
||||
case dDamage_Nukage:
|
||||
SetupSectorDamage(sector, 5, 32, 0, NAME_Slime, 0);
|
||||
break;
|
||||
|
||||
case dSector_DoorCloseIn30:
|
||||
Create<DDoor>(sector, DDoor::doorWaitClose, 2, 0, 0, 30 * TICRATE);
|
||||
break;
|
||||
|
||||
case dDamage_End:
|
||||
SetupSectorDamage(sector, 20, 32, 256, NAME_None, SECF_ENDGODMODE|SECF_ENDLEVEL);
|
||||
break;
|
||||
|
||||
case dSector_DoorRaiseIn5Mins:
|
||||
Create<DDoor> (sector, DDoor::doorWaitRaise, 2, TICRATE*30/7, 0, 5*60*TICRATE);
|
||||
break;
|
||||
|
||||
case dFriction_Low:
|
||||
sector->friction = FRICTION_LOW;
|
||||
sector->movefactor = 0x269/65536.;
|
||||
sector->Flags |= SECF_FRICTION;
|
||||
break;
|
||||
|
||||
case dDamage_SuperHellslime:
|
||||
SetupSectorDamage(sector, 20, 32, 5, NAME_Slime, 0);
|
||||
break;
|
||||
|
||||
case dDamage_LavaWimpy:
|
||||
SetupSectorDamage(sector, 5, 16, 256, NAME_Fire, SECF_DMGTERRAINFX);
|
||||
break;
|
||||
|
||||
case dDamage_LavaHefty:
|
||||
SetupSectorDamage(sector, 8, 16, 256, NAME_Fire, SECF_DMGTERRAINFX);
|
||||
break;
|
||||
|
||||
case dScroll_EastLavaDamage:
|
||||
SetupSectorDamage(sector, 5, 16, 256, NAME_Fire, SECF_DMGTERRAINFX);
|
||||
CreateScroller(EScroll::sc_floor, -4., 0, sector, 0);
|
||||
keepspecial = true;
|
||||
break;
|
||||
|
||||
case hDamage_Sludge:
|
||||
SetupSectorDamage(sector, 4, 32, 0, NAME_Slime, 0);
|
||||
break;
|
||||
|
||||
case sLight_Strobe_Hurt:
|
||||
SetupSectorDamage(sector, 5, 32, 0, NAME_Slime, 0);
|
||||
break;
|
||||
|
||||
case sDamage_Hellslime:
|
||||
SetupSectorDamage(sector, 2, 32, 0, NAME_Slime, SECF_HAZARD);
|
||||
break;
|
||||
|
||||
case Damage_InstantDeath:
|
||||
// Strife's instant death sector
|
||||
SetupSectorDamage(sector, TELEFRAG_DAMAGE, 1, 256, NAME_InstantDeath, 0);
|
||||
break;
|
||||
|
||||
case sDamage_SuperHellslime:
|
||||
SetupSectorDamage(sector, 4, 32, 0, NAME_Slime, SECF_HAZARD);
|
||||
break;
|
||||
|
||||
case Sector_Hidden:
|
||||
sector->MoreFlags |= SECMF_HIDDEN;
|
||||
break;
|
||||
|
||||
case Sector_Heal:
|
||||
// CoD's healing sector
|
||||
SetupSectorDamage(sector, -1, 32, 0, NAME_None, 0);
|
||||
break;
|
||||
|
||||
case Sky2:
|
||||
sector->sky = PL_SKYFLAT;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (sector->special >= Scroll_North_Slow && sector->special <= Scroll_SouthWest_Fast)
|
||||
{ // Hexen scroll special
|
||||
static const int8_t hexenScrollies[24][2] =
|
||||
{
|
||||
{ 0, 1 }, { 0, 2 }, { 0, 4 },
|
||||
{ -1, 0 }, { -2, 0 }, { -4, 0 },
|
||||
{ 0, -1 }, { 0, -2 }, { 0, -4 },
|
||||
{ 1, 0 }, { 2, 0 }, { 4, 0 },
|
||||
{ 1, 1 }, { 2, 2 }, { 4, 4 },
|
||||
{ -1, 1 }, { -2, 2 }, { -4, 4 },
|
||||
{ -1, -1 }, { -2, -2 }, { -4, -4 },
|
||||
{ 1, -1 }, { 2, -2 }, { 4, -4 }
|
||||
};
|
||||
|
||||
|
||||
int i = sector->special - Scroll_North_Slow;
|
||||
double dx = hexenScrollies[i][0] / 2.;
|
||||
double dy = hexenScrollies[i][1] / 2.;
|
||||
CreateScroller(EScroll::sc_floor, dx, dy, sector, 0);
|
||||
}
|
||||
else if (sector->special >= Carry_East5 && sector->special <= Carry_East35)
|
||||
{
|
||||
// Heretic scroll special
|
||||
// Only east scrollers also scroll the texture
|
||||
CreateScroller(EScroll::sc_floor, -0.5 * (1 << ((sector->special & 0xff) - Carry_East5)), 0, sector, 0);
|
||||
}
|
||||
keepspecial = true;
|
||||
break;
|
||||
}
|
||||
if (!keepspecial) sector->special = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// P_SpawnSpecials
|
||||
//
|
||||
// After the map has been loaded, scan for specials that spawn thinkers
|
||||
//
|
||||
|
||||
void MapLoader::SpawnSpecials ()
|
||||
{
|
||||
SetupPortals();
|
||||
|
||||
for (auto &sec : Level->sectors)
|
||||
{
|
||||
if (sec.special == 0)
|
||||
continue;
|
||||
|
||||
InitSectorSpecial(&sec, sec.special);
|
||||
}
|
||||
|
||||
ProcessEDSectors();
|
||||
|
||||
// Init other misc stuff
|
||||
|
||||
SpawnScrollers(); // killough 3/7/98: Add generalized scrollers
|
||||
SpawnFriction(); // phares 3/12/98: New friction model using linedefs
|
||||
SpawnPushers(); // phares 3/20/98: New pusher model using linedefs
|
||||
|
||||
auto it2 = Level->GetThinkerIterator<AActor>(NAME_SkyCamCompat);
|
||||
AActor *pt2;
|
||||
while ((pt2 = it2.Next()))
|
||||
{
|
||||
SpawnSkybox(pt2);
|
||||
}
|
||||
|
||||
for (auto &line : Level->lines)
|
||||
{
|
||||
switch (line.special)
|
||||
{
|
||||
int s;
|
||||
sector_t *sec;
|
||||
|
||||
// killough 3/7/98:
|
||||
// support for drawn heights coming from different sector
|
||||
case Transfer_Heights:
|
||||
{
|
||||
sec = line.frontsector;
|
||||
|
||||
if (line.args[1] & 2)
|
||||
{
|
||||
sec->MoreFlags |= SECMF_FAKEFLOORONLY;
|
||||
}
|
||||
if (line.args[1] & 4)
|
||||
{
|
||||
sec->MoreFlags |= SECMF_CLIPFAKEPLANES;
|
||||
}
|
||||
if (line.args[1] & 8)
|
||||
{
|
||||
sec->MoreFlags |= SECMF_UNDERWATER;
|
||||
}
|
||||
else if (forcewater)
|
||||
{
|
||||
sec->MoreFlags |= SECMF_FORCEDUNDERWATER;
|
||||
}
|
||||
if (line.args[1] & 16)
|
||||
{
|
||||
sec->MoreFlags |= SECMF_IGNOREHEIGHTSEC;
|
||||
}
|
||||
else Level->HasHeightSecs = true;
|
||||
if (line.args[1] & 32)
|
||||
{
|
||||
sec->MoreFlags |= SECMF_NOFAKELIGHT;
|
||||
}
|
||||
auto itr = Level->GetSectorTagIterator(line.args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
{
|
||||
Level->sectors[s].heightsec = sec;
|
||||
sec->e->FakeFloor.Sectors.Push(&Level->sectors[s]);
|
||||
Level->sectors[s].MoreFlags |= (sec->MoreFlags & SECMF_IGNOREHEIGHTSEC); // copy this to the destination sector for easier checking.
|
||||
Level->sectors[s].AdjustFloorClip();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// killough 3/16/98: Add support for setting
|
||||
// floor lighting independently (e.g. lava)
|
||||
case Transfer_FloorLight:
|
||||
Create<DLightTransfer> (line.frontsector, line.args[0], true);
|
||||
break;
|
||||
|
||||
// killough 4/11/98: Add support for setting
|
||||
// ceiling lighting independently
|
||||
case Transfer_CeilingLight:
|
||||
Create<DLightTransfer> (line.frontsector, line.args[0], false);
|
||||
break;
|
||||
|
||||
// [Graf Zahl] Add support for setting lighting
|
||||
// per wall independently
|
||||
case Transfer_WallLight:
|
||||
Create<DWallLightTransfer> (line.frontsector, line.args[0], line.args[1]);
|
||||
break;
|
||||
|
||||
case Sector_Attach3dMidtex:
|
||||
P_Attach3dMidtexLinesToSector(line.frontsector, line.args[0], line.args[1], !!line.args[2]);
|
||||
break;
|
||||
|
||||
case Sector_SetLink:
|
||||
if (line.args[0] == 0)
|
||||
{
|
||||
P_AddSectorLinks(line.frontsector, line.args[1], line.args[2], line.args[3]);
|
||||
}
|
||||
break;
|
||||
|
||||
case Sector_SetPortal:
|
||||
// arg 0 = sector tag
|
||||
// arg 1 = type
|
||||
// - 0: normal (handled here)
|
||||
// - 1: copy (handled by the portal they copy)
|
||||
// - 2: EE-style skybox (handled by the camera object)
|
||||
// - 3: EE-style flat portal (GZDoom HW renderer only for now)
|
||||
// - 4: EE-style horizon portal (GZDoom HW renderer only for now)
|
||||
// - 5: copy portal to line (GZDoom HW renderer only for now)
|
||||
// - 6: linked portal
|
||||
// other values reserved for later use
|
||||
// arg 2 = 0:floor, 1:ceiling, 2:both
|
||||
// arg 3 = 0: anchor, 1: reference line
|
||||
// arg 4 = for the anchor only: alpha
|
||||
if ((line.args[1] == 0 || line.args[1] == 6) && line.args[3] == 0)
|
||||
{
|
||||
SpawnPortal(&line, line.args[0], line.args[2], line.args[4], line.args[1]);
|
||||
}
|
||||
else if (line.args[1] == 3 || line.args[1] == 4)
|
||||
{
|
||||
unsigned pnum = P_GetPortal(line.args[1] == 3 ? PORTS_PLANE : PORTS_HORIZON, line.args[2], line.frontsector, NULL, { 0,0 });
|
||||
CopyPortal(line.args[0], line.args[2], pnum, 0, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case Line_SetPortal:
|
||||
P_SpawnLinePortal(&line);
|
||||
break;
|
||||
|
||||
// [RH] ZDoom Static_Init settings
|
||||
case Static_Init:
|
||||
switch (line.args[1])
|
||||
{
|
||||
case Init_Gravity:
|
||||
{
|
||||
double grav = line.Delta().Length() / 100.;
|
||||
auto itr = Level->GetSectorTagIterator(line.args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
Level->sectors[s].gravity = grav;
|
||||
}
|
||||
break;
|
||||
|
||||
//case Init_Color:
|
||||
// handled in P_LoadSideDefs2()
|
||||
|
||||
case Init_Damage:
|
||||
{
|
||||
int damage = int(line.Delta().Length());
|
||||
auto itr = Level->GetSectorTagIterator(line.args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
{
|
||||
sector_t *sec = &Level->sectors[s];
|
||||
sec->damageamount = damage;
|
||||
sec->damagetype = NAME_None;
|
||||
if (sec->damageamount < 20)
|
||||
{
|
||||
sec->leakydamage = 0;
|
||||
sec->damageinterval = 32;
|
||||
}
|
||||
else if (sec->damageamount < 50)
|
||||
{
|
||||
sec->leakydamage = 5;
|
||||
sec->damageinterval = 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
sec->leakydamage = 256;
|
||||
sec->damageinterval = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Init_SectorLink:
|
||||
if (line.args[3] == 0)
|
||||
P_AddSectorLinksByID(line.frontsector, line.args[0], line.args[2]);
|
||||
break;
|
||||
|
||||
// killough 10/98:
|
||||
//
|
||||
// Support for sky textures being transferred from sidedefs.
|
||||
// Allows scrolling and other effects (but if scrolling is
|
||||
// used, then the same sector tag needs to be used for the
|
||||
// sky sector, the sky-transfer linedef, and the scroll-effect
|
||||
// linedef). Still requires user to use F_SKY1 for the floor
|
||||
// or ceiling texture, to distinguish floor and ceiling sky.
|
||||
|
||||
case Init_TransferSky:
|
||||
{
|
||||
auto itr = Level->GetSectorTagIterator(line.args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
Level->sectors[s].sky = (line.Index() + 1) | PL_SKYFLAT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// [RH] Start running any open scripts on this map
|
||||
Level->Behaviors.StartTypedScripts (SCRIPT_Open, NULL, false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// FRICTION EFFECTS
|
||||
|
@ -1558,31 +909,6 @@ void MapLoader::SpawnSpecials ()
|
|||
//
|
||||
// Initialize the sectors where friction is increased or decreased
|
||||
|
||||
void MapLoader::SpawnFriction()
|
||||
{
|
||||
line_t *l = &Level->lines[0];
|
||||
|
||||
for (unsigned i = 0 ; i < Level->lines.Size() ; i++,l++)
|
||||
{
|
||||
if (l->special == Sector_SetFriction)
|
||||
{
|
||||
int length;
|
||||
|
||||
if (l->args[1])
|
||||
{ // [RH] Allow setting friction amount from parameter
|
||||
length = l->args[1] <= 200 ? l->args[1] : 200;
|
||||
}
|
||||
else
|
||||
{
|
||||
length = int(l->Delta().Length());
|
||||
}
|
||||
|
||||
P_SetSectorFriction (Level, l->args[0], length, false);
|
||||
l->special = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void P_SetSectorFriction (FLevelLocals *Level, int tag, int amount, bool alterFlag)
|
||||
{
|
||||
int s;
|
||||
|
|
253
src/p_spec_thinkers.h
Normal file
253
src/p_spec_thinkers.h
Normal file
|
@ -0,0 +1,253 @@
|
|||
#pragma once
|
||||
|
||||
#include "p_spec.h"
|
||||
#include "r_defs.h"
|
||||
|
||||
class DLightTransfer : public DThinker
|
||||
{
|
||||
DECLARE_CLASS (DLightTransfer, DThinker)
|
||||
|
||||
DLightTransfer() {}
|
||||
public:
|
||||
DLightTransfer (sector_t *srcSec, int target, bool copyFloor);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick ();
|
||||
|
||||
protected:
|
||||
void DoTransfer (int level, int target, bool floor);
|
||||
|
||||
sector_t *Source;
|
||||
int TargetTag;
|
||||
bool CopyFloor;
|
||||
short LastLight;
|
||||
};
|
||||
|
||||
class DWallLightTransfer : public DThinker
|
||||
{
|
||||
enum
|
||||
{
|
||||
WLF_SIDE1=1,
|
||||
WLF_SIDE2=2,
|
||||
WLF_NOFAKECONTRAST=4
|
||||
};
|
||||
|
||||
DECLARE_CLASS (DWallLightTransfer, DThinker)
|
||||
DWallLightTransfer() {}
|
||||
public:
|
||||
DWallLightTransfer (sector_t *srcSec, int target, uint8_t flags);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick ();
|
||||
|
||||
protected:
|
||||
void DoTransfer (short level, int target, uint8_t flags);
|
||||
|
||||
sector_t *Source;
|
||||
int TargetID;
|
||||
short LastLight;
|
||||
uint8_t Flags;
|
||||
};
|
||||
|
||||
|
||||
class DFireFlicker : public DLighting
|
||||
{
|
||||
DECLARE_CLASS(DFireFlicker, DLighting)
|
||||
public:
|
||||
DFireFlicker(sector_t *sector);
|
||||
DFireFlicker(sector_t *sector, int upper, int lower);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick();
|
||||
protected:
|
||||
int m_Count;
|
||||
int m_MaxLight;
|
||||
int m_MinLight;
|
||||
private:
|
||||
DFireFlicker();
|
||||
};
|
||||
|
||||
class DFlicker : public DLighting
|
||||
{
|
||||
DECLARE_CLASS(DFlicker, DLighting)
|
||||
public:
|
||||
DFlicker(sector_t *sector, int upper, int lower);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick();
|
||||
protected:
|
||||
int m_Count;
|
||||
int m_MaxLight;
|
||||
int m_MinLight;
|
||||
private:
|
||||
DFlicker();
|
||||
};
|
||||
|
||||
class DLightFlash : public DLighting
|
||||
{
|
||||
DECLARE_CLASS(DLightFlash, DLighting)
|
||||
public:
|
||||
DLightFlash(sector_t *sector);
|
||||
DLightFlash(sector_t *sector, int min, int max);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick();
|
||||
protected:
|
||||
int m_Count;
|
||||
int m_MaxLight;
|
||||
int m_MinLight;
|
||||
int m_MaxTime;
|
||||
int m_MinTime;
|
||||
private:
|
||||
DLightFlash();
|
||||
};
|
||||
|
||||
class DStrobe : public DLighting
|
||||
{
|
||||
DECLARE_CLASS(DStrobe, DLighting)
|
||||
public:
|
||||
DStrobe(sector_t *sector, int utics, int ltics, bool inSync);
|
||||
DStrobe(sector_t *sector, int upper, int lower, int utics, int ltics);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick();
|
||||
protected:
|
||||
int m_Count;
|
||||
int m_MinLight;
|
||||
int m_MaxLight;
|
||||
int m_DarkTime;
|
||||
int m_BrightTime;
|
||||
private:
|
||||
DStrobe();
|
||||
};
|
||||
|
||||
class DGlow : public DLighting
|
||||
{
|
||||
DECLARE_CLASS(DGlow, DLighting)
|
||||
public:
|
||||
DGlow(sector_t *sector);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick();
|
||||
protected:
|
||||
int m_MinLight;
|
||||
int m_MaxLight;
|
||||
int m_Direction;
|
||||
private:
|
||||
DGlow();
|
||||
};
|
||||
|
||||
// [RH] Glow from Light_Glow and Light_Fade specials
|
||||
class DGlow2 : public DLighting
|
||||
{
|
||||
DECLARE_CLASS(DGlow2, DLighting)
|
||||
public:
|
||||
DGlow2(sector_t *sector, int start, int end, int tics, bool oneshot);
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick();
|
||||
protected:
|
||||
int m_Start;
|
||||
int m_End;
|
||||
int m_MaxTics;
|
||||
int m_Tics;
|
||||
bool m_OneShot;
|
||||
private:
|
||||
DGlow2();
|
||||
};
|
||||
|
||||
// [RH] Phased light thinker
|
||||
class DPhased : public DLighting
|
||||
{
|
||||
DECLARE_CLASS(DPhased, DLighting)
|
||||
public:
|
||||
DPhased(sector_t *sector);
|
||||
DPhased(sector_t *sector, int baselevel, int phase);
|
||||
// These are for internal use only but the Create template needs access to them.
|
||||
DPhased();
|
||||
DPhased(sector_t *sector, int baselevel);
|
||||
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick();
|
||||
protected:
|
||||
uint8_t m_BaseLevel;
|
||||
uint8_t m_Phase;
|
||||
private:
|
||||
int PhaseHelper(sector_t *sector, int index, int light, sector_t *prev);
|
||||
};
|
||||
|
||||
// phares 3/20/98: added new model of Pushers for push/pull effects
|
||||
|
||||
class DPusher : public DThinker
|
||||
{
|
||||
DECLARE_CLASS (DPusher, DThinker)
|
||||
HAS_OBJECT_POINTERS
|
||||
public:
|
||||
enum EPusher
|
||||
{
|
||||
p_push,
|
||||
p_pull,
|
||||
p_wind,
|
||||
p_current
|
||||
};
|
||||
|
||||
DPusher ();
|
||||
DPusher (EPusher type, line_t *l, int magnitude, int angle, AActor *source, int affectee);
|
||||
void Serialize(FSerializer &arc);
|
||||
int CheckForSectorMatch (EPusher type, int tag);
|
||||
void ChangeValues (int magnitude, int angle)
|
||||
{
|
||||
DAngle ang = angle * (360. / 256.);
|
||||
m_PushVec = ang.ToVector(magnitude);
|
||||
m_Magnitude = magnitude;
|
||||
}
|
||||
|
||||
void Tick ();
|
||||
|
||||
protected:
|
||||
EPusher m_Type;
|
||||
TObjPtr<AActor*> m_Source;// Point source if point pusher
|
||||
DVector2 m_PushVec;
|
||||
double m_Magnitude; // Vector strength for point pusher
|
||||
double m_Radius; // Effective radius for point pusher
|
||||
int m_Affectee; // Number of affected sector
|
||||
|
||||
friend bool PIT_PushThing (AActor *thing);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// killough 3/7/98: Add generalized scroll effects
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class DScroller : public DThinker
|
||||
{
|
||||
DECLARE_CLASS (DScroller, DThinker)
|
||||
HAS_OBJECT_POINTERS
|
||||
public:
|
||||
|
||||
DScroller(EScroll type, double dx, double dy, sector_t *control, sector_t *sec, side_t *side, int accel, EScrollPos scrollpos = EScrollPos::scw_all);
|
||||
DScroller (double dx, double dy, const line_t *l, sector_t *control, int accel, EScrollPos scrollpos = EScrollPos::scw_all);
|
||||
void OnDestroy() override;
|
||||
|
||||
void Serialize(FSerializer &arc);
|
||||
void Tick ();
|
||||
|
||||
bool AffectsWall (side_t * wall) const { return m_Side == wall; }
|
||||
side_t *GetWall () const { return m_Side; }
|
||||
sector_t *GetSector() const { return m_Sector; }
|
||||
void SetRate (double dx, double dy) { m_dx = dx; m_dy = dy; }
|
||||
bool IsType (EScroll type) const { return type == m_Type; }
|
||||
EScrollPos GetScrollParts() const { return m_Parts; }
|
||||
|
||||
protected:
|
||||
EScroll m_Type; // Type of scroll effect
|
||||
double m_dx, m_dy; // (dx,dy) scroll speeds
|
||||
sector_t *m_Sector; // Affected sector
|
||||
side_t *m_Side; // ... or side
|
||||
sector_t *m_Controller; // Control sector (nullptr if none) used to control scrolling
|
||||
double m_LastHeight; // Last known height of control sector
|
||||
double m_vdx, m_vdy; // Accumulated velocity if accelerative
|
||||
int m_Accel; // Whether it's accelerative
|
||||
EScrollPos m_Parts; // Which parts of a sidedef are being scrolled?
|
||||
TObjPtr<DInterpolation*> m_Interpolations[3];
|
||||
|
||||
private:
|
||||
DScroller ()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in a new issue