- changed Polyobject thinkers to operate on the actual polyobjects instead of indices

This also changes the action special interface to pass a Level parameter to the separate functions and makes a few other minor adjustments to the polyobject code.
This commit is contained in:
Christoph Oelckers 2019-01-24 01:05:07 +01:00
parent 65750bd7bf
commit 9f8dd66189
15 changed files with 331 additions and 348 deletions

View file

@ -525,7 +525,7 @@ CUSTOM_CVAR (Int, compatflags, 0, CVAR_ARCHIVE|CVAR_SERVERINFO)
i_compatflags = GetCompatibility(self) | ii_compatflags; i_compatflags = GetCompatibility(self) | ii_compatflags;
if ((old ^ i_compatflags) & COMPATF_POLYOBJ) if ((old ^ i_compatflags) & COMPATF_POLYOBJ)
{ {
FPolyObj::ClearAllSubsectorLinks(); level.ClearAllSubsectorLinks();
} }
} }

View file

@ -1656,7 +1656,7 @@ void G_SnapshotLevel ()
if (arc.OpenWriter(save_formatted)) if (arc.OpenWriter(save_formatted))
{ {
SaveVersion = SAVEVER; SaveVersion = SAVEVER;
G_SerializeLevel(arc, false); G_SerializeLevel(arc, &level, false);
level.info->Snapshot = arc.GetCompressedOutput(); level.info->Snapshot = arc.GetCompressedOutput();
} }
} }
@ -1683,7 +1683,7 @@ void G_UnSnapshotLevel (bool hubLoad)
return; return;
} }
G_SerializeLevel (arc, hubLoad); G_SerializeLevel (arc, &level, hubLoad);
level.FromSnapshot = true; level.FromSnapshot = true;
TThinkerIterator<AActor> it(NAME_PlayerPawn); TThinkerIterator<AActor> it(NAME_PlayerPawn);

View file

@ -115,6 +115,8 @@ struct FLevelLocals : public FLevelData
void ClearLevelData(); void ClearLevelData();
void ClearPortals(); void ClearPortals();
bool CheckIfExitIsGood(AActor *self, level_info_t *newmap); bool CheckIfExitIsGood(AActor *self, level_info_t *newmap);
void FormatMapName(FString &mapname, const char *mapnamecolor);
void ClearAllSubsectorLinks();
FSectorTagIterator GetSectorTagIterator(int tag) FSectorTagIterator GetSectorTagIterator(int tag)
{ {
return FSectorTagIterator(tag); return FSectorTagIterator(tag);
@ -161,6 +163,13 @@ struct FLevelLocals : public FLevelData
return P_PointInSector(pos); return P_PointInSector(pos);
} }
FPolyObj *GetPolyobj (int polyNum)
{
auto index = Polyobjects.FindEx([=](const auto &poly) { return poly.tag == polyNum; });
return index == Polyobjects.Size()? nullptr : &Polyobjects[index];
}
uint8_t md5[16]; // for savegame validation. If the MD5 does not match the savegame won't be loaded. 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 time; // time in the hub
int maptime; // time in the map int maptime; // time in the map

View file

@ -424,7 +424,7 @@ void HWDrawInfo::CreateScene()
// reset the portal manager // reset the portal manager
screen->mPortalState->StartFrame(); screen->mPortalState->StartFrame();
PO_LinkToSubsectors(); PO_LinkToSubsectors(&level);
ProcessAll.Clock(); ProcessAll.Clock();

View file

@ -282,7 +282,7 @@ void MapLoader::TranslateToStartSpot (int tag, const DVector2 &origin)
FPolyObj *po; FPolyObj *po;
DVector2 delta; DVector2 delta;
po = PO_GetPolyobj(tag); po = Level->GetPolyobj(tag);
if (po == nullptr) if (po == nullptr)
{ // didn't match the tag with a polyobj tag { // didn't match the tag with a polyobj tag
Printf(TEXTCOLOR_RED "TranslateToStartSpot: Unable to match polyobj tag: %d\n", tag); Printf(TEXTCOLOR_RED "TranslateToStartSpot: Unable to match polyobj tag: %d\n", tag);

View file

@ -5654,7 +5654,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args)
const char *seqname = level.Behaviors.LookupString(args[1]); const char *seqname = level.Behaviors.LookupString(args[1]);
if (seqname != NULL) if (seqname != NULL)
{ {
FPolyObj *poly = PO_GetPolyobj(args[0]); FPolyObj *poly = level.GetPolyobj(args[0]);
if (poly != NULL) if (poly != NULL)
{ {
SN_StartSequence(poly, seqname, 0); SN_StartSequence(poly, seqname, 0);
@ -5665,7 +5665,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args)
case ACSF_GetPolyobjX: case ACSF_GetPolyobjX:
{ {
FPolyObj *poly = PO_GetPolyobj(args[0]); FPolyObj *poly = level.GetPolyobj(args[0]);
if (poly != NULL) if (poly != NULL)
{ {
return DoubleToACS(poly->StartSpot.pos.X); return DoubleToACS(poly->StartSpot.pos.X);
@ -5675,7 +5675,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args)
case ACSF_GetPolyobjY: case ACSF_GetPolyobjY:
{ {
FPolyObj *poly = PO_GetPolyobj(args[0]); FPolyObj *poly = level.GetPolyobj(args[0]);
if (poly != NULL) if (poly != NULL)
{ {
return DoubleToACS(poly->StartSpot.pos.Y); return DoubleToACS(poly->StartSpot.pos.Y);
@ -6817,7 +6817,7 @@ int DLevelScript::RunScript ()
case SCRIPT_PolyWait: case SCRIPT_PolyWait:
// Wait for polyobj(s) to stop moving, then enter state running // Wait for polyobj(s) to stop moving, then enter state running
if (!PO_Busy (statedata)) if (!PO_Busy (&level, statedata))
{ {
state = SCRIPT_Running; state = SCRIPT_Running;
} }

View file

@ -71,7 +71,7 @@
static const uint8_t ChangeMap[8] = { 0, 1, 5, 3, 7, 2, 6, 0 }; static const uint8_t ChangeMap[8] = { 0, 1, 5, 3, 7, 2, 6, 0 };
#define FUNC(a) static int a (line_t *ln, AActor *it, bool backSide, \ #define FUNC(a) static int a (FLevelLocals *Level, line_t *ln, AActor *it, bool backSide, \
int arg0, int arg1, int arg2, int arg3, int arg4) int arg0, int arg1, int arg2, int arg3, int arg4)
#define SPEED(a) ((a) / 8.) #define SPEED(a) ((a) / 8.)
@ -141,31 +141,31 @@ FUNC(LS_NOP)
FUNC(LS_Polyobj_RotateLeft) FUNC(LS_Polyobj_RotateLeft)
// Polyobj_RotateLeft (po, speed, angle) // Polyobj_RotateLeft (po, speed, angle)
{ {
return EV_RotatePoly (ln, arg0, arg1, arg2, 1, false); return EV_RotatePoly (Level, ln, arg0, arg1, arg2, 1, false);
} }
FUNC(LS_Polyobj_RotateRight) FUNC(LS_Polyobj_RotateRight)
// Polyobj_rotateRight (po, speed, angle) // Polyobj_rotateRight (po, speed, angle)
{ {
return EV_RotatePoly (ln, arg0, arg1, arg2, -1, false); return EV_RotatePoly (Level, ln, arg0, arg1, arg2, -1, false);
} }
FUNC(LS_Polyobj_Move) FUNC(LS_Polyobj_Move)
// Polyobj_Move (po, speed, angle, distance) // Polyobj_Move (po, speed, angle, distance)
{ {
return EV_MovePoly (ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg3, false); return EV_MovePoly (Level, ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg3, false);
} }
FUNC(LS_Polyobj_MoveTimes8) FUNC(LS_Polyobj_MoveTimes8)
// Polyobj_MoveTimes8 (po, speed, angle, distance) // Polyobj_MoveTimes8 (po, speed, angle, distance)
{ {
return EV_MovePoly (ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg3 * 8, false); return EV_MovePoly (Level, ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg3 * 8, false);
} }
FUNC(LS_Polyobj_MoveTo) FUNC(LS_Polyobj_MoveTo)
// Polyobj_MoveTo (po, speed, x, y) // Polyobj_MoveTo (po, speed, x, y)
{ {
return EV_MovePolyTo (ln, arg0, SPEED(arg1), DVector2(arg2, arg3), false); return EV_MovePolyTo (Level, ln, arg0, SPEED(arg1), DVector2(arg2, arg3), false);
} }
FUNC(LS_Polyobj_MoveToSpot) FUNC(LS_Polyobj_MoveToSpot)
@ -174,49 +174,49 @@ FUNC(LS_Polyobj_MoveToSpot)
FActorIterator iterator (arg2); FActorIterator iterator (arg2);
AActor *spot = iterator.Next(); AActor *spot = iterator.Next();
if (spot == NULL) return false; if (spot == NULL) return false;
return EV_MovePolyTo (ln, arg0, SPEED(arg1), spot->Pos(), false); return EV_MovePolyTo (Level, ln, arg0, SPEED(arg1), spot->Pos(), false);
} }
FUNC(LS_Polyobj_DoorSwing) FUNC(LS_Polyobj_DoorSwing)
// Polyobj_DoorSwing (po, speed, angle, delay) // Polyobj_DoorSwing (po, speed, angle, delay)
{ {
return EV_OpenPolyDoor (ln, arg0, arg1, BYTEANGLE(arg2), arg3, 0, PODOOR_SWING); return EV_OpenPolyDoor (Level, ln, arg0, arg1, BYTEANGLE(arg2), arg3, 0, PODOOR_SWING);
} }
FUNC(LS_Polyobj_DoorSlide) FUNC(LS_Polyobj_DoorSlide)
// Polyobj_DoorSlide (po, speed, angle, distance, delay) // Polyobj_DoorSlide (po, speed, angle, distance, delay)
{ {
return EV_OpenPolyDoor (ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg4, arg3, PODOOR_SLIDE); return EV_OpenPolyDoor (Level, ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg4, arg3, PODOOR_SLIDE);
} }
FUNC(LS_Polyobj_OR_RotateLeft) FUNC(LS_Polyobj_OR_RotateLeft)
// Polyobj_OR_RotateLeft (po, speed, angle) // Polyobj_OR_RotateLeft (po, speed, angle)
{ {
return EV_RotatePoly (ln, arg0, arg1, arg2, 1, true); return EV_RotatePoly (Level, ln, arg0, arg1, arg2, 1, true);
} }
FUNC(LS_Polyobj_OR_RotateRight) FUNC(LS_Polyobj_OR_RotateRight)
// Polyobj_OR_RotateRight (po, speed, angle) // Polyobj_OR_RotateRight (po, speed, angle)
{ {
return EV_RotatePoly (ln, arg0, arg1, arg2, -1, true); return EV_RotatePoly (Level, ln, arg0, arg1, arg2, -1, true);
} }
FUNC(LS_Polyobj_OR_Move) FUNC(LS_Polyobj_OR_Move)
// Polyobj_OR_Move (po, speed, angle, distance) // Polyobj_OR_Move (po, speed, angle, distance)
{ {
return EV_MovePoly (ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg3, true); return EV_MovePoly (Level, ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg3, true);
} }
FUNC(LS_Polyobj_OR_MoveTimes8) FUNC(LS_Polyobj_OR_MoveTimes8)
// Polyobj_OR_MoveTimes8 (po, speed, angle, distance) // Polyobj_OR_MoveTimes8 (po, speed, angle, distance)
{ {
return EV_MovePoly (ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg3 * 8, true); return EV_MovePoly (Level, ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg3 * 8, true);
} }
FUNC(LS_Polyobj_OR_MoveTo) FUNC(LS_Polyobj_OR_MoveTo)
// Polyobj_OR_MoveTo (po, speed, x, y) // Polyobj_OR_MoveTo (po, speed, x, y)
{ {
return EV_MovePolyTo (ln, arg0, SPEED(arg1), DVector2(arg2, arg3), true); return EV_MovePolyTo (Level, ln, arg0, SPEED(arg1), DVector2(arg2, arg3), true);
} }
FUNC(LS_Polyobj_OR_MoveToSpot) FUNC(LS_Polyobj_OR_MoveToSpot)
@ -225,13 +225,13 @@ FUNC(LS_Polyobj_OR_MoveToSpot)
FActorIterator iterator (arg2); FActorIterator iterator (arg2);
AActor *spot = iterator.Next(); AActor *spot = iterator.Next();
if (spot == NULL) return false; if (spot == NULL) return false;
return EV_MovePolyTo (ln, arg0, SPEED(arg1), spot->Pos(), true); return EV_MovePolyTo (Level, ln, arg0, SPEED(arg1), spot->Pos(), true);
} }
FUNC(LS_Polyobj_Stop) FUNC(LS_Polyobj_Stop)
// Polyobj_Stop (po) // Polyobj_Stop (po)
{ {
return EV_StopPoly (arg0); return EV_StopPoly (Level, arg0);
} }
FUNC(LS_Door_Close) FUNC(LS_Door_Close)
@ -258,7 +258,7 @@ FUNC(LS_Door_LockedRaise)
#if 0 #if 0
// In Hexen this originally created a thinker running for nearly 4 years. // In Hexen this originally created a thinker running for nearly 4 years.
// Let's not do this unless it becomes necessary because this can hang tagwait. // Let's not do this unless it becomes necessary because this can hang tagwait.
return EV_DoDoor (arg2 || (level.flags2 & LEVEL2_HEXENHACK) ? DDoor::doorRaise : DDoor::doorOpen, ln, it, return EV_DoDoor (arg2 || (Level->flags2 & LEVEL2_HEXENHACK) ? DDoor::doorRaise : DDoor::doorOpen, ln, it,
#else #else
return EV_DoDoor (arg2 ? DDoor::doorRaise : DDoor::doorOpen, ln, it, return EV_DoDoor (arg2 ? DDoor::doorRaise : DDoor::doorOpen, ln, it,
#endif #endif
@ -1060,7 +1060,7 @@ FUNC(LS_Generic_Lift)
FUNC(LS_Exit_Normal) FUNC(LS_Exit_Normal)
// Exit_Normal (position) // Exit_Normal (position)
{ {
if (level.CheckIfExitIsGood (it, FindLevelInfo(G_GetExitMap()))) if (Level->CheckIfExitIsGood (it, FindLevelInfo(G_GetExitMap())))
{ {
G_ExitLevel (arg0, false); G_ExitLevel (arg0, false);
return true; return true;
@ -1071,7 +1071,7 @@ FUNC(LS_Exit_Normal)
FUNC(LS_Exit_Secret) FUNC(LS_Exit_Secret)
// Exit_Secret (position) // Exit_Secret (position)
{ {
if (level.CheckIfExitIsGood (it, FindLevelInfo(G_GetSecretExitMap()))) if (Level->CheckIfExitIsGood (it, FindLevelInfo(G_GetSecretExitMap())))
{ {
G_SecretExitLevel (arg0); G_SecretExitLevel (arg0);
return true; return true;
@ -1086,7 +1086,7 @@ FUNC(LS_Teleport_NewMap)
{ {
level_info_t *info = FindLevelByNum (arg0); level_info_t *info = FindLevelByNum (arg0);
if (info && level.CheckIfExitIsGood (it, info)) if (info && Level->CheckIfExitIsGood (it, info))
{ {
G_ChangeLevel(info->MapName, arg1, arg2 ? CHANGELEVEL_KEEPFACING : 0); G_ChangeLevel(info->MapName, arg1, arg2 ? CHANGELEVEL_KEEPFACING : 0);
return true; return true;
@ -1181,7 +1181,7 @@ FUNC(LS_TeleportInSector)
FUNC(LS_Teleport_EndGame) FUNC(LS_Teleport_EndGame)
// Teleport_EndGame () // Teleport_EndGame ()
{ {
if (!backSide && level.CheckIfExitIsGood (it, NULL)) if (!backSide && Level->CheckIfExitIsGood (it, NULL))
{ {
G_ChangeLevel(NULL, 0, 0); G_ChangeLevel(NULL, 0, 0);
return true; return true;
@ -1219,7 +1219,7 @@ FUNC(LS_ThrustThing)
} }
else if (it) else if (it)
{ {
if (level.flags2 & LEVEL2_HEXENHACK && backSide) if (Level->flags2 & LEVEL2_HEXENHACK && backSide)
{ {
return false; return false;
} }
@ -1913,7 +1913,7 @@ FUNC(LS_ACS_Execute)
if (arg1 == 0) if (arg1 == 0)
{ {
mapname = level.MapName; mapname = Level->MapName;
} }
else if ((info = FindLevelByNum(arg1)) != NULL) else if ((info = FindLevelByNum(arg1)) != NULL)
{ {
@ -1936,7 +1936,7 @@ FUNC(LS_ACS_ExecuteAlways)
if (arg1 == 0) if (arg1 == 0)
{ {
mapname = level.MapName; mapname = Level->MapName;
} }
else if ((info = FindLevelByNum(arg1)) != NULL) else if ((info = FindLevelByNum(arg1)) != NULL)
{ {
@ -1955,7 +1955,7 @@ FUNC(LS_ACS_LockedExecute)
if (arg4 && !P_CheckKeys (it, arg4, true)) if (arg4 && !P_CheckKeys (it, arg4, true))
return false; return false;
else else
return LS_ACS_Execute (ln, it, backSide, arg0, arg1, arg2, arg3, 0); return LS_ACS_Execute (Level, ln, it, backSide, arg0, arg1, arg2, arg3, 0);
} }
FUNC(LS_ACS_LockedExecuteDoor) FUNC(LS_ACS_LockedExecuteDoor)
@ -1964,7 +1964,7 @@ FUNC(LS_ACS_LockedExecuteDoor)
if (arg4 && !P_CheckKeys (it, arg4, false)) if (arg4 && !P_CheckKeys (it, arg4, false))
return false; return false;
else else
return LS_ACS_Execute (ln, it, backSide, arg0, arg1, arg2, arg3, 0); return LS_ACS_Execute (Level, ln, it, backSide, arg0, arg1, arg2, arg3, 0);
} }
FUNC(LS_ACS_ExecuteWithResult) FUNC(LS_ACS_ExecuteWithResult)
@ -1976,7 +1976,7 @@ FUNC(LS_ACS_ExecuteWithResult)
int args[4] = { arg1, arg2, arg3, arg4 }; int args[4] = { arg1, arg2, arg3, arg4 };
int flags = (backSide ? ACS_BACKSIDE : 0) | ACS_ALWAYS | ACS_WANTRESULT; int flags = (backSide ? ACS_BACKSIDE : 0) | ACS_ALWAYS | ACS_WANTRESULT;
return P_StartScript (it, ln, arg0, level.MapName, args, 4, flags); return P_StartScript (it, ln, arg0, Level->MapName, args, 4, flags);
} }
FUNC(LS_ACS_Suspend) FUNC(LS_ACS_Suspend)
@ -1985,7 +1985,7 @@ FUNC(LS_ACS_Suspend)
level_info_t *info; level_info_t *info;
if (arg1 == 0) if (arg1 == 0)
P_SuspendScript (arg0, level.MapName); P_SuspendScript (arg0, Level->MapName);
else if ((info = FindLevelByNum (arg1)) ) else if ((info = FindLevelByNum (arg1)) )
P_SuspendScript (arg0, info->MapName); P_SuspendScript (arg0, info->MapName);
@ -1998,7 +1998,7 @@ FUNC(LS_ACS_Terminate)
level_info_t *info; level_info_t *info;
if (arg1 == 0) if (arg1 == 0)
P_TerminateScript (arg0, level.MapName); P_TerminateScript (arg0, Level->MapName);
else if ((info = FindLevelByNum (arg1)) ) else if ((info = FindLevelByNum (arg1)) )
P_TerminateScript (arg0, info->MapName); P_TerminateScript (arg0, info->MapName);
@ -2197,7 +2197,7 @@ FUNC(LS_Sector_ChangeSound)
FSectorTagIterator itr(arg0); FSectorTagIterator itr(arg0);
while ((secNum = itr.Next()) >= 0) while ((secNum = itr.Next()) >= 0)
{ {
level.sectors[secNum].seqType = arg1; Level->sectors[secNum].seqType = arg1;
rtn = true; rtn = true;
} }
return rtn; return rtn;
@ -2219,7 +2219,7 @@ FUNC(LS_Sector_ChangeFlags)
arg2 &= ~SECF_NOMODIFY; arg2 &= ~SECF_NOMODIFY;
while ((secNum = itr.Next()) >= 0) while ((secNum = itr.Next()) >= 0)
{ {
level.sectors[secNum].Flags = (level.sectors[secNum].Flags | arg1) & ~arg2; Level->sectors[secNum].Flags = (Level->sectors[secNum].Flags | arg1) & ~arg2;
rtn = true; rtn = true;
} }
return rtn; return rtn;
@ -2265,8 +2265,8 @@ FUNC(LS_Sector_SetTranslucent)
FSectorTagIterator itr(arg0); FSectorTagIterator itr(arg0);
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
level.sectors[secnum].SetAlpha(arg1, clamp(arg2, 0, 255) / 255.); Level->sectors[secnum].SetAlpha(arg1, clamp(arg2, 0, 255) / 255.);
level.sectors[secnum].ChangeFlags(arg1, ~PLANEF_ADDITIVE, arg3? PLANEF_ADDITIVE:0); Level->sectors[secnum].ChangeFlags(arg1, ~PLANEF_ADDITIVE, arg3? PLANEF_ADDITIVE:0);
} }
return true; return true;
} }
@ -2281,7 +2281,7 @@ FUNC(LS_Sector_SetLink)
int control = P_FindFirstSectorFromTag(arg0); int control = P_FindFirstSectorFromTag(arg0);
if (control >= 0) if (control >= 0)
{ {
return P_AddSectorLinks(&level.sectors[control], arg1, arg2, arg3); return P_AddSectorLinks(&Level->sectors[control], arg1, arg2, arg3);
} }
} }
return false; return false;
@ -2401,10 +2401,10 @@ FUNC(LS_Sector_SetDamage)
arg3 = 1; arg3 = 1;
} }
} }
level.sectors[secnum].damageamount = (short)arg1; Level->sectors[secnum].damageamount = (short)arg1;
level.sectors[secnum].damagetype = MODtoDamageType(arg2); Level->sectors[secnum].damagetype = MODtoDamageType(arg2);
level.sectors[secnum].damageinterval = (short)arg3; Level->sectors[secnum].damageinterval = (short)arg3;
level.sectors[secnum].leakydamage = (short)arg4; Level->sectors[secnum].leakydamage = (short)arg4;
} }
return true; return true;
} }
@ -2421,7 +2421,7 @@ FUNC(LS_Sector_SetGravity)
FSectorTagIterator itr(arg0); FSectorTagIterator itr(arg0);
int secnum; int secnum;
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
level.sectors[secnum].gravity = gravity; Level->sectors[secnum].gravity = gravity;
return true; return true;
} }
@ -2433,7 +2433,7 @@ FUNC(LS_Sector_SetColor)
int secnum; int secnum;
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
level.sectors[secnum].SetColor(PalEntry(arg1, arg2, arg3), arg4); Level->sectors[secnum].SetColor(PalEntry(arg1, arg2, arg3), arg4);
} }
return true; return true;
@ -2446,7 +2446,7 @@ FUNC(LS_Sector_SetFade)
int secnum; int secnum;
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
level.sectors[secnum].SetFade(PalEntry(arg1, arg2, arg3)); Level->sectors[secnum].SetFade(PalEntry(arg1, arg2, arg3));
} }
return true; return true;
} }
@ -2461,8 +2461,8 @@ FUNC(LS_Sector_SetCeilingPanning)
int secnum; int secnum;
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
level.sectors[secnum].SetXOffset(sector_t::ceiling, xofs); Level->sectors[secnum].SetXOffset(sector_t::ceiling, xofs);
level.sectors[secnum].SetYOffset(sector_t::ceiling, yofs); Level->sectors[secnum].SetYOffset(sector_t::ceiling, yofs);
} }
return true; return true;
} }
@ -2477,8 +2477,8 @@ FUNC(LS_Sector_SetFloorPanning)
int secnum; int secnum;
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
level.sectors[secnum].SetXOffset(sector_t::floor, xofs); Level->sectors[secnum].SetXOffset(sector_t::floor, xofs);
level.sectors[secnum].SetYOffset(sector_t::floor, yofs); Level->sectors[secnum].SetYOffset(sector_t::floor, yofs);
} }
return true; return true;
} }
@ -2499,9 +2499,9 @@ FUNC(LS_Sector_SetFloorScale)
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
if (xscale) if (xscale)
level.sectors[secnum].SetXScale(sector_t::floor, xscale); Level->sectors[secnum].SetXScale(sector_t::floor, xscale);
if (yscale) if (yscale)
level.sectors[secnum].SetYScale(sector_t::floor, yscale); Level->sectors[secnum].SetYScale(sector_t::floor, yscale);
} }
return true; return true;
} }
@ -2522,9 +2522,9 @@ FUNC(LS_Sector_SetCeilingScale)
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
if (xscale) if (xscale)
level.sectors[secnum].SetXScale(sector_t::ceiling, xscale); Level->sectors[secnum].SetXScale(sector_t::ceiling, xscale);
if (yscale) if (yscale)
level.sectors[secnum].SetYScale(sector_t::ceiling, yscale); Level->sectors[secnum].SetYScale(sector_t::ceiling, yscale);
} }
return true; return true;
} }
@ -2544,9 +2544,9 @@ FUNC(LS_Sector_SetFloorScale2)
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
if (arg1) if (arg1)
level.sectors[secnum].SetXScale(sector_t::floor, xscale); Level->sectors[secnum].SetXScale(sector_t::floor, xscale);
if (arg2) if (arg2)
level.sectors[secnum].SetYScale(sector_t::floor, yscale); Level->sectors[secnum].SetYScale(sector_t::floor, yscale);
} }
return true; return true;
} }
@ -2566,9 +2566,9 @@ FUNC(LS_Sector_SetCeilingScale2)
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
if (arg1) if (arg1)
level.sectors[secnum].SetXScale(sector_t::ceiling, xscale); Level->sectors[secnum].SetXScale(sector_t::ceiling, xscale);
if (arg2) if (arg2)
level.sectors[secnum].SetYScale(sector_t::ceiling, yscale); Level->sectors[secnum].SetYScale(sector_t::ceiling, yscale);
} }
return true; return true;
} }
@ -2583,8 +2583,8 @@ FUNC(LS_Sector_SetRotation)
int secnum; int secnum;
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
level.sectors[secnum].SetAngle(sector_t::floor, floor); Level->sectors[secnum].SetAngle(sector_t::floor, floor);
level.sectors[secnum].SetAngle(sector_t::ceiling, ceiling); Level->sectors[secnum].SetAngle(sector_t::ceiling, ceiling);
} }
return true; return true;
} }
@ -2631,7 +2631,7 @@ FUNC(LS_Line_SetTextureOffset)
int line; int line;
while ((line = itr.Next()) >= 0) while ((line = itr.Next()) >= 0)
{ {
side_t *side = level.lines[line].sidedef[arg3]; side_t *side = Level->lines[line].sidedef[arg3];
if (side != NULL) if (side != NULL)
{ {
@ -2686,7 +2686,7 @@ FUNC(LS_Line_SetTextureScale)
int line; int line;
while ((line = itr.Next()) >= 0) while ((line = itr.Next()) >= 0)
{ {
side_t *side = level.lines[line].sidedef[arg3]; side_t *side = Level->lines[line].sidedef[arg3];
if (side != NULL) if (side != NULL)
{ {
if ((arg4&8)==0) if ((arg4&8)==0)
@ -2760,7 +2760,7 @@ FUNC(LS_Line_SetBlocking)
int line; int line;
while ((line = itr.Next()) >= 0) while ((line = itr.Next()) >= 0)
{ {
level.lines[line].flags = (level.lines[line].flags & ~clearflags) | setflags; Level->lines[line].flags = (Level->lines[line].flags & ~clearflags) | setflags;
} }
return true; return true;
} }
@ -2792,7 +2792,7 @@ FUNC(LS_Line_SetAutomapFlags)
int line; int line;
while ((line = itr.Next()) >= 0) while ((line = itr.Next()) >= 0)
{ {
level.lines[line].flags = (level.lines[line].flags & ~clearflags) | setflags; Level->lines[line].flags = (Level->lines[line].flags & ~clearflags) | setflags;
} }
return true; return true;
@ -2807,7 +2807,7 @@ FUNC(LS_Line_SetAutomapStyle)
int line; int line;
while ((line = itr.Next()) >= 0) while ((line = itr.Next()) >= 0)
{ {
level.lines[line].automapstyle = (AutomapLineStyle) arg1; Level->lines[line].automapstyle = (AutomapLineStyle) arg1;
} }
return true; return true;
@ -2953,7 +2953,7 @@ FUNC(LS_SetPlayerProperty)
} }
else if (it->player - players == consoleplayer) else if (it->player - players == consoleplayer)
{ {
level.flags2 |= LEVEL2_ALLMAP; Level->flags2 |= LEVEL2_ALLMAP;
} }
} }
else else
@ -2968,7 +2968,7 @@ FUNC(LS_SetPlayerProperty)
} }
else if (it->player - players == consoleplayer) else if (it->player - players == consoleplayer)
{ {
level.flags2 &= ~LEVEL2_ALLMAP; Level->flags2 &= ~LEVEL2_ALLMAP;
} }
} }
} }
@ -2993,7 +2993,7 @@ FUNC(LS_SetPlayerProperty)
} }
else if (i == consoleplayer) else if (i == consoleplayer)
{ {
level.flags2 |= LEVEL2_ALLMAP; Level->flags2 |= LEVEL2_ALLMAP;
} }
} }
else else
@ -3008,7 +3008,7 @@ FUNC(LS_SetPlayerProperty)
} }
else if (i == consoleplayer) else if (i == consoleplayer)
{ {
level.flags2 &= ~LEVEL2_ALLMAP; Level->flags2 &= ~LEVEL2_ALLMAP;
} }
} }
} }
@ -3107,14 +3107,14 @@ FUNC(LS_TranslucentLine)
int linenum; int linenum;
while ((linenum = itr.Next()) >= 0) while ((linenum = itr.Next()) >= 0)
{ {
level.lines[linenum].alpha = clamp(arg1, 0, 255) / 255.; Level->lines[linenum].alpha = clamp(arg1, 0, 255) / 255.;
if (arg2 == 0) if (arg2 == 0)
{ {
level.lines[linenum].flags &= ~ML_ADDTRANS; Level->lines[linenum].flags &= ~ML_ADDTRANS;
} }
else if (arg2 == 1) else if (arg2 == 1)
{ {
level.lines[linenum].flags |= ML_ADDTRANS; Level->lines[linenum].flags |= ML_ADDTRANS;
} }
else else
{ {
@ -3129,7 +3129,7 @@ FUNC(LS_Autosave)
{ {
if (gameaction != ga_savegame) if (gameaction != ga_savegame)
{ {
level.flags2 &= ~LEVEL2_NOAUTOSAVEHINT; Level->flags2 &= ~LEVEL2_NOAUTOSAVEHINT;
Net_WriteByte (DEM_CHECKAUTOSAVE); Net_WriteByte (DEM_CHECKAUTOSAVE);
} }
return true; return true;
@ -3237,7 +3237,7 @@ FUNC(LS_ClearForceField)
int secnum; int secnum;
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
sector_t *sec = &level.sectors[secnum]; sector_t *sec = &Level->sectors[secnum];
rtn = true; rtn = true;
sec->RemoveForceField(); sec->RemoveForceField();
@ -3413,9 +3413,9 @@ FUNC(LS_Sector_SetPlaneReflection)
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
sector_t * s = &level.sectors[secnum]; sector_t * s = &Level->sectors[secnum];
if (!s->floorplane.isSlope()) s->reflect[sector_t::floor] = arg1 / 255.f; if (!s->floorplane.isSlope()) s->reflect[sector_t::floor] = arg1 / 255.f;
if (!s->ceilingplane.isSlope()) level.sectors[secnum].reflect[sector_t::ceiling] = arg2 / 255.f; if (!s->ceilingplane.isSlope()) Level->sectors[secnum].reflect[sector_t::ceiling] = arg2 / 255.f;
} }
return true; return true;
@ -3428,15 +3428,15 @@ FUNC(LS_SetGlobalFogParameter)
switch (arg0) switch (arg0)
{ {
case 0: case 0:
level.fogdensity = arg1 >> 1; Level->fogdensity = arg1 >> 1;
return true; return true;
case 1: case 1:
level.outsidefogdensity = arg1 >> 1; Level->outsidefogdensity = arg1 >> 1;
return true; return true;
case 2: case 2:
level.skyfog = arg1; Level->skyfog = arg1;
return true; return true;
default: default:
@ -3454,7 +3454,7 @@ FUNC(LS_Sector_SetFloorGlow)
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
sector_t * s = &level.sectors[secnum]; sector_t * s = &Level->sectors[secnum];
s->SetGlowColor(sector_t::floor, color); s->SetGlowColor(sector_t::floor, color);
s->SetGlowHeight(sector_t::floor, float(arg1)); s->SetGlowHeight(sector_t::floor, float(arg1));
} }
@ -3471,7 +3471,7 @@ FUNC(LS_Sector_SetCeilingGlow)
while ((secnum = itr.Next()) >= 0) while ((secnum = itr.Next()) >= 0)
{ {
sector_t * s = &level.sectors[secnum]; sector_t * s = &Level->sectors[secnum];
s->SetGlowColor(sector_t::ceiling, color); s->SetGlowColor(sector_t::ceiling, color);
s->SetGlowHeight(sector_t::ceiling, float(arg1)); s->SetGlowHeight(sector_t::ceiling, float(arg1));
} }
@ -3489,7 +3489,7 @@ FUNC(LS_Line_SetHealth)
while ((l = itr.Next()) >= 0) while ((l = itr.Next()) >= 0)
{ {
line_t* line = &level.lines[l]; line_t* line = &Level->lines[l];
line->health = arg1; line->health = arg1;
if (line->healthgroup) if (line->healthgroup)
P_SetHealthGroupHealth(line->healthgroup, arg1); P_SetHealthGroupHealth(line->healthgroup, arg1);
@ -3508,7 +3508,7 @@ FUNC(LS_Sector_SetHealth)
while ((s = itr.Next()) >= 0) while ((s = itr.Next()) >= 0)
{ {
sector_t* sector = &level.sectors[s]; sector_t* sector = &Level->sectors[s];
if (arg1 == SECPART_Ceiling) if (arg1 == SECPART_Ceiling)
{ {
sector->healthceiling = arg2; sector->healthceiling = arg2;
@ -3937,7 +3937,7 @@ int P_ExecuteSpecial(int num,
{ {
if (num >= 0 && num < (int)countof(LineSpecials)) if (num >= 0 && num < (int)countof(LineSpecials))
{ {
return LineSpecials[num](line, activator, backSide, arg1, arg2, arg3, arg4, arg5); return LineSpecials[num](&level, line, activator, backSide, arg1, arg2, arg3, arg4, arg5);
} }
return 0; return 0;
} }

View file

@ -187,10 +187,12 @@ typedef enum {
struct line_t; struct line_t;
class AActor; class AActor;
struct FLevelLocals;
FName MODtoDamageType (int mod); FName MODtoDamageType (int mod);
typedef int (*lnSpecFunc)(struct line_t *line, typedef int (*lnSpecFunc)(FLevelLocals *Level,
struct line_t *line,
class AActor *activator, class AActor *activator,
bool backSide, bool backSide,
int arg1, int arg1,
@ -211,6 +213,7 @@ int P_GetMaxLineSpecial();
int P_FindLineSpecial (const char *string, int *min_args=NULL, int *max_args=NULL); int P_FindLineSpecial (const char *string, int *min_args=NULL, int *max_args=NULL);
bool P_ActivateThingSpecial(AActor * thing, AActor * trigger, bool death=false); bool P_ActivateThingSpecial(AActor * thing, AActor * trigger, bool death=false);
int P_ExecuteSpecial(int num, int P_ExecuteSpecial(int num,
//FLevelLocals *lev, must be added later.
struct line_t *line, struct line_t *line,
class AActor *activator, class AActor *activator,
bool backSide, bool backSide,

View file

@ -248,11 +248,6 @@ FSerializer &Serialize(FSerializer &arc, const char *key, secplane_t &p, secplan
FSerializer &Serialize(FSerializer &arc, const char *key, sector_t &p, sector_t *def) FSerializer &Serialize(FSerializer &arc, const char *key, sector_t &p, sector_t *def)
{ {
// save the Scroll data here because it's a lot easier to handle a default.
// Just writing out the full array can massively inflate the archive for no gain.
DVector2 scroll = { 0,0 }, nul = { 0,0 };
if (arc.isWriting() && level.Scrolls.Size() > 0) scroll = level.Scrolls[p.sectornum];
if (arc.BeginObject(key)) if (arc.BeginObject(key))
{ {
arc("floorplane", p.floorplane, def->floorplane) arc("floorplane", p.floorplane, def->floorplane)
@ -300,23 +295,12 @@ FSerializer &Serialize(FSerializer &arc, const char *key, sector_t &p, sector_t
("gravity", p.gravity, def->gravity) ("gravity", p.gravity, def->gravity)
.Terrain("floorterrain", p.terrainnum[0], &def->terrainnum[0]) .Terrain("floorterrain", p.terrainnum[0], &def->terrainnum[0])
.Terrain("ceilingterrain", p.terrainnum[1], &def->terrainnum[1]) .Terrain("ceilingterrain", p.terrainnum[1], &def->terrainnum[1])
("scrolls", scroll, nul)
("healthfloor", p.healthfloor, def->healthfloor) ("healthfloor", p.healthfloor, def->healthfloor)
("healthceiling", p.healthceiling, def->healthceiling) ("healthceiling", p.healthceiling, def->healthceiling)
("health3d", p.health3d, def->health3d) ("health3d", p.health3d, def->health3d)
// GZDoom exclusive: // GZDoom exclusive:
.Array("reflect", p.reflect, def->reflect, 2, true) .Array("reflect", p.reflect, def->reflect, 2, true)
.EndObject(); .EndObject();
if (arc.isReading() && !scroll.isZero())
{
if (level.Scrolls.Size() == 0)
{
level.Scrolls.Resize(level.sectors.Size());
memset(&level.Scrolls[0], 0, sizeof(level.Scrolls[0])*level.Scrolls.Size());
level.Scrolls[p.sectornum] = scroll;
}
}
} }
return arc; return arc;
} }
@ -575,7 +559,7 @@ void P_SerializeSounds(FSerializer &arc)
void CopyPlayer(player_t *dst, player_t *src, const char *name); void CopyPlayer(player_t *dst, player_t *src, const char *name);
static void ReadOnePlayer(FSerializer &arc, bool skipload); static void ReadOnePlayer(FSerializer &arc, bool skipload);
static void ReadMultiplePlayers(FSerializer &arc, int numPlayers, int numPlayersNow, bool skipload); static void ReadMultiplePlayers(FSerializer &arc, int numPlayers, int numPlayersNow, bool skipload);
static void SpawnExtraPlayers(); static void SpawnExtraPlayers(FLevelLocals *Level);
//========================================================================== //==========================================================================
// //
@ -583,7 +567,7 @@ static void SpawnExtraPlayers();
// //
//========================================================================== //==========================================================================
void P_SerializePlayers(FSerializer &arc, bool skipload) void P_SerializePlayers(FLevelLocals *Level, FSerializer &arc, bool skipload)
{ {
int numPlayers, numPlayersNow; int numPlayers, numPlayersNow;
int i; int i;
@ -640,7 +624,7 @@ void P_SerializePlayers(FSerializer &arc, bool skipload)
} }
if (!skipload && numPlayersNow > numPlayers) if (!skipload && numPlayersNow > numPlayers)
{ {
SpawnExtraPlayers(); SpawnExtraPlayers(Level);
} }
// Redo pitch limits, since the spawned player has them at 0. // Redo pitch limits, since the spawned player has them at 0.
players[consoleplayer].SendPitchLimits(); players[consoleplayer].SendPitchLimits();
@ -891,7 +875,7 @@ void CopyPlayer(player_t *dst, player_t *src, const char *name)
// //
//========================================================================== //==========================================================================
static void SpawnExtraPlayers() static void SpawnExtraPlayers(FLevelLocals *Level)
{ {
// If there are more players now than there were in the savegame, // If there are more players now than there were in the savegame,
// be sure to spawn the extra players. // be sure to spawn the extra players.
@ -907,7 +891,7 @@ static void SpawnExtraPlayers()
if (playeringame[i] && players[i].mo == NULL) if (playeringame[i] && players[i].mo == NULL)
{ {
players[i].playerstate = PST_ENTER; players[i].playerstate = PST_ENTER;
P_SpawnPlayer(&level.playerstarts[i], i, (level.flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0); P_SpawnPlayer(&Level->playerstarts[i], i, (level.flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0);
} }
} }
} }
@ -918,13 +902,13 @@ static void SpawnExtraPlayers()
// //
//============================================================================ //============================================================================
void G_SerializeLevel(FSerializer &arc, bool hubload) void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload)
{ {
int i = level.totaltime; int i = Level->totaltime;
if (arc.isWriting()) if (arc.isWriting())
{ {
arc.Array("checksum", level.md5, 16); arc.Array("checksum", Level->md5, 16);
} }
else else
{ {
@ -933,11 +917,11 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
// deep down in the deserializer or just a crash if the few insufficient safeguards were not triggered. // deep down in the deserializer or just a crash if the few insufficient safeguards were not triggered.
uint8_t chk[16] = { 0 }; uint8_t chk[16] = { 0 };
arc.Array("checksum", chk, 16); arc.Array("checksum", chk, 16);
if (arc.GetSize("linedefs") != level.lines.Size() || if (arc.GetSize("linedefs") != Level->lines.Size() ||
arc.GetSize("sidedefs") != level.sides.Size() || arc.GetSize("sidedefs") != Level->sides.Size() ||
arc.GetSize("sectors") != level.sectors.Size() || arc.GetSize("sectors") != Level->sectors.Size() ||
arc.GetSize("polyobjs") != level.Polyobjects.Size() || arc.GetSize("polyobjs") != Level->Polyobjects.Size() ||
memcmp(chk, level.md5, 16)) memcmp(chk, Level->md5, 16))
{ {
I_Error("Savegame is from a different level"); I_Error("Savegame is from a different level");
} }
@ -953,55 +937,57 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
arc("multiplayer", multiplayer); arc("multiplayer", multiplayer);
arc("level.flags", level.flags) arc("flags", Level->flags)
("level.flags2", level.flags2) ("flags2", Level->flags2)
("level.fadeto", level.fadeto) ("fadeto", Level->fadeto)
("level.found_secrets", level.found_secrets) ("found_secrets", Level->found_secrets)
("level.found_items", level.found_items) ("found_items", Level->found_items)
("level.killed_monsters", level.killed_monsters) ("killed_monsters", Level->killed_monsters)
("level.total_secrets", level.total_secrets) ("total_secrets", Level->total_secrets)
("level.total_items", level.total_items) ("total_items", Level->total_items)
("level.total_monsters", level.total_monsters) ("total_monsters", Level->total_monsters)
("level.gravity", level.gravity) ("gravity", Level->gravity)
("level.aircontrol", level.aircontrol) ("aircontrol", Level->aircontrol)
("level.teamdamage", level.teamdamage) ("teamdamage", Level->teamdamage)
("level.maptime", level.maptime) ("maptime", Level->maptime)
("level.totaltime", i) ("totaltime", i)
("level.skytexture1", level.skytexture1) ("skytexture1", Level->skytexture1)
("level.skytexture2", level.skytexture2) ("skytexture2", Level->skytexture2)
("level.fogdensity", level.fogdensity) ("fogdensity", Level->fogdensity)
("level.outsidefogdensity", level.outsidefogdensity) ("outsidefogdensity", Level->outsidefogdensity)
("level.skyfog", level.skyfog) ("skyfog", Level->skyfog)
("level.deathsequence", level.deathsequence) ("deathsequence", Level->deathsequence)
("level.bodyqueslot", level.bodyqueslot) ("bodyqueslot", Level->bodyqueslot)
("level.spawnindex", level.spawnindex) ("spawnindex", Level->spawnindex)
.Array("level.bodyque", level.bodyque, level.BODYQUESIZE) .Array("bodyque", Level->bodyque, Level->BODYQUESIZE)
("level.corpsequeue", level.CorpseQueue) ("corpsequeue", Level->CorpseQueue)
("level.spotstate", level.SpotState) ("spotstate", Level->SpotState)
("level.fragglethinker", level.FraggleScriptThinker) ("fragglethinker", Level->FraggleScriptThinker)
("level.acsthinker", level.ACSThinker); ("acsthinker", Level->ACSThinker)
("level.impactdecalcount", level.ImpactDecalCount); ("impactdecalcount", Level->ImpactDecalCount)
("scrolls", Level->Scrolls);
// Hub transitions must keep the current total time // Hub transitions must keep the current total time
if (!hubload) if (!hubload)
level.totaltime = i; Level->totaltime = i;
if (arc.isReading()) if (arc.isReading())
{ {
sky1texture = level.skytexture1; sky1texture = Level->skytexture1;
sky2texture = level.skytexture2; sky2texture = Level->skytexture2;
R_InitSkyMap(); R_InitSkyMap();
G_AirControlChanged(); G_AirControlChanged();
} }
level.Behaviors.SerializeModuleStates(arc); Level->Behaviors.SerializeModuleStates(arc);
// The order here is important: First world state, then portal state, then thinkers, and last polyobjects. // The order here is important: First world state, then portal state, then thinkers, and last polyobjects.
arc("linedefs", level.lines, level.loadlines); arc("linedefs", Level->lines, Level->loadlines);
arc("sidedefs", level.sides, level.loadsides); arc("sidedefs", Level->sides, Level->loadsides);
arc("sectors", level.sectors, level.loadsectors); arc("sectors", Level->sectors, Level->loadsectors);
arc("zones", level.Zones); arc("zones", Level->Zones);
arc("lineportals", level.linePortals); arc("lineportals", Level->linePortals);
arc("sectorportals", level.sectorPortals); arc("sectorportals", Level->sectorPortals);
if (arc.isReading()) P_FinalizePortals(); if (arc.isReading()) P_FinalizePortals();
// [ZZ] serialize health groups // [ZZ] serialize health groups
@ -1009,18 +995,18 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
// [ZZ] serialize events // [ZZ] serialize events
E_SerializeEvents(arc); E_SerializeEvents(arc);
DThinker::SerializeThinkers(arc, hubload); DThinker::SerializeThinkers(arc, hubload);
arc("polyobjs", level.Polyobjects); arc("polyobjs", Level->Polyobjects);
SerializeSubsectors(arc, "subsectors"); SerializeSubsectors(arc, "subsectors");
StatusBar->SerializeMessages(arc); StatusBar->SerializeMessages(arc);
AM_SerializeMarkers(arc); AM_SerializeMarkers(arc);
FRemapTable::StaticSerializeTranslations(arc); FRemapTable::StaticSerializeTranslations(arc);
level.canvasTextureInfo.Serialize(arc); Level->canvasTextureInfo.Serialize(arc);
P_SerializePlayers(arc, hubload); P_SerializePlayers(Level, arc, hubload);
P_SerializeSounds(arc); P_SerializeSounds(arc);
if (arc.isReading()) if (arc.isReading())
{ {
for (auto &sec : level.sectors) for (auto &sec : Level->sectors)
{ {
P_Recalculate3DFloors(&sec); P_Recalculate3DFloors(&sec);
} }
@ -1033,5 +1019,5 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
} }
} }
AActor::RecreateAllAttachedLights(); AActor::RecreateAllAttachedLights();
InitPortalGroups(&level); InitPortalGroups(Level);
} }

View file

@ -44,6 +44,6 @@ void P_DestroyThinkers(bool hubLoad);
void P_ReadACSDefereds (FSerializer &); void P_ReadACSDefereds (FSerializer &);
void P_WriteACSDefereds (FSerializer &); void P_WriteACSDefereds (FSerializer &);
void G_SerializeLevel(FSerializer &arc, bool hubLoad); void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubLoad);
#endif // __P_SAVEG_H__ #endif // __P_SAVEG_H__

View file

@ -338,7 +338,7 @@ void P_FreeLevelData ()
AActor::ClearTIDHashes(); AActor::ClearTIDHashes();
interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level. interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level.
FPolyObj::ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process. level.ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
SN_StopAllSequences (); SN_StopAllSequences ();
DThinker::DestroyAllThinkers (); DThinker::DestroyAllThinkers ();
tagManager.Clear(); tagManager.Clear();

View file

@ -46,12 +46,12 @@ class DRotatePoly : public DPolyAction
{ {
DECLARE_CLASS (DRotatePoly, DPolyAction) DECLARE_CLASS (DRotatePoly, DPolyAction)
public: public:
DRotatePoly (int polyNum); DRotatePoly (FPolyObj *polyNum);
void Tick (); void Tick ();
private: private:
DRotatePoly (); DRotatePoly ();
friend bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle, int direction, bool overRide); friend bool EV_RotatePoly (FLevelLocals *Level, line_t *line, int polyNum, int speed, int byteAngle, int direction, bool overRide);
}; };
@ -59,7 +59,7 @@ class DMovePoly : public DPolyAction
{ {
DECLARE_CLASS (DMovePoly, DPolyAction) DECLARE_CLASS (DMovePoly, DPolyAction)
public: public:
DMovePoly (int polyNum); DMovePoly (FPolyObj *polyNum);
void Serialize(FSerializer &arc); void Serialize(FSerializer &arc);
void Tick (); void Tick ();
protected: protected:
@ -67,14 +67,14 @@ protected:
DAngle m_Angle; DAngle m_Angle;
DVector2 m_Speedv; DVector2 m_Speedv;
friend bool EV_MovePoly(line_t *line, int polyNum, double speed, DAngle angle, double dist, bool overRide); friend bool EV_MovePoly(FLevelLocals *Level, line_t *line, int polyNum, double speed, DAngle angle, double dist, bool overRide);
}; };
class DMovePolyTo : public DPolyAction class DMovePolyTo : public DPolyAction
{ {
DECLARE_CLASS(DMovePolyTo, DPolyAction) DECLARE_CLASS(DMovePolyTo, DPolyAction)
public: public:
DMovePolyTo(int polyNum); DMovePolyTo(FPolyObj *polyNum);
void Serialize(FSerializer &arc); void Serialize(FSerializer &arc);
void Tick(); void Tick();
protected: protected:
@ -82,7 +82,7 @@ protected:
DVector2 m_Speedv; DVector2 m_Speedv;
DVector2 m_Target; DVector2 m_Target;
friend bool EV_MovePolyTo(line_t *line, int polyNum, double speed, const DVector2 &pos, bool overRide); friend bool EV_MovePolyTo(FLevelLocals *Level, line_t *line, int polyNum, double speed, const DVector2 &pos, bool overRide);
}; };
@ -90,7 +90,7 @@ class DPolyDoor : public DMovePoly
{ {
DECLARE_CLASS (DPolyDoor, DMovePoly) DECLARE_CLASS (DPolyDoor, DMovePoly)
public: public:
DPolyDoor (int polyNum, podoortype_t type); DPolyDoor (FPolyObj *polyNum, podoortype_t type);
void Serialize(FSerializer &arc); void Serialize(FSerializer &arc);
void Tick (); void Tick ();
protected: protected:
@ -101,7 +101,7 @@ protected:
podoortype_t m_Type; podoortype_t m_Type;
bool m_Close; bool m_Close;
friend bool EV_OpenPolyDoor(line_t *line, int polyNum, double speed, DAngle angle, int delay, double distance, podoortype_t type); friend bool EV_OpenPolyDoor(FLevelLocals *Level, line_t *line, int polyNum, double speed, DAngle angle, int delay, double distance, podoortype_t type);
private: private:
DPolyDoor (); DPolyDoor ();
}; };
@ -165,7 +165,7 @@ void DPolyAction::Serialize(FSerializer &arc)
("interpolation", m_Interpolation); ("interpolation", m_Interpolation);
} }
DPolyAction::DPolyAction (int polyNum) DPolyAction::DPolyAction (FPolyObj *polyNum)
{ {
m_PolyObj = polyNum; m_PolyObj = polyNum;
m_Speed = 0; m_Speed = 0;
@ -175,11 +175,9 @@ DPolyAction::DPolyAction (int polyNum)
void DPolyAction::OnDestroy() void DPolyAction::OnDestroy()
{ {
FPolyObj *poly = PO_GetPolyobj (m_PolyObj); if (m_PolyObj->specialdata == this)
if (poly->specialdata == this)
{ {
poly->specialdata = NULL; m_PolyObj->specialdata = nullptr;
} }
StopInterpolation(); StopInterpolation();
@ -188,23 +186,21 @@ void DPolyAction::OnDestroy()
void DPolyAction::Stop() void DPolyAction::Stop()
{ {
FPolyObj *poly = PO_GetPolyobj(m_PolyObj); SN_StopSequence(m_PolyObj);
SN_StopSequence(poly);
Destroy(); Destroy();
} }
void DPolyAction::SetInterpolation () void DPolyAction::SetInterpolation ()
{ {
FPolyObj *poly = PO_GetPolyobj (m_PolyObj); m_Interpolation = m_PolyObj->SetInterpolation();
m_Interpolation = poly->SetInterpolation();
} }
void DPolyAction::StopInterpolation () void DPolyAction::StopInterpolation ()
{ {
if (m_Interpolation != NULL) if (m_Interpolation != nullptr)
{ {
m_Interpolation->DelRef(); m_Interpolation->DelRef();
m_Interpolation = NULL; m_Interpolation = nullptr;
} }
} }
@ -220,7 +216,7 @@ DRotatePoly::DRotatePoly ()
{ {
} }
DRotatePoly::DRotatePoly (int polyNum) DRotatePoly::DRotatePoly (FPolyObj *polyNum)
: Super (polyNum) : Super (polyNum)
{ {
} }
@ -244,7 +240,7 @@ void DMovePoly::Serialize(FSerializer &arc)
("speedv", m_Speedv); ("speedv", m_Speedv);
} }
DMovePoly::DMovePoly (int polyNum) DMovePoly::DMovePoly (FPolyObj *polyNum)
: Super (polyNum) : Super (polyNum)
{ {
m_Angle = 0.; m_Angle = 0.;
@ -271,7 +267,7 @@ void DMovePolyTo::Serialize(FSerializer &arc)
("target", m_Target); ("target", m_Target);
} }
DMovePolyTo::DMovePolyTo(int polyNum) DMovePolyTo::DMovePolyTo(FPolyObj *polyNum)
: Super(polyNum) : Super(polyNum)
{ {
m_Speedv = m_Target = { 0,0 }; m_Speedv = m_Target = { 0,0 };
@ -300,7 +296,7 @@ void DPolyDoor::Serialize(FSerializer &arc)
("close", m_Close); ("close", m_Close);
} }
DPolyDoor::DPolyDoor (int polyNum, podoortype_t type) DPolyDoor::DPolyDoor (FPolyObj * polyNum, podoortype_t type)
: Super (polyNum), m_Type (type) : Super (polyNum), m_Type (type)
{ {
m_Direction = 0.; m_Direction = 0.;
@ -320,8 +316,7 @@ DPolyDoor::DPolyDoor (int polyNum, podoortype_t type)
void DRotatePoly::Tick () void DRotatePoly::Tick ()
{ {
FPolyObj *poly = PO_GetPolyobj (m_PolyObj); if (m_PolyObj == nullptr) return;
if (poly == NULL) return;
// Don't let non-perpetual polyobjs overshoot their targets. // Don't let non-perpetual polyobjs overshoot their targets.
if (m_Dist != -1 && m_Dist < fabs(m_Speed)) if (m_Dist != -1 && m_Dist < fabs(m_Speed))
@ -329,7 +324,7 @@ void DRotatePoly::Tick ()
m_Speed = m_Speed < 0 ? -m_Dist : m_Dist; m_Speed = m_Speed < 0 ? -m_Dist : m_Dist;
} }
if (poly->RotatePolyobj (m_Speed)) if (m_PolyObj->RotatePolyobj (m_Speed))
{ {
if (m_Dist == -1) if (m_Dist == -1)
{ // perpetual polyobj { // perpetual polyobj
@ -338,7 +333,7 @@ void DRotatePoly::Tick ()
m_Dist -= fabs(m_Speed); m_Dist -= fabs(m_Speed);
if (m_Dist == 0) if (m_Dist == 0)
{ {
SN_StopSequence (poly); SN_StopSequence (m_PolyObj);
Destroy (); Destroy ();
} }
} }
@ -351,22 +346,21 @@ void DRotatePoly::Tick ()
//========================================================================== //==========================================================================
bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle, bool EV_RotatePoly (FLevelLocals *Level, line_t *line, int polyNum, int speed, int byteAngle, int direction, bool overRide)
int direction, bool overRide)
{ {
DRotatePoly *pe = NULL; DRotatePoly *pe = nullptr;
FPolyObj *poly; FPolyObj *poly;
if ((poly = PO_GetPolyobj(polyNum)) == NULL) if ((poly = Level->GetPolyobj(polyNum)) == nullptr)
{ {
Printf("EV_RotatePoly: Invalid polyobj num: %d\n", polyNum); Printf("EV_RotatePoly: Invalid polyobj num: %d\n", polyNum);
return false; return false;
} }
FPolyMirrorIterator it(poly); FPolyMirrorIterator it(poly);
while ((poly = it.NextMirror()) != NULL) while ((poly = it.NextMirror()) != nullptr)
{ {
if ((poly->specialdata != NULL || poly->bBlocked) && !overRide) if ((poly->specialdata != nullptr || poly->bBlocked) && !overRide)
{ // poly is already in motion { // poly is already in motion
break; break;
} }
@ -375,7 +369,7 @@ bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle,
// cannot do rotations on linked polyportals. // cannot do rotations on linked polyportals.
break; break;
} }
pe = Create<DRotatePoly>(poly->tag); pe = Create<DRotatePoly>(poly);
poly->specialdata = pe; poly->specialdata = pe;
poly->bBlocked = false; poly->bBlocked = false;
if (byteAngle != 0) if (byteAngle != 0)
@ -397,7 +391,7 @@ bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle,
SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0);
direction = -direction; // Reverse the direction direction = -direction; // Reverse the direction
} }
return pe != NULL; // Return true if something started moving. return pe != nullptr; // Return true if something started moving.
} }
//========================================================================== //==========================================================================
@ -408,17 +402,15 @@ bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle,
void DMovePoly::Tick () void DMovePoly::Tick ()
{ {
FPolyObj *poly = PO_GetPolyobj (m_PolyObj); if (m_PolyObj != nullptr)
if (poly != NULL)
{ {
if (poly->MovePolyobj (m_Speedv)) if (m_PolyObj->MovePolyobj (m_Speedv))
{ {
double absSpeed = fabs (m_Speed); double absSpeed = fabs (m_Speed);
m_Dist -= absSpeed; m_Dist -= absSpeed;
if (m_Dist <= 0) if (m_Dist <= 0)
{ {
SN_StopSequence (poly); SN_StopSequence (m_PolyObj);
Destroy (); Destroy ();
} }
else if (m_Dist < absSpeed) else if (m_Dist < absSpeed)
@ -426,7 +418,7 @@ void DMovePoly::Tick ()
m_Speed = m_Dist * (m_Speed < 0 ? -1 : 1); m_Speed = m_Dist * (m_Speed < 0 ? -1 : 1);
m_Speedv = m_Angle.ToVector(m_Speed); m_Speedv = m_Angle.ToVector(m_Speed);
} }
poly->UpdateLinks(); m_PolyObj->UpdateLinks();
} }
} }
} }
@ -437,27 +429,26 @@ void DMovePoly::Tick ()
// //
//========================================================================== //==========================================================================
bool EV_MovePoly (line_t *line, int polyNum, double speed, DAngle angle, bool EV_MovePoly (FLevelLocals *Level, line_t *line, int polyNum, double speed, DAngle angle, double dist, bool overRide)
double dist, bool overRide)
{ {
DMovePoly *pe = NULL; DMovePoly *pe = nullptr;
FPolyObj *poly; FPolyObj *poly;
DAngle an = angle; DAngle an = angle;
if ((poly = PO_GetPolyobj(polyNum)) == NULL) if ((poly = Level->GetPolyobj(polyNum)) == nullptr)
{ {
Printf("EV_MovePoly: Invalid polyobj num: %d\n", polyNum); Printf("EV_MovePoly: Invalid polyobj num: %d\n", polyNum);
return false; return false;
} }
FPolyMirrorIterator it(poly); FPolyMirrorIterator it(poly);
while ((poly = it.NextMirror()) != NULL) while ((poly = it.NextMirror()) != nullptr)
{ {
if ((poly->specialdata != NULL || poly->bBlocked) && !overRide) if ((poly->specialdata != nullptr || poly->bBlocked) && !overRide)
{ // poly is already in motion { // poly is already in motion
break; break;
} }
pe = Create<DMovePoly>(poly->tag); pe = Create<DMovePoly>(poly);
poly->specialdata = pe; poly->specialdata = pe;
poly->bBlocked = false; poly->bBlocked = false;
pe->m_Dist = dist; // Distance pe->m_Dist = dist; // Distance
@ -477,7 +468,7 @@ bool EV_MovePoly (line_t *line, int polyNum, double speed, DAngle angle,
angle += 180.; // Reverse the angle. angle += 180.; // Reverse the angle.
} }
return pe != NULL; // Return true if something started moving. return pe != nullptr; // Return true if something started moving.
} }
//========================================================================== //==========================================================================
@ -488,25 +479,23 @@ bool EV_MovePoly (line_t *line, int polyNum, double speed, DAngle angle,
void DMovePolyTo::Tick () void DMovePolyTo::Tick ()
{ {
FPolyObj *poly = PO_GetPolyobj (m_PolyObj); if (m_PolyObj != nullptr)
if (poly != NULL)
{ {
if (poly->MovePolyobj (m_Speedv)) if (m_PolyObj->MovePolyobj (m_Speedv))
{ {
double absSpeed = fabs (m_Speed); double absSpeed = fabs (m_Speed);
m_Dist -= absSpeed; m_Dist -= absSpeed;
if (m_Dist <= 0) if (m_Dist <= 0)
{ {
SN_StopSequence (poly); SN_StopSequence (m_PolyObj);
Destroy (); Destroy ();
} }
else if (m_Dist < absSpeed) else if (m_Dist < absSpeed)
{ {
m_Speed = m_Dist * (m_Speed < 0 ? -1 : 1); m_Speed = m_Dist * (m_Speed < 0 ? -1 : 1);
m_Speedv = m_Target - poly->StartSpot.pos; m_Speedv = m_Target - m_PolyObj->StartSpot.pos;
} }
poly->UpdateLinks(); m_PolyObj->UpdateLinks();
} }
} }
} }
@ -517,14 +506,14 @@ void DMovePolyTo::Tick ()
// //
//========================================================================== //==========================================================================
bool EV_MovePolyTo(line_t *line, int polyNum, double speed, const DVector2 &targ, bool overRide) bool EV_MovePolyTo(FLevelLocals *Level, line_t *line, int polyNum, double speed, const DVector2 &targ, bool overRide)
{ {
DMovePolyTo *pe = NULL; DMovePolyTo *pe = nullptr;
FPolyObj *poly; FPolyObj *poly;
DVector2 dist; DVector2 dist;
double distlen; double distlen;
if ((poly = PO_GetPolyobj(polyNum)) == NULL) if ((poly = Level->GetPolyobj(polyNum)) == nullptr)
{ {
Printf("EV_MovePolyTo: Invalid polyobj num: %d\n", polyNum); Printf("EV_MovePolyTo: Invalid polyobj num: %d\n", polyNum);
return false; return false;
@ -533,13 +522,13 @@ bool EV_MovePolyTo(line_t *line, int polyNum, double speed, const DVector2 &targ
dist = targ - poly->StartSpot.pos; dist = targ - poly->StartSpot.pos;
distlen = dist.MakeUnit(); distlen = dist.MakeUnit();
while ((poly = it.NextMirror()) != NULL) while ((poly = it.NextMirror()) != nullptr)
{ {
if ((poly->specialdata != NULL || poly->bBlocked) && !overRide) if ((poly->specialdata != nullptr || poly->bBlocked) && !overRide)
{ // poly is already in motion { // poly is already in motion
break; break;
} }
pe = Create<DMovePolyTo>(poly->tag); pe = Create<DMovePolyTo>(poly);
poly->specialdata = pe; poly->specialdata = pe;
poly->bBlocked = false; poly->bBlocked = false;
pe->m_Dist = distlen; pe->m_Dist = distlen;
@ -552,7 +541,7 @@ bool EV_MovePolyTo(line_t *line, int polyNum, double speed, const DVector2 &targ
} }
dist = -dist; // reverse the direction dist = -dist; // reverse the direction
} }
return pe != NULL; // Return true if something started moving. return pe != nullptr; // Return true if something started moving.
} }
//========================================================================== //==========================================================================
@ -563,28 +552,26 @@ bool EV_MovePolyTo(line_t *line, int polyNum, double speed, const DVector2 &targ
void DPolyDoor::Tick () void DPolyDoor::Tick ()
{ {
FPolyObj *poly = PO_GetPolyobj (m_PolyObj); if (m_PolyObj == nullptr) return;
if (poly == NULL) return;
if (m_Tics) if (m_Tics)
{ {
if (!--m_Tics) if (!--m_Tics)
{ {
SN_StartSequence (poly, poly->seqType, SEQ_DOOR, m_Close); SN_StartSequence (m_PolyObj, m_PolyObj->seqType, SEQ_DOOR, m_Close);
} }
return; return;
} }
switch (m_Type) switch (m_Type)
{ {
case PODOOR_SLIDE: case PODOOR_SLIDE:
if (m_Dist <= 0 || poly->MovePolyobj (m_Speedv)) if (m_Dist <= 0 || m_PolyObj->MovePolyobj (m_Speedv))
{ {
double absSpeed = fabs (m_Speed); double absSpeed = fabs (m_Speed);
m_Dist -= absSpeed; m_Dist -= absSpeed;
if (m_Dist <= 0) if (m_Dist <= 0)
{ {
SN_StopSequence (poly); SN_StopSequence (m_PolyObj);
if (!m_Close && m_WaitTics >= 0) if (!m_Close && m_WaitTics >= 0)
{ {
m_Dist = m_TotalDist; m_Dist = m_TotalDist;
@ -597,15 +584,15 @@ void DPolyDoor::Tick ()
{ {
// if set to wait infinitely, Hexen kept the dead thinker to block the polyobject from getting activated again but that causes some problems // if set to wait infinitely, Hexen kept the dead thinker to block the polyobject from getting activated again but that causes some problems
// with the subsectorlinks and the interpolation. Better delete the thinker and use a different means to block it. // with the subsectorlinks and the interpolation. Better delete the thinker and use a different means to block it.
if (!m_Close) poly->bBlocked = true; if (!m_Close) m_PolyObj->bBlocked = true;
Destroy (); Destroy ();
} }
} }
poly->UpdateLinks(); m_PolyObj->UpdateLinks();
} }
else else
{ {
if (poly->crush || !m_Close) if (m_PolyObj->crush || !m_Close)
{ // continue moving if the poly is a crusher, or is opening { // continue moving if the poly is a crusher, or is opening
return; return;
} }
@ -615,19 +602,19 @@ void DPolyDoor::Tick ()
m_Direction = -m_Direction; m_Direction = -m_Direction;
m_Speedv = -m_Speedv; m_Speedv = -m_Speedv;
m_Close = false; m_Close = false;
SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); SN_StartSequence (m_PolyObj, m_PolyObj->seqType, SEQ_DOOR, 0);
} }
} }
break; break;
case PODOOR_SWING: case PODOOR_SWING:
if (m_Dist <= 0 || poly->RotatePolyobj (m_Speed)) if (m_Dist <= 0 || m_PolyObj->RotatePolyobj (m_Speed))
{ {
double absSpeed = fabs (m_Speed); double absSpeed = fabs (m_Speed);
m_Dist -= absSpeed; m_Dist -= absSpeed;
if (m_Dist <= 0) if (m_Dist <= 0)
{ {
SN_StopSequence (poly); SN_StopSequence (m_PolyObj);
if (!m_Close && m_WaitTics >= 0) if (!m_Close && m_WaitTics >= 0)
{ {
m_Dist = m_TotalDist; m_Dist = m_TotalDist;
@ -637,14 +624,14 @@ void DPolyDoor::Tick ()
} }
else else
{ {
if (!m_Close) poly->bBlocked = true; if (!m_Close) m_PolyObj->bBlocked = true;
Destroy (); Destroy ();
} }
} }
} }
else else
{ {
if(poly->crush || !m_Close) if(m_PolyObj->crush || !m_Close)
{ // continue moving if the poly is a crusher, or is opening { // continue moving if the poly is a crusher, or is opening
return; return;
} }
@ -653,7 +640,7 @@ void DPolyDoor::Tick ()
m_Dist = m_TotalDist - m_Dist; m_Dist = m_TotalDist - m_Dist;
m_Speed = -m_Speed; m_Speed = -m_Speed;
m_Close = false; m_Close = false;
SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); SN_StartSequence (m_PolyObj, m_PolyObj->seqType, SEQ_DOOR, 0);
} }
} }
break; break;
@ -669,22 +656,22 @@ void DPolyDoor::Tick ()
// //
//========================================================================== //==========================================================================
bool EV_OpenPolyDoor(line_t *line, int polyNum, double speed, DAngle angle, int delay, double distance, podoortype_t type) bool EV_OpenPolyDoor(FLevelLocals *Level, line_t *line, int polyNum, double speed, DAngle angle, int delay, double distance, podoortype_t type)
{ {
DPolyDoor *pd = NULL; DPolyDoor *pd = nullptr;
FPolyObj *poly; FPolyObj *poly;
int swingdir = 1; // ADD: PODOOR_SWINGL, PODOOR_SWINGR int swingdir = 1; // ADD: PODOOR_SWINGL, PODOOR_SWINGR
if ((poly = PO_GetPolyobj(polyNum)) == NULL) if ((poly = Level->GetPolyobj(polyNum)) == nullptr)
{ {
Printf("EV_OpenPolyDoor: Invalid polyobj num: %d\n", polyNum); Printf("EV_OpenPolyDoor: Invalid polyobj num: %d\n", polyNum);
return false; return false;
} }
FPolyMirrorIterator it(poly); FPolyMirrorIterator it(poly);
while ((poly = it.NextMirror()) != NULL) while ((poly = it.NextMirror()) != nullptr)
{ {
if ((poly->specialdata != NULL || poly->bBlocked)) if ((poly->specialdata != nullptr || poly->bBlocked))
{ // poly is already moving { // poly is already moving
break; break;
} }
@ -694,7 +681,7 @@ bool EV_OpenPolyDoor(line_t *line, int polyNum, double speed, DAngle angle, int
break; break;
} }
pd = Create<DPolyDoor>(poly->tag, type); pd = Create<DPolyDoor>(poly, type);
poly->specialdata = pd; poly->specialdata = pd;
if (type == PODOOR_SLIDE) if (type == PODOOR_SLIDE)
{ {
@ -717,7 +704,7 @@ bool EV_OpenPolyDoor(line_t *line, int polyNum, double speed, DAngle angle, int
} }
} }
return pd != NULL; // Return true if something started moving. return pd != nullptr; // Return true if something started moving.
} }
//========================================================================== //==========================================================================
@ -726,13 +713,13 @@ bool EV_OpenPolyDoor(line_t *line, int polyNum, double speed, DAngle angle, int
// //
//========================================================================== //==========================================================================
bool EV_StopPoly(int polynum) bool EV_StopPoly(FLevelLocals *Level, int polynum)
{ {
FPolyObj *poly; FPolyObj *poly;
if (NULL != (poly = PO_GetPolyobj(polynum))) if (nullptr != (poly = Level->GetPolyobj(polynum)))
{ {
if (poly->specialdata != NULL) if (poly->specialdata != nullptr)
{ {
poly->specialdata->Stop(); poly->specialdata->Stop();
} }
@ -743,23 +730,6 @@ bool EV_StopPoly(int polynum)
// ===== Higher Level Poly Interface code ===== // ===== Higher Level Poly Interface code =====
//==========================================================================
//
// PO_GetPolyobj
//
//==========================================================================
FPolyObj *PO_GetPolyobj (int polyNum)
{
for(auto &poly : level.Polyobjects)
{
if (poly.tag == polyNum)
{
return &poly;
}
}
return nullptr;
}
//========================================================================== //==========================================================================
@ -780,9 +750,9 @@ FPolyObj::FPolyObj()
seqType = 0; seqType = 0;
Size = 0; Size = 0;
bBlocked = false; bBlocked = false;
subsectorlinks = NULL; subsectorlinks = nullptr;
specialdata = NULL; specialdata = nullptr;
interpolation = NULL; interpolation = nullptr;
} }
//========================================================================== //==========================================================================
@ -796,6 +766,11 @@ int FPolyObj::GetMirror()
return MirrorNum; return MirrorNum;
} }
FLevelLocals *FPolyObj::GetLevel() const
{
return &level;
}
//========================================================================== //==========================================================================
// //
// ThrustMobj // ThrustMobj
@ -806,6 +781,7 @@ void FPolyObj::ThrustMobj (AActor *actor, side_t *side)
{ {
DAngle thrustAngle; DAngle thrustAngle;
DPolyAction *pe; DPolyAction *pe;
auto Level = GetLevel();
double force; double force;
@ -843,11 +819,11 @@ void FPolyObj::ThrustMobj (AActor *actor, side_t *side)
DVector2 pos = actor->Vec2Offset(thrust.X, thrust.Y); DVector2 pos = actor->Vec2Offset(thrust.X, thrust.Y);
if (bHurtOnTouch || !P_CheckMove (actor, pos)) if (bHurtOnTouch || !P_CheckMove (actor, pos))
{ {
int newdam = P_DamageMobj (actor, NULL, NULL, crush, NAME_Crush); int newdam = P_DamageMobj (actor, nullptr, nullptr, crush, NAME_Crush);
P_TraceBleed (newdam > 0 ? newdam : crush, actor); P_TraceBleed (newdam > 0 ? newdam : crush, actor);
} }
} }
if (level.flags2 & LEVEL2_POLYGRIND) actor->CallGrind(false); // crush corpses that get caught in a polyobject's way if (Level->flags2 & LEVEL2_POLYGRIND) actor->CallGrind(false); // crush corpses that get caught in a polyobject's way
} }
//========================================================================== //==========================================================================
@ -860,6 +836,7 @@ void FPolyObj::UpdateLinks()
{ {
if (bHasPortals == 2) if (bHasPortals == 2)
{ {
auto Level = GetLevel();
TMap<int, bool> processed; TMap<int, bool> processed;
for (unsigned i = 0; i < Linedefs.Size(); i++) for (unsigned i = 0; i < Linedefs.Size(); i++)
{ {
@ -878,7 +855,7 @@ void FPolyObj::UpdateLinks()
{ {
processed[destgroup] = true; processed[destgroup] = true;
DVector2 delta = port->mDisplacement - old; DVector2 delta = port->mDisplacement - old;
level.Displacements.MoveGroup(destgroup, delta); Level->Displacements.MoveGroup(destgroup, delta);
} }
} }
} }
@ -1048,25 +1025,26 @@ void FPolyObj::UnLinkPolyobj ()
polyblock_t *link; polyblock_t *link;
int i, j; int i, j;
int index; int index;
auto Level = GetLevel();
// remove the polyobj from each blockmap section // remove the polyobj from each blockmap section
for(j = bbox[BOXBOTTOM]; j <= bbox[BOXTOP]; j++) for(j = bbox[BOXBOTTOM]; j <= bbox[BOXTOP]; j++)
{ {
index = j*level.blockmap.bmapwidth; index = j*Level->blockmap.bmapwidth;
for(i = bbox[BOXLEFT]; i <= bbox[BOXRIGHT]; i++) for(i = bbox[BOXLEFT]; i <= bbox[BOXRIGHT]; i++)
{ {
if(i >= 0 && i < level.blockmap.bmapwidth && j >= 0 && j < level.blockmap.bmapheight) if(i >= 0 && i < Level->blockmap.bmapwidth && j >= 0 && j < Level->blockmap.bmapheight)
{ {
link = level.PolyBlockMap[index+i]; link = Level->PolyBlockMap[index+i];
while(link != NULL && link->polyobj != this) while(link != nullptr && link->polyobj != this)
{ {
link = link->next; link = link->next;
} }
if(link == NULL) if(link == nullptr)
{ // polyobj not located in the link cell { // polyobj not located in the link cell
continue; continue;
} }
link->polyobj = NULL; link->polyobj = nullptr;
} }
} }
} }
@ -1080,6 +1058,7 @@ void FPolyObj::UnLinkPolyobj ()
bool FPolyObj::CheckMobjBlocking (side_t *sd) bool FPolyObj::CheckMobjBlocking (side_t *sd)
{ {
auto Level = GetLevel();
static TArray<AActor *> checker; static TArray<AActor *> checker;
FBlockNode *block; FBlockNode *block;
AActor *mobj; AActor *mobj;
@ -1088,15 +1067,15 @@ bool FPolyObj::CheckMobjBlocking (side_t *sd)
line_t *ld; line_t *ld;
bool blocked; bool blocked;
bool performBlockingThrust; bool performBlockingThrust;
int bmapwidth = level.blockmap.bmapwidth; int bmapwidth = Level->blockmap.bmapwidth;
int bmapheight = level.blockmap.bmapheight; int bmapheight = Level->blockmap.bmapheight;
ld = sd->linedef; ld = sd->linedef;
top = level.blockmap.GetBlockY(ld->bbox[BOXTOP]); top = Level->blockmap.GetBlockY(ld->bbox[BOXTOP]);
bottom = level.blockmap.GetBlockY(ld->bbox[BOXBOTTOM]); bottom = Level->blockmap.GetBlockY(ld->bbox[BOXBOTTOM]);
left = level.blockmap.GetBlockX(ld->bbox[BOXLEFT]); left = Level->blockmap.GetBlockX(ld->bbox[BOXLEFT]);
right = level.blockmap.GetBlockX(ld->bbox[BOXRIGHT]); right = Level->blockmap.GetBlockX(ld->bbox[BOXRIGHT]);
blocked = false; blocked = false;
checker.Clear(); checker.Clear();
@ -1114,7 +1093,7 @@ bool FPolyObj::CheckMobjBlocking (side_t *sd)
{ {
for (i = left; i <= right; i++) for (i = left; i <= right; i++)
{ {
for (block = level.blockmap.blocklinks[j+i]; block != NULL; block = block->NextActor) for (block = Level->blockmap.blocklinks[j+i]; block != nullptr; block = block->NextActor)
{ {
mobj = block->Me; mobj = block->Me;
for (k = (int)checker.Size()-1; k >= 0; --k) for (k = (int)checker.Size()-1; k >= 0; --k)
@ -1133,7 +1112,7 @@ bool FPolyObj::CheckMobjBlocking (side_t *sd)
open.top = LINEOPEN_MAX; open.top = LINEOPEN_MAX;
open.bottom = LINEOPEN_MIN; open.bottom = LINEOPEN_MIN;
// [TN] Check wether this actor gets blocked by the line. // [TN] Check wether this actor gets blocked by the line.
if (ld->backsector != NULL && if (ld->backsector != nullptr &&
!(ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING)) !(ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING))
&& !(ld->flags & ML_BLOCK_PLAYERS && (mobj->player || (mobj->flags8 & MF8_BLOCKASPLAYER))) && !(ld->flags & ML_BLOCK_PLAYERS && (mobj->player || (mobj->flags8 & MF8_BLOCKASPLAYER)))
&& !(ld->flags & ML_BLOCKMONSTERS && mobj->flags3 & MF3_ISMONSTER) && !(ld->flags & ML_BLOCKMONSTERS && mobj->flags3 & MF3_ISMONSTER)
@ -1173,7 +1152,7 @@ bool FPolyObj::CheckMobjBlocking (side_t *sd)
// We have a two-sided linedef so we should only check one side // We have a two-sided linedef so we should only check one side
// so that the thrust from both sides doesn't cancel each other out. // so that the thrust from both sides doesn't cancel each other out.
// Best use the one facing the player and ignore the back side. // Best use the one facing the player and ignore the back side.
if (ld->sidedef[1] != NULL) if (ld->sidedef[1] != nullptr)
{ {
int side = P_PointOnLineSidePrecise(mobj->Pos(), ld); int side = P_PointOnLineSidePrecise(mobj->Pos(), ld);
if (ld->sidedef[side] != sd) if (ld->sidedef[side] != sd)
@ -1215,8 +1194,9 @@ void FPolyObj::LinkPolyobj ()
{ {
polyblock_t **link; polyblock_t **link;
polyblock_t *tempLink; polyblock_t *tempLink;
int bmapwidth = level.blockmap.bmapwidth; auto Level = GetLevel();
int bmapheight = level.blockmap.bmapheight; int bmapwidth = Level->blockmap.bmapwidth;
int bmapheight = Level->blockmap.bmapheight;
// calculate the polyobj bbox // calculate the polyobj bbox
Bounds.ClearBox(); Bounds.ClearBox();
@ -1229,10 +1209,10 @@ void FPolyObj::LinkPolyobj ()
vt = Sidedefs[i]->linedef->v2; vt = Sidedefs[i]->linedef->v2;
Bounds.AddToBox(vt->fPos()); Bounds.AddToBox(vt->fPos());
} }
bbox[BOXRIGHT] = level.blockmap.GetBlockX(Bounds.Right()); bbox[BOXRIGHT] = Level->blockmap.GetBlockX(Bounds.Right());
bbox[BOXLEFT] = level.blockmap.GetBlockX(Bounds.Left()); bbox[BOXLEFT] = Level->blockmap.GetBlockX(Bounds.Left());
bbox[BOXTOP] = level.blockmap.GetBlockY(Bounds.Top()); bbox[BOXTOP] = Level->blockmap.GetBlockY(Bounds.Top());
bbox[BOXBOTTOM] = level.blockmap.GetBlockY(Bounds.Bottom()); bbox[BOXBOTTOM] = Level->blockmap.GetBlockY(Bounds.Bottom());
// add the polyobj to each blockmap section // add the polyobj to each blockmap section
for(int j = bbox[BOXBOTTOM]*bmapwidth; j <= bbox[BOXTOP]*bmapwidth; for(int j = bbox[BOXBOTTOM]*bmapwidth; j <= bbox[BOXTOP]*bmapwidth;
j += bmapwidth) j += bmapwidth)
@ -1241,24 +1221,24 @@ void FPolyObj::LinkPolyobj ()
{ {
if(i >= 0 && i < bmapwidth && j >= 0 && j < bmapheight*bmapwidth) if(i >= 0 && i < bmapwidth && j >= 0 && j < bmapheight*bmapwidth)
{ {
link = &level.PolyBlockMap[j+i]; link = &Level->PolyBlockMap[j+i];
if(!(*link)) if(!(*link))
{ // Create a new link at the current block cell { // Create a new link at the current block cell
*link = new polyblock_t; *link = new polyblock_t;
(*link)->next = NULL; (*link)->next = nullptr;
(*link)->prev = NULL; (*link)->prev = nullptr;
(*link)->polyobj = this; (*link)->polyobj = this;
continue; continue;
} }
else else
{ {
tempLink = *link; tempLink = *link;
while(tempLink->next != NULL && tempLink->polyobj != NULL) while(tempLink->next != nullptr && tempLink->polyobj != nullptr)
{ {
tempLink = tempLink->next; tempLink = tempLink->next;
} }
} }
if(tempLink->polyobj == NULL) if(tempLink->polyobj == nullptr)
{ {
tempLink->polyobj = this; tempLink->polyobj = this;
continue; continue;
@ -1266,7 +1246,7 @@ void FPolyObj::LinkPolyobj ()
else else
{ {
tempLink->next = new polyblock_t; tempLink->next = new polyblock_t;
tempLink->next->next = NULL; tempLink->next->next = nullptr;
tempLink->next->prev = tempLink; tempLink->next->prev = tempLink;
tempLink->next->polyobj = this; tempLink->next->polyobj = this;
} }
@ -1290,7 +1270,7 @@ void FPolyObj::RecalcActorFloorCeil(FBoundingBox bounds) const
FBlockThingsIterator it(bounds); FBlockThingsIterator it(bounds);
AActor *actor; AActor *actor;
while ((actor = it.Next()) != NULL) while ((actor = it.Next()) != nullptr)
{ {
// skip everything outside the bounding box. // skip everything outside the bounding box.
if (actor->X() + actor->radius <= bounds.Left() || if (actor->X() + actor->radius <= bounds.Left() ||
@ -1322,7 +1302,7 @@ void FPolyObj::ClosestPoint(const DVector2 &fpos, DVector2 &out, side_t **side)
double x = fpos.X, y = fpos.Y; double x = fpos.X, y = fpos.Y;
double bestdist = HUGE_VAL; double bestdist = HUGE_VAL;
double bestx = 0, besty = 0; double bestx = 0, besty = 0;
side_t *bestline = NULL; side_t *bestline = nullptr;
for (i = 0; i < Sidedefs.Size(); ++i) for (i = 0; i < Sidedefs.Size(); ++i)
{ {
@ -1370,7 +1350,7 @@ void FPolyObj::ClosestPoint(const DVector2 &fpos, DVector2 &out, side_t **side)
} }
} }
out = { bestx, besty }; out = { bestx, besty };
if (side != NULL) if (side != nullptr)
{ {
*side = bestline; *side = bestline;
} }
@ -1382,12 +1362,12 @@ void FPolyObj::ClosestPoint(const DVector2 &fpos, DVector2 &out, side_t **side)
// //
//========================================================================== //==========================================================================
bool PO_Busy (int polyobj) bool PO_Busy (FLevelLocals *Level, int polyobj)
{ {
FPolyObj *poly; FPolyObj *poly;
poly = PO_GetPolyobj (polyobj); poly = Level->GetPolyobj(polyobj);
return (poly != NULL && poly->specialdata != NULL); return (poly != nullptr && poly->specialdata != nullptr);
} }
@ -1400,19 +1380,19 @@ bool PO_Busy (int polyobj)
void FPolyObj::ClearSubsectorLinks() void FPolyObj::ClearSubsectorLinks()
{ {
while (subsectorlinks != NULL) while (subsectorlinks != nullptr)
{ {
assert(subsectorlinks->state == 1337); assert(subsectorlinks->state == 1337);
FPolyNode *next = subsectorlinks->snext; FPolyNode *next = subsectorlinks->snext;
if (subsectorlinks->pnext != NULL) if (subsectorlinks->pnext != nullptr)
{ {
assert(subsectorlinks->pnext->state == 1337); assert(subsectorlinks->pnext->state == 1337);
subsectorlinks->pnext->pprev = subsectorlinks->pprev; subsectorlinks->pnext->pprev = subsectorlinks->pprev;
} }
if (subsectorlinks->pprev != NULL) if (subsectorlinks->pprev != nullptr)
{ {
assert(subsectorlinks->pprev->state == 1337); assert(subsectorlinks->pprev->state == 1337);
subsectorlinks->pprev->pnext = subsectorlinks->pnext; subsectorlinks->pprev->pnext = subsectorlinks->pnext;
@ -1422,7 +1402,7 @@ void FPolyObj::ClearSubsectorLinks()
subsectorlinks->subsector->polys = subsectorlinks->pnext; subsectorlinks->subsector->polys = subsectorlinks->pnext;
} }
if (subsectorlinks->subsector->BSP != NULL) if (subsectorlinks->subsector->BSP != nullptr)
{ {
subsectorlinks->subsector->BSP->bDirty = true; subsectorlinks->subsector->BSP->bDirty = true;
} }
@ -1431,12 +1411,12 @@ void FPolyObj::ClearSubsectorLinks()
delete subsectorlinks; delete subsectorlinks;
subsectorlinks = next; subsectorlinks = next;
} }
subsectorlinks = NULL; subsectorlinks = nullptr;
} }
void FPolyObj::ClearAllSubsectorLinks() void FLevelLocals::ClearAllSubsectorLinks()
{ {
for(auto &poly : level.Polyobjects) for(auto &poly : Polyobjects)
{ {
poly.ClearSubsectorLinks(); poly.ClearSubsectorLinks();
} }
@ -1676,12 +1656,12 @@ static void SplitPoly(FPolyNode *pnode, void *node, float bbox[4])
// Link node to subsector // Link node to subsector
pnode->pnext = sub->polys; pnode->pnext = sub->polys;
if (pnode->pnext != NULL) if (pnode->pnext != nullptr)
{ {
assert(pnode->pnext->state == 1337); assert(pnode->pnext->state == 1337);
pnode->pnext->pprev = pnode; pnode->pnext->pprev = pnode;
} }
pnode->pprev = NULL; pnode->pprev = nullptr;
sub->polys = pnode; sub->polys = pnode;
// link node to polyobject // link node to polyobject
@ -1711,6 +1691,7 @@ static void SplitPoly(FPolyNode *pnode, void *node, float bbox[4])
void FPolyObj::CreateSubsectorLinks() void FPolyObj::CreateSubsectorLinks()
{ {
auto Level = GetLevel();
FPolyNode *node = NewPolyNode(); FPolyNode *node = NewPolyNode();
// Even though we don't care about it, we need to initialize this // Even though we don't care about it, we need to initialize this
// bounding box to something so that Valgrind won't complain about it // bounding box to something so that Valgrind won't complain about it
@ -1731,7 +1712,7 @@ void FPolyObj::CreateSubsectorLinks()
} }
if (!(i_compatflags & COMPATF_POLYOBJ)) if (!(i_compatflags & COMPATF_POLYOBJ))
{ {
SplitPoly(node, level.HeadNode(), dummybbox); SplitPoly(node, Level->HeadNode(), dummybbox);
} }
else else
{ {
@ -1739,12 +1720,12 @@ void FPolyObj::CreateSubsectorLinks()
// Link node to subsector // Link node to subsector
node->pnext = sub->polys; node->pnext = sub->polys;
if (node->pnext != NULL) if (node->pnext != nullptr)
{ {
assert(node->pnext->state == 1337); assert(node->pnext->state == 1337);
node->pnext->pprev = node; node->pnext->pprev = node;
} }
node->pprev = NULL; node->pprev = nullptr;
sub->polys = node; sub->polys = node;
// link node to polyobject // link node to polyobject
@ -1760,9 +1741,9 @@ void FPolyObj::CreateSubsectorLinks()
// //
//========================================================================== //==========================================================================
void PO_LinkToSubsectors() void PO_LinkToSubsectors(FLevelLocals *Level)
{ {
for(auto &poly : level.Polyobjects) for(auto &poly : Level->Polyobjects)
{ {
if (poly.subsectorlinks == nullptr) if (poly.subsectorlinks == nullptr)
{ {
@ -1781,7 +1762,7 @@ static FPolyNode *NewPolyNode()
{ {
FPolyNode *node; FPolyNode *node;
if (FreePolyNodes != NULL) if (FreePolyNodes != nullptr)
{ {
node = FreePolyNodes; node = FreePolyNodes;
FreePolyNodes = node->pnext; FreePolyNodes = node->pnext;
@ -1791,11 +1772,11 @@ static FPolyNode *NewPolyNode()
node = new FPolyNode; node = new FPolyNode;
} }
node->state = 1337; node->state = 1337;
node->poly = NULL; node->poly = nullptr;
node->pnext = NULL; node->pnext = nullptr;
node->pprev = NULL; node->pprev = nullptr;
node->subsector = NULL; node->subsector = nullptr;
node->snext = NULL; node->snext = nullptr;
return node; return node;
} }
@ -1822,7 +1803,7 @@ void ReleaseAllPolyNodes()
{ {
FPolyNode *node, *next; FPolyNode *node, *next;
for (node = FreePolyNodes; node != NULL; node = next) for (node = FreePolyNodes; node != nullptr; node = next)
{ {
next = node->pnext; next = node->pnext;
delete node; delete node;
@ -1841,7 +1822,7 @@ void ReleaseAllPolyNodes()
FPolyMirrorIterator::FPolyMirrorIterator(FPolyObj *poly) FPolyMirrorIterator::FPolyMirrorIterator(FPolyObj *poly)
{ {
CurPoly = poly; CurPoly = poly;
if (poly != NULL) if (poly != nullptr)
{ {
UsedPolys[0] = poly->tag; UsedPolys[0] = poly->tag;
NumUsedPolys = 1; NumUsedPolys = 1;
@ -1856,7 +1837,7 @@ FPolyMirrorIterator::FPolyMirrorIterator(FPolyObj *poly)
// //
// FPolyMirrorIterator :: NextMirror // FPolyMirrorIterator :: NextMirror
// //
// Returns the polyobject that mirrors the current one, or NULL if there // Returns the polyobject that mirrors the current one, or nullptr if there
// is no mirroring polyobject, or there is a mirroring polyobject but it was // is no mirroring polyobject, or there is a mirroring polyobject but it was
// already returned. // already returned.
// //
@ -1866,15 +1847,15 @@ FPolyObj *FPolyMirrorIterator::NextMirror()
{ {
FPolyObj *poly = CurPoly, *nextpoly; FPolyObj *poly = CurPoly, *nextpoly;
if (poly == NULL) if (poly == nullptr)
{ {
return NULL; return nullptr;
} }
// Do the work to decide which polyobject to return the next time this // Do the work to decide which polyobject to return the next time this
// function is called. // function is called.
int mirror = poly->GetMirror(), i; int mirror = poly->GetMirror(), i;
nextpoly = NULL; nextpoly = nullptr;
// Is there a mirror and we have room to remember it? // Is there a mirror and we have room to remember it?
if (mirror != 0 && NumUsedPolys != countof(UsedPolys)) if (mirror != 0 && NumUsedPolys != countof(UsedPolys))
@ -1890,8 +1871,8 @@ FPolyObj *FPolyMirrorIterator::NextMirror()
if (i == NumUsedPolys) if (i == NumUsedPolys)
{ // No, it has not been returned. { // No, it has not been returned.
UsedPolys[NumUsedPolys++] = mirror; UsedPolys[NumUsedPolys++] = mirror;
nextpoly = PO_GetPolyobj(mirror); nextpoly = poly->GetLevel()->GetPolyobj(mirror);
if (nextpoly == NULL) if (nextpoly == nullptr)
{ {
Printf("Invalid mirror polyobj num %d for polyobj num %d\n", mirror, UsedPolys[i - 1]); Printf("Invalid mirror polyobj num %d for polyobj num %d\n", mirror, UsedPolys[i - 1]);
} }

View file

@ -6,12 +6,14 @@
#include "m_bbox.h" #include "m_bbox.h"
#include "dthinker.h" #include "dthinker.h"
struct FPolyObj;
class DPolyAction : public DThinker class DPolyAction : public DThinker
{ {
DECLARE_CLASS(DPolyAction, DThinker) DECLARE_CLASS(DPolyAction, DThinker)
HAS_OBJECT_POINTERS HAS_OBJECT_POINTERS
public: public:
DPolyAction(int polyNum); DPolyAction(FPolyObj *polyNum);
void Serialize(FSerializer &arc); void Serialize(FSerializer &arc);
void OnDestroy() override; void OnDestroy() override;
void Stop(); void Stop();
@ -20,7 +22,7 @@ public:
void StopInterpolation(); void StopInterpolation();
protected: protected:
DPolyAction(); DPolyAction();
int m_PolyObj; FPolyObj *m_PolyObj;
double m_Speed; double m_Speed;
double m_Dist; double m_Dist;
TObjPtr<DInterpolation*> m_Interpolation; TObjPtr<DInterpolation*> m_Interpolation;
@ -107,6 +109,9 @@ struct FPolyObj
void UpdateLinks(); void UpdateLinks();
static void ClearAllSubsectorLinks(); static void ClearAllSubsectorLinks();
FLevelLocals *GetLevel() const;
private: private:
void ThrustMobj (AActor *actor, side_t *side); void ThrustMobj (AActor *actor, side_t *side);
@ -125,7 +130,7 @@ struct polyblock_t
}; };
void PO_LinkToSubsectors(); void PO_LinkToSubsectors(FLevelLocals *Level);
// ===== PO_MAN ===== // ===== PO_MAN =====
@ -137,14 +142,13 @@ typedef enum
PODOOR_SWING, PODOOR_SWING,
} podoortype_t; } podoortype_t;
bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle, int direction, bool overRide); bool EV_RotatePoly (FLevelLocals *Level, line_t *line, int polyNum, int speed, int byteAngle, int direction, bool overRide);
bool EV_MovePoly (line_t *line, int polyNum, double speed, DAngle angle, double dist, bool overRide); bool EV_MovePoly (FLevelLocals *Level, line_t *line, int polyNum, double speed, DAngle angle, double dist, bool overRide);
bool EV_MovePolyTo (line_t *line, int polyNum, double speed, const DVector2 &pos, bool overRide); bool EV_MovePolyTo (FLevelLocals *Level, line_t *line, int polyNum, double speed, const DVector2 &pos, bool overRide);
bool EV_OpenPolyDoor (line_t *line, int polyNum, double speed, DAngle angle, int delay, double distance, podoortype_t type); bool EV_OpenPolyDoor (FLevelLocals *Level, line_t *line, int polyNum, double speed, DAngle angle, int delay, double distance, podoortype_t type);
bool EV_StopPoly (int polyNum); bool EV_StopPoly (FLevelLocals *Level, int polyNum);
bool PO_Busy (int polyobj); bool PO_Busy (FLevelLocals *Level, int polyobj);
FPolyObj *PO_GetPolyobj(int polyNum);
#endif #endif

View file

@ -134,7 +134,7 @@ void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines)
R_SetupFrame(Viewpoint, Viewwindow, actor); R_SetupFrame(Viewpoint, Viewwindow, actor);
P_FindParticleSubsectors(); P_FindParticleSubsectors();
PO_LinkToSubsectors(); PO_LinkToSubsectors(&level);
static bool firstcall = true; static bool firstcall = true;
if (firstcall) if (firstcall)

View file

@ -163,7 +163,7 @@ namespace swrenderer
P_FindParticleSubsectors(); P_FindParticleSubsectors();
// Link the polyobjects right before drawing the scene to reduce the amounts of calls to this function // Link the polyobjects right before drawing the scene to reduce the amounts of calls to this function
PO_LinkToSubsectors(); PO_LinkToSubsectors(&level);
R_UpdateFuzzPosFrameStart(); R_UpdateFuzzPosFrameStart();