Skip to content

Combat Moves Debug Commands ​

Type these in the client console (F8). They are client-side and only act on the player running them.

What Config.Debug actually gates ​

It gates console printing, not the commands

client/debug.lua is always in client_scripts, and it registers every cs_* command and /unstuck at load — there is no Config.Debug check around any of them. The flag is read by slide.lua, roll.lua, guntricks.lua and dive.lua, and all it does there is decide whether to print.

So:

  • Setting Config.Debug = false stops the per-move console reports. It does not remove the commands.
  • /unstuck keeps working in production, which is what you want.
  • The only two diagnostic threads start when a player runs cs_watch or cs_dive, and stop with cs_watch off / cs_dive off. Nothing runs in the background because Config.Debug is on.

config.lua ships Config.Debug = true. Set it to false before launch — see Installation.

The one every player needs ​

/unstuck

Releases NUI focus, force-closes the menu, resets gun tricks, stops a slide, clears secondary and primary ped tasks, and sets the trick list back to 'none'.

What /unstuck covers, and the one thing it does not

A stranded trick-list title, a menu that left input grabbed, a slide that will not end, a spin that never started properly — /unstuck clears all of those, and it is safe to give to players.

It does not end a dive. It never calls StopDive, so the dive module stays in its current mode and the crawl and on-back loops re-issue the pose and re-assert the prone camera within a frame of the tasks being cleared. A player stranded prone, crawling, on their back or sitting needs the menu's Dive, Crawl & Gun → Fix → Stand up now row, or the StopDive() export.

General ​

CommandWhat it does
cs_watchlive read-out of health, cores, ammo and controls; cs_watch off to stop
cs_menuids [substring|off]every id Config.Menu can switch, with its state; the filter matches anywhere in the id, not just the start

cs_watch exists for one specific question — did the gun actually fire? IS_PED_SHOOTING and IS_PED_WEAPON_READY_TO_SHOOT are both unreliable on this RedM build, so the readout watches the ammo column instead. If ammo drops, the gun fired. The command prints its own two-step test when you start it:

  1. Stand still, aim, fire — ammo must drop, which proves the readout works.

  2. Slide while holding aim, then fire.

Slide ​

CommandWhat it does
cs_animprobe the two slide dictionaries for 31 candidate clip names; takes no arguments
cs_play <n> [flags]play combination n from cs_anim, right now
cs_stopclear any test animation
cs_noanimdoes nothing — it writes Config.Anim.disabled, which no code reads
cs_flags <flags>change Config.Anim.entryFlags live, decoded by name
cs_filter <name|auto>force a bone filter
cs_move / cs_speedmovement mode and speed
cs_cam / cs_camtesttune or cycle the slide camera
cs_preset / cs_usewhole coherent configurations
cs_sweep / cs_reportbisect Config.Apply, one subsystem per slide

How cs_anim knows a clip exists

GET_ANIM_DURATION returns 0.0 for a clip that is not in its dictionary, so it works as a "does this exist" oracle without having to play anything. cs_anim also runs a control test against a deliberately bogus dictionary first — if that reports as loaded, HasAnimDictLoaded cannot be trusted on your build and the rest of the output is meaningless.

It cannot be pointed at a dictionary, and it cannot enumerate one. The two dictionaries are always Config.Anim.entryDict and Config.Anim.exitDict, and the names it tries are a hardcoded list of 31 candidates — a clip whose name is not on that list is never reported, however real it is.

cs_sweep is a cumulative bisection, not a full matrix: 8 fixed rows, one slide each, starting from a slide that does nothing at all and turning one more Config.Apply subsystem back on with every row. For each row it records whether the animation played and whether a shot actually came out, so the first row that breaks usually names the subsystem responsible — with one exception: row 7 switches on stamina and the animation together, so a failure that first appears there could be either. cs_sweep off stops it and restores the action-disable flags.

cs_noanim is inert

It only writes Config.Anim.disabled, and nothing in the resource reads that field — the animation task is gated solely on Config.Apply.anim. To run the control experiment ("does the weapon fire when no animation plays?"), set Config.Apply.anim = false, or use row 1 of cs_sweep.

Roll ​

CommandWhat it does
cs_rollanimlist clips in the roll dictionary
cs_rollflagschange roll flags live
cs_rollrequest a roll
cs_rollkeyprint the roll key and trigger, or set the trigger with cs_rollkey trigger <key|native|both>

cs_rollkey cannot rebind the key. Given a key name it only prints a reminder to set Config.Roll.key in config.lua and restart, because the key is bound at start. Its one live effect is the trigger sub-command.

cs_rollflags is the one that matters, because the roll's flag word is the single value that could not be recovered from the original decompile — it ships as 0 and is meant to be tuned live. See Combat Roll.

Gun tricks ​

CommandWhat it does
cs_trick / cs_tricksplay or list tricks
cs_hands <auto|dual|single|left>force the hand mode
cs_hudtrick list renderer and position
cs_promptsprompt diagnostics

cs_hud with no arguments prints the current mode and all five position values. It takes either a mode — cs_hud nui|draw|prompt|none — or a field and a value: cs_hud <x|y|line|scale|key> <value>.

Dive ​

CommandWhat it does
cs_diveanimload every dive and crawl dictionary and print each clip's real duration
cs_divetest <class> <dir>force one dive animation without the movement keys
cs_divelive read-out of dive state, stealth, weapon class and submersion

cs_diveanim prints anything the dictionary does not contain in red. cs_divetest is how you check a single direction and weapon class without having to get the movement keys right. cs_dive off stops the watch.

cs_dive also prints eight IS_WEAPON_* predicates on its second line — pistol, revolver, rifle, repeater, shotgun, bow, two-handed and silent — which is the fastest way to find out why a weapon is landing in the wrong animation class. The other predicates in natives.lua, including sniper, melee and throwable, are not in the readout.

The full list ​

28 cs_* commands plus unstuck:

unstuck      cs_watch     cs_menuids
cs_anim      cs_play      cs_stop      cs_noanim    cs_flags
cs_filter    cs_move      cs_speed     cs_cam       cs_camtest
cs_preset    cs_use       cs_sweep     cs_report
cs_rollanim  cs_rollflags cs_roll      cs_rollkey
cs_trick     cs_tricks    cs_hands     cs_hud       cs_prompts
cs_diveanim  cs_divetest  cs_dive

Plus the two menu commands, which are not diagnostics: /combatmoves and /guntricks.

Bisecting a problem ​

Config.Apply switches every individual thing a slide does to the ped, so a problem can be bisected rather than guessed at:

lua
Config.Apply = {
    anim        = true,  -- TASK_PLAY_ANIM
    camera      = true,  -- the scripted slide camera
    velocity    = true,  -- SET_ENTITY_VELOCITY each frame
    heading     = true,  -- SET_ENTITY_HEADING each frame
    controls    = true,  -- the DISABLE_CONTROL_ACTION list
    actionFlags = true,  -- _SET_PED_ACTION_DISABLE_FLAG
    resetFlags  = true,  -- SET_PED_RESET_FLAG and keeping the weapon drawn
    stamina     = true,  -- _CHANGE_PED_STAMINA
}

With all of them false a slide does nothing but run its timer. Turn one back on at a time, or let cs_sweep do it for you.

Measure, do not guess

Most animation problems in this resource turned out to be a timing or flag value that could be read rather than guessed. cs_diveanim and cs_anim print real clip durations; cs_flags and cs_rollflags decode flag bits by name. Reach for those before changing a number in config.lua.

Documentation for RedMorrow. Scripts are licensed per server — redistribution is not permitted.