diff --git a/src/edf.cpp b/src/edf.cpp index 05c66ee8b..439cd542d 100644 --- a/src/edf.cpp +++ b/src/edf.cpp @@ -30,6 +30,8 @@ ** 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" @@ -42,6 +44,8 @@ #include "info.h" #include "p_lnspec.h" #include "p_setup.h" +#include "p_tags.h" +#include "r_data/colormaps.h" struct FEdfOptions : public FOptionalMapinfoData @@ -116,22 +120,23 @@ struct EDFSector int damageamount; int damageinterval; FNameNoInit damagetype; + FNameNoInit floorterrain; + + DWORD color; - // These do not represent any of ZDoom's features. They are maintained like this so that the Add and Remove versions work as intended. DWORD damageflags; DWORD damageflagsAdd; DWORD damageflagsRemove; - // floorterrain (Type TBD) - // ceilingterrain is ignored - // colormaptop/mid/bottom need to be translated into color values (the colormap implementation in Eternity is not the same as in Boom!) + // colormaptop//bottom cannot be used because ZDoom has no corresponding properties. FTransform planexform[2]; DWORD portalflags[2]; fixed_t overlayalpha[2]; }; +static FString EDFMap; static TMap EDFLines; static TMap EDFSectors; static TMap EDFThings; @@ -139,14 +144,15 @@ static TMap EDFThings; static void parseLinedef(FScanner &sc) { + EDFLinedef ld; + bool argsset = false; + + memset(&ld, 0, sizeof(ld)); + ld.alpha = FRACUNIT; + sc.MustGetStringName("{"); while (!sc.CheckString("}")) { - EDFLinedef ld; - bool argsset = false; - - memset(&ld, 0, sizeof(ld)); - ld.alpha = FRACUNIT; sc.MustGetString(); if (sc.Compare("recordnum")) { @@ -173,7 +179,7 @@ static void parseLinedef(FScanner &sc) { // 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. + // For now just store a negative number and resolve this later. ld.special = -sc.Number; } else @@ -187,11 +193,12 @@ static void parseLinedef(FScanner &sc) sc.CheckString("="); sc.MustGetStringName("{"); int c = 0; - while (!sc.CheckString("}")) + while (true) { sc.MustGetNumber(); ld.args[c++] = sc.Number; - + if (sc.CheckString("}")) break; + sc.MustGetStringName(","); } argsset = true; } @@ -201,13 +208,14 @@ static void parseLinedef(FScanner &sc) sc.MustGetFloat(); ld.alpha = FLOAT2FIXED(sc.Float); } - else if (sc.Compare("options")) + 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")) { @@ -235,29 +243,33 @@ static void parseLinedef(FScanner &sc) { 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; - if (!argsset) memcpy(ld.args, line.args, sizeof(ld.args)); - } } + 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)); + } + EDFLines[ld.recordnum] = ld; } static void parseSector(FScanner &sc) { + EDFSector sec; + + memset(&sec, 0, sizeof(sec)); + sec.overlayalpha[sector_t::floor] = sec.overlayalpha[sector_t::ceiling] = FRACUNIT; + sc.MustGetStringName("{"); while (!sc.CheckString("}")) { - EDFSector sec; - - memset(&sec, 0, sizeof(sec)); - sec.overlayalpha[sector_t::floor] = sec.overlayalpha[sector_t::ceiling] = FRACUNIT; sc.MustGetString(); if (sc.Compare("recordnum")) { @@ -288,6 +300,7 @@ static void parseSector(FScanner &sc) { flagvar = &sec.flags; } + sc.CheckString("="); do { sc.MustGetString(); @@ -337,6 +350,7 @@ static void parseSector(FScanner &sc) { flagvar = &sec.damageflags; } + sc.CheckString("="); do { sc.MustGetString(); @@ -355,7 +369,8 @@ static void parseSector(FScanner &sc) { sc.CheckString("="); sc.MustGetString(); - // ZDoom does not implement this yet. + sec.floorterrain = sc.String; // Todo: ZDoom does not implement this yet. + } else if (sc.Compare("floorangle")) { @@ -393,17 +408,23 @@ static void parseSector(FScanner &sc) sc.MustGetFloat(); sec.planexform[sector_t::ceiling].yoffs = FLOAT2FIXED(sc.Float); } - else if (sc.Compare("colormaptop") || sc.Compare("colormapbottom")) + else if (sc.Compare("colormaptop") || sc.Compare("colormapbottom") || sc.Compare("ceilingterrain")) { sc.CheckString("="); sc.MustGetString(); - // not implemented by ZDoom + // these properties are not implemented by ZDoom } else if (sc.Compare("colormapmid")) { sc.CheckString("="); sc.MustGetString(); - // the colormap should be analyzed and converted into an RGB color value. + // 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; + } } else if (sc.Compare("overlayalpha")) { @@ -411,12 +432,16 @@ static void parseSector(FScanner &sc) sc.MustGetString(); if (sc.Compare("floor")) { - sc.MustGetFloat(); + 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); } } @@ -429,6 +454,7 @@ static void parseSector(FScanner &sc) else if (sc.Compare("ceiling")) dest = sector_t::ceiling; else sc.ScriptError("Unknown portal type '%s'", sc.String); + sc.CheckString("="); do { sc.MustGetString(); @@ -450,17 +476,19 @@ static void parseSector(FScanner &sc) sc.ScriptError("Unknown property '%s'", sc.String); } } + EDFSectors[sec.recordnum] = sec; } static void parseMapthing(FScanner &sc) { + EDFMapthing mt; + + memset(&mt, 0, sizeof(mt)); + mt.flags |= MTF_SINGLE | MTF_COOPERATIVE | MTF_DEATHMATCH; // EDF uses inverse logic, like Doom.exe + sc.MustGetStringName("{"); while (!sc.CheckString("}")) { - EDFMapthing mt; - - memset(&mt, 0, sizeof(mt)); - mt.flags |= MTF_SINGLE | MTF_COOPERATIVE | MTF_DEATHMATCH; // EDF uses inverse logic, like Doom.exe sc.MustGetString(); if (sc.Compare("recordnum")) { @@ -505,7 +533,8 @@ static void parseMapthing(FScanner &sc) } else { - //Let's hope not something internal to Eternity... + // 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); } @@ -531,6 +560,7 @@ static void parseMapthing(FScanner &sc) } else if (sc.Compare("options")) { + sc.CheckString("="); do { sc.MustGetString(); @@ -554,54 +584,98 @@ static void parseMapthing(FScanner &sc) sc.ScriptError("Unknown property '%s'", sc.String); } } + EDFThings[mt.recordnum] = mt; } -void loadEDF() +void InitEDF() { FString filename; FScanner sc; - EDFLines.Clear(); - EDFSectors.Clear(); - EDFThings.Clear(); - - const char *arg = Args->CheckValue("-edf"); - - if (arg != NULL) filename = arg; - else + if (EDFMap.CompareNoCase(level.MapName) != 0) { - FEdfOptions *opt = level.info->GetOptData("EDF", false); - if (opt != NULL) - { - filename = opt->edfName; - } - } + EDFLines.Clear(); + EDFSectors.Clear(); + EDFThings.Clear(); + EDFMap = level.MapName; - if (filename.IsEmpty()) return; - int lump = Wads.CheckNumForFullName(filename, true, ns_global); - if (lump == -1) return; - sc.OpenLumpNum(lump); + const char *arg = Args->CheckValue("-edf"); - 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); - } + if (arg != NULL) filename = arg; else { - sc.ScriptError("Unknown keyword '%s'", sc.String); + FEdfOptions *opt = level.info->GetOptData("EDF", false); + if (opt != NULL) + { + filename = opt->edfName; + } + } + + 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 ProcessEDFMapthing(FMapThing *mt, int recordnum) +{ + InitEDF(); + + EDFMapthing *emt = EDFThings.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 ProcessEDFLinedef(line_t *ld, int recordnum) +{ + InitEDF(); + + EDFLinedef *eld = EDFLines.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); +} -} \ No newline at end of file diff --git a/src/g_doomedmap.cpp b/src/g_doomedmap.cpp index 42157101d..9a2cc137d 100644 --- a/src/g_doomedmap.cpp +++ b/src/g_doomedmap.cpp @@ -69,6 +69,7 @@ const char *SpecialMapthingNames[] = { "$CopyCeilingPlane", "$VertexFloorZ", "$VertexCeilingZ", + "$EDFThing", }; //========================================================================== diff --git a/src/info.h b/src/info.h index 22e3b2f5c..cd32f2f1b 100644 --- a/src/info.h +++ b/src/info.h @@ -313,6 +313,7 @@ enum ESpecialMapthings SMT_CopyCeilingPlane, SMT_VertexFloorZ, SMT_VertexCeilingZ, + SMT_EDFThing, }; diff --git a/src/p_lnspec.h b/src/p_lnspec.h index 9fb4c17b3..3f97c75e6 100644 --- a/src/p_lnspec.h +++ b/src/p_lnspec.h @@ -60,6 +60,8 @@ typedef enum { Init_Damage = 2, Init_SectorLink = 3, NUM_STATIC_INITS, + Init_EDFSector = 253, + Init_EDFLine = 254, Init_TransferSky = 255 } staticinit_t; diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 3749e97aa..6bbb85035 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -68,6 +68,9 @@ #include "po_man.h" #include "r_renderer.h" #include "r_data/colormaps.h" +#ifndef NO_EDF +#include "edf.h" +#endif #include "fragglescript/t_fs.h" @@ -1759,34 +1762,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_EDF + if (mti[i].info != NULL && mti[i].info->Special == SMT_EDFThing) + { + ProcessEDFMapthing(&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; } @@ -2157,7 +2171,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 EDF lines. + if (ld->special != Static_Init || (ld->args[1] != Init_EDFLine && ld->args[1] != Init_EDFSector)) + { + tagManager.AddLineID(i, mld->tag); + } +#ifndef NO_EDF + if (ld->special == Static_Init && ld->args[1] == Init_EDFLine) + { + ProcessEDFLinedef(ld, mld->tag); + } +#endif ld->v1 = &vertexes[LittleShort(mld->v1)]; ld->v2 = &vertexes[LittleShort(mld->v2)]; @@ -3325,7 +3351,7 @@ void P_LoadBehavior (MapData * map) void P_GetPolySpots (MapData * map, TArray &spots, TArray &anchors) { - if (map->HasBehavior) + //if (map->HasBehavior) { for (unsigned int i = 0; i < MapThingsConverted.Size(); ++i) { diff --git a/src/p_tags.cpp b/src/p_tags.cpp index 15528378b..50e5694a3 100644 --- a/src/p_tags.cpp +++ b/src/p_tags.cpp @@ -118,6 +118,28 @@ void FTagManager::RemoveSectorTags(int sect) // //----------------------------------------------------------------------------- +void FTagManager::RemoveLineIDs(int sect) +{ + if (startForLine.Size() > (unsigned int)sect) + { + int start = startForLine[sect]; + if (start >= 0) + { + while (allIDs[start].target == sect) + { + allIDs[start].tag = allIDs[start].target = -1; + start++; + } + } + } +} + +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- + void FTagManager::AddLineID(int line, int tag) { if (tag == -1) return; // For line IDs -1 means 'not set', unlike sectors. diff --git a/src/p_tags.h b/src/p_tags.h index c3162d9b5..e196600a6 100644 --- a/src/p_tags.h +++ b/src/p_tags.h @@ -64,6 +64,7 @@ public: void AddSectorTag(int sector, int tag); void AddLineID(int line, int tag); void RemoveSectorTags(int sect); + void RemoveLineIDs(int sect); void DumpTags(); }; diff --git a/wadsrc/static/mapinfo/eternity.txt b/wadsrc/static/mapinfo/eternity.txt new file mode 100644 index 000000000..ad0bab886 --- /dev/null +++ b/wadsrc/static/mapinfo/eternity.txt @@ -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 = "$EDFThing" +} + diff --git a/wadsrc/static/xlat/eternity.txt b/wadsrc/static/xlat/eternity.txt index d1cb400f5..02fbc0303 100644 --- a/wadsrc/static/xlat/eternity.txt +++ b/wadsrc/static/xlat/eternity.txt @@ -8,11 +8,18 @@ define Unsupported (0) +enum +{ + Init_EDFSector = 253, + Init_EDFLine = 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_EDFLine) // "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) @@ -62,6 +69,7 @@ define Unsupported (0) // Hexen format is incomplete; and Quasar wants to use ZDoom-compatible special values for UDMF. // The translation here is for the odd EDF that specifies them as numbers. +/* 300 = 0, Door_Raise(0) 301 = 0, Door_Open(0) 302 = 0, Door_Close(0) @@ -106,6 +114,7 @@ define Unsupported (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" @@ -186,6 +195,8 @@ define Unsupported (0) 399 = 0, Thing_SpawnNoFog(0) 400 = 0, Teleport_EndGame(0) +401 = 0, Static_Init(tag, Init_EDFSector) + 402 = 0, Thing_Projectile(0) 403 = 0, Thing_ProjectileGravity(0) 404 = 0, Thing_Activate(0)