# Configuration > Configuration reference for ML Skills Category: SKILLS · Source: https://miciomods.it/docs/ml-skills-configuration · Last updated: 2026-07-28 ## Overview - `shared/config.lua`: UI behavior, XP curves, listeners, prestige, admin permission - `server/config_server.lua`: Webhooks, log provider, rate-limit cooldown Most servers never need to touch the listener caps. The defaults match a balanced survival/RP economy. ## UI / Open Behavior **shared/config.lua** ```lua Config.OpenCommand = 'skills' Config.OpenKey = 'J' Config.DefaultCategory = 'personal' Config.UnifiedView = true ``` - `OpenCommand`: Chat command that opens the tree - `OpenKey`: Keybind that opens the tree. Any FiveM input name is accepted - `DefaultCategory`: Category shown when the UI opens. `'all'` opens the unified view; any category UID jumps straight to that tree - `UnifiedView`: When `true`, all categories render on one scrollable canvas. When `false`, the sidebar switches between separate canvases per category ## Theme & Visuals **shared/config.lua** ```lua Config.Theme = 'default' Config.MainColor = nil Config.UIOpacity = 0.85 Config.LockedPreviewGrayscale = true ``` - `Theme`: One of `'default'`, `'cyberpunk'`, `'wasteland'`, `'noir'`, `'fantasy'` - `MainColor`: Hex string (e.g. `'#ff8800'`) that overrides the theme accent. `nil` falls back to the theme default - `UIOpacity`: Background opacity of the tree panel, from `0.0` to `1.0` - `LockedPreviewGrayscale`: When `true`, the hover preview image renders grayscale until the skill is unlockable ## XP Notifications **shared/config.lua** ```lua Config.XpNotification = 'toast' Config.XpToastPosition = 'bottom' Config.XpToastDuration = 3000 ``` - `XpNotification`: `'toast'` shows the floating in-panel toast; `'bridge'` routes through `Bridge.Notify` for system-style notifications; `false` disables XP notifications entirely - `XpToastPosition`: `'top'`, `'bottom'`, or `'center'` - `XpToastDuration`: Toast display time in ms ## Performance / LOD **shared/config.lua** ```lua Config.PerformanceMode = 'auto' Config.LodZoomThreshold = 0.45 Config.LodNodeThreshold = 120 ``` - `PerformanceMode`: `'auto'` (recommended), `'quality'` (always full detail), `'performance'` (LOD always on for low-end rigs) - `LodZoomThreshold`: Below this zoom level the canvas switches to simple nodes - `LodNodeThreshold`: When more than this many nodes are visible, heavy animations pause ## XP Curve **shared/config.lua** ```lua Config.DefaultXpBase = 400 Config.DefaultXpMultiplier = 1.12 Config.DefaultMaxLevel = 50 Config.PointsPerLevel = 1 Config.UnifiedPoints = false Config.XpPerLevelCap = 20000 ``` - `DefaultXpBase`: Base XP required for level 1 - `DefaultXpMultiplier`: Exponential scaling per level. Required XP for level N is `base * multiplier^N` - `DefaultMaxLevel`: Global maximum level - `PointsPerLevel`: Skill points granted per level up - `UnifiedPoints`: When `true`, all categories share one point pool. When `false`, each category has its own pool - `XpPerLevelCap`: Hard cap on the XP required to clear a single level. Once the exponential curve crosses this value, every later level costs exactly `XpPerLevelCap`. Set `0` to disable Each category in `Config.Categories` can override `xpBase`, `xpMultiplier` and `maxLevel`. ## Categories **shared/config.lua** ```lua Config.Categories = { personal = { label = _L('cat_personal'), icon = 'user', xpBase = 400, xpMultiplier = 1.12, maxLevel = 50 }, } Config.DisabledCategories = {} ``` - Each entry keys on the category UID, the same string used everywhere in the API - `label`: Display name, supports `_L('key')` for localization - `icon`: Lucide icon name (`user`, `anvil`, `swords`, `crosshair`, etc.) - `xpBase`, `xpMultiplier`, `maxLevel`: Per-category overrides for the curve - `DisabledCategories`: Keys listed here are stripped at boot from `Config.Categories`, `Config.DefaultTrees` and `Config.XpListeners`. Useful to ship a default tree but hide it on a specific server ## XP Listeners Passive XP awarded by the client when the player performs an action. The server validates the timing, the movement, and enforces the daily cap. **shared/config.lua** ```lua Config.XpListeners = { driving = { category = 'personal', xp = 1, interval = 30000, intervalJitter = 6000, condition = function() local veh = cache.vehicle if not veh or veh == 0 then return false end if GetPedInVehicleSeat(veh, -1) ~= cache.ped then return false end return GetEntitySpeed(veh) > 5.0 end, }, } ``` - `category`: Category UID the XP is awarded to - `xp`: XP amount per trigger - `interval`: Base check interval in ms - `intervalJitter`: Random `±` jitter added on every wait. Each tick waits between `interval - jitter` and `interval + jitter` - `condition`: Function returning `true` when the activity is happening. Uses `cache.ped` and `cache.vehicle` from `ox_lib` - `requiresMovement`: Optional. Defaults to `true`. Set `false` for an activity done standing still (shooting from cover, or a kill relayed by another resource), otherwise the server drops the claim as AFK farming - `movementDistance`: Optional metres the ped must cover between two grants of this listener. Default `0.5` - `cooldown`: Optional minimum ms between two grants of this listener. Defaults to `interval - intervalJitter` capped at `5000`, and never goes below `1000` Built-in listeners: `driving`, `swimming`, `sprinting`, `shooting`, `flying`. Replace, extend, or remove any of them. A listener with no `interval` and no `condition` never fires by itself. It is the whitelist entry a client script requests by name through `exports.ml_skills:RequestXp(categoryUid, amount, listenerName)`, which is how a client-side event awards XP without trusting the client with an amount. ## Listener Anti-Abuse **shared/config.lua** ```lua Config.XpListenerCapPerMinute = 60 Config.XpListenerDailyCapPerCategory = 50000 Config.XpListenerMovementCheck = true ``` - `XpListenerCapPerMinute`: Hard cap on listener XP per minute per category, server-enforced. Listeners are activity hints sent by the client, so this value is what bounds a spoofed claim. Size it on the listeners a single player can trigger at once: the shipped set stays under 40 per minute - `XpListenerDailyCapPerCategory`: Daily hard cap per category - `XpListenerMovementCheck`: When `true`, the server rejects listener XP if the ped has not moved since the previous fire. Listeners that set requiresMovement = false are exempt ## Daily XP Cap **shared/config.lua** ```lua Config.DailyXpCap = { enabled = false, globalPerDay = 0, perCategoryPerDay = 0, resetMode = 'fixed', resetHour = 0, showInUI = true, notifyOnCap = true, } ``` Opt-in ceiling on how much XP a player can earn per day. It applies to every gain routed through `AddXp` (listeners, integrations, skill events); admin give/remove and `SetLevel` are exempt. - `enabled`: Master switch. Off by default, so there is no daily cap until you turn it on. - `globalPerDay`: Max total XP per day across all categories. `0` = unlimited. - `perCategoryPerDay`: Default daily ceiling per category. `0` = unlimited. Override one category with `Config.Categories[uid].dailyXpCap`, or scale it by level with `Config.Categories[uid].dailyXpCapTiers` (a list of `{ minLevel, cap }` bands; the highest band at or below the player level wins). Tiers take precedence over a flat cap. - `resetMode`: `'fixed'` resets every day at `resetHour`; `'rolling'` resets 24h after the player's first XP of the cycle. - `resetHour`: Hour (0-23, server local time) of the fixed reset. - `showInUI`: Show the Daily XP usage indicator inside the skill UI. - `notifyOnCap`: Notify the player when the daily limit is reached. ## Admin Permission **shared/config.lua** ```lua Config.AdminPermission = { level = 'admin', ace = nil, } ``` - `level`: `ml_bridge` permission level required for the Player Manager and the tree editor. Common values: `'admin'`, `'god'`, `'mod'` or `'mod'` - `ace`: Optional ACE permission (e.g. `'ml_skills.admin'`). When set, ACE takes precedence over the Bridge level ## Reset & Wipe Permissions **shared/config.lua** ```lua Config.AllowReset = false Config.AdminAllowResetSkills = true Config.AdminAllowFullWipe = true ``` - `AllowReset`: When `true`, players can reset their own skill points from the UI - `AdminAllowResetSkills`: When `true`, the Player Manager exposes the per-category reset action - `AdminAllowFullWipe`: When `true`, the Player Manager exposes the full wipe action ## Prestige **shared/config.lua** ```lua Config.PrestigeEnabled = false Config.PrestigeBonus = 0.10 Config.MaxPrestige = 5 ``` - `PrestigeEnabled`: Master switch. When `false`, no prestige UI shows up - `PrestigeBonus`: XP multiplier added per prestige level. `0.10` = `+10%` per tier - `MaxPrestige`: Maximum prestige levels achievable ## External Export Gate **shared/config.lua** ```lua Config.EnableUnlockSkillExport = true ``` - `EnableUnlockSkillExport`: When `true`, other resources can call `exports.ml_skills:UnlockSkill(catUid, skillUid, src)`. Set `false` to lock unlocks to the in-UI flow ## Skill Default Values **shared/config.lua** ```lua Config.SkillDefaultValues = { moreStamina = 100.0, moreMaxHp = 200, timeUnderwater = 10.0, } ``` GTA-default values used by `open/effects.lua` handlers as the baseline for percentage-based skill effects. Override these only when another resource modifies the same natives. ## HP Regeneration **shared/config.lua** ```lua Config.HpRegen = { idleSeconds = 300, maxRegenPercent = 25, tickHp = 1, tickMs = 5000, breakOnSprint = true, breakOnShoot = true, breakOnVehicle = true, breakOnDamage = true, notifyOnStart = true, disableNativeRegen = false, } ``` Powers the `hpRegeneration` perks in the personal tree: a slow out-of-combat heal that begins after the player has been still for `idleSeconds` and tops out at `maxRegenPercent` of the playable HP range. - `idleSeconds`: Idle time before regen begins (`300` = 5 minutes). - `maxRegenPercent`: Regen ceiling as a percent of the HP range (`25` stops at 125 HP). - `tickHp` / `tickMs`: HP restored per tick (multiplied by the skill effect) and the tick interval. - `breakOnSprint` / `breakOnShoot` / `breakOnVehicle` / `breakOnDamage`: Any of these resets the idle timer. - `notifyOnStart`: Notify the player the moment regen kicks in. - `disableNativeRegen`: Suppresses GTA's native HP regen. Leave `false` if another script (ml_healthsystem, esx_basicneeds) manages regen; ml_skills auto-skips it when ml_healthsystem is detected. ## Achievements **shared/config.lua** ```lua Config.Achievements = { firstSkill = { label = _L('achievement_first_step'), description = _L('achievement_first_step_desc'), icon = 'star', condition = { type = 'skills_unlocked', count = 1 }, rewards = { { item = 'bread', count = 3 }, }, }, } ``` Achievements declared here are seeded into the `ml_skills_achievements` table on first start. After seeding, the in-game achievement editor becomes the source of truth. - `condition.type`: `'skills_unlocked'`, `'skill_unlocked'`, or `'level_reached'` - `condition.count`: Used by `'skills_unlocked'` and `'level_reached'` - `condition.skillId` / `condition.category`: Used by `'skill_unlocked'` - `rewards`: Array of `{ item, count }` or `{ cash = N }` / `{ bank = N }` ## Webhooks **server/config_server.lua** ```lua ServerConfig.Webhook = '' ServerConfig.Webhooks = { player_skill_unlock = '', player_claim_reward = '', player_claim_achievement = '', player_prestige = '', player_reset_skills = '', player_reset_category = '', admin_give_xp = '', admin_remove_xp = '', admin_set_level = '', admin_give_points = '', admin_remove_points = '', admin_reset_skills = '', admin_full_wipe = '', admin_unlock_skill = '', admin_save_tree = '', admin_save_categories = '', admin_save_achievement = '', admin_delete_achievement = '', external_unlock_skill = '', security_devtools = '', } ServerConfig.LogProvider = 'discord' ServerConfig.RateLimitCooldown = 1000 ``` - `Webhook`: Generic fallback used when a specific slot is empty - `Webhooks.`: Dedicated webhook per action category - `LogProvider`: `'discord'`, `'fivemanage'`, `'ox_lib'`, `'both'`, or `'all'` - `RateLimitCooldown`: Minimum ms between two UI actions from the same player Set any webhook to `false` to disable that log entirely.