# Developer > Hooks and integration for ML Recoil Category: RECOIL · Source: https://miciomods.it/docs/ml-recoil-developer · Last updated: 2026-07-28 ## Overview ml_recoil exposes no public exports and no commands. Integration happens through four overridable hooks on the client (`client/main_open.lua`) and four on the server (`server/server_open.lua`), plus a single internal callback the client uses to fetch a server-resolved multiplier. All hooks are plain global functions you edit in place; both files are escrow-ignored. ## How the multiplier flows On weapon equip, the client reads `Config.XPSystem.Type`. With `'client'` it calls `GetClientSkillMultiplier(skillName)` locally. With `'server'` it triggers the callback `ml_recoil:getSkillMultiplier`, which runs `GetPlayerSkillMultiplier(source, skillName)` on the server. The returned number scales every recoil value: below 1.0 steadies the aim, above 1.0 makes recoil harder. ## Client Hooks Defined in `client/main_open.lua`. - `GetClientSkillMultiplier(skillName)`: returns the local multiplier. Ships an ml_skills integration that trims 10% recoil per `betterAccuracy` rank. - `OnWeaponEquipped(weaponHash, weaponData)`: fires when a configured weapon is equipped. Return `false` to skip recoil for it. - `OnShotFired(weaponHash, totalMultiplier)`: fires after every shot with the final applied multiplier. A good place to award shooting XP. - `OnAimStateChanged(weaponHash, isAiming)`: fires when the player starts or stops aiming down sights. **client/main_open.lua** ```lua function GetClientSkillMultiplier(skillName) local multiplier = 1.0 if Config.XPSystem.Enabled and GetResourceState('ml_skills') == 'started' then local ok, effect = pcall(function() return exports.ml_skills:GetActiveEffect('betterAccuracy') end) if ok and type(effect) == 'number' and effect > 0 then multiplier = math.max(0.1, 1.0 - (0.1 * effect)) end end return multiplier end ``` ## Server Hooks Defined in `server/server_open.lua`. Used when `Config.XPSystem.Type = 'server'`. - `GetPlayerSkillMultiplier(source, skillName)`: returns the multiplier for a player. Wire your own skill lookup here. - `ServerSkillToMultiplier(level)`: helper that maps a 0-100 level to a multiplier (1.5 untrained, 1.0 default, 0.5 master). - `ValidateWeaponAccess(source, weaponHash)`: return `false` to force the maximum recoil penalty (2.0) on a player as an anti-cheat gate. - `LogWeaponUsage(source, weaponHash, skillName, multiplier)`: called once per skill lookup; hook analytics or logging here. **server/server_open.lua** ```lua function GetPlayerSkillMultiplier(source, skillName) if not Config.XPSystem.Enabled then return 1.0 end -- local level = exports.ml_skills:GetPlayerLevel(skillName, source) -- return ServerSkillToMultiplier(level) return 1.0 end ``` ## Examples **Award shooting XP on every shot (client)** Edit `OnShotFired` in `client/main_open.lua`. **client/main_open.lua** ```lua function OnShotFired(weaponHash, totalMultiplier) exports.ml_skills:RequestXp('personal', 2, 'shooting') end ``` **Resolve the multiplier server-side from ml_skills** Set `Config.XPSystem.Type = 'server'` and edit `GetPlayerSkillMultiplier`. **server/server_open.lua** ```lua function GetPlayerSkillMultiplier(source, skillName) if not Config.XPSystem.Enabled then return 1.0 end local level = exports.ml_skills:GetPlayerLevel(skillName, source) return ServerSkillToMultiplier(level) end ``` **Skip recoil for a specific weapon** Return `false` from `OnWeaponEquipped` for the hashes you want untouched. **client/main_open.lua** ```lua function OnWeaponEquipped(weaponHash, weaponData) if weaponHash == `WEAPON_REVOLVER` then return false end return true end ```