Skip to content

Releases: DarkMatter-Productions/MuffMode

MuffMode v0.22.10

03 Apr 15:10

Choose a tag to compare

Changelog

Scoreboard: captain indicator for TDM/CTF

  • Show asterisk (*) next to team captains on the scoreboard. Server-side only; no client download required.

Tab menu: Ready Up option

  • Added Ready Up / Not Ready option to the join menu (team and free modes), shown only during ready-up warmup when g_dm_do_readyup is enabled. Toggles ready state on selection. Replaced a blank row and removed an extra blank for a cleaner layout.

Voting menu: Shuffle Teams and Ready All

  • Added Shuffle Teams and Ready All options to the Call Vote menu.
  • Shuffle Teams shows N/A for non-team gametypes; Ready All shows N/A when not in ready-up warmup.
  • Added readyall vote command (calls ReadyAll during MATCH_WARMUP_READYUP). Vote validation and execution include defensive checks for both votes.

Map vote / nextmap fix

  • Fixed a bug where the same map could load again after a map vote when the voted map was not in g_map_list. level.nextmap (set by the vote) was persisting across map loads because most maps don't define a worldspawn nextmap key. The next match end would then use that stale value and reload the same map instead of advancing the rotation.
  • Now clears level.nextmap when loading a map that has no worldspawn nextmap key, so Match_End correctly falls through to map queue, g_map_list, or other fallbacks.
  • When the current map is not in g_map_list (e.g. voted from pool), Match_End now rejoins the rotation at the first map in the list instead of falling through to target_changelevel or same map.

Eyecam spectator stutter fix

  • Fixed stuttery view when spectating players with g_eyecam 1 enabled. Zero delta_angles for eyecam spectators so the view is fully server-authoritative, avoiding jitter from spectator cmd_angles mismatch. Only apply the vanilla chase cam delta formula when g_eyecam is off.
  • Aligned spectator entity origin with pmove (view position) for consistency.

MuffMode v0.22.0

27 Feb 22:42

Choose a tag to compare

  • Added read-only admin doctor diagnostics command that runs all checks.
  • doctor now reports cvar misconfigurations and risky combinations with suggested fixes (no auto-apply).
  • Fixed single-player level transitions: prevent repeated ExitLevel() calls from causing Got null changemap when trying to exit level after re-entering maps.
  • Refactored ruleset tuning in p_weapon.cpp into centralized helper paths (pickup/drop, MG/CG, rocket/hyper, rail/BFG, plasma/ion) and aligned non-explicit overrides toward vanilla-default behavior.
  • Default ruleset changed to 1 to preserve vanilla behavior.
  • Fixed gametype voting race condition: voting for duel from TDM could incorrectly load deathmatch due to GT_Changes() overriding the gametype after teamplay/ctf cvar changes.
  • Adjusted chaingun damage to 4.5 for Balanced and QC rulesets.
  • Added diagnostic logging to KillBox for telefrag lag investigation (enable with g_muffmode_debug 1).

MuffMode v0.21.87

23 Feb 17:28

Choose a tag to compare

  • Clan Arena/spectator: clear eliminated when switching to true spectator team so unteamed spectators can enter and use chasecam/follow normally.
  • Spectator/chasecam: allow eliminated players to receive and process queued follow targets (killer/leader auto-follow), reducing cases where they remain stuck in freecam after death.
  • Clan Arena: reset per-player damage carryover counters on round reset (dmg_scorer/dmg_team) so damage-based scoring does not leak across rounds.
  • Arena self-damage: clarified in-code behavior/docs that self-health damage is always blocked in arena modes, and g_arena_dmg_armor only controls self-hit armor absorption.
  • Clan Arena: fix round-timeout winner checks to use fresh live-player counts at timeout, preventing incorrect winner calls from stale team-living counters.
  • Fix end-of-match team score HUD showing stale tied values in TDM/CTF; now displays the final score.
  • g_ruleset 4 balance: reverted machinegun and chaingun spread overrides to defaults, reverted shotgun RS_VANILLA_PLUS override to default behavior, and increased rocket speed from 720 to 750.
  • Fix crash: P_Menu_Close now clears inmenu flag alongside menu = nullptr, preventing ClientThink from dereferencing a freed menu handle after menu close.
  • Fix sporadic end-of-map crash (seen on maps like q64/dm4): screenshot filenames now sanitize map names/path separators before screenshot command enqueue, and ExitLevel logs raw vs sanitized map names plus final screenshot command for diagnosis.
  • Harden end-of-map screenshot flow: validate duel sorted-client indices before entity access, require follow_target to be inuse before name reads, cap screenshot filename length, and guard against empty screenshot command enqueue.
  • AutoDoc tech: fixed armor regeneration cadence for non-MM rulesets to match health regen timing (500ms), while preserving MM's 1s cadence.
  • Fix crash: close any open player menu in MoveClientToIntermission to prevent stale svc_layout writes after match end, which caused a renderer double-begin-frame assertion (g_bInValidFrame).

Muffmode v0.21.78

21 Feb 13:25

Choose a tag to compare

Voting Menu Improvements

  • Enabled voting menu in GUI: Uncommented "Call a Vote" option in join menus (teams and free-for-all)
  • Fixed duplicate "Admin" option: Removed static "Admin" entry that was duplicating the dynamic one
  • Fixed "Admin" menu alignment: Changed from centered to left-aligned to match other menu options
  • Simplified voting menu: Hid all voting options except "Map" (renamed from "change map") for focused testing
  • Map names display in uppercase: Map names in the voting menu are now displayed in uppercase for better visibility while preserving original case for voting
  • Fixed critical map name corruption bug: Resolved issue where map names were being corrupted when voting from the menu (e.g., "mm-mcoil" becoming "4UD" or "`MKD")
    • Root cause: Memory corruption occurring when reading map names from menu entries
    • Solution: Store original map names in menu_t.text_arg1 when populating menu, read directly from there instead of doing case-insensitive lookup
    • Additional safety: Use C string buffers until menu is closed, then convert to std::string to prevent corruption from P_Menu_Close
    • Ensures map names are preserved correctly throughout the voting process
  • Spectator voting restriction: Added checks to prevent spectators from calling votes via the menu system
    • Menu-based voting now respects the g_allow_spec_vote cvar (defaults to 0, disabled)
    • Matches the behavior of command-based voting (/callvote)
    • Checks added at menu entry point (G_Menu_CallVote) and map selection (G_Menu_CallVote_Map_Selection)
  • Scorelimit voting menu: Fixed first-vote issue and improved reliability
    • Fixed critical bug where scorelimit vote would show blank value on first vote from menu
    • Root cause: level.vote_arg was being set using plain std::string assignment which was getting corrupted
    • Solution: Use same clear → reserve → assign pattern as map votes for consistent memory management
    • Menu option shows current scorelimit value
    • Submenu allows selection of common limit values: 0, 5, 10, 20, 30, 40, 50, 100
    • Includes spectator voting checks
  • Timelimit voting menu: Added new timelimit voting option
    • Menu option shows current timelimit value in minutes
    • Submenu allows selection of: 0, 5, 10, 15, 20, 25, 30 minutes
    • Mirrors scorelimit menu implementation for consistency
    • Includes spectator voting checks
  • Gametype voting menu: Added new gametype voting option
    • Menu displays all available gametypes with their full names (e.g., "Deathmatch", "Team Deathmatch", "Capture the Flag")
    • Respects g_votable_gametypes cvar: if set, only shows gametypes listed in the cvar
    • If g_votable_gametypes is empty, shows all implemented gametypes (skips GT_NONE, GT_STRIKE, GT_RR, GT_LMS, GT_BALL)
    • Uses same reliable memory management pattern as other voting menus
    • Includes spectator voting checks
  • Gametype config execution fix: Fixed gametype-specific cfg files executing on every map load
    • Problem: gt-{gametype}.cfg files were executing on every map load, overriding player votes and map progression
    • Example: Players vote gametype to TDM (cfg sets map to q2dm1), vote scorelimit to 30, match ends, map advances to q2dm2, but then cfg executes again and resets map back to q2dm1
    • Solution: Moved cfg execution from InitGame() to ChangeGametype() so it only runs when gametype actually changes
    • Cfg files now execute immediately when gametype changes (via vote or admin command), not on every map load
    • Preserves player votes and natural map progression
  • Powerups voting menu: Added powerups toggle vote with submenu
    • Menu option shows current powerup state: "Powerups: ON" or "Powerups: OFF"
    • Opens submenu with "ON" and "OFF" options for explicit selection
    • When powerups vote passes, map automatically restarts so changes take effect immediately
    • Uses same reliable memory management pattern as other voting menus
    • Includes spectator voting checks
  • Friendly Fire voting menu: Added friendly fire toggle vote with submenu
    • Menu option shows current friendly fire state: "Friendly Fire: ON" or "Friendly Fire: OFF"
    • Only available in TDM and CTF gametypes specifically
    • In other gametypes, shows "Friendly Fire: N/A" and is not selectable
    • Opens submenu with "ON" and "OFF" options for explicit selection
    • When friendly fire vote passes, map automatically restarts so changes take effect immediately
    • Uses same reliable memory management pattern as other voting menus
    • Includes spectator voting checks
    • Vote command validates that friendly fire can only be changed in TDM or CTF gametypes
  • Main voting menu reorganization: Reordered main callvote menu options
    • New order: Gametype, Map, (blank line), Scorelimit, Timelimit, (blank line), Powerups, Friendly Fire
    • All submenus now return to the main callvote menu instead of the top-level main menu
    • Consistent navigation experience across all voting submenus

Gametype System Enhancements

  • Instagib as a gametype: Converted g_instagib cvar functionality into a full gametype (GT_INSTAGIB)
    • Instagib can now be selected via the gametype voting menu
    • When selected, executes gt-INSTAGIB.cfg config file (if g_gametype_cfg is enabled)
    • Maintains backward compatibility: g_instagib cvar still works and syncs with gametype
    • When switching to Instagib gametype, g_instagib cvar is automatically set to 1
    • When switching away from Instagib gametype, g_instagib cvar is automatically cleared
    • Both cvar and gametype methods can be used without conflict
    • All existing code checks updated from g_instagib->integer to (g_instagib->integer || GT(GT_INSTAGIB))
    • Added to votable gametypes list
    • Displays as "Instagib" in gametype menus and HUD
  • NadeFest as a gametype: Converted g_nadefest cvar functionality into a full gametype (GT_NADEFEST)
    • NadeFest can now be selected via the gametype voting menu
    • When selected, executes gt-NADEFEST.cfg config file (if g_gametype_cfg is enabled)
    • Maintains backward compatibility: g_nadefest cvar still works and syncs with gametype
    • When switching to NadeFest gametype, g_nadefest cvar is automatically set to 1
    • When switching away from NadeFest gametype, g_nadefest cvar is automatically cleared
    • Both cvar and gametype methods can be used without conflict
    • All existing code checks updated from g_nadefest->integer to (g_nadefest->integer || GT(GT_NADEFEST))
    • Added to votable gametypes list
    • Displays as "NadeFest" in gametype menus and HUD

Team Captain System

  • Added team captains for team modes: Teams now track captain ownership (red and blue) and auto-assign captains when needed
    • First eligible player to join a team becomes captain when no captain is set
    • If a captain leaves/switches teams/disconnects, captain status auto-transfers to the longest-tenured teammate
    • Captain validity is rechecked on match start/reset to prevent stale captain pointers
  • New captain command:
    • captain shows your current team captain, or claims captain if your team has none
    • captain <player> transfers captain status to a teammate (captain only)
  • Captain permissions:
    • Captains can lock/unlock their own team with lockteam / unlockteam
    • Captains can ready their full team with readyteam
    • Admins retain override control for all captain-gated actions

Ruleset Fixes

  • Vanilla (Q2RE) powerup sound broadcasting: Fixed missing powerup sound broadcasting in vanilla ruleset
    • Problem: Powerup pickup and activation sounds were only broadcast to all players in MM, Q3A, and Vanilla Plus rulesets, but not in vanilla (Q2RE) ruleset
    • This was inconsistent behavior - vanilla should match other rulesets for competitive awareness
    • Solution: Added RS(RS_Q2RE) to powerup sound broadcasting checks
    • Powerup pickup sounds (when touching items) now broadcast to all players in deathmatch with vanilla ruleset
    • Powerup activation sounds (when using Quad, Haste, Double Damage) now broadcast to all players in deathmatch with vanilla ruleset
    • Matches behavior of MM, Q3A, and Vanilla Plus rulesets for consistency
  • Quake Champions (QC) ruleset weapon tuning:
    • Rocket launcher speed increased to 750
    • Plasma Beam in deathmatch now matches Q2RE Balanced behavior: damage reduced to 10 and maximum range limited to 768
    • Keeps QC ruleset pacing while aligning Plasma Beam balance with modern competitive settings

Voting System Stability

  • Fixed vote counting in duel mode: Vote tallies are now recounted every frame in UpdateActiveVote, fixing cases where votes wouldn't pass due to stale counts
  • Fixed crash when vote caller disconnects: level.vote_state.caller is now cleared immediately when a vote transitions to FAILED, preventing dangling pointer access
  • Fixed potential crash during map vote execution: Added proper null/validity checks for entity pointers in ExitLevel screenshot logic, preventing access violations during mid-game map changes
  • Defensive null guard in vote menu: Added null check for level.vote_state.caller in G_Menu_Vote_Update to prevent crash if caller becomes invalid during menu rendering
  • Fixed duel vote eligibility: Duel-queued players are now counted as eligible voters. Previously, queued players were treated as spectators and excluded from vote counts when g_allow_spec_vote was 0, causing votes to pass/fail immediately with only 1 eligible voter in 2-player duel matches
  • New ClientCanVote() helper: Centralized vote eligibility logic — returns true for active players, duel-queued players, and spectators when g_allow_spec_vote is enabled
  • Fixed crash on gametype change map load: `SV...
Read more

v0.21.29

27 Jan 00:20

Choose a tag to compare

Fixed

  • Duel queue joining during match lock: Fixed issue where players were unable to join the duel queue when a match was locked. Queue joining is now allowed during match lock since it doesn't affect the active match - queued players are only pulled into matches during warmup periods. This allows players connecting mid-match to queue up for the next match without having to wait for warmup.
  • Duel queue refilling during readyup: Fixed issue where the duel queue would not refill if a player disconnected during the readyup phase. Duel_AddPlayer() now works during MATCH_WARMUP_READYUP in addition to MATCH_WARMUP_DEFAULT, allowing queued players to be pulled in immediately if a slot opens during readyup. This ensures matches can start with a full roster even if players disconnect during the readyup phase.
  • Duel mode map change crash: Fixed crash error "Got null changemap when trying to exit level" that occurred when duel matches ended. Duel mode now automatically restarts on the same map if no changemap is configured, ensuring continuous duel matches without requiring map changelevel entities. This prevents server crashes when duel matches end and allows the queue system to continue functioning properly.
  • Callvote map display: Fixed issue where callvote map only displayed maps from either g_map_pool or g_map_list depending on which was populated. The callvote system now displays all maps from both lists combined, with case-insensitive deduplication and alphabetical sorting. This ensures players can see and vote for all available maps regardless of which cvar they're configured in.
  • Callvote map crash fix: Fixed access violation crash (0xc0000005) that occurred when executing callvote map <mapname>. The crash was caused by insufficient validation of the level.changemap pointer before dereferencing it in ExitLevel(). Added comprehensive pointer validation and string length checks to prevent crashes from invalid or corrupted pointers. The fix also adds validation in Vote_Pass_Map() to ensure the map name is properly copied to safe storage before use.
  • g_inactivity false positives: Fixed issue where g_inactivity could incorrectly trigger for actively playing players. The inactivity timer previously only checked for newly pressed buttons (latched_buttons), which meant players holding movement keys continuously or only moving the mouse could be flagged as inactive. The timer now checks for any button input, movement input (forwardmove/sidemove), view angle changes (mouse movement), and newly pressed buttons to accurately detect player activity. View angle changes are detected by comparing current and previous frame angles with a 1-degree threshold to avoid false positives from tiny movements.
  • [Special Colendro Fix] Eyecam spectator fall sound: Fixed the "donk" sound that played when spectating players in eyecam mode as they fell off ledges.

Added

  • Automatic bot queueing in duel mode: Bots that are spectating in duel mode are now automatically added to the queue regardless of how many players are currently in the match. This allows bots to fill empty slots in duel matches and be ready for future matches, making it easier to test and play duel mode with bots. Bots are queued whenever they're spectating (except during intermission), and will be pulled into matches by Duel_AddPlayer() during warmup periods.

Changed

  • Team border display: Changed default value of cl_teamBorder from 0 to 1, enabling team border display by default in team-based gamemodes. Players can still disable it by setting cl_teamBorder 0 if desired.

v0.21.20

21 Jan 12:39

Choose a tag to compare

v0.21.20

Added

  • Team border indicator: Added a configurable colored border at the bottom of the screen to clearly indicate team membership in team-based game modes (TDM, CTF, etc.). The border displays red for Red team and blue for Blue team. Configurable via cvars: cl_teamBorder (enable/disable, default: 0), cl_teamBorderWidth (thickness in pixels, default: 4), and cl_teamBorderAlpha (transparency 0-255, default: 180). Fixed missing team_id assignment in player_state_t that was preventing the feature from working.
  • Configurable votable gametypes: Added g_votable_gametypes cvar to allow server admins to control which gametypes can be voted on by players. The cvar accepts a space-separated list of gametype short names (e.g., "ffa duel tdm ctf ca"). If empty (default), all gametypes are votable for backward compatibility. When set, only gametypes in the list can be voted on via callvote. Admin gametype command still allows setting any gametype but shows a warning if the gametype is not in the votable list. Help text dynamically displays only the votable gametypes.

Fixed

  • Spectator sound fixes: Fixed issue where positioned sounds for footsteps, fall damage, and ladder steps were being sent to all clients (including the player themselves), causing players to hear duplicate or changed sounds. Now positioned sounds are only sent when there are actual spectators viewing the player, so players hear normal entity event sounds while spectators can still hear the sounds properly.
  • Callvote crash fixes: Fixed multiple null pointer dereference issues in the voting system that could cause server crashes when players used the callvote command. Added null checks in vote menu updates, vote execution, and vote storage functions. Also fixed incomplete state cleanup when votes time out or fail, ensuring level.vote is properly cleared along with level.vote_time. Fixed vote state persistence across map changes - vote_execute_time and other vote state variables are now properly cleared during level initialization. Fixed vote cancellation when the vote caller disconnects. Fixed incorrect vote_arg initialization in G_InitLevel() (was using = '\n' instead of .clear() for std::string).
  • Voting system improvements: Fixed duplicate vote vulnerability in menu voting functions (G_Menu_Vote_Yes/No) that allowed players to vote multiple times. Added vote state validation in CheckVote() to detect and clear invalid vote state when level.vote is null, preventing hanging votes. Added automatic vote count recalculation in CalculateRanks() when a vote is in progress, preventing race conditions when players join or leave during voting. Ensured complete state cleanup in all vote exit paths, including vote_arg clearing in Cmd_ForceVote_f() and Vote_Passed() error paths.
  • Division by zero fixes: Fixed potential division by zero in P_CurrentKickFactor() when kick.total is zero or negative, which could cause crashes or NaN/infinity values to propagate through view angle calculations, resulting in corrupted camera views. Also fixed potential division by zero in vec3_t operator/(const vec3_t &v) when any component is zero, preventing infinity/NaN values from propagating through vector calculations and causing physics or rendering issues.
  • Duel queue ordering fix: Fixed broken duel queue ordering where all queued players had team_join_time = 0_sec, making queue order unpredictable. Now queued players correctly get team_join_time = level.time when joining the queue, ensuring proper FIFO ordering based on when they entered the queue. Non-queued spectators still get 0_sec to maintain correct separation.
  • Gametype vote menu cleanup: Removed "ft" (Freeze Tag) and "horde" from the hardcoded available gametypes in vote command help text. Now replaced with configurable g_votable_gametypes cvar system that allows admins to control which gametypes are votable. The removed gametypes still function if set directly but are no longer in the default votable list.
  • Two-tier map validation system: Implemented proper validation hierarchy for map votes and commands using g_map_pool and g_map_list. The system now validates maps against g_map_pool first (all available maps), then falls back to g_map_list (maps in rotation) if not found in the pool. This allows players to vote for any map in the pool, not just those currently in rotation. Applied to callvote map validation, admin setmap command, and map queue system. Error messages now display the appropriate map list (pool if available, otherwise rotation list).

v0.21.14

16 Jan 00:37

Choose a tag to compare

Fixed

  • Spectate functionality: Fixed issue where attempting to spectate would spam console with "You may not switch teams more than once per 5 seconds" message and prevent spectating. Players can now switch to spectator immediately without being blocked by the team switch rate limit. The rate limit still applies when switching between playing teams.

  • Spectator sound fixes: Fixed issue where spectators could not hear player footsteps, fall damage sounds, or ladder step sounds when spectating. These sounds used entity events (EV_FOOTSTEP, EV_FALL_SHORT/MEDIUM/FAR, EV_LADDER_STEP) which weren't being transmitted to spectators. The fix adds positioned sound calls alongside the entity events to ensure spectators can hear these sounds. Item pickup sounds already worked correctly as they use direct sound calls rather than entity events.

  • Spectator POV mode: Fixed issue where spectators were stuck in freecam mode and couldn't view from spectator POV (following other players). This was most noticeable in CA mode where eliminated players stay eliminated longer, but affected all gametypes. The issue was that GetFollowTarget, FollowNext, and FollowPrev functions were setting the follow target but not updating spectator_state to SPECTATOR_FOLLOW. Now when spectators follow a player, they properly enter follow mode instead of remaining in freecam.

  • Invisible player in CA mode: Fixed issue where a player could become invisible in Clan Arena mode. This occurred when Entities_Reset set SVF_NOCLIENT flag during round resets, but the flag wasn't properly cleared when a playing (non-eliminated) player spawned. Now SVF_NOCLIENT is explicitly cleared for playing players during spawn, ensuring they are always visible when they should be.

Restored

  • Map item layout switching: Restored functionality from v0.19.60 that allows maps to switch between different item layouts using entity keys and cvars. Maps can use bfg_on/bfg_off and plasmabeam_on/plasmabeam_off entity keys to define alternative layouts, controlled by g_no_bfg and g_no_plasmabeam cvars. This fixes issues on maps like mm-kmach where multiple items were spawning at the same location - the map can now use these keys to have different layouts (e.g., BFG layout vs non-BFG layout) and toggle between them.

  • Match cancellation delay: Added 300ms delay before match cancellation due to too few players. This allows bot_minclients (or other bot systems) time to add bots before the match is cancelled, preventing premature cancellations when bots are being automatically added to maintain minimum player count.

v0.21.09

05 Jan 19:28

Choose a tag to compare

Fix elevators sometimes breaking after match start by resetting trains in Entities_Reset
Fix drop command: move special case checks before item lookup

Added new cvar g_frag_messages

Configure as below:

0: disable rampage messages across all game modes
1: disable rampage messages in TDM/CTF (default)
2: enable rampage messages in all game modes

v0.21.07

27 Dec 22:10

Choose a tag to compare

Disabled/removed banlist code as was causing issues.

Selectively implemented bugfixes from 0.21.0

Added new cvar: g_map_list_shuffle_once: when set to 1, shuffles the map list once at server startup, then cycles through maps in that order without re-shuffling. This differs from g_map_list_shuffle which re-shuffles on every map cycle. (default: 0)

v0.21.0

11 Nov 22:03
e51338e

Choose a tag to compare

  • target_teleporter bug fix
  • numerous bug fixes and stability improvements
  • plasmabeam knockback greatly reduced in muffmode ruleset
  • banned player exploit fixed, more robust now