From 145fcc23449ce9d3c121b58af7507e06f73574a2 Mon Sep 17 00:00:00 2001 From: Craftyawesome Date: Thu, 29 Aug 2024 01:19:02 -0400 Subject: [PATCH 01/12] Workaround for Egg TV replay deletion bugs --- src/menus/class-egg-tv/EggTV.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/menus/class-egg-tv/EggTV.cpp b/src/menus/class-egg-tv/EggTV.cpp index 79ba9bbd8..243c95643 100644 --- a/src/menus/class-egg-tv/EggTV.cpp +++ b/src/menus/class-egg-tv/EggTV.cpp @@ -461,6 +461,8 @@ void EggTV::erase() } } + cache_ = cache_->folder().load(); + if (cache_->folder().empty()) { // Remove empty folder from list From 6125572b635cf110c9873422307afd57cb133cd2 Mon Sep 17 00:00:00 2001 From: Jack Date: Sun, 1 Sep 2024 14:50:27 +0100 Subject: [PATCH 02/12] I've spent the last 3 or so hours just trying to get a feel as to how to even begin approaching this task but I think it's just way beyond my understanding, I don't have enough experience with big C / C++ projects to know if its just me or if this project being 2 decades running makes it a freak of nature but I'm just barely holding on here and not seeing any results, so nuts to it for now. --- src/hardware/hw_md2.c | 2 +- src/info.c | 3 ++- src/info.h | 1 + src/objects/destroyed-kart.cpp | 18 ++++++++++++++---- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index c6c25cb10..934e957bb 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1195,7 +1195,7 @@ static void HWR_GetBlendedTexture(patch_t *patch, patch_t *blendpatch, INT32 ski static boolean HWR_AllowModel(mobj_t *mobj) { // Don't allow rendering of model for these. - if (mobj->sprite2 == SPR2_XTRA || mobj->sprite2 == SPR2_SIGN || mobj->sprite2 == SPR2_SIGL || mobj->sprite2 == SPR2_SSIG || mobj->sprite2 == SPR2_TALK) + if (mobj->sprite2 == SPR2_XTRA || mobj->sprite2 == SPR2_SIGN || mobj->sprite2 == SPR2_SIGL || mobj->sprite2 == SPR2_SSIG || mobj->sprite2 == SPR2_TALK || mobj->sprite2 == SPR2_DKRT) // TODO: Remove SPR2_DKRT from this list of clauses once player-specific destroyed karts have an associated model return false; // Otherwise, render the model. diff --git a/src/info.c b/src/info.c index c639c7c35..a09a00dbc 100644 --- a/src/info.c +++ b/src/info.c @@ -839,6 +839,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_SIGN, // SPR2_SSIG 0, // SPR2_XTRA 0, // SPR2_TALK + 0, // SPR2_DKRT }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -902,7 +903,7 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, -1, {NULL}, 0, 0, S_OBJPLACE_DUMMY}, // S_OBJPLACE_DUMMY {SPR_KART, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KART_LEFTOVER - {SPR_DIEF, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KART_LEFTOVER_NOTIRES + {SPR_DIEF, SPR2_DKRT, -1, {NULL}, 0, 0, S_NULL}, // S_KART_LEFTOVER_NOTIRES {SPR_TIRE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KART_TIRE1 {SPR_TIRE, 1, -1, {NULL}, 0, 0, S_NULL}, // S_KART_TIRE2 diff --git a/src/info.h b/src/info.h index dc9006856..3246580ff 100644 --- a/src/info.h +++ b/src/info.h @@ -1329,6 +1329,7 @@ typedef enum playersprite SPR2_SIGN, SPR2_SIGL, SPR2_SSIG, SPR2_XTRA, SPR2_TALK, + SPR2_DKRT, SPR2_FIRSTFREESLOT, SPR2_LASTFREESLOT = 0x7f, diff --git a/src/objects/destroyed-kart.cpp b/src/objects/destroyed-kart.cpp index b029d8304..3da915467 100644 --- a/src/objects/destroyed-kart.cpp +++ b/src/objects/destroyed-kart.cpp @@ -328,11 +328,21 @@ struct Kart : Mobj if (Mobj* p = player(); Mobj::valid(p)) { - if (p->player && skins[p->player->skin].flags & SF_BADNIK) + if (p->player) { - P_SpawnBadnikExplosion(p); - p->spritescale({2*FRACUNIT, 2*FRACUNIT}); - p->flags |= MF_NOSQUISH; + skin = (&skins[p->player->skin]); + color = (p->player->skincolor); + + // it's necessary to refresh SPR2 on skin changes. + state(S_KART_LEFTOVER_NOTIRES); + sprite2 = (P_GetSkinSprite2(static_cast(skin), SPR2_DKRT, NULL));; + + if(skins[p->player->skin].flags & SF_BADNIK){ + P_SpawnBadnikExplosion(p); + p->spritescale({2*FRACUNIT, 2*FRACUNIT}); + p->flags |= MF_NOSQUISH; + } + } p->state(S_KART_DEAD); From 51112a07f7ed53b68434758082cc7661db6b88b2 Mon Sep 17 00:00:00 2001 From: Jack Date: Fri, 6 Sep 2024 01:13:55 +0100 Subject: [PATCH 03/12] Revert "I've spent the last 3 or so hours just trying to get a feel as to how to even begin approaching this task but I think it's just way beyond my understanding, I don't have enough experience with big C / C++ projects to know if its just me or if this project being 2 decades running makes it a freak of nature but I'm just barely holding on here and not seeing any results, so nuts to it for now." This reverts commit 6125572b635cf110c9873422307afd57cb133cd2. --- src/hardware/hw_md2.c | 2 +- src/info.c | 3 +-- src/info.h | 1 - src/objects/destroyed-kart.cpp | 18 ++++-------------- 4 files changed, 6 insertions(+), 18 deletions(-) diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 934e957bb..c6c25cb10 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1195,7 +1195,7 @@ static void HWR_GetBlendedTexture(patch_t *patch, patch_t *blendpatch, INT32 ski static boolean HWR_AllowModel(mobj_t *mobj) { // Don't allow rendering of model for these. - if (mobj->sprite2 == SPR2_XTRA || mobj->sprite2 == SPR2_SIGN || mobj->sprite2 == SPR2_SIGL || mobj->sprite2 == SPR2_SSIG || mobj->sprite2 == SPR2_TALK || mobj->sprite2 == SPR2_DKRT) // TODO: Remove SPR2_DKRT from this list of clauses once player-specific destroyed karts have an associated model + if (mobj->sprite2 == SPR2_XTRA || mobj->sprite2 == SPR2_SIGN || mobj->sprite2 == SPR2_SIGL || mobj->sprite2 == SPR2_SSIG || mobj->sprite2 == SPR2_TALK) return false; // Otherwise, render the model. diff --git a/src/info.c b/src/info.c index a09a00dbc..c639c7c35 100644 --- a/src/info.c +++ b/src/info.c @@ -839,7 +839,6 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_SIGN, // SPR2_SSIG 0, // SPR2_XTRA 0, // SPR2_TALK - 0, // SPR2_DKRT }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -903,7 +902,7 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, -1, {NULL}, 0, 0, S_OBJPLACE_DUMMY}, // S_OBJPLACE_DUMMY {SPR_KART, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KART_LEFTOVER - {SPR_DIEF, SPR2_DKRT, -1, {NULL}, 0, 0, S_NULL}, // S_KART_LEFTOVER_NOTIRES + {SPR_DIEF, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KART_LEFTOVER_NOTIRES {SPR_TIRE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KART_TIRE1 {SPR_TIRE, 1, -1, {NULL}, 0, 0, S_NULL}, // S_KART_TIRE2 diff --git a/src/info.h b/src/info.h index 3246580ff..dc9006856 100644 --- a/src/info.h +++ b/src/info.h @@ -1329,7 +1329,6 @@ typedef enum playersprite SPR2_SIGN, SPR2_SIGL, SPR2_SSIG, SPR2_XTRA, SPR2_TALK, - SPR2_DKRT, SPR2_FIRSTFREESLOT, SPR2_LASTFREESLOT = 0x7f, diff --git a/src/objects/destroyed-kart.cpp b/src/objects/destroyed-kart.cpp index 3da915467..b029d8304 100644 --- a/src/objects/destroyed-kart.cpp +++ b/src/objects/destroyed-kart.cpp @@ -328,21 +328,11 @@ struct Kart : Mobj if (Mobj* p = player(); Mobj::valid(p)) { - if (p->player) + if (p->player && skins[p->player->skin].flags & SF_BADNIK) { - skin = (&skins[p->player->skin]); - color = (p->player->skincolor); - - // it's necessary to refresh SPR2 on skin changes. - state(S_KART_LEFTOVER_NOTIRES); - sprite2 = (P_GetSkinSprite2(static_cast(skin), SPR2_DKRT, NULL));; - - if(skins[p->player->skin].flags & SF_BADNIK){ - P_SpawnBadnikExplosion(p); - p->spritescale({2*FRACUNIT, 2*FRACUNIT}); - p->flags |= MF_NOSQUISH; - } - + P_SpawnBadnikExplosion(p); + p->spritescale({2*FRACUNIT, 2*FRACUNIT}); + p->flags |= MF_NOSQUISH; } p->state(S_KART_DEAD); From af16e3f993d50ab1f055ce364c098c091ec3cc83 Mon Sep 17 00:00:00 2001 From: Jack Date: Fri, 6 Sep 2024 14:23:18 +0100 Subject: [PATCH 04/12] Implemented SPR2_DKRT and integrated it into the state system --- src/deh_tables.c | 1 + src/info.c | 5 ++++- src/info.h | 2 ++ src/objects/destroyed-kart.cpp | 32 +++++++++++++++++++++++++++----- src/p_mobj.c | 2 ++ 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index c8da6cabd..1474296f9 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -369,6 +369,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_KART_LEFTOVER", "S_KART_LEFTOVER_NOTIRES", + "S_KART_LEFTOVER_CUSTOM", "S_KART_TIRE1", "S_KART_TIRE2", diff --git a/src/info.c b/src/info.c index c639c7c35..ffdf5daf8 100644 --- a/src/info.c +++ b/src/info.c @@ -795,6 +795,7 @@ char spr2names[NUMPLAYERSPRITES][5] = "SIGN", "SIGL", "SSIG", // Finish signpost "XTRA", // Three Faces of Darkness "TALK", // Dialogue + "DKRT", // Kart husk }; playersprite_t free_spr2 = SPR2_FIRSTFREESLOT; @@ -839,13 +840,14 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_SIGN, // SPR2_SSIG 0, // SPR2_XTRA 0, // SPR2_TALK + 0, // SPR2_DKRT }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) state_t states[NUMSTATES] = { // frame is masked through FF_FRAMEMASK - // FF_ANIMATE makes simple state animations (var1 #frames, var2 tic delay) + // FF_ANIMATE makes simple state animations (var1 #frames, var2 tic delay) (var1 is ignored in P_SetupStateAnimation() if sprite is SPR_PLAY) // FF_FULLBRIGHT activates the fullbright colormap // use FF_TRANS10 - FF_TRANS90 for easy translucency // (or tr_trans10<player && skins[p->player->skin].sprites[SPR2_DKRT].numframes; + + if(hasCustomHusk) + { + skin = (void*)(&skins[p->player->skin]); + frame = 0; + } + Particle::spew(this); - scale(3 * scale() / 2); + + auto oldScale = scale(); + scale(3*scale()/2); + + if(hasCustomHusk){ + flags |= MF_NOSQUISH; //K_Squish() automates spritexscale/spriteyscale & this flag prevents that at the cost of no squish visual when the kart husk hits the ground + float div = ((float)1/(float)oldScale)*(float)scale(); + auto formula = [&](fixed_t subject){return (fixed_t)((float)subject/div);}; + spritexscale(formula(spritexscale())); + spriteyscale(formula(spriteyscale())); + } + health = 1; - state(S_KART_LEFTOVER_NOTIRES); + state(!hasCustomHusk ? S_KART_LEFTOVER_NOTIRES : S_KART_LEFTOVER_CUSTOM); cooldown(20); burning(burn_duration()); @@ -326,9 +348,9 @@ struct Kart : Mobj voice(sfx_die00); } - if (Mobj* p = player(); Mobj::valid(p)) + if(pValid) { - if (p->player && skins[p->player->skin].flags & SF_BADNIK) + if((skins[p->player->skin].flags & SF_BADNIK)) { P_SpawnBadnikExplosion(p); p->spritescale({2*FRACUNIT, 2*FRACUNIT}); @@ -446,7 +468,7 @@ private: P_PlayDeathSound(p); } - // First tick after hitlag: destroyed kart appears! + // First tick after hitlag: destroyed kart appears! State will change away from S_INVISIBLE inside destroy() where S_INVISIBLE was set in static spawn() if (state()->num() == S_INVISIBLE) { destroy(); diff --git a/src/p_mobj.c b/src/p_mobj.c index 8b1862fab..7f66444bc 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9886,10 +9886,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj) case MT_KART_LEFTOVER: { Obj_DestroyedKartThink(mobj); + if (P_MobjWasRemoved(mobj)) { return false; } + break; } From 40b231ff6214948983138732670569718f99a32e Mon Sep 17 00:00:00 2001 From: Jack Date: Sat, 7 Sep 2024 17:55:30 +0100 Subject: [PATCH 05/12] Changed float percentage mathematics in destroyed-kart.cpp into approximated fixed mathematics that will not risk a desync across platforms with different float standards --- src/objects/destroyed-kart.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/objects/destroyed-kart.cpp b/src/objects/destroyed-kart.cpp index d5eaa9fec..c8325db84 100644 --- a/src/objects/destroyed-kart.cpp +++ b/src/objects/destroyed-kart.cpp @@ -332,8 +332,12 @@ struct Kart : Mobj if(hasCustomHusk){ flags |= MF_NOSQUISH; //K_Squish() automates spritexscale/spriteyscale & this flag prevents that at the cost of no squish visual when the kart husk hits the ground - float div = ((float)1/(float)oldScale)*(float)scale(); - auto formula = [&](fixed_t subject){return (fixed_t)((float)subject/div);}; + + //approximate inverse spritescale() by exaggerating fixed_t values by 100 and then dividing back down instead of doing float maths + //this way there's no decimal points and no potential for desyncs across builds/platforms + //there is potential this could overflow at exceptionally high scale() values + fixed_t z = FixedDiv(FixedMul(scale(),100),oldScale); + auto formula = [&](fixed_t subject){return FixedDiv(FixedMul(subject,100),z);}; spritexscale(formula(spritexscale())); spriteyscale(formula(spriteyscale())); } From 2bdc0140069d9ceb1870e8f01eab1b3c132fafa0 Mon Sep 17 00:00:00 2001 From: Jack Date: Mon, 9 Sep 2024 15:41:26 +0100 Subject: [PATCH 06/12] With the help of GitLab user Lach, I turned my approximated sprite scaling in destroyed-kart.cpp into 100% accurate sprite scaling --- src/objects/destroyed-kart.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/objects/destroyed-kart.cpp b/src/objects/destroyed-kart.cpp index c8325db84..c5043534c 100644 --- a/src/objects/destroyed-kart.cpp +++ b/src/objects/destroyed-kart.cpp @@ -326,20 +326,13 @@ struct Kart : Mobj } Particle::spew(this); - - auto oldScale = scale(); scale(3*scale()/2); if(hasCustomHusk){ flags |= MF_NOSQUISH; //K_Squish() automates spritexscale/spriteyscale & this flag prevents that at the cost of no squish visual when the kart husk hits the ground - - //approximate inverse spritescale() by exaggerating fixed_t values by 100 and then dividing back down instead of doing float maths - //this way there's no decimal points and no potential for desyncs across builds/platforms - //there is potential this could overflow at exceptionally high scale() values - fixed_t z = FixedDiv(FixedMul(scale(),100),oldScale); - auto formula = [&](fixed_t subject){return FixedDiv(FixedMul(subject,100),z);}; - spritexscale(formula(spritexscale())); - spriteyscale(formula(spriteyscale())); + fixed_t huskScale = FixedDiv(mapobjectscale, scale()); + spritexscale(FixedMul(spritexscale(), huskScale)); + spriteyscale(FixedMul(spriteyscale(), huskScale)); } health = 1; From f3ed9f580e33fad1f332f6e4e4f284e3660505f2 Mon Sep 17 00:00:00 2001 From: Jack Date: Mon, 9 Sep 2024 16:19:17 +0100 Subject: [PATCH 07/12] Fixed the p->player null check in destroyed-kart.cpp being a part of hasCustomHusk rather than being a part of pValid as it's supposed to be --- src/objects/destroyed-kart.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objects/destroyed-kart.cpp b/src/objects/destroyed-kart.cpp index c5043534c..95782cf74 100644 --- a/src/objects/destroyed-kart.cpp +++ b/src/objects/destroyed-kart.cpp @@ -316,8 +316,8 @@ struct Kart : Mobj } Mobj* p = player(); - bool pValid = Mobj::valid(p); - bool hasCustomHusk = pValid && p->player && skins[p->player->skin].sprites[SPR2_DKRT].numframes; + bool pValid = Mobj::valid(p) && p->player; + bool hasCustomHusk = pValid && skins[p->player->skin].sprites[SPR2_DKRT].numframes; if(hasCustomHusk) { From 3ca282c3b46db64d78755e9e8384243068f71d17 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 15 Sep 2024 17:09:28 +0100 Subject: [PATCH 08/12] COM_Exec_f: By default, insert into command buffer - Resolves KartKrew/RingRacers#281 under standard operation - Add `-immediate` parameter for previous, `wait`-ignoring behaviour - Used by configfile, EXECCFG --- src/command.c | 15 +++++++++++++-- src/deh_soc.c | 2 +- src/m_misc.cpp | 4 ++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/command.c b/src/command.c index b42b73a5c..2808e1f8c 100644 --- a/src/command.c +++ b/src/command.c @@ -855,8 +855,19 @@ static void COM_Exec_f(void) if (!COM_CheckParm("-silent")) CONS_Printf(M_GetText("executing %s\n"), COM_Argv(1)); - // insert text file into the command buffer - COM_ImmedExecute((char *)buf); + if (COM_CheckParm("-immediate")) + { + // immediately parses and executes all lines + // sidesteps wait from all sources, even self + COM_ImmedExecute((char *)buf); + } + else + { + // insert text file into the command buffer + // delays execution if interpreting wait cmd + COM_BufAddTextEx((char *)buf, com_flags); + COM_BufAddTextEx("\n", com_flags); + } // free buffer Z_Free(buf); diff --git a/src/deh_soc.c b/src/deh_soc.c index 32475d0a6..800e5b201 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -3533,7 +3533,7 @@ void readmaincfg(MYFILE *f, boolean mainfile) else if (fastcmp(word, "EXECCFG")) { if (strchr(word2, '.')) - COM_BufAddText(va("exec %s\n", word2)); + COM_BufAddText(va("exec \"%s\" -immediate\n", word2)); else { lumpnum_t lumpnum; diff --git a/src/m_misc.cpp b/src/m_misc.cpp index d6788a729..6f5b3474a 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -587,7 +587,7 @@ void Command_LoadConfig_f(void) CV_InitFilterVar(); // exec the config - COM_BufInsertText(va("exec \"%s\"\n", configfile)); + COM_BufInsertText(va("exec \"%s\" -immediate\n", configfile)); // don't filter anymore vars and don't let this convsvar be changed COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, EXECVERSION)); @@ -648,7 +648,7 @@ void M_FirstLoadConfig(void) CV_InitFilterVar(); // load config, make sure those commands doesnt require the screen... - COM_BufInsertText(va("exec \"%s\"\n", configfile)); + COM_BufInsertText(va("exec \"%s\" -immediate\n", configfile)); // no COM_BufExecute() needed; that does it right away // don't filter anymore vars and don't let this convsvar be changed From 5eb3ab91957908f87b6a890e92ebf0358d2eaa93 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 20 Sep 2024 17:08:57 -0400 Subject: [PATCH 09/12] Add UDMF extension documentation --- docs/udmf.txt | 273 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 docs/udmf.txt diff --git a/docs/udmf.txt b/docs/udmf.txt new file mode 100644 index 000000000..ea6cfb146 --- /dev/null +++ b/docs/udmf.txt @@ -0,0 +1,273 @@ +=============================================================================== +Universal Doom Map Format - Ring Racers extensions v1.0 - 20.09.2024 + + Copyright (c) 2024 Sally Cochenour. + Copyright (c) 2024 Kart Krew Dev. + + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.2 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + +=============================================================================== + +This document serves to only specify changes that "Dr. Robotnik's Ring Racers" +makes to the base UDMF specification. + +======================================= +I. Grammar / Syntax +======================================= + +No changes were made. + +======================================= +II. Implementation Semantics +======================================= + +------------------------------------ +II.A : Storage and Retrieval of Data +------------------------------------ + +No changes were made. + +----------------------------------- +II.B : Storage Within Archive Files +----------------------------------- + +Between the TEXTMAP and ENDMAP lumps, Ring Racers supports the following +additional lumps: + + BEHAVIOR = Compiled ACS code. + ZNODES = Compiled extended / GL friendly nodes. These are required. + PICTURE = A Doom graphic lump, expected to be 320x200. Intended to be a + screenshot of the map itself. This is used by the game for level + select menus. + MINIMAP = A Doom graphic lump, expected to be 100x100. Intended to be a + an overview of the map. This is used by the game for the minimap + on-screen HUD. + ENCORE = A Doom flat lump, expected to be 16x16. Describes a color remap + palette to use in Encore Mode. + TWEAKMAP = A Doom flat lump, expected to be 16x16. Describes a color remap + palette to use outside of Encore Mode. + +Any lumps not listed or specified in the original document will be ignored by +the game. In particular, the "SCRIPTS" lump is considered to be ACS source +code, and is garantueed to be ignored by the engine. + +-------------------------------- +II.C : Implementation Dependence +-------------------------------- + +Ring Racers does not aspire for Doom backwards compatibility, thus it does not +support any of the namespaces in the original document, and only implements +its own: "ringracers". Any maps not using the "ringracers" namespace is +considered unsupported. + +======================================= +III. Standardized Fields +======================================= + +Ring Racers' namespace implements the following additional fields: + + version = ; // Specifies the map format version. + // This is used for resolving backwards compatibility issues. + + // Note that this doesn't map directly to specification version; + // it means behavior of an already existing field or action special + // was changed. + + // 0 / default - RR indev + // 1 - RR v2.0, spec v1.0 + // 2 - RR v2.4, spec v1.0 + + linedef + { + moreids = ; // Additional IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505") + + arg5 = ; // Argument 5. Default = 0. + arg6 = ; // Argument 6. Default = 0. + arg7 = ; // Argument 7. Default = 0. + arg8 = ; // Argument 8. Default = 0. + arg9 = ; // Argument 9. Default = 0. + + stringarg0 = ; // String argument 0. This replaces usage of 'arg0' when specified. + stringarg1 = ; // String argument 1. This replaces usage of 'arg1' when specified. + + alpha = ; // Transparency value of the mid-textures. Default = 1.0. + renderstyle = ; // The rendering mode to use for the mid-textures. + // Can be "translucent", "add", "subtract", "reversesubtract", "modulate", or "fog". + // Default = "translucent". + + // The following flags default to false. + blockplayers = ; // true = line blocks players. + skewtd = ; // true = upper and lower textures are skewed to match slopes. + noskew = ; // true = mid-textures are not skewed to match slopes. + midpeg = ; // true = invert mid-texture unpegged behavior. + midsolid = ; // true = mid-texture has collision. + wrapmidtex = ; // true = mid-textures are wrapped. + nonet = ; // true = special is disabled in networked multiplayer games. + netonly = ; // true = special is only enabled in networked multiplayer games. + notbouncy = ; // true = disable bouncing collision. + transfer = ; // true = use FOF transfer properties effect. + } + + sidedef + { + repeatcnt = ; // Number of times to mid-texture wrap. Default = 0. + } + + vertex + { + zfloor = ; // The floor height at this vertex, for vertex slopes. + zceiling = ; // The ceiling height at this vertex, for vertex slopes + } + + sector + { + lightfloor = ; // The floor's light level. Default is 0. + lightceiling = ; // The ceiling's light level. Default is 0. + + lightfloorabsolute = ; // true = 'lightfloor' is an absolute value. Default is + // relative to the owning sector's light level. + lightceilingabsolute = ; // true = 'lightceiling' is an absolute value. Default is + // relative to the owning sector's light level. + + moreids = ; // Additional IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505") + + xpanningfloor = ; // X texture offset of floor texture, Default = 0.0. + ypanningfloor = ; // Y texture offset of floor texture, Default = 0.0. + + xpanningceiling = ; // X texture offset of ceiling texture, Default = 0.0. + ypanningceiling = ; // Y texture offset of ceiling texture, Default = 0.0. + + rotationfloor = ; // Rotation of floor texture in degrees, Default = 0.0. + rotationceiling = ; // Rotation of ceiling texture in degrees, Default = 0.0. + + floorplane_a = ; // Define the plane equation for the sector's floor. Default is a horizontal plane at 'heightfloor'. + floorplane_b = ; // 'heightfloor' will still be used to calculate texture alignment. + floorplane_c = ; // The plane equation will only be used if all 4 values are given. + floorplane_d = ; + + ceilingplane_a = ; // Define the plane equation for the sector's ceiling. Default is a horizontal plane at 'heightceiling'. + ceilingplane_b = ; // 'heightceiling' will still be used to calculate texture alignment. + ceilingplane_c = ; // The plane equation will only be used if all 4 values are given. + ceilingplane_d = ; + + friction = ; // Sector's friction. Default = 0.90625. + gravity = ; // Sector's gravity multiplier. Default = 1.0. + damagetype = ; // Damage inflicted by the sector. + // Can be "None", "Generic", "Lava", "DeathPit", "Instakill", or "Stumble". + // Default = "None". + + action = ; // Sector action, same as line special. Default = 0. + arg0 = ; // Argument 0. Default = 0. + arg1 = ; // Argument 1. Default = 0. + arg2 = ; // Argument 2. Default = 0. + arg3 = ; // Argument 3. Default = 0. + arg4 = ; // Argument 4. Default = 0. + arg5 = ; // Argument 5. Default = 0. + arg6 = ; // Argument 6. Default = 0. + arg7 = ; // Argument 7. Default = 0. + arg8 = ; // Argument 8. Default = 0. + arg9 = ; // Argument 9. Default = 0. + stringarg0 = ; // String argument 0. This replaces usage of 'arg0' when specified. + stringarg1 = ; // String argument 1. This replaces usage of 'arg1' when specified. + + lightcolor = ; // Sector's light color as RRGGBB value. Default = 0x000000. + lightalpha = ; // Sector's light color alpha value. Default = 25. + fadecolor = ; // Sector's fog color as RRGGBB value. Default = 0x000000. + fadealpha = ; // Sector's fog color alpha value. Default = 25. + fadestart = ; // Sector's fog start distance. Default = 0. + fadeend = ; // Sector's fog end distance. Default = 31. + + // The following flags default to false. + colormapfog = ; // true = render transparent planes at light level instead of fullbright + colormapfadesprites = ; // true = fog color affects fullbright sprites + colormapprotected = ; // true = colormap cannot be changed at run-time + + flipspecial_nofloor = ; // true = plane touch specials aren't ran when on the floor + flipspecial_ceiling = ; // true = plane touch specials are ran when on the ceiling + triggerspecial_touch = ; // true = specials are ran when touching edges of sector + triggerspecial_headbump = ; // true = plane touch specials are ran when touching the opposite plane than gravity + invertprecip = ; // true = precipitation spawning rules are inverted + gravityflip = ; // true = flip gravity of objects in this sector + heatwave = ; // true = add heat wave screen effect + noclipcamera = ; // true = camera is not blocked by this sector + ripple_floor = ; // true = add ripple effect to floor + ripple_ceiling = ; // true = add ripple effect to ceiling + invertencore = ; // true = encore remap rules are inverted + flatlighting = ; // true = directional lighting is forced off + forcedirectionallighting = ; // true = directional lighting is forced on + nostepup = ; // true = objects can't step up + doublestepup = ; // true = objects have increased step up + nostepdown = ; // true = objects can't step down + cheatcheckactivator = ; // true = players activate cheat checks when in this sector + exit = ; // true = players finish match when entering sector + deleteitems = ; // true = items instantly explode when entering sector + fan = ; // true = players are propelled upwards in this sector + zoomtubestart = ; // true = sector is start of a zoom tube + zoomtubeend = ; // true = sector is end of a zoom tube + + repeatspecial = ; // true = repeatable action + continuousspecial = ; // true = action is executed every game tick + playerenter = ; // true = player activates when entering + playerfloor = ; // true = player activates when touching floor + playerceiling = ; // true = player activates when touching ceiling + monsterenter = ; // true = enemy activates when entering + monsterfloor = ; // true = enemy activates when touching floor + monsterceiling = ; // true = enemy activates when touching ceiling + missileenter = ; // true = items / projectiles activate when entering + missilefloor = ; // true = items / projectiles activate when touching floor + missileceiling = ; // true = items / projectiles activate when touching ceiling + } + + thing + { + pitch = ; // Pitch of thing in degrees. Default = 0 (horizontal). + roll = ; // Pitch of thing in degrees. Default = 0 (horizontal). + + scalex = ; // Vertical visual scale on thing. Default = 1.0. + scaley = ; // Horizontal visual scale on thing. Default = 1.0. + scale = ; // Vertical and horizontal visual scale on thing. Default = 1.0. + + mobjscale = ; // Physical scale on thing. Default = 1.0. + + foflayer = ; // Which FOF is treated as the base floor/ceiling. + // This changes what 'height' is relative to. + // Default = 0, for no FOF. + + // Action special arguments + arg5 = ; // Argument 5. Default = 0. + arg6 = ; // Argument 6. Default = 0. + arg7 = ; // Argument 7. Default = 0. + arg8 = ; // Argument 8. Default = 0. + arg9 = ; // Argument 9. Default = 0. + + stringarg0 = ; // String argument 0. This replaces usage of 'arg0' when specified. + stringarg1 = ; // String argument 1. This replaces usage of 'arg1' when specified. + + // These arguments modify object behavior on a per-type basis. + // Not to be confused with action special arguments. + thingarg0 = ; // Argument 0. Default = 0. + thingarg1 = ; // Argument 1. Default = 0. + thingarg2 = ; // Argument 2. Default = 0. + thingarg3 = ; // Argument 3. Default = 0. + thingarg4 = ; // Argument 4. Default = 0. + thingarg5 = ; // Argument 5. Default = 0. + thingarg6 = ; // Argument 6. Default = 0. + thingarg7 = ; // Argument 7. Default = 0. + thingarg8 = ; // Argument 8. Default = 0. + thingarg9 = ; // Argument 9. Default = 0. + thingstringarg0 = ; // String argument 0. This replaces usage of 'thingarg0' when specified. + thingstringarg1 = ; // String argument 1. This replaces usage of 'thingarg1' when specified. + + // Following flags default to false. + flip = ; // true = object has reversed gravity + } + +======================================= +Changelog +======================================= + +1.0: 20.09.2024 +- Initial document created. From a7aaf0eddb68e78b5a0e76fa16bf05a091067499 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 14 Sep 2024 12:18:58 -0400 Subject: [PATCH 10/12] Level_SetWeather: Use str instead of int --- src/deh_soc.c | 2 +- src/p_setup.cpp | 2 +- src/p_spec.c | 23 ++++++++++++++++++++--- src/r_state.h | 3 ++- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index 32475d0a6..c721f20ea 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -4697,7 +4697,7 @@ preciptype_t get_precip(const char *word) return i; } deh_warning("Couldn't find weather type named 'PRECIP_%s'",word); - return PRECIP_RAIN; + return PRECIP_NONE; } /// \todo Make ANY of this completely over-the-top math craziness obey the order of operations. diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 8131364c5..405d26e87 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -141,7 +141,7 @@ unsigned char mapmd5[16]; // boolean udmf; -static INT32 udmf_version; +INT32 udmf_version; size_t numvertexes, numsegs, numsectors, numsubsectors, numnodes, numlines, numsides, nummapthings; size_t num_orig_vertexes; vertex_t *vertexes; diff --git a/src/p_spec.c b/src/p_spec.c index f7f46b4e0..e8a3a5499 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3195,14 +3195,31 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha break; case 424: // Change Weather + { + preciptype_t new_precip = PRECIP_NONE; + if (udmf_version < 2) + { + new_precip = args[0]; + } + else + { + new_precip = stringargs[0] ? get_number(stringargs[0]) : PRECIP_NONE; + } + if (args[1]) { - globalweather = (UINT8)(args[0]); + globalweather = new_precip; P_SwitchWeather(globalweather); } - else if (mo && mo->player && P_IsPartyPlayer(mo->player)) - P_SwitchWeather(args[0]); + else + { + if (mo && mo->player && P_IsPartyPlayer(mo->player)) + { + P_SwitchWeather(new_precip); + } + } break; + } case 425: // Calls P_SetMobjState on calling mobj { diff --git a/src/r_state.h b/src/r_state.h index 5b9303f2d..6cfcc1a09 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -64,8 +64,9 @@ extern size_t numspritelumps, max_spritelumps; // // Lookup tables for map data. // -#define UDMF_CURRENT_VERSION (1) +#define UDMF_CURRENT_VERSION (2) extern boolean udmf; +extern INT32 udmf_version; extern size_t numsprites; extern spritedef_t *sprites; From a2ddd5079e57a3c111bc1d40361e85059a3b7e97 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 21 Sep 2024 03:58:33 -0400 Subject: [PATCH 11/12] Thing_StartTracking: Make it do something Instead of using a linedef executor tag as an argument, apply an action special to the angle manager object that you had to place anyways. There is no UDMF version check because the old behavior was practically unusable. --- src/p_mobj.c | 8 +------- src/p_spec.c | 6 ++---- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 8b1862fab..7941c228a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6790,12 +6790,8 @@ static void P_TracerAngleThink(mobj_t *mobj) if (!mobj->tracer) return; - if (!mobj->extravalue2) - return; - // mobj->lastlook - Don't disable behavior after first failure // mobj->extravalue1 - Angle tolerance - // mobj->extravalue2 - Exec tag upon failure // mobj->cvval - Allowable failure delay // mobj->cvmem - Failure timer @@ -6818,8 +6814,6 @@ static void P_TracerAngleThink(mobj_t *mobj) mobj->cvmem--; else { - INT32 exectag = mobj->extravalue2; // remember this before we erase the values - if (mobj->lastlook) mobj->cvmem = mobj->cusval; // reset timer for next failure else @@ -6829,7 +6823,7 @@ static void P_TracerAngleThink(mobj_t *mobj) mobj->lastlook = mobj->extravalue1 = mobj->extravalue2 = mobj->cvmem = mobj->cusval = 0; } - P_LinedefExecute(exectag, mobj, NULL); + P_ActivateThingSpecial(mobj->tracer, mobj); } } else diff --git a/src/p_spec.c b/src/p_spec.c index e8a3a5499..e80769fb2 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4156,8 +4156,7 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha { INT32 failureangle = FixedAngle((min(max(abs(args[1]), 0), 360))*FRACUNIT); INT32 failuredelay = abs(args[2]); - INT32 failureexectag = args[3]; - boolean persist = !!(args[4]); + boolean persist = !!(args[3]); mobj_t *anchormo; anchormo = P_FindObjectTypeFromTag(MT_ANGLEMAN, args[0]); @@ -4168,7 +4167,6 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha P_SetTarget(&mo->tracer, anchormo); mo->lastlook = persist; // don't disable behavior after first failure mo->extravalue1 = failureangle; // angle to exceed for failure state - mo->extravalue2 = failureexectag; // exec tag for failure state (angle is not within range) mo->cusval = mo->cvmem = failuredelay; // cusval = tics to allow failure before line trigger; cvmem = decrement timer } break; @@ -4178,7 +4176,7 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha { mo->eflags &= ~MFE_TRACERANGLE; P_SetTarget(&mo->tracer, NULL); - mo->lastlook = mo->cvmem = mo->cusval = mo->extravalue1 = mo->extravalue2 = 0; + mo->lastlook = mo->cvmem = mo->cusval = mo->extravalue1 = 0; } break; From 287c711da4294d822390c501f26b62bca9d7347f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 21 Sep 2024 04:17:00 -0400 Subject: [PATCH 12/12] Implement SetLineBlocking This could be done with Get/SetLineProperty just fine, but added just for completion's sake -- the Hexen instruction set is now fully implemented, minus SoundSequence which is for a feature we straight up don't have. --- src/acs/call-funcs.cpp | 31 +++++++++++++++++++++++++++++++ src/acs/call-funcs.hpp | 1 + src/acs/environment.cpp | 2 +- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/acs/call-funcs.cpp b/src/acs/call-funcs.cpp index 3283bb865..3175db90d 100644 --- a/src/acs/call-funcs.cpp +++ b/src/acs/call-funcs.cpp @@ -1147,6 +1147,37 @@ bool CallFunc_SetLineTexture(ACSVM::Thread *thread, const ACSVM::Word *argV, ACS return false; } +/*-------------------------------------------------- + bool CallFunc_SetLineBlocking(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Changes a linedef's blocking flag. +--------------------------------------------------*/ +bool CallFunc_SetLineBlocking(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + mtag_t tag = 0; + UINT32 blocking = 0; + INT32 lineId = -1; + + tag = argV[0]; + + if (argV[1] != 0) + { + blocking = ML_IMPASSABLE; + } + + TAG_ITER_LINES(tag, lineId) + { + line_t *line = &lines[lineId]; + + if (line->flags & ML_TWOSIDED) // disallow changing this for 1-sided lines + { + line->flags = (line->flags & ~ML_IMPASSABLE) | blocking; + } + } + + return false; +} + /*-------------------------------------------------- bool CallFunc_SetLineSpecial(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) diff --git a/src/acs/call-funcs.hpp b/src/acs/call-funcs.hpp index ba2dee6e8..4f79d6b6c 100644 --- a/src/acs/call-funcs.hpp +++ b/src/acs/call-funcs.hpp @@ -57,6 +57,7 @@ bool CallFunc_IsNetworkGame(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSV bool CallFunc_SectorSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_AmbientSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_SetLineTexture(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_SetLineBlocking(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_SetLineSpecial(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_ThingSound(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_EndPrintBold(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); diff --git a/src/acs/environment.cpp b/src/acs/environment.cpp index 0a4939811..4cfb05d20 100644 --- a/src/acs/environment.cpp +++ b/src/acs/environment.cpp @@ -88,7 +88,7 @@ Environment::Environment() addCodeDataACS0( 95, {"", 2, addCallFunc(CallFunc_AmbientSound)}); addCodeDataACS0( 97, {"", 4, addCallFunc(CallFunc_SetLineTexture)}); - + addCodeDataACS0( 98, {"", 2, addCallFunc(CallFunc_SetLineBlocking)}); addCodeDataACS0( 99, {"", 7, addCallFunc(CallFunc_SetLineSpecial)}); addCodeDataACS0(100, {"", 3, addCallFunc(CallFunc_ThingSound)}); addCodeDataACS0(101, {"", 0, addCallFunc(CallFunc_EndPrintBold)});