# Config Files

{% tabs %}
{% tab title="config.lua" %}

```lua
Config = {}

-- Framework: 'qb' | 'esx' | 'standalone'
Config.Framework = GetConvar('izaap_framework', 'qb')
Config.Debug = false
-- Resource locale: 'es' | 'en'
Config.Locale = 'en'
-- Enable headshot down system
Config.HeadshotDown = true
-- Round duration in seconds
Config.RoundTimeSec = 120
-- Discord bot token used for real Discord avatars.
-- Leave empty to use a default avatar fallback.
Config.DiscordBotToken = "YOUR_BOT_TOKEN"


-- Revive integration
Config.ReviveIntegration = {
    enabled = true,
    -- Available options:
    -- 'auto'   = tries qb / hospital / esx, then native revive
    -- 'qb'     = forces QB / Hospital events
    -- 'esx'    = forces ESX events
    -- 'custom' = reserved for custom adaptation in integrations/revive.lua
    -- 'native' = uses only native revive
    provider = 'auto'
}

-- Inventory guard integration
Config.ArenaInventoryGuard = {
    Enabled = true,

    -- Supported values: "qb" | "ox" | "qs" | "esx"
    Inventory = "ox",

    -- Items preserved when entering a match
    KeepItems = {
        -- ["phone"] = true,
        -- ["radio"] = true,
    },

    -- Used for ESX classic loadout handling
    SaveWeaponsESX = true,
    Debug = false
}

-- GTA weapon name to inventory item override map.
-- By default, weapon names are resolved as weapon_xxx.
-- Override entries here if your inventory uses custom item names.
Config.WeaponItemOverrides = {
    -- ["WEAPON_PISTOL"] = "weapon_pistol",
    -- ["WEAPON_SMG"] = "weapon_smg",
}


Config.Tournaments = {
    Enabled = true,

    Command = 'torneo',

    AllowedLicenses = {
        --'license:c70da7d1b951554d2f69aae6632823642b0fa939',
    },

    MaxOpenTournaments = 10,

    InviteModes = {
        byId = true,
        allPlayers = true,
        radioRange = true
    },

    InviteRadius = 120.0,

    AllowedModes = {
        ['1v1'] = true,
        ['2v2'] = false,
        ['4v4'] = false
    },

    AllowedSizes = {
        ['1v1'] = { 2, 8, 16 },
        ['2v2'] = { 4, 8, 16 },
        ['4v4'] = { 8, 16 }
    },

    AutoSeedPlayers = true,
    AutoStartNextMatchDelay = 5000,

    InviteCooldowns = {
        byId = 0,          -- segundos
        allPlayers = 120,  -- segundos
        radioRange = 60    -- segundos
    },

    UI = {
        ShowStats = true
    }
}

Config.Tournaments.JoinControl = 170 -- F3
Config.Tournaments.JoinKeyLabel = "F3"
Config.Tournaments.NotifyDuration = 10000
Config.Tournaments.NotifyRadius = 60.0

-- Head and neck bones used by the headshot system
Config.HeadBones = {
    [31086] = true, -- Head
    [39317] = true, -- Neck 1
    [52301] = true, -- Neck 2

    -- Optional face / brow bones if your game build reports them
    [12844] = true,
    [17188] = true,
    [26610] = true,
    [65068] = true,
    [11174] = true,
    [1356]  = true,
}

-- Arena world lock settings
Config.ArenaWorldLock = {
    enabled = true,
    hour = 18,
    minute = 0,
    weather = "EXTRASUNNY"
}

-- Arena NPC settings
Config.NPC = {
    model = "s_m_m_highsec_01",
    prompt = "~y~[E]~w~ Open Matches",
    coord = vec4(-271.4685, -2027.3038, 30.1456, 260.2192)
}

-- Invite notification settings
Config.InviteNotification = {
    Enabled = true,
    JoinControl = 167,      -- F6
    JoinKeyLabel = "F6",
    DurationMs = 10000,
    Sound = true,

    UseRadius = true,
    Radius = 120.0
}

-- Enemy head marker settings
Config.EnemyHeadMarker = {
    enabled = true,
    markerType = 28,
    scaleX = 0.08,
    scaleY = 0.08,
    scaleZ = 0.08,
    alpha = 255,
    r = 255,
    g = 0,
    b = 0,
    maxDist = 200.0,
    updateMs = 500,
    zOffset = 0.95
}

-- Supported bet currencies
Config.BetCurrencies = {
    { key = "cash", label = "Cash", type = "cash" },
    { key = "bank", label = "Bank", type = "bank" },

    -- Example:
    -- { key = "vip", label = "VIP Coins", type = "vipcoins" },
}

-- Weapon catalog used by the NUI
Config.Weapons = {
    { name = "WEAPON_PISTOL",       label = "Pistol" },
    { name = "WEAPON_PISTOL_MK2",   label = "Pistol MK2" },
    { name = "WEAPON_COMBATPISTOL", label = "Combat Pistol" },
    { name = "WEAPON_PISTOL50",     label = "Pistol .50" },
    { name = "WEAPON_SMG_PDW",      label = "PDW SMG" },
    { name = "WEAPON_MICROSMG",     label = "Micro SMG" },
    { name = "WEAPON_SMG",          label = "SMG" },
    { name = "WEAPON_CARBINERIFLE", label = "Carbine Rifle" },
    { name = "WEAPON_COMPACTRIFLE", label = "Compact Rifle" },
    { name = "WEAPON_HEAVYSNIPER",  label = "Heavy Sniper" }
}

-- Arena maps
Config.Maps = {
    {
        key = "small",
        label = "Small",
        image = "https://r2.fivemanage.com/eDqO9cilMKCMzsiyN4KCx/Capturadepantalla2026-01-20170523.png",
        spawnA = vec4(123.0345, -879.6693, 134.7700, 68.5857),
        spawnB = vec4(80.2180, -863.3383, 134.7700, 242.4418),
    },
    {
        key = "medium",
        label = "Medium",
        image = "https://r2.fivemanage.com/sUslP5eNXi7xeMGd1QYsh/OIP.webp",
        spawnA = vec4(200.0, 200.0, 40.0, 0.0),
        spawnB = vec4(220.0, 220.0, 40.0, 180.0),
    },
    {
        key = "large",
        label = "Large",
        image = "nui://izaap_arenapvp/html/img/map3.png",
        spawnA = vec4(300.0, 300.0, 50.0, 45.0),
        spawnB = vec4(330.0, 330.0, 50.0, 225.0),
    },
}

-- Leaderboard ped groups
Config.LeaderboardGroups = {
    enabled = true,
    refreshMs = 60000,
    drawRadius = 2.0,
    fallbackModel = `mp_m_freemode_01`,

    labels = {
        wins  = "%s\nWins: %d",
        kills = "%s\nKills: %d",
        score = "%s\nScore: %d",
    },

    wins = {
        [1] = {
            coord = vec4(-269.8986, -2035.7838, 30.1456, 313.0613),
            textOffset = vec3(0, 0, 1.05),
            emote = { dict = "amb@world_human_cheering@male_a", name = "base", flag = 49 }
        },
        [2] = {
            coord = vec4(-269.0040, -2037.2075, 30.1456, 321.2733),
            textOffset = vec3(0, 0, 1.05),
            emote = { dict = "amb@world_human_hang_out_street@male_b@idle_a", name = "idle_a", flag = 49 }
        },
        [3] = {
            coord = vec4(-270.6870, -2034.4614, 30.1456, 279.1490),
            textOffset = vec3(0, 0, 1.05),
            emote = { dict = "amb@world_human_guard_patrol@male@idle_a", name = "idle_a", flag = 49 }
        },
    },

    kills = {
        [1] = {
            coord = vec4(-266.4269, -2018.7629, 30.1456, 263.7490),
            textOffset = vec3(0, 0, 1.05),
            emote = { dict = "amb@world_human_cheering@male_a", name = "base", flag = 49 }
        },
        [2] = {
            coord = vec4(-265.7287, -2017.9717, 30.1456, 268.9214),
            textOffset = vec3(0, 0, 1.05),
            emote = { dict = "amb@world_human_hang_out_street@male_b@idle_a", name = "idle_a", flag = 49 }
        },
        [3] = {
            coord = vec4(-267.6994, -2019.9095, 30.1456, 222.3392),
            textOffset = vec3(0, 0, 1.05),
            emote = { dict = "amb@world_human_guard_patrol@male@idle_a", name = "idle_a", flag = 49 }
        },
    },

    score = {
        [1] = {
            coord = vec4(-260.3930, -2027.7667, 30.1456, 322.8690),
            textOffset = vec3(0, 0, 1.05),
            emote = { dict = "amb@world_human_cheering@male_a", name = "base", flag = 49 }
        },
        [2] = {
            coord = vec4(-261.3148, -2028.6167, 30.1456, 122.2778),
            textOffset = vec3(0, 0, 1.05),
            emote = { dict = "amb@world_human_hang_out_street@male_b@idle_a", name = "idle_a", flag = 49 }
        },
        [3] = {
            coord = vec4(-259.5196, -2026.9435, 30.1456, 47.3062),
            textOffset = vec3(0, 0, 1.05),
            emote = { dict = "amb@world_human_guard_patrol@male@idle_a", name = "idle_a", flag = 49 }
        },
    },
}

-- Leaderboard skin integration
Config.LeaderboardGroups.SkinIntegration = {
    enabled = true,

    -- Available options:
    -- 'auto'     = tries illenium first, then falls back to native
    -- 'illenium' = forces illenium, then falls back to native if unavailable
    -- 'custom'   = reserved for custom adaptation in integrations/skin.lua
    -- 'native'   = uses only native components / props
    provider = 'auto'
}

-- Ranked settings
Config.Ranked = {
    Enabled = true,
    WinScore = 3,
    QueueTickMs = 1000,
    QueueWaitNotifyMs = 5000,
    QueueTimeoutSec = 120,

    -- Allowed ranked modes
    Modes = {
        "1v1",
        "2v2",
        "3v3",
        "4v4",
        "5v5",
        "7v7"
    },

    -- Random ranked weapons
    -- If empty, Config.Weapons will be used
    RandomWeapons = {
        "weapon_pistol",
        "weapon_combatpistol",
        "weapon_appistol",
        "weapon_heavypistol",
        "weapon_microsmg",
        "weapon_smg",
        "weapon_assaultrifle",
        "weapon_carbinerifle"
    },

    -- Ranked divisions
    Arenas = {
        {
            key = "arena_1",
            label = "Arena 1",
            minScore = 0,
            maxScore = 100,
            rankName = "Rookie",
            icon = "fa-solid fa-seedling",
            color = "#84cc16",
            glow = "rgba(132, 204, 22, 0.35)"
        },
        {
            key = "arena_2",
            label = "Arena 2",
            minScore = 101,
            maxScore = 300,
            rankName = "Bronze",
            icon = "fa-solid fa-shield-halved",
            color = "#f97316",
            glow = "rgba(249, 115, 22, 0.35)"
        },
        {
            key = "arena_3",
            label = "Arena 3",
            minScore = 301,
            maxScore = 600,
            rankName = "Silver",
            icon = "fa-solid fa-medal",
            color = "#cbd5e1",
            glow = "rgba(203, 213, 225, 0.35)"
        },
        {
            key = "arena_4",
            label = "Arena 4",
            minScore = 601,
            maxScore = 1000,
            rankName = "Gold",
            icon = "fa-solid fa-crown",
            color = "#facc15",
            glow = "rgba(250, 204, 21, 0.35)"
        },
        {
            key = "arena_5",
            label = "Arena 5",
            minScore = 1001,
            maxScore = 1500,
            rankName = "Platinum",
            icon = "fa-solid fa-gem",
            color = "#22d3ee",
            glow = "rgba(34, 211, 238, 0.35)"
        },
        {
            key = "arena_6",
            label = "Arena 6",
            minScore = 1501,
            maxScore = 2500,
            rankName = "Diamond",
            icon = "fa-solid fa-trophy",
            color = "#60a5fa",
            glow = "rgba(96, 165, 250, 0.35)"
        },
        {
            key = "arena_7",
            label = "Arena 7",
            minScore = 2501,
            maxScore = 999999,
            rankName = "Master",
            icon = "fa-solid fa-fire",
            color = "#ef4444",
            glow = "rgba(239, 68, 68, 0.35)"
        }
    },

    -- Ranked map pool using Config.Maps keys
    MapPool = {
        "small",
        "small",
        "small"
    },

    -- Queue definitions created automatically at resource start
    QueueDefinitions = {
        { arenaKey = "arena_1", mode = "1v1" },
        { arenaKey = "arena_1", mode = "2v2" },

        { arenaKey = "arena_2", mode = "1v1" },
        { arenaKey = "arena_2", mode = "2v2" },
        { arenaKey = "arena_2", mode = "3v3" },

        { arenaKey = "arena_3", mode = "1v1" },
        { arenaKey = "arena_3", mode = "2v2" },
        { arenaKey = "arena_3", mode = "3v3" },
        { arenaKey = "arena_3", mode = "4v4" },

        { arenaKey = "arena_4", mode = "2v2" },
        { arenaKey = "arena_4", mode = "3v3" },
        { arenaKey = "arena_4", mode = "4v4" },
        { arenaKey = "arena_4", mode = "5v5" },

        { arenaKey = "arena_5", mode = "3v3" },
        { arenaKey = "arena_5", mode = "4v4" },
        { arenaKey = "arena_5", mode = "5v5" },
        { arenaKey = "arena_5", mode = "7v7" },

        { arenaKey = "arena_6", mode = "4v4" },
        { arenaKey = "arena_6", mode = "5v5" },
        { arenaKey = "arena_6", mode = "7v7" },

        { arenaKey = "arena_7", mode = "5v5" },
        { arenaKey = "arena_7", mode = "7v7" }
    },

    -- Ranked reward track
    Rewards = {
        Enabled = true,

        Track = {
            {
                rewardKey = "arena_1_reward",
                arenaKey = "arena_1",
                title = "Rookie Pack",
                description = "First ranked reward for unlocking Arena 1.",
                icon = "fa-solid fa-seedling",
                rewards = {
                    money = 5000,
                    items = {
                        { name = "bandage", label = "Bandage", amount = 5 },
                        { name = "armor", label = "Armor", amount = 1 }
                    },
                    weapons = {},
                    commands = {}
                }
            },
            {
                rewardKey = "arena_2_reward",
                arenaKey = "arena_2",
                title = "Fighter Pack",
                description = "Unlocked when you reach Arena 2.",
                icon = "fa-solid fa-shield-halved",
                rewards = {
                    money = 10000,
                    items = {
                        { name = "bandage", label = "Bandage", amount = 10 }
                    },
                    weapons = {},
                    commands = {}
                }
            },
            {
                rewardKey = "arena_3_reward",
                arenaKey = "arena_3",
                title = "Veteran Pack",
                description = "Exclusive reward for Arena 3 players.",
                icon = "fa-solid fa-medal",
                rewards = {
                    money = 20000,
                    items = {
                        { name = "medkit", label = "Medkit", amount = 2 }
                    },
                    weapons = {},
                    commands = {
                        -- {id} will be replaced with the player identifier
                        "say Ranked reward granted to {id}"
                    }
                }
            }
        }
    }
}
```

{% endtab %}

{% tab title="server\_web.lua" %}

```lua
Arena = Arena or {}
Arena.Webhooks = Arena.Webhooks or {}
Config = Config or {}

Config.Webhooks = Config.Webhooks or {
    Enabled = true,

    Colors = {
        info    = 3447003,   
        success = 5763719,  
        warning = 16705372,  
        error   = 15548997   
    },

    Tournaments = {
        Enabled = true,

        Created  = '',
        Joined   = '',
        Left     = '',
        Started  = '',
        Finished = '',
        Deleted  = ''
    },

    Rooms = {
        Enabled = true,

        Created          = '',
        Joined           = '',
        Started          = '',
        NotificationSent = '',
        Deleted          = '',
        Finished         = ''
    }
}

local function safeTable(x)
    return type(x) == 'table' and x or {}
end

local function webhookDebugEnabled()
    if Config.DebugModules and Config.DebugModules.webhooks ~= nil then
        return Config.Debug == true and Config.DebugModules.webhooks == true
    end
    return Config.Debug == true
end

local function webhookDebugPrint(...)
    if not webhookDebugEnabled() then return end

    local args = { ... }
    local parts = {}

    for i = 1, #args do
        parts[#parts + 1] = tostring(args[i])
    end

    print(('[izaap_arenapvp][WEBHOOKS] %s'):format(table.concat(parts, ' ')))
end

local function getColorByType(kind)
    local colors = safeTable((Config.Webhooks or {}).Colors)

    if kind == 'success' then
        return tonumber(colors.success) or 5763719
    elseif kind == 'warning' then
        return tonumber(colors.warning) or 16705372
    elseif kind == 'error' then
        return tonumber(colors.error) or 15548997
    end

    return tonumber(colors.info) or 3447003
end

local function buildEmbed(data)
    data = safeTable(data)

    local embed = {
        title = tostring(data.title or 'iZaap ArenaPvP'),
        description = tostring(data.description or ''),
        color = tonumber(data.color or getColorByType(data.type)) or getColorByType('info'),
        footer = {
            text = tostring(data.footer or 'iZaap ArenaPvP')
        },
        timestamp = os.date('!%Y-%m-%dT%H:%M:%SZ')
    }

    local fields = {}
    for _, field in ipairs(safeTable(data.fields)) do
        fields[#fields + 1] = {
            name = tostring(field.name or 'Info'),
            value = tostring(field.value or '-'),
            inline = field.inline == true
        }
    end

    if #fields > 0 then
        embed.fields = fields
    end

    if data.thumbnail and tostring(data.thumbnail) ~= '' then
        embed.thumbnail = { url = tostring(data.thumbnail) }
    end

    if data.image and tostring(data.image) ~= '' then
        embed.image = { url = tostring(data.image) }
    end

    return embed
end

local function sendWebhook(url, payload)
    if not Config.Webhooks or Config.Webhooks.Enabled ~= true then
        webhookDebugPrint('sendWebhook skipped => global disabled')
        return false, 'webhooks_disabled'
    end

    if not url or url == '' then
        webhookDebugPrint('sendWebhook skipped => empty url')
        return false, 'empty_url'
    end

    PerformHttpRequest(url, function(statusCode, responseBody, headers)
        webhookDebugPrint(
            'sendWebhook response => status:',
            statusCode or 'nil'
        )
    end, 'POST', json.encode(payload), {
        ['Content-Type'] = 'application/json'
    })

    return true
end

Arena.Webhooks.Send = function(url, data)
    data = safeTable(data)

    local payload = {
        embeds = {
            buildEmbed(data)
        }
    }

    if data.username and tostring(data.username) ~= '' then
        payload.username = tostring(data.username)
    end

    if data.avatar_url and tostring(data.avatar_url) ~= '' then
        payload.avatar_url = tostring(data.avatar_url)
    end

    return sendWebhook(url, payload)
end
Arena.Webhooks.SendTournament = function(eventName, data)
    local cfg = safeTable((Config.Webhooks or {}).Tournaments)
    if cfg.Enabled ~= true then
        webhookDebugPrint('SendTournament skipped => tournaments disabled')
        return false, 'tournaments_webhook_disabled'
    end

    local url = cfg[eventName]
    if not url or url == '' then
        webhookDebugPrint('SendTournament skipped => missing url for event:', tostring(eventName))
        return false, 'missing_event_url'
    end

    return Arena.Webhooks.Send(url, data)
end

Arena.Webhooks.TournamentCreated = function(payload)
    payload = safeTable(payload)

    return Arena.Webhooks.SendTournament('Created', {
        type = 'success',
        title = 'Tournament Created',
        description = 'A new tournament was created.',
        fields = {
            { name = 'Tournament', value = tostring(payload.name or '-'), inline = true },
            { name = 'ID', value = tostring(payload.id or '-'), inline = true },
            { name = 'UID', value = tostring(payload.uid or '-'), inline = true },
            { name = 'Creator', value = tostring(payload.creatorName or '-'), inline = true },
            { name = 'Creator License', value = tostring(payload.creatorLicense or '-'), inline = false },
            { name = 'Mode', value = tostring(payload.mode or '-'), inline = true },
            { name = 'Rounds', value = tostring(payload.rounds or '-'), inline = true },
            { name = 'Weapon', value = tostring(payload.weapon or '-'), inline = true },
            { name = 'Map', value = tostring(payload.mapKey or '-'), inline = true },
            { name = 'Max Players', value = tostring(payload.maxPlayers or '-'), inline = true },
            {
                name = 'Return Coords',
                value = payload.returnCoords and (
                    ('x: %.2f\ny: %.2f\nz: %.2f\nw: %.2f'):format(
                        tonumber(payload.returnCoords.x or 0.0),
                        tonumber(payload.returnCoords.y or 0.0),
                        tonumber(payload.returnCoords.z or 0.0),
                        tonumber(payload.returnCoords.w or 0.0)
                    )
                ) or 'Not set',
                inline = false
            }
        }
    })
end

Arena.Webhooks.TournamentJoined = function(payload)
    payload = safeTable(payload)

    return Arena.Webhooks.SendTournament('Joined', {
        type = 'info',
        title = 'Tournament Joined',
        description = 'A player joined a tournament.',
        fields = {
            { name = 'Tournament', value = tostring(payload.tournamentName or '-'), inline = true },
            { name = 'Tournament ID', value = tostring(payload.tournamentId or '-'), inline = true },
            { name = 'Player', value = tostring(payload.playerName or '-'), inline = true },
            { name = 'License', value = tostring(payload.playerLicense or '-'), inline = false },
            { name = 'Players', value = tostring(payload.currentPlayers or '0') .. '/' .. tostring(payload.maxPlayers or '0'), inline = true }
        }
    })
end

Arena.Webhooks.TournamentLeft = function(payload)
    payload = safeTable(payload)

    return Arena.Webhooks.SendTournament('Left', {
        type = 'warning',
        title = 'Tournament Left',
        description = 'A player left a tournament.',
        fields = {
            { name = 'Tournament', value = tostring(payload.tournamentName or '-'), inline = true },
            { name = 'Tournament ID', value = tostring(payload.tournamentId or '-'), inline = true },
            { name = 'Player', value = tostring(payload.playerName or '-'), inline = true },
            { name = 'License', value = tostring(payload.playerLicense or '-'), inline = false },
            { name = 'Players Remaining', value = tostring(payload.currentPlayers or '0') .. '/' .. tostring(payload.maxPlayers or '0'), inline = true }
        }
    })
end

Arena.Webhooks.TournamentStarted = function(payload)
    payload = safeTable(payload)

    return Arena.Webhooks.SendTournament('Started', {
        type = 'success',
        title = 'Tournament Started',
        description = 'The tournament has started.',
        fields = {
            { name = 'Tournament', value = tostring(payload.name or '-'), inline = true },
            { name = 'ID', value = tostring(payload.id or '-'), inline = true },
            { name = 'UID', value = tostring(payload.uid or '-'), inline = true },
            { name = 'Mode', value = tostring(payload.mode or '-'), inline = true },
            { name = 'Rounds', value = tostring(payload.rounds or '-'), inline = true },
            { name = 'Weapon', value = tostring(payload.weapon or '-'), inline = true },
            { name = 'Map', value = tostring(payload.mapKey or '-'), inline = true },
            { name = 'Players', value = tostring(payload.currentPlayers or '0') .. '/' .. tostring(payload.maxPlayers or '0'), inline = true },
            { name = 'Creator', value = tostring(payload.creatorName or '-'), inline = true }
        }
    })
end

Arena.Webhooks.TournamentFinished = function(payload)
    payload = safeTable(payload)

    return Arena.Webhooks.SendTournament('Finished', {
        type = 'success',
        title = 'Tournament Finished',
        description = 'The tournament has ended.',
        fields = {
            { name = 'Tournament', value = tostring(payload.name or '-'), inline = true },
            { name = 'ID', value = tostring(payload.id or '-'), inline = true },
            { name = 'Winner', value = tostring(payload.winnerName or '-'), inline = true },
            { name = 'Winner License', value = tostring(payload.winnerLicense or '-'), inline = false },
            { name = 'Mode', value = tostring(payload.mode or '-'), inline = true },
            { name = 'Weapon', value = tostring(payload.weapon or '-'), inline = true },
            { name = 'Map', value = tostring(payload.mapKey or '-'), inline = true }
        }
    })
end

Arena.Webhooks.TournamentDeleted = function(payload)
    payload = safeTable(payload)

    return Arena.Webhooks.SendTournament('Deleted', {
        type = 'error',
        title = 'Tournament Deleted',
        description = 'A tournament was deleted.',
        fields = {
            { name = 'Tournament', value = tostring(payload.name or '-'), inline = true },
            { name = 'ID', value = tostring(payload.id or '-'), inline = true },
            { name = 'UID', value = tostring(payload.uid or '-'), inline = true },
            { name = 'Deleted By', value = tostring(payload.deletedByName or '-'), inline = true },
            { name = 'Deleted By License', value = tostring(payload.deletedByLicense or '-'), inline = false },
            { name = 'State', value = tostring(payload.state or '-'), inline = true }
        }
    })
end
Arena.Webhooks.SendRoom = function(eventName, data)
    local cfg = safeTable((Config.Webhooks or {}).Rooms)
    if cfg.Enabled ~= true then
        webhookDebugPrint('SendRoom skipped => rooms disabled')
        return false, 'rooms_webhook_disabled'
    end

    local url = cfg[eventName]
    if not url or url == '' then
        webhookDebugPrint('SendRoom skipped => missing url for event:', tostring(eventName))
        return false, 'missing_event_url'
    end

    return Arena.Webhooks.Send(url, data)
end

Arena.Webhooks.RoomCreated = function(payload)
    payload = safeTable(payload)

    return Arena.Webhooks.SendRoom('Created', {
        type = 'success',
        title = 'Room Created',
        description = 'A new room was created.',
        fields = {
            { name = 'Room ID', value = tostring(payload.roomId or '-'), inline = true },
            { name = 'Code', value = tostring(payload.code or '-'), inline = true },
            { name = 'Owner', value = tostring(payload.ownerName or '-'), inline = true },
            { name = 'Owner License', value = tostring(payload.ownerLicense or '-'), inline = false },
            { name = 'Mode', value = tostring(payload.mode or '-'), inline = true },
            { name = 'Rounds', value = tostring(payload.rounds or '-'), inline = true },
            { name = 'Weapon', value = tostring(payload.weapon or '-'), inline = true },
            { name = 'Map', value = tostring(payload.mapKey or '-'), inline = true },
            { name = 'Bet Type', value = tostring(payload.betType or 'none'), inline = true },
            { name = 'Bet Amount', value = tostring(payload.betAmount or '0'), inline = true },
            { name = 'Bet Money Type', value = tostring(payload.betMoneyType or '-'), inline = true },
            { name = 'Bet Weapon', value = tostring(payload.betWeapon or '-'), inline = true },
            { name = 'Players', value = tostring(payload.currentPlayers or '0') .. '/' .. tostring(payload.maxPlayers or '0'), inline = true }
        }
    })
end

Arena.Webhooks.RoomJoined = function(payload)
    payload = safeTable(payload)

    return Arena.Webhooks.SendRoom('Joined', {
        type = 'info',
        title = 'Room Joined',
        description = 'A player joined a room.',
        fields = {
            { name = 'Room ID', value = tostring(payload.roomId or '-'), inline = true },
            { name = 'Code', value = tostring(payload.code or '-'), inline = true },
            { name = 'Player', value = tostring(payload.playerName or '-'), inline = true },
            { name = 'Player License', value = tostring(payload.playerLicense or '-'), inline = false },
            { name = 'Owner', value = tostring(payload.ownerName or '-'), inline = true },
            { name = 'Mode', value = tostring(payload.mode or '-'), inline = true },
            { name = 'Map', value = tostring(payload.mapKey or '-'), inline = true },
            { name = 'Players', value = tostring(payload.currentPlayers or '0') .. '/' .. tostring(payload.maxPlayers or '0'), inline = true }
        }
    })
end

Arena.Webhooks.RoomStarted = function(payload)
    payload = safeTable(payload)

    return Arena.Webhooks.SendRoom('Started', {
        type = 'success',
        title = 'Room Started',
        description = 'A room match has started.',
        fields = {
            { name = 'Room ID', value = tostring(payload.roomId or '-'), inline = true },
            { name = 'Code', value = tostring(payload.code or '-'), inline = true },
            { name = 'Starter', value = tostring(payload.starterName or '-'), inline = true },
            { name = 'Starter License', value = tostring(payload.starterLicense or '-'), inline = false },
            { name = 'Owner', value = tostring(payload.ownerName or '-'), inline = true },
            { name = 'Owner License', value = tostring(payload.ownerLicense or '-'), inline = false },
            { name = 'Opponent', value = tostring(payload.opponentName or '-'), inline = true },
            { name = 'Opponent License', value = tostring(payload.opponentLicense or '-'), inline = false },
            { name = 'Mode', value = tostring(payload.mode or '-'), inline = true },
            { name = 'Rounds', value = tostring(payload.rounds or '-'), inline = true },
            { name = 'Weapon', value = tostring(payload.weapon or '-'), inline = true },
            { name = 'Map', value = tostring(payload.mapKey or '-'), inline = true },
            { name = 'Bet Type', value = tostring(payload.betType or 'none'), inline = true },
            { name = 'Bet Amount', value = tostring(payload.betAmount or '0'), inline = true },
            { name = 'Bet Money Type', value = tostring(payload.betMoneyType or '-'), inline = true },
            { name = 'Bet Weapon', value = tostring(payload.betWeapon or '-'), inline = true },
            { name = 'Players', value = tostring(payload.currentPlayers or '0') .. '/' .. tostring(payload.maxPlayers or '0'), inline = true },
            { name = 'Ranked', value = tostring(payload.ranked == true), inline = true }
        }
    })
end

Arena.Webhooks.RoomNotificationSent = function(payload)
    payload = safeTable(payload)

    return Arena.Webhooks.SendRoom('NotificationSent', {
        type = 'info',
        title = 'Room Notification Sent',
        description = 'A room invite notification was sent.',
        fields = {
            { name = 'Room ID', value = tostring(payload.roomId or '-'), inline = true },
            { name = 'Code', value = tostring(payload.code or '-'), inline = true },
            { name = 'Sender', value = tostring(payload.senderName or '-'), inline = true },
            { name = 'Sender License', value = tostring(payload.senderLicense or '-'), inline = false },
            { name = 'Mode', value = tostring(payload.mode or '-'), inline = true },
            { name = 'Rounds', value = tostring(payload.rounds or '-'), inline = true },
            { name = 'Weapon', value = tostring(payload.weapon or '-'), inline = true },
            { name = 'Map', value = tostring(payload.mapKey or '-'), inline = true },
            { name = 'Bet Type', value = tostring(payload.betType or 'none'), inline = true },
            { name = 'Players', value = tostring(payload.currentPlayers or '0') .. '/' .. tostring(payload.maxPlayers or '0'), inline = true },
            { name = 'Sent Count', value = tostring(payload.sentCount or '0'), inline = true }
        }
    })
end

Arena.Webhooks.RoomDeleted = function(payload)
    payload = safeTable(payload)

    return Arena.Webhooks.SendRoom('Deleted', {
        type = 'error',
        title = 'Room Deleted',
        description = 'A room was deleted.',
        fields = {
            { name = 'Room ID', value = tostring(payload.roomId or '-'), inline = true },
            { name = 'Code', value = tostring(payload.code or '-'), inline = true },
            { name = 'Deleted By', value = tostring(payload.deletedByName or '-'), inline = true },
            { name = 'Deleted By License', value = tostring(payload.deletedByLicense or '-'), inline = false },
            { name = 'Owner', value = tostring(payload.ownerName or '-'), inline = true },
            { name = 'Owner License', value = tostring(payload.ownerLicense or '-'), inline = false },
            { name = 'Opponent', value = tostring(payload.opponentName or '-'), inline = true },
            { name = 'Opponent License', value = tostring(payload.opponentLicense or '-'), inline = false },
            { name = 'Mode', value = tostring(payload.mode or '-'), inline = true },
            { name = 'Map', value = tostring(payload.mapKey or '-'), inline = true },
            { name = 'State', value = tostring(payload.state or '-'), inline = true },
            { name = 'Players', value = tostring(payload.currentPlayers or '0') .. '/' .. tostring(payload.maxPlayers or '0'), inline = true }
        }
    })
end

Arena.Webhooks.RoomFinished = function(payload)
    payload = safeTable(payload)

    return Arena.Webhooks.SendRoom('Finished', {
        type = 'success',
        title = 'Room Finished',
        description = 'A room match has finished.',
        fields = {
            { name = 'Room ID', value = tostring(payload.roomId or '-'), inline = true },
            { name = 'Code', value = tostring(payload.code or '-'), inline = true },
            { name = 'Winner', value = tostring(payload.winnerName or '-'), inline = true },
            { name = 'Winner License', value = tostring(payload.winnerLicense or '-'), inline = false },
            { name = 'Loser', value = tostring(payload.loserName or '-'), inline = true },
            { name = 'Loser License', value = tostring(payload.loserLicense or '-'), inline = false },
            { name = 'Owner', value = tostring(payload.ownerName or '-'), inline = true },
            { name = 'Owner License', value = tostring(payload.ownerLicense or '-'), inline = false },
            { name = 'Opponent', value = tostring(payload.opponentName or '-'), inline = true },
            { name = 'Opponent License', value = tostring(payload.opponentLicense or '-'), inline = false },
            { name = 'Mode', value = tostring(payload.mode or '-'), inline = true },
            { name = 'Rounds', value = tostring(payload.rounds or '-'), inline = true },
            { name = 'Weapon', value = tostring(payload.weapon or '-'), inline = true },
            { name = 'Map', value = tostring(payload.mapKey or '-'), inline = true },
            { name = 'Bet Type', value = tostring(payload.betType or 'none'), inline = true },
            { name = 'Bet Amount', value = tostring(payload.betAmount or '0'), inline = true },
            { name = 'Bet Money Type', value = tostring(payload.betMoneyType or '-'), inline = true },
            { name = 'Bet Weapon', value = tostring(payload.betWeapon or '-'), inline = true },
            { name = 'Score A', value = tostring(payload.scoreA or '0'), inline = true },
            { name = 'Score B', value = tostring(payload.scoreB or '0'), inline = true },
            { name = 'Ranked', value = tostring(payload.ranked == true), inline = true }
        }
    })
end
```

{% endtab %}
{% endtabs %}
