Merge pull request 'Map Patches' (#52) from mappatch into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/52
This commit is contained in:
commit
0699647d60
16 changed files with 331 additions and 85 deletions
|
|
@ -43,7 +43,7 @@ engine = "zdoom";
|
|||
linetagindicatesectors = true;
|
||||
|
||||
// The format interface handles the map data format - DoomMapSetIO for SRB2DB2, SRB2MapSetIO for Zone Builder
|
||||
formatinterface = "SRB2MapSetIO";
|
||||
formatinterface = "DoomMapSetIO";
|
||||
|
||||
//Sky textures for vanilla maps
|
||||
defaultskytextures
|
||||
|
|
|
|||
|
|
@ -82,8 +82,14 @@ udmf
|
|||
prefix = "(2001)";
|
||||
arg0
|
||||
{
|
||||
title = "Flip?";
|
||||
type = 3;
|
||||
title = "Flags";
|
||||
type = 12;
|
||||
enum
|
||||
{
|
||||
1 = "Flip";
|
||||
2 = "Single-use";
|
||||
4 = "Require sector special";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5388,6 +5388,17 @@ udmf
|
|||
5 = "End drift";
|
||||
}
|
||||
}
|
||||
arg4
|
||||
{
|
||||
title = "Patch finish flags";
|
||||
type = 12;
|
||||
enum
|
||||
{
|
||||
1 = "Flip";
|
||||
2 = "Single-use";
|
||||
4 = "Require sector special";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2004
|
||||
|
|
|
|||
|
|
@ -441,7 +441,7 @@ UINT32 quickncasehash (const char *p, size_t n)
|
|||
#include "xxhash.h"
|
||||
#define HASH64(p, n) ((UINT64)XXH3_64bits(p, n))
|
||||
#define HASH32(p, n) ((UINT32)(XXH3_64bits(p, n) & UINT32_MAX))
|
||||
#define HASHFMT "%jx"
|
||||
#define HASHFMT "%016jx"
|
||||
|
||||
#ifndef __cplusplus
|
||||
#ifndef min // Double-Check with WATTCP-32's cdefs.h
|
||||
|
|
|
|||
18
src/k_hud.c
18
src/k_hud.c
|
|
@ -4790,21 +4790,15 @@ static void K_drawCheckpointDebugger(void)
|
|||
if (stplyr != &players[displayplayers[0]]) // only for p1
|
||||
return;
|
||||
|
||||
if (K_UsingLegacyCheckpoints())
|
||||
{
|
||||
if (stplyr->starpostnum >= (numstarposts - (numstarposts/2)))
|
||||
V_DrawString(8, 184, 0, va("Checkpoint: %d / %d (Can finish)", stplyr->starpostnum, numstarposts));
|
||||
else
|
||||
V_DrawString(8, 184, 0, va("Checkpoint: %d / %d (Skip: %d)", stplyr->starpostnum, numstarposts, ((numstarposts/2) + stplyr->starpostnum)));
|
||||
V_DrawString(8, 192, 0, va("Waypoint dist: Prev %d, Next %d", stplyr->prevcheck, stplyr->nextcheck));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stplyr->starpostnum == numstarposts)
|
||||
if (stplyr->starpostnum >= K_CheckpointThreshold(true))
|
||||
V_DrawString(8, 184, 0, va("Checkpoint: %d / %d (Can finish)", stplyr->starpostnum, numstarposts));
|
||||
else if (K_CheckpointThreshold(false) != numstarposts)
|
||||
V_DrawString(8, 184, 0, va("Checkpoint: %d / %d (Skip: %d)", stplyr->starpostnum, numstarposts, K_CheckpointThreshold(false) + stplyr->starpostnum));
|
||||
else
|
||||
V_DrawString(8, 184, 0, va("Checkpoint: %d / %d", stplyr->starpostnum, numstarposts));
|
||||
}
|
||||
|
||||
if (K_UsingLegacyCheckpoints())
|
||||
V_DrawString(8, 192, 0, va("Waypoint dist: Prev %d, Next %d", stplyr->prevcheck, stplyr->nextcheck));
|
||||
}
|
||||
|
||||
static void K_DrawWaypointDebugger(void)
|
||||
|
|
|
|||
32
src/k_kart.c
32
src/k_kart.c
|
|
@ -8358,6 +8358,11 @@ static boolean K_SetPlayerNextWaypoint(player_t *player)
|
|||
if (bestwaypoint != NULL)
|
||||
{
|
||||
player->currentwaypoint = bestwaypoint;
|
||||
|
||||
// if currentwaypoint is the finish line, don't set nextwaypoint to it!
|
||||
// fixes bigwaypointgap triggering if we're facing the back of the finish line
|
||||
if (bestwaypoint == finishline)
|
||||
bestwaypoint = NULL;
|
||||
}
|
||||
|
||||
// check the waypoint's location in relation to the player
|
||||
|
|
@ -8475,7 +8480,8 @@ static boolean K_SetPlayerNextWaypoint(player_t *player)
|
|||
}
|
||||
|
||||
if ((waypoint->prevwaypoints != NULL) && (waypoint->numprevwaypoints > 0U)
|
||||
&& !(K_PlayerUsesBotMovement(player))) // Bots do not need prev waypoints
|
||||
&& !(K_PlayerUsesBotMovement(player)) // Bots do not need prev waypoints
|
||||
&& waypoint != finishline) // do not check finish line's prevwaypoints
|
||||
{
|
||||
for (i = 0U; i < waypoint->numprevwaypoints; i++)
|
||||
{
|
||||
|
|
@ -10978,6 +10984,11 @@ boolean K_SlipdashActive(void)
|
|||
|
||||
boolean K_UsingLegacyCheckpoints(void)
|
||||
{
|
||||
if (K_UsingPatchedMap() && waypointcap)
|
||||
{
|
||||
// we're presumably adding waypoints to an existing map
|
||||
return false;
|
||||
}
|
||||
if (numbosswaypoints > 0)
|
||||
{
|
||||
// We are using Kart V1 waypoints!
|
||||
|
|
@ -10987,6 +10998,25 @@ boolean K_UsingLegacyCheckpoints(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
boolean K_UsingPatchedMap(void)
|
||||
{
|
||||
if (patch_version)
|
||||
{
|
||||
// This map has been patched!
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
INT32 K_CheckpointThreshold(boolean roundup)
|
||||
{
|
||||
if (K_UsingLegacyCheckpoints() || K_UsingPatchedMap())
|
||||
return roundup ? numstarposts - numstarposts/2 : numstarposts/2;
|
||||
else
|
||||
return numstarposts;
|
||||
}
|
||||
|
||||
void K_UpdateMobjItemOverlay(mobj_t *part, SINT8 itemType, UINT8 itemCount)
|
||||
{
|
||||
switch (itemType)
|
||||
|
|
|
|||
|
|
@ -255,6 +255,8 @@ boolean K_SlipdashActive(void);
|
|||
boolean K_BoostChain(player_t *player, INT32 timer, boolean chainsound);
|
||||
INT32 K_ChainOrDeincrementTime(player_t *player, INT32 timer, INT32 deincrement, boolean chainsound);
|
||||
boolean K_UsingLegacyCheckpoints(void);
|
||||
boolean K_UsingPatchedMap(void);
|
||||
INT32 K_CheckpointThreshold(boolean roundup);
|
||||
|
||||
void K_UpdateMobjItemOverlay(mobj_t *part, SINT8 itemType, UINT8 itemCount);
|
||||
|
||||
|
|
|
|||
|
|
@ -2179,14 +2179,14 @@ static waypoint_t *K_SetupWaypoint(mobj_t *const mobj)
|
|||
firstwaypoint = thiswaypoint;
|
||||
}
|
||||
|
||||
if (K_GetWaypointIsFinishline(thiswaypoint))
|
||||
if (K_GetWaypointIsFinishline(thiswaypoint) && K_GetWaypointIsEnabled(thiswaypoint))
|
||||
{
|
||||
if (finishline != NULL)
|
||||
{
|
||||
const INT32 oldfinishlineid = K_GetWaypointID(finishline);
|
||||
const INT32 thiswaypointid = K_GetWaypointID(thiswaypoint);
|
||||
CONS_Alert(
|
||||
CONS_WARNING, "Multiple finish line waypoints with IDs %d and %d! Using %d.",
|
||||
CONS_WARNING, "Multiple finish line waypoints with IDs %d and %d! Using %d.\n",
|
||||
oldfinishlineid, thiswaypointid, thiswaypointid);
|
||||
}
|
||||
finishline = thiswaypoint;
|
||||
|
|
|
|||
|
|
@ -941,8 +941,10 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost)
|
|||
|
||||
(void)snaptopost;
|
||||
|
||||
// Player must have touched all previous starposts
|
||||
if ((post->health - player->starpostnum > 1) && (!K_UsingLegacyCheckpoints()))
|
||||
// Going backwards triggers sound
|
||||
if (K_CheckpointThreshold(false) == numstarposts
|
||||
? post->health - player->starpostnum > 1
|
||||
: post->health >= player->starpostnum + K_CheckpointThreshold(false))
|
||||
{
|
||||
if (!player->checkskip)
|
||||
{
|
||||
|
|
@ -952,17 +954,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost)
|
|||
player->grieftime += TICRATE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
player->checkskip = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
// Going backwards triggers sound
|
||||
if ((post->health >= ((numstarposts/2) + player->starpostnum)) && (K_UsingLegacyCheckpoints()))
|
||||
{
|
||||
if (!player->checkskip)
|
||||
S_StartSound(toucher, sfx_s26d);
|
||||
|
||||
player->checkskip = 3;
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -100,6 +100,9 @@ camera_t *mapcampointer;
|
|||
//
|
||||
static boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
|
||||
{
|
||||
boolean startingonground = P_IsObjectOnGround(thing);
|
||||
sector_t *oldsector = thing->subsector->sector;
|
||||
|
||||
numspechit = 0U;
|
||||
|
||||
// the move is ok,
|
||||
|
|
@ -129,6 +132,8 @@ static boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
|
|||
thing->floorrover = g_tm.floorrover;
|
||||
thing->ceilingrover = g_tm.ceilingrover;
|
||||
|
||||
P_CheckSectorTransitionalEffects(thing, oldsector, startingonground);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2745,6 +2750,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff, Try
|
|||
fixed_t oldx = thing->x;
|
||||
fixed_t oldy = thing->y;
|
||||
fixed_t startingonground = P_IsObjectOnGround(thing);
|
||||
sector_t *oldsector = thing->subsector->sector;
|
||||
|
||||
// Is the move OK?
|
||||
if (increment_move(thing, x, y, allowdropoff, result) == false)
|
||||
|
|
@ -2847,6 +2853,8 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff, Try
|
|||
|
||||
P_SetThingPosition(thing);
|
||||
|
||||
P_CheckSectorTransitionalEffects(thing, oldsector, startingonground);
|
||||
|
||||
// remove any duplicates that may be in spechitint
|
||||
spechitint_removedups();
|
||||
|
||||
|
|
|
|||
|
|
@ -1236,7 +1236,6 @@ static void P_LinkToBlockMap(mobj_t *thing, mobj_t **bmap)
|
|||
void P_SetThingPosition(mobj_t *thing)
|
||||
{ // link into subsector
|
||||
subsector_t *ss;
|
||||
sector_t *prevsec = NULL;
|
||||
sector_t *oldsec = NULL;
|
||||
fixed_t tfloorz, tceilz;
|
||||
|
||||
|
|
@ -1249,11 +1248,6 @@ void P_SetThingPosition(mobj_t *thing)
|
|||
oldsec = thing->subsector->sector;
|
||||
}
|
||||
|
||||
if (thing->subsector)
|
||||
{
|
||||
prevsec = thing->subsector->sector;
|
||||
}
|
||||
|
||||
ss = thing->subsector = R_PointInSubsector(thing->x, thing->y);
|
||||
|
||||
if (!(thing->flags & MF_NOSECTOR))
|
||||
|
|
@ -1310,12 +1304,6 @@ void P_SetThingPosition(mobj_t *thing)
|
|||
else if (thing->z <= tfloorz)
|
||||
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
|
||||
}
|
||||
|
||||
if (udmf && prevsec != thing->subsector->sector)
|
||||
{
|
||||
// Check for each time / once sector special actions
|
||||
P_CheckMobjTouchingSectorActions(thing, false);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
51
src/p_mobj.c
51
src/p_mobj.c
|
|
@ -2175,10 +2175,13 @@ boolean P_ZMovement(mobj_t *mo)
|
|||
{
|
||||
fixed_t dist, delta;
|
||||
boolean onground;
|
||||
boolean wasonground;
|
||||
|
||||
I_Assert(mo != NULL);
|
||||
I_Assert(!P_MobjWasRemoved(mo));
|
||||
|
||||
wasonground = P_IsObjectOnGround(mo);
|
||||
|
||||
// Intercept the stupid 'fall through 3dfloors' bug
|
||||
if (mo->subsector->sector->ffloors)
|
||||
P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 0);
|
||||
|
|
@ -2604,6 +2607,8 @@ boolean P_ZMovement(mobj_t *mo)
|
|||
}
|
||||
}
|
||||
|
||||
P_CheckSectorTransitionalEffects(mo, mo->subsector->sector, wasonground);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2697,6 +2702,7 @@ static boolean P_PlayerPolyObjectZMovement(mobj_t *mo)
|
|||
void P_PlayerZMovement(mobj_t *mo)
|
||||
{
|
||||
boolean onground;
|
||||
boolean wasonground;
|
||||
|
||||
I_Assert(mo != NULL);
|
||||
I_Assert(!P_MobjWasRemoved(mo));
|
||||
|
|
@ -2704,6 +2710,8 @@ void P_PlayerZMovement(mobj_t *mo)
|
|||
if (!mo->player)
|
||||
return;
|
||||
|
||||
wasonground = P_IsObjectOnGround(mo);
|
||||
|
||||
// Intercept the stupid 'fall through 3dfloors' bug
|
||||
if (mo->subsector->sector->ffloors)
|
||||
P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 0);
|
||||
|
|
@ -2834,6 +2842,8 @@ void P_PlayerZMovement(mobj_t *mo)
|
|||
P_CheckGravity(mo, true);
|
||||
}
|
||||
}
|
||||
|
||||
P_CheckSectorTransitionalEffects(mo, mo->subsector->sector, wasonground);
|
||||
}
|
||||
|
||||
boolean P_SceneryZMovement(mobj_t *mo)
|
||||
|
|
@ -10212,7 +10222,7 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
if (udmf)
|
||||
{
|
||||
// Check for continuous sector special actions
|
||||
P_CheckMobjTouchingSectorActions(mobj, true);
|
||||
P_CheckMobjTouchingSectorActions(mobj, true, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -12856,15 +12866,21 @@ static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void P_SnapToFinishLine(mobj_t *mobj)
|
||||
static void SpreadFinishLine(line_t *line, line_t *prev, INT32 args)
|
||||
{
|
||||
line_t *finishline = P_FindNearestLine(mobj->x, mobj->y,
|
||||
mobj->subsector->sector, 2001); // case 2001: Finish Line
|
||||
if (finishline != NULL)
|
||||
size_t i;
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
P_UnsetThingPosition(mobj);
|
||||
P_ClosestPointOnLine(mobj->x, mobj->y, finishline, (vertex_t *)&mobj->x);
|
||||
P_SetThingPosition(mobj);
|
||||
line_t *line2 = &lines[i];
|
||||
if (line2 != line && line2 != prev && (line2->slopetype == ST_HORIZONTAL || line2->slopetype == ST_VERTICAL) && line2->slopetype == line->slopetype &&
|
||||
(line->v1 == line2->v1 || line->v2 == line2->v2 || line->v1 == line2->v2 || line->v2 == line2->v1))
|
||||
{
|
||||
boolean flipped = line->v1 == line2->v1 || line->v2 == line2->v2 ? TMCFF_FLIP : 0;
|
||||
line2->special = 2001; // Finish Line
|
||||
line2->activation = SPAC_CROSS|SPAC_REPEATSPECIAL;
|
||||
line2->args[0] = args ^ flipped;
|
||||
SpreadFinishLine(line2, line, args ^ flipped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -13128,6 +13144,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
|
|||
mobj->threshold = mthing->args[0];
|
||||
|
||||
mobj->movecount = tag;
|
||||
|
||||
if (mthing->args[2] & TMWPF_DISABLED)
|
||||
{
|
||||
mobj->extravalue1 = 0; // The waypoint is disabled if extra is on
|
||||
|
|
@ -13152,12 +13169,28 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
|
|||
{
|
||||
mobj->reactiontime = 1;
|
||||
}
|
||||
|
||||
if (mthing->args[2] & TMWPF_FINISHLINE)
|
||||
{
|
||||
mobj->extravalue2 = 1; // args[2] of 1 means the waypoint is at the finish line
|
||||
mobj->reactiontime = 0; // Also don't respawn at finish lines
|
||||
|
||||
P_SnapToFinishLine(mobj);
|
||||
line_t *finishline = P_FindNearestLine(mobj->x, mobj->y,
|
||||
mobj->subsector->sector, K_UsingPatchedMap() ? -1 : 2001); // case 2001: Finish Line
|
||||
if (finishline != NULL)
|
||||
{
|
||||
P_UnsetThingPosition(mobj);
|
||||
P_ClosestPointOnLine(mobj->x, mobj->y, finishline, (vertex_t *)&mobj->x);
|
||||
P_SetThingPosition(mobj);
|
||||
|
||||
if (K_UsingPatchedMap())
|
||||
{
|
||||
finishline->special = 2001; // Finish Line
|
||||
finishline->activation = SPAC_CROSS|SPAC_REPEATSPECIAL;
|
||||
finishline->args[0] = mthing->args[4];
|
||||
SpreadFinishLine(finishline, NULL, mthing->args[4]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
142
src/p_setup.c
142
src/p_setup.c
|
|
@ -125,7 +125,7 @@ UINT64 maphash;
|
|||
//
|
||||
|
||||
boolean udmf;
|
||||
INT32 udmf_version;
|
||||
INT32 udmf_version, patch_version;
|
||||
mapnamespace_t mapnamespace = MNS_UNKNOWN;
|
||||
size_t numvertexes, numsegs, numsectors, numsubsectors, numnodes, numlines, numsides, nummapthings;
|
||||
size_t num_orig_vertexes;
|
||||
|
|
@ -1461,20 +1461,32 @@ static void TextmapStorePos(textmap_block_t *blocks, size_t *count)
|
|||
}
|
||||
|
||||
// Determine total amount of map data in TEXTMAP.
|
||||
static boolean TextmapCount(size_t size)
|
||||
static boolean TextmapCount(size_t size, boolean patch)
|
||||
{
|
||||
TracyCZone(__zone, true);
|
||||
|
||||
const char *tkn = M_TokenizerRead(0);
|
||||
UINT8 brackets = 0;
|
||||
|
||||
nummapthings = 0;
|
||||
numlines = 0;
|
||||
numsides = 0;
|
||||
numvertexes = 0;
|
||||
numsectors = 0;
|
||||
// check namespace for patches
|
||||
if (patch)
|
||||
{
|
||||
// Look for namespace at the beginning.
|
||||
if (!fastcmp(tkn, "namespace"))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "No namespace at beginning of lump!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// skip namespace, it's checked by P_SetMapNamespace
|
||||
// Check if namespace is valid.
|
||||
tkn = M_TokenizerRead(0);
|
||||
if (!fastcmp(tkn, "blankart-patch"))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Invalid namespace '%s'. Only 'blankart-patch' is supported.\n", tkn);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
M_TokenizerRead(0);
|
||||
|
||||
// Check for version
|
||||
|
|
@ -1482,10 +1494,63 @@ static boolean TextmapCount(size_t size)
|
|||
if (fastcmp(tkn, "version"))
|
||||
{
|
||||
tkn = M_TokenizerRead(0);
|
||||
if (patch)
|
||||
{
|
||||
patch_version = atoi(tkn);
|
||||
if (patch_version > PATCH_CURRENT_VERSION)
|
||||
CONS_Alert(CONS_WARNING, "Patch is intended for future patch version '%d', current supported version is '%d'. This patch may have issues loading.\n", patch_version, PATCH_CURRENT_VERSION);
|
||||
}
|
||||
else
|
||||
{
|
||||
udmf_version = atoi(tkn);
|
||||
if (udmf_version > UDMF_CURRENT_VERSION)
|
||||
CONS_Alert(CONS_WARNING, "Map is intended for future UDMF version '%d', current supported version is '%d'. This map may have issues loading.\n", udmf_version, UDMF_CURRENT_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
// check hash for patches
|
||||
if (patch)
|
||||
{
|
||||
tkn = M_TokenizerRead(0);
|
||||
if (!fastcmp(tkn, "checksum"))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "No checksum in lump!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
tkn = M_TokenizerRead(0);
|
||||
boolean foundhash = false;
|
||||
const char *hashstr = tkn;
|
||||
char *end;
|
||||
|
||||
// check for hashes separated by pipes
|
||||
// e.g. "abc123|def456|ghi789"
|
||||
do
|
||||
{
|
||||
UINT64 hash = strtoull(hashstr, &end, 16);
|
||||
if (hash == maphash)
|
||||
foundhash = true;
|
||||
if (end == hashstr || (*end && *end != '|'))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Invalid checksum string '%s'\n", tkn);
|
||||
return false;
|
||||
}
|
||||
hashstr = end + 1;
|
||||
}
|
||||
while (*end);
|
||||
|
||||
if (!foundhash)
|
||||
CONS_Alert(CONS_WARNING, "This map patch is not compatible with the current map (checksum: " HASHFMT "). The patch may not work.\n", maphash);
|
||||
}
|
||||
|
||||
nummapthings = 0;
|
||||
if (!patch)
|
||||
{
|
||||
numlines = 0;
|
||||
numsides = 0;
|
||||
numvertexes = 0;
|
||||
numsectors = 0;
|
||||
}
|
||||
|
||||
while ((tkn = M_TokenizerRead(0)) && M_TokenizerGetEndPos() < size)
|
||||
{
|
||||
|
|
@ -1500,6 +1565,8 @@ static boolean TextmapCount(size_t size)
|
|||
// Check for valid fields.
|
||||
else if (fastcmp(tkn, "thing"))
|
||||
TextmapStorePos(&mapthingBlocks, &nummapthings);
|
||||
else if (patch)
|
||||
continue;
|
||||
else if (fastcmp(tkn, "linedef"))
|
||||
TextmapStorePos(&linedefBlocks, &numlines);
|
||||
else if (fastcmp(tkn, "sidedef"))
|
||||
|
|
@ -3213,7 +3280,7 @@ static void P_WriteTextmapWaypoints(void)
|
|||
|
||||
/** Loads the textmap data, after obtaining the elements count and allocating their respective space.
|
||||
*/
|
||||
static void P_LoadTextmap(void)
|
||||
static void P_LoadTextmap(boolean patch)
|
||||
{
|
||||
TracyCZone(__zone, true);
|
||||
|
||||
|
|
@ -3232,6 +3299,7 @@ static void P_LoadTextmap(void)
|
|||
/// from the textmap, and therefore we have to account for it by
|
||||
/// preemptively setting that value beforehand.
|
||||
|
||||
if (!patch)
|
||||
for (i = 0, vt = vertexes; i < numvertexes; i++, vt++)
|
||||
{
|
||||
// Defaults.
|
||||
|
|
@ -3247,6 +3315,7 @@ static void P_LoadTextmap(void)
|
|||
I_Error("P_LoadTextmap: vertex %s has no y value set!\n", sizeu1(i));
|
||||
}
|
||||
|
||||
if (!patch)
|
||||
for (i = 0, sc = sectors; i < numsectors; i++, sc++)
|
||||
{
|
||||
// Defaults.
|
||||
|
|
@ -3332,6 +3401,7 @@ static void P_LoadTextmap(void)
|
|||
TextmapFixFlatOffsets(sc);
|
||||
}
|
||||
|
||||
if (!patch)
|
||||
for (i = 0, ld = lines; i < numlines; i++, ld++)
|
||||
{
|
||||
// Defaults.
|
||||
|
|
@ -3362,6 +3432,7 @@ static void P_LoadTextmap(void)
|
|||
P_InitializeLinedef(ld);
|
||||
}
|
||||
|
||||
if (!patch)
|
||||
for (i = 0, sd = sides; i < numsides; i++, sd++)
|
||||
{
|
||||
// Defaults.
|
||||
|
|
@ -3576,7 +3647,7 @@ static boolean P_LoadMapData(const virtres_t *virt)
|
|||
{
|
||||
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
|
||||
M_TokenizerOpen((char *)textmap->data, textmap->size);
|
||||
if (!TextmapCount(textmap->size))
|
||||
if (!TextmapCount(textmap->size, false))
|
||||
{
|
||||
M_TokenizerClose();
|
||||
TracyCZoneEnd(__zone);
|
||||
|
|
@ -3640,7 +3711,7 @@ static boolean P_LoadMapData(const virtres_t *virt)
|
|||
// Load map data.
|
||||
if (udmf)
|
||||
{
|
||||
P_LoadTextmap();
|
||||
P_LoadTextmap(false);
|
||||
M_TokenizerClose();
|
||||
}
|
||||
else
|
||||
|
|
@ -3670,6 +3741,44 @@ static boolean P_LoadMapData(const virtres_t *virt)
|
|||
return true;
|
||||
}
|
||||
|
||||
static boolean P_LoadMapPatchData(const lumpnum_t lumpnum)
|
||||
{
|
||||
TracyCZone(__zone, true);
|
||||
|
||||
size_t realnummapthings = nummapthings;
|
||||
|
||||
// Count map data.
|
||||
size_t patchlen = W_LumpLength(lumpnum);
|
||||
char *patchdata = malloc(patchlen);
|
||||
W_ReadLump(lumpnum, patchdata);
|
||||
M_TokenizerOpen(patchdata, patchlen);
|
||||
if (!TextmapCount(patchlen, true))
|
||||
{
|
||||
M_TokenizerClose();
|
||||
free(patchdata);
|
||||
TracyCZoneEnd(__zone);
|
||||
return false;
|
||||
}
|
||||
|
||||
mapthing_t *realmapthings = mapthings;
|
||||
mapthings = Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL);
|
||||
|
||||
// Load map data.
|
||||
P_LoadTextmap(true);
|
||||
M_TokenizerClose();
|
||||
free(patchdata);
|
||||
|
||||
// concatenate the two mapthing arrays
|
||||
realmapthings = Z_Realloc(realmapthings, (nummapthings + realnummapthings) * sizeof (*mapthings), PU_LEVEL, NULL);
|
||||
memcpy(realmapthings + realnummapthings, mapthings, nummapthings * sizeof (*mapthings));
|
||||
Z_Free(mapthings);
|
||||
mapthings = realmapthings;
|
||||
nummapthings += realnummapthings;
|
||||
|
||||
TracyCZoneEnd(__zone);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void P_InitializeSubsector(subsector_t *ss)
|
||||
{
|
||||
ss->sector = NULL;
|
||||
|
|
@ -7728,7 +7837,7 @@ static boolean P_LoadMapFromFile(void)
|
|||
virtlump_t *textmap = vres_Find(curmapvirt, "TEXTMAP");
|
||||
size_t i;
|
||||
udmf = textmap != NULL;
|
||||
udmf_version = 0;
|
||||
udmf_version = patch_version = 0;
|
||||
|
||||
if (!P_LoadMapData(curmapvirt))
|
||||
{
|
||||
|
|
@ -7748,6 +7857,14 @@ static boolean P_LoadMapFromFile(void)
|
|||
if (!udmf)
|
||||
P_ConvertBinaryMap();
|
||||
|
||||
P_MakeMapHash(curmapvirt, &maphash);
|
||||
|
||||
// load map patch?
|
||||
lumpnum_t patchlump = W_CheckNumForNameInFolder(G_BuildMapName(gamemap), "MapPatch/");
|
||||
if (patchlump != LUMPERROR)
|
||||
if (!P_LoadMapPatchData(patchlump))
|
||||
CONS_Alert(CONS_ERROR, "Failed to load map patch for %s\n", G_BuildMapName(gamemap));
|
||||
|
||||
// Copy relevant map data for NetArchive purposes.
|
||||
spawnsectors = Z_Calloc(numsectors * sizeof(*sectors), PU_LEVEL, NULL);
|
||||
spawnlines = Z_Calloc(numlines * sizeof(*lines), PU_LEVEL, NULL);
|
||||
|
|
@ -7761,7 +7878,6 @@ static boolean P_LoadMapFromFile(void)
|
|||
if (sectors[i].tags.count)
|
||||
spawnsectors[i].tags.tags = memcpy(Z_Malloc(sectors[i].tags.count*sizeof(mtag_t), PU_LEVEL, NULL), sectors[i].tags.tags, sectors[i].tags.count*sizeof(mtag_t));
|
||||
|
||||
P_MakeMapHash(curmapvirt, &maphash);
|
||||
TracyCZoneEnd(__zone);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
84
src/p_spec.c
84
src/p_spec.c
|
|
@ -1988,7 +1988,7 @@ static void K_HandleLapIncrement(player_t *player)
|
|||
{
|
||||
if (K_IgnoreFinishLine(player))
|
||||
return;
|
||||
if (((K_UsingLegacyCheckpoints()) ? (player->starpostnum >= (numstarposts - (numstarposts/2))) : (player->starpostnum == numstarposts)) || (player->laps == 0))
|
||||
if ((player->starpostnum >= K_CheckpointThreshold(true)) || (player->laps == 0))
|
||||
{
|
||||
size_t i = 0;
|
||||
UINT8 nump = 0;
|
||||
|
|
@ -2051,7 +2051,7 @@ static void K_HandleLapIncrement(player_t *player)
|
|||
player->karthud[khud_lapanimation] = 80;
|
||||
}
|
||||
|
||||
if (netgame && player->laps >= numlaps)
|
||||
if (netgame && player->laps > numlaps)
|
||||
CON_LogMessage(va(M_GetText("%s has finished the race.\n"), player_names[player-players]));
|
||||
|
||||
if (P_IsDisplayPlayer(player))
|
||||
|
|
@ -2135,7 +2135,9 @@ static void K_HandleLapDecrement(player_t *player)
|
|||
{
|
||||
if (player)
|
||||
{
|
||||
if ((player->starpostnum == 0) && (player->laps > 0))
|
||||
if (K_IgnoreFinishLine(player))
|
||||
return;
|
||||
if (player->laps > 0)
|
||||
{
|
||||
player->starpostnum = numstarposts;
|
||||
player->laps--;
|
||||
|
|
@ -4449,6 +4451,36 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha
|
|||
|
||||
if ((gametyperules & GTR_CIRCUIT) && (mo->player->exiting == 0) && !(mo->player->pflags & PF_HITFINISHLINE))
|
||||
{
|
||||
// megablock cope 1: single-use finish lines
|
||||
if (args[0] & TMCFF_SINGLEUSE && mo->player->laps > 0)
|
||||
return false;
|
||||
|
||||
// megablock cope 2: require a circuit finish line special to be hit at the same time
|
||||
if (args[0] & TMCFF_NEEDSECTOR)
|
||||
{
|
||||
boolean touching = false;
|
||||
if (P_MobjTouchingSectorSpecialFlag(mo, SSF_FINISHLINE))
|
||||
touching = true;
|
||||
|
||||
// we have to check if we WERE touching a finish line sector last tic too!
|
||||
// otherwise lap decrementing wouldn't work!
|
||||
// YAAAAAAAAAAAAAAY
|
||||
fixed_t realx = mo->x, realy = mo->y;
|
||||
P_UnsetThingPosition(mo);
|
||||
mo->x = mo->old_x, mo->y = mo->old_y;
|
||||
P_SetThingPosition(mo);
|
||||
|
||||
if (P_MobjTouchingSectorSpecialFlag(mo, SSF_FINISHLINE))
|
||||
touching = true;
|
||||
|
||||
P_UnsetThingPosition(mo);
|
||||
mo->x = realx, mo->y = realy;
|
||||
P_SetThingPosition(mo);
|
||||
|
||||
if (!touching)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (((args[0] & TMCFF_FLIP) && (side == 0))
|
||||
|| (!(args[0] & TMCFF_FLIP) && (side == 1))) // crossed from behind to infront
|
||||
{
|
||||
|
|
@ -5356,7 +5388,7 @@ static void P_EvaluateSpecialFlags(player_t *player, sector_t *sector, sector_t
|
|||
P_ProcessZoomTube(player, sectag, true);
|
||||
if (sector->specialflags & SSF_FINISHLINE)
|
||||
{
|
||||
if ((gametyperules & GTR_CIRCUIT) && (player->exiting == 0) && !(player->pflags & PF_HITFINISHLINE))
|
||||
if (K_UsingLegacyCheckpoints() && (gametyperules & GTR_CIRCUIT) && (player->exiting == 0) && !(player->pflags & PF_HITFINISHLINE))
|
||||
{
|
||||
K_HandleLapIncrement(player);
|
||||
player->pflags |= PF_HITFINISHLINE;
|
||||
|
|
@ -5761,7 +5793,7 @@ static boolean P_AllowSpecialCeiling(sector_t *sec, mobj_t *thing)
|
|||
return false;
|
||||
}
|
||||
|
||||
static void P_CheckMobj3DFloorAction(mobj_t *mo, sector_t *sec, boolean continuous)
|
||||
static void P_CheckMobj3DFloorAction(mobj_t *mo, sector_t *sec, boolean continuous, boolean sectorchanged)
|
||||
{
|
||||
sector_t *originalsector = mo->subsector->sector;
|
||||
ffloor_t *rover;
|
||||
|
|
@ -5820,6 +5852,10 @@ static void P_CheckMobj3DFloorAction(mobj_t *mo, sector_t *sec, boolean continuo
|
|||
continue;
|
||||
}
|
||||
}
|
||||
else if (sectorchanged == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
activator = Z_Calloc(sizeof(activator_t), PU_LEVEL, NULL);
|
||||
I_Assert(activator != NULL);
|
||||
|
|
@ -5839,7 +5875,7 @@ static void P_CheckMobj3DFloorAction(mobj_t *mo, sector_t *sec, boolean continuo
|
|||
}
|
||||
}
|
||||
|
||||
static void P_CheckMobjPolyobjAction(mobj_t *mo, boolean continuous)
|
||||
static void P_CheckMobjPolyobjAction(mobj_t *mo, boolean continuous, boolean sectorchanged)
|
||||
{
|
||||
sector_t *originalsector = mo->subsector->sector;
|
||||
polyobj_t *po;
|
||||
|
|
@ -5894,6 +5930,10 @@ static void P_CheckMobjPolyobjAction(mobj_t *mo, boolean continuous)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
else if (sectorchanged == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
activator = Z_Calloc(sizeof(activator_t), PU_LEVEL, NULL);
|
||||
I_Assert(activator != NULL);
|
||||
|
|
@ -5913,7 +5953,7 @@ static void P_CheckMobjPolyobjAction(mobj_t *mo, boolean continuous)
|
|||
}
|
||||
}
|
||||
|
||||
static void P_CheckMobjSectorAction(mobj_t *mo, sector_t *sec, boolean continuous)
|
||||
static void P_CheckMobjSectorAction(mobj_t *mo, sector_t *sec, boolean continuous, boolean sectorchanged)
|
||||
{
|
||||
activator_t *activator = NULL;
|
||||
boolean result = false;
|
||||
|
|
@ -5950,6 +5990,10 @@ static void P_CheckMobjSectorAction(mobj_t *mo, sector_t *sec, boolean continuou
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (sectorchanged == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
activator = Z_Calloc(sizeof(activator_t), PU_LEVEL, NULL);
|
||||
I_Assert(activator != NULL);
|
||||
|
|
@ -5966,7 +6010,7 @@ static void P_CheckMobjSectorAction(mobj_t *mo, sector_t *sec, boolean continuou
|
|||
}
|
||||
}
|
||||
|
||||
void P_CheckMobjTouchingSectorActions(mobj_t *mobj, boolean continuous)
|
||||
void P_CheckMobjTouchingSectorActions(mobj_t *mobj, boolean continuous, boolean sectorchanged)
|
||||
{
|
||||
sector_t *originalsector;
|
||||
|
||||
|
|
@ -5992,13 +6036,13 @@ void P_CheckMobjTouchingSectorActions(mobj_t *mobj, boolean continuous)
|
|||
}
|
||||
}
|
||||
|
||||
P_CheckMobj3DFloorAction(mobj, originalsector, continuous);
|
||||
P_CheckMobj3DFloorAction(mobj, originalsector, continuous, sectorchanged);
|
||||
if TELEPORTED(mobj) return;
|
||||
|
||||
P_CheckMobjPolyobjAction(mobj, continuous);
|
||||
P_CheckMobjPolyobjAction(mobj, continuous, sectorchanged);
|
||||
if TELEPORTED(mobj) return;
|
||||
|
||||
P_CheckMobjSectorAction(mobj, originalsector, continuous);
|
||||
P_CheckMobjSectorAction(mobj, originalsector, continuous, sectorchanged);
|
||||
}
|
||||
|
||||
#undef TELEPORTED
|
||||
|
|
@ -9491,3 +9535,21 @@ void P_StartQuake(fixed_t intensity, tic_t time)
|
|||
quake.intensity = FixedMul(intensity, mapobjectscale);
|
||||
quake.time = time;
|
||||
}
|
||||
|
||||
void P_CheckSectorTransitionalEffects(mobj_t *thing, sector_t *prevsec, boolean wasgrounded)
|
||||
{
|
||||
if (!udmf)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
boolean sectorchanged = (prevsec != thing->subsector->sector);
|
||||
|
||||
if (!sectorchanged && wasgrounded == P_IsObjectOnGround(thing))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for each time / once sector special actions
|
||||
P_CheckMobjTouchingSectorActions(thing, false, sectorchanged);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -488,6 +488,8 @@ typedef enum
|
|||
typedef enum
|
||||
{
|
||||
TMCFF_FLIP = 1,
|
||||
TMCFF_SINGLEUSE = 1<<1,
|
||||
TMCFF_NEEDSECTOR = 1<<2,
|
||||
} textmapcrossfinishflags_t;
|
||||
|
||||
typedef enum
|
||||
|
|
@ -542,12 +544,13 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n
|
|||
sector_t *P_PlayerTouchingSectorSpecialFlag(player_t *player, sectorspecialflags_t flag);
|
||||
void P_PlayerInSpecialSector(player_t *player);
|
||||
void P_CheckMobjTrigger(mobj_t *mobj, boolean pushable);
|
||||
void P_CheckMobjTouchingSectorActions(mobj_t *mobj, boolean continuous);
|
||||
void P_CheckMobjTouchingSectorActions(mobj_t *mobj, boolean continuous, boolean sectorchanged);
|
||||
sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline);
|
||||
boolean P_IsPlayerValid(size_t playernum);
|
||||
boolean P_CanPlayerTrigger(size_t playernum);
|
||||
void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector);
|
||||
sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo);
|
||||
void P_CheckSectorTransitionalEffects(mobj_t *thing, sector_t *prevsec, boolean wasgrounded);
|
||||
|
||||
fixed_t P_FindLowestFloorSurrounding(sector_t *sec);
|
||||
fixed_t P_FindHighestFloorSurrounding(sector_t *sec);
|
||||
|
|
|
|||
|
|
@ -64,8 +64,9 @@ extern size_t numspritelumps, max_spritelumps;
|
|||
// Lookup tables for map data.
|
||||
//
|
||||
#define UDMF_CURRENT_VERSION (3)
|
||||
#define PATCH_CURRENT_VERSION (1)
|
||||
extern boolean udmf;
|
||||
extern INT32 udmf_version;
|
||||
extern INT32 udmf_version, patch_version;
|
||||
|
||||
extern size_t numsprites;
|
||||
extern spritedef_t *sprites;
|
||||
|
|
|
|||
Loading…
Reference in a new issue