🛠️Menu Props

🇫🇷 Le menu Props est idéal pour permettre à vos joueurs d’ajouter des objets de décoration ou d’aider à la création de mini-événements. Ajoutez des props qui resteront persistants, mais se supprimeront automatiquement au bout d’un certain temps que vous aurez défini. Déplacez les props avec précision grâce à l’outil Gizmo ! Vous avez peur d’un abus ? Les membres du staff peuvent gérer tous les props du serveur !

🇺🇸 The Props Menu is perfect for allowing your players to add decorative objects or help create mini-events. Add props that remain persistent but will automatically be removed after a set time you define. Move props precisely using the Gizmo tool! Worried about abuse? Staff members can manage all server props !


Preview Vidéo

Buy


Feature

🇫🇷

  • Menu RageUI Custom – Style épuré

  • Suppression automatique des props au bout de x minutes

  • Herse fonctionnelle (crève toutes les roues, même s’il n’y en a qu’une qui touche)

  • Liste de props prédéfinis dans des catégories, ouverte à tout le monde ou aux jobs.

  • Option admin ou ouverte à tout le monde : possibilité de spawn n’importe quel prop (dimension max à définir pour éviter les abus)

  • Admin : voir tous les props, les supprimer, savoir qui les a posés

  • Limite de props que peuvent poser les joueurs et le staff

🇺🇸

  • Custom RageUI Menu – Clean Style

  • Automatic deletion of props after x minutes

  • Functional spike strip (pops all tires, even if only one is touched)

  • List of predefined props sorted by category, available to everyone or restricted to specific jobs

  • Admin option or open to everyone: ability to spawn any prop (maximum size to be defined to prevent abuse)

  • Admin: view all props, delete them, see who placed them

  • Limit on the number of props that players and staff can place


Installation

🇫🇷 Téléchargez le script depuis votre keymaster, extrayez le fichier, placer le dans le dossier de votre choix et ajoutez-le à votre resources.cfg / server.cfg. Ensuite, ouvrez votre fichier sql.sql et insérez-le dans la base de données.

🇺🇸 Download the script from your keymaster, extract the file, place it in the folder of your choice and add it to your resources.cfg / server.cfg. Then, open your sql.sql file and insert it into the database.

DROP TABLE IF EXISTS `s_props`;
CREATE TABLE IF NOT EXISTS `s_props` (
  `id` int NOT NULL AUTO_INCREMENT,
  `identifier` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  `prop_name` varchar(30) COLLATE utf8mb4_general_ci NOT NULL,
  `timestamp` varchar(20) COLLATE utf8mb4_general_ci NOT NULL,
  `timestamp_limit` varchar(20) COLLATE utf8mb4_general_ci NOT NULL,
  `metadata` json DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=275 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
COMMIT;

Configuration

🇫🇷 Vous allez utiliser plusieurs fichiers pour configurer au maximum le script. Les deux fichiers principaux sont ceux ci-dessous :

🇺🇸 You will use several files to configure the script to the maximum extent. The two main files are those below:

Config.lua
Config = {}

Config.LockerMenu = {

    ['Framework'] = 'QBCore', -- QBCore or ESX
    ['Inventory'] = 'QS', -- QS, OX (QS potentially automatically creates for the qb-inventory)

    ['Settings'] = { 
        MinCharacForNewName = 3, -- Minimum number of characters to change the locker name
        MinNumberForNewPassword = 4, -- Minimum number of digits to change the password

        DrawMarkerDistance = 10, -- The distance to display the marker
        InteractDistance = 2.5, -- The distance in order to be able to interact and open the locker menu

        KeyOpenMenu = 38, -- The key to open the menu : https://docs.fivem.net/docs/game-references/controls/#controls
    },

    ['Lockers'] = {
        ['lspd_locker'] = {
            TitleName = "Los Santos Police Department",
            Coords = vector3(316.38, -272.42, 53.92),
            MarkerOption = {Type = 6, dirX = 0.0, dirY = 0.0, dirZ = 0.0, rotX = -90.0, rotY = 0.0, rotZ = 0.0, scaleX = 0.7, scaleY = 0.7, scaleZ = 0.7, red = 255, green = 255, blue = 255, alpha = 100, bobUpAndDown = false, faceCamera = false, p19 = true, rotate = false, textureDict = false, textureName = false, drawOnEnts = false}, -- Yes, lots of settings ^^
            MarkerZPosition = (-0.97), -- If you want to increase the height of the marker. Remove the “-”

            ['Restriction'] = {
                JobName = "police", -- "job_name" or "none"
                GradeJob = {'all'}, -- {'all'} or {'1','2','3','4'}
                LockerManagement = 3, -- Grade for Add, Remove, Edit Lockers
                MaxLockers = 20, -- Maximum number of lockers
            },
        },
        ['lspd_locker2'] = {
            TitleName = "Emergency Medical Services",
            Coords = vector3(307.56, -271.09, 53.95),
            MarkerOption = {Type = 6, dirX = 0.0, dirY = 0.0, dirZ = 0.0, rotX = -90.0, rotY = 0.0, rotZ = 0.0, scaleX = 0.7, scaleY = 0.7, scaleZ = 0.7, red = 255, green = 255, blue = 255, alpha = 100, bobUpAndDown = false, faceCamera = false, p19 = true, rotate = false, textureDict = false, textureName = false, drawOnEnts = false}, -- Yes, lots of settings ^^
            MarkerZPosition = (-0.97), -- If you want to increase the height of the marker. Remove the “-”

            ['Restriction'] = {
                JobName = "ambulance", -- "job_name" or "none"
                GradeJob = {'1','2','3','4'}, -- {'all'} or {'1','2','3','4'}
                LockerManagement = 7, -- Grade for Add, Remove, Edit Lockers
                MaxLockers = 10, -- Maximum number of lockers
            },
        },

        ['test_video'] = {
            TitleName = "Tuto Vidéo",
            Coords = vector3(-1017.69, -1129.02, 2.12),
            MarkerOption = {Type = 6, dirX = 0.0, dirY = 0.0, dirZ = 0.0, rotX = -90.0, rotY = 0.0, rotZ = 0.0, scaleX = 0.7, scaleY = 0.7, scaleZ = 0.7, red = 255, green = 255, blue = 255, alpha = 100, bobUpAndDown = false, faceCamera = false, p19 = true, rotate = false, textureDict = false, textureName = false, drawOnEnts = false}, -- Yes, lots of settings ^^
            MarkerZPosition = (-0.97), -- If you want to increase the height of the marker. Remove the “-”

            ['Restriction'] = {
                JobName = "ambulance", -- "job_name" or "none"
                GradeJob = {'1','2','3','4'}, -- {'all'} or {'1','2','3','4'}
                LockerManagement = 3, -- Grade for Add, Remove, Edit Lockers
                MaxLockers = 25, -- Maximum number of lockers
            },
        },






    },

    ['ShowNotification'] = function(text, typenotif) -- Notification type, depending on your framework or external script (Server notifications are forwarded here)
        if Config.LockerMenu['Framework'] == 'QBCore' then 
            TriggerEvent('QBCore:Notify', text, typenotif)
        elseif Config.LockerMenu['Framework'] == 'ESX' then 
            TriggerEvent('esx:showNotification', text, typenotif)
        end
    end,

    ['Translate'] = { 
        -- Client Side

        Interact = "[E] Ouvrir",

        NeedMoreCharacters = "Le nom du casier doit comporter au minimum %s caractères.",
        NameChanged = "Changement du nom du casier effectué : de '%s' à '%s'.",


        NeedMoreNumber = "Le mot de passe doit contenir %s chiffres.",
        PasswordIsNotNumbers = "Le mot de passe ne contient pas que des chiffres.",
        NumberTooLow = "Le mot de passe doit comporter plus de %s chiffres.",

        NotBeNegative = "Le mot de passe ne doit pas être une valeur négative.",
        PasswordChanged = "Le mot de passe du casier a été changé : de '%s' à '%s'.",

        LockerDeleted = "Casier n°%s supprimé (Sous le nom %s).",

        NotHaveAccess = "Vous n'avez pas les accès nécessaires pour effectuer cette action.",

        IncorrectPassword = "Mot de passe incorrect.",

        -- Server Side : 
        NewLocker = "Nouveau casier",
        NewLockerCreated = "Nouveau casier créé.",
    },

    ['OpenInventory'] = function(inv_name) -- For any requests for inventory management additions, come to my Discord if you're having trouble : discord.gg/EyT4mt8Pwf
        if Config.LockerMenu['Inventory'] == 'QS' then 
            local inventory_settings = { maxweight = 20000, slots = 10 }
            TriggerServerEvent("inventory:server:OpenInventory", "stash", inv_name, inventory_settings)
            TriggerEvent("inventory:client:SetCurrentStash", inv_name)
        elseif Config.LockerMenu['Inventory'] == 'OX' then 
            local ox_inventory = exports.ox_inventory
            local inventory_settings = { maxweight = 20000, slots = 10 }

            if ox_inventory:openInventory('stash', inv_name) == false then
                TriggerServerEvent('Lockers:Inventory:Register', inv_name, inventory_settings)
                ox_inventory:openInventory('stash', inv_name)
            end
        end 
    end,
}

LockersUI_DrawText = function(x, y, z, text)
    local px,py,pz=table.unpack(GetGameplayCamCoords())
    local dist = GetDistanceBetweenCoords(px,py,pz, x,y,z, 1)
 
    local scale = (1/dist)*2
    local fov = (1/GetGameplayCamFov())*100
    local scale = scale*fov
        SetTextScale(0.0*scale, 0.40*scale)
        SetTextFont(4)
        SetTextProportional(1)
        SetTextColour(255, 255, 255, 215)
        SetTextDropshadow(0, 0, 0, 0, 255)
        SetTextEdge(1, 0, 0, 0, 150)
        SetTextDropShadow()
        SetTextOutline()
        SetTextEntry("STRING")
        SetTextCentre(1)
        AddTextComponentString(text)
        SetDrawOrigin(x,y,z, 0)
        DrawText(0.0, 0.0)
        ClearDrawOrigin()
end
Config.js
const Config = {
    EnableBlackBackground: true, 
    ColorBackground: "rgba(0, 0, 0, 0.7)", 
    
    BlurOpacity : "3px", // 0px = disabled | 3px = default

    ['NewNameSettings'] : {
        MinLenght : 3,
        MaxLength : 30,
    },
};

const Translate = {
    CreateLocker : "Ajouter un casier",

    ['NewLocker'] : {
        NewLocker : "Nouveau casier",
        Open : "Ouvrir",
        Edit : "Gestion",
        LockerLimitReached : "Vous avez atteint la limite de casier créable",
    },

    ['Open'] : {
        EnterPassword : "Saisiez le mot de passe",
        Placeholder : "...",
    },

    ['Edit'] : {
        ChangeNameLocker : "Changer le nom du casier",
        Placeholder_newname : "Casier de ......",

        ChangePasswordLocker : "Changer le mot de passe",
        Placeholder_newpassword : "1111-9999",

        ValidEmojie : "✔",

        ['Footer'] : {
            DeleteLocker : "Supprimer le casier",
            Valid : "Valider",
            Cancel : "Annuler",
        },
    },

    NotHaveAcces : "Vous n'avez pas les accès requis pour cette action",

    ['Footer'] : {
        Valid : "Valider",
        Cancel : "Annuler",
    },
};

🇫🇷 Après, vous avez le fichier server_config.lua afin de gérer les journaux, l'impression dans la console pour le casier supprimé inutile, et la gestion de l'inventaire du côté serveur.

🇺🇸 Afterward, you have the server_config.lua file to manage logs, printing in the console for unnecessary removed lockers, and server-side inventory management.

server_config.lua
MySQL.ready(function() -- Small addition to remove boxes not inserted in your config.lua
    local lockers_lists = MySQL.query.await('SELECT * FROM `s_lockers`')
    for _,lockers in pairs(lockers_lists) do
        if not Config.LockerMenu['Lockers'][lockers.label] then 
            MySQL.update('DELETE FROM `s_lockers` WHERE label = ?', {lockers.label}, function(result)
                print("[^1DEBUG^7] Casier sous le nom ^3"..lockers.label.."^7 supprimé de la base de données car il n'était pas mentionné dans votre fichier Config.lua.")
                -- print("[^1DEBUG^7] Locker under the name ^3"..lockers.label.."^7 deleted from the database because it was not mentioned in your Config.lua file.")
                Logs_TableDeletedDebug(lockers.label)
            end)
        end
    end
end)

RegisterNetEvent('Lockers:Inventory:Register', function(inv_name, inventory_settings)
    if source == 0 then return end 

    if Config.LockerMenu['Inventory'] == 'OX' then 
        local ox_inventory = exports.ox_inventory
        ox_inventory:RegisterStash(inv_name, inv_name, inventory_settings.slots, inventory_settings.maxweight)
    end
end)


local Logs_Webhook = {
    ['LockerDeleted'] ='https://discord.com/api/webhooks/',
    ['LockerAddNewLocker'] ='https://discord.com/api/webhooks/',
    ['TableDeletedDebug'] = 'https://discord.com/api/webhooks/',
}

Logs_LockerDeleted = function(source, name)
    if source == 0 then return end 

    local embeds = {{
        ["description"] = ("· **ID du joueur :** %s \n· **Pseudo du joueur :** %s \n· **Nom du casier supprimé :** %s"):format(tonumber(source), GetPlayerName(tonumber(source)), name),
        ["color"] = 15605278, -- https://www.colorhexa.com/30ff00
    }}
    PerformHttpRequest(Logs_Webhook['LockerDeleted'], function(err, text, headers) end, 'POST', json.encode({username=username,embeds=embeds}), { ['Content-Type'] = 'application/json' })
end

Logs_AddNewLocker = function(source, label, lists)
    if source == 0 then return end 

    local embeds = {{
        ["description"] = ("· **ID du joueur :** %s \n· **Pseudo du joueur :** %s \n· **Nom des casiers :** %s \n· **Total des casiers :** %s "):format(tonumber(source), GetPlayerName(tonumber(source)), label, #lists),
        ["color"] = 3211008, -- https://www.colorhexa.com/30ff00
    }}
    PerformHttpRequest(Logs_Webhook['LockerAddNewLocker'], function(err, text, headers) end, 'POST', json.encode({username=username,embeds=embeds}), { ['Content-Type'] = 'application/json' })
end

Logs_TableDeletedDebug = function(name)
    local embeds = {{
        ["description"] = ("· **Nom de la table supprimé :** %s"):format(name),
        ["footer"] = {
            ["text"] = "Supprimé de la base de données car il n'était pas mentionné dans votre fichier Config.lua.",
        },
        ["color"] = 13800222, -- https://www.colorhexa.com/30ff00
    }}
    PerformHttpRequest(Logs_Webhook['TableDeletedDebug'], function(err, text, headers) end, 'POST', json.encode({username=username,embeds=embeds}), { ['Content-Type'] = 'application/json' })
end

Différence : ESCROW & OPEN-SOURCE

🇫🇷 La version escrow reste assez simple, comme montré dans la vidéo. Elle est vraiment spécialement conçue pour la configuration du script. Les modifications plus poussées ne vous sont pas fournies, bien que je pense vous avoir donné accès à de nombreuses modifications. C'est pourquoi le prix reste relativement bas pour la qualité de ce dernier.

🇺🇸 The escrow version remains quite simple, as shown in the video. It is specifically designed for script configuration. More advanced modifications are not provided, although I believe I have given you access to many adjustments. Hence, the price remains relatively low considering its quality.

Mis à jour

Ce contenu vous a-t-il été utile ?