Combat Moves Server Setup
The resource is client-side, so a server's job here is to set sensible defaults, decide what players may change, and use the convars for the things that must not be negotiable.
Hard limits: convars
Put these in server.cfg. The client re-reads all four at the start of every slide, so a setr change applies on the player's next slide with no restart or reconnect. They clamp what the slide actually does, whatever config.lua and the menu say — the menu rows still appear and still toggle, the clamp bites when the slide runs.
setr combat_slide_allow_timescale "false" # recommended
setr combat_slide_allow_deadeye "true"
setr combat_slide_allow_infinite "false"
setr combat_slide_max_duration "2000"| Convar | Default | What it does |
|---|---|---|
combat_slide_allow_timescale | true | false blocks the slide's bullet time |
combat_slide_allow_deadeye | true | false blocks automatic Dead Eye on a slide |
combat_slide_allow_infinite | true | false blocks unlimited-length slides |
combat_slide_max_duration | 10000 | ceiling in ms on a finite slide's length |
combat_slide_max_duration only bounds finite slides. When Config.InfiniteSlide is on and combat_slide_allow_infinite is still true, the slide ends at Config.MaxInfiniteDuration instead, which is client-side and editable — so set combat_slide_allow_infinite to false if you want the convar to be the real ceiling.
Set combat_slide_allow_timescale to false on a populated server
Bullet time changes time scale for the whole client, which means the player using it sees the world slowed while everyone else sees them moving normally. It already ships off in config.lua — the convar is what stops a player turning it back on from the menu. The convar covers the slide only: the dive has its own bullet time, Config.Dive.enableBulletTimeDuringDive, which also ships false but has no convar behind it, so leave that one off in config.lua.
These four are the only values a player cannot reach. Everything else is advisory.
Deciding what players can change
Config.Menu gates the panel at four levels, coarse to fine.
Hiding something only removes it from the panel
The feature carries on running on whatever config.lua says. To switch a feature off, use its own enabled flag.
Config.Menu = {
enabled = true, -- the whole menu
pages = { -- a page, and its tab
slide = true,
roll = true,
tricks = true,
dive = true,
},
sections = { -- a heading inside a page, and its rows
['slide.behaviour'] = true,
['slide.combat'] = true,
['slide.camera'] = true,
['roll.try-it'] = true,
['tricks.tricks'] = true,
['tricks.more'] = true,
['dive.diving'] = true,
['dive.crawling'] = true,
['dive.prone-camera'] = true,
['dive.dive-camera'] = true,
['dive.stealth'] = true,
['dive.fix'] = true,
['menu.menu'] = true,
['menu.pages'] = true,
['menu.session'] = true,
},
options = { -- one row; absent means shown
-- ['slide.behaviour.mud-decal'] = false,
},
}Find ids with cs_menuids, never by hand
cs_menuidsIt prints every id the menu can switch with its current state, read off the pages as they are really built — so what it prints is exactly what config.lua will match. cs_menuids dive filters on a substring anywhere in the id, not a prefix, so root-list ids such as menu.dive-crawl-gun come through too; cs_menuids off lists only what is hidden.
Ids are page.section.row, lower case with dashes for spaces. A row above the first heading has no section part. Full behaviour on The menu.
Common setups
Read-only panel. Players can look but not change anything useful:
Config.Menu.sections = {
['slide.behaviour'] = false,
['slide.combat'] = false,
['slide.camera'] = false,
['dive.diving'] = false,
['dive.crawling'] = false,
}No menu at all.
Config.Menu.enabled = falseThe key is ignored, /combatmoves prints a notice once, and the OpenMenu export returns false. Every feature still works on your values.
Lock the page set. The root list has a live Pages section that lets a player turn pages back on. Hide it and config.lua becomes the only way:
Config.Menu.sections['menu.pages'] = falseSet your pages deliberately first — with that section hidden, nothing in game can turn one on again.
Turning features off entirely
Hiding a page does not disable it. These do:
Config.Roll.enabled = false
Config.GunTricks.enabled = false
Config.Dive.enabled = falseThe slide has no single flag — trigger combat_slide:setEnabled with false, or call the SetEnabled export. Both write the one flag the slide's input loop reads.
Config.SlideKey = nil does not disable the slide
client/input.lua resolves the key once at load, cannot resolve nil, prints unknown key "nil" - falling back to C and binds C instead — so the slide carries on, on a key you did not pick. Config.MenuKey has nothing to do with the slide either: it is only the key that opens the panel, and setting it to nil leaves /combatmoves as the way in.
To stop a feature loading at all, remove its file from client_scripts in fxmanifest.lua and set the matching Config.Menu.pages key to false. The menu does not notice a missing file — its tab list is static, so the tab stays. The Tricks and Dive pages call the feature's exports while building their rows, so they fail as soon as a player opens the tab: openPage catches it, prints [combat_moves] menu page failed: ... and closes the whole menu rather than dropping the one page. The Slide and Roll pages build without touching any export, so they open normally and only fail when a row is actually used.
Keep four files whatever you remove
client/natives.lua, client/keys.lua, client/input.lua and client/menu.lua. input.lua is the only definition of CS.Input, which slide.lua calls; menu.lua is what cs_menuids reads.
That is the minimum, not a guarantee — the four feature files also call each other's exports, unguarded. roll.lua calls IsSliding(); guntricks.lua calls IsSliding() and IsRolling(); dive.lua calls all three. Remove slide.lua and rolling, spinning and diving all break. Only dive.lua can be dropped without taking a sibling with it.
Things worth tuning
| Setting | Default | Why you might change it |
|---|---|---|
Config.MinSpeed | 2.5 | raise it so only a full sprint can slide |
Config.RequireSprint | false | true requires an actual sprint, not a jog |
Config.Cooldown | 750 | raise it to stop slide-spamming in a fight |
Config.StaminaDrainRate | 2.0 | make sliding cost something |
Config.Roll.cooldown | 900 | the equivalent for rolls |
Config.Dive.cooldown | 800 | and for dives |
Config.Dive.enableIFramesDuringDive | true | invincibility while airborne — consider turning this off for PvP |
Config.Dive.minStaminaToDive | 10.0 | gates diving on stamina |
Config.GunTricks.requirePistol | true | false lets anything be spun |
Config.GunTricks.key | 'N' | push-to-talk — change it on a voice server |
Config.MenuMouse | true | false makes the menu keyboard-only and leaves mouse look alone |
Config.Debug | true | must be false in production |
enableIFramesDuringDive is the one to think hardest about
It makes the player bullet, fire and melee proof for the length of a dive. That is good for cinematic play and exploitable in serious PvP. The dive already costs 9 stamina and needs at least 10 to start, which is the only other brake on it.
Before you go live
- [ ]
Config.Debug = false— it shipstrue, and prints a report to every player's console after every move - [ ]
setr combat_slide_allow_timescale "false"inserver.cfg - [ ] Decide on
Config.Dive.enableIFramesDuringDive - [ ] Change
Config.GunTricks.keyoffNif you run voice chat - [ ] Decide what
Config.Menuexposes, then consider hidingmenu.pages - [ ] Cooldowns set for your server's pace
- [ ] Test the menu opens and closes cleanly, and that
/unstuckworks
Performance
The resource is client-side only. There is no server tick, no database query and no network traffic beyond the normal replication of a character's animations.
Each feature runs an idle loop that waits on an input and does nothing else. The per-frame work — camera, controls, animation state — only happens while a move is actually in progress, which is at most a second or two at a time. When nobody is sliding, rolling, spinning or prone, the resource costs effectively nothing.
Turning Config.Debug off removes the per-move console reports. The two diagnostic threads only exist while a player is running cs_watch or cs_dive, and stop with cs_watch off / cs_dive off.
Running alongside other resources
It touches no framework, so it coexists with VORP, RSG Core, RedEM:RP, QBR and standalone setups without configuration.
What could conflict:
- Anything that calls
ClearPedTaskson the local player every frame will interrupt a move mid-animation. - Anything that takes over the camera will fight the slide and dive cameras. Set
Config.CustomCamera = falseandConfig.Dive.enableProneCamera = false/enableDiveCamera = falseto hand the camera back. - Anything that disables control groups every frame may swallow the inputs.
If a move half-plays and snaps back, suspect one of those first. cs_watch shows live control and ped state, which usually identifies the culprit in a few seconds.
Security notes
The resource is client-side, which means a player with a modified client can set any value in their own copy of config.lua. That is true of every client-side resource. What it does and does not mean here:
- They can only affect their own character. The moves are played as animation tasks on their own ped. There is no event another client acts on, because there is no server script and no net events the resource sends.
- The four convars are read from the server, freshly on every slide, so
allow_timescale,allow_deadeye,allow_infiniteandmax_durationare genuinely not under the player's control.max_durationonly bounds a finite slide, so pair it withallow_infiniteset tofalse. - Everything else is advisory. Cooldowns, stamina costs, invincibility during a dive — assume a determined player can remove those limits for themselves, and set
Config.Dive.enableIFramesDuringDive = falseon principle if your server is competitive PvP.
There are four net events the resource listens on (combat_slide:setEnabled and its three siblings) so your own scripts can enable and disable features. They only ever turn things on or off for the client that receives them.
The cs_* commands are always registered
Config.Debug gates console printing, not command registration — so the 28 diagnostic commands exist on every client whether it is on or off. They are client-side and only act on the player running them: the worst a player can do with them is change their own animation flags or camera values, which they could already do by editing their own config.lua. The useful consequence is that /unstuck works in production. See Debug commands.