Skip to content

Usage

Controls

InputAction
W / A / S / DMove around the ring
Left ShiftSprint (costs stamina)
LMBLeft hook (body)
RMBRight hook (body)
Q + LMBLeft jab (body)
Q + RMBRight jab (body)
E + LMBLeft uppercut (body)
E + RMBRight uppercut (body)
Caps Lock + LMB/RMB/Q+LMB/...Target the head instead of body
SpaceBlock
EGet up after being knocked down

Power Punches

Hold the modifier key longer before releasing to throw a power punch (e.g. Q held → LMB = power jab). Power punches deal more damage and drain more of the opponent's stamina on block.

Starting a Match

  1. Approach a boxing ring - an interaction prompt will appear.
  2. Choose Invite player to match and select a nearby player.
  3. Configure the match settings:
    • Rounds - 1 to 12 (default: 3)
    • Round Time - 30 to 300 seconds (default: 180)
    • Rest Time - 0 to 300 seconds between rounds (default: 30)
    • Match Type - Ranked or Sparring
  4. The invited player receives a notification and must approach the same ring to accept.
  5. Both players pick an intro animation, then the match begins.

Sparring

Sparring matches are informal - they do not count towards the win/loss record and are not saved to the database.

Tutorial

Select Start Tutorial at any ring to begin a 2-step NPC tutorial:

  • Step 1 - Movement (WASD, sprint) and basic punches (hooks, jabs, uppercuts)
  • Step 2 - Blocking, head shots (Caps Lock), and getting up after a knockdown

Rings

Config-defined rings

Rings can be hardcoded in config/sh_config.lua. They will always be present and cannot be removed by admins in-game.

lua
Config.BoxingRings = {
    ["main_gym"] = {
        position = vector4(x, y, z, heading),
        rotation = vector3(rx, ry, rz),
    },
}

Admin-spawned rings

Admins can place rings at runtime using the in-game gizmo. These are saved to config/adminRings.json and persist across restarts.

CommandPermissionDescription
/boxingspawnring [name]group.adminSpawn a ring at your current position (opens gizmo)
/boxingremovering [name]group.adminRemove a named ring
/boxinglistringsgroup.adminOpen the admin panel listing all active rings

The gizmo controls during placement:

KeyAction
WPosition mode
RRotation mode
XToggle snap-to-ground
EnterConfirm and spawn
EscCancel

Custom ring model

To replace the default ring prop, set this before sh_config.lua is loaded (e.g. at the top of your own config):

lua
Config.OverrideRingModel = `your_model_hash`

General Settings (sh_config.lua)

OptionDefaultDescription
Config.DefaultRoundCount3Pre-filled round count when setting up a match
Config.DefaultRoundTime180Pre-filled round duration (seconds)
Config.DefaultRestTime30Pre-filled rest time between rounds (seconds)
Config.InviteDuration60000How long an invitation stays open (ms)
Config.RingSpawnDistance200.0Max distance at which a ring prop is streamed in
Config.DebugtrueEnable debug logging (override with boxing_debug convar)
Config.HitSoundVolume0.2Volume for hit sounds
Config.WhooshSoundVolume0.05Volume for miss sounds
Config.BellVolume0.2Volume for round bell

Balance Settings (balance_config.lua)

OptionDefaultDescription
Config.DefenseStaminaDrain5% stamina drained per second while holding block
Config.StaminaRegen25% stamina regained per second
Config.StaminaRegenDelay750ms after last action before stamina starts regenerating
Config.SprintSpeedMultiplier2.0Speed multiplier when sprinting
Config.SprintStaminaCost50Stamina cost per second of sprinting
Config.KOThreshold30KO meter value required to knock an opponent down
Config.RemoveMaxStaminaPercentage3% of max stamina permanently removed per round based on total stamina used

Per-move stamina costs, damage values, defense stamina costs and KO contributions are all defined in Config.AttackStaminaCost, Config.AttackDamage, Config.DefenseStaminaCost and Config.KOAttacks respectively.