├── .editorconfig ├── .github └── ISSUE_TEMPLATE │ └── bug_report.md ├── .vscode └── settings.json ├── README.md ├── client ├── callbacks.lua ├── clientapi.lua ├── commands.lua ├── controllers.lua ├── coreactions.lua ├── dataview.lua ├── discrichpresence.lua ├── exports │ └── exp_notifications.lua ├── instance.lua ├── miscellanea.lua ├── notifications.lua ├── ref │ └── vorp_notifications.lua ├── respawnsystem.lua ├── spawnplayer.lua └── uicore.lua ├── config ├── commands.lua ├── config.lua ├── logs.lua └── skills.lua ├── fxmanifest.lua ├── license.md ├── pull_request_template.md ├── server ├── apicontroller.lua ├── bans.lua ├── class │ ├── callbacks.lua │ ├── character.lua │ ├── user.lua │ └── whitelisting.lua ├── commands.lua ├── init.lua ├── instance.lua ├── loadcharacter.lua ├── loadusers.lua ├── logs.lua ├── old_api.lua ├── richpresence.lua ├── saveusers.lua ├── services │ └── dbupdater │ │ ├── dbupdater.lua │ │ └── status.json └── whitelist.lua ├── translation └── language.lua ├── types ├── client │ ├── callback.lua │ └── notify.lua └── server │ ├── callback.lua │ └── classes.lua ├── ui ├── app.js ├── assets │ ├── css │ │ ├── level.css │ │ └── style.css │ ├── fonts │ │ └── rdrlino-regular-webfont.woff │ └── icons │ │ ├── gold.png │ │ ├── id.png │ │ ├── lv.png │ │ ├── money.png │ │ ├── pvpoff.png │ │ ├── pvpon.png │ │ └── token.png ├── index.html └── vendor │ └── vue.js └── version /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | max_line_length = 1000 5 | indent_size = 4 -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the issue** 11 | A clear and concise description of what the issue is with vorp core plugin. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | 27 | **Additional context** 28 | Add any other context about the problem here. 29 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Lua.diagnostics.globals": [ 3 | "MySQL" 4 | ] 5 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VORP Core 2 | 3 | ## Introduction 4 | 5 | VORP Core is a comprehensive Lua-based framework for RedM, designed to enhance server functionality and player experience with a wide array of configurable settings and commands. 6 | 7 | ## Requirements 8 | 9 | - [oxmysql](https://github.com/overextended/oxmysql/releases): A must-have for database operations, ensuring smooth data handling and integration. 10 | 11 | ## Installation Guide 12 | 13 | 1. **Setup:** 14 | - Download and ensure `oxmysql` is properly set up and configured in your RedM server environment. 15 | 2. **VORP Core Installation:** 16 | - Rename the downloaded folder to `vorp_core`. 17 | - Move the `vorp_core` folder into your server's resources directory, usually found under `\resources\[VORP]\vorp_core`. 18 | - Include `ensure vorp_core` in your server's `resources.cfg/server.cfg` file, placing it at the top of the load order for priority loading. 19 | 20 | ## Documentation 21 | 22 | - [Documentation](https://docs.vorp-core.com/introduction) 23 | - Direct link to the full VORP Core documentation for in-depth details and guides. 24 | 25 | --- 26 | 27 | ## Features Overview 28 | 29 | ## Configuration Options (`config.lua`) 30 | 31 | ### Server Settings 32 | - **Language:** Set the server's language, referring to available options in the 'translation' folder. 33 | - **OneSync:** Toggle OneSync integration (`true` for enabled). 34 | - **Database Updates:** Enable automatic database updates. 35 | - **Player Info Logs:** Configure logging of player information on join/leave. 36 | 37 | ### Starting Configuration 38 | - **Initial Resources:** Set starting amounts for gold, money, role-play currency, and experience points. 39 | - **Default Player Settings:** Configure default job, job grade, user group, and job label for new players. 40 | - **Whitelist and Auto-update:** Manage whitelist settings and auto-updates. 41 | 42 | ### Player Limits 43 | - **Health and Stamina:** Set maximum health and stamina for players. 44 | - **PvP Settings:** Enable or disable player vs player combat and toggling. 45 | 46 | ### Multicharacter Support 47 | - **Character Limits:** Set the maximum number of characters a player can create. 48 | - **Discord ID Saving:** Choose to save Discord IDs in the character/user database. 49 | 50 | ### UI Core Settings 51 | - **UI Visibility:** Manage the visibility of various UI elements, including player cores and the Dead Eye core. 52 | 53 | ### Webhook Configurations 54 | - **Discord Integration:** Configure webhook color, name, logo, and footer for Discord integration. 55 | 56 | ### Map Configurations 57 | - **Radar Settings:** Customize radar types for different scenarios (on foot, on horse). 58 | 59 | ### Respawn Settings 60 | - **Health on Respawn/Resurrection:** Define health parameters for respawning and resurrection. 61 | - **Respawn Mechanics:** Configure respawn timers, keys, and combat logging penalties. 62 | 63 | ### Ban System Configurations 64 | - **Time Formatting:** Set the date and time format for ban notifications. 65 | - **Time Zone Settings:** Configure server time zone and time difference from UTC. 66 | 67 | ### Command Permission Settings 68 | - **Command Permissions:** Manage permissions for using various commands, including admin rights in the database. 69 | 70 | ### Discord Rich Presence Integration 71 | - **Rich Presence Settings:** Customize Discord rich presence, including maximum players, application ID, and button configurations. 72 | 73 | --- 74 | 75 | ### Commands Overview (`commands.lua`) 76 | 77 | ##### Administrative Commands 78 | - **addGroup:** Assign a group to a player with specified ID and group name. 79 | - **addJob:** Assign a job to a player, including job name, grade, and salary. 80 | - **addItem:** Add items to a player's inventory with item name and quantity. 81 | - **addWeapon:** Provide weapons to a player with weapon name and ammo count. 82 | - **delMoney:** Remove currency from a player's account, specifying type and amount. 83 | - **addMoney:** Add currency to a player's account, specifying type and amount. 84 | - **delWagons:** Delete a player's wagons. 85 | - **revive:** Revive a player with specified ID. 86 | - **teleport:** Teleport a player to a marked location. 87 | - **delHorse:** Delete a player's horse. 88 | - **heal:** Heal a player and replenish their needs. 89 | - **addWhitelist:** Add a player to the whitelist. 90 | - **unWhitelist:** Remove a player from the whitelist. 91 | - **ban:** Ban a player with specified duration. 92 | - **unBan:** Unban a player. 93 | - **warn:** Issue a warning to a player. 94 | - **unWarn:** Remove a warning from a player. 95 | - **charName:** Change a character's name. 96 | - **charCreateAdd:** Allow a player to create additional characters. 97 | - **charCreateRemove:** Remove a player's ability to create additional characters. 98 | - **myJob:** Display the player's current job and details. 99 | 100 | These commands and configurations offer extensive control over the server's gameplay, administration, and player management, ensuring a tailored and smooth experience for all participants. 101 | 102 | --- 103 | 104 | ## Support and Community 105 | 106 | For assistance, join the [VORP Core Discord](https://discord.gg/DHGVAbCj7N) community. Engage with developers and server administrators, share insights, and stay updated on the latest features and improvements. 107 | 108 | --- 109 | 110 | ## Credits 111 | 112 | - **Original Framework:** Inspired by the [VORP-Core C# version](https://github.com/VORPCORE/VORP-Core/releases), this Lua version extends the core's functionality while maintaining its foundational principles. 113 | - **Contributors:** Special thanks to `goncalobsccosta#9041` and all community members for their contributions and support in the development and enhancement of VORP Core. 114 | 115 | --- 116 | 117 | VORP Core Lua Version offers a robust platform for RedM servers, providing the tools necessary for a highly customizable and immersive gameplay experience. 118 | -------------------------------------------------------------------------------- /client/callbacks.lua: -------------------------------------------------------------------------------- 1 | ---@class ClientRPC @Callback class 2 | ---@field name string callback name 3 | ---@field _callback fun(any) | fun(cb: fun(data: any), ...) trigger or register 4 | ---@field uniqueId string callback unique id 5 | ClientRPC = {} 6 | ClientRPC.__index = ClientRPC 7 | ClientRPC.__call = function() 8 | return "ClientRPC" 9 | end 10 | 11 | local TriggeredCalls = {} 12 | local callBackId = 0 13 | 14 | ClientRPC.Callback = {} 15 | 16 | function ClientRPC:New(name, callback) 17 | local self = setmetatable({}, ClientRPC) 18 | self.name = name 19 | self._callback = callback 20 | self.uniqueId = "" 21 | return self 22 | end 23 | 24 | function ClientRPC:TriggerRpcAsync(...) 25 | if not self.name and type(self.name) ~= "string" then 26 | return error("Callback name must be a string!", 1) 27 | end 28 | 29 | callBackId = callBackId + 1 30 | if callBackId >= 65565 then 31 | callBackId = 0 32 | TriggeredCalls = {} 33 | end 34 | 35 | self.uniqueId = self.name .. tostring(callBackId) 36 | 37 | TriggerServerEvent("vorp:TriggerServerCallback", self.name, self.uniqueId, false, ...) 38 | 39 | TriggeredCalls[self.uniqueId] = self._callback 40 | end 41 | 42 | function ClientRPC:TriggerRpcAwait(...) 43 | if not self.name and type(self.name) ~= "string" then 44 | return error("Callback name must be a string!", 1) 45 | end 46 | 47 | callBackId = callBackId + 1 48 | if callBackId >= 65565 then 49 | callBackId = 0 50 | TriggeredCalls = {} 51 | end 52 | 53 | self.uniqueId = self.name .. tostring(callBackId) 54 | 55 | TriggerServerEvent("vorp:TriggerServerCallback", self.name, self.uniqueId, true, ...) 56 | 57 | local promise = promise.new() 58 | TriggeredCalls[self.uniqueId] = promise 59 | 60 | local result = Citizen.Await(promise) 61 | return result 62 | end 63 | 64 | function ClientRPC.ExecuteRpc(uniqueId, isSync, name, ...) 65 | if not TriggeredCalls[uniqueId] then 66 | return error("ERROR: No callback with this id found! callback name: " .. name, 1) 67 | end 68 | if not isSync then 69 | TriggeredCalls[uniqueId](...) 70 | else 71 | TriggeredCalls[uniqueId]:resolve(...) 72 | end 73 | 74 | TriggeredCalls[uniqueId] = nil 75 | end 76 | 77 | RegisterNetEvent('vorp:ServerCallback', ClientRPC.ExecuteRpc) 78 | 79 | 80 | --- * Trigger a callback Asynchronously 81 | ---@param name string callback name 82 | ---@param callback fun(any) callback function 83 | ---@param ... any callback parameters tables strings numbers etc 84 | function ClientRPC.Callback.TriggerAsync(name, callback, ...) 85 | local trigger = ClientRPC:New(name, callback) 86 | trigger:TriggerRpcAsync(...) 87 | end 88 | 89 | --- * Trigger a callback Synchronously 90 | ---@param name string callback name 91 | ---@param ... any callback parameters tables strings numbers etc 92 | ---@return any callback return 93 | function ClientRPC.Callback.TriggerAwait(name, ...) 94 | local trigger = ClientRPC:New(name, nil) 95 | return trigger:TriggerRpcAwait(...) 96 | end 97 | 98 | AddEventHandler('vorp:ExecuteServerCallBack', ClientRPC.Callback.TriggerAsync) 99 | 100 | 101 | --* REGISTER CLIENT CALLBACKS 102 | 103 | local RegisteredCalls = {} 104 | 105 | function ClientRPC:Trigger(uniqueId, isSync, ...) 106 | if not self._callback then 107 | return error("Callback " .. self.name .. " does not exist. Make sure it's registered in the server side.", 1) 108 | end 109 | 110 | self._callback(function(...) 111 | TriggerServerEvent("vorp:ServerCallback", uniqueId, isSync, self.name, ...) 112 | end, ...) 113 | end 114 | 115 | RegisterNetEvent("vorp:TriggerServerCallback", function(name, uniqueId, isSync, ...) 116 | if not RegisteredCalls[name] then 117 | return error("Callback " .. name .. " hasn't been registered.", 1) 118 | end 119 | 120 | RegisteredCalls[name]:Trigger(uniqueId, isSync, ...) 121 | end) 122 | 123 | --- * Register a callback 124 | ---@param name string callback name 125 | ---@param callback fun( func:fun(any),any) callback function 126 | function ClientRPC.Callback.Register(name, callback) 127 | if not name and type(name) ~= "string" then 128 | return error("Callback name must be a string!", 1) 129 | end 130 | 131 | RegisteredCalls[name] = ClientRPC:New(name, callback) 132 | end 133 | 134 | -- Export 135 | exports("ClientRpcCall", function() 136 | return ClientRPC 137 | end) 138 | -------------------------------------------------------------------------------- /client/clientapi.lua: -------------------------------------------------------------------------------- 1 | local ScreenResolution = nil 2 | local CoreFunctions = {} 3 | 4 | CoreFunctions.RpcCall = function(name, callback, ...) 5 | ClientRPC.Callback.TriggerAsync(name, callback, ...) 6 | end 7 | 8 | CoreFunctions.instancePlayers = function(set) 9 | TriggerServerEvent("vorp_core:instanceplayers", set) 10 | end 11 | 12 | CoreFunctions.AddWebhook = function(title, webhook, description, color, name, logo, footerlogo, avatar) 13 | TriggerServerEvent('vorp_core:addWebhook', title, webhook, description, color, name, logo, footerlogo, avatar) 14 | end 15 | 16 | CoreFunctions.NotifyTip = function(text, duration) 17 | VorpNotification:NotifyTip(tostring(text), tonumber(duration)) 18 | end 19 | 20 | CoreFunctions.NotifyLeft = function(title, subtitle, dict, icon, duration, color) 21 | VorpNotification:NotifyLeft(tostring(title), tostring(subtitle), tostring(dict), tostring(icon), tonumber(duration), tostring(color or "COLOR_WHITE")) 22 | end 23 | 24 | CoreFunctions.NotifyRightTip = function(text, duration) 25 | VorpNotification:NotifyRightTip(tostring(text), tonumber(duration)) 26 | end 27 | 28 | CoreFunctions.NotifyObjective = function(text, duration) 29 | TriggerEvent('vorp:TipBottom', text, duration) -- listner 30 | -- VorpNotification:NotifyObjective(tostring(text), tonumber(duration)) 31 | end 32 | 33 | CoreFunctions.NotifyTop = function(text, location, duration) 34 | VorpNotification:NotifyTop(tostring(text), tostring(location), tonumber(duration)) 35 | end 36 | 37 | CoreFunctions.NotifySimpleTop = function(text, subtitle, duration) 38 | VorpNotification:NotifySimpleTop(tostring(text), tostring(subtitle), tonumber(duration)) 39 | end 40 | 41 | CoreFunctions.NotifyAvanced = function(text, dict, icon, text_color, duration, quality, showquality) 42 | VorpNotification:NotifyAvanced(tostring(text), tostring(dict), tostring(icon), tostring(text_color), tonumber(duration), quality, showquality) 43 | end 44 | 45 | CoreFunctions.NotifyBasicTop = function(text, duration) 46 | VorpNotification:NotifyBasicTop(tostring(text), tonumber(duration)) 47 | end 48 | 49 | CoreFunctions.NotifyCenter = function(text, duration, text_color) 50 | VorpNotification:NotifyCenter(tostring(text), tonumber(duration), tostring(text_color)) 51 | end 52 | 53 | CoreFunctions.NotifyBottomRight = function(text, duration) 54 | VorpNotification:NotifyBottomRight(tostring(text), tonumber(duration)) 55 | end 56 | 57 | CoreFunctions.NotifyFail = function(text, subtitle, duration) 58 | VorpNotification:NotifyFail(tostring(text), tostring(subtitle), tonumber(duration)) 59 | end 60 | 61 | CoreFunctions.NotifyDead = function(title, audioRef, audioName, duration) 62 | VorpNotification:NotifyDead(tostring(title), tostring(audioRef), tostring(audioName), tonumber(duration)) 63 | end 64 | 65 | CoreFunctions.NotifyUpdate = function(title, subtitle, duration) 66 | VorpNotification:NotifyUpdate(tostring(title), tostring(subtitle), tonumber(duration)) 67 | end 68 | 69 | CoreFunctions.NotifyWarning = function(title, msg, audioRef, audioName, duration) 70 | VorpNotification:NotifyWarning(tostring(title), tostring(msg), tostring(audioRef), tostring(audioName), tonumber(duration)) 71 | end 72 | 73 | CoreFunctions.NotifyLeftRank = function(title, subtitle, dict, icon, duration, color) 74 | VorpNotification:NotifyLeftRank(tostring(title), tostring(subtitle), tostring(dict), tostring(icon), tonumber(duration), tostring(color or "COLOR_WHITE")) 75 | end 76 | 77 | 78 | CoreFunctions.Graphics = { 79 | ScreenResolution = function() 80 | local width, height = GetCurrentScreenResolution() 81 | return { width = width, height = height } 82 | end 83 | } 84 | 85 | CoreFunctions.Callback = { 86 | 87 | Register = function(name, callback) 88 | ClientRPC.Callback.Register(name, callback) 89 | end, 90 | TriggerAsync = function(name, callback, ...) 91 | ClientRPC.Callback.TriggerAsync(name, callback, ...) 92 | end, 93 | TriggerAwait = function(name, ...) 94 | return ClientRPC.Callback.TriggerAwait(name, ...) 95 | end 96 | } 97 | 98 | exports('GetCore', function() 99 | return CoreFunctions 100 | end) 101 | 102 | --- use exports 103 | ---@deprecated 104 | AddEventHandler('getCore', function(cb) 105 | return cb(CoreFunctions) 106 | end) 107 | -------------------------------------------------------------------------------- /client/commands.lua: -------------------------------------------------------------------------------- 1 | local T = Translation[Lang].MessageOfSystem 2 | local S = Translation[Lang].SuggestChat 3 | 4 | local StopAnimCommandCooldown = 0 5 | 6 | PlayerCommands = { 7 | hideui = { 8 | command = Config.CommandHideIU, 9 | suggestion = S.hideUi, 10 | run = function() 11 | CoreAction.Utils.ToggleAllUI() 12 | end, 13 | restricted = false 14 | }, 15 | toggleui = { 16 | command = Config.CommandToogleUI, 17 | suggestion = S.toogleUi, 18 | run = function() 19 | CoreAction.Utils.ToggleVorpUI() 20 | end, 21 | restricted = false 22 | }, 23 | clear = { 24 | command = Config.CommandClearAnim, 25 | suggestion = S.stopAnim, 26 | run = function() 27 | local ped = PlayerPedId() 28 | local hogtied = IsPedHogtied(ped) == 1 or IsPedHogtied(ped) == true 29 | local IsBeingHogtied = IsPedBeingHogtied(ped) == 1 or IsPedBeingHogtied(ped) == true 30 | local beingGrapple = Citizen.InvokeNative(0x3BDFCF25B58B0415, ped) 31 | local isFalling = IsPedFalling(ped) 32 | local isOnMount = IsPedOnMount(ped) 33 | local isInAir = IsEntityInAir(ped) 34 | 35 | local Timer = GetGameTimer() 36 | if (Timer - StopAnimCommandCooldown) < (Config.StopAnimCooldown * 1000) then 37 | VorpNotification:NotifyRightTip(T.StopAnimCooldown, 4000) 38 | return 39 | end 40 | 41 | if hogtied or IsPedCuffed(ped) or IsBeingHogtied or beingGrapple or isFalling or isOnMount or isInAir then 42 | return 43 | end 44 | 45 | StopAnimCommandCooldown = Timer 46 | ClearPedTasksImmediately(ped) 47 | end, 48 | restricted = false 49 | }, 50 | pvp = { 51 | command = Config.CommandOnOffPVP, 52 | suggestion = S.tooglePVP, 53 | run = function() 54 | local pvp = CoreAction.Utils.TogglePVP() 55 | 56 | if pvp then 57 | VorpNotification:NotifyRightTip(T.PVPNotifyOn, 4000) 58 | else 59 | VorpNotification:NotifyRightTip(T.PVPNotifyOff, 4000) 60 | end 61 | end, 62 | restricted = not Config.PVPToggle -- false means it should not display, so we have to negate with the not 63 | } 64 | } 65 | 66 | CreateThread(function() 67 | repeat Wait(5000) until LocalPlayer.state.IsInSession 68 | for _, value in pairs(PlayerCommands) do 69 | if not value.restricted then 70 | RegisterCommand(value.command, function() 71 | value.run() 72 | end, false) 73 | TriggerEvent("chat:addSuggestion", "/" .. value.command, value.suggestion) 74 | end 75 | end 76 | end) 77 | -------------------------------------------------------------------------------- /client/controllers.lua: -------------------------------------------------------------------------------- 1 | RegisterNetEvent('vorp:deleteVehicle') 2 | RegisterNetEvent('vorp:delHorse') 3 | AddEventHandler('vorp:deleteVehicle', CoreAction.Admin.DeleteVehicleInRadius) 4 | AddEventHandler('vorp:delHorse', CoreAction.Admin.DeleteHorse) 5 | RegisterNetEvent('vorp:teleportWayPoint', CoreAction.Admin.TeleportToWayPoint) 6 | RegisterNetEvent('vorp_core:Client:OnPlayerHeal', CoreAction.Admin.HealPlayer) 7 | RegisterNetEvent('vorp_core:Client:OnPlayerRespawn', function(param) 8 | CoreAction.Player.RespawnPlayer(param) 9 | end) 10 | RegisterNetEvent('vorp_core:Client:OnPlayerRevive', function(bool) 11 | bool = bool or true 12 | CoreAction.Player.ResurrectPlayer(false, nil, bool) 13 | end) 14 | 15 | 16 | ---@deprecated 17 | RegisterNetEvent("vorp:Heal", function() 18 | print("^3 vorp:Heal is deprecated, use vorp_core:Client:OnPlayerHeal instead^7") 19 | end) 20 | 21 | RegisterNetEvent("vorp_core:respawnPlayer", function() 22 | print("^3 vorp_core:respawnPlayer is deprecated, use vorp_core:Client:OnPlayerRespawn instead^7") 23 | end) 24 | 25 | RegisterNetEvent('vorp:resurrectPlayer', function(just) 26 | print("^3 vorp:resurrectPlayer is deprecated, use vorp_core:Client:OnPlayerRevive instead^7") 27 | end) 28 | -------------------------------------------------------------------------------- /client/coreactions.lua: -------------------------------------------------------------------------------- 1 | ---@class CoreAction CoreAction 2 | CoreAction = {} 3 | CoreAction.Admin = {} 4 | CoreAction.Utils = {} 5 | CoreAction.Player = {} 6 | 7 | local T = Translation[Lang].MessageOfSystem 8 | 9 | 10 | function CoreAction.Admin.HealPlayer() 11 | local player = PlayerPedId() 12 | local isPlayerDead = IsEntityDead(player) 13 | if isPlayerDead then 14 | print("cannot heal a dead player, revive player first") 15 | return 16 | end 17 | Citizen.InvokeNative(0xC6258F41D86676E0, player, 0, 100) -- _SET_ATTRIBUTE_CORE_VALUE HEALTH 18 | SetEntityHealth(player, 600, 1) 19 | Citizen.InvokeNative(0xC6258F41D86676E0, player, 1, 100) --_SET_ATTRIBUTE_CORE_VALUE STAMINA 20 | Citizen.InvokeNative(0x675680D089BFA21F, player, 1065330373) 21 | -- not sure why but player will be invincible from this point, only when max chars is to 1, makes no sense. so we gotta invoke these natives after healing. 22 | FreezeEntityPosition(player, false) 23 | SetEntityVisible(player, true) 24 | SetPlayerInvincible(PlayerId(), false) 25 | SetEntityCanBeDamaged(player, true) 26 | SetGameplayCamRelativeHeading(0.0, 1.0) 27 | end 28 | 29 | function CoreAction.Admin.DeleteHorse() 30 | local player = PlayerPedId() 31 | 32 | if not IsPedOnMount(player) then 33 | return VorpNotification:NotifyRightTip(T.sit, 3000) 34 | end 35 | local mount = GetMount(player) 36 | local attempt = 0 37 | if not NetworkHasControlOfEntity(mount) then 38 | NetworkRequestControlOfEntity(mount) 39 | repeat 40 | Wait(100) 41 | attempt = attempt + 1 42 | until NetworkHasControlOfEntity(mount) or attempt > 100 or not DoesEntityExist(mount) 43 | end 44 | 45 | DeleteEntity(mount) 46 | end 47 | 48 | local entityEnumerator = { 49 | __gc = function(enum) 50 | if enum.destructor and enum.handle then 51 | enum.destructor(enum.handle) 52 | end 53 | 54 | enum.destructor = nil 55 | enum.handle = nil 56 | end 57 | } 58 | 59 | local function EnumerateEntities(initFunc, moveFunc, disposeFunc) 60 | return coroutine.wrap(function() 61 | local iter, id = initFunc() 62 | if not id or id == 0 then 63 | disposeFunc(iter) 64 | return 65 | end 66 | 67 | local enum = { handle = iter, destructor = disposeFunc } 68 | setmetatable(enum, entityEnumerator) 69 | 70 | local next = true 71 | repeat 72 | coroutine.yield(id) 73 | next, id = moveFunc(iter) 74 | until not next 75 | 76 | enum.destructor, enum.handle = nil, nil 77 | disposeFunc(iter) 78 | end) 79 | end 80 | 81 | ---@param radius number 82 | function CoreAction.Admin.DeleteVehicleInRadius(radius) 83 | local player = PlayerPedId() 84 | 85 | local function EnumerateVehicles() 86 | return EnumerateEntities(FindFirstVehicle, FindNextVehicle, EndFindVehicle) 87 | end 88 | 89 | local function GetVehicles() 90 | local vehicles = {} 91 | 92 | for vehicle in EnumerateVehicles() do 93 | table.insert(vehicles, vehicle) 94 | end 95 | 96 | return vehicles 97 | end 98 | 99 | local function GetVehiclesInArea(coords, area) 100 | local vehicles = GetVehicles() 101 | local vehiclesInArea = {} 102 | 103 | for i = 1, #vehicles, 1 do 104 | local vehicleCoords = GetEntityCoords(vehicles[i]) 105 | local distance = #(coords - vehicleCoords) 106 | 107 | if distance <= area then 108 | table.insert(vehiclesInArea, vehicles[i]) 109 | end 110 | end 111 | 112 | return vehiclesInArea 113 | end 114 | 115 | local function GetVehicleInDirection() 116 | local playerPed = PlayerPedId() 117 | local playerCoords = GetEntityCoords(playerPed) 118 | local inDirection = GetOffsetFromEntityInWorldCoords(playerPed, 0.0, 5.0, 0.0) 119 | local rayHandle = StartExpensiveSynchronousShapeTestLosProbe(playerCoords.x, playerCoords.y, 120 | playerCoords.z, inDirection.x, inDirection.y, inDirection.z, 10, playerPed, 0) 121 | local _, hit, _, _, entityHit = GetShapeTestResult(rayHandle) 122 | 123 | if hit == 1 and GetEntityType(entityHit) == 2 then 124 | local entityCoords = GetEntityCoords(entityHit) 125 | return entityHit, entityCoords 126 | end 127 | 128 | return nil 129 | end 130 | 131 | if radius and tonumber(radius) then 132 | radius = tonumber(radius) + 0.01 133 | local vehicles = GetVehiclesInArea(GetEntityCoords(player), radius) 134 | for k, entity in ipairs(vehicles) do 135 | local attempt = 0 136 | 137 | while not NetworkHasControlOfEntity(entity) and attempt < 100 and DoesEntityExist(entity) do 138 | Wait(100) 139 | NetworkRequestControlOfEntity(entity) 140 | attempt = attempt + 1 141 | end 142 | 143 | if DoesEntityExist(entity) and NetworkHasControlOfEntity(entity) then 144 | SetEntityAsMissionEntity(entity, true, true) 145 | DeleteVehicle(entity) 146 | end 147 | end 148 | else 149 | local vehicle, attempt = GetVehicleInDirection(), 0 150 | 151 | if IsPedInAnyVehicle(player, true) then 152 | vehicle = GetVehiclePedIsIn(player, false) 153 | end 154 | 155 | while not NetworkHasControlOfEntity(vehicle) and attempt < 100 and DoesEntityExist(vehicle) do 156 | Wait(100) 157 | NetworkRequestControlOfEntity(vehicle) 158 | attempt = attempt + 1 159 | end 160 | 161 | if DoesEntityExist(vehicle) and NetworkHasControlOfEntity(vehicle) then 162 | SetEntityAsMissionEntity(vehicle, true, true) 163 | DeleteVehicle(vehicle) 164 | end 165 | end 166 | end 167 | 168 | --- teleport player to waypoint 169 | function CoreAction.Admin.TeleportToWayPoint() 170 | local ped = PlayerPedId() 171 | local GetGroundZAndNormalFor_3dCoord = GetGroundZAndNormalFor_3dCoord 172 | local waypoint = IsWaypointActive() 173 | local coords = GetWaypointCoords() 174 | local x, y, groundZ, startingpoint = coords.x, coords.y, 650.0, 750.0 175 | local found = false 176 | 177 | if not waypoint then 178 | return VorpNotification:NotifyRightTip(T.wayPoint, 3000) 179 | end 180 | 181 | DoScreenFadeOut(500) 182 | Wait(1000) 183 | FreezeEntityPosition(ped, true) 184 | for i = startingpoint, 0, -25.0 do 185 | local z = i 186 | if (i % 2) ~= 0 then 187 | z = startingpoint + i 188 | end 189 | SetEntityCoords(ped, x, y, z - 1000, false, false, false, false) 190 | Wait(1000) 191 | found, groundZ = GetGroundZAndNormalFor_3dCoord(x, y, z) 192 | if found then 193 | RequestCollisionAtCoord(x, y, groundZ) 194 | Wait(200) 195 | SetEntityCoords(ped, x, y, groundZ, false, false, false, false) 196 | repeat Wait(0) until HasCollisionLoadedAroundEntity(ped) 197 | FreezeEntityPosition(ped, false) 198 | Wait(1000) 199 | DoScreenFadeIn(650) 200 | break 201 | end 202 | end 203 | end 204 | 205 | function CoreAction.Utils.LoadModel(hash) 206 | if not IsModelValid(hash) then return false end 207 | 208 | if not HasModelLoaded(hash) then 209 | RequestModel(hash, false) 210 | repeat Wait(0) until HasModelLoaded(hash) 211 | return true 212 | end 213 | 214 | return true 215 | end 216 | 217 | function CoreAction.Utils.LoadTexture(hash) 218 | if not HasStreamedTextureDictLoaded(hash) then 219 | RequestStreamedTextureDict(hash, true) 220 | repeat Wait(0) until HasStreamedTextureDictLoaded(hash) 221 | return true 222 | end 223 | return true 224 | end 225 | 226 | function CoreAction.Utils.bigInt(text) 227 | local string1 = DataView.ArrayBuffer(16) 228 | string1:SetInt64(0, text) 229 | return string1:GetInt64(0) 230 | end 231 | -------------------------------------------------------------------------------- /client/dataview.lua: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------------------------------------- 2 | ------------------------------------------------------------------------------------------------------------- 3 | ----------------- DATAVIEW FUNCTIONS ------------- 4 | ----------------- ------------- 5 | ----------------- BIG THNKS to gottfriedleibniz for this DataView in LUA. ------------- 6 | ----------------- https://gist.github.com/gottfriedleibniz/8ff6e4f38f97dd43354a60f8494eedff ------------- 7 | ------------------------------------------------------------------------------------------------------------- 8 | ------------------------------------------------------------------------------------------------------------- 9 | 10 | local _strblob = string.blob or function(length) 11 | return string.rep("\0", math.max(40 + 1, length)) 12 | end 13 | 14 | DataView = { 15 | EndBig = ">", 16 | EndLittle = "<", 17 | Types = { 18 | Int8 = { code = "i1", size = 1 }, 19 | Uint8 = { code = "I1", size = 1 }, 20 | Int16 = { code = "i2", size = 2 }, 21 | Uint16 = { code = "I2", size = 2 }, 22 | Int32 = { code = "i4", size = 4 }, 23 | Uint32 = { code = "I4", size = 4 }, 24 | Int64 = { code = "i8", size = 8 }, 25 | Uint64 = { code = "I8", size = 8 }, 26 | 27 | LuaInt = { code = "j", size = 8 }, 28 | UluaInt = { code = "J", size = 8 }, 29 | LuaNum = { code = "n", size = 8 }, 30 | Float32 = { code = "f", size = 4 }, 31 | Float64 = { code = "d", size = 8 }, 32 | String = { code = "z", size = -1, }, 33 | }, 34 | 35 | FixedTypes = { 36 | String = { code = "c", size = -1, }, 37 | Int = { code = "i", size = -1, }, 38 | Uint = { code = "I", size = -1, }, 39 | }, 40 | } 41 | DataView.__index = DataView 42 | local function _ib(o, l, t) return ((t.size < 0 and true) or (o + (t.size - 1) <= l)) end 43 | 44 | local function _ef(big) return (big and DataView.EndBig) or DataView.EndLittle end 45 | 46 | local SetFixed = nil 47 | function DataView.ArrayBuffer(length) 48 | return setmetatable({ 49 | offset = 1, length = length, blob = _strblob(length) 50 | }, DataView) 51 | end 52 | 53 | function DataView.Wrap(blob) 54 | return setmetatable({ 55 | offset = 1, blob = blob, length = blob:len(), 56 | }, DataView) 57 | end 58 | 59 | function DataView:Buffer() return self.blob end 60 | 61 | function DataView:ByteLength() return self.length end 62 | 63 | function DataView:ByteOffset() return self.offset end 64 | 65 | function DataView:SubView(offset) 66 | return setmetatable({ 67 | offset = offset, blob = self.blob, length = self.length, 68 | }, DataView) 69 | end 70 | 71 | for label, datatype in pairs(DataView.Types) do 72 | DataView["Get" .. label] = function(self, offset, endian) 73 | local o = self.offset + offset 74 | if _ib(o, self.length, datatype) then 75 | local v, _ = string.unpack(_ef(endian) .. datatype.code, self.blob, o) 76 | return v 77 | end 78 | return nil 79 | end 80 | 81 | DataView["Set" .. label] = function(self, offset, value, endian) 82 | local o = self.offset + offset 83 | if _ib(o, self.length, datatype) then 84 | return SetFixed(self, o, value, _ef(endian) .. datatype.code) 85 | end 86 | return self 87 | end 88 | if datatype.size >= 0 and string.packsize(datatype.code) ~= datatype.size then 89 | local msg = "Pack size of %s (%d) does not match cached length: (%d)" 90 | error(msg:format(label, string.packsize(fmt[#fmt]), datatype.size)) 91 | return nil 92 | end 93 | end 94 | for label, datatype in pairs(DataView.FixedTypes) do 95 | DataView["GetFixed" .. label] = function(self, offset, typelen, endian) 96 | local o = self.offset + offset 97 | if o + (typelen - 1) <= self.length then 98 | local code = _ef(endian) .. "c" .. tostring(typelen) 99 | local v, _ = string.unpack(code, self.blob, o) 100 | return v 101 | end 102 | return nil 103 | end 104 | DataView["SetFixed" .. label] = function(self, offset, typelen, value, endian) 105 | local o = self.offset + offset 106 | if o + (typelen - 1) <= self.length then 107 | local code = _ef(endian) .. "c" .. tostring(typelen) 108 | return SetFixed(self, o, value, code) 109 | end 110 | return self 111 | end 112 | end 113 | 114 | SetFixed = function(self, offset, value, code) 115 | local fmt = {} 116 | local values = {} 117 | if self.offset < offset then 118 | local size = offset - self.offset 119 | fmt[#fmt + 1] = "c" .. tostring(size) 120 | values[#values + 1] = self.blob:sub(self.offset, size) 121 | end 122 | fmt[#fmt + 1] = code 123 | values[#values + 1] = value 124 | local ps = string.packsize(fmt[#fmt]) 125 | if (offset + ps) <= self.length then 126 | local newoff = offset + ps 127 | local size = self.length - newoff + 1 128 | 129 | fmt[#fmt + 1] = "c" .. tostring(size) 130 | values[#values + 1] = self.blob:sub(newoff, self.length) 131 | end 132 | self.blob = string.pack(table.concat(fmt, ""), table.unpack(values)) 133 | self.length = self.blob:len() 134 | return self 135 | end 136 | 137 | DataStream = {} 138 | DataStream.__index = DataStream 139 | 140 | function DataStream.New(view) 141 | return setmetatable({ view = view, offset = 0, }, DataStream) 142 | end 143 | 144 | for label, datatype in pairs(DataView.Types) do 145 | DataStream[label] = function(self, endian, align) 146 | local o = self.offset + self.view.offset 147 | if not _ib(o, self.view.length, datatype) then 148 | return nil 149 | end 150 | local v, no = string.unpack(_ef(endian) .. datatype.code, self.view:Buffer(), o) 151 | if align then 152 | self.offset = self.offset + math.max(no - o, align) 153 | else 154 | self.offset = no - self.view.offset 155 | end 156 | return v 157 | end 158 | end 159 | -------------------------------------------------------------------------------- /client/discrichpresence.lua: -------------------------------------------------------------------------------- 1 | CreateThread(function() 2 | local maxplayers = GetConvarInt('sv_maxClients', 48) 3 | SetDiscordAppId(Config.appid) 4 | SetDiscordRichPresenceAsset(Config.biglogo) 5 | SetDiscordRichPresenceAssetText(Config.biglogodesc) 6 | SetDiscordRichPresenceAssetSmall(Config.smalllogo) 7 | SetDiscordRichPresenceAssetSmallText(Config.smalllogodesc) 8 | if Config.Buttons and type(Config.Buttons) == "table" then 9 | for k, v in pairs(Config.Buttons) do 10 | SetDiscordRichPresenceAction(k - 1, v.text, v.url) 11 | end 12 | end 13 | 14 | while true do 15 | local playercount = ClientRPC.Callback.TriggerAwait("vorp:richpresence:callback:getplayers", {}) 16 | if Config.shownameandid then 17 | local pId = GetPlayerServerId(PlayerId()) 18 | local pName = GetPlayerName(PlayerId()) 19 | SetRichPresence(playercount .. "/" .. maxplayers .. " - ID: " .. pId .. " | " .. pName) 20 | else 21 | SetRichPresence(playercount .. "/" .. maxplayers) 22 | end 23 | Wait(60000) -- 1 min update 24 | end 25 | end) 26 | -------------------------------------------------------------------------------- /client/exports/exp_notifications.lua: -------------------------------------------------------------------------------- 1 | --============================= NOTIFICATION EXPORTS ==========================================-- 2 | 3 | exports("DisplayTip", function(text, duration) 4 | VorpNotification:NotifyTip(tostring(text), tonumber(duration)) 5 | end) 6 | 7 | exports("DisplayLeftNotification", function(title, subTitle, dict, icon, duration, color) 8 | VorpNotification:NotifyLeft(tostring(title), tostring(subTitle), tostring(dict), tostring(icon), tonumber(duration), 9 | (tostring(color) or "COLOR_WHITE")) 10 | end) 11 | 12 | exports("DisplayTopCenterNotification", function(text, location, duration) 13 | VorpNotification:NotifyTop(tostring(text), tostring(location), tonumber(duration)) 14 | end) 15 | 16 | exports("DisplayTipRight", function(text, duration) 17 | VorpNotification:NotifyRightTip(tostring(text), tonumber(duration)) 18 | end) 19 | 20 | exports("DisplayObjective", function(text, duration) 21 | VorpNotification:NotifyObjective(tostring(text), tonumber(duration)) 22 | end) 23 | 24 | exports("ShowTopNotification", function(title, subtext, duration) 25 | VorpNotification:NotifySimpleTop(tostring(title), tostring(subtext), tonumber(duration)) 26 | end) 27 | 28 | exports("ShowAdvancedRightNotification", function(_text, _dict, icon, text_color, duration, quality, showquality) 29 | VorpNotification:NotifyAvanced(tostring(_text), tostring(_dict), tostring(icon), tostring(text_color), 30 | tonumber(duration), quality, showquality) 31 | end) 32 | 33 | exports("ShowBasicTopNotification", function(text, duration) 34 | VorpNotification:NotifyBasicTop(tostring(text), tonumber(duration)) 35 | end) 36 | 37 | exports("ShowSimpleCenterText", function(text, duration, text_color) 38 | VorpNotification:NotifyCenter(tostring(text), tonumber(duration), tostring(text_color)) 39 | end) 40 | 41 | exports("showBottomRight", function(text, duration) 42 | VorpNotification:NotifyBottomRight(tostring(text), tonumber(duration)) 43 | end) 44 | 45 | exports("failmissioNotifY", function(title, subTitle, duration) 46 | VorpNotification:NotifyFail(tostring(title), tostring(subTitle), tonumber(duration)) 47 | end) 48 | 49 | exports("deadplayerNotifY", function(title, _audioRef, _audioName, duration) 50 | VorpNotification:NotifyDead(tostring(title), tostring(_audioRef), tostring(_audioName), tonumber(duration)) 51 | end) 52 | 53 | exports("updatemissioNotify", function(utitle, umsg, duration) 54 | VorpNotification:NotifyUpdate(tostring(utitle), tostring(umsg), tonumber(duration)) 55 | end) 56 | 57 | exports("warningNotify", function(title, msg, _audioRef, _audioName, duration) 58 | VorpNotification:NotifyWarning(tostring(title), tostring(msg), tostring(_audioRef), tostring(_audioName), 59 | tonumber(duration)) 60 | end) 61 | 62 | exports("LeftRank", function(title, subTitle, dict, icon, duration, color) 63 | VorpNotification:NotifyLeftRank(tostring(title), tostring(subTitle), tostring(dict), tostring(icon), tonumber(duration), 64 | (tostring(color))) 65 | end) -------------------------------------------------------------------------------- /client/instance.lua: -------------------------------------------------------------------------------- 1 | RegisterNetEvent('vorp:setInstancePlayer', function(instance) 2 | if instance then 3 | NetworkStartSoloTutorialSession() 4 | else 5 | NetworkEndTutorialSession() 6 | end 7 | end) 8 | -------------------------------------------------------------------------------- /client/miscellanea.lua: -------------------------------------------------------------------------------- 1 | local T = Translation[Lang].MessageOfSystem 2 | 3 | 4 | local function HidePlayerCores() 5 | local playerCores = { 6 | playerhealth = 0, 7 | playerhealthcore = 1, 8 | playerdeadeye = 3, 9 | playerdeadeyecore = 2, 10 | playerstamina = 4, 11 | playerstaminacore = 5, 12 | } 13 | 14 | local horsecores = { 15 | horsehealth = 6, 16 | horsehealthcore = 7, 17 | horsedeadeye = 9, 18 | horsedeadeyecore = 8, 19 | horsestamina = 10, 20 | horsestaminacore = 11, 21 | } 22 | 23 | if Config.HideOnlyDEADEYE then 24 | Citizen.InvokeNative(0xC116E6DF68DCE667, 2, 2) 25 | Citizen.InvokeNative(0xC116E6DF68DCE667, 3, 2) 26 | end 27 | if Config.HidePlayersCore then 28 | for key, value in pairs(playerCores) do 29 | Citizen.InvokeNative(0xC116E6DF68DCE667, value, 2) 30 | end 31 | end 32 | if Config.HideHorseCores then 33 | for key, value in pairs(horsecores) do 34 | Citizen.InvokeNative(0xC116E6DF68DCE667, value, 2) 35 | end 36 | end 37 | end 38 | 39 | local function FillUpCores() 40 | local a2 = DataView.ArrayBuffer(12 * 8) 41 | local a3 = DataView.ArrayBuffer(12 * 8) 42 | Citizen.InvokeNative(0xCB5D11F9508A928D, 1, a2:Buffer(), a3:Buffer(), GetHashKey("UPGRADE_HEALTH_TANK_1"), 1084182731, Config.maxHealth, 752097756) 43 | local a2 = DataView.ArrayBuffer(12 * 8) 44 | local a3 = DataView.ArrayBuffer(12 * 8) 45 | Citizen.InvokeNative(0xCB5D11F9508A928D, 1, a2:Buffer(), a3:Buffer(), GetHashKey("UPGRADE_STAMINA_TANK_1"), 1084182731, Config.maxStamina, 752097756) 46 | end 47 | 48 | -- remove event notifications 49 | local events = { 50 | [`EVENT_CHALLENGE_GOAL_COMPLETE`] = true, 51 | [`EVENT_CHALLENGE_REWARD`] = true, 52 | [`EVENT_DAILY_CHALLENGE_STREAK_COMPLETED`] = true, 53 | } 54 | 55 | --f6 photo mode doesnt work so just hide the prompt 56 | local function disablePhotoMode() 57 | DatabindingAddDataBoolFromPath('', 'bPauseMenuPhotoModeVisible', false) 58 | DatabindingAddDataBoolFromPath('', 'bEnablePauseMenuPhotoMode', false) 59 | end 60 | 61 | CreateThread(function() 62 | disablePhotoMode() 63 | HidePlayerCores() 64 | while true do 65 | Wait(0) 66 | local event = GetNumberOfEvents(0) 67 | 68 | if event > 0 then 69 | for i = 0, event - 1 do 70 | local eventAtIndex = GetEventAtIndex(0, i) 71 | if events[eventAtIndex] then 72 | Citizen.InvokeNative(0x6035E8FBCA32AC5E) -- _UI_FEED_CLEAR_ALL_CHANNELS 73 | end 74 | end 75 | end 76 | 77 | if Config.disableAutoAIM then 78 | Citizen.InvokeNative(0xD66A941F401E7302, 3) -- SET_PLAYER_TARGETING_MODE 79 | Citizen.InvokeNative(0x19B4F71703902238, 3) -- _SET_PLAYER_IN_VEHICLE_TARGETING_MODE 80 | end 81 | 82 | if Config.DisableCinematicMode then -- Cinematic Camera / Mode 83 | DisableCinematicModeThisFrame() 84 | end 85 | end 86 | end) 87 | 88 | -- show players id when focus on other players 89 | CreateThread(function() 90 | repeat Wait(5000) until LocalPlayer.state.IsInSession 91 | FillUpCores() 92 | 93 | while true do 94 | local sleep = 1000 95 | if #GetActivePlayers() > 1 then -- we also count ourselfs 96 | sleep = 400 97 | for _, playersid in ipairs(GetActivePlayers()) do 98 | if playersid ~= PlayerId() then 99 | local ped = GetPlayerPed(playersid) 100 | local id = GetPlayerServerId(playersid) 101 | local state = Player(id).state 102 | if state and state.Character then 103 | local name = Player(id).state.Character.FirstName .. " " .. Player(id).state.Character.LastName 104 | local promptName = Config.showplayerIDwhenfocus and GetPlayerServerId(playersid) or name 105 | SetPedPromptName(ped, T.PlayerWhenFocus .. promptName) 106 | else 107 | SetPedPromptName(ped, T.PlayerWhenFocus .. GetPlayerServerId(playersid)) 108 | end 109 | end 110 | end 111 | end 112 | Wait(sleep) 113 | end 114 | end) 115 | 116 | -- zoom in when in interiors for better navigation 117 | CreateThread(function() 118 | repeat Wait(5000) until LocalPlayer.state.IsInSession 119 | 120 | while true do 121 | Wait(500) 122 | local playerPed = PlayerPedId() 123 | local interiorId = GetInteriorFromEntity(playerPed) 124 | local hash = interiorId ~= 0 and 0xDF5DB58C or 0x25B517BF 125 | SetRadarConfigType(hash, 0) 126 | SetPedConfigFlag(playerPed, 560, true) -- enable horse ducking, needs to be here incase player ped id changes 127 | end 128 | end) 129 | -------------------------------------------------------------------------------- /client/notifications.lua: -------------------------------------------------------------------------------- 1 | -- NOTIFICATIONS 2 | RegisterNetEvent('vorp:NotifyLeft') 3 | RegisterNetEvent('vorp:Tip') 4 | RegisterNetEvent('vorp:NotifyTop') 5 | RegisterNetEvent('vorp:TipRight') 6 | RegisterNetEvent('vorp:TipBottom') 7 | RegisterNetEvent('vorp:ShowTopNotification') 8 | RegisterNetEvent('vorp:ShowAdvancedRightNotification') 9 | RegisterNetEvent('vorp:ShowBasicTopNotification') 10 | RegisterNetEvent('vorp:ShowSimpleCenterText') 11 | RegisterNetEvent('vorp:ShowBottomRight') 12 | RegisterNetEvent('vorp:failmissioNotifY') 13 | RegisterNetEvent('vorp:deadplayerNotifY') 14 | RegisterNetEvent('vorp:updatemissioNotify') 15 | RegisterNetEvent('vorp:warningNotify') 16 | RegisterNetEvent('vorp:LeftRank') 17 | 18 | 19 | AddEventHandler('vorp:NotifyLeft', function(firsttext, secondtext, dict, icon, duration, color) 20 | VorpNotification:NotifyLeft(tostring(firsttext), tostring(secondtext), tostring(dict), tostring(icon), tonumber(duration), (tostring(color) or "COLOR_WHITE")) 21 | end) 22 | 23 | AddEventHandler('vorp:Tip', function(text, duration) 24 | VorpNotification:NotifyTip(tostring(text), tonumber(duration)) 25 | end) 26 | 27 | AddEventHandler('vorp:NotifyTop', function(text, location, duration) 28 | VorpNotification:NotifyTop(tostring(text), tostring(location), tonumber(duration)) 29 | end) 30 | 31 | AddEventHandler('vorp:TipRight', function(text, duration) 32 | VorpNotification:NotifyRightTip(tostring(text), tonumber(duration)) 33 | end) 34 | 35 | AddEventHandler('vorp:TipBottom', function(text, duration) 36 | VorpNotification:NotifyObjective(tostring(text), tonumber(duration)) 37 | end) 38 | 39 | AddEventHandler('vorp:ShowTopNotification', function(tittle, subtitle, duration) 40 | VorpNotification:NotifySimpleTop(tostring(tittle), tostring(subtitle), tonumber(duration)) 41 | end) 42 | 43 | AddEventHandler('vorp:ShowAdvancedRightNotification', function(text, dict, icon, text_color, duration, quality) 44 | VorpNotification:NotifyAvanced(tostring(text), tostring(dict), tostring(icon), 45 | tostring(text_color), tonumber(duration), quality) 46 | end) 47 | 48 | AddEventHandler('vorp:ShowBasicTopNotification', function(text, duration) 49 | VorpNotification:NotifyBasicTop(tostring(text), tonumber(duration)) 50 | end) 51 | 52 | AddEventHandler('vorp:ShowSimpleCenterText', function(text, duration) 53 | VorpNotification:NotifyCenter(tostring(text), tonumber(duration)) 54 | end) 55 | 56 | AddEventHandler('vorp:ShowBottomRight', function(text, duration) 57 | VorpNotification:NotifyBottomRight(tostring(text), tonumber(duration)) 58 | end) 59 | 60 | AddEventHandler('vorp:failmissioNotifY', function(title, subtitle, duration) 61 | VorpNotification:NotifyFail(tostring(title), tostring(subtitle), tonumber(duration)) 62 | end) 63 | 64 | AddEventHandler('vorp:deadplayerNotifY', function(title, audioRef, audioName, duration) 65 | VorpNotification:NotifyDead(tostring(title), tostring(audioRef), tostring(audioName), tonumber(duration)) 66 | end) 67 | 68 | AddEventHandler('vorp:updatemissioNotify', function(utitle, umsg, duration) 69 | VorpNotification:NotifyUpdate(tostring(utitle), tostring(umsg), tonumber(duration)) 70 | end) 71 | 72 | AddEventHandler('vorp:warningNotify', function(title, msg, audioRef, audioName, duration) 73 | VorpNotification:NotifyWarning(tostring(title), tostring(msg), tostring(audioRef), tostring(audioName), 74 | tonumber(duration)) 75 | end) 76 | 77 | AddEventHandler('vorp:LeftRank', function(title, subtitle, dict, icon, duration, color) 78 | VorpNotification:NotifyLeftRank(tostring(title), tostring(subtitle), tostring(dict), tostring(icon), tonumber(duration), (tostring(color))) 79 | end) 80 | -------------------------------------------------------------------------------- /client/respawnsystem.lua: -------------------------------------------------------------------------------- 1 | local setDead = false 2 | local TimeToRespawn = 1 3 | local cam 4 | local angleY = 0.0 5 | local angleZ = 0.0 6 | local prompts = GetRandomIntInRange(0, 0xffffff) 7 | local prompt 8 | local PressKey = false 9 | local carried = false 10 | local Done = false 11 | local T = Translation[Lang].MessageOfSystem 12 | local keepdown 13 | 14 | local function CheckLabel() 15 | if not carried then 16 | if not Done then 17 | local label = VarString(10, 'LITERAL_STRING', 18 | T.RespawnIn .. TimeToRespawn .. T.SecondsMove .. T.message) 19 | return label 20 | else 21 | local label = VarString(10, 'LITERAL_STRING', T.message2) 22 | return label 23 | end 24 | else 25 | local label = VarString(10, 'LITERAL_STRING', T.YouAreCarried) 26 | return label 27 | end 28 | end 29 | 30 | local function RespawnTimer() 31 | TimeToRespawn = Config.RespawnTime 32 | CreateThread(function() -- asyncronous 33 | while true do 34 | Wait(1000) 35 | TimeToRespawn = TimeToRespawn - 1 36 | if TimeToRespawn < 0 and setDead then 37 | TimeToRespawn = 0 38 | break 39 | end 40 | 41 | if not setDead then 42 | TimeToRespawn = Config.RespawnTime 43 | break 44 | end 45 | end 46 | end) 47 | end 48 | 49 | local function ProcessNewPosition() 50 | local mouseX = 0.0 51 | local mouseY = 0.0 52 | if (IsInputDisabled(0)) then -- THIS DOESNT EXIST ? 53 | mouseX = GetDisabledControlNormal(1, 0x4D8FB4C1) * 1.5 54 | mouseY = GetDisabledControlNormal(1, 0xFDA83190) * 1.5 55 | else 56 | mouseX = GetDisabledControlNormal(1, 0x4D8FB4C1) * 0.5 57 | mouseY = GetDisabledControlNormal(1, 0xFDA83190) * 0.5 58 | end 59 | angleZ = angleZ - mouseX 60 | angleY = angleY + mouseY 61 | 62 | if (angleY > 89.0) then angleY = 89.0 elseif (angleY < -89.0) then angleY = -89.0 end 63 | local pCoords = GetEntityCoords(PlayerPedId()) 64 | local behindCam = { 65 | x = pCoords.x + ((Cos(angleZ) * Cos(angleY)) + (Cos(angleY) * Cos(angleZ))) / 2 * (3.0 + 0.5), 66 | y = pCoords.y + ((Sin(angleZ) * Cos(angleY)) + (Cos(angleY) * Sin(angleZ))) / 2 * (3.0 + 0.5), 67 | z = pCoords.z + ((Sin(angleY))) * (3.0 + 0.5) 68 | } 69 | local rayHandle = StartShapeTestLosProbe(pCoords.x, pCoords.y, pCoords.z + 0.5, behindCam.x, behindCam.y, behindCam.z, -1, PlayerPedId(), 0) 70 | local hitBool, hitCoords = GetShapeTestResult(rayHandle) 71 | 72 | local maxRadius = 3.0 73 | if (hitBool and Vdist(pCoords.x, pCoords.y, pCoords.z + 0.5, hitCoords, 0, 0) < 3.0 + 0.5) then 74 | maxRadius = Vdist(pCoords.x, pCoords.y, pCoords.z + 0.5, hitCoords, 0, 0) 75 | end 76 | 77 | local offset = { 78 | x = ((Cos(angleZ) * Cos(angleY)) + (Cos(angleY) * Cos(angleZ))) / 2 * maxRadius, 79 | y = ((Sin(angleZ) * Cos(angleY)) + (Cos(angleY) * Sin(angleZ))) / 2 * maxRadius, 80 | z = ((Sin(angleY))) * maxRadius 81 | } 82 | 83 | local pos = { 84 | x = pCoords.x + offset.x, 85 | y = pCoords.y + offset.y, 86 | z = pCoords.z + offset.z 87 | } 88 | 89 | return pos 90 | end 91 | 92 | local function StartDeathCam() 93 | ClearFocus() 94 | local playerPed = PlayerPedId() 95 | local pos = GetEntityCoords(playerPed) 96 | cam = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", pos.x, pos.y, pos.z, 0, 0, 0, GetGameplayCamFov(), false, 0) 97 | SetCamActive(cam, true) 98 | RenderScriptCams(true, true, 1000, true, false, 0) 99 | end 100 | 101 | local function ProcessCamControls() 102 | local playerCoords 103 | if Config.UseControlsCamera then 104 | playerCoords = ProcessNewPosition() 105 | else 106 | playerCoords = GetEntityCoords(PlayerPedId()) 107 | end 108 | 109 | local newPos = playerCoords 110 | if IsEntityAttachedToAnyPed(PlayerPedId()) then 111 | SetCamCoord(cam, newPos.x, newPos.y + -2, newPos.z + 0.50) 112 | SetCamRot(cam, -20.0, 0.0, 0.0, 1) 113 | SetCamFov(cam, 50.0) 114 | else 115 | SetCamCoord(cam, newPos.x, newPos.y, newPos.z + 1.0) 116 | SetCamRot(cam, -80.0, 0.0, 0.0, 1) 117 | SetCamFov(cam, 50.0) 118 | end 119 | end 120 | 121 | local function EndDeathCam() 122 | NetworkSetInSpectatorMode(false, PlayerPedId()) 123 | ClearFocus() 124 | RenderScriptCams(false, false, 0, true, false, 0) 125 | DestroyCam(cam, false) 126 | cam = nil 127 | DestroyAllCams(true) 128 | end 129 | 130 | function CoreAction.Player.ResurrectPlayer(currentHospital, currentHospitalName, justrevive) 131 | local player = PlayerPedId() 132 | Citizen.InvokeNative(0xCE7A90B160F75046, false) --SET_CINEMATIC_MODE_ACTIVE 133 | TriggerEvent("vorp:showUi", not Config.HideUi) 134 | ResurrectPed(player) 135 | Wait(200) 136 | EndDeathCam() 137 | TriggerServerEvent("vorp:ImDead", false) 138 | -- this cant be here cause its triggering on revive and on respawn functions also these are client sided and people can exploit them, this has been move to server side 139 | --TriggerServerEvent("vorp_core:Server:OnPlayerRevive") 140 | -- TriggerEvent("vorp_core:Client:OnPlayerRevive") 141 | setDead = false 142 | DisplayHud(true) 143 | DisplayRadar(true) 144 | CoreAction.Utils.setPVP() 145 | TriggerEvent("vorpcharacter:reloadafterdeath") 146 | Wait(500) 147 | if currentHospital and currentHospital then 148 | Citizen.InvokeNative(0x203BEFFDBE12E96A, player, currentHospital, false, false, false) -- _SET_ENTITY_COORDS_AND_HEADING 149 | end 150 | Wait(2000) 151 | CoreAction.Admin.HealPlayer() 152 | if Config.RagdollOnResurrection and not justrevive then 153 | keepdown = true 154 | CreateThread(function() 155 | while keepdown do 156 | Wait(0) 157 | SetPedToRagdoll(player, 4000, 4000, 0, false, false, false) 158 | ResetPedRagdollTimer(player) 159 | DisablePedPainAudio(player, true) 160 | end 161 | end) 162 | AnimpostfxPlay("Title_Gen_FewHoursLater") 163 | Wait(3000) 164 | DoScreenFadeIn(2000) 165 | AnimpostfxPlay("PlayerWakeUpInterrogation") 166 | Wait(19000) 167 | keepdown = false 168 | VorpNotification:NotifyLeft(currentHospitalName or T.message6, T.message5, "minigames_hud", "five_finger_burnout", 8000, "COLOR_PURE_WHITE") 169 | else 170 | DoScreenFadeIn(2000) 171 | end 172 | end 173 | 174 | function CoreAction.Player.RespawnPlayer(allowCleanItems) 175 | if allowCleanItems then 176 | TriggerServerEvent("vorp:PlayerForceRespawn") -- inventory clean items 177 | end 178 | TriggerEvent("vorp:PlayerForceRespawn") -- inventory dead handler and metabolism , this need to be changed to the new events 179 | local closestDistance = math.huge 180 | local closestLocation = "" 181 | local coords = nil 182 | local pedCoords = GetEntityCoords(PlayerPedId()) 183 | for key, location in pairs(Config.Hospitals) do 184 | local locationCoords = vector3(location.pos.x, location.pos.y, location.pos.z) 185 | local currentDistance = #(pedCoords - locationCoords) 186 | if currentDistance < closestDistance then 187 | closestDistance = currentDistance 188 | closestLocation = location.name 189 | coords = location.pos 190 | end 191 | end 192 | 193 | TriggerEvent("vorpmetabolism:changeValue", "Thirst", 1000) 194 | TriggerEvent("vorpmetabolism:changeValue", "Hunger", 1000) 195 | CoreAction.Player.ResurrectPlayer(coords, closestLocation, false) -- no need to trigger events repawns even already triggered 196 | end 197 | 198 | -- CREATE PROMPT 199 | CreateThread(function() 200 | repeat Wait(1000) until LocalPlayer.state.IsInSession 201 | local str = T.prompt 202 | local keyPress = Config.RespawnKey 203 | prompt = UiPromptRegisterBegin() 204 | UiPromptSetControlAction(prompt, keyPress) 205 | str = VarString(10, 'LITERAL_STRING', str) 206 | UiPromptSetText(prompt, str) 207 | UiPromptSetEnabled(prompt, true) 208 | UiPromptSetVisible(prompt, true) 209 | UiPromptSetHoldMode(prompt, Config.RespawnKeyTime) 210 | UiPromptSetGroup(prompt, prompts, 0) 211 | UiPromptSetPriority(prompt, 3) 212 | UiPromptRegisterEnd(prompt) 213 | end) 214 | 215 | RegisterNetEvent("vorp_core:Client:AddTimeToRespawn") 216 | AddEventHandler("vorp_core:Client:AddTimeToRespawn", function(time) 217 | if TimeToRespawn >= 1 then 218 | TimeToRespawn = TimeToRespawn + time 219 | else 220 | RespawnTimer() 221 | end 222 | end) 223 | 224 | 225 | --DEATH HANDLER 226 | CreateThread(function() 227 | repeat Wait(1000) until LocalPlayer.state.IsInSession 228 | while Config.UseDeathHandler do 229 | local sleep = 1000 230 | 231 | if IsPlayerDead(PlayerId()) then 232 | if not setDead then 233 | setDead = true 234 | PressKey = false 235 | UiPromptSetEnabled(prompt, true) 236 | NetworkSetInSpectatorMode(false, PlayerPedId()) 237 | exports.spawnmanager.setAutoSpawn(false) 238 | TriggerServerEvent("vorp:ImDead", true) -- internal event 239 | local getKillerPed = GetPedSourceOfDeath(PlayerPedId()) 240 | local killerServerId = 0 241 | if IsPedAPlayer(getKillerPed) then 242 | local killer = NetworkGetPlayerIndexFromPed(getKillerPed) 243 | if killer then 244 | killerServerId = GetPlayerServerId(killer) 245 | end 246 | end 247 | local deathCause = GetPedCauseOfDeath(PlayerPedId()) 248 | TriggerServerEvent("vorp_core:Server:OnPlayerDeath", killerServerId, deathCause) 249 | TriggerEvent("vorp_core:Client:OnPlayerDeath", killerServerId, deathCause) 250 | DisplayRadar(false) 251 | CreateThread(RespawnTimer) 252 | CreateThread(StartDeathCam) 253 | end 254 | if not PressKey and setDead then 255 | sleep = 0 256 | if not IsEntityAttachedToAnyPed(PlayerPedId()) then 257 | UiPromptSetActiveGroupThisFrame(prompts, CheckLabel(), 0, 0, 0, 0) 258 | 259 | if UiPromptHasHoldModeCompleted(prompt) then 260 | if Config.CanRespawn() then 261 | DoScreenFadeOut(3000) 262 | Wait(3000) 263 | TriggerServerEvent("vorp_core:PlayerRespawnInternal", true) -- needs to go to server so that the respawn event listeners are triggered 264 | Wait(1000) 265 | PressKey = true 266 | carried = false 267 | Done = false 268 | TimeToRespawn = Config.RespawnTime 269 | end 270 | end 271 | 272 | if TimeToRespawn >= 1 and setDead then 273 | ProcessCamControls() 274 | Done = false 275 | UiPromptSetEnabled(prompt, false) 276 | else 277 | ProcessCamControls() 278 | Done = true 279 | UiPromptSetEnabled(prompt, true) 280 | end 281 | carried = false 282 | else 283 | if setDead then 284 | UiPromptSetActiveGroupThisFrame(prompts, CheckLabel(), 0, 0, 0, 0) 285 | UiPromptSetEnabled(prompt, false) 286 | ProcessCamControls() 287 | carried = true 288 | end 289 | end 290 | end 291 | end 292 | 293 | Wait(sleep) 294 | end 295 | end) 296 | -------------------------------------------------------------------------------- /client/spawnplayer.lua: -------------------------------------------------------------------------------- 1 | local HealthData = {} 2 | local pvp = Config.PVP 3 | local multiplierHealth, multiplierStamina 4 | local T = Translation[Lang].MessageOfSystem 5 | local active = false 6 | -- FUNCTIONS 7 | function CoreAction.Utils.TogglePVP() 8 | pvp = not pvp 9 | TriggerEvent("vorp:setPVPUi", pvp) 10 | return pvp 11 | end 12 | 13 | function CoreAction.Utils.setPVP() 14 | local playerHash = joaat("PLAYER") 15 | NetworkSetFriendlyFireOption(pvp) 16 | 17 | if not active then 18 | if pvp then 19 | SetRelationshipBetweenGroups(5, playerHash, playerHash) 20 | else 21 | SetRelationshipBetweenGroups(1, playerHash, playerHash) 22 | end 23 | else 24 | SetRelationshipBetweenGroups(1, playerHash, playerHash) 25 | end 26 | end 27 | 28 | function CoreAction.Player.TeleportToCoords(coords, heading) 29 | StartPlayerTeleport(PlayerId(), coords.x, coords.y, coords.z, heading, true, true, true, false) 30 | repeat Wait(0) until not IsPlayerTeleportActive() 31 | RequestCollisionAtCoord(coords.x, coords.y, coords.z) 32 | repeat Wait(0) until HasCollisionLoadedAroundEntity(PlayerPedId()) 33 | end 34 | 35 | function CoreAction.Player.MapCheck() 36 | while Config.enableTypeRadar do 37 | Wait(3000) 38 | local player = PlayerPedId() 39 | local playerOnMout = IsPedOnMount(player) 40 | local playerOnVeh = IsPedInAnyVehicle(player, false) 41 | if not playerOnMout and not playerOnVeh then 42 | SetMinimapType(Config.mapTypeOnFoot) 43 | elseif playerOnMout or playerOnVeh then 44 | SetMinimapType(Config.mapTypeOnMount) 45 | end 46 | end 47 | end 48 | 49 | -- PLAYERSPAWN 50 | AddEventHandler('playerSpawned', function() 51 | DoScreenFadeOut(0) 52 | local random = GetRandomIntInRange(0, 10000) + PlayerId() 53 | TriggerServerEvent('vorp_core:instanceplayers', random) 54 | Citizen.InvokeNative(0x1E5B70E53DB661E5, 0, 0, 0, T.Hold, T.Load, T.Almost) --_DISPLAY_LOADING_SCREENS 55 | DisplayRadar(false) 56 | SetMinimapHideFow(false) 57 | Wait(2000) 58 | TriggerServerEvent("vorp:playerSpawn") 59 | SetTimeout(7000, function() 60 | ShutdownLoadingScreen() 61 | end) 62 | SetEntityCanBeDamaged(PlayerPedId(), false) 63 | CreateThread(function() 64 | while not LocalPlayer.state.IsInSession do 65 | Wait(0) 66 | DisableControlAction(0, `INPUT_MP_TEXT_CHAT_ALL`, true) 67 | DisableControlAction(0, `INPUT_QUICK_USE_ITEM`, true) 68 | end 69 | end) 70 | end) 71 | 72 | --EVENTS character Innitialize 73 | RegisterNetEvent('vorp:initCharacter') 74 | AddEventHandler('vorp:initCharacter', function(coords, heading, isdead) 75 | CoreAction.Player.TeleportToCoords(coords, heading) 76 | if isdead then 77 | if not Config.CombatLogDeath then 78 | if Config.Loadinscreen then 79 | Citizen.InvokeNative(0x1E5B70E53DB661E5, 0, 0, 0, T.forcedrespawn, T.forced, T.Almost) 80 | end 81 | SetEntityCanBeDamaged(PlayerPedId(), true) 82 | CoreAction.Player.RespawnPlayer() -- this one doesnt need to trigger events, its for player combat log 83 | Wait(Config.LoadinScreenTimer) 84 | Wait(1000) 85 | ShutdownLoadingScreen() 86 | Wait(5000) 87 | else 88 | if Config.Loadinscreen then 89 | Citizen.InvokeNative(0x1E5B70E53DB661E5, 0, 0, 0, T.Holddead, T.Loaddead, T.Almost) 90 | end 91 | Wait(10000) 92 | TriggerEvent("vorp_inventory:CloseInv") 93 | Wait(4000) 94 | SetEntityCanBeDamaged(PlayerPedId(), true) 95 | SetEntityHealth(PlayerPedId(), 0, 0) 96 | Citizen.InvokeNative(0xC6258F41D86676E0, PlayerPedId(), 0, -1) 97 | ShutdownLoadingScreen() 98 | end 99 | else 100 | local PlayerId = PlayerId() 101 | if Config.Loadinscreen then 102 | if Config.LoadingScreenPlayerInfo then 103 | Citizen.InvokeNative(0x1E5B70E53DB661E5, 0, 0, 0, LocalPlayer.state.Character.FirstName .. " " .. LocalPlayer.state.Character.LastName, "Job:" .. " " .. LocalPlayer.state.Character.JobLabel) 104 | else 105 | Citizen.InvokeNative(0x1E5B70E53DB661E5, 0, 0, 0, T.Hold, T.Load, T.Almost) 106 | end 107 | Wait(Config.LoadinScreenTimer) 108 | Wait(1000) 109 | ShutdownLoadingScreen() 110 | end 111 | 112 | if not Config.HealthRecharge.enable then 113 | Citizen.InvokeNative(0x8899C244EBCF70DE, PlayerId, 0.0) -- SetPlayerHealthRechargeMultiplier 114 | else 115 | Citizen.InvokeNative(0x8899C244EBCF70DE, PlayerId, Config.HealthRecharge.multiplier) 116 | multiplierHealth = Citizen.InvokeNative(0x22CD23BB0C45E0CD, PlayerId) -- GetPlayerHealthRechargeMultiplier 117 | end 118 | 119 | if not Config.StaminaRecharge.enable then 120 | Citizen.InvokeNative(0xFECA17CF3343694B, PlayerId, 0.0) -- SetPlayerStaminaRechargeMultiplier 121 | else 122 | Citizen.InvokeNative(0xFECA17CF3343694B, PlayerId, Config.StaminaRecharge.multiplier) 123 | multiplierStamina = Citizen.InvokeNative(0x617D3494AD58200F, PlayerId) -- GetPlayerStaminaRechargeMultiplier 124 | end 125 | 126 | SetEntityCanBeDamaged(PlayerPedId(), true) 127 | 128 | if Config.SavePlayersStatus then 129 | TriggerServerEvent("vorp:GetValues") 130 | Wait(200) 131 | if HealthData then 132 | local player = PlayerPedId() 133 | Citizen.InvokeNative(0xC6258F41D86676E0, player, 0, HealthData.hInner or 600) 134 | SetEntityHealth(player, (HealthData.hOuter and HealthData.hOuter > 0 and HealthData.hOuter or 600) + (HealthData.hInner and HealthData.hInner > 0 and HealthData.hInner or 600), 0) 135 | Citizen.InvokeNative(0xC6258F41D86676E0, player, 1, HealthData.sInner or 600) 136 | Citizen.InvokeNative(0x675680D089BFA21F, player, (HealthData.sOuter or (1065353215 * 100)) / 1065353215 * 100) 137 | end 138 | HealthData = {} 139 | else 140 | CoreAction.Admin.HealPlayer() 141 | end 142 | end 143 | 144 | TriggerEvent("vorp_core:Client:onPlayerSpawned") 145 | 146 | SetTimeout(2000, function() 147 | DoScreenFadeIn(4000) 148 | repeat Wait(500) until IsScreenFadedIn() 149 | end) 150 | end) 151 | 152 | 153 | -- PLAYER SPAWN AFTER SELECT CHARACTER 154 | RegisterNetEvent("vorp:SelectedCharacter", function() 155 | CoreAction.Utils.setPVP() 156 | local PlayerPed = PlayerPedId() 157 | local PlayerId = PlayerId() 158 | SetEntityCanBeDamaged(PlayerPed, true) 159 | Citizen.InvokeNative(0xA63FCAD3A6FEC6D2, PlayerId, Config.ActiveEagleEye) 160 | Citizen.InvokeNative(0x95EE1DEE1DCD9070, PlayerId, Config.ActiveDeadEye) 161 | TriggerEvent("vorp:showUi", not Config.HideUi) 162 | DisplayRadar(true) 163 | SetMinimapHideFow(true) 164 | TriggerServerEvent("vorp:chatSuggestion") 165 | TriggerServerEvent('vorp_core:instanceplayers', 0) -- remove instanced players 166 | TriggerServerEvent("vorp:SaveDate") 167 | 168 | SetTimeout(10000, function() 169 | -- GUARMA SPAWN 170 | local pedCoords = GetEntityCoords(PlayerPedId()) 171 | local area = Citizen.InvokeNative(0x43AD8FC02B429D33, pedCoords, 10) 172 | if area == -512529193 then 173 | Citizen.InvokeNative(0xA657EC9DBC6CC900, 1935063277) 174 | Citizen.InvokeNative(0xE8770EE02AEE45C2, 1) 175 | Citizen.InvokeNative(0x74E2261D2A66849A, true) 176 | end 177 | end) 178 | 179 | CreateThread(CoreAction.Player.MapCheck) 180 | end) 181 | 182 | RegisterNetEvent("vorp:GetHealthFromCore") 183 | AddEventHandler("vorp:GetHealthFromCore", function(healthData) 184 | HealthData = healthData 185 | end) 186 | 187 | -- THREADS 188 | CreateThread(function() 189 | repeat Wait(5000) until LocalPlayer.state.IsInSession 190 | while true do 191 | local sleep = 1000 192 | local pped = PlayerPedId() 193 | 194 | sleep = 0 195 | if IsControlPressed(0, 0xCEFD9220) then 196 | active = true 197 | CoreAction.Utils.setPVP() 198 | Wait(4000) 199 | end 200 | 201 | if not IsPedOnMount(pped) and not IsPedInAnyVehicle(pped, false) and active then 202 | active = false 203 | CoreAction.Utils.setPVP() 204 | elseif active and IsPedOnMount(pped) or IsPedInAnyVehicle(pped, false) then 205 | if IsPedInAnyVehicle(pped, false) then 206 | 207 | elseif GetPedInVehicleSeat(GetMount(pped), -1) == pped then 208 | active = false 209 | CoreAction.Utils.setPVP() 210 | end 211 | else 212 | CoreAction.Utils.setPVP() 213 | end 214 | 215 | Wait(sleep) 216 | end 217 | end) 218 | 219 | 220 | 221 | CreateThread(function() 222 | while true do 223 | Wait(0) 224 | DisableControlAction(0, 0x580C4473, true) -- Disable hud 225 | DisableControlAction(0, 0xCF8A4ECA, true) -- Disable hud 226 | DisableControlAction(0, 0x9CC7A1A4, true) -- disable special ability when open hud 227 | DisableControlAction(0, 0x1F6D95E5, true) -- diable f4 key that contains HUD 228 | end 229 | end) 230 | 231 | 232 | CreateThread(function() 233 | repeat Wait(5000) until LocalPlayer.state.IsInSession 234 | while Config.SavePlayersStatus do 235 | Wait(1000) 236 | local player = PlayerPedId() 237 | local innerCoreHealth = Citizen.InvokeNative(0x36731AC041289BB1, player, 0) 238 | local outerCoreStamina = Citizen.InvokeNative(0x22F2A386D43048A9, player) 239 | local innerCoreStamina = Citizen.InvokeNative(0x36731AC041289BB1, player, 1) 240 | local getHealth = GetEntityHealth(player) 241 | TriggerServerEvent("vorp:HealthCached", getHealth, innerCoreHealth, outerCoreStamina, innerCoreStamina) 242 | end 243 | end) 244 | 245 | CreateThread(function() 246 | repeat Wait(5000) until LocalPlayer.state.IsInSession 247 | while Config.SavePlayersStatus do 248 | local player = PlayerPedId() 249 | Wait(300000) -- wont be accurate as it waits for too long 250 | local innerCoreHealth = Citizen.InvokeNative(0x36731AC041289BB1, player, 0, Citizen.ResultAsInteger()) 251 | local outerCoreStamina = Citizen.InvokeNative(0x22F2A386D43048A9, player) 252 | local innerCoreStamina = Citizen.InvokeNative(0x36731AC041289BB1, player, 1, Citizen.ResultAsInteger()) 253 | local getHealth = GetEntityHealth(player) 254 | local innerHealth = tonumber(innerCoreHealth) 255 | local innerStamina = tonumber(innerCoreStamina) 256 | TriggerServerEvent("vorp:SaveHealth", getHealth, innerHealth) 257 | TriggerServerEvent("vorp:SaveStamina", outerCoreStamina, innerStamina) 258 | end 259 | end) 260 | 261 | -- APPLY HEALTHRECHARGE WHEN CHARACTER RC 262 | CreateThread(function() 263 | repeat Wait(5000) until LocalPlayer.state.IsInSession 264 | 265 | while true do 266 | local sleep = 1000 267 | 268 | if not IsPlayerDead(PlayerId()) then 269 | sleep = 500 270 | local PlayerId = PlayerId() 271 | local multiplierH = Citizen.InvokeNative(0x22CD23BB0C45E0CD, PlayerId) -- GetPlayerHealthRechargeMultiplier 272 | 273 | if multiplierHealth and multiplierHealth ~= multiplierH then 274 | Wait(500) 275 | Citizen.InvokeNative(0x8899C244EBCF70DE, PlayerId, Config.HealthRecharge.multiplier) -- SetPlayerHealthRechargeMultiplier 276 | elseif not multiplierHealth and multiplierH then 277 | Wait(500) 278 | Citizen.InvokeNative(0x8899C244EBCF70DE, PlayerId, 0.0) -- SetPlayerHealthRechargeMultiplier 279 | end 280 | 281 | local multiplierS = Citizen.InvokeNative(0x617D3494AD58200F, PlayerId) -- GetPlayerStaminaRechargeMultiplier 282 | 283 | if multiplierStamina and multiplierStamina ~= multiplierS then 284 | Wait(500) 285 | Citizen.InvokeNative(0xFECA17CF3343694B, PlayerId, Config.StaminaRecharge.multiplier) -- SetPlayerStaminaRechargeMultiplier 286 | elseif not multiplierStamina and multiplierS then 287 | Wait(500) 288 | Citizen.InvokeNative(0xFECA17CF3343694B, PlayerId, 0.0) -- SetPlayerStaminaRechargeMultiplier 289 | end 290 | end 291 | 292 | Wait(sleep) 293 | end 294 | end) 295 | -------------------------------------------------------------------------------- /client/uicore.lua: -------------------------------------------------------------------------------- 1 | local vorpShowUI = true 2 | local ShowUI = true 3 | 4 | function CoreAction.Utils.ToggleVorpUI() 5 | vorpShowUI = not vorpShowUI 6 | TriggerEvent("vorp:showUi", vorpShowUI) 7 | end 8 | 9 | function CoreAction.Utils.ToggleAllUI() 10 | ShowUI = not ShowUI 11 | DisplayRadar(ShowUI) 12 | TriggerEvent("syn_displayrange", ShowUI) 13 | TriggerEvent("vorp:showUi", ShowUI) 14 | end 15 | 16 | RegisterNetEvent('vorp:updateUi', function(stringJson) 17 | SendNUIMessage(json.decode(stringJson)) 18 | end) 19 | 20 | RegisterNetEvent('vorp:showUi', function(active) 21 | vorpShowUI = active 22 | local jsonpost = { type = "ui", action = "hide" } 23 | if active then jsonpost = { type = "ui", action = "show" } end 24 | 25 | SendNUIMessage(jsonpost) 26 | end) 27 | 28 | RegisterNetEvent('vorp:setPVPUi', function(active) 29 | SendNUIMessage({ type = "ui", action = "setpvp", pvp = active }) 30 | end) 31 | 32 | RegisterNetEvent('vorp:SelectedCharacter', function() 33 | Wait(10000) 34 | SendNUIMessage({ 35 | type = "ui", 36 | action = "initiate", 37 | hidegold = Config.HideGold, 38 | hidemoney = Config.HideMoney, 39 | hidelevel = Config.HideLevel, 40 | hideid = Config.HideID, 41 | hidetokens = Config.HideTokens, 42 | uiposition = Config.UIPosition, 43 | uilayout = Config.UILayout, 44 | closeondelay = Config.CloseOnDelay, 45 | closeondelayms = Config.CloseOnDelayMS, 46 | hidepvp = Config.HidePVP, 47 | pvp = Config.PVP 48 | }) 49 | 50 | if Config.HideWithRader then 51 | local cantoggle = not Config.HideUi 52 | 53 | CreateThread(function() 54 | while true do 55 | if IsRadarHidden() then 56 | cantoggle = true 57 | SendNUIMessage({ type = "ui", action = "hide" }) 58 | vorpShowUI = false 59 | elseif cantoggle and Config.OpenAfterRader then 60 | cantoggle = false 61 | SendNUIMessage({ type = "ui", action = "show" }) 62 | vorpShowUI = true 63 | end 64 | 65 | Wait(1000) 66 | end 67 | end) 68 | end 69 | end) 70 | 71 | RegisterNUICallback('close', function(args, cb) 72 | vorpShowUI = false 73 | cb('ok') 74 | end) 75 | -------------------------------------------------------------------------------- /config/commands.lua: -------------------------------------------------------------------------------- 1 | local T = Translation[Lang].Commands 2 | --============================ 3 | --? EXAMPLE 4 | -- * in this file is where vorp core commands are registered 5 | -- * you can register your own commands here too 6 | -- * it has features such as : arguments needed , is user in game , groups allowed ,aces allowed ,jobs allowed, webhooks and chat suggestions 7 | -- * callfunction bellow, will return a table with {source , args , rawCommand , config} config is the value on this file the parameters of the command used like commandName 8 | -- TODO job grade support 9 | 10 | --[[ addgroup = { 11 | webhook = "", -- discord log when someone uses this command leave to false if you dont need 12 | custom = "\n**PlayerID** `%d`\n**Group given** `%s`", -- for webhook 13 | title = "📋 `/Group command`", -- webhook title 14 | ---#end webhook 15 | commandName = "addGroup", -- name of the command to use 16 | label = "set players group", -- label of command when using 17 | suggestion = { -- chat arguments needed 18 | { name = "Id", help = T.Commands.help1 }, -- add how many you need 19 | { name = "Group", help = T.Commands.help2 }, 20 | }, 21 | userCheck = true, -- does this command need to check if user is playing ? 22 | groupAllowed = { "admin" }, -- from users table in the database this group will be allowed to use this command 23 | aceAllowed = 'vorpcore.setGroup.Command', -- dont touch, 24 | jobsAllow = {}, -- jobs allowed ? remove or leave empty if not needed 25 | callFunction = function(...) -- dont touch 26 | -- this is a function 27 | -- you can run code here trigger client events or server events , exports etc, 28 | -- get source local data = ... 29 | --local source = data.source 30 | SetGroup(...) 31 | end 32 | 33 | },]] 34 | --END 35 | 36 | --============================== 37 | Commands = { 38 | giveExp = { 39 | webhook = "", 40 | custom = T.giveExp.custom, 41 | title = T.giveExp.title, 42 | commandName = "addExp", 43 | label = T.giveExp.label, 44 | suggestion = { 45 | { name = T.giveExp.name, help = T.giveExp.help }, 46 | { name = T.giveExp.name1, help = T.giveExp.help1 }, 47 | { name = T.giveExp.name2, help = T.giveExp.help2 }, 48 | }, 49 | userCheck = true, 50 | groupAllowed = { "admin" }, 51 | aceAllowed = 'vorpcore.setExp.Command', 52 | callFunction = function(...) 53 | SetExp(...) 54 | end 55 | }, 56 | myExp = { 57 | webhook = "", 58 | custom = T.myExp.custom, 59 | title = T.myExp.title, 60 | commandName = "myExp", 61 | label = T.myExp.label, 62 | suggestion = { 63 | { name = T.myExp.name, help = T.myExp.help }, 64 | }, 65 | userCheck = false, 66 | groupAllowed = {}, 67 | aceAllowed = nil, 68 | callFunction = function(...) 69 | MyExp(...) 70 | end 71 | }, 72 | addgroup = { 73 | webhook = "", 74 | custom = T.addGroup.custom, 75 | title = T.addGroup.tittle, 76 | ---#end webhook 77 | commandName = "addGroup", 78 | label = T.addGroup.label, 79 | suggestion = { 80 | { name = T.addGroup.name, help = T.addGroup.help }, 81 | { name = T.addGroup.name1, help = T.addGroup.help1 }, 82 | }, 83 | userCheck = true, 84 | groupAllowed = { "admin" }, 85 | aceAllowed = 'vorpcore.setGroup.Command', 86 | callFunction = function(...) 87 | SetGroup(...) 88 | end 89 | }, 90 | addGroupCharacter = { 91 | webhook = "", 92 | custom = T.addGroupCharacter.custom, 93 | title = T.addGroupCharacter.tittle, 94 | ---#end webhook 95 | commandName = "addGroupChar", 96 | label = T.addGroupCharacter.label, 97 | suggestion = { 98 | { name = T.addGroupCharacter.name, help = T.addGroupCharacter.help }, 99 | { name = T.addGroupCharacter.name1, help = T.addGroupCharacter.help1 }, 100 | }, 101 | userCheck = true, 102 | groupAllowed = { "admin" }, 103 | aceAllowed = 'vorpcore.setGroup.Command', 104 | callFunction = function(...) 105 | SetGroupCharacter(...) 106 | end 107 | }, 108 | addJob = { 109 | webhook = "", 110 | custom = T.addJob.custom, 111 | title = T.addJob.title, 112 | ---#end webhook 113 | commandName = "addJob", 114 | label = T.addJob.label, 115 | suggestion = { 116 | { name = T.addJob.name, help = T.addJob.help }, 117 | { name = T.addJob.name1, help = T.addJob.help1 }, 118 | { name = T.addJob.name2, help = T.addJob.help2 }, 119 | { name = T.addJob.name3, help = T.addJob.help3 }, 120 | }, 121 | userCheck = true, 122 | groupAllowed = { "admin" }, 123 | aceAllowed = 'vorpcore.setJob.Command', 124 | callFunction = function(...) 125 | AddJob(...) 126 | end 127 | }, 128 | addItem = { 129 | webhook = "", 130 | custom = T.addItem.custom, 131 | title = T.addItem.title, 132 | ---#end webhook 133 | commandName = "addItems", 134 | label = T.addItem.label, 135 | suggestion = { 136 | { name = T.addItem.name, help = T.addItem.help }, 137 | { name = T.addItem.name1, help = T.addItem.help1 }, 138 | { name = T.addItem.name2, help = T.addItem.help2 }, 139 | }, 140 | userCheck = true, 141 | groupAllowed = { "admin" }, 142 | aceAllowed = 'vorpcore.additems.Command', 143 | callFunction = function(...) 144 | AddItems(...) 145 | end 146 | }, 147 | addWeapon = { 148 | webhook = "", 149 | custom = T.addWeapon.custom, 150 | title = T.addWeapon.title, 151 | ---#end webhook 152 | commandName = "addWeapon", 153 | label = T.addWeapon.label, 154 | suggestion = { 155 | { name = T.addWeapon.name, help = T.addWeapon.help }, 156 | { name = T.addWeapon.name1, help = T.addWeapon.help1 }, 157 | }, 158 | userCheck = true, 159 | groupAllowed = { "admin" }, 160 | aceAllowed = 'vorpcore.addweapons.Command', 161 | callFunction = function(...) 162 | AddWeapons(...) 163 | end 164 | }, 165 | delMoney = { 166 | webhook = "", 167 | custom = T.delMoney.custom, 168 | title = T.delMoney.title, 169 | ---#end webhook 170 | commandName = "delMoney", 171 | label = T.delMoney.label, 172 | suggestion = { 173 | { name = T.delMoney.name, help = T.delMoney.help }, 174 | { name = T.delMoney.name1, help = T.delMoney.help1 }, 175 | { name = T.delMoney.name2, help = T.delMoney.help2 }, 176 | }, 177 | userCheck = true, 178 | groupAllowed = { "admin" }, 179 | aceAllowed = 'vorpcore.delCurrency.Command', 180 | callFunction = function(...) 181 | RemmoveCurrency(...) 182 | end 183 | }, 184 | addMoney = { 185 | webhook = "", 186 | custom = T.addMoney.custom, 187 | title = T.addMoney.title, 188 | ---#end webhook 189 | commandName = "addMoney", 190 | label = T.addMoney.label, 191 | suggestion = { 192 | { name = T.addMoney.name, help = T.addMoney.help }, 193 | { name = T.addMoney.name1, help = T.addMoney.help1 }, 194 | { name = T.addMoney.name2, help = T.addMoney.help2 }, 195 | 196 | }, 197 | userCheck = true, 198 | groupAllowed = { "admin" }, 199 | aceAllowed = 'vorpcore.addMoney.Command', 200 | callFunction = function(...) 201 | AddMoney(...) 202 | end 203 | }, 204 | delWagons = { 205 | webhook = "", 206 | custom = T.delWagons.custom, 207 | title = T.delWagons.title, 208 | ---#end webhook 209 | commandName = "delWagons", 210 | label = T.delWagons.label, 211 | suggestion = { 212 | { name = T.delWagons.name, help = T.delWagons.help }, 213 | }, 214 | userCheck = false, 215 | groupAllowed = { "admin" }, 216 | aceAllowed = 'vorpcore.delwagons.Command', 217 | callFunction = function(...) 218 | DeleteWagons(...) 219 | end 220 | }, 221 | revive = { 222 | webhook = "", 223 | custom = T.revive.custom, 224 | title = T.revive.title, 225 | commandName = "revive", 226 | label = T.revive.label, 227 | suggestion = { 228 | { name = T.revive.name, help = T.revive.help } 229 | }, 230 | userCheck = true, 231 | groupAllowed = { "admin" }, 232 | aceAllowed = 'vorpcore.reviveplayer.Command', 233 | callFunction = function(...) 234 | RevivePlayer(...) 235 | end 236 | }, 237 | teleport = { 238 | webhook = "", 239 | custom = T.teleport.custom, 240 | title = T.teleport.title, 241 | commandName = "tpm", 242 | label = T.teleport.label, 243 | suggestion = {}, 244 | userCheck = false, 245 | groupAllowed = { "admin" }, 246 | aceAllowed = 'vorpcore.tpm.Command', 247 | callFunction = function(...) 248 | TeleporPlayer(...) 249 | end 250 | }, 251 | delHorse = { 252 | webhook = "", 253 | custom = T.delHorse.custom, 254 | title = T.delHorse.title, 255 | commandName = "delHorse", 256 | label = T.delHorse.label, 257 | suggestion = {}, 258 | userCheck = false, 259 | groupAllowed = { "admin" }, 260 | aceAllowed = 'vorpcore.delhorse.Command', 261 | callFunction = function(...) 262 | DeleteHorse(...) 263 | end 264 | }, 265 | heal = { 266 | webhook = "", 267 | custom = T.heal.custom, 268 | title = T.heal.title, 269 | commandName = "heal", 270 | label = T.heal.label, 271 | suggestion = { 272 | { name = T.heal.name, help = T.heal.help } 273 | }, 274 | userCheck = true, 275 | groupAllowed = { "admin" }, 276 | aceAllowed = 'vorpcore.healplayer.Command', 277 | callFunction = function(data) 278 | -- in here you can add your metabolism events 279 | TriggerClientEvent("vorpmetabolism:changeValue", tonumber(data.args[1]), "Thirst", 1000) 280 | TriggerClientEvent("vorpmetabolism:changeValue", tonumber(data.args[1]), "Hunger", 1000) 281 | HealPlayers(data) 282 | end 283 | }, 284 | addWhitelist = { 285 | webhook = "", 286 | custom = T.addWhitelist.custom, 287 | title = T.addWhitelist.title, 288 | commandName = "addWhtelist", 289 | label = T.addWhitelist.label, 290 | suggestion = { 291 | { name = T.addWhitelist.name, help = T.addWhitelist.help }, 292 | 293 | }, 294 | userCheck = false, 295 | groupAllowed = { "admin" }, 296 | aceAllowed = 'vorpcore.wlplayer.Command', 297 | callFunction = function(...) 298 | AddPlayerToWhitelist(...) 299 | end 300 | }, 301 | unWhitelist = { 302 | webhook = "", 303 | custom = T.unWhitelist.custom, 304 | title = T.unWhitelist.title, 305 | commandName = "unWhitelist", 306 | label = T.unWhitelist.label, 307 | suggestion = { 308 | { name = T.unWhitelist.name, help = T.unWhitelist.help }, 309 | }, 310 | userCheck = false, 311 | groupAllowed = { "admin" }, 312 | aceAllowed = 'vorpcore.unwlplayer.Command', 313 | callFunction = function(...) 314 | RemovePlayerFromWhitelist(...) 315 | end 316 | }, 317 | ban = { 318 | webhook = "", 319 | custom = T.ban.custom, 320 | title = T.ban.title, 321 | commandName = "ban", 322 | label = T.ban.label, 323 | suggestion = { 324 | { name = T.ban.name, help = T.ban.help }, 325 | { name = T.ban.name1, help = T.ban.help1 }, 326 | }, 327 | userCheck = false, 328 | groupAllowed = { "admin" }, 329 | aceAllowed = 'vorpcore.ban.Command', 330 | callFunction = function(...) 331 | BanPlayers(...) 332 | end 333 | }, 334 | unBan = { 335 | webhook = "", 336 | custom = T.unBan.custom, 337 | title = T.unBan.title, 338 | commandName = "unBan", 339 | label = T.unBan.label, 340 | suggestion = { 341 | { name = T.unBan.name, help = T.unBan.help }, 342 | }, 343 | userCheck = false, 344 | groupAllowed = { "admin" }, 345 | aceAllowed = 'vorpcore.unban.Command', 346 | callFunction = function(...) 347 | UnBanPlayers(...) 348 | end 349 | }, 350 | warn = { 351 | webhook = "", 352 | custom = T.warn.custom, 353 | title = T.warn.title, 354 | commandName = "warn", 355 | label = T.warn.label, 356 | suggestion = { 357 | { name = T.warn.name, help = T.warn.help }, 358 | }, 359 | userCheck = false, 360 | groupAllowed = { "admin" }, 361 | aceAllowed = 'vorpcore.warn.Command', 362 | callFunction = function(...) 363 | WarnPlayers(...) 364 | end 365 | }, 366 | unWarn = { 367 | webhook = "", 368 | custom = T.unWarn.custom, 369 | title = T.unWarn.title, 370 | commandName = "unWarn", 371 | label = T.unWarn.label, 372 | suggestion = { 373 | { name = T.unWarn.name, help = T.unWarn.help } 374 | }, 375 | userCheck = false, 376 | groupAllowed = { "admin" }, 377 | aceAllowed = 'vorpcore.unwarn.Command', 378 | callFunction = function(...) 379 | UnWarnPlayer(...) 380 | end 381 | }, 382 | charName = { 383 | webhook = "", 384 | custom = T.charName.custom, 385 | title = T.charName.title, 386 | commandName = "modifyCharName", 387 | label = T.charName.label, 388 | suggestion = { 389 | { name = T.charName.name, help = T.charName.help }, 390 | { name = T.charName.name1, help = T.charName.help1 }, 391 | { name = T.charName.name2, help = T.charName.help2 }, 392 | 393 | }, 394 | userCheck = true, 395 | groupAllowed = { "admin" }, 396 | aceAllowed = 'vorpcore.changeCharName', 397 | callFunction = function(...) 398 | ModifyCharName(...) 399 | end 400 | }, 401 | charCreateAdd = { 402 | webhook = "", 403 | custom = T.charCreateAdd.custom, 404 | title = T.charCreateAdd.title, 405 | commandName = "addChar", 406 | label = T.charCreateAdd.label, 407 | suggestion = { 408 | { name = T.charCreateAdd.name, help = T.charCreateAdd.help }, 409 | { name = T.charCreateAdd.name1, help = T.charCreateAdd.help1 }, 410 | }, 411 | userCheck = true, 412 | groupAllowed = { "admin" }, 413 | aceAllowed = 'vorpcore.addchar.Command', 414 | callFunction = function(...) 415 | AddCharCanCreateMore(...) 416 | end 417 | }, 418 | myJob = { 419 | webhook = "", 420 | commandName = "myJob", 421 | label = T.myJob.label, 422 | suggestion = {}, 423 | userCheck = false, 424 | groupAllowed = {}, -- leave empty anyone can use 425 | aceAllowed = nil, -- leave nil anyone can use 426 | callFunction = function(...) 427 | MyJob(...) 428 | end 429 | }, 430 | 431 | -- create your commands here just copy from above , see first line on how to do it 432 | 433 | 434 | } 435 | -------------------------------------------------------------------------------- /config/config.lua: -------------------------------------------------------------------------------- 1 | --============================================= 2 | -- VORP SHARED CONFIG -- 3 | --============================================= 4 | 5 | Lang = "English" 6 | Config = Config or {} 7 | 8 | Config = { 9 | autoUpdateDB = true, -- Enables automatic database updates. 10 | 11 | ReportCrashes = true, -- Reports crashes to https://monitor.gtp-dev.com login in here to create your API KEY , by doing this you will help the community to improve the server stability and fix crashes faster 12 | 13 | API_KEY = "", -- API key for crash reporting. Get your API key at https://monitor.gtp-dev.com to allow more requests make a donation in the website 14 | 15 | -- (IF YOU HAVE WHITELIST ENABLED DONT ENABLE THIS)-- 16 | DeleteFromUsersTable = true, -- this will delete from users table if character does not exist "optimising the queries" 17 | ----------------------------------------------------- 18 | 19 | CanRespawn = function() -- use this function to add your own logic if player can respawn or not 20 | -- add your logic here 21 | return true -- dont touch 22 | end, 23 | --============================================= 24 | -- STARTING CONFIGURATION -- 25 | --============================================= 26 | 27 | initGold = 0.0, -- Initial gold amount for new players. 28 | 29 | initMoney = 200.0, -- Initial money amount for new players. 30 | 31 | initRol = 0.0, -- Initial role-play currency amount for new players. 32 | 33 | initInvCapacity = 35.0, -- Initial number of character inventory weight for new players. for old characters you must change in the database if you dont ave a new server 34 | 35 | initXp = 0, -- Initial experience points for new players. 36 | 37 | initJob = "unemployed", -- Default job for new players. Recommended not to change. 38 | 39 | initJobGrade = 0, -- Default job grade for new players. Recommended not to change. 40 | 41 | initGroup = "user", -- Default user group for new players. Recommended not to change. 42 | 43 | initJobLabel = "Unemployed", -- Default job label for new players. Recommended not to change. 44 | 45 | Whitelist = false, -- Enable if not using TxAdmin's whitelist system. 46 | 47 | SavePlayersStatus = false, -- Future deprecated. Advised not to use, as it will be removed. 48 | 49 | maxHealth = 10, -- Maximum health for players. 10 is full, 0 is empty. 50 | 51 | maxStamina = 10, -- Maximum stamina for players. 10 is full, 0 is empty. 52 | 53 | PVP = true, -- Enables player vs player combat. 54 | 55 | PVPToggle = false, -- Allows players to toggle their PVP status. 56 | 57 | CommandOnOffPVP = 'pvp', -- Command to toggle PVP status, requires PVPToggle to be true. 58 | 59 | savePlayersTimer = 10, -- Interval in minutes for automatically saving all players to the database. 60 | 61 | showplayerIDwhenfocus = true, -- Shows player Steam name when focusing on them with RMB if set to false. 62 | 63 | disableAutoAIM = true, -- Disables auto-aim for controller players if set to false. 64 | 65 | DisableCinematicMode = false, -- Set false to disable cineamtic mode/camera (While holding "V" key) (You should be aware that disabling cinematic mode may break functionality in scripts that use it.) 66 | --============================================= 67 | -- MULTICHARACTER SUPPORT -- 68 | --============================================= 69 | 70 | SaveDiscordId = true, -- Saves Discord ID in the character/user database upon joining/leaving. 71 | 72 | MaxCharacters = 5, -- Maximum number of characters a player can create. when first join, for old users go to users table and change the number of characters there 73 | 74 | --============================================= 75 | -- UI CORE SETTINGS -- 76 | --============================================= 77 | 78 | HideOnlyDEADEYE = true, -- Hides only the Dead Eye core in the UI. 79 | 80 | HidePlayersCore = false, -- Hides player cores in the UI. 81 | 82 | HideHorseCores = false, -- Hides horse cores in the UI. 83 | 84 | --============================================= 85 | -- WEBHOOK CONFIGURATIONS -- 86 | -- Refer to commands.config for usage. -- 87 | --============================================= 88 | 89 | webhookColor = 16711680, -- Color for embeds in Discord webhooks. 90 | 91 | name = "VORP", -- Name displayed in webhook embeds. 92 | 93 | logo = "https://via.placeholder.com/30x30", -- Logo URL for webhook embeds. 94 | 95 | footerLogo = "https://via.placeholder.com/30x30", -- Footer logo URL for webhook embeds. 96 | 97 | Avatar = "https://via.placeholder.com/30x30", -- Avatar URL for webhook embeds. 98 | 99 | 100 | --============================================= 101 | -- UI CONFIGURATIONS -- 102 | --============================================= 103 | 104 | 105 | HideUi = false, -- Shows or hides the overall UI. 106 | 107 | HideGold = false, -- Disables the Gold UI for all players. 108 | 109 | HideMoney = false, -- Disables the Money UI for all players. 110 | 111 | HideLevel = false, -- Disables the Level UI for all players. 112 | 113 | HideID = false, -- Disables the ID UI for all players. 114 | 115 | HideTokens = false, -- Disables the Token UI for all players. 116 | 117 | HidePVP = false, -- Disables the PVP UI for all players. 118 | 119 | UIPosition = 'TopRight', -- Sets the UI position on the screen. Options are 'TopRight', 'TopLeft', 'BottomRight', 'BottomLeft', 'MiddleRight', 'TopMiddle', 'BottomMiddle'. 120 | 121 | UILayout = 'Column', -- Sets the UI layout, options are 'Row' or 'Column'. 122 | 123 | HideWithRader = true, -- UI hides when the radar (minimap) is hidden. 124 | 125 | OpenAfterRader = true, -- UI shows when the radar (minimap) reappears. 126 | 127 | CloseOnDelay = false, -- UI automatically closes after a set time. 128 | 129 | CloseOnDelayMS = 10000, -- Time in milliseconds before the UI auto-closes, 10000 equals 10 seconds. 130 | 131 | CommandHideIU = 'hideUi', -- Command to hide all UI elements, useful for screenshots. 132 | 133 | CommandToogleUI = 'toggleUi', -- Command to toggle the visibility of VORP UI elements. 134 | 135 | CommandClearAnim = 'stopAnim', -- Command to stop animations if a player is stuck. 136 | 137 | StopAnimCooldown = 5, -- Cooldown time to reuse the command to stop animations. (Second) 138 | 139 | --============================================= 140 | -- MAP CONFIGURATIONS -- 141 | --============================================= 142 | 143 | mapTypeOnFoot = 3, -- Radar type when on foot. 0 = Off, 1 = Regular, 2 = Expanded, 3 = Simple (compass). 144 | 145 | mapTypeOnMount = 3, -- Radar type when on horse. Same options as on foot. 146 | 147 | enableTypeRadar = false, -- Enables custom radar types if true, otherwise players use game settings. 148 | 149 | Loadinscreen = true, -- Enables loading screens during spawn and respawn. 150 | 151 | LoadinScreenTimer = 10000, -- Duration of loading screens in milliseconds. 152 | 153 | LoadingScreenPlayerInfo = false, -- Enables showing player information on the loading screen (Player name, surname and job) 154 | 155 | --============================================= 156 | -- RESPAWN SETTINGS -- 157 | --============================================= 158 | 159 | HealthOnRespawn = 500, -- Player health after respawning at a hospital (max is 500). 160 | 161 | HealthOnResurrection = 100, -- Player health after being resurrected (max is 500). 162 | 163 | RagdollOnResurrection = true, -- Enables ragdoll and revive effects upon resurrection. 164 | 165 | HealthRecharge = { enable = true, multiplier = 0.37 }, -- Auto-recharge for health, with a multiplier for speed. 166 | 167 | StaminaRecharge = { enable = true, multiplier = 0.4 }, -- Auto-recharge for stamina, with a multiplier for speed. 168 | 169 | RespawnTime = 10, -- Time in seconds before a player can respawn. 170 | 171 | RespawnKey = 0xDFF812F9, -- Key code for respawning (default is 'E'). 172 | 173 | RespawnKeyTime = 5000, -- Time in milliseconds to hold the respawn key. 174 | 175 | CombatLogDeath = true, -- Combat loggers respawn in a dead state instead of alive. 176 | 177 | UseControlsCamera = false, -- Allows dead or carried players to move the camera with WASD (resource intensive). 178 | 179 | UseDeathHandler = true, -- Keeps default death handling unless you have a custom system. 180 | 181 | Hospitals = { -- Spawn points for players respawning at hospitals. 182 | Valentine = { 183 | name = "Valentine", 184 | pos = vector4(-283.83, 806.4, 119.38, 321.76), -- Vector4 coordinates: x, y, z, heading. 185 | }, 186 | SaintDenis = { 187 | name = "Saint Denis", 188 | pos = vector4(2721.4562, -1446.0975, 46.2303, 321.76), 189 | }, 190 | Armadillo = { 191 | name = "Armadillo", 192 | pos = vector4(-3742.5, -2600.9, -13.23, 321.76), 193 | }, 194 | Blackwater = { 195 | name = "Black water", 196 | pos = vector4(-723.9527, -1242.8358, 44.7341, 321.76), 197 | }, 198 | Rhodes = { 199 | name = "Rhodes", 200 | pos = vector4(1229.0, -1306.1, 76.9, 321.76), 201 | }, 202 | }, 203 | ActiveEagleEye = true, -- Enables or disables Eagle Eye feature. 204 | 205 | ActiveDeadEye = false, -- Enables or disables Dead Eye feature. 206 | 207 | --============================================= 208 | -- BAN SYSTEM CONFIGURATIONS -- 209 | --============================================= 210 | 211 | DateTimeFormat = "%d/%m/%y %H:%M:%S", -- Format for displaying date and time in ban notifications. 212 | 213 | TimeZone = " CET", -- Set your server's timezone. 214 | 215 | TimeZoneDifference = 1, -- Time difference from UTC, used in the banning system. 216 | 217 | --=========================================== 218 | -- DISCORD RICH PRESENCE INTEGRATION -- 219 | --=========================================== 220 | appid = nil, -- Discord Application ID. Replace this with your own application's ID. 221 | 222 | biglogo = "LOGOname", -- Name of the image asset to use for the large icon in the rich presence. 223 | 224 | biglogodesc = " Redm Server Connect: ", -- Description displayed when hovering over the large icon. 225 | 226 | smalllogo = "smallboy name", -- Name of the image asset for the small icon in the rich presence. This is optional. 227 | 228 | smalllogodesc = "Join us for a good time ", -- Description displayed when hovering over the small icon. 229 | 230 | richpresencebutton = "Join Discord", -- Text displayed on the rich presence button. 231 | 232 | shownameandid = true, -- Whether to display the player's Steam name and ID. 233 | 234 | Buttons = { -- Configuration for buttons shown in the Discord rich presence. 235 | { 236 | text = 'Join Discord!', -- Text displayed on the first button. 237 | -- URL the first button directs to. Replace with your Discord invite link. 238 | url = 'https://discord.gg/vorpcore' 239 | 240 | }, 241 | { 242 | text = 'Website', -- Text displayed on the second button. 243 | -- URL the second button directs to. Fill in with your website URL. 244 | url = '' -- Example for Rich Presence Button 245 | } 246 | }, 247 | --============================================= 248 | 249 | } 250 | -------------------------------------------------------------------------------- /config/logs.lua: -------------------------------------------------------------------------------- 1 | Logs = {} 2 | 3 | Logs.Whitelist = "" -- only if you use whitelist in vorp core 4 | 5 | Logs.EnableWebhookJoinleave = true -- Enable webhooks for player join and leave? 6 | 7 | Logs.JoinWebhookURL = "" -- only if you use join leave in vorp core 8 | 9 | Logs.LeaveWebhookURL = "" -- only if you use join leave in vorp core 10 | -------------------------------------------------------------------------------- /config/skills.lua: -------------------------------------------------------------------------------- 1 | --============================================= 2 | -- SKILLS CONFIGURATION -- 3 | --============================================= 4 | 5 | -- skills are leveled up automatically when the experience points are reached for each level 6 | -- events are being triggered when player levels up for you to use on your scripts 7 | -- skills by it self dont do anything they need to be implemented in your scripts look at the documentation to see how to use them 8 | Config = Config or {} 9 | 10 | Config.Skills = { 11 | 12 | Crafting = { --Name of the Skill Name 13 | 14 | Levels = { 15 | { -- level 1 16 | NextLevel = 100, -- if 100 xp is reached then level up, this is the max xp for this level 17 | Label = "Beginner", 18 | }, 19 | { --level 2 20 | NextLevel = 200, -- need to have 200 xp to level up 21 | Label = "Novice", 22 | }, 23 | { --level 3 24 | NextLevel = 300, -- need to have 300 xp to level up 25 | Label = "Apprentice", 26 | }, 27 | { --level 4 28 | NextLevel = 400, -- need to have 400 xp to level up 29 | Label = "Journeyman", 30 | }, 31 | 32 | { --level 5 33 | NextLevel = 500, -- need to have 500 xp to level up 34 | Label = "Expert", 35 | } 36 | }, 37 | }, 38 | -- add more here categories here make sure to understand that levels are in order from top to bottom like 1,2,3,4,5 39 | Mining = { 40 | 41 | Levels = { 42 | 43 | { 44 | NextLevel = 100, 45 | Label = "Beginner", 46 | }, 47 | { 48 | NextLevel = 200, 49 | Label = "Novice", 50 | }, 51 | { 52 | NextLevel = 300, 53 | Label = "Apprentice", 54 | }, 55 | { 56 | NextLevel = 400, 57 | Label = "Journeyman", 58 | }, 59 | { 60 | NextLevel = 500, 61 | Label = "Expert", 62 | } 63 | }, 64 | }, 65 | 66 | Hunting = { 67 | 68 | Levels = { 69 | 70 | { 71 | NextLevel = 100, 72 | Label = "Beginner", 73 | }, 74 | { 75 | NextLevel = 200, 76 | Label = "Novice", 77 | }, 78 | { 79 | NextLevel = 300, 80 | Label = "Apprentice", 81 | }, 82 | { 83 | NextLevel = 400, 84 | Label = "Journeyman", 85 | }, 86 | { 87 | NextLevel = 500, 88 | Label = "Expert", 89 | } 90 | }, 91 | }, 92 | 93 | Fishing = { 94 | Levels = { 95 | { 96 | NextLevel = 100, 97 | Label = "Beginner", 98 | }, 99 | { 100 | NextLevel = 200, 101 | Label = "Novice", 102 | }, 103 | { 104 | NextLevel = 300, 105 | Label = "Apprentice", 106 | }, 107 | { 108 | NextLevel = 400, 109 | Label = "Journeyman", 110 | }, 111 | { 112 | NextLevel = 500, 113 | Label = "Expert", 114 | } 115 | }, 116 | }, 117 | 118 | } 119 | -------------------------------------------------------------------------------- /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'cerulean' 2 | game 'rdr3' 3 | rdr3_warning 'I acknowledge that this is a prerelease build of RedM, and I am aware my resources *will* become incompatible once RedM ships.' 4 | lua54 'yes' 5 | 6 | name 'vorp core' 7 | description 'A Tool to build your RedM server and scripts' 8 | author 'VORP' -- converted from the original C# vorp core by goncalobsccosta#9041 9 | repository 'https://github.com/VORPCORE/vorp-core-lua' 10 | 11 | shared_scripts { 12 | 'config/config.lua', 13 | 'config/skills.lua', 14 | 'translation/language.lua' 15 | } 16 | 17 | client_scripts { 18 | 'client/ref/*.lua', 19 | 'client/exports/*.lua', 20 | 'client/coreactions.lua', 21 | 'client/*.lua', 22 | } 23 | 24 | server_scripts { 25 | 'config/logs.lua', 26 | '@oxmysql/lib/MySQL.lua', 27 | 'server/class/*.lua', 28 | 'config/commands.lua', 29 | 'server/*lua', 30 | 'server/services/dbupdater/*.lua', 31 | } 32 | 33 | files { 34 | 'ui/**/*', 35 | } 36 | 37 | ui_page 'ui/index.html' 38 | 39 | version '3.0' 40 | vorp_checker 'yes' 41 | vorp_name '^4Resource version Check^3' 42 | vorp_github 'https://github.com/VORPCORE/vorp_core-lua' 43 | -------------------------------------------------------------------------------- /pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Pull request template 2 | > [!IMPORTANT] 3 | > Please complete all fields. PRs will not be merged if any fields are incomplete. Be respectful, and keep in mind that it may take some time for your PR to be reviewed. 4 | > 5 | > Bear in mind refactors are up to the developers and not it's contributors after all we are the ones giving support when needed. if they are big changes I suggest you to release it under your name instead. 6 | 7 | ## Type of change 8 | 9 | - [ ] Bug fix (non-breaking change which fixes an issue) 10 | - [ ] New feature (non-breaking change which adds functionality) 11 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 12 | - [ ] This change requires a documentation update 13 | 14 | ### Motive for This Pull Request 15 | explanation field 16 | 17 | ### Provide a brief explanation of why these changes are being proposed and what they aim to achieve. 18 | explanation field 19 | 20 | ### Explain the necessity of these changes and how they will impact the framework or its users. 21 | explanation field 22 | 23 | ### Please describe the tests you have conducted to verify your changes. Provide instructions so we can reproduce these tests. Also, list any relevant details for your test configuration. 24 | 25 | - [ ] Tested with latest vorp scripts 26 | - [ ] Tested with latest artifacts 27 | 28 | ## Notes if any 29 | explanation field 30 | -------------------------------------------------------------------------------- /server/apicontroller.lua: -------------------------------------------------------------------------------- 1 | CoreFunctions = {} 2 | 3 | CoreFunctions.maxCharacters = function(source) 4 | return GetMaxCharactersAllowed(source) 5 | end 6 | 7 | CoreFunctions.getUsers = function() 8 | return _users 9 | end 10 | 11 | CoreFunctions.getUser = function(source) 12 | if not source then return nil end 13 | 14 | local sid = GetPlayerIdentifierByType(source, 'steam') 15 | if not sid or not _users[sid] then return nil end 16 | 17 | return _users[sid].GetUser() 18 | end 19 | 20 | CoreFunctions.getUserByCharId = function(charid) 21 | if charid == nil then return nil end 22 | for k, v in pairs(_users) do 23 | if v.usedCharacterId ~= -1 and tonumber(v.usedCharacterId) == tonumber(charid) then 24 | return v.GetUser() 25 | end 26 | end 27 | return nil 28 | end 29 | 30 | CoreFunctions.NotifyTip = function(source, text, duration) 31 | TriggerClientEvent('vorp:Tip', source, text, duration) 32 | end 33 | 34 | CoreFunctions.NotifyLeft = function(source, title, subtitle, dict, icon, duration, colors) 35 | TriggerClientEvent('vorp:NotifyLeft', source, title, subtitle, dict, icon, duration, colors) 36 | end 37 | 38 | CoreFunctions.NotifyRightTip = function(source, text, duration) 39 | TriggerClientEvent('vorp:TipRight', source, text, duration) 40 | end 41 | 42 | CoreFunctions.NotifyObjective = function(source, text, duration) 43 | TriggerClientEvent('vorp:TipBottom', source, text, duration) 44 | end 45 | 46 | CoreFunctions.NotifyTop = function(source, text, location, duration) 47 | TriggerClientEvent('vorp:NotifyTop', source, text, location, duration) 48 | end 49 | 50 | CoreFunctions.NotifySimpleTop = function(source, text, subtitle, duration) 51 | TriggerClientEvent('vorp:ShowTopNotification', source, text, subtitle, duration) 52 | end 53 | 54 | CoreFunctions.NotifyAvanced = function(source, text, dict, icon, text_color, duration, quality, showquality) 55 | TriggerClientEvent('vorp:ShowAdvancedRightNotification', source, text, dict, icon, text_color, duration, quality, showquality) 56 | end 57 | 58 | CoreFunctions.NotifyCenter = function(source, text, duration, color) 59 | TriggerClientEvent('vorp:ShowSimpleCenterText', source, text, duration, color) 60 | end 61 | 62 | CoreFunctions.NotifyBottomRight = function(source, text, duration) 63 | TriggerClientEvent('vorp:ShowBottomRight', source, text, duration) 64 | end 65 | 66 | CoreFunctions.NotifyFail = function(source, text, subtitle, duration) 67 | TriggerClientEvent('vorp:failmissioNotifY', source, text, subtitle, duration) 68 | end 69 | 70 | CoreFunctions.NotifyDead = function(source, title, audioRef, audioName, duration) 71 | TriggerClientEvent('vorp:deadplayerNotifY', source, title, audioRef, audioName, duration) 72 | end 73 | 74 | CoreFunctions.NotifyUpdate = function(source, title, subtitle, duration) 75 | TriggerClientEvent('vorp:updatemissioNotify', source, title, subtitle, duration) 76 | end 77 | 78 | CoreFunctions.NotifyBasicTop = function(source, title, duration) 79 | TriggerClientEvent('vorp:ShowBasicTopNotification', source, title, duration) 80 | end 81 | 82 | CoreFunctions.NotifyWarning = function(source, title, msg, audioRef, audioName, duration) 83 | TriggerClientEvent('vorp:warningNotify', source, title, msg, audioRef, audioName, duration) 84 | end 85 | CoreFunctions.NotifyLeftRank = function(source, title, subtitle, dict, icon, duration, color) 86 | TriggerClientEvent('vorp:LeftRank', source, title, subtitle, dict, icon, duration, color) 87 | end 88 | 89 | CoreFunctions.dbUpdateAddTables = function(tbl) 90 | dbupdaterAPI.addTables(tbl) 91 | end 92 | 93 | CoreFunctions.dbUpdateAddUpdates = function(updt) 94 | dbupdaterAPI.addUpdates(updt) 95 | end 96 | 97 | CoreFunctions.AddWebhook = function(title, webhook, description, color, name, logo, footerlogo, avatar) 98 | TriggerEvent('vorp_core:addWebhook', title, webhook, description, color, name, logo, footerlogo, avatar) 99 | end 100 | 101 | CoreFunctions.Callback = { 102 | 103 | Register = function(name, callback) 104 | ServerRPC.Callback.Register(name, callback) 105 | end, 106 | TriggerAsync = function(name, source, callback, ...) 107 | ServerRPC.Callback.TriggerAsync(name, source, callback, ...) 108 | end, 109 | TriggerAwait = function(name, source, ...) 110 | return ServerRPC.Callback.TriggerAwait(name, source, ...) 111 | end 112 | } 113 | 114 | CoreFunctions.Whitelist = { 115 | 116 | getEntry = function(identifier) 117 | if not identifier then return nil end 118 | local userid = Whitelist.Functions.GetUserId(identifier) 119 | if userid then 120 | return Whitelist.Functions.GetUsersData(userid) 121 | end 122 | return nil 123 | end, 124 | 125 | whitelistUser = function(steam) 126 | if not steam then return end 127 | return Whitelist.Functions.InsertWhitelistedUser({ identifier = steam, status = true }) 128 | end, 129 | 130 | unWhitelistUser = function(steam) 131 | if not steam then return end 132 | local id = Whitelist.Functions.GetUserId(steam) 133 | if id then 134 | Whitelist.Functions.WhitelistUser(id, false) 135 | end 136 | end, 137 | } 138 | 139 | CoreFunctions.Player = { 140 | Heal = function(source) 141 | if not source then return end 142 | TriggerEvent("vorp_core:Server:OnPlayerHeal", source) 143 | TriggerClientEvent("vorp_core:Client:OnPlayerHeal", source) 144 | end, 145 | Revive = function(source, param) 146 | if not source then return end 147 | TriggerEvent("vorp_core:Server:OnPlayerRevive", source, param) 148 | TriggerClientEvent("vorp_core:Client:OnPlayerRevive", source, param) 149 | end, 150 | Respawn = function(source, param) 151 | if not source then return end 152 | TriggerEvent("vorp_core:Server:OnPlayerRespawn", source, param) 153 | TriggerClientEvent("vorp_core:Client:OnPlayerRespawn", source, param) 154 | end, 155 | } 156 | 157 | 158 | -- WIP 159 | --[[ CoreFunctions.Command = { 160 | 161 | Register = function(data) 162 | if Commands[data.name] then 163 | print('^1[ERROR] ^0Command ^1' .. data.name .. ' ^0already exists.') 164 | return 165 | end 166 | 167 | Commands[data.name] = data 168 | 169 | for index, value in pairs(data) do 170 | RegisterCommands(value, index) 171 | end 172 | end, 173 | 174 | Remove = function(name) 175 | if not Commands[name] then 176 | print('^1[ERROR] ^0Command ^1' .. name .. ' ^0does not exist can only remove commands you have added through core export.') 177 | return 178 | end 179 | Commands[name] = nil 180 | end 181 | } 182 | ]] 183 | 184 | 185 | --Example usage 186 | 187 | --[[ local data = { 188 | CommandName = { -- must be unique 189 | --webhook 190 | webhook = "link", -- discord log when someone uses this command leave to false if you dont need 191 | custom = "message to display on webhook", -- for webhook 192 | title = "webhook title", -- webhook title 193 | ---#end webhook 194 | commandName = "command name", -- name of the command to use 195 | label = "command label", -- label of command when using 196 | suggestion = { -- chat arguments needed this is needd to check all arguments have met 197 | { name = "Id", help = "palyer id" }, -- add how many you need 198 | { name = "msg", help = "description" }, 199 | }, 200 | userCheck = true, -- does this command need to check if user is online ? lets say its an admin comand and argument is a player id or it could be identifier or char id etc 201 | groupAllowed = { "admin" }, -- from users table in the database this group will be allowed to use this command 202 | aceAllowed = 'vorpcore.setGroup.Command', -- ace allow or false must have this in your permissions file 203 | jobsAllow = {}, -- jobs allowed ? remove or leave empty if not needed, not supporting ranks yet 204 | callFunction = function(data) -- dont touch 205 | -- you can run code here trigger client events or server events , exports etc, 206 | -- local source = data.source -- player id 207 | -- local args = data.args -- arguments from chat 208 | -- local raw = data.rawCommand 209 | -- local data = data.config -- all the values you set above 210 | end 211 | } 212 | } 213 | ]] 214 | 215 | 216 | exports('GetCore', function() 217 | return CoreFunctions 218 | end) 219 | 220 | ----------------------------------------------------------------------------- 221 | --- use exports 222 | ---@deprecated 223 | AddEventHandler('getCore', function(cb) 224 | cb(CoreFunctions) 225 | end) 226 | 227 | --- use exports 228 | ---@deprecated 229 | AddEventHandler('getWhitelistTables', function(cb) 230 | cb(CoreFunctions.Whitelist) 231 | end) 232 | 233 | --- use Core object 234 | ---@deprecated 235 | CoreFunctions.addRpcCallback = function(name, callback) 236 | ServerRPC.Callback.Register(name, callback) 237 | end 238 | -------------------------------------------------------------------------------- /server/bans.lua: -------------------------------------------------------------------------------- 1 | local T = Translation[Lang].MessageOfSystem 2 | 3 | AddEventHandler("vorpbans:addtodb", function(status, steamid, datetime) 4 | local user = _users[steamid] 5 | 6 | if user then 7 | local source = user.GetUser().source 8 | if status == true then 9 | if datetime == 0 then 10 | DropPlayer(source, Translation[Lang].Notify.banned3) 11 | else 12 | local bannedUntil = os.date(Config.DateTimeFormat, datetime + Config.TimeZoneDifference * 3600) 13 | DropPlayer(source, T.DropReasonBanned .. bannedUntil .. Config.TimeZone) 14 | end 15 | end 16 | end 17 | 18 | MySQL.update("UPDATE users SET banned = @banned, banneduntil=@time WHERE identifier = @identifier", { ['@banned'] = status, ['@time'] = datetime, ['@identifier'] = steamid }) 19 | end) 20 | 21 | 22 | AddEventHandler("vorpwarns:addtodb", function(status, target, source) 23 | local sid = GetPlayerIdentifierByType(target, 'steam') 24 | 25 | if sid and _users[sid] then 26 | local user = _users[sid].GetUser() 27 | local warnings = user.getPlayerwarnings() 28 | warnings = status and warnings + 1 or warnings - 1 29 | local notifyMsg = status and T.Warned or T.Unwarned 30 | TriggerClientEvent("vorp:Tip", target, notifyMsg, 10000) 31 | user.setPlayerWarnings(warnings) 32 | 33 | MySQL.update("UPDATE users SET warnings = @warnings WHERE identifier = @identifier", { ['@warnings'] = warnings, ['@identifier'] = sid }) 34 | return 35 | end 36 | 37 | TriggerClientEvent("vorp:Tip", source, "User Is not in game to be warned or id is wrong", 10000) 38 | end) 39 | -------------------------------------------------------------------------------- /server/class/callbacks.lua: -------------------------------------------------------------------------------- 1 | ---@class ServerRPC 2 | ---@field name string callback name 3 | ---@field _callback fun(source: number, cb: fun(data: any), ...) callback function 4 | ---@field uniqueId string callback unique id 5 | ServerRPC = {} 6 | ServerRPC.Callback = {} 7 | ServerRPC.__index = ServerRPC 8 | ServerRPC.__call = function() 9 | return 'ServerRPC' 10 | end 11 | 12 | function ServerRPC:New(name, callback) 13 | self = setmetatable({}, ServerRPC) 14 | self.name = name 15 | self._callback = callback 16 | self.uniqueId = "" 17 | return self 18 | end 19 | 20 | function ServerRPC:Trigger(_source, uniqueId, isSync, ...) 21 | if not self._callback then 22 | return error("Callback " .. self.name .. " does not exist. Make sure it's registered in the server side.", 1) 23 | end 24 | 25 | self._callback(_source, function(...) 26 | TriggerClientEvent("vorp:ServerCallback", _source, uniqueId, isSync, self.name, ...) 27 | end, ...) 28 | end 29 | 30 | local RegisteredCalls = {} 31 | 32 | RegisterNetEvent("vorp:TriggerServerCallback", function(name, uniqueId, isSync, ...) 33 | local _source = source 34 | 35 | if not RegisteredCalls[name] then 36 | return error("Callback " .. name .. " hasn't been registered.", 1) 37 | end 38 | 39 | RegisteredCalls[name]:Trigger(_source, uniqueId, isSync, ...) 40 | end) 41 | 42 | --- Register a new Rpc callback 43 | ---@param name string callback name 44 | ---@param callback fun(source: number, cb: fun(...), ...) callback function 45 | function ServerRPC.Callback.Register(name, callback) 46 | if name == nil or type(name) ~= "string" then 47 | return error("Parameter \"name\" must be a string!", 1) 48 | end 49 | RegisteredCalls[name] = ServerRPC:New(name, callback) 50 | end 51 | 52 | --- * Trigger a callback Asynchronously 53 | ---@param source number player source 54 | ---@param name string callback name 55 | ---@param callback fun(...) callback function 56 | ---@param ... any callback parameters tables strings numbers etc 57 | function ServerRPC.Callback.TriggerAsync(name, source, callback, ...) 58 | local trigger = ServerRPC:New(name, callback) 59 | trigger:TriggerRpcAsync(source, ...) 60 | end 61 | 62 | --- * Trigger a callback Synchronously 63 | ---@param source number player source 64 | ---@param name string callback name 65 | ---@param ... any callback parameters tables strings numbers etc 66 | ---@return any callback return 67 | function ServerRPC.Callback.TriggerAwait(name, source, ...) 68 | local trigger = ServerRPC:New(name, nil) 69 | return trigger:TriggerRpcAwait(source, ...) 70 | end 71 | 72 | -- * TRIGGER CLIENT CALLBACKS HANDLER 73 | local callBackId = 0 74 | local TriggeredCalls = {} 75 | 76 | function ServerRPC:TriggerRpcAsync(source, ...) 77 | if not self.name and type(self.name) ~= "string" then 78 | return error("Callback name must be a string!", 1) 79 | end 80 | 81 | if not source and type(source) ~= "number" then 82 | return error("Callback source must exist and be a number!", 1) 83 | end 84 | 85 | callBackId = callBackId + 1 86 | if callBackId >= 65565 then 87 | callBackId = 0 88 | TriggeredCalls = {} 89 | end 90 | 91 | self.uniqueId = self.name .. tostring(callBackId) 92 | 93 | TriggerClientEvent("vorp:TriggerServerCallback", source, self.name, self.uniqueId, false, ...) 94 | 95 | TriggeredCalls[self.uniqueId] = self._callback 96 | end 97 | 98 | function ServerRPC:TriggerRpcAwait(source, ...) 99 | if not self.name and type(self.name) ~= "string" then 100 | return error("Callback name must be a string!", 1) 101 | end 102 | callBackId = callBackId + 1 103 | if callBackId >= 65565 then 104 | callBackId = 0 105 | TriggeredCalls = {} 106 | end 107 | 108 | self.uniqueId = self.name .. tostring(callBackId) 109 | TriggerClientEvent("vorp:TriggerServerCallback", source, self.name, self.uniqueId, true, ...) 110 | 111 | local promise = promise.new() 112 | TriggeredCalls[self.uniqueId] = promise 113 | 114 | local result = Citizen.Await(promise) 115 | return result 116 | end 117 | 118 | function ServerRPC.ExecuteRpc(uniqueId, isSync, name, ...) 119 | local _source = source 120 | if not TriggeredCalls[uniqueId] then 121 | return error("ERROR: No callback with this id found! callback name: " .. name, 1) 122 | end 123 | 124 | if not isSync then 125 | TriggeredCalls[uniqueId](...) 126 | else 127 | TriggeredCalls[uniqueId]:resolve(...) 128 | end 129 | TriggeredCalls[uniqueId] = nil 130 | end 131 | 132 | RegisterNetEvent('vorp:ServerCallback', ServerRPC.ExecuteRpc) 133 | 134 | 135 | -- Export 136 | exports("ServerRpcCall", function() 137 | return ServerRPC 138 | end) 139 | 140 | -- backwards compatibility 141 | RegisterNetEvent("vorp:addNewCallBack", ServerRPC.Callback.Register) 142 | -------------------------------------------------------------------------------- /server/class/user.lua: -------------------------------------------------------------------------------- 1 | GlobalState.PlayersInSession = 0 2 | 3 | ---@param source number 4 | ---@param identifier string 5 | ---@param group string 6 | ---@param playerwarnings number 7 | ---@param license string 8 | ---@param char number 9 | ---@return User 10 | function User(source, identifier, group, playerwarnings, license, char) 11 | local self = {} 12 | self._identifier = identifier 13 | self._license = license 14 | self._group = group 15 | self._playerwarnings = playerwarnings 16 | self._charperm = char 17 | self._usercharacters = {} 18 | self._numofcharacters = 0 19 | self.usedCharacterId = -1 20 | self.source = source 21 | self.steamname = GetPlayerName(source) or "" 22 | 23 | self.UsedCharacterId = function(value) 24 | if value ~= nil then 25 | self.usedCharacterId = value 26 | self._usercharacters[value].source = self.source 27 | self._usercharacters[value].updateCharUi() 28 | local player = self._usercharacters[self.usedCharacterId].getCharacter() 29 | GlobalState.PlayersInSession = GlobalState.PlayersInSession + 1 30 | TriggerClientEvent("vorp:SelectedCharacter", self.source, self.usedCharacterId) 31 | TriggerEvent("vorp:SelectedCharacter", self.source, player) 32 | Player(self.source).state:set('IsInSession', true, true) 33 | Player(self.source).state:set('Character', { 34 | Group = player.group, 35 | FirstName = player.firstname, 36 | LastName = player.lastname, 37 | Job = player.job, 38 | JobLabel = player.jobLabel, 39 | Grade = player.jobGrade, 40 | Gender = player.gender, 41 | Age = player.age, 42 | CharDescription = player.charDescription, 43 | NickName = player.nickname, 44 | Money = player.money, 45 | Gold = player.gold, 46 | Rol = player.rol, 47 | CharId = self.usedCharacterId, 48 | }, true) 49 | end 50 | 51 | return self.usedCharacterId 52 | end 53 | 54 | 55 | self.Source = function(value) 56 | if value then 57 | self.source = value 58 | end 59 | return self.source 60 | end 61 | 62 | self.Numofcharacters = function(value) 63 | if value then 64 | self._numofcharacters = value 65 | end 66 | return self._numofcharacters 67 | end 68 | 69 | self.Identifier = function(value) 70 | if value then 71 | self._identifier = value 72 | end 73 | return self._identifier 74 | end 75 | 76 | self.License = function(value) 77 | if value then 78 | self._license = value 79 | end 80 | return self._license 81 | end 82 | 83 | self.Group = function(value) 84 | if value then 85 | self._group = value 86 | MySQL.update("UPDATE users SET `group` = ? WHERE `identifier` = ?", { self._group, self.Identifier() }) 87 | end 88 | return self._group 89 | end 90 | 91 | self.Playerwarnings = function(value) 92 | if value then 93 | self._playerwarnings = value 94 | MySQL.update("UPDATE users SET `warnings` = ? WHERE `identifier` = ?", { self._playerwarnings, self.Identifier() }) 95 | end 96 | 97 | return self._playerwarnings 98 | end 99 | 100 | self.Charperm = function(value) 101 | if value ~= nil then 102 | self._charperm = value 103 | MySQL.update("UPDATE users SET `char` = ? WHERE `identifier` = ?", { self._charperm, self.Identifier() }) 104 | end 105 | 106 | return self._charperm 107 | end 108 | 109 | self.GetUser = function() 110 | local userData = {} 111 | userData.getCharperm = self.Charperm() 112 | userData.source = self.source 113 | userData.getGroup = self.Group() 114 | userData.getUsedCharacter = self.UsedCharacter() 115 | userData.getUserCharacters = self.UserCharacters() 116 | 117 | userData.getIdentifier = function() 118 | return self.Identifier() 119 | end 120 | 121 | userData.getPlayerwarnings = function() 122 | return self.Playerwarnings() 123 | end 124 | 125 | userData.setPlayerWarnings = function(warnings) 126 | self.Playerwarnings(warnings) 127 | end 128 | 129 | userData.setGroup = function(group) 130 | self.Group(group) 131 | end 132 | 133 | userData.setCharperm = function(char) 134 | self.Charperm(char) 135 | end 136 | 137 | userData.getNumOfCharacters = function() 138 | return self._numofcharacters 139 | end 140 | 141 | userData.addCharacter = function(data) 142 | self._numofcharacters = self._numofcharacters + 1 143 | self.addCharacter(data) 144 | end 145 | 146 | userData.removeCharacter = function(charid) 147 | if self._usercharacters[charid] then 148 | self._numofcharacters = self._numofcharacters - 1 149 | self.delCharacter(charid) 150 | end 151 | end 152 | 153 | userData.setUsedCharacter = function(charid) 154 | self.SetUsedCharacter(charid) 155 | end 156 | 157 | return userData 158 | end 159 | 160 | self.UsedCharacter = function() 161 | if self._usercharacters[self.usedCharacterId] then 162 | return self._usercharacters[self.usedCharacterId].getCharacter() 163 | end 164 | 165 | return {} 166 | end 167 | 168 | self.UserCharacters = function() 169 | local userCharacters = {} 170 | for k, v in pairs(self._usercharacters) do 171 | table.insert(userCharacters, v.getCharacter()) 172 | end 173 | return userCharacters 174 | end 175 | 176 | self.LoadCharacters = function() 177 | MySQL.query("SELECT identifier, charidentifier, `group`, job, jobgrade, joblabel, firstname, lastname, inventory, status, coords, money, gold, rol, healthouter, healthinner, staminaouter, staminainner, xp, isdead, skinPlayer, compPlayer, compTints, age,gender, character_desc, nickname, slots,skills FROM characters WHERE identifier = @identifier", { identifier = self._identifier }, function(usercharacters) 178 | self.Numofcharacters(#usercharacters) 179 | if #usercharacters > 0 then 180 | for _, character in ipairs(usercharacters) do 181 | if character.identifier then 182 | local data = { 183 | identifier = character.identifier, 184 | charIdentifier = character.charidentifier, 185 | group = character.group, 186 | job = character.job, 187 | jobgrade = character.jobgrade, 188 | joblabel = character.joblabel, 189 | firstname = character.firstname, 190 | lastname = character.lastname, 191 | inventory = character.inventory, 192 | status = character.status, 193 | coords = character.coords, 194 | money = character.money, 195 | gold = character.gold, 196 | rol = character.rol, 197 | healthOuter = character.healthouter, 198 | healthInner = character.healthinner, 199 | staminaOuter = character.staminaouter, 200 | staminaInner = character.staminainner, 201 | xp = character.xp, 202 | isdead = character.isdead, 203 | skin = character.skinPlayer, 204 | comps = character.compPlayer, 205 | source = self.source, 206 | compTints = character.compTints, 207 | age = character.age, 208 | gender = character.gender, 209 | charDescription = character.character_desc, 210 | nickname = character.nickname, 211 | steamname = self.steamname, 212 | slots = character.slots or 200, 213 | skills = character.skills and json.decode(character.skills) or {}, 214 | } 215 | local newCharacter = Character(data) 216 | self._usercharacters[newCharacter.CharIdentifier()] = newCharacter 217 | end 218 | end 219 | end 220 | end) 221 | end 222 | 223 | self.addCharacter = function(data) 224 | local info = { 225 | identifier = self._identifier, 226 | charIdentifier = -1, 227 | group = Config.initGroup, 228 | job = Config.initJob, 229 | jobgrade = Config.initJobGrade, 230 | joblabel = Config.initJobLabel, 231 | firstname = data.firstname, 232 | lastname = data.lastname, 233 | inventory = "{}", 234 | status = "{}", 235 | coords = "{}", 236 | money = Config.initMoney, 237 | gold = Config.initGold, 238 | rol = Config.initRol, 239 | healthOuter = 500, 240 | healthInner = 100, 241 | staminaOuter = 500, 242 | staminaInner = 100, 243 | xp = Config.initXp, 244 | isdead = false, 245 | skin = data.skin, 246 | comps = data.comps, 247 | source = self.source, 248 | compTints = data.compTints, 249 | age = data.age, 250 | gender = data.gender, 251 | charDescription = data.charDescription, 252 | nickname = data.nickname, 253 | steamname = self.steamname, 254 | slots = Config.initInvCapacity or 200, 255 | skills = {}, 256 | } 257 | 258 | local newChar = Character(info) 259 | 260 | newChar.SaveNewCharacterInDb(function(id) 261 | newChar.CharIdentifier(id) 262 | self._usercharacters[id] = newChar 263 | self.UsedCharacterId(id) 264 | end) 265 | end 266 | 267 | self.delCharacter = function(charIdentifier) 268 | if self._usercharacters[charIdentifier] then 269 | self._usercharacters[charIdentifier].DeleteCharacter() 270 | self._usercharacters[charIdentifier] = nil 271 | end 272 | end 273 | 274 | self.GetUsedCharacter = function() 275 | if self._usercharacters[self.UsedCharacterId()] then 276 | return self._usercharacters[self.UsedCharacterId()] 277 | else 278 | return nil 279 | end 280 | end 281 | 282 | self.SetUsedCharacter = function(charid) 283 | if self._usercharacters[charid] then 284 | self.UsedCharacterId(charid) 285 | end 286 | end 287 | 288 | self.SaveUser = function() 289 | if self.usedCharacterId and self._usercharacters[self.usedCharacterId] then 290 | if not Player(self.source).state.PlayerIsInCharacterShops then -- dont allow to save position if player is in character shops 291 | local player = self.source 292 | local ped = GetPlayerPed(player) 293 | local Pcoords = GetEntityCoords(ped) 294 | local Pheading = GetEntityHeading(ped) 295 | local characterCoords = json.encode({ x = Pcoords.x, y = Pcoords.y, z = Pcoords.z, heading = Pheading }) 296 | self._usercharacters[self.usedCharacterId].Coords(characterCoords) 297 | end 298 | 299 | self._usercharacters[self.usedCharacterId].SaveCharacterInDb() 300 | end 301 | end 302 | 303 | return self 304 | end 305 | -------------------------------------------------------------------------------- /server/class/whitelisting.lua: -------------------------------------------------------------------------------- 1 | ---@class Whitelist 2 | ---@field _id number 3 | ---@field _identifier string 4 | ---@field _status boolean 5 | ---@field _discordid string 6 | ---@field _firstconnection boolean 7 | ---@alias whitelistFunctions {id : number, identifier : string, status : boolean, discordid : string, firstconnection : boolean} 8 | Whitelist = {} 9 | Whitelist.Functions = {} 10 | Whitelist.__index = Whitelist 11 | Whitelist.__call = function() 12 | return 'Whitelist' 13 | end 14 | 15 | ---@param data {id: number, identifier: string, status: boolean, discordid: string, firstconnection: boolean} 16 | function Whitelist:New(data) 17 | self = setmetatable({}, Whitelist) 18 | self._id = data.id 19 | self._identifier = data.identifier 20 | self._status = data.status 21 | self._discordid = data.discordid 22 | self._firstconnection = data.firstconnection 23 | return self 24 | end 25 | 26 | function Whitelist:Id() 27 | return self._id 28 | end 29 | 30 | function Whitelist:Identifier() 31 | return self._identifier 32 | end 33 | 34 | function Whitelist:Status(value) 35 | if value ~= nil then 36 | self._status = value 37 | MySQL.query('UPDATE whitelist SET status = @status where id = @id', { ['@status'] = value and 1 or 0, ['@id'] = self:Id() }) 38 | end 39 | return self._status 40 | end 41 | 42 | function Whitelist:Discord(value) 43 | if value ~= nil then 44 | self._status = value 45 | MySQL.query('UPDATE whitelist SET discordid = @discordid where id = @id', { ['@discordid'] = value, ['@id'] = self:Id() }) 46 | end 47 | return self._discordid 48 | end 49 | 50 | function Whitelist:Firstconnection(value) 51 | if value ~= nil then 52 | self._firstconnection = value 53 | MySQL.query('UPDATE whitelist SET firstconnection = @firstconnection where id = @id', { ['@firstconnection'] = value, ['@id'] = self:Id() }) 54 | end 55 | return self._firstconnection 56 | end 57 | 58 | function Whitelist:GetEntry() 59 | return { 60 | id = self:Id(), 61 | identifier = self:Identifier(), 62 | status = self:Status(), 63 | discordid = self:Discord(), 64 | firstconnection = self:Firstconnection(), 65 | } 66 | end 67 | 68 | --FUNCTIONS 69 | 70 | --- Get the data of a whitelisted user 71 | ---@param userid number entry id 72 | ---@return whitelistFunctions | nil 73 | function Whitelist.Functions.GetUsersData(userid) 74 | if WhiteListedUsers[userid] then 75 | return WhiteListedUsers[userid]:GetEntry() 76 | end 77 | return nil 78 | end 79 | 80 | --- set the status of a whitelisted user 81 | ---@param id number entry id 82 | ---@param value boolean 83 | function Whitelist.Functions.WhitelistUser(id, value) 84 | if not WhiteListedUsers[id] then 85 | return 86 | end 87 | WhiteListedUsers[id]:Status(value) 88 | end 89 | 90 | --- set Firstconnection of a whitelisted user 91 | ---@param id number entry id 92 | function Whitelist.Functions.GetFirstConnection(id) 93 | if not WhiteListedUsers[id] then 94 | return 95 | end 96 | 97 | return WhiteListedUsers[id]:Firstconnection() 98 | end 99 | 100 | --- set Firstconnection of a whitelisted user 101 | ---@param id number entry id 102 | ---@param value boolean? 103 | function Whitelist.Functions.SetFirstConnection(id, value) 104 | if not WhiteListedUsers[id] then 105 | return 106 | end 107 | 108 | WhiteListedUsers[id]:Firstconnection(value) 109 | end 110 | 111 | --- get user id by identifier 112 | ---@param identifier string 113 | ---@return number | nil 114 | function Whitelist.Functions.GetUserId(identifier) 115 | for k, v in pairs(WhiteListedUsers) do 116 | if v:Identifier() == identifier then 117 | return v:Id() 118 | end 119 | end 120 | return nil 121 | end 122 | 123 | --- insert a new whitelisted user 124 | ---@param data {identifier: string, status: boolean, discordid: string} 125 | ---@return boolean success 126 | function Whitelist.Functions.InsertWhitelistedUser(data) 127 | local entry = MySQL.single.await('SELECT * FROM whitelist WHERE identifier = ?', { data.identifier }) 128 | 129 | if not entry then 130 | MySQL.prepare.await("INSERT INTO whitelist (identifier, status, discordid, firstconnection) VALUES (?,?,?,?)", { data.identifier, false, data.discordid, true }) 131 | return true 132 | end 133 | 134 | if entry.status and not entry.firstconnection then 135 | WhiteListedUsers[entry.id] = Whitelist:New({ id = entry.id, identifier = entry.identifier, status = data.status, discordid = entry.discordid, firstconnection = false }) 136 | return true 137 | end 138 | 139 | MySQL.update('UPDATE whitelist SET status = @status, discordid = @discordid, firstconnection = @firstconnection where id = @id', { ['@status'] = data.status and 1 or 0, ['@discordid'] = entry.discordid, ['@firstconnection'] = false, ['@id'] = entry.id }) 140 | WhiteListedUsers[entry.id] = Whitelist:New({ id = entry.id, identifier = entry.identifier, status = data.status, discordid = entry.discordid, firstconnection = false }) 141 | return true 142 | end 143 | -------------------------------------------------------------------------------- /server/init.lua: -------------------------------------------------------------------------------- 1 | local function init_core() 2 | local IsLinux = false 3 | 4 | print("###############################################################################\n" .. 5 | "\n^1----- ^3#RedM ^1----------------------------------------------------------------------^0\n" .. 6 | " /## /## /###### /####### /####### /###### /###### /####### /########\n" .. 7 | "| ## | ## /##__ ##| ##__ ##| ##__ ## /##__ ## /##__ ##| ##__ ##| ##_____/\n" .. 8 | "| ## | ##| ## | ##| ## | ##| ## | ##| ## |__/| ## | ##| ## | ##| ## \n" .. 9 | "| ## / ##/| ## | ##| #######/| #######/| ## | ## | ##| #######/| ##### \n" .. 10 | " | ## ##/ | ## | ##| ##__ ##| ##____/ | ## | ## | ##| ##__ ##| ##__/ \n" .. 11 | " | ###/ | ## | ##| ## | ##| ## | ## ##| ## | ##| ## | ##| ## \n" .. 12 | " | #/ | ######/| ## | ##| ## | ######/| ######/| ## | ##| ########\n" .. 13 | " |_/ |______/ |__/ |__/|__/ |______/ |______/ |__/ |__/|________/\n" .. 14 | "^1----------------------------------------------------^3VORPcore Framework ^2Lua^0 ^1-----^0\n") 15 | 16 | if IsLinux then 17 | print("\nVORP CORE Running on Linux, thanks for using VorpCore"); 18 | end 19 | end 20 | 21 | local resourcename = GetCurrentResourceName() 22 | if resourcename ~= 'vorp_core' then 23 | return print("^3WARNING ^0 This resource is not named correctly, please change it to ^1'vorp_core'^0.") 24 | end 25 | 26 | local steamwebapikey = GetConvar("steam_webApiKey", "") == "" 27 | if steamwebapikey then 28 | return print("Steam Web API Key is not set, please set it in your server.cfg") 29 | end 30 | 31 | local oneSyncConvar = GetConvar('onesync', 'off') 32 | if oneSyncConvar == 'off' then 33 | return print('^1WARNING: onesync is off, you must enable it in txAdmin settings | onesync infinity') 34 | end 35 | 36 | 37 | ScriptList = {} 38 | Changelogs = 0 39 | 40 | VorpInitialized = false 41 | -- 42 | CreateThread(function() 43 | local Resources = GetNumResources() 44 | 45 | for i = 0, Resources, 1 do 46 | local resource = GetResourceByFindIndex(i) 47 | UpdateChecker(resource) 48 | end 49 | 50 | if next(ScriptList) ~= nil then 51 | VorpInitialized = true 52 | init_core() 53 | Checker() 54 | end 55 | end) 56 | 57 | function UpdateChecker(resource) 58 | if resource and GetResourceState(resource) == 'started' then 59 | if GetResourceMetadata(resource, 'vorp_checker', 0) == 'yes' then 60 | local Name = GetResourceMetadata(resource, 'vorp_name', 0) 61 | local Github = GetResourceMetadata(resource, 'vorp_github', 0) 62 | local Version = GetResourceMetadata(resource, 'vorp_version', 0) 63 | local GithubL, NewestVersion 64 | if Github then 65 | Script = {} 66 | 67 | Script['Resource'] = resource 68 | if Version == nil then 69 | Version = GetResourceMetadata(resource, 'version', 0) 70 | end 71 | if Name ~= nil then 72 | Script['Name'] = Name 73 | else 74 | resource = resource:upper() 75 | Script['Name'] = '^6' .. resource 76 | end 77 | if string.find(Github, "github") then 78 | if string.find(Github, "github.com") then 79 | Script['Github'] = Github 80 | Github = string.gsub(Github, "github", "raw.githubusercontent") .. '/master/version' 81 | else 82 | GithubL = string.gsub(Github, "raw.githubusercontent", "github"):gsub("/master", "") 83 | Github = Github .. '/version' 84 | Script['Github'] = GithubL 85 | end 86 | else 87 | Script['Github'] = Github .. '/version' 88 | end 89 | PerformHttpRequest(Github, function(Error, V, Header) 90 | NewestVersion = V 91 | end) 92 | repeat 93 | Wait(10) 94 | until NewestVersion ~= nil 95 | 96 | StripVersion = NewestVersion:match("<%d?%d.%d?%d.?%d?%d?>") 97 | if StripVersion == nil then 98 | print(Name, "Version is setup incorrectly!") 99 | else 100 | CleanedVersion = StripVersion:gsub("[<>]", "") 101 | Version1 = CleanedVersion 102 | 103 | if string.find(Version1, Version) then 104 | else 105 | if Version1 < Version then 106 | Changelog = "Your script version is newer than what was found in github" 107 | NewestVersion = Version 108 | else 109 | local MinV = NewestVersion:gsub("<" .. Version1 .. ">", "") 110 | local StripedExtra 111 | local isMatch = MinV:match("<" .. Version .. ">") 112 | if isMatch then 113 | StripedExtra = MinV:gsub("<" .. Version .. ">.*", "") 114 | else 115 | StripedExtra = MinV:gsub("<%d?%d.%d?%d.?%d?%d?>.*", "") 116 | end 117 | 118 | local stripedVersions = StripedExtra:gsub("<%d?%d.%d?%d.?%d?%d?>", "") 119 | 120 | local Changelog = stripedVersions 121 | Changelog = string.gsub(Changelog, "\n", "") 122 | Changelog = string.gsub(Changelog, "-", " \n-"):gsub("%b<>", ""):sub(1, -2) 123 | 124 | NewestVersion = Version1 125 | 126 | Script['CL'] = true 127 | Script['Changelog'] = Changelog 128 | end 129 | end 130 | Script['NewestVersion'] = Version1 131 | Script['Version'] = Version 132 | 133 | table.insert(ScriptList, Script) 134 | end 135 | else 136 | print(Name, "version metadata now found in the fxmanifest", resource) 137 | end 138 | end 139 | end 140 | end 141 | 142 | function Checker() 143 | print("^3VORPcore Version check ") 144 | print("^2Resources found\n") 145 | 146 | local outdated, upToDate = {}, {} 147 | 148 | for i, v in pairs(ScriptList) do 149 | if string.find(v.NewestVersion, v.Version) then 150 | table.insert(upToDate, 151 | { 152 | message = '^4' .. v.Name .. ' (' .. v.Resource .. ') ^2✅ ' .. 'Up to date - Version ' .. v.Version .. '\n' 153 | }) 154 | elseif v.Version > v.NewestVersion then 155 | table.insert(outdated, { 156 | message = '^4' .. v.Name .. ' (' .. v.Resource .. ') ⚠️ ' .. 'Mismatch (v' .. v.Version .. ') ^5- Official Version: ' .. v.NewestVersion .. ' ^0(' .. v.Github .. ')\n' 157 | }) 158 | else 159 | table.insert(outdated, { 160 | message = '^4' .. v.Name .. ' (' .. v.Resource .. ') ^1❌ ' .. 'Outdated (v' .. v.Version .. ') ^5- Update found: Version ' .. v.NewestVersion .. ' ^0(' .. v.Github .. ')\n' 161 | }) 162 | end 163 | 164 | if v.CL then 165 | Changelogs = Changelogs + 1 166 | end 167 | end 168 | -- print outdated first and up-to-date at the end 169 | for _, data in ipairs(outdated) do 170 | print(data.message) 171 | end 172 | 173 | if Changelogs > 0 then 174 | print('^1###############################') 175 | Changelog() 176 | else 177 | print('^0\n###############################################################################') 178 | end 179 | 180 | for _, data in ipairs(upToDate) do 181 | print(data.message) 182 | end 183 | end 184 | 185 | function Changelog() 186 | print('') 187 | for _, v in pairs(ScriptList) do 188 | local isNewVersion = v.Version ~= v.NewestVersion 189 | local hasChangelog = v.CL 190 | 191 | if isNewVersion and hasChangelog then 192 | local resourceUpper = v.Resource:upper() 193 | local clStringFmt = '^3%s - Changelog:\n^0%s\n^1###############################^0\n' 194 | print(string.format(clStringFmt, resourceUpper, v.Changelog)) 195 | end 196 | end 197 | print('^0###############################################################################') 198 | end 199 | -------------------------------------------------------------------------------- /server/instance.lua: -------------------------------------------------------------------------------- 1 | local Namedinstances = {} 2 | math.randomseed(os.time()) 3 | 4 | -- credits to MrDankKetchup 5 | RegisterServerEvent("vorp_core:instanceplayers") 6 | AddEventHandler("vorp_core:instanceplayers", function(setRoom) 7 | local src = source 8 | local instanceSource = nil 9 | 10 | -- if setRoom is 0, then we are leaving the instance 11 | if setRoom == 0 then 12 | for k, v in pairs(Namedinstances) do 13 | for k2, v2 in pairs(v.people) do 14 | if v2 == src then 15 | table.remove(v.people, k2) 16 | end 17 | end 18 | if #v.people == 0 then 19 | Namedinstances[k] = nil 20 | end 21 | end 22 | instanceSource = setRoom 23 | else 24 | for k, v in pairs(Namedinstances) do 25 | if v.name == setRoom then 26 | instanceSource = k 27 | end 28 | end 29 | 30 | if instanceSource == nil then 31 | instanceSource = math.random(1, 63) 32 | 33 | while Namedinstances[instanceSource] and #Namedinstances[instanceSource] >= 1 do 34 | instanceSource = math.random(1, 63) 35 | Wait(1) 36 | end 37 | end 38 | end 39 | 40 | if instanceSource ~= 0 then 41 | if not Namedinstances[instanceSource] then 42 | Namedinstances[instanceSource] = { 43 | name = setRoom, 44 | people = {} 45 | } 46 | end 47 | 48 | table.insert(Namedinstances[instanceSource].people, src) 49 | end 50 | 51 | SetPlayerRoutingBucket(src, instanceSource) 52 | --todo: document this 53 | TriggerClientEvent('vorp_core:instanceChanged', src, instanceSource) 54 | end) 55 | -------------------------------------------------------------------------------- /server/loadcharacter.lua: -------------------------------------------------------------------------------- 1 | --TX ADMIN HEAL EVENT 2 | AddEventHandler('txAdmin:events:healedPlayer', function(eventData) 3 | if GetInvokingResource() ~= "monitor" or type(eventData) ~= "table" or type(eventData.id) ~= "number" then 4 | return 5 | end 6 | 7 | local Player = eventData.id 8 | if Player ~= -1 then 9 | local identifier = GetPlayerIdentifierByType(Player, 'steam') 10 | if not identifier or not _users[identifier] then return end 11 | 12 | local Character = _users[identifier].GetUsedCharacter() 13 | if Character and Character.isdead then 14 | CoreFunctions.NotifyRightTip(Player, Translation[Lang].Notify.healself, 4000) 15 | CoreFunctions.Player.Revive(Player) 16 | end 17 | else 18 | CoreFunctions.NotifyRightTip(-1, Translation[Lang].Notify.healall, 4000) 19 | CoreFunctions.Player.Revive(-1) 20 | end 21 | end) 22 | 23 | RegisterNetEvent('vorp:ImDead', function(isDead) 24 | local _source = source 25 | 26 | local identifier = GetPlayerIdentifierByType(_source, 'steam') 27 | if identifier and _users[identifier] then 28 | _users[identifier].GetUsedCharacter().setDead(isDead) 29 | end 30 | end) 31 | 32 | RegisterServerEvent('vorp:SaveDate', function() 33 | local _source = source 34 | local identifier = GetPlayerIdentifierByType(_source, 'steam') 35 | local Character = _users[identifier].GetUsedCharacter() 36 | local charid = Character.charIdentifier 37 | MySQL.update("UPDATE characters SET LastLogin =NOW() WHERE charidentifier =@charidentifier", { charidentifier = charid }) 38 | end) 39 | 40 | 41 | RegisterNetEvent("vorp_core:PlayerRespawnInternal", function(param) 42 | local _source = source 43 | CoreFunctions.Player.Respawn(_source, param) 44 | end) 45 | -------------------------------------------------------------------------------- /server/loadusers.lua: -------------------------------------------------------------------------------- 1 | local _usersLoading = {} 2 | _users = {} 3 | _healthData = {} 4 | 5 | local T = Translation[Lang].MessageOfSystem 6 | 7 | 8 | 9 | function GetMaxCharactersAllowed(source) 10 | local identifier = GetPlayerIdentifierByType(source, 'steam') 11 | local user = _users[identifier] 12 | if not user then 13 | return 14 | end 15 | return user._charperm 16 | end 17 | 18 | local function savePlayer(_source, reason, identifier) 19 | local discordId = GetDiscordID(_source) 20 | local steamName = GetPlayerName(_source) 21 | 22 | if _users[identifier] and _users[identifier].GetUsedCharacter() then 23 | if Config.SavePlayersStatus then 24 | _users[identifier].GetUsedCharacter().HealthOuter(_healthData[identifier].hOuter) 25 | _users[identifier].GetUsedCharacter().HealthInner(_healthData[identifier].hInner) 26 | _users[identifier].GetUsedCharacter().StaminaOuter(_healthData[identifier].sOuter) 27 | _users[identifier].GetUsedCharacter().StaminaInner(_healthData[identifier].sInner) 28 | end 29 | _users[identifier].SaveUser() 30 | Player(_source).state:set('Character', nil, true) 31 | Player(_source).state:set('IsInSession', nil, true) 32 | end 33 | 34 | if Logs.EnableWebhookJoinleave then 35 | local finaltext = string.format(T.PlayerJoinLeave.Leave, steamName, identifier, reason and (T.PlayerJoinLeave.Reason .. reason) or "") 36 | TriggerEvent("vorp_core:addWebhook", T.PlayerJoinLeave.Leavetitle, Logs.LeaveWebhookURL, finaltext) 37 | end 38 | 39 | if Config.SaveDiscordId then --TODO this can de added as default 40 | MySQL.update('UPDATE characters SET `discordid` = ? WHERE `identifier` = ? ', { discordId, identifier }) 41 | end 42 | end 43 | 44 | local function removePlayer(identifier, license) 45 | if not identifier or not license then 46 | return 47 | end 48 | 49 | if _usersLoading[license] then 50 | _usersLoading[license] = nil 51 | end 52 | 53 | local userid = Whitelist.Functions.GetUserId(identifier) 54 | if userid and WhiteListedUsers[userid] then 55 | WhiteListedUsers[userid] = nil 56 | end 57 | 58 | SetTimeout(6000, function() 59 | if _users[identifier] then 60 | _users[identifier] = nil 61 | end 62 | end) 63 | end 64 | 65 | local function ReportCrash(reason, _source) 66 | local _, _, errorMessage = reason:find("RAGE error:%s(.+)") 67 | if not errorMessage then 68 | _, _, errorMessage = reason:find("Game crashed:%s(.+)") 69 | end 70 | 71 | if errorMessage then 72 | local ped = GetPlayerPed(_source) 73 | local pcoords = GetEntityCoords(ped) 74 | local coords = { 75 | x = pcoords.x, 76 | y = pcoords.y, 77 | z = pcoords.z 78 | } 79 | local crash_id = string.lower(errorMessage:gsub("%b()", "")) 80 | PerformHttpRequest("http://api.polycode.pl:8080/api/crashes", function(code, data, _) 81 | if code ~= 200 then 82 | print("[Crash Reporter] Failed to send crash report: HTTP " .. tostring(code)) 83 | if data then 84 | local decoded = json.decode(data) 85 | if decoded and decoded.error then 86 | print("[Crash Reporter] Server error: " .. decoded.error) 87 | else 88 | print("[Crash Reporter] Response: " .. tostring(data)) 89 | end 90 | end 91 | end 92 | end, "POST", json.encode({ 93 | apiKey = Config.API_KEY, 94 | crash_id = crash_id, 95 | server = GetConvar("sv_projectName", "Unknown"), 96 | coords = json.encode(coords) 97 | }), { 98 | ["Content-Type"] = "application/json" 99 | }) 100 | end 101 | end 102 | 103 | if Config.ReportCrash and Config.API_KEY ~= "" then 104 | CreateThread(function() 105 | SetTimeout(5000, function() 106 | local resourceList = {} 107 | for i = 0, GetNumResources(), 1 do 108 | local resource_name = GetResourceByFindIndex(i) 109 | if resource_name and GetResourceState(resource_name) == "started" then 110 | table.insert(resourceList, resource_name) 111 | end 112 | end 113 | PerformHttpRequest("http://api.polycode.pl:8080/api/resources", function(_, _, _) 114 | end, "POST", json.encode({ 115 | apiKey = Config.API_KEY, 116 | server = GetConvar("sv_projectName", "Unknown"), 117 | resourceList = json.encode(resourceList) 118 | }), { 119 | ["Content-Type"] = "application/json" 120 | }) 121 | end) 122 | end) 123 | end 124 | 125 | AddEventHandler('playerDropped', function(reason) 126 | local _source = source 127 | local identifier = GetPlayerIdentifierByType(_source, 'steam') 128 | local license = GetPlayerIdentifierByType(_source, 'license') 129 | savePlayer(_source, reason, identifier) 130 | removePlayer(identifier, license) 131 | if Config.ReportCrashes and Config.API_KEY ~= "" then 132 | ReportCrash(reason, _source) 133 | end 134 | GlobalState.PlayersInSession = GlobalState.PlayersInSession - 1 135 | end) 136 | 137 | ---@todo allow to save player when they are still in the server example of usage is not have to relog to select another character 138 | --[[ AddEventHandler("vorp_core:playerRemove", function(source) 139 | local _source = source 140 | local identifier = GetPlayerIdentifierByType(_source, 'steam') 141 | savePlayer(_source, nil, identifier) 142 | end) 143 | 144 | AddEventHandler("vorp:Server:playerLeave", function(source) -- trigger this event when you have logic to remove player 145 | local _source = source 146 | TriggerEvent("vorp_core:playerRemove", _source) -- save player 147 | TriggerClientEvent("vorp_core:Client:playerLeave", _source) -- let client know character left 148 | end) ]] 149 | 150 | AddEventHandler("playerJoining", function() 151 | local _source = source 152 | local identifier = GetPlayerIdentifierByType(_source, 'steam') 153 | local license = GetPlayerIdentifierByType(_source, 'license') 154 | Player(_source).state:set('IsInSession', false, true) 155 | 156 | if not identifier or not license then 157 | return print("user cant load no identifier steam or license found") 158 | end 159 | 160 | if _usersLoading[license] then 161 | return DropPlayer(_source, "player with this license is already in game") 162 | end 163 | _usersLoading[license] = _source 164 | 165 | local user = MySQL.single.await('SELECT `group`, `warnings`, `char` FROM users WHERE identifier = ?', { identifier }) 166 | if user then 167 | _users[identifier] = User(_source, identifier, user.group, user.warnings, license, user.char) 168 | _users[identifier].LoadCharacters() 169 | else 170 | local count = MySQL.scalar.await('SELECT COUNT(*) FROM users') or 0 171 | local defaultGroup = count == 0 and "admin" or "user" 172 | 173 | MySQL.insert("INSERT INTO users VALUES(?,?,?,?,?,?)", { identifier, defaultGroup, 0, 0, 0, Config.MaxCharacters }) 174 | _users[identifier] = User(_source, identifier, defaultGroup, 0, license, Config.MaxCharacters) 175 | end 176 | end) 177 | 178 | 179 | RegisterNetEvent('vorp:playerSpawn', function() 180 | local _source = source 181 | local identifier = GetPlayerIdentifierByType(_source, 'steam') 182 | 183 | if not identifier then 184 | return print("user cant load no identifier steam found") 185 | end 186 | 187 | local user = _users[identifier] 188 | if not user then 189 | return 190 | end 191 | 192 | user.Source(_source) 193 | 194 | local numCharacters = user.Numofcharacters() 195 | 196 | if numCharacters <= 0 then 197 | return TriggerEvent("vorp_CreateNewCharacter", _source) 198 | else 199 | if tonumber(user._charperm) > 1 then 200 | return TriggerEvent("vorp_character:server:GoToSelectionMenu", _source) 201 | else 202 | return TriggerEvent("vorp_character:server:SpawnUniqueCharacter", _source) 203 | end 204 | end 205 | end) 206 | 207 | 208 | RegisterNetEvent('vorp:SaveHealth', function(healthOuter, healthInner) 209 | local _source = source 210 | local identifier = GetPlayerIdentifierByType(_source, 'steam') 211 | 212 | if healthInner and healthOuter then 213 | local user = _users[identifier] or nil 214 | 215 | if user then 216 | local used_char = user.GetUsedCharacter() or nil 217 | 218 | if used_char then 219 | used_char.HealthOuter(healthOuter - healthInner) 220 | used_char.HealthInner(healthInner) 221 | end 222 | end 223 | end 224 | end) 225 | 226 | RegisterNetEvent('vorp:SaveStamina', function(staminaOuter, staminaInner) 227 | local _source = source 228 | local identifier = GetPlayerIdentifierByType(_source, 'steam') 229 | if staminaOuter and staminaInner then 230 | local user = _users[identifier] or nil 231 | if user then 232 | local used_char = user.GetUsedCharacter() or nil 233 | if used_char then 234 | used_char.StaminaOuter(staminaOuter) 235 | used_char.StaminaInner(staminaInner) 236 | end 237 | end 238 | end 239 | end) 240 | 241 | RegisterNetEvent('vorp:HealthCached', function(healthOuter, healthInner, staminaOuter, staminaInner) 242 | local _source = source 243 | local identifier = GetPlayerIdentifierByType(_source, 'steam') 244 | 245 | if not identifier then 246 | return 247 | end 248 | 249 | if not _healthData[identifier] then 250 | _healthData[identifier] = {} 251 | end 252 | 253 | _healthData[identifier].hOuter = healthOuter 254 | _healthData[identifier].hInner = healthInner 255 | _healthData[identifier].sOuter = staminaOuter 256 | _healthData[identifier].sInner = staminaInner 257 | end) 258 | 259 | RegisterNetEvent("vorp:GetValues", function() 260 | local _source = source 261 | local healthData = { hOuter = 10, hInner = 10, sOuter = 10, sInner = 10 } 262 | local identifier = GetPlayerIdentifierByType(_source, 'steam') 263 | local user = _users[identifier] or nil 264 | 265 | -- Only if the player exists in online table... 266 | if user and user.GetUsedCharacter then 267 | local used_char = user.GetUsedCharacter() or nil 268 | 269 | -- Only there is an character... 270 | if used_char then 271 | healthData.hOuter = used_char.HealthOuter() or 10 272 | healthData.hInner = used_char.HealthInner() or 10 273 | healthData.sOuter = used_char.StaminaOuter() or 10 274 | healthData.sInner = used_char.StaminaInner() or 10 275 | end 276 | end 277 | 278 | TriggerClientEvent("vorp:GetHealthFromCore", _source, healthData) 279 | end) 280 | 281 | -- clean up users table if character is deleted 282 | if Config.DeleteFromUsersTable and not Config.Whitelist then 283 | MySQL.ready(function() 284 | local query = "DELETE FROM users WHERE NOT EXISTS (SELECT 1 FROM characters WHERE characters.identifier = users.identifier);" 285 | MySQL.query(query, {}) 286 | end) 287 | end 288 | -------------------------------------------------------------------------------- /server/logs.lua: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------------------------------------------- 2 | --------------------------------------------------- DISCORD -------------------------------------------------------- 3 | 4 | RegisterServerEvent('vorp_core:addWebhook') 5 | AddEventHandler('vorp_core:addWebhook', function(title, webhook, description, color, name, logo, footerlogo, avatar) 6 | if not webhook or webhook == "" then 7 | return 8 | end 9 | local webhookColor = (not color or color == "") and Config.webhookColor or color 10 | local webhookName = (not name or name == "") and Config.name or name 11 | local webhookLogo = (not logo or logo == "") and Config.logo or logo 12 | local webhookFooterLogo = (not footerlogo or footerlogo == "") and Config.footerLogo or footerlogo 13 | local webhookAvatar = (not avatar or avatar == "") and Config.Avatar or avatar 14 | 15 | PerformHttpRequest(webhook, function(err, text, headers) 16 | 17 | end, 'POST', json.encode({ 18 | embeds = { 19 | { 20 | color = webhookColor, 21 | author = { 22 | name = webhookName, 23 | icon_url = webhookLogo, 24 | }, 25 | title = title, 26 | description = description, 27 | footer = { 28 | text = "VORPcore" .. " • " .. os.date("%x %X %p"), 29 | icon_url = webhookFooterLogo, 30 | 31 | }, 32 | }, 33 | }, 34 | avatar_url = webhookAvatar 35 | }), { 36 | ['Content-Type'] = 'application/json' 37 | }) 38 | end) 39 | -------------------------------------------------------------------------------- /server/old_api.lua: -------------------------------------------------------------------------------- 1 | ---@deprecated PLEASE UPDATE TO NEW API 2 | exports('vorpAPI', function() 3 | local self = {} 4 | 5 | self.getCharacter = function(source) 6 | local timeout = 200 -- 5 seconds 7 | local user = nil 8 | TriggerEvent("vorp:getCharacter", source, function(result) 9 | user = result 10 | end) 11 | 12 | while user == nil and timeout ~= 0 do 13 | timeout = timeout - 1 14 | Wait(25) 15 | end 16 | 17 | if timeout == 0 then 18 | print("VORP Core: Callback is nil or not loaded ERROR: Timeout") 19 | end 20 | print("JUST A WARNING: this are deprecated API please refer to api docs to use new ones.") 21 | return user 22 | end 23 | print("JUST A WARNING: this are deprecated API please refer to api docs to use new ones.") 24 | 25 | self.addMoney = function(source, currency, quantity) 26 | TriggerEvent("vorp:addMoney", source, tonumber(currency), tonumber(quantity)) 27 | end 28 | 29 | self.removeMoney = function(source, currency, quantity) 30 | TriggerEvent("vorp:removeMoney", source, tonumber(currency), tonumber(quantity)) 31 | end 32 | 33 | self.addXp = function(source, quantity) 34 | TriggerEvent("vorp:addXp", source, tonumber(quantity)) 35 | end 36 | 37 | self.removeXp = function(source, quantity) 38 | TriggerEvent("vorp:removeXp", source, tonumber(quantity)) 39 | end 40 | 41 | self.setJob = function(source, jobname) 42 | TriggerEvent("vorp:setJob", source, jobname) 43 | end 44 | 45 | self.setGroup = function(source, groupname) 46 | TriggerEvent("vorp:setGroup", source, groupname) 47 | end 48 | 49 | self.setJobGrade = function(source, jobgrade) 50 | TriggerEvent("vorp:setJobGrade", source, jobgrade) 51 | end 52 | 53 | self.setInstancePlayer = function(source, active) 54 | TriggerClientEvent("vorp:setInstancePlayer", source, active) 55 | end 56 | 57 | self.addNewCallBack = function(name, cb) 58 | TriggerEvent("vorp:addNewCallBack", name, cb) 59 | end 60 | 61 | return self 62 | end) 63 | 64 | 65 | local function _getUsedCharacter(player) 66 | local sid = GetPlayerIdentifierByType(player, 'steam') 67 | 68 | if not sid then 69 | return nil 70 | end 71 | 72 | local user = _users[sid] or nil 73 | 74 | if not user then 75 | return nil 76 | end 77 | 78 | local used_char = user.GetUsedCharacter() or nil 79 | 80 | return used_char 81 | end 82 | 83 | 84 | AddEventHandler('vorp:getCharacter', function(player, cb) 85 | local function _getCharDetails(player) 86 | local used_char = _getUsedCharacter(player) 87 | 88 | if not used_char then 89 | return nil 90 | end 91 | 92 | local char = used_char.getCharacter() or nil 93 | 94 | return char 95 | end 96 | 97 | local char_details = _getCharDetails(player) 98 | 99 | if char_details ~= nil then 100 | cb(char_details) 101 | end 102 | end) 103 | 104 | AddEventHandler('vorp:addMoney', function(player, typeCash, quantity) 105 | local used_char = _getUsedCharacter(player) 106 | 107 | if used_char ~= nil then 108 | used_char.addCurrency(typeCash, quantity) 109 | used_char.updateCharUi() 110 | end 111 | end) 112 | 113 | AddEventHandler('vorp:removeMoney', function(player, typeCash, quantity) 114 | local used_char = _getUsedCharacter(player) 115 | 116 | if used_char ~= nil then 117 | used_char.removeCurrency(typeCash, quantity) 118 | used_char.updateCharUi() 119 | end 120 | end) 121 | 122 | AddEventHandler('vorp:addXp', function(player, quantity) 123 | local used_char = _getUsedCharacter(player) 124 | 125 | if used_char ~= nil then 126 | used_char.addXp(quantity) 127 | used_char.updateCharUi() 128 | end 129 | end) 130 | 131 | AddEventHandler('vorp:removeXp', function(player, quantity) 132 | local used_char = _getUsedCharacter(player) 133 | 134 | if used_char ~= nil then 135 | used_char.removeXp(quantity) 136 | used_char.updateCharUi() 137 | end 138 | end) 139 | 140 | AddEventHandler('vorp:setJob', function(player, job, jobgrade) 141 | local used_char = _getUsedCharacter(player) 142 | 143 | if used_char ~= nil then 144 | used_char.setJob(job) 145 | used_char.setJobGrade(jobgrade) 146 | end 147 | end) 148 | 149 | AddEventHandler('vorp:setGroup', function(player, group) 150 | local used_char = _getUsedCharacter(player) 151 | 152 | if used_char ~= nil then 153 | used_char.setGroup(group) 154 | end 155 | end) 156 | -------------------------------------------------------------------------------- /server/richpresence.lua: -------------------------------------------------------------------------------- 1 | -- get player count from server 2 | ServerRPC.Callback.Register("vorp:richpresence:callback:getplayers", function(source, callback) 3 | local pCount = #GetPlayers() 4 | callback(pCount) 5 | end) 6 | -------------------------------------------------------------------------------- /server/saveusers.lua: -------------------------------------------------------------------------------- 1 | CreateThread(function() 2 | while true do 3 | for k, v in pairs(_users) do 4 | if v.usedCharacterId and v.usedCharacterId ~= -1 then 5 | if Player(v.source).state.IsInSession then 6 | v.SaveUser() 7 | end 8 | end 9 | end 10 | Wait(Config.savePlayersTimer * 60000) 11 | end 12 | end) 13 | -------------------------------------------------------------------------------- /server/services/dbupdater/dbupdater.lua: -------------------------------------------------------------------------------- 1 | -- Service that creates a table if it doesnt exist or if the table does exist, add new columns. 2 | local dbversion = nil 3 | 4 | local Tables = { 5 | -- { 6 | -- name = "whitelist", 7 | -- script = "vorp_core", 8 | -- sql = [[ 9 | -- CREATE TABLE IF NOT EXISTS `whitelist` ( 10 | -- `id` int(11) NOT NULL AUTO_INCREMENT, 11 | -- `identifier` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, 12 | -- `status` boolean, 13 | -- `firstconnection` boolean DEFAULT TRUE, 14 | -- PRIMARY KEY (`id`) USING BTREE, 15 | -- UNIQUE INDEX `identifier`(`identifier`) USING BTREE 16 | -- ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; 17 | -- ]] 18 | -- }, 19 | 20 | } 21 | 22 | local Updates = { 23 | 24 | { 25 | name = "users", 26 | script = "vorp_core", 27 | find = [[ 28 | SELECT * FROM Information_Schema.Columns 29 | WHERE Table_Name = 'users' AND COLUMN_NAME = 'char' AND DATA_TYPE = 'int' 30 | ]], 31 | sql = [[ 32 | ALTER TABLE `users` MODIFY COLUMN `char` INT DEFAULT 5; 33 | ]] 34 | } 35 | 36 | } 37 | 38 | dbupdaterAPI = {} 39 | 40 | dbupdaterAPI.addTables = function(tbls) 41 | for _, tbl in ipairs(tbls) do 42 | table.insert(Tables, tbl) 43 | end 44 | end 45 | 46 | dbupdaterAPI.addUpdates = function(updts) 47 | for _, updt in ipairs(updts) do 48 | table.insert(Updates, updt) 49 | end 50 | end 51 | 52 | local function runSQLList(list, type) 53 | for index, it in ipairs(list) do 54 | local hascolumn = false 55 | if it.find then 56 | local findresponse = MySQL.query.await(it.find) 57 | 58 | if #findresponse > 0 then 59 | hascolumn = true 60 | print('^4Database Auto Updater ^3(' .. it.script .. ')^2✅ Column Exists: ' .. it.name .. ' ^0') 61 | end 62 | end 63 | 64 | if hascolumn == false then 65 | MySQL.query(it.sql, function(result) 66 | if result and result.warningStatus > 0 then 67 | local out = '' 68 | if type == 'table' then 69 | out = '^1❌ (' .. dbversion .. ') Failed to Create: ' 70 | if result.warningStatus == 1 or dbversion == 'MySQL' then 71 | out = '^2✅ ' .. 'Table exists: ' 72 | end 73 | else 74 | out = '^1❌ (' .. dbversion .. ') Failed to Updated: ' 75 | end 76 | print('^4Database Auto Updater ^3(' .. it.script .. ')' .. out .. it.name .. ' ^0') 77 | else 78 | local out = '' 79 | if type == 'table' then 80 | out = 'Created Table: ' 81 | else 82 | out = 'Updated Column: ' 83 | end 84 | print('^4Database Auto Updater ^3(' .. it.script .. ')^2✅ ' .. out .. it.name .. '^0') 85 | end 86 | end) 87 | end 88 | end 89 | end 90 | 91 | function RunDBCheck() 92 | local rversion = MySQL.single.await('SELECT VERSION();') 93 | local version = rversion['VERSION()'] 94 | 95 | if string.match(version, "MariaDB") then 96 | dbversion = "MariaDB" 97 | else 98 | dbversion = "MySQL" 99 | end 100 | end 101 | 102 | CreateThread(function() 103 | if not Config.autoUpdateDB then 104 | return 105 | end 106 | 107 | repeat 108 | Wait(10) 109 | until GetResourceState('oxmysql') == 'started' and VorpInitialized == true 110 | 111 | local filedata = LoadResourceFile(GetCurrentResourceName(), "./server/services/dbupdater/status.json") 112 | local status = json.decode(filedata) 113 | local updated = false 114 | 115 | RunDBCheck() 116 | print('') 117 | print("^3VORPcore Database Auto Updater ") 118 | print('') 119 | if status.tablecount < #Tables then 120 | runSQLList(Tables, 'table') 121 | status.tablecount = #Tables 122 | updated = true 123 | end 124 | 125 | if status.updatecount < #Updates then 126 | runSQLList(Updates, 'update') 127 | status.updatecount = #Updates 128 | updated = true 129 | end 130 | 131 | if updated then 132 | SaveResourceFile(GetCurrentResourceName(), "./server/services/dbupdater/status.json", json.encode(status), -1) 133 | else 134 | print('^4Database Auto Updater ^3(' .. dbversion .. ')^2✅ Database is up to date^0') 135 | end 136 | 137 | print('^0###############################################################################') 138 | end) 139 | -------------------------------------------------------------------------------- /server/services/dbupdater/status.json: -------------------------------------------------------------------------------- 1 | {"tablecount":0,"updatecount":0} -------------------------------------------------------------------------------- /server/whitelist.lua: -------------------------------------------------------------------------------- 1 | local T = Translation[Lang].MessageOfSystem 2 | WhiteListedUsers = {} 3 | 4 | local function CheckWhitelistStatusOnConnect(identifier) 5 | local result = MySQL.single.await('SELECT status FROM whitelist WHERE identifier = ?', { identifier }) 6 | if result and result.status ~= nil then 7 | return result.status and true or false 8 | end 9 | return false 10 | end 11 | 12 | function GetDiscordID(src) 13 | local discordId = GetPlayerIdentifierByType(src, 'discord') 14 | local discordIdentifier = discordId and discordId:sub(9) or "" 15 | return discordIdentifier 16 | end 17 | 18 | local function checkBannedUser(setKickReason, deferrals, identifier) 19 | local resultList = MySQL.single.await('SELECT banned, banneduntil FROM users WHERE identifier = ?', { identifier }) 20 | 21 | if resultList then 22 | local user = resultList 23 | if user.banned == true then 24 | local bannedUntilTime = user.banneduntil 25 | local currentTime = tonumber(os.time(os.date("!*t"))) 26 | 27 | if bannedUntilTime == 0 then 28 | deferrals.done(T.permanentlyBan) 29 | setKickReason(T.permanentlyBan) 30 | elseif bannedUntilTime > currentTime then 31 | local bannedUntil = os.date(Config.DateTimeFormat, bannedUntilTime + Config.TimeZoneDifference * 3600) 32 | deferrals.done(T.BannedUser .. bannedUntil .. Config.TimeZone) 33 | setKickReason(T.BannedUser .. bannedUntil .. Config.TimeZone) 34 | else 35 | TriggerEvent("vorpbans:addtodb", false, identifier, 0) 36 | end 37 | end 38 | end 39 | deferrals.done() 40 | end 41 | 42 | AddEventHandler("playerConnecting", function(playerName, setKickReason, deferrals) 43 | local _source = source 44 | deferrals.defer() 45 | 46 | local steamIdentifier = GetPlayerIdentifierByType(_source, 'steam') 47 | 48 | Wait(1) 49 | if not steamIdentifier then 50 | deferrals.done(T.NoSteam) 51 | setKickReason(T.NoSteam) 52 | return CancelEvent() 53 | end 54 | 55 | if Config.Whitelist then 56 | local discordIdentifier = GetDiscordID(_source) 57 | local isPlayerWhiteListed = CheckWhitelistStatusOnConnect(steamIdentifier) 58 | 59 | if not isPlayerWhiteListed then 60 | Whitelist.Functions.InsertWhitelistedUser({ identifier = steamIdentifier, discordid = discordIdentifier, status = false }) 61 | deferrals.done(T.NoInWhitelist .. " steam id: " .. steamIdentifier) 62 | setKickReason(T.NoInWhitelist .. " steam id: " .. steamIdentifier) 63 | return CancelEvent() 64 | else 65 | Whitelist.Functions.InsertWhitelistedUser({ identifier = steamIdentifier, discordid = discordIdentifier, status = true }) 66 | end 67 | end 68 | 69 | deferrals.update(T.LoadingUser) 70 | checkBannedUser(setKickReason, deferrals, steamIdentifier) 71 | 72 | if Logs.EnableWebhookJoinleave then 73 | local finaltext = string.format(T.PlayerJoinLeave.Join, playerName, steamIdentifier) 74 | TriggerEvent("vorp_core:addWebhook", T.JoinTitle, Logs.JoinWebhookURL, finaltext) 75 | end 76 | 77 | --TODO this can de added as default in class characters 78 | if Config.SaveDiscordId then 79 | MySQL.update('UPDATE characters SET `discordid` = ? WHERE `identifier` = ? ', { GetDiscordID(_source), steamIdentifier }) 80 | end 81 | end) 82 | 83 | AddEventHandler('playerJoining', function() 84 | local _source = source 85 | 86 | if not Config.Whitelist then return end 87 | 88 | local identifier = GetPlayerIdentifierByType(_source, 'steam') 89 | local discordId = GetDiscordID(_source) 90 | local userid = Whitelist.Functions.GetUserId(identifier) 91 | 92 | if userid and WhiteListedUsers[userid] then 93 | if not Whitelist.Functions.GetFirstConnection(userid) then 94 | local steamName = GetPlayerName(_source) or "" 95 | local message = string.format(Translation[Lang].addWebhook.whitelistid, steamName, identifier, discordId, userid) 96 | local webhook = "" -- add your webhook here if you use white list 97 | TriggerEvent("vorp_core:addWebhook", Translation[Lang].addWebhook.whitelistid1, webhook, message) 98 | Whitelist.Functions.SetFirstConnection(userid, false) 99 | end 100 | end 101 | end) 102 | -------------------------------------------------------------------------------- /types/client/callback.lua: -------------------------------------------------------------------------------- 1 | ---@class ClientCallBack @CallBack ClientRPC 2 | ---@field TriggerAwait fun(name:string, ...?) 3 | ---@field TriggerAsync fun(name:string, callback: fun(any), ...?) 4 | ---@field Register fun(name: string, callback: fun(callback: fun(any), ...?)) 5 | --- * `CLIENT` see vorpcore >> [documentation](https://vorpcore.github.io/VORP_Documentation/api/core#cient) << for more information 6 | function exports.vorp_core:ClientRpcCall() end 7 | -------------------------------------------------------------------------------- /types/client/notify.lua: -------------------------------------------------------------------------------- 1 | ---@meta 2 | 3 | --- CLIENT SIDE NOTIFICATION 4 | ---@param text string text 5 | ---@param duration number duration 6 | function exports.vorp_core:DisplayTip(text, duration) end 7 | 8 | --- CLIENT SIDE NOTIFICATION 9 | ---@param title string title 10 | ---@param subTitle string subTitle 11 | ---@param dict string dictionary 12 | ---@param icon string icon 13 | ---@param duration number duration 14 | ---@param color string color 15 | function exports.vorp_core:DisplayLeftNotification(title, subTitle, dict, icon, duration, color) end 16 | 17 | --- CLIENT SIDE NOTIFICATION 18 | ---@param text string text 19 | ---@param location string location 20 | ---@param duration number duration 21 | function exports.vorp_core:DisplayTopCenterNotification(text, location, duration) end 22 | 23 | --- CLIENT SIDE NOTIFICATION 24 | ---@param text string text 25 | ---@param duration number duration 26 | function exports.vorp_core:DisplayTipRight(text, duration) end 27 | 28 | --- CLIENT SIDE NOTIFICATION 29 | ---@param text string text 30 | ---@param duration number duration 31 | function exports.vorp_core:DisplayObjective(text, duration) end 32 | 33 | --- CLIENT SIDE NOTIFICATION 34 | ---@param title string text 35 | ---@param subtext string subtext 36 | ---@param duration number duration 37 | function exports.vorp_core:ShowTopNotification(title, subtext, duration) end 38 | 39 | --- CLIENT SIDE NOTIFICATION 40 | ---@param _text string text 41 | ---@param _dict string dict 42 | ---@param icon string icon 43 | ---@param text_color string text_color 44 | ---@param duration number duration 45 | ---@param quality number quality 46 | function exports.vorp_core:ShowAdvancedRightNotification(_text, _dict, icon, text_color, duration, quality, showquality) end 47 | 48 | --- CLIENT SIDE NOTIFICATION 49 | ---@param title string text 50 | ---@param duration number duration 51 | function exports.vorp_core:ShowBasicTopNotification(title, duration) end 52 | 53 | --- CLIENT SIDE NOTIFICATION 54 | ---@param text string text 55 | ---@param duration number duration 56 | ---@param text_color string text_color 57 | function exports.vorp_core:ShowSimpleCenterText(text, duration, text_color) end 58 | 59 | --- CLIENT SIDE NOTIFICATION 60 | ---@param text string text 61 | ---@param duration number duration 62 | function exports.vorp_core:showBottomRight(text, duration) end 63 | 64 | --- CLIENT SIDE NOTIFICATION 65 | ---@param title string title 66 | ---@param subTitle string subTitle 67 | ---@param duration number duration 68 | function exports.vorp_core:failmissioNotifY(title, subTitle, duration) end 69 | 70 | --- CLIENT SIDE NOTIFICATION 71 | ---@param title string title 72 | ---@param _audioRef string audio reference 73 | ---@param _audioName string audio name 74 | ---@param duration number duration 75 | function exports.vorp_core:deadplayerNotifY(title, _audioRef, _audioName, duration) end 76 | 77 | --- CLIENT SIDE NOTIFICATION 78 | ---@param utitle string title 79 | ---@param umsg string message 80 | ---@param duration number duration 81 | function exports.vorp_core:updateMission(utitle, umsg, duration) end 82 | 83 | --- CLIENT SIDE NOTIFICATION 84 | ---@param title string title 85 | ---@param msg string message 86 | ---@param _audioRef string audio reference 87 | ---@param _audioName string audio name 88 | ---@param duration number duration 89 | function exports.vorp_core:warningNotify(title, msg, _audioRef, _audioName, duration) end 90 | 91 | --- CLIENT SIDE NOTIFICATION 92 | ---@param title string title 93 | ---@param subTitle string subTitle 94 | ---@param dict string dictionary 95 | ---@param icon string icon 96 | ---@param duration number duration 97 | ---@param color string color 98 | function exports.vorp_core:LeftRank(title, subTitle, dict, icon, duration, color) end 99 | -------------------------------------------------------------------------------- /types/server/callback.lua: -------------------------------------------------------------------------------- 1 | ---@class CallBack CallBack ServerRPC 2 | ---@field TriggerAwait fun(name:string, source:number, ...?) @Trigger a callback and wait for the response Synchronously 3 | ---@field TriggerAsync fun(name:string, source:number, callback: fun(any), ...?) @Trigger a callback Asynchronously 4 | ---@field Register fun(name: string, callback: fun(source:number,callback: fun(any), ...?)) @Register a callback 5 | --- * `SERVER` see vorpcore >> [documentation](https://vorpcore.github.io/VORP_Documentation/api/core#server) << for more information 6 | function exports.vorp_core:ServerRpcCall() end 7 | -------------------------------------------------------------------------------- /types/server/classes.lua: -------------------------------------------------------------------------------- 1 | ---@meta 2 | 3 | ---@class Character 4 | ---@field public identifier string 5 | ---@field public charIdentifier string 6 | ---@field public group string 7 | ---@field public job string 8 | ---@field public jobLabel string 9 | ---@field public jobGrade number 10 | ---@field public money number 11 | ---@field public gold number 12 | ---@field public rol number 13 | ---@field public xp number 14 | ---@field public healthOuter number 15 | ---@field public healthInner number 16 | ---@field public staminaOuter number 17 | ---@field public staminaInner number 18 | ---@field public firstname string 19 | ---@field public lastname string 20 | ---@field public inventory string 21 | ---@field public status string 22 | ---@field public coords vector 23 | ---@field public isdead boolean 24 | ---@field public skin table 25 | ---@field public comps table 26 | ---@field public compTints table 27 | ---@field public age number 28 | ---@field public skills { [string]: { Level: number, Exp: number,MaxExp:number, MaxLevel: number ,Label:string,NextLevel:number} } 29 | ---@field public updateInvCapacity fun(slots:number) 30 | ---@field public setStatus fun(status:string) 31 | ---@field public setJobGrade fun(jobgrade:number) 32 | ---@field public setJobLabel fun(joblabel:string) 33 | ---@field public setGroup fun(group:string) 34 | ---@field public setJob fun(job:string) 35 | ---@field public setMoney fun(money:number) 36 | ---@field public setGold fun(gold:number) 37 | ---@field public setRol fun(rol:number) 38 | ---@field public setXp fun(xp:number) 39 | ---@field public setFirstname fun(firstname:string) 40 | ---@field public setLastname fun(lastname:string) 41 | ---@field public setAge fun(age:number) 42 | ---@field public setGender fun(gender:string) 43 | ---@field public setCharDescription fun(charDescription:string) 44 | ---@field public setNickName fun(nickname:string) 45 | ---@field public updateSkin fun(skin:table) 46 | ---@field public updateComps fun(comps:table) 47 | ---@field public updateCompTints fun(tints:table) 48 | ---@field public addCurrency fun(currency:number, quantity:number) 49 | ---@field public removeCurrency fun(currency:number, quantity:number) 50 | ---@field public addXp fun(xp:number) 51 | ---@field public removeXp fun(xp:number) 52 | ---@field public updateCharUi fun() 53 | ---@field public setSkills fun(skillName:string,exp:number) 54 | 55 | 56 | ---@class User 57 | ---@field public getCharperm integer 58 | ---@field public source integer 59 | ---@field public getGroup string 60 | ---@field public getUsedCharacter Character 61 | ---@field public getUserCharacters table 62 | ---@field public getIdentifier fun():string 63 | ---@field public getPlayerwarnings fun():number 64 | ---@field public setPlayerWarnings fun(warnings:number) 65 | ---@field public setGroup fun(group:string) 66 | ---@field public setCharperm fun(char:string) 67 | ---@field public getNumOfCharacters fun():number 68 | ---@field public addCharacter fun(data:table) 69 | ---@field public removeCharacter fun(charid:number) 70 | ---@field public setUsedCharacter fun(charid:number) 71 | -------------------------------------------------------------------------------- /ui/app.js: -------------------------------------------------------------------------------- 1 | const { createApp } = Vue; 2 | 3 | createApp({ 4 | data() { 5 | return { 6 | visible: true, 7 | initiated: false, 8 | iconrows: { 9 | token: { 10 | value: 0, 11 | hide: true, 12 | image: './assets/icons/token.png' 13 | }, 14 | gold: { 15 | value: 0, 16 | decimal: '00', 17 | hide: true, 18 | image: './assets/icons/gold.png' 19 | }, 20 | money: { 21 | value: 0, 22 | decimal: '00', 23 | hide: true, 24 | image: './assets/icons/money.png' 25 | }, 26 | pvp: { 27 | value: false, 28 | hide: true, 29 | toggle: false, 30 | image: './assets/icons/pvpoff.png', 31 | offimage: './assets/icons/pvpon.png' 32 | }, 33 | id: { 34 | value: 0, 35 | hide: true, 36 | image: './assets/icons/id.png' 37 | }, 38 | lv: { 39 | xp: 0, 40 | value: 0, 41 | raw: 0, 42 | anim: 0, 43 | hide: true, 44 | type: 'progress', 45 | image: './assets/icons/lv.png' 46 | } 47 | }, 48 | uiposition: 'TopRight', 49 | uilayout: 'Column', 50 | uiicons: 'right', 51 | closeondelay: false, 52 | closeondelayms: 0 53 | }; 54 | }, 55 | mounted() { 56 | // Window Event Listeners 57 | window.addEventListener("message", this.onMessage); 58 | }, 59 | destroyed() { 60 | // Remove listeners when UI is destroyed to save on memory 61 | window.removeEventListener("message"); 62 | }, 63 | computed: { 64 | layoutstyle() { 65 | switch (this.uilayout) { 66 | case 'Column': 67 | this.uiicons = 'right' 68 | return 'layout-column' 69 | case 'Row': 70 | this.uiicons = 'left' 71 | return 'layout-row' 72 | default: 73 | return 'layout-column' 74 | } 75 | }, 76 | contentstyle() { 77 | switch (this.uiposition) { 78 | case 'BottomLeft': 79 | return 'content-bottom-left' 80 | case 'BottomRight': 81 | return 'content-bottom-right' 82 | case 'MiddleRight': 83 | return 'content-middle-right' 84 | case 'TopRight': 85 | return 'content-top-right' 86 | case 'TopMiddle': 87 | return 'content-top-middle' 88 | case 'BottomMiddle': 89 | return 'content-bottom-middle' 90 | default: 91 | return 'content-bottom-right' 92 | } 93 | } 94 | }, 95 | methods: { 96 | onMessage(event) { 97 | let item = event.data; 98 | if (item !== undefined && item.type === "ui") { 99 | switch (event.data.action) { 100 | case "initiate": 101 | this.initiated = true 102 | this.iconrows.money.hide = item.hidemoney 103 | this.iconrows.gold.hide = item.hidegold 104 | this.iconrows.lv.hide = item.hidelevel 105 | this.iconrows.id.hide = item.hideid 106 | this.iconrows.token.hide = item.hidetokens 107 | this.uiposition = item.uiposition 108 | this.uilayout = item.uilayout 109 | this.closeondelay = item.closeondelay 110 | this.closeondelayms = item.closeondelayms 111 | this.iconrows.pvp.hide = item.hidepvp 112 | this.iconrows.pvp.toggle = item.pvp 113 | this.iconrows.pvp.value = item.pvp ? 'On' : 'Off' 114 | 115 | break; 116 | case "update": 117 | if (item && typeof item.moneyquanty === "number") { 118 | this.iconrows.money.value = Math.trunc(item.moneyquanty + 0.0); 119 | this.iconrows.money.decimal = item.moneyquanty.toFixed(2).toString().substr(-2); 120 | } 121 | 122 | if (item && typeof item.goldquanty === "number") { 123 | this.iconrows.gold.value = Math.trunc(item.goldquanty); 124 | this.iconrows.gold.decimal = item.goldquanty.toFixed(2).toString().substr(-2); 125 | } 126 | 127 | if (item && typeof item.rolquanty === "number") { 128 | this.iconrows.token.value = Math.trunc(item.rolquanty); 129 | } 130 | 131 | if (item && typeof item.serverId === "number") { 132 | this.iconrows.id.value = item.serverId; 133 | } 134 | 135 | if (item && typeof item.xp === "number") { 136 | let lv = item.xp / 1000 137 | this.iconrows.lv.xp = item.xp 138 | this.iconrows.lv.value = Math.trunc(lv) 139 | this.iconrows.lv.raw = lv 140 | this.iconrows.lv.anim = Math.floor((lv % 1) * 100) 141 | } 142 | 143 | break; 144 | case "setmoney": 145 | if (item && typeof item.moneyquanty === "number") { 146 | this.iconrows.money.value = Math.trunc(item.moneyquanty + 0.0); 147 | this.iconrows.money.decimal = item.moneyquanty.toFixed(2).toString().substr(-2); 148 | } 149 | 150 | break; 151 | case "setgold": 152 | if (item && typeof item.goldquanty === "number") { 153 | this.iconrows.gold.value = Math.trunc(item.goldquanty); 154 | this.iconrows.gold.decimal = item.goldquanty.toFixed(2).toString().substr(-2); 155 | } 156 | 157 | break; 158 | case "setrol": 159 | if (item && typeof item.rolquanty === "number") { 160 | this.iconrows.token.value = Math.trunc(item.rolquanty); 161 | } 162 | 163 | break; 164 | case "setpvp": 165 | if (item && item.pvp !== null) { 166 | this.iconrows.pvp.toggle = item.pvp 167 | this.iconrows.pvp.value = item.pvp ? 'ON' : 'OFF' 168 | } 169 | 170 | break; 171 | case "setxp": 172 | if (item && typeof item.xp === "number") { 173 | let lvl = item.xp / 1000 174 | this.iconrows.lv.xp = item.xp 175 | this.iconrows.lv.value = Math.trunc(lvl) 176 | this.iconrows.lv.raw = lvl 177 | this.iconrows.lv.anim = Math.floor((lv % 1) * 100) 178 | } 179 | 180 | break; 181 | case "hide": 182 | this.visible = false; 183 | break; 184 | case "show": 185 | this.visible = true; 186 | 187 | if (this.closeondelay) { 188 | setTimeout(() => { 189 | this.visible = false 190 | fetch(`https://${GetParentResourceName()}/close`, { 191 | method: 'POST' 192 | }) 193 | }, this.closeondelayms); 194 | } 195 | break; 196 | default: 197 | break; 198 | } 199 | } 200 | } 201 | }, 202 | }).mount("#app"); 203 | -------------------------------------------------------------------------------- /ui/assets/css/style.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | 6 | @font-face { 7 | font-family: rdr; 8 | src: url(../fonts/rdrlino-regular-webfont.woff); 9 | } 10 | 11 | body { 12 | display: flex; 13 | flex-direction: column; 14 | justify-content: center; 15 | background-color: transparent; 16 | overflow: hidden; 17 | } 18 | 19 | #app { 20 | font-family: rdr; 21 | touch-action: manipulation; 22 | -webkit-font-smoothing: antialiased; 23 | -moz-osx-font-smoothing: grayscale; 24 | color: #fff; 25 | 26 | height: 100vh; 27 | width: 100vw; 28 | } 29 | 30 | .v-enter-active, 31 | .v-leave-active { 32 | transition: opacity 0.8s ease; 33 | } 34 | 35 | .v-enter-from, 36 | .v-leave-to { 37 | opacity: 0; 38 | } 39 | 40 | .content-bottom-left { 41 | position: absolute; 42 | bottom: 18rem; 43 | left: 1rem; 44 | } 45 | 46 | .content-bottom-right { 47 | position: absolute; 48 | bottom: 2rem; 49 | right: 2rem; 50 | } 51 | 52 | .content-top-right { 53 | position: absolute; 54 | top: 8.2rem; 55 | right: 2rem; 56 | } 57 | 58 | .content-middle-right { 59 | position: absolute; 60 | top: 50%; 61 | right: 2rem; 62 | transform: translateY(-50%); 63 | } 64 | 65 | .content-top-middle { 66 | position: absolute; 67 | top: 2rem; 68 | left: 50%; 69 | transform: translateX(-50%); 70 | } 71 | 72 | .content-bottom-middle { 73 | position: absolute; 74 | bottom: 2rem; 75 | left: 50%; 76 | transform: translateX(-50%); 77 | } 78 | 79 | 80 | .content-right { 81 | position: absolute; 82 | bottom: 2rem; 83 | right: 2rem; 84 | } 85 | 86 | .content-row { 87 | text-align: right; 88 | } 89 | 90 | .content-row img{ 91 | height: 1.6rem; 92 | width: 1.6rem; 93 | vertical-align: middle; 94 | } 95 | 96 | .content-row div { 97 | vertical-align: middle; 98 | display: inline-flex; 99 | } 100 | 101 | .content-row .content-font { 102 | font-size: 1.8rem; 103 | letter-spacing: 1px; 104 | vertical-align: middle; 105 | margin-right: 10px; 106 | } 107 | 108 | .decimal { 109 | font-size: 1.5rem; 110 | } 111 | 112 | .gold .decimal { 113 | text-decoration: underline #d89a2e; 114 | } 115 | 116 | .money .decimal { 117 | text-decoration: underline #049904; 118 | } 119 | 120 | .layout-row .icon { 121 | display: inline-block; 122 | margin-left: 10px; 123 | } 124 | -------------------------------------------------------------------------------- /ui/assets/fonts/rdrlino-regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VORPCORE/vorp_core-lua/7b85ccf81326e6945abd201fe437e56f434b5794/ui/assets/fonts/rdrlino-regular-webfont.woff -------------------------------------------------------------------------------- /ui/assets/icons/gold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VORPCORE/vorp_core-lua/7b85ccf81326e6945abd201fe437e56f434b5794/ui/assets/icons/gold.png -------------------------------------------------------------------------------- /ui/assets/icons/id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VORPCORE/vorp_core-lua/7b85ccf81326e6945abd201fe437e56f434b5794/ui/assets/icons/id.png -------------------------------------------------------------------------------- /ui/assets/icons/lv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VORPCORE/vorp_core-lua/7b85ccf81326e6945abd201fe437e56f434b5794/ui/assets/icons/lv.png -------------------------------------------------------------------------------- /ui/assets/icons/money.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VORPCORE/vorp_core-lua/7b85ccf81326e6945abd201fe437e56f434b5794/ui/assets/icons/money.png -------------------------------------------------------------------------------- /ui/assets/icons/pvpoff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VORPCORE/vorp_core-lua/7b85ccf81326e6945abd201fe437e56f434b5794/ui/assets/icons/pvpoff.png -------------------------------------------------------------------------------- /ui/assets/icons/pvpon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VORPCORE/vorp_core-lua/7b85ccf81326e6945abd201fe437e56f434b5794/ui/assets/icons/pvpon.png -------------------------------------------------------------------------------- /ui/assets/icons/token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VORPCORE/vorp_core-lua/7b85ccf81326e6945abd201fe437e56f434b5794/ui/assets/icons/token.png -------------------------------------------------------------------------------- /ui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 |