Skip to content

Extending the System

Artmines edited this page Nov 3, 2025 · 1 revision

Extending the System

Guide for customizing and extending QC-AdvancedMedic with new weapons, treatments, body parts, and custom features.


Adding New Weapons

Step-by-Step

  1. Open config.lua
  2. Find Config.WeaponDamage (around line 337)
  3. Add your weapon entry:
['WEAPON_YOUR_GUN'] = {
    bleedingAmount = 5,              -- 0-10 scale
    painAmount = 6,                  -- 0-10 scale
    hitChance = 0.9,                 -- 0.0-1.0 (90% hit detection)
    canLodge = true,                 -- Can bullet lodge in body?
    ballisticType = 'rifle',         -- handgun, rifle, shotgun
    description = 'Custom gun wound description'
},
  1. Save and restart resource - weapon is automatically detected

Ballistic Types

  • handgun - Uses handgun ballistic ranges (high lodge chance at distance)
  • rifle - Uses rifle ballistic ranges (lower lodge chance, higher penetration)
  • shotgun - Spawns multiple pellets based on Config.BallisticRanges.shotgun.pelletCount

Example: Custom Sniper Rifle

['WEAPON_CUSTOM_SNIPER'] = {
    bleedingAmount = 8,              -- Very high bleeding
    painAmount = 9,                  -- Extreme pain
    hitChance = 0.95,                -- High accuracy
    canLodge = true,
    ballisticType = 'rifle',
    description = 'High-caliber sniper rifle wound - severe tissue damage'
},

Adding New Treatment Items

1. Add to Config

For Bandages:

-- In config.lua
Config.BandageTypes['super_bandage'] = {
    label = "Super Bandage",
    itemName = "super_band",
    effectiveness = 100,             -- Best effectiveness
    oneTimeHeal = 30,                -- Restores 30 HP immediately
    bleedingReduction = 10,          -- Reduces bleeding by 10 levels
    painReduction = 10,              -- Reduces pain by 10 levels
    decayRate = 15,                  -- Lasts 15 minutes
    description = "Advanced medical bandage with enhanced clotting"
}

For Medicines:

-- In config.lua
Config.MedicineTypes['medicine_custom'] = {
    label = "Custom Medicine",
    effectiveness = 90,
    healAmount = 40,
    duration = 600,                  -- 10 minutes
    painReliefLevel = 9,
    sideEffects = {"euphoria", "drowsiness"},
    addictionRisk = 10               -- 10% addiction chance
}

2. Add Item to RSG-Core

-- In rsg-core/shared/items.lua
['super_band'] = {
    ['name'] = 'super_band',
    ['label'] = 'Super Bandage',
    ['weight'] = 150,
    ['type'] = 'item',
    ['image'] = 'super_band.png',
    ['unique'] = false,
    ['useable'] = true,
    ['shouldClose'] = true,
    ['description'] = 'Advanced medical bandage with enhanced clotting'
},

3. Add Item Image

Place super_band.png in your inventory images folder (typically rsg-inventory/html/images/)

4. Restart Resource

The item is automatically registered on server start - no code changes needed!


Adding New Body Parts

1. Add to Config

-- In config.lua
Config.BodyParts['CUSTOM_PART'] = {
    label = "Custom Body Part",
    maxHealth = 100,
    canLimp = false,                 -- Can this body part cause limping?
    bones = {12345}                  -- RedM bone ID
}

2. Update Bone Mapping

-- In client/wound_system.lua (around line 50)
local boneMapping = {
    [12345] = 'CUSTOM_PART',         -- Add your bone mapping
    [31086] = 'HEAD',
    -- ... existing bones
}

3. Update NUI

NUI source code is included in ui/src/. To add a new body part to the UI:

  1. Add body part image to ui/src/assets/imgs/custom_part.png
  2. Edit ui/src/components/MedicalPanel.tsx or InspectionPanel.tsx
  3. Add clickable region for the new body part
  4. Rebuild the UI:
    cd ui
    bun run build

Example: Adding a clickable body part in MedicalPanel.tsx:

<div
  className="body-part custom-part"
  onClick={() => handleBodyPartClick('CUSTOM_PART')}
  style={{
    backgroundImage: 'url(/assets/imgs/custom_part.png)',
    top: '100px',
    left: '150px'
  }}
/>

Adding New Infection Types

Custom Infection Category

-- In config.lua
Config.InfectionSystem.categories = Config.InfectionSystem.categories or {}

Config.InfectionSystem.categories['customInfection'] = {
    name = "Custom Infection",
    baseChance = 0.20,               -- 20% base chance
    symptoms = {
        "Custom symptom 1",
        "Custom symptom 2"
    }
}

Custom Cure Item

-- In config.lua
Config.InfectionSystem.cureItems['custom_cure'] = {
    label = "Custom Cure",
    itemName = "custom_cure",
    effectiveness = 50,              -- 50% cure progress per use
    immunityDuration = 45            -- 45 minutes immunity
}

Don't forget to add the item to rsg-core/shared/items.lua!


Creating Custom Exports

Client-Side Custom Export

-- In client/your_custom_file.lua
exports('GetCustomMedicalData', function()
    local wounds = exports['QC-AdvancedMedic']:GetPlayerWounds()
    local bleeding = exports['QC-AdvancedMedic']:GetBleedingLevel()

    -- Process and return custom data
    return {
        totalWounds = #wounds,
        totalBleeding = bleeding,
        isDying = bleeding > 8
    }
end)

Usage from another resource:

local data = exports['QC-AdvancedMedic']:GetCustomMedicalData()
print(string.format("Player has %d wounds", data.totalWounds))

Server-Side Custom Export

-- In server/your_custom_file.lua
exports('GetPlayerMedicalSummary', function(citizenid)
    local profile = exports['QC-AdvancedMedic']:GetCompleteMedicalProfile(citizenid)

    local summary = {
        wounds = 0,
        infections = 0,
        fractures = 0,
        scars = 0
    }

    for _, wound in pairs(profile.wounds or {}) do
        if wound.is_scar then
            summary.scars = summary.scars + 1
        else
            summary.wounds = summary.wounds + 1
        end
    end

    for _ in pairs(profile.infections or {}) do
        summary.infections = summary.infections + 1
    end

    for _ in pairs(profile.fractures or {}) do
        summary.fractures = summary.fractures + 1
    end

    return summary
end)

Custom Progression Logic

Custom Wound Progression

-- In client/wound_system.lua (modify existing progression thread)
CreateThread(function()
    while true do
        Wait(Config.WoundProgression.bleedingProgressionInterval * 60000)

        for bodyPart, wound in pairs(PlayerWounds) do
            if not wound.isScar then
                -- Your custom progression logic
                if someCustomCondition then
                    wound.bleedingLevel = wound.bleedingLevel + 2
                end

                TriggerServerEvent('QC-AdvancedMedic:server:UpdateWoundData', PlayerWounds)
            end
        end
    end
end)

Custom Healing Logic

-- Create new file: client/custom_healing.lua
-- Add to fxmanifest.lua client_scripts

CreateThread(function()
    while true do
        Wait(60000) -- Check every minute

        local wounds = exports['QC-AdvancedMedic']:GetPlayerWounds()

        for bodyPart, wound in pairs(wounds) do
            -- Custom healing condition
            if wound.bleedingLevel == 1 and yourCustomCondition then
                -- Heal wound to scar
                exports['QC-AdvancedMedic']:RemoveWound(bodyPart)
                exports['QC-AdvancedMedic']:CreateScar(bodyPart, {
                    scarType = 'custom_scar',
                    description = 'Custom healed wound'
                })
            end
        end
    end
end)

Integrating with Other Systems

Death System Integration

-- In your death script
AddEventHandler('baseevents:onPlayerDied', function(killerId, deathData)
    local bleeding = exports['QC-AdvancedMedic']:GetBleedingLevel()

    if bleeding > 8 then
        -- Died from bleeding out
        print("Player bled to death")
    else
        -- Died from other causes
        print("Player died from other cause")
    end
end)

Hospital/Clinic Integration

-- In your hospital script
RegisterNetEvent('hospital:checkin', function()
    local wounds = exports['QC-AdvancedMedic']:GetPlayerWounds()

    -- Calculate treatment cost based on injuries
    local cost = 0
    for bodyPart, wound in pairs(wounds) do
        if not wound.isScar then
            cost = cost + (wound.painLevel * 10)
            cost = cost + (wound.bleedingLevel * 20)
        end
    end

    -- Heal all wounds for payment
    if PlayerHasMoney(cost) then
        exports['QC-AdvancedMedic']:ClearAllWounds()
        RemoveMoney(cost)
    end
end)

Needs System Integration (Hunger/Thirst)

-- In your needs script
CreateThread(function()
    while true do
        Wait(60000) -- Check every minute

        local wounds = exports['QC-AdvancedMedic']:GetPlayerWounds()
        local bleeding = exports['QC-AdvancedMedic']:GetBleedingLevel()

        -- Bleeding causes faster hunger/thirst drain
        if bleeding > 5 then
            DecreaseHunger(bleeding * 2)  -- Your hunger function
            DecreaseThirst(bleeding * 3)  -- Your thirst function
        end

        -- Infections cause thirst
        for bodyPart, wound in pairs(wounds) do
            local infection = exports['QC-AdvancedMedic']:GetInfectionData(bodyPart)
            if infection and infection.stage >= 3 then
                DecreaseThirst(infection.stage * 5)  -- Fever causes dehydration
            end
        end
    end
end)

Custom Commands

Medic Heal Command

-- In server/server.lua
RSGCore.Commands.Add('medicheal', 'Heal nearby player (Medic Only)', {{name = 'id', help = 'Player ID'}}, true, function(source, args)
    local Player = RSGCore.Functions.GetPlayer(source)

    if not IsMedicJob(Player.PlayerData.job.name) then
        return
    end

    local targetId = tonumber(args[1])
    local TargetPlayer = RSGCore.Functions.GetPlayer(targetId)

    if not TargetPlayer then
        return TriggerClientEvent('RSGCore:Notify', source, 'Player not found', 'error')
    end

    -- Clear all wounds
    TriggerClientEvent('QC-AdvancedMedic:client:ClearAllWounds', targetId)

    -- Log medical event
    exports['QC-AdvancedMedic']:LogMedicalEvent(
        TargetPlayer.PlayerData.citizenid,
        'admin_clear_wounds',
        nil,
        json.encode({healer = Player.PlayerData.citizenid}),
        Player.PlayerData.citizenid
    )

    TriggerClientEvent('RSGCore:Notify', source, 'Player healed', 'success')
    TriggerClientEvent('RSGCore:Notify', targetId, 'You have been healed by a medic', 'success')
end, 'medic')

← API Reference | Next: Performance Optimization →

📖 QC-AdvancedMedic

🏠 Home


📚 Documentation

  1. Architecture
  2. Client Systems
  3. Server Systems
  4. Database Schema

⚙️ Configuration

  1. Configuration
  2. Translation System
  3. API Reference

🛠️ Development

  1. Extending the System
  2. Performance Optimization

⚠️ Support

  1. Known Issues

🔗 Links


v0.3.1-alpha

Clone this wiki locally