Inicio › Documentación › Acciones del menú rápido · origen_ilegalv2

Acciones del menú rápido · origen_ilegalv2

Config.QuickMenu.Actions define las entradas que se muestran en el menú F6 cuando el jugador está cerca de otro jugador. Cada acción se ejecuta en el servidor a través de un handler que declaras en línea.

Puedes añadir tus propias acciones sin tocar el código del núcleo: basta con añadir entradas al array.


Anatomía de una acción

luaconfig/interactions.lua
Config.QuickMenu = {
    Enable      = true,
    Key         = 'F6',
    UseCommand  = true,
    CommandName = 'quickmenu',
 
    canInteract = function(playerPed, targetPed)
        return true, nil
    end,
 
    Actions = {
        {
            id                 = 'search',
            order              = 1,
            label              = 'quickmenu.actions.search.label',
            icon               = 'fa-solid fa-magnifying-glass',
            requiredPermission = 'quick_search',
 
            canExecute = function(playerPed, targetPed)
                return true, nil
            end,
 
            onExecute = function(src, targetId)
                QuickActions.Search(src, targetId)
            end,
        },
    },
}

Campos

Campo Tipo Obligatorio Descripción
id string sí Id único de la acción. Se usa para enrutar la ejecución en el servidor.
order number sí Orden de aparición en el menú (ascendente).
label string sí Texto del botón. Puede ser un texto plano o una clave de traducción (p. ej. quickmenu.actions.myaction.label).
icon string sí Clase de Font Awesome (p. ej. fa-solid fa-magnifying-glass).
requiredPermission string | nil sí Permiso de rango que necesita el jugador. nil = cualquier miembro de la banda.
canExecute(playerPed, targetPed) function no Filtro del lado del cliente que se llama antes de enviar la petición al servidor. Devuelve true para permitir, o false, reason para bloquear mostrando una notificación.
onExecute(src, targetId) function sí Handler del lado del servidor. src es quien lo ejecuta y targetId es el jugador más cercano en un radio de 3 m.

El núcleo ya valida la distancia (3 m), el permiso y que exista un objetivo antes de llamar a onExecute. Solo tienes que implementar el comportamiento en sí.


Sistema de permisos

Toda acción que declara requiredPermission se comprueba dos veces:

  1. Cliente: la acción se oculta del menú si HasPermission(action.requiredPermission) devuelve false.
  2. Servidor: Gang:hasPermission(identifier, action.requiredPermission) se vuelve a comprobar dentro de origen_gang:server:quickAction antes de ejecutar onExecute. Protección anti-manipulación por diseño.

Añadir tu propio flag de permiso

Declara el flag en cada rango de Config.Gang.DefaultRanks (config/gangs.lua). Cualquier flag que incluyas ahí queda automáticamente:

luaconfig/gangs.lua — DefaultRanks
{
    id = 1, name = "Leader",
    permissions = {
        -- ... existing flags ...
        quick_revive = true,   -- 👈 new flag
    },
},
{
    id = 3, name = "Member",
    permissions = {
        quick_revive = false,
    },
},

Los rangos que no tengan el flag definido explícitamente NO verán ni ejecutarán la acción. Los flags ausentes valen false por defecto.


Ejemplo 1 — reanimar a un compañero caído

luaconfig/interactions.lua — Actions
{
    id                 = 'revive',
    order              = 6,
    label              = 'quickmenu.actions.revive.label',
    icon               = 'fa-solid fa-heart-pulse',
    requiredPermission = 'quick_revive',
 
    -- Client gate: only show/allow if the target is dead
    canExecute = function(playerPed, targetPed)
        if not IsPedDeadOrDying(targetPed, true) then
            return false, 'target_not_dead'
        end
        return true, nil
    end,
 
    -- Server handler
    onExecute = function(src, targetId)
        TriggerClientEvent('hospital:client:Revive', targetId)
        -- Optional: charge an item, log the action, etc.
    end,
},

Ejemplo 2 — dar dinero de la banda a un miembro cercano

luaconfig/interactions.lua — Actions
{
    id                 = 'give_cash',
    order              = 7,
    label              = 'quickmenu.actions.give_cash.label',
    icon               = 'fa-solid fa-hand-holding-dollar',
    requiredPermission = 'withdraw',   -- reuses the existing bank permission
 
    canExecute = function(playerPed, targetPed)
        if #(GetEntityCoords(playerPed) - GetEntityCoords(targetPed)) > 2.0 then
            return false, 'too_far'
        end
        return true, nil
    end,
 
    onExecute = function(src, targetId)
        local gang = Gang.GetPlayerGangBySource(src)
        if not gang then return end
 
        local amount = 500
        if gang.bank < amount then
            NotifyPlayer(src, 'Not enough funds', 'error')
            return
        end
 
        gang.bank = gang.bank - amount
        -- give to target via your framework API
        exports.ox_inventory:AddItem(targetId, 'money', amount)
 
        gang:addLog(GetPlayerIdentifier(src), 'quick_give_cash', {
            amount = amount,
            target = GetPlayerName(targetId),
        })
    end,
},

Flujo de ejecución

text
[F6] ─▶ OpenQuickMenu()
         │
         ├─▶ GetAvailableActions()        (client-side permission filter)
         │
         └─▶ player picks action
                 │
                 ├─▶ canExecute()         (client gate, optional)
                 │
                 └─▶ TriggerServerEvent('origen_gang:server:quickAction', id, targetId)
                         │
                         ├─▶ validate Config.Actions[id] exists
                         ├─▶ validate gang:hasPermission(requiredPermission)
                         ├─▶ validate target is within 3m (lib.getClosestPlayer)
                         │
                         └─▶ action.onExecute(src, targetId)
                                 │
                                 └─▶ TriggerClientEvent('origen_gang:client:quickActionExecuted', targetId, id, src)

El evento de cliente quickActionExecuted se dispara en el objetivo: puedes escucharlo si tu acción personalizada necesita que la víctima reproduzca una animación, muestre una notificación, etc.


Filtro global — canInteract

Config.QuickMenu.canInteract(playerPed, targetPed) se ejecuta antes de listar cualquier acción. Úsalo para bloquear todo el menú según reglas propias (p. ej. que el objetivo esté dentro de un vehículo o en una zona segura):

lua
canInteract = function(playerPed, targetPed)
    if IsPedInAnyVehicle(targetPed, false) then
        return false, 'target_in_vehicle'
    end
    return true, nil
end,

Si devuelve false, se ocultan todas las acciones por objetivo de esa interacción. El interruptor de ZoneSale y otras entradas que no dependen de un objetivo no se ven afectados.


Ampliar QuickActions (opcional)

Las utilidades integradas están en server/functions/f_quick_actions.lua:

lua
QuickActions.Search(src, targetId)
QuickActions.Handcuff(src, targetId)
QuickActions.Escort(src, targetId)
QuickActions.PutInVehicle(src, targetId)
QuickActions.TakeOutVehicle(src, targetId)

Si quieres mantener tu lógica ordenada, puedes añadir tu propia función a la tabla QuickActions desde un fichero complementario y llamarla desde onExecute:

luaserver/custom/qa_revive.lua
QuickActions = QuickActions or {}
 
function QuickActions.Revive(src, targetId)
    TriggerClientEvent('hospital:client:Revive', targetId)
end
luaconfig/interactions.lua
onExecute = function(src, targetId)
    QuickActions.Revive(src, targetId)
end,