Custom Skills Guide
Create and register custom skills dynamically
Custom Skills Guide
This guide explains how to create and register custom skills dynamically using the addSkill export.
Overview
Custom skills allow you to:
- Add server-specific skills at runtime
- Create job-specific progression systems
- Extend the skill system without modifying core files
- Integrate with custom resources
Creating Custom Skills
Basic Structure
Use the addSkill export to register a new skill:
exports.dime_skills:addSkill({
name = 'skill_identifier',
label = 'Display Name',
description = 'Skill description',
category = 'Category Name',
icon = 'fontawesome-icon',
levels = {
lvlMulti = { default = 2.5 },
lvlMax = 30
},
rewardMax = 50,
reduceMax = 50
})When to Register
Register skills during server startup:
-- In your resource's server.lua
CreateThread(function()
Wait(5000) -- Wait for dime_skills to initialize
exports.dime_skills:addSkill({
-- Your skill configuration
})
end)Don't register skills dynamically during gameplay. Always register on server start.
Skill Configuration
Required Properties
Prop
Type
name Examples
name = 'hacking' -- ✓ Good
name = 'hack skill' -- ✗ Bad (contains space)category Options
Common categories:
'Character'- Personal attributes'Crafting'- Creation skills'Jobs'- Job-specific skills'Illegal'- Criminal skills
Optional Properties
Prop
Type
Find icons at: fontawesome.com/icons
Levels Configuration
Action Configuration
Degradation Configuration
Complete Examples
Hacking Skill
exports.dime_skills:addSkill({
name = 'hacking',
label = 'Hacking',
description = 'Bypass security systems and access restricted data.',
category = 'Illegal',
icon = 'laptop-code',
iconColor = '#10B981',
levels = {
lvlMulti = {
default = 3.0,
[1] = 1.5,
[2] = 2.0,
[3] = 2.5
},
lvlMax = 40
},
rewardMax = 30,
reduceMax = 15,
action = {
event = 'hacking:levelUp'
}
})Fishing Skill
exports.dime_skills:addSkill({
name = 'fishing',
label = 'Fishing',
description = 'Master the art of fishing to catch rare fish.',
category = 'Character',
icon = 'fish',
iconColor = '#3B82F6',
levels = {
lvlMulti = { default = 2.0 },
lvlMax = 30
},
rewardMax = 25,
reduceMax = 10
})Job-Locked Skill
exports.dime_skills:addSkill({
name = 'advanced_mechanics',
label = 'Advanced Mechanics',
description = 'Master advanced vehicle repair and customization.',
category = 'Jobs',
icon = 'wrench',
job = 'mechanic', -- Only mechanics
levels = {
lvlMulti = { default = 2.5 },
lvlMax = 35
},
rewardMax = 40,
reduceMax = 20
})Skill with Degradation
exports.dime_skills:addSkill({
name = 'lockpicking',
label = 'Lockpicking',
description = 'Pick locks with speed and precision.',
category = 'Illegal',
icon = 'key',
levels = {
lvlMulti = { default = 2.0 },
lvlMax = 25,
degrade = {
enable = true,
timer = 336, -- 2 weeks
amount = 100
}
},
rewardMax = 30,
reduceMax = 15
})Integration Examples
Complete Resource Integration
-- In your resource's server.lua
CreateThread(function()
-- Wait for dime_skills to load
Wait(5000)
-- Register your skill
exports.dime_skills:addSkill({
name = 'mining',
label = 'Mining',
description = 'Extract valuable minerals from the earth.',
category = 'Jobs',
icon = 'pickaxe',
levels = {
lvlMulti = { default = 2.0 },
lvlMax = 50
},
rewardMax = 25,
reduceMax = 10
})
print('[Mining] Skill registered successfully')
end)
-- Grant XP when player mines
RegisterNetEvent('mining:oreCollected', function(oreType)
local xpAmounts = {
copper = 5,
iron = 10,
gold = 20,
diamond = 50
}
local xp = xpAmounts[oreType] or 5
exports.dime_skills:addEXP(source, 'mining', xp)
end)
-- Check skill level before allowing action
RegisterNetEvent('mining:attemptAdvancedMine', function(nodeId)
local skill = exports.dime_skills:grabSkill(source, 'mining')
if not skill or skill.level < 25 then
TriggerClientEvent('ox_lib:notify', source, {
type = 'error',
description = 'Requires Mining Level 25'
})
return
end
-- Allow advanced mining
TriggerClientEvent('mining:startAdvanced', source, nodeId)
end)Level-Up Events
-- Register skill with level-up event
exports.dime_skills:addSkill({
name = 'hacking',
-- ... other config
action = {
event = 'hacking:levelUp'
}
})
-- Handle level-up event
RegisterNetEvent('hacking:levelUp', function()
local _source = source
local skill = exports.dime_skills:grabSkill(_source, 'hacking')
-- Grant rewards based on level
if skill.level == 10 then
-- Unlock basic hacking
TriggerClientEvent('hacking:unlockBasic', _source)
elseif skill.level == 25 then
-- Unlock advanced hacking
TriggerClientEvent('hacking:unlockAdvanced', _source)
elseif skill.level == 40 then
-- Unlock master hacking
TriggerClientEvent('hacking:unlockMaster', _source)
end
-- Special notification
TriggerClientEvent('ox_lib:notify', _source, {
type = 'success',
title = 'Hacking Level Up!',
description = ('Reached level %d'):format(skill.level)
})
end)Progressive Difficulty System
-- Register skill
exports.dime_skills:addSkill({
name = 'fishing',
label = 'Fishing',
-- ... config
})
-- Progressive rewards based on player level
RegisterNetEvent('fishing:catchFish', function(fishDifficulty)
local skill = exports.dime_skills:grabSkill(source, 'fishing')
if not skill then return end
-- Calculate XP based on difficulty and player level
local baseXP = fishDifficulty * 5
local levelDiff = fishDifficulty - skill.level
local finalXP
if levelDiff > 0 then
-- Harder than player level = more XP
finalXP = baseXP * (1 + (levelDiff * 0.2))
else
-- Easier than player level = less XP
finalXP = baseXP * math.max(0.5, 1 - (math.abs(levelDiff) * 0.1))
end
exports.dime_skills:addEXP(source, 'fishing', math.floor(finalXP))
end)Multiple Skills System
Register multiple related skills:
CreateThread(function()
Wait(5000)
-- Illegal skills category
local illegalSkills = {
{
name = 'lockpicking',
label = 'Lockpicking',
description = 'Pick locks with precision.',
icon = 'key'
},
{
name = 'hacking',
label = 'Hacking',
description = 'Bypass security systems.',
icon = 'laptop-code'
},
{
name = 'carjacking',
label = 'Carjacking',
description = 'Steal vehicles efficiently.',
icon = 'car'
}
}
for _, skillData in ipairs(illegalSkills) do
exports.dime_skills:addSkill({
name = skillData.name,
label = skillData.label,
description = skillData.description,
category = 'Illegal',
icon = skillData.icon,
iconColor = '#EF4444',
levels = {
lvlMulti = { default = 2.5 },
lvlMax = 30
},
rewardMax = 30,
reduceMax = 15
})
end
print('Registered ' .. #illegalSkills .. ' illegal skills')
end)Best Practices
Naming Convention
Use clear, descriptive names:
-- Good
name = 'hacking'
name = 'advanced_mechanics'
name = 'lockpicking'
-- Bad
name = 'skill1'
name = 'test'
name = 'my skill' -- No spaces!Balanced Progression
Set appropriate XP limits:
-- Frequent actions
rewardMax = 10-20
-- Moderate actions
rewardMax = 25-40
-- Rare actions
rewardMax = 50-100Level Caps
Choose realistic max levels:
-- Quick progression (minigames)
lvlMax = 15-20
-- Standard progression
lvlMax = 30-40
-- Long-term progression
lvlMax = 50-100Registration Timing
CreateThread(function()
-- Wait for dime_skills
Wait(5000)
-- Check if dime_skills exists
if GetResourceState('dime_skills') ~= 'started' then
print('[ERROR] dime_skills not found!')
return
end
-- Register skills
exports.dime_skills:addSkill({...})
end)Database Integration
When you register a skill:
- Column Created: New database column added to
player_skillstable - Default Values: All existing players get default values (level 1, 0 XP)
- Automatic Sync: Configuration synced to all clients
- Persistence: Skill data saved automatically
Troubleshooting
Skill Not Appearing
- Wait at least 5 seconds after server start
- Check console for registration messages
- Verify skill name is unique
- Ensure dime_skills is started
- Try restarting both resources
XP Not Granting
- Check
rewardMaxisn't too low - Verify skill name in
addEXPmatches registered name - Enable Debug mode in config
- Check console for errors
Job Restriction Not Working
- Verify job name matches framework
- Check player has correct job
- Ensure framework bridge is working
- Test without job restriction first
Advanced Patterns
Dynamic Skill Unlocking
-- Unlock skills based on story progression
RegisterNetEvent('story:chapterComplete', function(chapter)
if chapter == 3 then
exports.dime_skills:addSkill({
name = 'special_ability',
label = 'Special Ability',
-- ... config
})
end
end)Seasonal Skills
-- Register seasonal skills
local function registerSeasonalSkills(season)
if season == 'winter' then
exports.dime_skills:addSkill({
name = 'ice_fishing',
label = 'Ice Fishing',
-- ... config
})
end
endVIP/Donator Skills
-- Skills for VIP players only
RegisterNetEvent('player:becameVIP', function()
-- Could register VIP-only skills or just adjust existing ones
end)Related
- Server Exports - API reference
- Configuration - Config options
- Skills System - How skills work