mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 14:51:40 +00:00
- added the EE-Extradata parser I wrote for GZDoom so I can use the Vaporware demo map for testing portal stuff.
This commit is contained in:
parent
1201ad0366
commit
e88901f4b7
12 changed files with 980 additions and 109 deletions
|
@ -901,6 +901,7 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
|
|||
doomstat.cpp
|
||||
dsectoreffect.cpp
|
||||
dthinker.cpp
|
||||
edata.cpp
|
||||
f_wipe.cpp
|
||||
farchive.cpp
|
||||
files.cpp
|
||||
|
|
784
src/edata.cpp
Normal file
784
src/edata.cpp
Normal file
|
@ -0,0 +1,784 @@
|
|||
/*
|
||||
** edata.cpp
|
||||
** Parses Eternity Extradata lumps
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2015 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
** This code was written based on the documentation in the Eternity Wiki
|
||||
**
|
||||
*/
|
||||
|
||||
#include "w_wad.h"
|
||||
#include "m_argv.h"
|
||||
#include "zstring.h"
|
||||
#include "sc_man.h"
|
||||
#include "g_level.h"
|
||||
#include "doomdata.h"
|
||||
#include "r_defs.h"
|
||||
#include "info.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "p_setup.h"
|
||||
#include "p_tags.h"
|
||||
#include "p_terrain.h"
|
||||
#include "v_palette.h"
|
||||
#include "p_acs.h"
|
||||
#include "r_data/colormaps.h"
|
||||
|
||||
|
||||
struct FEDOptions : public FOptionalMapinfoData
|
||||
{
|
||||
FEDOptions()
|
||||
{
|
||||
identifier = "EData";
|
||||
}
|
||||
virtual FOptionalMapinfoData *Clone() const
|
||||
{
|
||||
FEDOptions *newopt = new FEDOptions;
|
||||
newopt->identifier = identifier;
|
||||
newopt->EDName = EDName;
|
||||
newopt->acsName = acsName;
|
||||
return newopt;
|
||||
}
|
||||
FString EDName;
|
||||
FString acsName;
|
||||
};
|
||||
|
||||
DEFINE_MAP_OPTION(edata, false)
|
||||
{
|
||||
FEDOptions *opt = info->GetOptData<FEDOptions>("EData");
|
||||
|
||||
parse.ParseAssign();
|
||||
parse.sc.MustGetString();
|
||||
opt->EDName = parse.sc.String;
|
||||
}
|
||||
|
||||
DEFINE_MAP_OPTION(loadacs, false)
|
||||
{
|
||||
FEDOptions *opt = info->GetOptData<FEDOptions>("EData");
|
||||
|
||||
parse.ParseAssign();
|
||||
parse.sc.MustGetString();
|
||||
opt->acsName = parse.sc.String;
|
||||
}
|
||||
|
||||
struct EDMapthing
|
||||
{
|
||||
int recordnum;
|
||||
int tid;
|
||||
int type;
|
||||
fixed_t height;
|
||||
int args[5];
|
||||
WORD skillfilter;
|
||||
DWORD flags;
|
||||
};
|
||||
|
||||
struct EDLinedef
|
||||
{
|
||||
int recordnum;
|
||||
int special;
|
||||
int tag;
|
||||
int id;
|
||||
int args[5];
|
||||
fixed_t alpha;
|
||||
DWORD flags;
|
||||
DWORD activation;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct EDSector
|
||||
{
|
||||
int recordnum;
|
||||
|
||||
DWORD flags;
|
||||
DWORD flagsRemove;
|
||||
DWORD flagsAdd;
|
||||
|
||||
int damageamount;
|
||||
int damageinterval;
|
||||
FNameNoInit damagetype;
|
||||
BYTE leaky;
|
||||
BYTE leakyadd;
|
||||
BYTE leakyremove;
|
||||
int floorterrain;
|
||||
int ceilingterrain;
|
||||
|
||||
DWORD color;
|
||||
|
||||
DWORD damageflags;
|
||||
DWORD damageflagsAdd;
|
||||
DWORD damageflagsRemove;
|
||||
|
||||
bool flagsSet;
|
||||
bool damageflagsSet;
|
||||
bool colorSet;
|
||||
|
||||
// colormaptop//bottom cannot be used because ZDoom has no corresponding properties.
|
||||
|
||||
FTransform planexform[2];
|
||||
DWORD portalflags[2];
|
||||
fixed_t overlayalpha[2];
|
||||
};
|
||||
|
||||
static FString EDMap;
|
||||
static TMap<int, EDLinedef> EDLines;
|
||||
static TMap<int, EDSector> EDSectors;
|
||||
static TMap<int, EDMapthing> EDThings;
|
||||
|
||||
|
||||
static void parseLinedef(FScanner &sc)
|
||||
{
|
||||
EDLinedef ld;
|
||||
bool argsset = false;
|
||||
|
||||
memset(&ld, 0, sizeof(ld));
|
||||
ld.alpha = FRACUNIT;
|
||||
|
||||
sc.MustGetStringName("{");
|
||||
while (!sc.CheckString("}"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("recordnum"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetNumber();
|
||||
ld.recordnum = sc.Number;
|
||||
}
|
||||
else if (sc.Compare("tag"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetNumber();
|
||||
ld.tag = sc.Number;
|
||||
}
|
||||
else if (sc.Compare("id"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetNumber();
|
||||
ld.id = sc.Number;
|
||||
}
|
||||
else if (sc.Compare("special"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
if (sc.CheckNumber())
|
||||
{
|
||||
// Oh joy, this is going to be fun...
|
||||
// Here we cannot do anything because we need the tag to make this work.
|
||||
// For now just store a negative number and resolve this later.
|
||||
ld.special = -sc.Number;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.MustGetString();
|
||||
ld.special = P_FindLineSpecial(sc.String);
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("args"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetStringName("{");
|
||||
int c = 0;
|
||||
while (true)
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
ld.args[c++] = sc.Number;
|
||||
if (sc.CheckString("}")) break;
|
||||
sc.MustGetStringName(",");
|
||||
}
|
||||
argsset = true;
|
||||
}
|
||||
else if (sc.Compare("alpha"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetFloat();
|
||||
ld.alpha = FLOAT2FIXED(sc.Float);
|
||||
}
|
||||
else if (sc.Compare("extflags"))
|
||||
{
|
||||
// these are needed to build the proper activation mask out of the possible flags which do not match ZDoom 1:1.
|
||||
DWORD actmethod = 0;
|
||||
DWORD acttype = 0;
|
||||
do
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetString();
|
||||
for (const char *tok = strtok(sc.String, ",+ \t"); tok != NULL; tok = strtok(NULL, ",+ \t"))
|
||||
{
|
||||
if (!stricmp(tok, "USE")) actmethod |= SPAC_Use | SPAC_MUse;
|
||||
else if (!stricmp(tok, "CROSS")) actmethod |= SPAC_Cross | SPAC_MCross | SPAC_PCross;
|
||||
else if (!stricmp(tok, "IMPACT")) ld.activation |= SPAC_Impact;
|
||||
else if (!stricmp(tok, "PUSH")) actmethod |= SPAC_Push;
|
||||
else if (!stricmp(tok, "PLAYER")) acttype |= SPAC_Use | SPAC_Cross | SPAC_Push;
|
||||
else if (!stricmp(tok, "MONSTER")) acttype |= SPAC_MUse | SPAC_MCross | SPAC_MPush;
|
||||
else if (!stricmp(tok, "MISSILE")) acttype |= SPAC_PCross;
|
||||
else if (!stricmp(tok, "REPEAT")) ld.flags |= ML_REPEAT_SPECIAL;
|
||||
else if (!stricmp(tok, "1SONLY")) ld.flags |= ML_FIRSTSIDEONLY;
|
||||
else if (!stricmp(tok, "ADDITIVE")) ld.flags |= ML_ADDTRANS;
|
||||
else if (!stricmp(tok, "BLOCKALL")) ld.flags |= ML_BLOCKEVERYTHING;
|
||||
else if (!stricmp(tok, "ZONEBOUNDARY")) ld.flags |= ML_ZONEBOUNDARY;
|
||||
else if (!stricmp(tok, "CLIPMIDTEX")) ld.flags |= ML_CLIP_MIDTEX;
|
||||
else sc.ScriptError("Unknown option '%s'", tok);
|
||||
}
|
||||
} while (sc.CheckString("|")); // Unquoted strings with '|' separator - parse as a separate string in the loop.
|
||||
|
||||
// and finally we must mask in the activation method
|
||||
ld.activation |= (actmethod & acttype);
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Unknown property '%s'", sc.String);
|
||||
}
|
||||
}
|
||||
if (ld.tag == 0) ld.tag = ld.id; // urgh...
|
||||
if (ld.special < 0) // translate numeric specials.
|
||||
{
|
||||
line_t line;
|
||||
maplinedef_t mld;
|
||||
mld.special = -ld.special;
|
||||
mld.tag = ld.tag;
|
||||
P_TranslateLineDef(&line, &mld);
|
||||
ld.special = line.special;
|
||||
ld.activation = line.activation;
|
||||
ld.flags = (ld.flags & ~(ML_REPEAT_SPECIAL | ML_FIRSTSIDEONLY)) | (line.flags & (ML_REPEAT_SPECIAL | ML_FIRSTSIDEONLY));
|
||||
if (!argsset) memcpy(ld.args, line.args, sizeof(ld.args));
|
||||
}
|
||||
EDLines[ld.recordnum] = ld;
|
||||
}
|
||||
|
||||
static void parseSector(FScanner &sc)
|
||||
{
|
||||
EDSector sec;
|
||||
|
||||
memset(&sec, 0, sizeof(sec));
|
||||
sec.overlayalpha[sector_t::floor] = sec.overlayalpha[sector_t::ceiling] = FRACUNIT;
|
||||
sec.floorterrain = sec.ceilingterrain = -1;
|
||||
|
||||
sc.MustGetStringName("{");
|
||||
while (!sc.CheckString("}"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("recordnum"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetNumber();
|
||||
sec.recordnum = sc.Number;
|
||||
}
|
||||
else if (sc.Compare("flags"))
|
||||
{
|
||||
DWORD *flagvar = NULL;
|
||||
if (sc.CheckString("."))
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("add"))
|
||||
{
|
||||
flagvar = &sec.flagsAdd;
|
||||
}
|
||||
else if (sc.Compare("remove"))
|
||||
{
|
||||
flagvar = &sec.flagsRemove;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Invalid property 'flags.%s'", sc.String);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sec.flagsSet = true;
|
||||
flagvar = &sec.flags;
|
||||
}
|
||||
sc.CheckString("=");
|
||||
do
|
||||
{
|
||||
sc.MustGetString();
|
||||
for (const char *tok = strtok(sc.String, ",+ \t"); tok != NULL; tok = strtok(NULL, ",+ \t"))
|
||||
{
|
||||
if (!stricmp(tok, "SECRET")) *flagvar |= SECF_SECRET | SECF_WASSECRET;
|
||||
else if (!stricmp(tok, "FRICTION")) *flagvar |= SECF_FRICTION;
|
||||
else if (!stricmp(tok, "PUSH")) *flagvar |= SECF_PUSH;
|
||||
else if (!stricmp(tok, "KILLSOUND")) *flagvar |= SECF_SILENT;
|
||||
else if (!stricmp(tok, "KILLMOVESOUND")) *flagvar |= SECF_SILENTMOVE;
|
||||
else sc.ScriptError("Unknown option '%s'", tok);
|
||||
}
|
||||
} while (sc.CheckString("|")); // Unquoted strings with '|' separator - parse as a separate string in the loop.
|
||||
}
|
||||
else if (sc.Compare("damage"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetNumber();
|
||||
sec.damageamount = sc.Number;
|
||||
}
|
||||
else if (sc.Compare("damagemask"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetNumber();
|
||||
sec.damageinterval = sc.Number;
|
||||
}
|
||||
else if (sc.Compare("damageflags"))
|
||||
{
|
||||
DWORD *flagvar = NULL;
|
||||
BYTE *leakvar = NULL;
|
||||
if (sc.CheckString("."))
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("add"))
|
||||
{
|
||||
flagvar = &sec.damageflagsAdd;
|
||||
leakvar = &sec.leakyadd;
|
||||
}
|
||||
else if (sc.Compare("remove"))
|
||||
{
|
||||
flagvar = &sec.damageflagsRemove;
|
||||
leakvar = &sec.leakyremove;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Invalid property 'flags.%s'", sc.String);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sec.damageflagsSet = true;
|
||||
flagvar = &sec.damageflags;
|
||||
leakvar = &sec.leaky;
|
||||
}
|
||||
sc.CheckString("=");
|
||||
do
|
||||
{
|
||||
sc.MustGetString();
|
||||
for (const char *tok = strtok(sc.String, ",+ \t"); tok != NULL; tok = strtok(NULL, ",+ \t"))
|
||||
{
|
||||
if (!stricmp(tok, "LEAKYSUIT")) *leakvar |= 1;
|
||||
else if (!stricmp(tok, "IGNORESUIT")) *leakvar |= 2; // these 2 bits will be used to set 'leakychance', but this can only be done when the sector gets initialized
|
||||
else if (!stricmp(tok, "ENDGODMODE")) *flagvar |= SECF_ENDGODMODE;
|
||||
else if (!stricmp(tok, "ENDLEVEL")) *flagvar |= SECF_ENDLEVEL;
|
||||
else if (!stricmp(tok, "TERRAINHIT")) *flagvar |= SECF_DMGTERRAINFX;
|
||||
else sc.ScriptError("Unknown option '%s'", tok);
|
||||
}
|
||||
} while (sc.CheckString("|")); // Unquoted strings with '|' separator - parse as a separate string in the loop.
|
||||
}
|
||||
else if (sc.Compare("floorterrain"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetString();
|
||||
sec.floorterrain = P_FindTerrain(sc.String);
|
||||
}
|
||||
else if (sc.Compare("floorangle"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetFloat();
|
||||
sec.planexform[sector_t::floor].angle = angle_t(sc.Float * ANGLE_90 / 90.);
|
||||
}
|
||||
else if (sc.Compare("flooroffsetx"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetFloat();
|
||||
sec.planexform[sector_t::floor].xoffs = FLOAT2FIXED(sc.Float);
|
||||
}
|
||||
else if (sc.Compare("flooroffsety"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetFloat();
|
||||
sec.planexform[sector_t::floor].yoffs = FLOAT2FIXED(sc.Float);
|
||||
}
|
||||
else if (sc.Compare("ceilingterrain"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetString();
|
||||
sec.ceilingterrain = P_FindTerrain(sc.String);
|
||||
}
|
||||
else if (sc.Compare("ceilingangle"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetFloat();
|
||||
sec.planexform[sector_t::ceiling].angle = angle_t(sc.Float * ANGLE_90 / 90.);
|
||||
}
|
||||
else if (sc.Compare("ceilingoffsetx"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetFloat();
|
||||
sec.planexform[sector_t::ceiling].xoffs = FLOAT2FIXED(sc.Float);
|
||||
}
|
||||
else if (sc.Compare("ceilingoffsety"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetFloat();
|
||||
sec.planexform[sector_t::ceiling].yoffs = FLOAT2FIXED(sc.Float);
|
||||
}
|
||||
else if (sc.Compare("colormaptop") || sc.Compare("colormapbottom"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetString();
|
||||
// these properties are not implemented by ZDoom
|
||||
}
|
||||
else if (sc.Compare("colormapmid"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetString();
|
||||
// Eternity is based on SMMU and uses colormaps differently than all other ports.
|
||||
// The only solution here is to convert the colormap to an RGB value and set it as the sector's color.
|
||||
DWORD cmap = R_ColormapNumForName(sc.String);
|
||||
if (cmap != 0)
|
||||
{
|
||||
sec.color = R_BlendForColormap(cmap) & 0xff000000;
|
||||
sec.colorSet = true;
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("overlayalpha"))
|
||||
{
|
||||
sc.MustGetStringName(".");
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("floor"))
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
if (sc.CheckString("%")) sc.Float = sc.Number / 100.f;
|
||||
else sc.Float = sc.Number / 255.f;
|
||||
sec.overlayalpha[sector_t::floor] = FLOAT2FIXED(sc.Float);
|
||||
}
|
||||
else if (sc.Compare("ceiling"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
if (sc.CheckString("%")) sc.Float = sc.Number / 100.f;
|
||||
else sc.Float = sc.Number / 255.f;
|
||||
sec.overlayalpha[sector_t::floor] = FLOAT2FIXED(sc.Float);
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("portalflags"))
|
||||
{
|
||||
int dest = 0;
|
||||
sc.MustGetStringName(".");
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("floor")) dest = sector_t::floor;
|
||||
else if (sc.Compare("ceiling")) dest = sector_t::ceiling;
|
||||
else sc.ScriptError("Unknown portal type '%s'", sc.String);
|
||||
|
||||
sc.CheckString("=");
|
||||
do
|
||||
{
|
||||
sc.MustGetString();
|
||||
for (const char *tok = strtok(sc.String, ",+ \t"); tok != NULL; tok = strtok(NULL, ",+ \t"))
|
||||
{
|
||||
if (!stricmp(tok, "DISABLED")) sec.portalflags[dest] |= PLANEF_DISABLED;
|
||||
else if (!stricmp(tok, "NORENDER")) sec.portalflags[dest] |= PLANEF_NORENDER;
|
||||
else if (!stricmp(tok, "NOPASS")) sec.portalflags[dest] |= PLANEF_NOPASS;
|
||||
else if (!stricmp(tok, "BLOCKSOUND")) sec.portalflags[dest] |= PLANEF_BLOCKSOUND;
|
||||
else if (!stricmp(tok, "OVERLAY")) sec.portalflags[dest] |= 0; // we do not use this. Alpha is the sole determinant for overlay drawing
|
||||
else if (!stricmp(tok, "ADDITIVE")) sec.portalflags[dest] |= PLANEF_ADDITIVE;
|
||||
else if (!stricmp(tok, "USEGLOBALTEX")) {} // not implemented
|
||||
else sc.ScriptError("Unknown option '%s'", tok);
|
||||
}
|
||||
} while (sc.CheckString("|")); // Unquoted strings with '|' separator - parse as a separate string in the loop.
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Unknown property '%s'", sc.String);
|
||||
}
|
||||
}
|
||||
EDSectors[sec.recordnum] = sec;
|
||||
}
|
||||
|
||||
static void parseMapthing(FScanner &sc)
|
||||
{
|
||||
EDMapthing mt;
|
||||
|
||||
memset(&mt, 0, sizeof(mt));
|
||||
mt.flags |= MTF_SINGLE | MTF_COOPERATIVE | MTF_DEATHMATCH; // Extradata uses inverse logic, like Doom.exe
|
||||
|
||||
sc.MustGetStringName("{");
|
||||
while (!sc.CheckString("}"))
|
||||
{
|
||||
sc.MustGetString();
|
||||
if (sc.Compare("recordnum"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetNumber();
|
||||
mt.recordnum = sc.Number;
|
||||
}
|
||||
else if (sc.Compare("tid"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetNumber();
|
||||
mt.tid = sc.Number;
|
||||
}
|
||||
else if (sc.Compare("type"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
if (sc.CheckNumber())
|
||||
{
|
||||
mt.type = sc.Number;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Class name.
|
||||
sc.MustGetString();
|
||||
// According to the Eternity Wiki a name may be prefixed with 'thing:'.
|
||||
const char *pos = strchr(sc.String, ':'); // Eternity never checks if the prefix actually is 'thing'.
|
||||
if (pos) pos++;
|
||||
else pos = sc.String;
|
||||
const PClass *cls = PClass::FindClass(pos);
|
||||
if (cls != NULL)
|
||||
{
|
||||
FDoomEdMap::Iterator it(DoomEdMap);
|
||||
FDoomEdMap::Pair *pair;
|
||||
while (it.NextPair(pair))
|
||||
{
|
||||
if (pair->Value.Type == cls)
|
||||
{
|
||||
mt.type = pair->Key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Let's hope this isn't an internal Eternity name.
|
||||
// If so, a name mapping needs to be defined...
|
||||
sc.ScriptError("Unknown type '%s'", sc.String);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("args"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetStringName("{");
|
||||
int c = 0;
|
||||
while (!sc.CheckString("}"))
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
mt.args[c++] = sc.Number;
|
||||
|
||||
}
|
||||
}
|
||||
else if (sc.Compare("height"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
sc.MustGetFloat(); // no idea if Eternity allows fractional numbers. Better be safe and do it anyway.
|
||||
mt.height = FLOAT2FIXED(sc.Float);
|
||||
}
|
||||
else if (sc.Compare("options"))
|
||||
{
|
||||
sc.CheckString("=");
|
||||
do
|
||||
{
|
||||
sc.MustGetString();
|
||||
for (const char *tok = strtok(sc.String, ",+ \t"); tok != NULL; tok = strtok(NULL, ",+ \t"))
|
||||
{
|
||||
if (!stricmp(tok, "EASY")) mt.skillfilter |= 3;
|
||||
else if (!stricmp(tok, "NORMAL")) mt.skillfilter |= 4;
|
||||
else if (!stricmp(tok, "HARD")) mt.skillfilter |= 24;
|
||||
else if (!stricmp(tok, "AMBUSH")) mt.flags |= MTF_AMBUSH;
|
||||
else if (!stricmp(tok, "NOTSINGLE")) mt.flags &= ~MTF_SINGLE;
|
||||
else if (!stricmp(tok, "NOTDM")) mt.flags &= ~MTF_DEATHMATCH;
|
||||
else if (!stricmp(tok, "NOTCOOP")) mt.flags &= ~MTF_COOPERATIVE;
|
||||
else if (!stricmp(tok, "FRIEND")) mt.flags |= MTF_FRIENDLY;
|
||||
else if (!stricmp(tok, "DORMANT")) mt.flags |= MTF_DORMANT;
|
||||
else sc.ScriptError("Unknown option '%s'", tok);
|
||||
}
|
||||
} while (sc.CheckString("|")); // Unquoted strings with '|' separator - parse as a separate string in the loop.
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Unknown property '%s'", sc.String);
|
||||
}
|
||||
}
|
||||
EDThings[mt.recordnum] = mt;
|
||||
}
|
||||
|
||||
void InitED()
|
||||
{
|
||||
FString filename;
|
||||
FScanner sc;
|
||||
|
||||
if (EDMap.CompareNoCase(level.MapName) != 0)
|
||||
{
|
||||
EDLines.Clear();
|
||||
EDSectors.Clear();
|
||||
EDThings.Clear();
|
||||
EDMap = level.MapName;
|
||||
|
||||
const char *arg = Args->CheckValue("-edf");
|
||||
|
||||
if (arg != NULL) filename = arg;
|
||||
else
|
||||
{
|
||||
FEDOptions *opt = level.info->GetOptData<FEDOptions>("EData", false);
|
||||
if (opt != NULL)
|
||||
{
|
||||
filename = opt->EDName;
|
||||
}
|
||||
}
|
||||
|
||||
if (filename.IsEmpty()) return;
|
||||
int lump = Wads.CheckNumForFullName(filename, true, ns_global);
|
||||
if (lump == -1) return;
|
||||
sc.OpenLumpNum(lump);
|
||||
|
||||
sc.SetCMode(true);
|
||||
while (sc.GetString())
|
||||
{
|
||||
if (sc.Compare("linedef"))
|
||||
{
|
||||
parseLinedef(sc);
|
||||
}
|
||||
else if (sc.Compare("mapthing"))
|
||||
{
|
||||
parseMapthing(sc);
|
||||
}
|
||||
else if (sc.Compare("sector"))
|
||||
{
|
||||
parseSector(sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Unknown keyword '%s'", sc.String);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessEDMapthing(FMapThing *mt, int recordnum)
|
||||
{
|
||||
InitED();
|
||||
|
||||
EDMapthing *emt = EDThings.CheckKey(recordnum);
|
||||
if (emt == NULL)
|
||||
{
|
||||
Printf("EDF Mapthing record %d not found\n", recordnum);
|
||||
mt->EdNum = 0;
|
||||
return;
|
||||
}
|
||||
mt->thingid = emt->tid;
|
||||
mt->EdNum = emt->type;
|
||||
mt->info = DoomEdMap.CheckKey(mt->EdNum);
|
||||
mt->z = emt->height;
|
||||
memcpy(mt->args, emt->args, sizeof(mt->args));
|
||||
mt->SkillFilter = emt->skillfilter;
|
||||
mt->flags = emt->flags;
|
||||
}
|
||||
|
||||
void ProcessEDLinedef(line_t *ld, int recordnum)
|
||||
{
|
||||
InitED();
|
||||
|
||||
EDLinedef *eld = EDLines.CheckKey(recordnum);
|
||||
if (eld == NULL)
|
||||
{
|
||||
Printf("EDF Linedef record %d not found\n", recordnum);
|
||||
ld->special = 0;
|
||||
return;
|
||||
}
|
||||
const DWORD fmask = ML_REPEAT_SPECIAL | ML_FIRSTSIDEONLY | ML_ADDTRANS | ML_BLOCKEVERYTHING | ML_ZONEBOUNDARY | ML_CLIP_MIDTEX;
|
||||
ld->special = eld->special;
|
||||
ld->activation = eld->activation;
|
||||
ld->flags = (ld->flags&~fmask) | eld->flags;
|
||||
ld->Alpha = eld->alpha;
|
||||
memcpy(ld->args, eld->args, sizeof(ld->args));
|
||||
tagManager.AddLineID(int(ld - lines), eld->tag);
|
||||
}
|
||||
|
||||
void ProcessEDSector(sector_t *sec, int recordnum)
|
||||
{
|
||||
EDSector *esec = EDSectors.CheckKey(recordnum);
|
||||
if (esec == NULL)
|
||||
{
|
||||
Printf("EDF Sector record %d not found\n", recordnum);
|
||||
return;
|
||||
}
|
||||
|
||||
// In ZDoom the regular and the damage flags are part of the same flag word so we need to do some masking.
|
||||
const DWORD flagmask = SECF_SECRET | SECF_WASSECRET | SECF_FRICTION | SECF_PUSH | SECF_SILENT | SECF_SILENTMOVE;
|
||||
if (esec->flagsSet) sec->Flags = (sec->Flags & ~flagmask);
|
||||
sec->Flags = (sec->Flags | esec->flags | esec->flagsAdd) & ~esec->flagsRemove;
|
||||
|
||||
BYTE leak = 0;
|
||||
if (esec->damageflagsSet) sec->Flags = (sec->Flags & ~SECF_DAMAGEFLAGS);
|
||||
else leak = sec->leakydamage >= 256 ? 2 : sec->leakydamage >= 5 ? 1 : 0;
|
||||
sec->Flags = (sec->Flags | esec->damageflags | esec->damageflagsAdd) & ~esec->damageflagsRemove;
|
||||
leak = (leak | esec->leaky | esec->leakyadd) & ~esec->leakyremove;
|
||||
|
||||
// the damage properties will be unconditionally overridden by Extradata.
|
||||
sec->leakydamage = leak == 0 ? 0 : leak == 1 ? 5 : 256;
|
||||
sec->damageamount = esec->damageamount;
|
||||
sec->damageinterval = esec->damageinterval;
|
||||
sec->damagetype = esec->damagetype;
|
||||
|
||||
sec->terrainnum[sector_t::floor] = esec->floorterrain;
|
||||
sec->terrainnum[sector_t::ceiling] = esec->ceilingterrain;
|
||||
|
||||
if (esec->colorSet) sec->SetColor(RPART(esec->color), GPART(esec->color), BPART(esec->color), 0);
|
||||
|
||||
const DWORD pflagmask = PLANEF_DISABLED | PLANEF_NORENDER | PLANEF_NOPASS | PLANEF_BLOCKSOUND | PLANEF_ADDITIVE;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
sec->planes[i].xform.xoffs = esec->planexform[i].xoffs;
|
||||
sec->planes[i].xform.yoffs = esec->planexform[i].yoffs;
|
||||
sec->planes[i].xform.angle = esec->planexform[i].angle;
|
||||
sec->planes[i].alpha = esec->overlayalpha[i];
|
||||
sec->planes[i].Flags = (sec->planes[i].Flags & ~pflagmask) | esec->portalflags[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ProcessEDSectors()
|
||||
{
|
||||
int i;
|
||||
|
||||
InitED();
|
||||
if (EDSectors.CountUsed() == 0) return; // don't waste time if there's no records.
|
||||
|
||||
// collect all Extradata sector records up front so we do not need to search the complete line array for each sector separately.
|
||||
int *sectorrecord = new int[numsectors];
|
||||
memset(sectorrecord, -1, numsectors * sizeof(int));
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
if (lines[i].special == Static_Init && lines[i].args[1] == Init_EDSector)
|
||||
{
|
||||
sectorrecord[lines[i].frontsector - sectors] = lines[i].args[0];
|
||||
lines[i].special = 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < numsectors; i++)
|
||||
{
|
||||
if (sectorrecord[i] >= 0)
|
||||
{
|
||||
ProcessEDSector(§ors[i], sectorrecord[i]);
|
||||
}
|
||||
}
|
||||
delete[] sectorrecord;
|
||||
}
|
||||
|
||||
void LoadMapinfoACSLump()
|
||||
{
|
||||
FEDOptions *opt = level.info->GetOptData<FEDOptions>("EData", false);
|
||||
if (opt != NULL)
|
||||
{
|
||||
int lump = Wads.CheckNumForName(opt->acsName);
|
||||
if (lump >= 0) FBehavior::StaticLoadModule(lump);
|
||||
}
|
||||
}
|
12
src/edata.h
Normal file
12
src/edata.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef EDATA_H
|
||||
#define EDATA_H
|
||||
|
||||
struct FMapThing;
|
||||
struct line_t;
|
||||
|
||||
void ProcessEDMapthing(FMapThing *mt, int recordnum);
|
||||
void ProcessEDLinedef(line_t *line, int recordnum);
|
||||
void ProcessEDSectors();
|
||||
void LoadMapinfoACSLump();
|
||||
|
||||
#endif
|
|
@ -69,6 +69,7 @@ const char *SpecialMapthingNames[] = {
|
|||
"$CopyCeilingPlane",
|
||||
"$VertexFloorZ",
|
||||
"$VertexCeilingZ",
|
||||
"$EDThing",
|
||||
|
||||
};
|
||||
//==========================================================================
|
||||
|
|
|
@ -310,6 +310,7 @@ enum ESpecialMapthings
|
|||
SMT_CopyCeilingPlane,
|
||||
SMT_VertexFloorZ,
|
||||
SMT_VertexCeilingZ,
|
||||
SMT_EDThing,
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -59,6 +59,8 @@ typedef enum {
|
|||
Init_Damage = 2,
|
||||
Init_SectorLink = 3,
|
||||
NUM_STATIC_INITS,
|
||||
Init_EDSector = 253,
|
||||
Init_EDLine = 254,
|
||||
Init_TransferSky = 255
|
||||
} staticinit_t;
|
||||
|
||||
|
|
|
@ -69,6 +69,9 @@
|
|||
#include "r_renderer.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "portal.h"
|
||||
#ifndef NO_EDATA
|
||||
#include "edata.h"
|
||||
#endif
|
||||
|
||||
#include "fragglescript/t_fs.h"
|
||||
|
||||
|
@ -1757,34 +1760,45 @@ void P_LoadThings (MapData * map)
|
|||
mti[i].alpha = -1;
|
||||
mti[i].health = 1;
|
||||
mti[i].FloatbobPhase = -1;
|
||||
flags &= ~MTF_SKILLMASK;
|
||||
mti[i].flags = (short)((flags & 0xf) | 0x7e0);
|
||||
if (gameinfo.gametype == GAME_Strife)
|
||||
{
|
||||
mti[i].flags &= ~MTF_AMBUSH;
|
||||
if (flags & STF_SHADOW) mti[i].flags |= MTF_SHADOW;
|
||||
if (flags & STF_ALTSHADOW) mti[i].flags |= MTF_ALTSHADOW;
|
||||
if (flags & STF_STANDSTILL) mti[i].flags |= MTF_STANDSTILL;
|
||||
if (flags & STF_AMBUSH) mti[i].flags |= MTF_AMBUSH;
|
||||
if (flags & STF_FRIENDLY) mti[i].flags |= MTF_FRIENDLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags & BTF_BADEDITORCHECK)
|
||||
{
|
||||
flags &= 0x1F;
|
||||
}
|
||||
if (flags & BTF_NOTDEATHMATCH) mti[i].flags &= ~MTF_DEATHMATCH;
|
||||
if (flags & BTF_NOTCOOPERATIVE) mti[i].flags &= ~MTF_COOPERATIVE;
|
||||
if (flags & BTF_FRIENDLY) mti[i].flags |= MTF_FRIENDLY;
|
||||
}
|
||||
if (flags & BTF_NOTSINGLE) mti[i].flags &= ~MTF_SINGLE;
|
||||
|
||||
mti[i].x = LittleShort(mt->x) << FRACBITS;
|
||||
mti[i].y = LittleShort(mt->y) << FRACBITS;
|
||||
mti[i].angle = LittleShort(mt->angle);
|
||||
mti[i].EdNum = LittleShort(mt->type);
|
||||
mti[i].info = DoomEdMap.CheckKey(mti[i].EdNum);
|
||||
|
||||
|
||||
#ifndef NO_EDATA
|
||||
if (mti[i].info != NULL && mti[i].info->Special == SMT_EDThing)
|
||||
{
|
||||
ProcessEDMapthing(&mti[i], flags);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
flags &= ~MTF_SKILLMASK;
|
||||
mti[i].flags = (short)((flags & 0xf) | 0x7e0);
|
||||
if (gameinfo.gametype == GAME_Strife)
|
||||
{
|
||||
mti[i].flags &= ~MTF_AMBUSH;
|
||||
if (flags & STF_SHADOW) mti[i].flags |= MTF_SHADOW;
|
||||
if (flags & STF_ALTSHADOW) mti[i].flags |= MTF_ALTSHADOW;
|
||||
if (flags & STF_STANDSTILL) mti[i].flags |= MTF_STANDSTILL;
|
||||
if (flags & STF_AMBUSH) mti[i].flags |= MTF_AMBUSH;
|
||||
if (flags & STF_FRIENDLY) mti[i].flags |= MTF_FRIENDLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags & BTF_BADEDITORCHECK)
|
||||
{
|
||||
flags &= 0x1F;
|
||||
}
|
||||
if (flags & BTF_NOTDEATHMATCH) mti[i].flags &= ~MTF_DEATHMATCH;
|
||||
if (flags & BTF_NOTCOOPERATIVE) mti[i].flags &= ~MTF_COOPERATIVE;
|
||||
if (flags & BTF_FRIENDLY) mti[i].flags |= MTF_FRIENDLY;
|
||||
}
|
||||
if (flags & BTF_NOTSINGLE) mti[i].flags &= ~MTF_SINGLE;
|
||||
}
|
||||
}
|
||||
delete [] mtp;
|
||||
}
|
||||
|
@ -2160,7 +2174,19 @@ void P_LoadLineDefs (MapData * map)
|
|||
|
||||
// [RH] Translate old linedef special and flags to be
|
||||
// compatible with the new format.
|
||||
P_TranslateLineDef (ld, mld, i);
|
||||
|
||||
P_TranslateLineDef (ld, mld, -1);
|
||||
// do not assign the tag for Extradata lines.
|
||||
if (ld->special != Static_Init || (ld->args[1] != Init_EDLine && ld->args[1] != Init_EDSector))
|
||||
{
|
||||
tagManager.AddLineID(i, mld->tag);
|
||||
}
|
||||
#ifndef NO_EDATA
|
||||
if (ld->special == Static_Init && ld->args[1] == Init_EDLine)
|
||||
{
|
||||
ProcessEDLinedef(ld, mld->tag);
|
||||
}
|
||||
#endif
|
||||
|
||||
ld->v1 = &vertexes[LittleShort(mld->v1)];
|
||||
ld->v2 = &vertexes[LittleShort(mld->v2)];
|
||||
|
@ -3330,7 +3356,7 @@ void P_LoadBehavior (MapData * map)
|
|||
|
||||
void P_GetPolySpots (MapData * map, TArray<FNodeBuilder::FPolyStart> &spots, TArray<FNodeBuilder::FPolyStart> &anchors)
|
||||
{
|
||||
if (map->HasBehavior)
|
||||
//if (map->HasBehavior)
|
||||
{
|
||||
for (unsigned int i = 0; i < MapThingsConverted.Size(); ++i)
|
||||
{
|
||||
|
@ -3682,6 +3708,10 @@ void P_SetupLevel (const char *lumpname, int position)
|
|||
}
|
||||
|
||||
FBehavior::StaticLoadDefaultModules ();
|
||||
#ifndef NO_EDATA
|
||||
LoadMapinfoACSLump();
|
||||
#endif
|
||||
|
||||
|
||||
P_LoadStrifeConversations (map, lumpname);
|
||||
|
||||
|
|
|
@ -65,6 +65,9 @@
|
|||
#include "c_dispatch.h"
|
||||
#include "r_sky.h"
|
||||
#include "portal.h"
|
||||
#ifndef NO_EDATA
|
||||
#include "edata.h"
|
||||
#endif
|
||||
|
||||
// State.
|
||||
#include "r_state.h"
|
||||
|
@ -1324,6 +1327,11 @@ void P_SpawnSpecials (void)
|
|||
|
||||
P_InitSectorSpecial(sector, sector->special, false);
|
||||
}
|
||||
|
||||
#ifndef NO_EDATA
|
||||
ProcessEDSectors();
|
||||
#endif
|
||||
|
||||
|
||||
// Init other misc stuff
|
||||
|
||||
|
|
|
@ -336,6 +336,13 @@ enum
|
|||
PLANEF_ABSLIGHTING = 1, // floor/ceiling light is absolute, not relative
|
||||
PLANEF_BLOCKED = 2, // can not be moved anymore.
|
||||
PLANEF_ADDITIVE = 4, // rendered additive
|
||||
|
||||
// linked portal stuff
|
||||
PLANEF_NORENDER = 8,
|
||||
PLANEF_NOPASS = 16,
|
||||
PLANEF_BLOCKSOUND = 32,
|
||||
PLANEF_DISABLED = 64,
|
||||
PLANEF_OBSTRUCTED = 128, // if the portal plane is beyond the sector's floor or ceiling.
|
||||
};
|
||||
|
||||
// Internal sector flags
|
||||
|
|
|
@ -856,7 +856,7 @@ int FScanner::MustMatchString (const char * const *strings, size_t stride)
|
|||
i = MatchString (strings, stride);
|
||||
if (i == -1)
|
||||
{
|
||||
ScriptError (NULL);
|
||||
ScriptError ("Unknown keyword '%s'", String);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
|
8
wadsrc/static/mapinfo/eternity.txt
Normal file
8
wadsrc/static/mapinfo/eternity.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
// This should be included by any converted Eternity project so set the DoomEdNums that conflict with regular ZDoom get set.
|
||||
|
||||
DoomEdNums
|
||||
{
|
||||
5003 = none
|
||||
5004 = "$EDThing"
|
||||
}
|
||||
|
|
@ -8,11 +8,18 @@
|
|||
|
||||
define Unsupported (0)
|
||||
|
||||
enum
|
||||
{
|
||||
Init_EDSector = 253,
|
||||
Init_EDLine = 254
|
||||
}
|
||||
|
||||
// The tag for such a line is actually a key to find, in an ExtraData lump
|
||||
// indicated for the current level by the EMAPINFO lump, what line special
|
||||
// to actually use. This is how parameterized linedefs are used by Eternity
|
||||
// in the Doom format. "xlating" this would thus be quite complicated...
|
||||
270 = 0, Unsupported() // "ExtraDataSpecial"
|
||||
// in the Doom format.
|
||||
|
||||
270 = 0, Static_Init(tag, Init_EDLine) // "ExtraDataSpecial"
|
||||
|
||||
// These two are standard MBF specials, no need to redefine them, they're in xlat/doom.txt
|
||||
// 271 = 0, Static_Init (tag, Init_TransferSky, 0)
|
||||
|
@ -60,53 +67,51 @@ define Unsupported (0)
|
|||
// Parameterized linedefs
|
||||
// They are never used directly in Doom-format maps. Instead, it passes through ExtraData and 270.
|
||||
// Hexen format is incomplete; and Quasar wants to use ZDoom-compatible special values for UDMF.
|
||||
// So there is no need to bother with them and they are listed only for completeness' sake.
|
||||
/*
|
||||
300: "Door_Raise"
|
||||
301: "Door_Open"
|
||||
302: "Door_Close"
|
||||
303: "Door_CloseWaitOpen"
|
||||
304: "Door_WaitRaise"
|
||||
305: "Door_WaitClose"
|
||||
306: "Floor_RaiseToHighest"
|
||||
307: "Floor_LowerToHighest"
|
||||
308: "Floor_RaiseToLowest"
|
||||
309: "Floor_LowerToLowest"
|
||||
310: "Floor_RaiseToNearest"
|
||||
311: "Floor_LowerToNearest"
|
||||
312: "Floor_RaiseToLowestCeiling"
|
||||
313: "Floor_LowerToLowestCeiling"
|
||||
314: "Floor_RaiseToCeiling"
|
||||
315: "Floor_RaiseByTexture"
|
||||
316: "Floor_LowerByTexture"
|
||||
317: "Floor_RaiseByValue"
|
||||
318: "Floor_LowerByValue"
|
||||
319: "Floor_MoveToValue"
|
||||
320: "Floor_RaiseInstant"
|
||||
321: "Floor_LowerInstant"
|
||||
322: "Floor_ToCeilingInstant"
|
||||
323: "Ceiling_RaiseToHighest"
|
||||
324: "Ceiling_ToHighestInstant"
|
||||
325: "Ceiling_RaiseToNearest"
|
||||
326: "Ceiling_LowerToNearest"
|
||||
327: "Ceiling_RaiseToLowest"
|
||||
328: "Ceiling_LowerToLowest"
|
||||
329: "Ceiling_RaiseToHighestFloor"
|
||||
330: "Ceiling_LowerToHighestFloor"
|
||||
331: "Ceiling_ToFloorInstant"
|
||||
332: "Ceiling_LowerToFloor"
|
||||
333: "Ceiling_RaiseByTexture"
|
||||
334: "Ceiling_LowerByTexture"
|
||||
335: "Ceiling_RaiseByValue"
|
||||
336: "Ceiling_LowerByValue"
|
||||
337: "Ceiling_MoveToValue"
|
||||
338: "Ceiling_RaiseInstant"
|
||||
339: "Ceiling_LowerInstant"
|
||||
340: "Stairs_BuildUpDoom"
|
||||
341: "Stairs_BuildDownDoom"
|
||||
342: "Stairs_BuildUpDoomSync"
|
||||
343: "Stairs_BuildDownDoomSync"
|
||||
*/
|
||||
// The translation here is for the odd Extradata that specifies them as numbers.
|
||||
300 = 0, Door_Raise(0)
|
||||
301 = 0, Door_Open(0)
|
||||
302 = 0, Door_Close(0)
|
||||
303 = 0, Door_CloseWaitOpen(0)
|
||||
304 = 0, Door_WaitRaise(0)
|
||||
305 = 0, Door_WaitClose(0)
|
||||
306 = 0, Floor_RaiseToHighest(0)
|
||||
307 = 0, Floor_LowerToHighestEE(0)
|
||||
308 = 0, Floor_RaiseToLowest(0)
|
||||
309 = 0, Floor_LowerToLowest(0)
|
||||
310 = 0, Floor_RaiseToNearest(0)
|
||||
311 = 0, Floor_LowerToNearest(0)
|
||||
312 = 0, Floor_RaiseToLowestCeiling(0)
|
||||
313 = 0, Floor_LowerToLowestCeiling(0)
|
||||
314 = 0, Floor_RaiseToCeiling(0)
|
||||
315 = 0, Floor_RaiseByTexture(0)
|
||||
316 = 0, Floor_LowerByTexture(0)
|
||||
317 = 0, Floor_RaiseByValue(0)
|
||||
318 = 0, Floor_LowerByValue(0)
|
||||
319 = 0, Floor_MoveToValue(0)
|
||||
320 = 0, Floor_RaiseInstant(0)
|
||||
321 = 0, Floor_LowerInstant(0)
|
||||
322 = 0, Floor_ToCeilingInstant(0)
|
||||
323 = 0, Ceiling_RaiseToHighest(0)
|
||||
324 = 0, Ceiling_ToHighestInstant(0)
|
||||
325 = 0, Ceiling_RaiseToNearest(0)
|
||||
326 = 0, Ceiling_LowerToNearest(0)
|
||||
327 = 0, Ceiling_RaiseToLowest(0)
|
||||
328 = 0, Ceiling_LowerToLowest(0)
|
||||
329 = 0, Ceiling_RaiseToHighestFloor(0)
|
||||
330 = 0, Ceiling_LowerToHighestFloor(0)
|
||||
331 = 0, Ceiling_ToFloorInstant(0)
|
||||
332 = 0, Ceiling_LowerToFloor(0)
|
||||
333 = 0, Ceiling_RaiseByTexture(0)
|
||||
334 = 0, Ceiling_LowerByTexture(0)
|
||||
335 = 0, Ceiling_RaiseByValue(0)
|
||||
336 = 0, Ceiling_LowerByValue(0)
|
||||
337 = 0, Ceiling_MoveToValue(0)
|
||||
338 = 0, Ceiling_RaiseInstant(0)
|
||||
339 = 0, Ceiling_LowerInstant(0)
|
||||
340 = 0, Stairs_BuildUpDoom(0)
|
||||
341 = 0, Stairs_BuildDownDoom(0)
|
||||
342 = 0, Stairs_BuildUpDoomSync(0)
|
||||
343 = 0, Stairs_BuildDownDoomSync(0)
|
||||
|
||||
// Two-way portals are not supported yet either
|
||||
344 = 0, Unsupported() // "Portal_TwowayCeiling"
|
||||
|
@ -115,18 +120,16 @@ define Unsupported (0)
|
|||
347 = 0, Unsupported() // "Portal_TwowayAnchorLineFloor"
|
||||
|
||||
// More parameterized linedefs
|
||||
/*
|
||||
348: "Polyobj_StartLine"
|
||||
349: "Polyobj_ExplicitLine"
|
||||
350: "Polyobj_DoorSlide"
|
||||
351: "Polyobj_DoorSwing"
|
||||
352: "Polyobj_Move"
|
||||
353: "Polyobj_OR_Move"
|
||||
354: "Polyobj_RotateRight"
|
||||
355: "Polyobj_OR_RotateRight"
|
||||
356: "Polyobj_RotateLeft"
|
||||
357: "Polyobj_OR_RotateLeft"
|
||||
*/
|
||||
348 = 0, Polyobj_StartLine(0)
|
||||
349 = 0, Polyobj_ExplicitLine(0)
|
||||
350 = 0, Polyobj_DoorSlide(0)
|
||||
351 = 0, Polyobj_DoorSwing(0)
|
||||
352 = 0, Polyobj_Move(0)
|
||||
353 = 0, Polyobj_OR_Move(0)
|
||||
354 = 0, Polyobj_RotateRight(0)
|
||||
355 = 0, Polyobj_OR_RotateRight(0)
|
||||
356 = 0, Polyobj_RotateLeft(0)
|
||||
357 = 0, Polyobj_OR_RotateLeft(0)
|
||||
|
||||
// Eternity's linked portals, vertical link version (floor-to-ceiling)
|
||||
358 = 0, Unsupported() // "Portal_LinkedCeiling"
|
||||
|
@ -135,29 +138,27 @@ define Unsupported (0)
|
|||
361 = 0, Unsupported() // "Portal_LinkedAnchorLineFloor"
|
||||
|
||||
// Even more parameterized linedefs
|
||||
/*
|
||||
362: "Pillar_Build"
|
||||
363: "Pillar_BuildAndCrush"
|
||||
364: "Pillar_Open"
|
||||
365: "ACS_Execute"
|
||||
366: "ACS_Suspend"
|
||||
367: "ACS_Terminate"
|
||||
368: "Light_RaiseByValue"
|
||||
369: "Light_LowerByValue"
|
||||
370: "Light_ChangeToValue"
|
||||
371: "Light_Fade"
|
||||
372: "Light_Glow"
|
||||
373: "Light_Flicker"
|
||||
374: "Light_Strobe"
|
||||
375: "Radius_Quake"
|
||||
*/
|
||||
362 = 0, Pillar_Build(0)
|
||||
363 = 0, Pillar_BuildAndCrush(0)
|
||||
364 = 0, Pillar_Open(0)
|
||||
365 = 0, ACS_Execute(0)
|
||||
366 = 0, ACS_Suspend(0)
|
||||
367 = 0, ACS_Terminate(0)
|
||||
368 = 0, Light_RaiseByValue(0)
|
||||
369 = 0, Light_LowerByValue(0)
|
||||
370 = 0, Light_ChangeToValue(0)
|
||||
371 = 0, Light_Fade(0)
|
||||
372 = 0, Light_Glow(0)
|
||||
373 = 0, Light_Flicker(0)
|
||||
374 = 0, Light_Strobe(0)
|
||||
375 = 0, Radius_Quake(0)
|
||||
|
||||
// Eternity's linked portals, horizontal link version (wall-to-wall)
|
||||
376 = 0, Unsupported() // "Portal_LinkedLineToLine"
|
||||
377 = 0, Unsupported() // "Portal_LinkedLineToLineAnchor"
|
||||
376 = 0, Line_SetPortal(0, tag, 4) // "Portal_LinkedLineToLine"
|
||||
377 = 0, Line_SetPortal(1, tag, 4) // "Portal_LinkedLineToLineAnchor"
|
||||
|
||||
// The famous Hexen linedef
|
||||
// 378 = Line_SetIdentification
|
||||
378 = 0, Line_SetIdentification(0)
|
||||
|
||||
// Attached sectors == linked sectors; However, the implementation in Eternity
|
||||
// is based on front sectors of tagged lines, not on sector tags. So instead
|
||||
|
@ -186,7 +187,23 @@ define Unsupported (0)
|
|||
396 = 0, Plane_Copy(tag, tag)// "Slope_FrontFloorAndCeilingToTaggedSlope"
|
||||
|
||||
// Last parameterized linedefs
|
||||
// 397 = Floor_Waggle
|
||||
// 398 = Thing_Spawn
|
||||
// 399 = Thing_SpawnNoFog
|
||||
// 400 = Teleport_EndGame
|
||||
397 = 0, Floor_Waggle(0)
|
||||
398 = 0, Thing_Spawn(0)
|
||||
399 = 0, Thing_SpawnNoFog(0)
|
||||
400 = 0, Teleport_EndGame(0)
|
||||
|
||||
401 = 0, Static_Init(tag, Init_EDSector)
|
||||
|
||||
402 = 0, Thing_Projectile(0)
|
||||
403 = 0, Thing_ProjectileGravity(0)
|
||||
404 = 0, Thing_Activate(0)
|
||||
405 = 0, Thing_Deactivate(0)
|
||||
410 = 0, Plat_PerpetualRaise(0)
|
||||
411 = 0, Plat_Stop(0)
|
||||
412 = 0, Plat_DownWaitUpStay(0)
|
||||
413 = 0, Plat_DownByValue(0)
|
||||
414 = 0, Plat_UpWaitDownStay(0)
|
||||
415 = 0, Plat_UpByValue(0)
|
||||
416 = 0, Floor_LowerToHighest(0)
|
||||
420 = 0, ACS_ExecuteWithResult(0)
|
||||
421 = 0, Thing_ChangeTID(0)
|
||||
|
|
Loading…
Reference in a new issue