diff --git a/src/d_main.cpp b/src/d_main.cpp index cac75766f..cefd446b9 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -530,9 +530,6 @@ CVAR (Flag, sv_respawnsuper, dmflags2, DF2_RESPAWN_SUPER); // //========================================================================== -int i_compatflags, i_compatflags2; // internal compatflags composed from the compatflags CVAR and MAPINFO settings -int ii_compatflags, ii_compatflags2, ib_compatflags; - EXTERN_CVAR(Int, compatmode) static int GetCompatibility(FLevelLocals *Level, int mask) @@ -549,17 +546,24 @@ static int GetCompatibility2(FLevelLocals *Level, int mask) CUSTOM_CVAR (Int, compatflags, 0, CVAR_ARCHIVE|CVAR_SERVERINFO) { - int old = i_compatflags; - i_compatflags = GetCompatibility(&level, self) | ii_compatflags; - if ((old ^ i_compatflags) & COMPATF_POLYOBJ) + for (auto Level : AllLevels()) { - level.ClearAllSubsectorLinks(); + int old = Level->i_compatflags; + Level->i_compatflags = GetCompatibility(Level, self) | Level->ii_compatflags; + if ((old ^ Level->i_compatflags) & COMPATF_POLYOBJ) + { + Level->ClearAllSubsectorLinks(); + } } } CUSTOM_CVAR (Int, compatflags2, 0, CVAR_ARCHIVE|CVAR_SERVERINFO) { - i_compatflags2 = GetCompatibility2(&level, self) | ii_compatflags2; + for (auto Level : AllLevels()) + { + Level->i_compatflags2 = GetCompatibility2(Level, self) | Level->ii_compatflags2; + Level->SetCompatLineOnSide(true); + } } CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL) diff --git a/src/doomdata.h b/src/doomdata.h index ee0b21f32..05bcfbfc1 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -151,7 +151,9 @@ enum ELineFlags : unsigned ML_MAPPED = 0x00000100, // set if already drawn in automap ML_REPEAT_SPECIAL = 0x00000200, // special is repeatable + // 0x400, 0x800 and 0x1000 are ML_SPAC_MASK, they can be used for internal things but not for real map flags. ML_ADDTRANS = 0x00000400, // additive translucency (can only be set internally) + ML_COMPATSIDE = 0x00000800, // for compatible PointOnLineSide checks. Using the global compatibility check would be a bit expensive for this check. // Extended flags ML_MONSTERSCANACTIVATE = 0x00002000, // [RH] Monsters (as well as players) can activate the line diff --git a/src/doomstat.h b/src/doomstat.h index 6f0007f4c..23356b25f 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -248,7 +248,6 @@ EXTERN_CVAR (Int, dmflags2); // [BC] EXTERN_CVAR (Int, compatflags); EXTERN_CVAR (Int, compatflags2); -extern int i_compatflags, i_compatflags2, ii_compatflags, ii_compatflags2, ib_compatflags; // Filters from AddAutoloadFiles(). Used to filter files from archives. extern FString LumpFilterIWAD; diff --git a/src/dsectoreffect.cpp b/src/dsectoreffect.cpp index adc9c5f0a..8fbf3c8a7 100644 --- a/src/dsectoreffect.cpp +++ b/src/dsectoreffect.cpp @@ -214,7 +214,7 @@ EMoveResult sector_t::MoveFloor(double speed, double dest, int crush, int direct //destheight = (dest < ceilingheight) ? dest : ceilingheight; if (!ceilingplane.isSlope() && !floorplane.isSlope() && !PortalIsLinked(sector_t::ceiling) && - (!(i_compatflags2 & COMPATF2_FLOORMOVE) && -dest > ceilingplane.fD())) + (!(Level->i_compatflags2 & COMPATF2_FLOORMOVE) && -dest > ceilingplane.fD())) { dest = -ceilingplane.fD(); } @@ -304,7 +304,7 @@ EMoveResult sector_t::MoveCeiling(double speed, double dest, int crush, int dire //destheight = (dest > floorheight) ? dest : floorheight; if (!ceilingplane.isSlope() && !floorplane.isSlope() && !PortalIsLinked(sector_t::floor) && - (!(i_compatflags2 & COMPATF2_FLOORMOVE) && dest < -floorplane.fD())) + (!(Level->i_compatflags2 & COMPATF2_FLOORMOVE) && dest < -floorplane.fD())) { dest = -floorplane.fD(); } diff --git a/src/g_level.cpp b/src/g_level.cpp index 8bc9ab97d..5491367ad 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -578,7 +578,7 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill Printf (TEXTCOLOR_RED "Unloading scripts cannot exit the level again.\n"); return; } - if (gameaction == ga_completed && !(i_compatflags2 & COMPATF2_MULTIEXIT)) // do not exit multiple times. + if (gameaction == ga_completed && !(level.i_compatflags2 & COMPATF2_MULTIEXIT)) // do not exit multiple times. { return; } @@ -1070,7 +1070,7 @@ void G_DoLoadLevel (const FString &nextmapname, int position, bool autosave, boo level.starttime = gametic; level.UnSnapshotLevel (!savegamerestore); // [RH] Restore the state of the level. - int pnumerr = G_FinishTravel (); + int pnumerr = level.FinishTravel (); if (!level.FromSnapshot) { @@ -2075,6 +2075,21 @@ int FLevelLocals::GetInfighting() return G_SkillProperty(SKILLP_Infight); } +//============================================================================ +// +// transfers the compatiblity flag for old PointOnLineSide to each line. +// This gets checked in a frequently called worker function and the closer +// this info is to the data this function works on, the better. +// +//============================================================================ + +void FLevelLocals::SetCompatLineOnSide(bool state) +{ + int on = (state && (i_compatflags2 & COMPATF2_POINTONLINE)); + if (on) for (auto l : lines) l.flags |= ML_COMPATSIDE; + else for (auto l : lines) l.flags &= ML_COMPATSIDE; +} + //========================================================================== // IsPointInMap // diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 758370db5..aa19b989e 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -120,6 +120,7 @@ struct FLevelLocals void SetConversation(int convid, PClassActor *Class, int dlgindex); int FindNode (const FStrifeDialogueNode *node); int GetInfighting(); + void SetCompatLineOnSide(bool state); void Init(); private: @@ -442,6 +443,12 @@ public: FDialogueIDMap DialogueRoots; FDialogueMap ClassRoots; + int ii_compatflags = 0; + int ii_compatflags2 = 0; + int ib_compatflags = 0; + int i_compatflags = 0; + int i_compatflags2 = 0; + uint8_t md5[16]; // for savegame validation. If the MD5 does not match the savegame won't be loaded. int time; // time in the hub int maptime; // time in the map diff --git a/src/hwrenderer/scene/hw_drawlist.cpp b/src/hwrenderer/scene/hw_drawlist.cpp index f50c49b8b..b6f4859f1 100644 --- a/src/hwrenderer/scene/hw_drawlist.cpp +++ b/src/hwrenderer/scene/hw_drawlist.cpp @@ -588,7 +588,7 @@ inline int HWDrawList::CompareSprites(SortNode * a,SortNode * b) int res = s1->depth - s2->depth; if (res != 0) return -res; - else return (i_compatflags & COMPATF_SPRITESORT)? s2->index-s1->index : s1->index-s2->index; + else return reverseSort? s2->index-s1->index : s1->index-s2->index; } //========================================================================== @@ -702,6 +702,7 @@ SortNode * HWDrawList::DoSort(HWDrawInfo *di, SortNode * head) //========================================================================== void HWDrawList::Sort(HWDrawInfo *di) { + reverseSort = !!(di->Level->i_compatflags & COMPATF_SPRITESORT); SortZ = di->Viewpoint.Pos.Z; MakeSortList(); sorted = DoSort(di, SortNodes[SortNodeStart]); diff --git a/src/hwrenderer/scene/hw_drawlist.h b/src/hwrenderer/scene/hw_drawlist.h index 66ae468ed..e4279516c 100644 --- a/src/hwrenderer/scene/hw_drawlist.h +++ b/src/hwrenderer/scene/hw_drawlist.h @@ -67,6 +67,7 @@ struct HWDrawList int SortNodeStart; float SortZ; SortNode * sorted; + bool reverseSort; public: HWDrawList() diff --git a/src/hwrenderer/scene/hw_walls.cpp b/src/hwrenderer/scene/hw_walls.cpp index 9b42ac5cc..91ec1a5f8 100644 --- a/src/hwrenderer/scene/hw_walls.cpp +++ b/src/hwrenderer/scene/hw_walls.cpp @@ -2068,7 +2068,7 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_ FTexture *tex = TexMan.GetTexture(seg->sidedef->GetTexture(side_t::mid), true); if (tex != NULL) { - if (i_compatflags & COMPATF_MASKEDMIDTEX) + if (di->Level->i_compatflags & COMPATF_MASKEDMIDTEX) { tex = tex->GetRawTexture(); } diff --git a/src/maploader/compatibility.cpp b/src/maploader/compatibility.cpp index 1c9ed5c60..f3a424cac 100644 --- a/src/maploader/compatibility.cpp +++ b/src/maploader/compatibility.cpp @@ -279,17 +279,17 @@ FName MapLoader::CheckCompatibility(MapData *map) if (BCompatMap.CountUsed() == 0) ParseCompatibility(); - ii_compatflags = 0; - ii_compatflags2 = 0; - ib_compatflags = 0; + Level->ii_compatflags = 0; + Level->ii_compatflags2 = 0; + Level->ib_compatflags = 0; // When playing Doom IWAD levels force COMPAT_SHORTTEX and COMPATF_LIGHT. // I'm not sure if the IWAD maps actually need COMPATF_LIGHT but it certainly does not hurt. // TNT's MAP31 also needs COMPATF_STAIRINDEX but that only gets activated for TNT.WAD. if (Wads.GetLumpFile(map->lumpnum) == Wads.GetIwadNum() && (gameinfo.flags & GI_COMPATSHORTTEX) && Level->maptype == MAPTYPE_DOOM) { - ii_compatflags = COMPATF_SHORTTEX|COMPATF_LIGHT; - if (gameinfo.flags & GI_COMPATSTAIRS) ii_compatflags |= COMPATF_STAIRINDEX; + Level->ii_compatflags = COMPATF_SHORTTEX|COMPATF_LIGHT; + if (gameinfo.flags & GI_COMPATSTAIRS) Level->ii_compatflags |= COMPATF_STAIRINDEX; } map->GetChecksum(md5.Bytes); @@ -319,9 +319,9 @@ FName MapLoader::CheckCompatibility(MapData *map) if (flags != NULL) { - ii_compatflags |= flags->CompatFlags[SLOT_COMPAT]; - ii_compatflags2 |= flags->CompatFlags[SLOT_COMPAT2]; - ib_compatflags |= flags->CompatFlags[SLOT_BCOMPAT]; + Level->ii_compatflags |= flags->CompatFlags[SLOT_COMPAT]; + Level->ii_compatflags2 |= flags->CompatFlags[SLOT_COMPAT2]; + Level->ib_compatflags |= flags->CompatFlags[SLOT_BCOMPAT]; } // Reset i_compatflags @@ -330,7 +330,7 @@ FName MapLoader::CheckCompatibility(MapData *map) // Set floatbob compatibility for all maps with an original Hexen MAPINFO. if (Level->flags2 & LEVEL2_HEXENHACK) { - ib_compatflags |= BCOMPATF_FLOATBOB; + Level->ib_compatflags |= BCOMPATF_FLOATBOB; } return FName(hash, true); // if this returns NAME_None it means there is no scripted compatibility handler. } @@ -574,6 +574,9 @@ CCMD (mapchecksum) CCMD (hiddencompatflags) { - Printf("%08x %08x %08x\n", ii_compatflags, ii_compatflags2, ib_compatflags); + for(auto Level : AllLevels()) + { + Printf("%s: %08x %08x %08x\n", Level->MapName.GetChars(), Level->ii_compatflags, Level->ii_compatflags2, Level->ib_compatflags); + } } diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index aa4c2bd7c..a22491009 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -1516,7 +1516,7 @@ void MapLoader::SetLineID (int i, line_t *ld) break; case Plane_Align: - if (!(ib_compatflags & BCOMPATF_NOSLOPEID)) setid = ld->args[2]; + if (!(Level->ib_compatflags & BCOMPATF_NOSLOPEID)) setid = ld->args[2]; break; case Static_Init: @@ -3016,7 +3016,7 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position) Level->maptype = MAPTYPE_UDMF; } FName checksum = CheckCompatibility(map); - if (ib_compatflags & BCOMPATF_REBUILDNODES) + if (Level->ib_compatflags & BCOMPATF_REBUILDNODES) { ForceNodeBuild = true; } diff --git a/src/maploader/slopes.cpp b/src/maploader/slopes.cpp index 92c761103..2fb44e628 100644 --- a/src/maploader/slopes.cpp +++ b/src/maploader/slopes.cpp @@ -179,7 +179,7 @@ void MapLoader::SetSlope (secplane_t *plane, bool setCeil, int xyangi, int zangi DVector3 norm; - if (ib_compatflags & BCOMPATF_SETSLOPEOVERFLOW) + if (Level->ib_compatflags & BCOMPATF_SETSLOPEOVERFLOW) { // We have to consider an integer multiplication overflow here. norm[0] = FixedToFloat(FloatToFixed(zang.Cos()) * FloatToFixed(xyang.Cos())) / 65536.; diff --git a/src/p_doors.cpp b/src/p_doors.cpp index 00b4f214e..c3c8b92e8 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -352,7 +352,7 @@ void DDoor::Construct(sector_t *sec, EVlDoor type, double speed, int delay, int m_TopCountdown = topcountdown; m_LightTag = lightTag; - if (i_compatflags & COMPATF_NODOORLIGHT) + if (Level->i_compatflags & COMPATF_NODOORLIGHT) { m_LightTag = 0; } diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 17f1e8561..162e9a76c 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -464,7 +464,7 @@ int P_Move (AActor *actor) // [RH] I'm not so sure this is such a good idea // [GZ] That's why it's compat-optioned. - if (compatflags & COMPATF_MBFMONSTERMOVE && !(actor->flags8 & MF8_NOFRICTION)) + if (actor->Level->i_compatflags & COMPATF_MBFMONSTERMOVE && !(actor->flags8 & MF8_NOFRICTION)) { // killough 10/98: make monsters get affected by ice and sludge too: movefactor = P_GetMoveFactor (actor, &friction); @@ -864,7 +864,7 @@ void P_NewChaseDir(AActor * actor) if (actor->floorz - actor->dropoffz > actor->MaxDropOffHeight && actor->Z() <= actor->floorz && !(actor->flags & MF_DROPOFF) && !(actor->flags2 & MF2_ONMOBJ) && - !(actor->flags & MF_FLOAT) && !(i_compatflags & COMPATF_DROPOFF)) + !(actor->flags & MF_FLOAT) && !(actor->Level->i_compatflags & COMPATF_DROPOFF)) { FBoundingBox box(actor->X(), actor->Y(), actor->radius); FBlockLinesIterator it(actor->Level, box); @@ -1715,7 +1715,7 @@ int P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) // the player then, eh? if(!(actor->flags6 & MF6_SEEINVISIBLE)) { - if ((player->mo->flags & MF_SHADOW && !(i_compatflags & COMPATF_INVISIBILITY)) || + if ((player->mo->flags & MF_SHADOW && !(actor->Level->i_compatflags & COMPATF_INVISIBILITY)) || player->mo->flags3 & MF3_GHOST) { if (player->mo->Distance2D (actor) > 128 && player->mo->Vel.XY().LengthSquared() < 5*5) @@ -1776,7 +1776,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look) } else { - targ = (i_compatflags & COMPATF_SOUNDTARGET || self->flags & MF_NOSECTOR)? + targ = (self->Level->i_compatflags & COMPATF_SOUNDTARGET || self->flags & MF_NOSECTOR)? self->Sector->SoundTarget : self->LastHeard; // [RH] If the soundtarget is dead, don't chase it @@ -1909,7 +1909,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LookEx) { if (!(flags & LOF_NOSOUNDCHECK)) { - targ = (i_compatflags & COMPATF_SOUNDTARGET || self->flags & MF_NOSECTOR)? + targ = (self->Level->i_compatflags & COMPATF_SOUNDTARGET || self->flags & MF_NOSECTOR)? self->Sector->SoundTarget : self->LastHeard; if (targ != NULL) { @@ -2721,7 +2721,7 @@ bool P_CheckForResurrection(AActor *self, bool usevilestates) { corpsehit->Translation = info->Translation; // Clean up bloodcolor translation from crushed corpses } - if (ib_compatflags & BCOMPATF_VILEGHOSTS) + if (self->Level->ib_compatflags & BCOMPATF_VILEGHOSTS) { corpsehit->Height *= 4; // [GZ] This was a commented-out feature, so let's make use of it, @@ -3116,7 +3116,7 @@ void A_BossDeath(AActor *self) LEVEL_SORCERER2SPECIAL)) == 0) return; - if ((i_compatflags & COMPATF_ANYBOSSDEATH) || ( // [GZ] Added for UAC_DEAD + if ((Level->i_compatflags & COMPATF_ANYBOSSDEATH) || ( // [GZ] Added for UAC_DEAD ((Level->flags & LEVEL_MAP07SPECIAL) && (type == NAME_Fatso || type == NAME_Arachnotron)) || ((Level->flags & LEVEL_BRUISERSPECIAL) && (type == NAME_BaronOfHell)) || ((Level->flags & LEVEL_CYBORGSPECIAL) && (type == NAME_Cyberdemon)) || diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 4f6e087b1..0bd2ae5b7 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -461,7 +461,7 @@ bool FLevelLocals::CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t * // [Graf Zahl] // Don't make sounds for instant movement hacks but make an exception for // switches that activate their own back side. - if (!(i_compatflags & COMPATF_SILENT_INSTANT_FLOORS)) + if (!(sec->Level->i_compatflags & COMPATF_SILENT_INSTANT_FLOORS)) { if (!line || !(line->activation & (SPAC_Use | SPAC_Push)) || line->backsector != sec) silent = true; diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index ed594244b..04d7d9337 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -3065,7 +3065,7 @@ FUNC(LS_SetPlayerProperty) { int i; - if ((ib_compatflags & BCOMPATF_LINKFROZENPROPS) && (mask & (CF_FROZEN | CF_TOTALLYFROZEN))) + if ((Level->ib_compatflags & BCOMPATF_LINKFROZENPROPS) && (mask & (CF_FROZEN | CF_TOTALLYFROZEN))) { // Clearing one of these properties clears both of them (if the compat flag is set.) mask = CF_FROZEN | CF_TOTALLYFROZEN; } diff --git a/src/p_map.cpp b/src/p_map.cpp index 1d14c00bd..ebfda7f83 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -459,7 +459,7 @@ bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modi // [RH] Z-Check // But not if not MF2_PASSMOBJ or MF3_DONTOVERLAP are set! // Otherwise those things would get stuck inside each other. - if ((thing->flags2 & MF2_PASSMOBJ || th->flags4 & MF4_ACTLIKEBRIDGE) && !(i_compatflags & COMPATF_NO_PASSMOBJ)) + if ((thing->flags2 & MF2_PASSMOBJ || th->flags4 & MF4_ACTLIKEBRIDGE) && !(thing->Level->i_compatflags & COMPATF_NO_PASSMOBJ)) { if (!(th->flags3 & thing->flags3 & MF3_DONTOVERLAP)) { @@ -516,7 +516,7 @@ bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modi // If this teleport was caused by a move, P_TryMove() will handle the // sector transition messages better than we can here. // This needs to be compatibility optioned because some older maps exploited this missing feature. - if (!(thing->flags6 & MF6_INTRYMOVE) && !(i_compatflags2 & COMPATF2_TELEPORT)) + if (!(thing->flags6 & MF6_INTRYMOVE) && !(thing->Level->i_compatflags2 & COMPATF2_TELEPORT)) { thing->CheckSectorTransition(oldsec); } @@ -850,7 +850,7 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec // into being friendly with the MBF flag automatically gain MF3_NOBLOCKMONST, so this // just optionally generalizes the behavior to other friendly monsters. bool NotBlocked = ((tm.thing->flags3 & MF3_NOBLOCKMONST) - || ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (tm.thing->flags & MF_FRIENDLY))); + || ((tm.thing->Level->i_compatflags & COMPATF_NOBLOCKFRIENDS) && (tm.thing->flags & MF_FRIENDLY))); uint32_t ProjectileBlocking = ML_BLOCKEVERYTHING | ML_BLOCKPROJECTILE; if ( tm.thing->flags8 & MF8_BLOCKASPLAYER ) ProjectileBlocking |= ML_BLOCK_PLAYERS | ML_BLOCKING; @@ -1263,7 +1263,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch // walking on other actors and unblocking is too messy through restricted portal types so disable it. if (!(cres.portalflags & FFCF_RESTRICTEDPORTAL)) { - if (!(i_compatflags & COMPATF_NO_PASSMOBJ) && !(tm.thing->flags & (MF_FLOAT | MF_MISSILE | MF_SKULLFLY | MF_NOGRAVITY)) && + if (!(thing->Level->i_compatflags & COMPATF_NO_PASSMOBJ) && !(tm.thing->flags & (MF_FLOAT | MF_MISSILE | MF_SKULLFLY | MF_NOGRAVITY)) && (thing->flags & MF_SOLID) && (thing->flags4 & MF4_ACTLIKEBRIDGE)) { // [RH] Let monsters walk on actors as well as floors @@ -1311,7 +1311,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch // [RH] If the other thing is a bridge, then treat the moving thing as if it had MF2_PASSMOBJ, so // you can use a scrolling floor to move scenery items underneath a bridge. - if ((tm.thing->flags2 & MF2_PASSMOBJ || thing->flags4 & MF4_ACTLIKEBRIDGE) && !(i_compatflags & COMPATF_NO_PASSMOBJ)) + if ((tm.thing->flags2 & MF2_PASSMOBJ || thing->flags4 & MF4_ACTLIKEBRIDGE) && !(tm.thing->Level->i_compatflags & COMPATF_NO_PASSMOBJ)) { // check if a mobj passed over/under another object if (!(tm.thing->flags & MF_MISSILE) || !(tm.thing->flags2 & MF2_RIP) || @@ -1441,7 +1441,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch { clipheight = thing->projectilepassheight; } - else if (thing->projectilepassheight < 0 && (i_compatflags & COMPATF_MISSILECLIP)) + else if (thing->projectilepassheight < 0 && (thing->Level->i_compatflags & COMPATF_MISSILECLIP)) { clipheight = -thing->projectilepassheight; } @@ -1763,7 +1763,7 @@ bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, boo AActor *BlockingMobj = thing->BlockingMobj; // If this blocks through a restricted line portal, it will always completely block. - if (BlockingMobj == NULL || (i_compatflags & COMPATF_NO_PASSMOBJ) || (tcres.portalflags & FFCF_RESTRICTEDPORTAL)) + if (BlockingMobj == NULL || (thing->Level->i_compatflags & COMPATF_NO_PASSMOBJ) || (tcres.portalflags & FFCF_RESTRICTEDPORTAL)) { // Thing slammed into something; don't let it move now. thing->Height = realHeight; return false; @@ -2068,7 +2068,7 @@ static void CheckForPushSpecial(line_t *line, int side, AActor *mobj, DVector2 * { if (line->special && !(mobj->flags6 & MF6_NOTRIGGER)) { - if (posforwindowcheck && !(i_compatflags2 & COMPATF2_PUSHWINDOW) && line->backsector != NULL) + if (posforwindowcheck && !(mobj->Level->i_compatflags2 & COMPATF2_PUSHWINDOW) && line->backsector != NULL) { // Make sure this line actually blocks us and is not a window // or similar construct we are standing inside of. DVector3 pos = mobj->PosRelative(line); @@ -2175,7 +2175,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, goto pushline; } } - if (!(tm.thing->flags2 & MF2_PASSMOBJ) || (i_compatflags & COMPATF_NO_PASSMOBJ)) + if (!(tm.thing->flags2 & MF2_PASSMOBJ) || (tm.thing->Level->i_compatflags & COMPATF_NO_PASSMOBJ)) { thing->SetZ(oldz); thing->flags6 &= ~MF6_INTRYMOVE; @@ -2274,7 +2274,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, // compatibility check: Doom originally did not allow monsters to cross dropoffs at all. // If the compatibility flag is on, only allow this when the velocity comes from a scroller - if ((i_compatflags & COMPATF_CROSSDROPOFF) && !(thing->flags4 & MF4_SCROLLMOVE)) + if ((thing->Level->i_compatflags & COMPATF_CROSSDROPOFF) && !(thing->flags4 & MF4_SCROLLMOVE)) { dropoff = false; } @@ -2963,7 +2963,7 @@ void FSlide::SlideTraverse(const DVector2 &start, const DVector2 &end) goto isblocking; } if (li->flags & ML_BLOCKMONSTERS && !((slidemo->flags3 & MF3_NOBLOCKMONST) - || ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (slidemo->flags & MF_FRIENDLY)))) + || ((slidemo->Level->i_compatflags & COMPATF_NOBLOCKFRIENDS) && (slidemo->flags & MF_FRIENDLY)))) { goto isblocking; } @@ -4588,7 +4588,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, // Hit a thing, so it could be either a puff or blood DVector3 bleedpos = trace.HitPos; // position a bit closer for puffs/blood if using compatibility mode. - if (i_compatflags & COMPATF_HITSCAN) + if (trace.Actor->Level->i_compatflags & COMPATF_HITSCAN) { DVector2 ofs = t1->Level->GetPortalOffsetPosition(bleedpos.X, bleedpos.Y, -10 * trace.HitVector.X, -10 * trace.HitVector.Y); bleedpos.X = ofs.X; @@ -4781,7 +4781,7 @@ int P_LineTrace(AActor *t1, DAngle angle, double distance, if ( flags & TRF_BLOCKSELF ) { bool Projectile = ( (t1->flags&MF_MISSILE) || (t1->BounceFlags&BOUNCE_MBF) ); - bool NotBlocked = ( (t1->flags3&MF3_NOBLOCKMONST) || ( (i_compatflags&COMPATF_NOBLOCKFRIENDS) && (t1->flags&MF_FRIENDLY) ) ); + bool NotBlocked = ( (t1->flags3&MF3_NOBLOCKMONST) || ( (t1->Level->i_compatflags&COMPATF_NOBLOCKFRIENDS) && (t1->flags&MF_FRIENDLY) ) ); if ( Projectile ) lflags |= ML_BLOCKPROJECTILE; if ( !Projectile || (t1->flags8&MF8_BLOCKASPLAYER) ) lflags |= ML_BLOCKING; if ( !NotBlocked ) lflags |= ML_BLOCKMONSTERS; @@ -5099,7 +5099,7 @@ static ETraceStatus ProcessRailHit(FTraceResults &res, void *userdata) newhit.HitActor = res.Actor; newhit.HitPos = res.HitPos; newhit.HitAngle = res.SrcAngleFromTarget; - if (i_compatflags & COMPATF_HITSCAN) + if (res.Actor->Level->i_compatflags & COMPATF_HITSCAN) { DVector2 ofs = res.Actor->Level->GetPortalOffsetPosition(newhit.HitPos.X, newhit.HitPos.Y, -10 * res.HitVector.X, -10 * res.HitVector.Y); newhit.HitPos.X = ofs.X; @@ -5427,7 +5427,7 @@ bool P_UseTraverse(AActor *usething, const DVector2 &start, const DVector2 &end, P_LineOpening(open, NULL, in->d.line, it.InterceptPoint(in)); } if (open.range <= 0 || - (in->d.line->special != 0 && (i_compatflags & COMPATF_USEBLOCKING))) + (in->d.line->special != 0 && (usething->Level->i_compatflags & COMPATF_USEBLOCKING))) { // [RH] Give sector a chance to intercept the use @@ -5487,7 +5487,7 @@ bool P_UseTraverse(AActor *usething, const DVector2 &start, const DVector2 &end, //[RH] And now I've changed it again. If the line is of type // SPAC_USE, then it eats the use. Everything else passes // it through, including SPAC_USETHROUGH. - if (i_compatflags & COMPATF_USEBLOCKING) + if (usething->Level->i_compatflags & COMPATF_USEBLOCKING) { if (in->d.line->activation & SPAC_UseThrough) continue; else return true; diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 4ea687216..16f6a72ad 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -1543,7 +1543,7 @@ void FPathTraverse::init(double x1, double y1, double x2, double y2, int flags, // Count is present to prevent a round off error // from skipping the break statement. - bool compatible = (flags & PT_COMPATIBLE) && (i_compatflags & COMPATF_HITSCAN); + bool compatible = (flags & PT_COMPATIBLE) && (Level->i_compatflags & COMPATF_HITSCAN); // we want to use one list of checked actors for the entire operation FBlockThingsIterator btit(Level); diff --git a/src/p_maputl.h b/src/p_maputl.h index e22c9cddd..99a8a8a04 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -4,6 +4,7 @@ #include #include "r_defs.h" #include "doomstat.h" +#include "doomdata.h" #include "m_bbox.h" extern int validcount; @@ -50,7 +51,7 @@ inline int P_PointOnLineSidePrecise(const DVector2 &pt, const line_t *line) inline int P_PointOnLineSide (double x, double y, const line_t *line) { extern int P_VanillaPointOnLineSide(double x, double y, const line_t* line); - return i_compatflags2 & COMPATF2_POINTONLINE + return (line->flags & ML_COMPATSIDE) ? P_VanillaPointOnLineSide(x, y, line) : P_PointOnLineSidePrecise(x, y, line); } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 52e413278..57216d5e3 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1161,7 +1161,7 @@ bool AActor::Grind(bool items) // see rh_log entry for February 21, 1999. Don't know if it is still relevant. if (state == NULL // Only use the default crushed state if: && !(flags & MF_NOBLOOD) // 1. the monster bleeeds, - && (i_compatflags & COMPATF_CORPSEGIBS) // 2. the compat setting is on, + && (Level->i_compatflags & COMPATF_CORPSEGIBS) // 2. the compat setting is on, && player == NULL) // 3. and the thing isn't a player. { isgeneric = true; @@ -1816,7 +1816,7 @@ double P_XYMovement (AActor *mo, DVector2 scroll) // [anon] When friction is turned off, turn off the crouching and water // speed caps as well, since it is a sort of friction, and the modders // most likely want to deal with that themselves. - if ((mo->player != NULL && (i_compatflags & COMPATF_WALLRUN)) || ((mo->waterlevel >= 1 || + if ((mo->player != NULL && (mo->Level->i_compatflags & COMPATF_WALLRUN)) || ((mo->waterlevel >= 1 || (mo->player != NULL && mo->player->crouchfactor < 0.75)) && !(mo->flags8 & MF8_NOFRICTION))) { // preserve the direction instead of clamping x and y independently. @@ -1938,7 +1938,7 @@ double P_XYMovement (AActor *mo, DVector2 scroll) DAngle oldangle = mo->Angles.Yaw; do { - if (i_compatflags & COMPATF_WALLRUN) pushtime++; + if (mo->Level->i_compatflags & COMPATF_WALLRUN) pushtime++; tm.PushTime = pushtime; ptry = start + move * step / steps; @@ -1989,7 +1989,7 @@ double P_XYMovement (AActor *mo, DVector2 scroll) // actor's velocity, do not attempt to slide. if (mo->Vel.XY() == startvel) { - if (player && (i_compatflags & COMPATF_WALLRUN)) + if (player && (mo->Level->i_compatflags & COMPATF_WALLRUN)) { // [RH] Here is the key to wall running: The move is clipped using its full speed. // If the move is done a second time (because it was too fast for one move), it @@ -2007,7 +2007,7 @@ double P_XYMovement (AActor *mo, DVector2 scroll) } else { - if (!player || !(i_compatflags & COMPATF_WALLRUN)) + if (!player || !(mo->Level->i_compatflags & COMPATF_WALLRUN)) { move = mo->Vel; onestep = move / steps; @@ -2451,7 +2451,7 @@ void P_ZMovement (AActor *mo, double oldfloorz) // Hexen yanked all items to the floor, except those being spawned at map start in the air. // Those were kept at their original height. // Do this only if the item was actually spawned by the map above ground to avoid problems. - if (mo->specialf1 > 0 && (mo->flags2 & MF2_FLOATBOB) && (ib_compatflags & BCOMPATF_FLOATBOB)) + if (mo->specialf1 > 0 && (mo->flags2 & MF2_FLOATBOB) && (mo->Level->ib_compatflags & BCOMPATF_FLOATBOB)) { mo->SetZ(mo->floorz + mo->specialf1); } @@ -3713,7 +3713,7 @@ void AActor::Tick () scrolltype <= Scroll_SouthWest_Fast) { // Hexen scroll special scrolltype -= Scroll_North_Slow; - if (i_compatflags&COMPATF_RAVENSCROLL) + if (Level->i_compatflags&COMPATF_RAVENSCROLL) { scrollv.X -= HexenCompatSpeeds[HexenScrollies[scrolltype][0]+4] * (1. / (32 * CARRYFACTOR)); scrollv.Y += HexenCompatSpeeds[HexenScrollies[scrolltype][1]+4] * (1. / (32 * CARRYFACTOR)); @@ -3732,7 +3732,7 @@ void AActor::Tick () scrolltype -= Carry_East5; uint8_t dir = HereticScrollDirs[scrolltype / 5]; double carryspeed = HereticSpeedMuls[scrolltype % 5] * (1. / (32 * CARRYFACTOR)); - if (scrolltype < 5 && !(i_compatflags&COMPATF_RAVENSCROLL)) + if (scrolltype < 5 && !(Level->i_compatflags&COMPATF_RAVENSCROLL)) { // Use speeds that actually match the scrolling textures! carryspeed = (1 << ((scrolltype % 5) + 15)) / 65536.; @@ -3742,7 +3742,7 @@ void AActor::Tick () } else if (scrolltype == dScroll_EastLavaDamage) { // Special Heretic scroll special - if (i_compatflags&COMPATF_RAVENSCROLL) + if (Level->i_compatflags&COMPATF_RAVENSCROLL) { scrollv.X += 28. / (32*CARRYFACTOR); } @@ -3795,7 +3795,7 @@ void AActor::Tick () // Some levels designed with Boom in mind actually want things to accelerate // at neighboring scrolling sector boundaries. But it is only important for // non-player objects. - if (player != NULL || !(i_compatflags & COMPATF_BOOMSCROLL)) + if (player != NULL || !(Level->i_compatflags & COMPATF_BOOMSCROLL)) { if (countx > 1) { @@ -3888,7 +3888,7 @@ void AActor::Tick () } if (Vel.Z != 0 || BlockingMobj || Z() != floorz) { // Handle Z velocity and gravity - if (((flags2 & MF2_PASSMOBJ) || (flags & MF_SPECIAL)) && !(i_compatflags & COMPATF_NO_PASSMOBJ)) + if (((flags2 & MF2_PASSMOBJ) || (flags & MF_SPECIAL)) && !(Level->i_compatflags & COMPATF_NO_PASSMOBJ)) { if (!(onmo = P_CheckOnmobj (this))) { @@ -5414,7 +5414,7 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position) if (sz == ONFLOORZ) { mobj->AddZ(mthing->pos.Z); - if ((mobj->flags2 & MF2_FLOATBOB) && (ib_compatflags & BCOMPATF_FLOATBOB)) + if ((mobj->flags2 & MF2_FLOATBOB) && (mobj->Level->ib_compatflags & BCOMPATF_FLOATBOB)) { mobj->specialf1 = mthing->pos.Z; } @@ -5437,7 +5437,7 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position) } // For Hexen floatbob 'compatibility' we do not really want to alter the floorz. - if (mobj->specialf1 == 0 || !(mobj->flags2 & MF2_FLOATBOB) || !(ib_compatflags & BCOMPATF_FLOATBOB)) + if (mobj->specialf1 == 0 || !(mobj->flags2 & MF2_FLOATBOB) || !(mobj->Level->ib_compatflags & BCOMPATF_FLOATBOB)) { P_FindFloorCeiling(mobj, FFCF_SAMESECTOR | FFCF_ONLY3DFLOORS | FFCF_3DRESTRICT); } diff --git a/src/p_pusher.cpp b/src/p_pusher.cpp index c06ee2c1f..2f580048c 100644 --- a/src/p_pusher.cpp +++ b/src/p_pusher.cpp @@ -199,7 +199,7 @@ void DPusher::Tick () bool pusharound = ((thing->flags2 & MF2_WINDTHRUST) && !(thing->flags & MF_NOCLIP)); // MBF allows any sentient or shootable thing to be affected, but players with a fly cheat aren't. - if (compatflags & COMPATF_MBFMONSTERMOVE) + if (Level->i_compatflags & COMPATF_MBFMONSTERMOVE) { pusharound = ((pusharound || (thing->IsSentient()) || (thing->flags & MF_SHOOTABLE)) // Add categories here && (!(thing->player && (thing->flags & (MF_NOGRAVITY))))); // Exclude flying players here diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index cb7cdc848..333992601 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -984,7 +984,9 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload) Behaviors.SerializeModuleStates(arc); // The order here is important: First world state, then portal state, then thinkers, and last polyobjects. + SetCompatLineOnSide(false); // This flag should not be saved. It solely depends on current compatibility state. arc("linedefs", lines, loadlines); + SetCompatLineOnSide(true); arc("sidedefs", sides, loadsides); arc("sectors", sectors, loadsectors); arc("zones", Zones); diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index 1694652d5..b9e17dd5e 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -473,9 +473,9 @@ double FindHighestCeilingSurrounding (const sector_t *sector, vertex_t **v) // jff 02/03/98 Add routine to find shortest lower texture // -static inline void CheckShortestTex (FTextureID texnum, double &minsize) +static inline void CheckShortestTex (FLevelLocals *Level, FTextureID texnum, double &minsize) { - if (texnum.isValid() || (texnum.isNull() && (i_compatflags & COMPATF_SHORTTEX))) + if (texnum.isValid() || (texnum.isNull() && (Level->i_compatflags & COMPATF_SHORTTEX))) { FTexture *tex = TexMan.GetTexture(texnum); if (tex != NULL) @@ -497,8 +497,8 @@ double FindShortestTextureAround (sector_t *sec) { if (check->flags & ML_TWOSIDED) { - CheckShortestTex (check->sidedef[0]->GetTexture(side_t::bottom), minsize); - CheckShortestTex (check->sidedef[1]->GetTexture(side_t::bottom), minsize); + CheckShortestTex (sec->Level, check->sidedef[0]->GetTexture(side_t::bottom), minsize); + CheckShortestTex (sec->Level, check->sidedef[1]->GetTexture(side_t::bottom), minsize); } } return minsize < FLT_MAX ? minsize : TexMan.ByIndex(0)->GetDisplayHeight(); @@ -522,8 +522,8 @@ double FindShortestUpperAround (sector_t *sec) { if (check->flags & ML_TWOSIDED) { - CheckShortestTex (check->sidedef[0]->GetTexture(side_t::top), minsize); - CheckShortestTex (check->sidedef[1]->GetTexture(side_t::top), minsize); + CheckShortestTex (sec->Level, check->sidedef[0]->GetTexture(side_t::top), minsize); + CheckShortestTex (sec->Level, check->sidedef[1]->GetTexture(side_t::top), minsize); } } return minsize < FLT_MAX ? minsize : TexMan.ByIndex(0)->GetDisplayHeight(); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 4a9955dd9..602adff56 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -546,6 +546,7 @@ void P_SetupLevel(FLevelLocals *Level, int position, bool newGame) Level->automap = AM_Create(Level); Level->automap->LevelInit(); + Level->SetCompatLineOnSide(true); // [RH] Start lightning, if MAPINFO tells us to if (Level->flags & LEVEL_STARTLIGHTNING) diff --git a/src/p_sight.cpp b/src/p_sight.cpp index 2e31e5f19..610025301 100644 --- a/src/p_sight.cpp +++ b/src/p_sight.cpp @@ -222,7 +222,7 @@ bool SightCheck::PTR_SightTraverse (intercept_t *in) // // ignore self referencing sectors if COMPAT_TRACE is on - if ((i_compatflags & COMPATF_TRACE) && li->frontsector == li->backsector) + if ((Level->i_compatflags & COMPATF_TRACE) && li->frontsector == li->backsector) return true; double trX = Trace.x + Trace.dx * in->frac; diff --git a/src/p_trace.cpp b/src/p_trace.cpp index 624f11bd7..dd9c7bb99 100644 --- a/src/p_trace.cpp +++ b/src/p_trace.cpp @@ -421,7 +421,7 @@ bool FTraceInfo::LineCheck(intercept_t *in, double dist, DVector3 hit, bool spec // For backwards compatibility: Ignore lines with the same sector on both sides. // This is the way Doom.exe did it and some WADs (e.g. Alien Vendetta MAP15) need it. - if (i_compatflags & COMPATF_TRACE && in->d.line->backsector == in->d.line->frontsector && !special3dpass) + if (Level->i_compatflags & COMPATF_TRACE && in->d.line->backsector == in->d.line->frontsector && !special3dpass) { // We must check special activation here because the code below is never reached. if (TraceFlags & TRACE_PCross) diff --git a/src/po_man.cpp b/src/po_man.cpp index 8c2aa750f..5147d77ff 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -1674,7 +1674,7 @@ void FPolyObj::CreateSubsectorLinks() seg->v2 = side->V2(); seg->wall = side; } - if (!(i_compatflags & COMPATF_POLYOBJ)) + if (!(Level->i_compatflags & COMPATF_POLYOBJ)) { SplitPoly(node, Level->HeadNode(), dummybbox); } diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 7179b8bbe..fd609cabe 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -848,7 +848,7 @@ static bool ValidatePosVel(const FSoundChan *const chan, const FVector3 &pos, co static void CalcSectorSoundOrg(const DVector3 &listenpos, const sector_t *sec, int channum, FVector3 &pos) { - if (!(i_compatflags & COMPATF_SECTORSOUNDS)) + if (!(sec->Level->i_compatflags & COMPATF_SECTORSOUNDS)) { // Are we inside the sector? If yes, the closest point is the one we're on. if (currentUILevel->PointInSector(listenpos.X, listenpos.Y) == sec) @@ -1663,7 +1663,7 @@ void S_StopSound (int channel) { FSoundChan *next = chan->NextChan; if (chan->SourceType == SOURCE_None && - (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) + (chan->EntChannel == channel || (compatflags & COMPATF_MAGICSILENCE))) { S_StopChannel(chan); } @@ -1687,7 +1687,7 @@ void S_StopSound (AActor *actor, int channel) FSoundChan *next = chan->NextChan; if (chan->SourceType == SOURCE_Actor && chan->Actor == actor && - (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) + (chan->EntChannel == channel || (compatflags & COMPATF_MAGICSILENCE))) { S_StopChannel(chan); } @@ -1711,7 +1711,7 @@ void S_StopSound (const sector_t *sec, int channel) FSoundChan *next = chan->NextChan; if (chan->SourceType == SOURCE_Sector && chan->Sector == sec && - (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) + (chan->EntChannel == channel || (compatflags & COMPATF_MAGICSILENCE))) { S_StopChannel(chan); } @@ -1735,7 +1735,7 @@ void S_StopSound (const FPolyObj *poly, int channel) FSoundChan *next = chan->NextChan; if (chan->SourceType == SOURCE_Polyobj && chan->Poly == poly && - (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) + (chan->EntChannel == channel || (compatflags & COMPATF_MAGICSILENCE))) { S_StopChannel(chan); } @@ -1827,7 +1827,7 @@ void S_ChangeSoundVolume(AActor *actor, int channel, double dvolume) { if (chan->SourceType == SOURCE_Actor && chan->Actor == actor && - (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) + (chan->EntChannel == channel || (compatflags & COMPATF_MAGICSILENCE))) { GSnd->ChannelVolume(chan, volume); chan->Volume = volume; @@ -1933,7 +1933,7 @@ static bool S_IsChannelUsed(AActor *actor, int channel, int *seen) bool S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id) { - if (i_compatflags & COMPATF_MAGICSILENCE) + if (compatflags & COMPATF_MAGICSILENCE) { channel = 0; } diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 2a854d346..6b5a4b9f8 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -6858,9 +6858,7 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) int *pVal; auto cv = static_cast(CVar); auto vcv = &cv->ValueVar; - if (vcv == &compatflags) pVal = &i_compatflags; - else if (vcv == &compatflags2) pVal = &i_compatflags2; - else pVal = &vcv->Value; + pVal = &vcv->Value; build->Emit(OP_LKP, addr.RegNum, build->GetConstantAddress(pVal)); build->Emit(OP_LW, dest.RegNum, addr.RegNum, nul); build->Emit(OP_SRL_RI, dest.RegNum, dest.RegNum, cv->BitNum); diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index a670907bb..d4b8f260a 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -1666,6 +1666,34 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, isFrozen, isFrozen) } +//===================================================================================== +// +// compat flags. These two are the only ones that get checked in script code +// so anything more complex isn't really needed. +// +//===================================================================================== +static int compat_limitpain_(AActor *self) +{ + return self->Level->i_compatflags & COMPATF_LIMITPAIN; +} + +static int compat_mushroom_(AActor *self) +{ + return self->Level->i_compatflags & COMPATF_MUSHROOM; +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, compat_limitpain, compat_limitpain_) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_INT(compat_limitpain_(self)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, compat_mushroom, compat_mushroom_) +{ + PARAM_SELF_PROLOGUE(AActor); + ACTION_RETURN_INT(compat_mushroom_(self)); +} + //=========================================================================== // // PlayerPawn functions diff --git a/src/swrenderer/line/r_line.cpp b/src/swrenderer/line/r_line.cpp index 731292147..2b3578437 100644 --- a/src/swrenderer/line/r_line.cpp +++ b/src/swrenderer/line/r_line.cpp @@ -591,7 +591,7 @@ namespace swrenderer if (mFrontSector->e && mFrontSector->e->XFloor.lightlist.Size()) return true; if (mBackSector->e && mBackSector->e->XFloor.lightlist.Size()) return true; - if (sidedef->GetTexture(side_t::mid).isValid() && ((ib_compatflags & BCOMPATF_CLIPMIDTEX) || (linedef->flags & (ML_CLIP_MIDTEX | ML_WRAP_MIDTEX)) || sidedef->Flags & (WALLF_CLIP_MIDTEX | WALLF_WRAP_MIDTEX))) return true; + if (sidedef->GetTexture(side_t::mid).isValid() && ((mFrontSector->Level->ib_compatflags & BCOMPATF_CLIPMIDTEX) || (linedef->flags & (ML_CLIP_MIDTEX | ML_WRAP_MIDTEX)) || sidedef->Flags & (WALLF_CLIP_MIDTEX | WALLF_WRAP_MIDTEX))) return true; return false; } @@ -653,7 +653,7 @@ namespace swrenderer if (sidedef->GetTexture(side_t::mid).isValid()) { - if (ib_compatflags & BCOMPATF_CLIPMIDTEX) return true; + if (mFrontSector->Level->ib_compatflags & BCOMPATF_CLIPMIDTEX) return true; if (linedef->flags & (ML_CLIP_MIDTEX | ML_WRAP_MIDTEX)) return true; if (sidedef->Flags & (WALLF_CLIP_MIDTEX | WALLF_WRAP_MIDTEX)) return true; } diff --git a/src/swrenderer/line/r_renderdrawsegment.cpp b/src/swrenderer/line/r_renderdrawsegment.cpp index 0f477d70c..610641fdf 100644 --- a/src/swrenderer/line/r_renderdrawsegment.cpp +++ b/src/swrenderer/line/r_renderdrawsegment.cpp @@ -150,7 +150,7 @@ namespace swrenderer return false; FTexture *ttex = TexMan.GetPalettedTexture(curline->sidedef->GetTexture(side_t::mid), true); - if (i_compatflags & COMPATF_MASKEDMIDTEX) + if (curline->GetLevel()->i_compatflags & COMPATF_MASKEDMIDTEX) { ttex = ttex->GetRawTexture(); } @@ -294,7 +294,7 @@ namespace swrenderer // this drawseg. if ((curline->linedef->flags & ML_CLIP_MIDTEX) || (curline->sidedef->Flags & WALLF_CLIP_MIDTEX) || - (ib_compatflags & BCOMPATF_CLIPMIDTEX)) + (curline->GetLevel()->ib_compatflags & BCOMPATF_CLIPMIDTEX)) { ClipMidtex(x1, x2); } @@ -356,7 +356,7 @@ namespace swrenderer // this drawseg. if ((curline->linedef->flags & ML_CLIP_MIDTEX) || (curline->sidedef->Flags & WALLF_CLIP_MIDTEX) || - (ib_compatflags & BCOMPATF_CLIPMIDTEX)) + (curline->GetLevel()->ib_compatflags & BCOMPATF_CLIPMIDTEX)) { ClipMidtex(x1, x2); } diff --git a/src/swrenderer/things/r_visiblespritelist.cpp b/src/swrenderer/things/r_visiblespritelist.cpp index 8c3935a4b..ca1a40ab5 100644 --- a/src/swrenderer/things/r_visiblespritelist.cpp +++ b/src/swrenderer/things/r_visiblespritelist.cpp @@ -69,7 +69,7 @@ namespace swrenderer if (count == 0) return; - if (!(i_compatflags & COMPATF_SPRITESORT)) + if (!(thread->Viewport->Level()->i_compatflags & COMPATF_SPRITESORT)) { for (unsigned int i = 0; i < count; i++) SortedSprites[i] = Sprites[first + i]; diff --git a/wadsrc/static/zscript/doom/fatso.txt b/wadsrc/static/zscript/doom/fatso.txt index f24b0d2e7..cbf820398 100644 --- a/wadsrc/static/zscript/doom/fatso.txt +++ b/wadsrc/static/zscript/doom/fatso.txt @@ -105,6 +105,7 @@ extend class Actor { const FATSPREAD = 90./8; + private native bool compat_mushroom(); void A_FatRaise() { @@ -195,7 +196,7 @@ extend class Actor aimtarget.Height = Height; bool shootmode = ((flags & MSF_Classic) || // Flag explicitly set, or no flags and compat options - (flags == 0 && CurState.bDehacked && compat_mushroom)); + (flags == 0 && CurState.bDehacked && compat_mushroom())); for (i = -numspawns; i <= numspawns; i += 8) { diff --git a/wadsrc/static/zscript/doom/painelemental.txt b/wadsrc/static/zscript/doom/painelemental.txt index f953e47ef..7995eae1b 100644 --- a/wadsrc/static/zscript/doom/painelemental.txt +++ b/wadsrc/static/zscript/doom/painelemental.txt @@ -62,6 +62,8 @@ class PainElemental : Actor extend class Actor { + private native bool compat_limitpain(); + // // A_PainShootSkull // Spawn a lost soul and launch it at the target @@ -86,7 +88,7 @@ extend class Actor } // [RH] make this optional - if (limit < 0 && compat_limitpain) + if (limit < 0 && compat_limitpain()) limit = 21; if (limit > 0)