diff --git a/source/core/maphack.cpp b/source/core/maphack.cpp index eb0158126..d9d0ddb3c 100644 --- a/source/core/maphack.cpp +++ b/source/core/maphack.cpp @@ -163,107 +163,6 @@ static int32_t LoadMapHack(const char *filename, SpawnSpriteDef& sprites) } } } - else if (sc.Compare("picnum")) - { - if (sc.CheckNumber()) - { - if (currentwall != -1 && validateWall()) - { - wall[currentwall].picnum = sc.Number; - } - else if (currentsprite != -1 && validateSprite()) - { - sprites.sprites[currentsprite].picnum = sc.Number; - } - } - } - else if (sc.Compare("overpicnum")) - { - if (sc.CheckNumber() && validateWall()) - { - wall[currentwall].overpicnum = sc.Number; - } - } - else if (sc.Compare("overpicnum")) - { - if (sc.CheckNumber() && validateWall()) - { - wall[currentwall].overpicnum = sc.Number; - } - } - else if (sc.Compare("split")) - { - int start = -1, end = -1; - if (sc.CheckNumber()) start = sc.Number; - if (sc.CheckNumber()) end = sc.Number; - if (end >= 0 && validateSector()) - { - hw_SetSplitSector(currentsector, start, end); - } - } - else if (sc.Compare("dontclip")) - { - sector[currentsector].exflags |= SECTOREX_DONTCLIP; - } - else if (sc.Compare("clearflags")) - { - if (currentsector != -1 && validateSector()) - { - sc.GetString(); - if (sc.Compare("floor") && sc.CheckNumber()) - { - sector[currentsector].floorstat &= ESectorFlags::FromInt(~sc.Number); - } - else if (sc.Compare("ceiling") && sc.CheckNumber()) - { - sector[currentsector].ceilingstat &= ESectorFlags::FromInt(~sc.Number); - } - else sc.ScriptError("Bad token %s", sc.String); - } - else if (sc.CheckNumber()) - { - if (currentwall != -1 && validateWall()) - { - wall[currentwall].cstat &= EWallFlags::FromInt(~sc.Number); - } - else if (currentsprite != -1 && validateSprite()) - { - sprites.sprites[currentsprite].cstat &= ESpriteFlags::FromInt(~sc.Number); - } - } - } - else if (sc.Compare("setflags")) - { - if (sc.CheckNumber()) - { - if (currentwall != -1 && validateWall()) - { - wall[currentwall].cstat |= EWallFlags::FromInt(sc.Number); - } - else if (currentsprite != -1 && validateSprite()) - { - sprites.sprites[currentsprite].cstat |= ESpriteFlags::FromInt(sc.Number); - } - } - } - else if (sc.Compare("lotag")) - { - if (sc.CheckNumber()) - { - if (currentwall != -1 && validateWall()) - { - wall[currentwall].lotag = sc.Number; - } - else if (currentsprite != -1 && validateSprite()) - { - sprites.sprites[currentsprite].lotag = sc.Number; - } - } - } - else if (sc.Compare("sw_serp_continue")) // This is a hack for SW's Last Warrior mod to continue from L4 to L5. - { - if (currentLevel) currentLevel->gameflags |= LEVEL_SW_DEATHEXIT_SERPENT_NEXT; - } else if (sc.Compare("angleoff") || sc.Compare("angoff")) { @@ -383,8 +282,6 @@ static int32_t LoadMapHack(const char *filename, SpawnSpriteDef& sprites) void loadMapHack(const char* filename, const uint8_t* md4, SpawnSpriteDef& sprites) { - hw_ClearSplitSector(); - FString internal = "engine/compatibility/"; for (int j = 0; j < 16; ++j) { diff --git a/source/core/maploader.cpp b/source/core/maploader.cpp index 298f08af2..66e639f7d 100644 --- a/source/core/maploader.cpp +++ b/source/core/maploader.cpp @@ -543,6 +543,7 @@ void loadMap(const char* filename, int flags, DVector3* pos, int16_t* ang, secto auto buffer = fr.Read(); uint8_t md4[16]; md4once(buffer.Data(), buffer.Size(), md4); + PostProcessLevel(md4, filename, sprites); loadMapHack(filename, md4, sprites); setWallSectors(); hw_CreateSections(); diff --git a/source/core/maptypes.h b/source/core/maptypes.h index 4b848490b..c50836d6b 100644 --- a/source/core/maptypes.h +++ b/source/core/maptypes.h @@ -698,6 +698,7 @@ TArray loadMapWalls(const char* filename); void loadMapBackup(const char* filename); void loadMapHack(const char* filename, const uint8_t*, SpawnSpriteDef& sprites); void validateStartSector(const char* filename, const DVector3& pos, sectortype** cursectnum, unsigned numsectors, bool noabort = false); +void PostProcessLevel(const uint8_t* checksum, const FString& mapname, SpawnSpriteDef& sprites); // should only be used to read angles from map-loaded data (for proper documentation) constexpr DAngle mapangle(int mapang) diff --git a/source/core/postprocessor.cpp b/source/core/postprocessor.cpp index 7a48052e7..2230a7beb 100644 --- a/source/core/postprocessor.cpp +++ b/source/core/postprocessor.cpp @@ -37,6 +37,9 @@ #include "vm.h" #include "printf.h" #include "types.h" +#include "maptypes.h" +#include "hw_sections.h" +#include "mapinfo.h" //========================================================================== // @@ -48,13 +51,21 @@ class DLevelPostProcessor : public DObject { DECLARE_ABSTRACT_CLASS(DLevelPostProcessor, DObject) public: + SpawnSpriteDef* sprites; }; IMPLEMENT_CLASS(DLevelPostProcessor, true, false); -void PostProcessLevel(FName checksum, const FString& mapname) +void PostProcessLevel(const uint8_t* md4, const FString& mapname, SpawnSpriteDef& sprites) { + hw_ClearSplitSector(); auto lc = Create(); + lc->sprites = &sprites; + + char md4string[33]; + for (int i = 0; i < 16; i++) mysnprintf(md4string + 2 * i, 3, "%02x", md4[i]); + FName checksum(md4string, true); + if (checksum == NAME_None) return; // we do not have anything so save the work. for(auto cls : PClass::AllClasses) { @@ -83,21 +94,47 @@ void PostProcessLevel(FName checksum, const FString& mapname) DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SetSpriteLotag) { PARAM_SELF_PROLOGUE(DLevelPostProcessor); - PARAM_INT(sprite); + PARAM_UINT(sprite); PARAM_INT(lotag); - - // todo + if (sprite < self->sprites->sprites.Size()) + self->sprites->sprites[sprite].lotag = lotag; + return 0; } DEFINE_ACTION_FUNCTION(DLevelPostProcessor, ChangeSpriteFlags) { PARAM_SELF_PROLOGUE(DLevelPostProcessor); - PARAM_INT(sprite); + PARAM_UINT(sprite); PARAM_INT(clearmask); - PARAM_INT(setflag); + PARAM_INT(setmask); + + if (sprite < self->sprites->sprites.Size()) + self->sprites->sprites[sprite].cstat = (self->sprites->sprites[sprite].cstat & ~ESpriteFlags::FromInt(clearmask)) | ESpriteFlags::FromInt(setmask); - // todo return 0; } +DEFINE_ACTION_FUNCTION(DLevelPostProcessor, SplitSector) +{ + PARAM_SELF_PROLOGUE(DLevelPostProcessor); + PARAM_UINT(sectornum); + PARAM_INT(firstwall); + PARAM_INT(secondwall); + + if (sectornum < sector.Size()) + { + if (firstwall >= sector[sectornum].wallptr && firstwall < sector[sectornum].wallptr + sector[sectornum].wallnum && + secondwall >= sector[sectornum].wallptr && secondwall < sector[sectornum].wallptr + sector[sectornum].wallnum) + + hw_SetSplitSector(sectornum, firstwall, secondwall); + } + return 0; +} + +DEFINE_ACTION_FUNCTION(DLevelPostProcessor, sw_serp_continue) +{ + PARAM_SELF_PROLOGUE(DLevelPostProcessor); + currentLevel->gameflags |= LEVEL_SW_DEATHEXIT_SERPENT_NEXT; + return 0; +} diff --git a/source/core/thingdef_data.cpp b/source/core/thingdef_data.cpp index 62282497d..da391588f 100644 --- a/source/core/thingdef_data.cpp +++ b/source/core/thingdef_data.cpp @@ -293,7 +293,7 @@ void InitThingdef() //secplanestruct->Size = sizeof(secplane_t); //secplanestruct->Align = alignof(secplane_t); - auto sectorstruct = NewStruct("Sector", nullptr, true); + auto sectorstruct = NewStruct("sectortype", nullptr, true); sectorstruct->Size = sizeof(sectortype); sectorstruct->Align = alignof(sectortype); NewPointer(sectorstruct, false)->InstallHandlers( @@ -308,7 +308,7 @@ void InitThingdef() } ); - auto linestruct = NewStruct("Wall", nullptr, true); + auto linestruct = NewStruct("walltype", nullptr, true); linestruct->Size = sizeof(walltype); linestruct->Align = alignof(walltype); NewPointer(linestruct, false)->InstallHandlers( diff --git a/source/core/vmexports.cpp b/source/core/vmexports.cpp index 98b814c11..2cc9b5133 100644 --- a/source/core/vmexports.cpp +++ b/source/core/vmexports.cpp @@ -35,6 +35,7 @@ #include "maptypes.h" #include "vm.h" +#include "gamefuncs.h" //============================================================================= // @@ -496,6 +497,21 @@ DEFINE_ACTION_FUNCTION_NATIVE(_walltype, move, wall_move) return 0; } +void wall_dragpoint(walltype* wal, double x, double y) +{ + if (!wal) ThrowAbortException(X_READ_NIL, nullptr); + dragpoint(wal, DVector2(x, y)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_walltype, dragpoint, wall_dragpoint) +{ + PARAM_SELF_STRUCT_PROLOGUE(walltype); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + wall_dragpoint(self, x, y); + return 0; +} + int wall_twosided(walltype* wal) { if (!wal) ThrowAbortException(X_READ_NIL, nullptr); diff --git a/source/games/blood/src/db.cpp b/source/games/blood/src/db.cpp index 49b5064e4..68e921aa8 100644 --- a/source/games/blood/src/db.cpp +++ b/source/games/blood/src/db.cpp @@ -593,6 +593,7 @@ void dbLoadMap(const char* pPath, DVector3& pos, short* pAngle, sectortype** cur auto buffer = fr.Read(); uint8_t md4[16]; md4once(buffer.Data(), buffer.Size(), md4); + PostProcessLevel(md4, mapname, sprites); loadMapHack(mapname, md4, sprites); if (CalcCRC32(buffer.Data(), buffer.Size() - 4) != nCRC) diff --git a/source/games/duke/src/premap_r.cpp b/source/games/duke/src/premap_r.cpp index 539087c68..4daf49134 100644 --- a/source/games/duke/src/premap_r.cpp +++ b/source/games/duke/src/premap_r.cpp @@ -421,11 +421,6 @@ void prelevel_r(int g, TArray& actors) prelevel_common(g); p = &ps[screenpeek]; - if (currentLevel->levelNumber == 1001 && wall.Size() > 4687 && wall[4592].pos.X == 1612 && wall[4592].pos.Y == -2714) // fix sector overlap in E1L1 Taylor Town - { - dragpoint(&wall[4592], { 1615., -2715. }); - } - if (currentLevel->gameflags & LEVEL_RR_CLEARMOONSHINE) ps[myconnectindex].steroids_amount = 0; diff --git a/wadsrc/static/engine/compatibility/24c7b1434070dbe01fa83c6a48926ed9.mhk b/wadsrc/static/engine/compatibility/24c7b1434070dbe01fa83c6a48926ed9.mhk deleted file mode 100644 index b0b19900a..000000000 --- a/wadsrc/static/engine/compatibility/24c7b1434070dbe01fa83c6a48926ed9.mhk +++ /dev/null @@ -1,2 +0,0 @@ -// RR E1L1.map sector bleeds into another area. -sector 47 split 367 375 diff --git a/wadsrc/static/engine/compatibility/25d4164814f10cd71d26d52d494c4fb8.mhk b/wadsrc/static/engine/compatibility/25d4164814f10cd71d26d52d494c4fb8.mhk deleted file mode 100644 index f1999796f..000000000 --- a/wadsrc/static/engine/compatibility/25d4164814f10cd71d26d52d494c4fb8.mhk +++ /dev/null @@ -1,2 +0,0 @@ -// Wanton Destruction $auto.map - workaround for sector object overlapping with an outer wall. -sector 152 dontclip diff --git a/wadsrc/static/engine/compatibility/2bac4971499306ee6c86462e6a03dae8.mhk b/wadsrc/static/engine/compatibility/2bac4971499306ee6c86462e6a03dae8.mhk deleted file mode 100644 index ba819ff93..000000000 --- a/wadsrc/static/engine/compatibility/2bac4971499306ee6c86462e6a03dae8.mhk +++ /dev/null @@ -1,4 +0,0 @@ -// bad sky setting in WT's $volcano.map (original version) -sector 118 clearflags ceiling 1 -sector 57 clearflags ceiling 1 -sector 281 clearflags ceiling 1 diff --git a/wadsrc/static/engine/compatibility/491a04a732cd5aa253703216ff2feff4.mhk b/wadsrc/static/engine/compatibility/491a04a732cd5aa253703216ff2feff4.mhk deleted file mode 100644 index e4ce92728..000000000 --- a/wadsrc/static/engine/compatibility/491a04a732cd5aa253703216ff2feff4.mhk +++ /dev/null @@ -1,2 +0,0 @@ -// missing texture in RR E1L2. -wall 3312 setflags 2 diff --git a/wadsrc/static/engine/compatibility/4f2233ed8fb32f6a3deebc7803dbed69.mhk b/wadsrc/static/engine/compatibility/4f2233ed8fb32f6a3deebc7803dbed69.mhk deleted file mode 100644 index dcfb54fc5..000000000 --- a/wadsrc/static/engine/compatibility/4f2233ed8fb32f6a3deebc7803dbed69.mhk +++ /dev/null @@ -1,3 +0,0 @@ -// SW $plax1.map sector bleeds into another area. -sector 64 split 281 283 - diff --git a/wadsrc/static/engine/compatibility/5e49c7f6c496e337d59d0c072ed1879b.mhk b/wadsrc/static/engine/compatibility/5e49c7f6c496e337d59d0c072ed1879b.mhk deleted file mode 100644 index f50cd8af8..000000000 --- a/wadsrc/static/engine/compatibility/5e49c7f6c496e337d59d0c072ed1879b.mhk +++ /dev/null @@ -1,3 +0,0 @@ -// SW $bath.ap sector bleeds into another area. -sector 198 split 1105 1125 - diff --git a/wadsrc/static/engine/compatibility/67207fb90130ad561479301c0970c7ba.mhk b/wadsrc/static/engine/compatibility/67207fb90130ad561479301c0970c7ba.mhk deleted file mode 100644 index 388eced27..000000000 --- a/wadsrc/static/engine/compatibility/67207fb90130ad561479301c0970c7ba.mhk +++ /dev/null @@ -1,4 +0,0 @@ -// bad sky setting in WT's $volcano.map (fixed version) -sector 118 clearflags ceiling 1 -sector 57 clearflags ceiling 1 -sector 281 clearflags ceiling 1 diff --git a/wadsrc/static/engine/compatibility/745182e393945e0d308e8e0a5ee80c3c.mhk b/wadsrc/static/engine/compatibility/745182e393945e0d308e8e0a5ee80c3c.mhk deleted file mode 100644 index a3906bbb4..000000000 --- a/wadsrc/static/engine/compatibility/745182e393945e0d308e8e0a5ee80c3c.mhk +++ /dev/null @@ -1,2 +0,0 @@ -// SW's Last Warrior level 4. Do not make the serpent's death end the game. The menu has no second episode so this needs to continue. -sw_serp_continue diff --git a/wadsrc/static/engine/compatibility/b4ee363e9d15adc5c9becd01520acd23.mhk b/wadsrc/static/engine/compatibility/b4ee363e9d15adc5c9becd01520acd23.mhk deleted file mode 100644 index 8eb89748a..000000000 --- a/wadsrc/static/engine/compatibility/b4ee363e9d15adc5c9becd01520acd23.mhk +++ /dev/null @@ -1,3 +0,0 @@ -// SW $outpost.map -// silence a misplaced and *very* annoying ambient sound. -sprite 442 lotag -1 diff --git a/wadsrc/static/engine/compatibility/c3bfb6a6e7cded2e5fe16cea86632d79.mhk b/wadsrc/static/engine/compatibility/c3bfb6a6e7cded2e5fe16cea86632d79.mhk deleted file mode 100644 index 5d24c10b7..000000000 --- a/wadsrc/static/engine/compatibility/c3bfb6a6e7cded2e5fe16cea86632d79.mhk +++ /dev/null @@ -1,2 +0,0 @@ -// CP07 sector bleeds into another area. -sector 33 split 192 196 diff --git a/wadsrc/static/engine/compatibility/c6f9e49e397c0b424e8030abc23ac003.mhk b/wadsrc/static/engine/compatibility/c6f9e49e397c0b424e8030abc23ac003.mhk deleted file mode 100644 index 6b7284136..000000000 --- a/wadsrc/static/engine/compatibility/c6f9e49e397c0b424e8030abc23ac003.mhk +++ /dev/null @@ -1,3 +0,0 @@ -// flip inverted keyholes in TD's $shore.map -sprite 298 clearflags 8 -sprite 307 clearflags 8 diff --git a/wadsrc/static/engine/compatibility/ef6331237eb36c84a4f7b9f5c3cd225d.mhk b/wadsrc/static/engine/compatibility/ef6331237eb36c84a4f7b9f5c3cd225d.mhk deleted file mode 100644 index dd4806a2d..000000000 --- a/wadsrc/static/engine/compatibility/ef6331237eb36c84a4f7b9f5c3cd225d.mhk +++ /dev/null @@ -1,2 +0,0 @@ -// flip the inverted card reader in TD's level 10. -sprite 179 clearflags 12 diff --git a/wadsrc/static/zscript/level_compatibility.zs b/wadsrc/static/zscript/level_compatibility.zs index 52192b199..70c2264fe 100644 --- a/wadsrc/static/zscript/level_compatibility.zs +++ b/wadsrc/static/zscript/level_compatibility.zs @@ -7,6 +7,64 @@ class LevelCompatibility : LevelPostProcessor { case 'none': return; + + case 'c3bfb6a6e7cded2e5fe16cea86632d79': // CP07 + SplitSector(33, 192, 196); // sector bleeds into another area. + break; + + case '24c7b1434070dbe01fa83c6a48926ed9': // RR E1L1.map + SplitSector(47, 367, 375); // sector bleeds into another area. + wall[4592].dragpoint((1615., -2715.)); // fix overlapping sectors + break; + + case 'd7bf49213531cd2607e0459b950ac454': // RR E2L7.map + // need to add a sprite with picnum 11 (RRJAILDOOR) lotag = 48, hitag = 32, sector = 534 + // see premap_r.cpp, line 477. + break; + + case '491a04a732cd5aa253703216ff2feff4': // RR E1L2.map + wall[3312].cstat |= CSTAT_WALL_BOTTOM_SWAP; // missing lower texture . + break; + + case '4f2233ed8fb32f6a3deebc7803dbed69': // SW $plax.map + SplitSector(64, 281, 283); // sector bleeds into another area. + break; + + case '5e49c7f6c496e337d59d0c072ed1879b': // SW $bath.map + SplitSector(198, 1105, 1125); // sector bleeds into another area. + break; + + case 'b4ee363e9d15adc5c9becd01520acd23': // SW $outpost.map + SetSpriteLotag(442, -1); // silence a misplaced and *very* annoying ambient sound. + break; + + case '25d4164814f10cd71d26d52d494c4fb8': // WT $auto.map + sector[152].exflags |= SECTOREX_DONTCLIP; // workaround for sector object overlapping with an outer wall. + break; + + case '2bac4971499306ee6c86462e6a03dae8': // WT $volcano.map (original version) + case '67207fb90130ad561479301c0970c7ba': // WT $volcano.map (fixed version) + sector[118].ceilingstat &= ~CSTAT_SECTOR_SKY; + sector[57].ceilingstat &= ~CSTAT_SECTOR_SKY; + sector[281].ceilingstat &= ~CSTAT_SECTOR_SKY; + break; + + case '745182e393945e0d308e8e0a5ee80c3c': // SW Last Warrior level 4. + sw_serp_continue(); // Do not make the serpent's death end the game. The menu has no second episode so this needs to continue. + break; + + case 'c6f9e49e397c0b424e8030abc23ac003': // TD $shore.map + ChangeSpriteFlags(298, CSTAT_SPRITE_YFLIP, 0); // flip inverted keyhole + ChangeSpriteFlags(307, CSTAT_SPRITE_YFLIP, 0); // flip inverted keyhole + break; + + case 'ef6331237eb36c84a4f7b9f5c3cd225d': // TD level 10 + ChangeSpriteFlags(179, CSTAT_SPRITE_XFLIP | CSTAT_SPRITE_YFLIP, 0); // flip the inverted card reader + break; + + + + } } } diff --git a/wadsrc/static/zscript/level_postprocessor.zs b/wadsrc/static/zscript/level_postprocessor.zs index 9af905a9d..02ec4cab0 100644 --- a/wadsrc/static/zscript/level_postprocessor.zs +++ b/wadsrc/static/zscript/level_postprocessor.zs @@ -7,4 +7,6 @@ class LevelPostProcessor native play protected native void SetSpriteLotag(int sprite, int tag); protected native void ChangeSpriteFlags(int sprite, int set, int clear); + protected native void sw_serp_continue(); + protected native void SplitSector(int sect, int wal1, int wal2); } diff --git a/wadsrc/static/zscript/maptypes.zs b/wadsrc/static/zscript/maptypes.zs index 594ff4ec7..1e640bd31 100644 --- a/wadsrc/static/zscript/maptypes.zs +++ b/wadsrc/static/zscript/maptypes.zs @@ -99,6 +99,13 @@ enum ETSprFlags TSPR_SLOPESPRITE = 8, // render as sloped sprite } +enum ESectorExBits +{ + SECTOREX_CLOUDSCROLL = 1, + SECTOREX_DRAGGED = 2, + SECTOREX_DONTCLIP = 4, +}; + //============================================================================= @@ -262,6 +269,7 @@ struct walltype native native double Length(); native void move(Vector2 vec); + native void dragpoint(Vector2 vec); } //=============================================================================