Compare commits

...
6 Commits
Author SHA1 Message Date
alufolie91 36d1f59114 correct map issues clientside
but be loud about it instead of I_Error´ing
most of those would be fatal anyways, so screw vanilla desyncing if they crash eitherways
2026-06-22 20:50:32 +02:00
entryway 99d49adad5 Check for blockmap overflow in P_BlockLinesIterator. Under RANGECHECK define. 2026-06-20 18:55:01 +02:00
alufolie91 6267e1a062 just set backsector to NULL
if not in vanilla doom compat mode/overflow emulation GetSectorAtNullAddress will just return NULL, so we can do so aswell
2026-06-19 19:08:14 +02:00
alufolie91 051bb528a6 add flag "COMPAT_VANILLA"
undefine to enable features that are not vanilla compatible
2026-06-19 19:08:11 +02:00
alufolie91 a95c9bf6ee port more checks from dsda-doom for invalid map data
decided to have it i_error for now, not sure what exactly is the best approach here
should we just "correct" some of those instead?
vanilla probably just crashes anyways
2026-06-19 16:54:58 +02:00
alufolie91 d74ebda83e replace non valid sidenum magic number
with what dsda-doom uses
2026-06-19 16:54:55 +02:00
16 changed files with 258 additions and 52 deletions

No files matched your search

+3 -1
View File
@@ -81,10 +81,12 @@ typedef struct
INT16 flags;
INT16 special;
INT16 tag;
// sidenum[1] will be 0xffff if one sided
// sidenum[1] will be NO_INDEX if one sided
UINT16 sidenum[2];
} ATTRPACK maplinedef_t;
#define NO_INDEX 0xffff
//
// LineDef attributes.
//
+11
View File
@@ -602,6 +602,9 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
// None of these that are disabled in the normal build are guaranteed to work perfectly
// Compile them at your own risk!
// undefine to enable fixes and features that are not vanilla compatible
#define COMPAT_VANILLA
//-- SATURN __
/// Detect if a client is on Saturn in the clientconfig.
/// To seperately allow them to join or block joining from vanilla clients.
@@ -666,6 +669,14 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
#undef UPDATE_ALERT
#endif
// overwrite some of those
// when not compiling in vanilla compat mode
#ifndef COMPAT_VANILLA
#define SATURNJOIN
#define SATURNPAK
#undef SEENAMES
#endif
#ifdef __cplusplus
} // extern "C"
#endif
+3
View File
@@ -1309,6 +1309,7 @@ static void G_DoLoadLevel(boolean resetplayer)
{
// fail so reset game stuff
Command_ExitGame_f();
P_FreeCorruptMapWarnings();
return;
}
@@ -1342,6 +1343,8 @@ static void G_DoLoadLevel(boolean resetplayer)
// clear hud messages remains (usually from game startup)
CON_ClearHUD();
// print any map errors now due to clearhud above :chaosleep:
P_PrintCorruptMapWarnings();
server_lagless = !cv_gentlemens.value;
+1 -1
View File
@@ -373,7 +373,7 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 count, poly_t *poly)
if (!gl_maphashorizonlines && line->special == HORIZONSPECIAL)
gl_maphashorizonlines = true;
if (line->sidenum[1] != 0xffff)
if (line->sidenum[1] != NO_INDEX)
{
if (sides[line->sidenum[0]].sector == sides[line->sidenum[1]].sector)
{
+1 -1
View File
@@ -729,7 +729,7 @@ static void HWR_PrecacheLevelTextures(void)
for (j = 0; j < 2; j++)
{
// check if single-sided linedef
if (line->sidenum[j] == 0xffff)
if (line->sidenum[j] == NO_INDEX)
continue;
const side_t *side = &sides[line->sidenum[j]];
+1 -1
View File
@@ -652,7 +652,7 @@ static int line_get(lua_State *L)
LUA_PushUserdata(L, &sides[line->sidenum[0]], META_SIDE);
return 1;
case line_backside: // backside
if (line->sidenum[1] == 0xffff)
if (line->sidenum[1] == NO_INDEX)
return 0;
LUA_PushUserdata(L, &sides[line->sidenum[1]], META_SIDE);
return 1;
+6 -2
View File
@@ -242,7 +242,7 @@ void P_CameraLineOpening(line_t *linedef)
sector_t *back;
fixed_t frontfloor, frontceiling, backfloor, backceiling;
if (linedef->sidenum[1] == 0xffff)
if (linedef->sidenum[1] == NO_INDEX)
{
// single sided line
openrange = 0;
@@ -398,7 +398,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
{
sector_t *front, *back;
if (linedef->sidenum[1] == 0xffff)
if (linedef->sidenum[1] == NO_INDEX)
{
// single sided line
openrange = 0;
@@ -972,6 +972,10 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *))
// First index is really empty, so +1 it.
for (list = blockmaplump + offset + 1; *list != -1; list++)
{
#ifdef RANGECHECK
if (*list < 0 || (UINT32)*list >= numlines)
I_Error("P_BlockLinesIterator: index >= numlines");
#endif
ld = &lines[*list];
if (ld->validcount == validcount)
+8
View File
@@ -11029,7 +11029,11 @@ void P_SpawnMapThing(mapthing_t *mthing)
{
if (mthing->type > MAXPLAYERS) // be wary of playerstarts size! playerstarts[MAXPLAYERS]
{
#ifdef COMPAT_VANILLA
CONS_Alert(CONS_ERROR, "Excess player start detected %d This will crash vanilla clients!\n", mthing->type);
#else
CONS_Debug(DBG_SETUP, "Excess player start detected %d\n", mthing->type);
#endif
}
else
{
@@ -11280,7 +11284,11 @@ void P_SpawnMapThing(mapthing_t *mthing)
if (P_MobjWasRemoved(mobj))
{
#ifdef COMPAT_VANILLA
CONS_Alert(CONS_ERROR, "Failed to spawn map thing #%d at %d, %d. This will crash vanilla clients!\n", mthing->type, x>>FRACBITS, y>>FRACBITS);
#else
CONS_Debug(DBG_SETUP, "Failed to spawn map thing #%d at %d, %d.\n", mthing->type, x>>FRACBITS, y>>FRACBITS);
#endif
return;
}
+9 -4
View File
@@ -691,7 +691,7 @@ static void ArchiveLines(savebuffer_t *save)
if (spawnli->special == 321 || spawnli->special == 322) // only reason li->callcount would be non-zero is if either of these are involved
diff |= LD_CLLCOUNT;
if (li->sidenum[0] != 0xffff)
if (li->sidenum[0] != NO_INDEX)
{
si = &sides[li->sidenum[0]];
spawnsi = &spawnsides[li->sidenum[0]];
@@ -706,7 +706,8 @@ static void ArchiveLines(savebuffer_t *save)
if (si->midtexture != spawnsi->midtexture)
diff |= LD_S1MIDTEX;
}
if (li->sidenum[1] != 0xffff)
if (li->sidenum[1] != NO_INDEX)
{
si = &sides[li->sidenum[1]];
spawnsi = &spawnsides[li->sidenum[1]];
@@ -786,6 +787,7 @@ static void UnArchiveFFloors(savebuffer_t *save, const sector_t *ss)
I_Error("Sector does not have any ffloors!");
fflr_i = READUINT16(save->p); // get first modified ffloor's number ready
for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here?
{
if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already
@@ -3510,7 +3512,7 @@ static void P_ReloadSaveLevelData(void)
li->firsttag = spawnli->firsttag;
li->nexttag = spawnli->nexttag;
if (li->sidenum[0] != 0xffff)
if (li->sidenum[0] != NO_INDEX)
{
si = &sides[li->sidenum[0]];
spawnsi = &spawnsides[li->sidenum[0]];
@@ -3521,7 +3523,7 @@ static void P_ReloadSaveLevelData(void)
si->midtexture = spawnsi->midtexture;
}
if (li->sidenum[1] != 0xffff)
if (li->sidenum[1] != NO_INDEX)
{
si = &sides[li->sidenum[1]];
spawnsi = &spawnsides[li->sidenum[1]];
@@ -3588,8 +3590,11 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool
if (!P_SetupLevel(true, reloading))
{
CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n"));
P_FreeCorruptMapWarnings();
return false;
}
P_PrintCorruptMapWarnings();
}
else
{
+196 -30
View File
@@ -188,6 +188,57 @@ FUNCNORETURN static ATTRNORETURN void CorruptMapError(const char *msg)
I_Error("Invalid or corrupt map.\nLook in log file or text console for technical details.");
}
static char **mapwarnings = NULL;
static size_t nummapwarnings = 0;
// collect map errors we can fix clientside
// we then can print em when the map finishes loading
// so they actually appear and raise awareness shits fucked
// see G_DoLoadLevel as to why :chaosleep:
static void CorruptMapWarning(const char *msg)
{
#ifdef PARANOIA
// just error out
I_Error("%sThis WILL crash Vanilla clients!\n", msg);
#endif
nummapwarnings++;
mapwarnings = Z_Realloc(mapwarnings, nummapwarnings * sizeof(*mapwarnings), PU_STATIC, NULL);
mapwarnings[nummapwarnings-1] = Z_StrDup(msg);
}
void P_PrintCorruptMapWarnings(void)
{
size_t i;
if (!nummapwarnings)
return;
for (i = 0; i < nummapwarnings; i++)
{
CONS_Alert(CONS_ERROR, "%sAttempting to fix... This WILL crash Vanilla clients!\n", mapwarnings[i]);
}
P_FreeCorruptMapWarnings();
}
void P_FreeCorruptMapWarnings(void)
{
size_t i;
if (!nummapwarnings)
return;
for (i = 0; i < nummapwarnings; i++)
{
Z_Free(mapwarnings[i]);
mapwarnings[i] = NULL;
}
Z_Free(mapwarnings);
mapwarnings = NULL;
nummapwarnings = 0;
}
#define NUMLAPS_DEFAULT 3
static void P_ClearMapHeaderLighting(mapheader_lighting_t *lighting)
@@ -437,8 +488,39 @@ static void P_LoadSegs(UINT8 *data)
for (i = 0; i < numsegs; i++, li++, ml++)
{
li->v1 = &vertexes[SHORT(ml->v1)];
li->v2 = &vertexes[SHORT(ml->v2)];
INT16 v1, v2;
v1 = SHORT(ml->v1);
v2 = SHORT(ml->v2);
// e6y
// check and fix wrong references to non-existent vertexes
// see e1m9 @ NIVELES.WAD
// http://www.doomworld.com/idgames/index.php?id=12647
if ((unsigned)v1 >= numvertexes || (unsigned)v2 >= numvertexes)
{
if ((unsigned)v1 >= numvertexes)
CorruptMapWarning(va("P_LoadSegs: seg %s references a non-existent vertex %d\n", sizeu1(i), v1));
if ((unsigned)v2 >= numvertexes)
CorruptMapWarning(va("P_LoadSegs: seg %s references a non-existent vertex %d\n", sizeu1(i), v2));
if (li->sidedef == &sides[li->linedef->sidenum[0]])
{
li->v1 = lines[ml->linedef].v1;
li->v2 = lines[ml->linedef].v2;
}
else
{
li->v1 = lines[ml->linedef].v2;
li->v2 = lines[ml->linedef].v1;
}
}
else
{
li->v1 = &vertexes[v1];
li->v2 = &vertexes[v2];
}
#ifdef HWRENDER
if (rendermode == render_opengl)
{
@@ -455,14 +537,59 @@ static void P_LoadSegs(UINT8 *data)
li->angle = (SHORT(ml->angle))<<FRACBITS;
li->offset = (SHORT(ml->offset))<<FRACBITS;
rawlinedef = SHORT(ml->linedef);
//e6y: check for wrong indexes
if ((unsigned)rawlinedef >= numlines)
{
I_Error("P_LoadSegs: seg %s references a non-existent linedef %d", sizeu1(i), (unsigned)rawlinedef);
}
ldef = &lines[rawlinedef];
li->linedef = ldef;
li->side = rawside = SHORT(ml->side);
rawside = SHORT(ml->side);
//e6y: fix wrong side index
if (rawside != 0 && rawside != 1)
{
CorruptMapWarning(va("P_LoadSegs: seg %s contains wrong side index %d.\n", sizeu1(i), rawside));
rawside = 1;
}
//e6y: check for wrong indexes
if (ldef->sidenum[rawside] >= numsides)
{
I_Error("P_LoadSegs: linedef %d for seg %s references a non-existent sidedef %d", rawlinedef, sizeu1(i), ldef->sidenum[rawside]);
}
li->side = rawside;
li->sidedef = &sides[ldef->sidenum[rawside]];
li->frontsector = sides[ldef->sidenum[rawside]].sector;
/* cph 2006/09/30 - our frontsector can be the second side of the
* linedef, so must check for NO_INDEX in case we are incorrectly
* referencing the back of a 1S line */
if (ldef->sidenum[rawside] == NO_INDEX)
{
CorruptMapWarning(va("P_LoadSegs: front of seg %s has no sidedef\n", sizeu1(i)));
li->frontsector = NULL;
}
else
{
li->frontsector = sides[ldef->sidenum[rawside]].sector;
}
if (ldef->flags & ML_TWOSIDED)
li->backsector = sides[ldef->sidenum[rawside^1]].sector;
{
if (ldef->sidenum[rawside^1] == NO_INDEX)
{
CorruptMapWarning(va("P_LoadSegs: back of seg %s has no sidedef while being marked as double sided\n", sizeu1(i)));
li->backsector = NULL;
}
else
{
li->backsector = sides[ldef->sidenum[rawside^1]].sector;
}
}
P_UpdateSegLightOffset(li);
}
@@ -738,7 +865,33 @@ static void P_LoadNodes(UINT8 *data)
for (j = 0; j < 2; j++)
{
no->children[j] = SHORT(mn->children[j]);
UINT16 child;
child = SHORT(mn->children[j]);
if (child & NF_SUBSECTOR)
{
// Convert to extended type
child &= ~NF_SUBSECTOR;
// haleyjd 11/06/10: check for invalid subsector reference
if (child >= numsubsectors)
{
CorruptMapWarning(va("P_LoadNodes: BSP tree %s references invalid subsector %d\n", sizeu1(i), child));
child = 0;
}
child |= NF_SUBSECTOR;
}
else if (child >= numnodes)
{
CorruptMapWarning(va("P_LoadNodes: BSP node %s references invalid node.\n", sizeu1(i)));
//I_Error("P_LoadNodes: BSP node %d references invalid node %d.\n", sizeu1(i), Index(((node_t *)no->children[j])));
child = 0;
}
no->children[j] = child;
for (k = 0; k < 4; k++)
no->bbox[j][k] = SHORT(mn->bbox[j][k])<<FRACBITS;
}
@@ -1001,9 +1154,9 @@ static void P_InitializeLinedef(line_t *ld)
// cph 2002/07/20 - these errors are fatal if not fixed, so apply them
for (j = 0; j < 2; j++)
{
if (ld->sidenum[j] != 0xffff && ld->sidenum[j] >= (UINT16)numsides)
if (ld->sidenum[j] != NO_INDEX && ld->sidenum[j] >= (UINT16)numsides)
{
ld->sidenum[j] = 0xffff;
ld->sidenum[j] = NO_INDEX;
CONS_Debug(DBG_SETUP, "P_InitializeLinedef: Linedef %s has out-of-range sidedef number\n", sizeu1((size_t)(ld - lines)));
}
}
@@ -1011,23 +1164,23 @@ static void P_InitializeLinedef(line_t *ld)
ld->firsttag = ld->nexttag = -1;
// killough 11/98: fix common wad errors (missing sidedefs):
if (ld->sidenum[0] == 0xffff)
if (ld->sidenum[0] == NO_INDEX)
{
ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side
// cph - print a warning about the bug
CONS_Debug(DBG_SETUP, "P_InitializeLinedef: Linedef %s missing first sidedef\n", sizeu1((size_t)(ld - lines)));
}
if ((ld->sidenum[1] == 0xffff) && (ld->flags & ML_TWOSIDED))
if ((ld->sidenum[1] == NO_INDEX) && (ld->flags & ML_TWOSIDED))
{
ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side
// cph - print a warning about the bug
CONS_Debug(DBG_SETUP, "P_InitializeLinedef: Linedef %s has two-sided flag set, but no second sidedef\n", sizeu1((size_t)(ld - lines)));
}
if (ld->sidenum[0] != 0xffff && ld->special)
if (ld->sidenum[0] != NO_INDEX && ld->special)
sides[ld->sidenum[0]].special = ld->special;
if (ld->sidenum[1] != 0xffff && ld->special)
if (ld->sidenum[1] != NO_INDEX && ld->special)
sides[ld->sidenum[1]].special = ld->special;
}
@@ -1060,10 +1213,10 @@ static void P_LoadLineDefs2(void)
for (; i--; ld++)
{
ld->frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here
ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : NULL;
ld->backsector = ld->sidenum[1] != NO_INDEX ? sides[ld->sidenum[1]].sector : NULL;
// Repeat count for midtexture
if ((ld->flags & ML_EFFECT5) && (ld->sidenum[1] != 0xffff))
if ((ld->flags & ML_EFFECT5) && (ld->sidenum[1] != NO_INDEX))
{
sides[ld->sidenum[0]].repeatcnt = (INT16)(((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) >> 12);
sides[ld->sidenum[0]].textureoffset = (((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) & 2047) << FRACBITS;
@@ -1079,13 +1232,13 @@ static void P_LoadLineDefs2(void)
{
size_t len = strlen(sides[ld->sidenum[0]].text)+1;
if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text)
if (ld->sidenum[1] != NO_INDEX && sides[ld->sidenum[1]].text)
len += strlen(sides[ld->sidenum[1]].text);
ld->text = Z_Malloc(len, PU_LEVEL, NULL);
memcpy(ld->text, sides[ld->sidenum[0]].text, strlen(sides[ld->sidenum[0]].text)+1);
if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text)
if (ld->sidenum[1] != NO_INDEX && sides[ld->sidenum[1]].text)
memcpy(ld->text+strlen(ld->text)+1, sides[ld->sidenum[1]].text, strlen(sides[ld->sidenum[1]].text)+1);
}
break;
@@ -1747,16 +1900,11 @@ static boolean P_LoadRawBlockMap(UINT8 *data, size_t count)
// http://www.doomworld.com/idgames/index.php?id=12935
if (!P_VerifyBlockMap(count))
{
#ifdef PARANOIA
I_Error("P_LoadBlockMap: erroneous BLOCKMAP lump may cause crashes.\n");
#endif
CONS_Alert(CONS_ERROR, "P_LoadBlockMap: erroneous BLOCKMAP lump may cause crashes.\n");
//Z_Free(blockmaplump);
//blockmaplump = NULL;
//return false; // ideally we would just let the game rebuild the blockmap
// but this has a chance of desynching vanilla clients
// not sure whats worse honestly and i do not want to decide that :chaosleep:
CorruptMapWarning(va("P_LoadBlockMap: corrupted or invalid BLOCKMAP lump! Check the log for more information.\n"));
// vanilla WILL crash here anyways so just rebuild it ourselves
Z_Free(blockmaplump);
blockmaplump = NULL;
return false;
}
// clear out mobj chains
@@ -1793,22 +1941,35 @@ static void P_GroupLines(void)
for (i = 0; i < numsubsectors; i++, ss++)
{
if (ss->firstline >= numsegs)
{
CorruptMapError(va("P_GroupLines: ss->firstline invalid "
"(subsector %s, firstline refers to %d of %s)", sizeu1(i), ss->firstline,
sizeu2(numsegs)));
}
seg = &segs[ss->firstline];
sidei = (size_t)(seg->sidedef - sides);
if (!seg->sidedef)
{
CorruptMapError(va("P_GroupLines: seg->sidedef is NULL "
"(subsector %s, firstline is %d)", sizeu1(i), ss->firstline));
}
if (seg->sidedef - sides < 0 || seg->sidedef - sides > (UINT16)numsides)
{
CorruptMapError(va("P_GroupLines: seg->sidedef refers to sidedef %s of %s "
"(subsector %s, firstline is %d)", sizeu1(sidei), sizeu2(numsides),
sizeu3(i), ss->firstline));
}
if (!seg->sidedef->sector)
{
CorruptMapError(va("P_GroupLines: seg->sidedef->sector is NULL "
"(subsector %s, firstline is %d, sidedef is %s)", sizeu1(i), ss->firstline,
sizeu1(sidei)));
}
ss->sector = seg->sidedef->sector;
}
@@ -1886,11 +2047,16 @@ static void P_LoadReject(UINT8 *data, size_t rejectsize)
{
if (rejectsize < neededsize)
{
#ifdef PARANOIA
I_Error("REJECT is %s byte%s too small. REJECT might be invalid and crash vanilla clients!\n", sizeu1(neededsize - rejectsize), (neededsize - rejectsize) == 1 ? "" : "s");
#endif
CONS_Alert(CONS_ERROR, "REJECT is %s byte%s too small. REJECT might be invalid and crash vanilla clients!\n", sizeu1(neededsize - rejectsize), (neededsize - rejectsize) == 1 ? "" : "s");
CorruptMapWarning(va("P_LoadReject: REJECT is %s byte%s too small. REJECT might be invalid!\n", sizeu1(neededsize - rejectsize), (neededsize - rejectsize) == 1 ? "" : "s"));
#ifdef COMPAT_VANILLA
// we can pad this and somewhat prevent desyncs
// probs not cool if the reject is from a completely different map
// but whatever
allocsize = neededsize;
#else
rejectmatrix = NULL;
return;
#endif
}
rejectmatrix = Z_Calloc(allocsize, PU_LEVEL, NULL); // allocate memory for the reject matrix
+3
View File
@@ -114,6 +114,9 @@ size_t P_PrecacheLevelFlats(void);
void P_AllocMapHeader(INT16 i);
void P_PrintCorruptMapWarnings(void);
void P_FreeCorruptMapWarnings(void);
#ifdef __cplusplus
} // extern "C"
#endif
+11 -9
View File
@@ -889,7 +889,7 @@ static boolean PolyDoor(line_t *line)
pdd.angle = line->angle; // angle of motion
pdd.distance = sides[line->sidenum[0]].rowoffset;
if (line->sidenum[1] != 0xffff)
if (line->sidenum[1] != NO_INDEX)
pdd.delay = sides[line->sidenum[1]].textureoffset >> FRACBITS; // delay in tics
else
pdd.delay = 0;
@@ -899,7 +899,7 @@ static boolean PolyDoor(line_t *line)
pdd.speed = sides[line->sidenum[0]].textureoffset >> FRACBITS; // angular speed
pdd.distance = sides[line->sidenum[0]].rowoffset >> FRACBITS; // angular distance
if (line->sidenum[1] != 0xffff)
if (line->sidenum[1] != NO_INDEX)
pdd.delay = sides[line->sidenum[1]].textureoffset >> FRACBITS; // delay in tics
else
pdd.delay = 0;
@@ -1989,8 +1989,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
INT32 position = (INT32)max(sides[line->sidenum[0]].midtexture, 0);
UINT32 prefadems = (UINT32)max(sides[line->sidenum[0]].textureoffset >> FRACBITS, 0);
UINT32 postfadems = (UINT32)max(sides[line->sidenum[0]].rowoffset >> FRACBITS, 0);
UINT8 fadetarget = (UINT8)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].textureoffset >> FRACBITS : 0, 0);
INT16 fadesource = (INT16)max((line->sidenum[1] != 0xffff) ? sides[line->sidenum[1]].rowoffset >> FRACBITS : -1, -1);
UINT8 fadetarget = (UINT8)max((line->sidenum[1] != NO_INDEX) ? sides[line->sidenum[1]].textureoffset >> FRACBITS : 0, 0);
INT16 fadesource = (INT16)max((line->sidenum[1] != NO_INDEX) ? sides[line->sidenum[1]].rowoffset >> FRACBITS : -1, -1);
// Seek offset from current song position
if (line->flags & ML_EFFECT1)
@@ -2504,7 +2504,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
var1 = sides[line->sidenum[0]].toptexture; //(line->dx>>FRACBITS)-1;
if (line->sidenum[1] != 0xffff && line->flags & ML_BLOCKMONSTERS) // read power from back sidedef
if (line->sidenum[1] != NO_INDEX && line->flags & ML_BLOCKMONSTERS) // read power from back sidedef
var2 = sides[line->sidenum[1]].toptexture;
else if (line->flags & ML_NOCLIMB) // 'Infinite'
var2 = UINT16_MAX;
@@ -2633,7 +2633,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (always || this->bottomtexture)
this->bottomtexture = set->bottomtexture;
if (lines[linenum].sidenum[1] == 0xffff)
if (lines[linenum].sidenum[1] == NO_INDEX)
continue; // One-sided stops here.
// Back side
@@ -2682,7 +2682,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
sector_t *sec;
mobj_t *thing;
if (line->sidenum[1] != 0xffff)
if (line->sidenum[1] != NO_INDEX)
state = (statenum_t)sides[line->sidenum[1]].toptexture;
while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
@@ -4609,11 +4609,13 @@ void P_UpdateSpecials(void)
// POINT LIMIT
P_CheckPointLimit();
#ifdef COMPAT_VANILLA
// Dynamic slopeness
// we run this here only when not joined midrace
// for vanilla compat reasons :chaosleep:
if (!midgamejoin)
P_RunDynamicSlopes();
#endif
P_UpdateAnimFlats();
}
@@ -6056,7 +6058,7 @@ void P_SpawnSpecials(INT32 fromnetsave, boolean reloadinggamestate)
break;
case 259: // Make-Your-Own FOF!
if (lines[i].sidenum[1] != 0xffff)
if (lines[i].sidenum[1] != NO_INDEX)
{
UINT8 *data;
UINT16 b;
@@ -6785,7 +6787,7 @@ static void P_SpawnScrollers(void)
case 506:
s = lines[i].sidenum[1];
if (s != 0xffff)
if (s != NO_INDEX)
Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, lines[i].sidenum[0], accel, 0);
else
CONS_Debug(DBG_GAMELOGIC, "Line special 506 (line #%s) missing 2nd side!\n", sizeu1(i));
+2
View File
@@ -646,7 +646,9 @@ void P_Ticker(boolean run)
if (run)
{
// Dynamic slopeness
#ifdef COMPAT_VANILLA
if (midgamejoin) // only run here if we joined midgame to fix some desynchs
#endif
P_RunDynamicSlopes();
PS_START_TIMING(ps_thinkertime);
+1 -1
View File
@@ -430,7 +430,7 @@ typedef struct line_s
INT16 tag;
// Visual appearance: sidedefs.
UINT16 sidenum[2]; // sidenum[1] will be 0xffff if one-sided
UINT16 sidenum[2]; // sidenum[1] will be NO_INDEX if one-sided
fixed_t alpha; // translucency
UINT8 blendmode; // blendmode
+1 -1
View File
@@ -2204,7 +2204,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
topremap = (encoremap && !(curline->linedef->flags & ML_TFERLINE));
if ((linedef->flags & (ML_DONTPEGTOP) && (linedef->flags & ML_DONTPEGBOTTOM))
&& linedef->sidenum[1] != 0xffff)
&& linedef->sidenum[1] != NO_INDEX)
{
// Special case... use offsets from 2nd side but only if it has a texture.
side_t *def = &sides[linedef->sidenum[1]];
+1 -1
View File
@@ -131,7 +131,7 @@ void R_AddWallSplat(line_t *wallline, INT16 sectorside, const char *patchname, f
// set the splat
splat->patch = W_GetNumForName(patchname);
sectorside ^= 1;
if (wallline->sidenum[sectorside] != 0xffff)
if (wallline->sidenum[sectorside] != NO_INDEX)
{
backsector = sides[wallline->sidenum[sectorside]].sector;