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. 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)}); diff --git a/src/deh_soc.c b/src/deh_soc.c index 800e5b201..da9d355a2 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_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_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..e80769fb2 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 { @@ -4139,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]); @@ -4151,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; @@ -4161,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; 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;