Gridbase
Paid releasesDime SkillsGuides

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-100

Level Caps

Choose realistic max levels:

-- Quick progression (minigames)
lvlMax = 15-20

-- Standard progression
lvlMax = 30-40

-- Long-term progression
lvlMax = 50-100

Registration 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:

  1. Column Created: New database column added to player_skills table
  2. Default Values: All existing players get default values (level 1, 0 XP)
  3. Automatic Sync: Configuration synced to all clients
  4. 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 rewardMax isn't too low
  • Verify skill name in addEXP matches 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
end

VIP/Donator Skills

-- Skills for VIP players only
RegisterNetEvent('player:becameVIP', function()
    -- Could register VIP-only skills or just adjust existing ones
end)