diff --git a/ND_Core/config_client.lua b/ND_Core/config_client.lua index f686727..a28f433 100644 --- a/ND_Core/config_client.lua +++ b/ND_Core/config_client.lua @@ -1,9 +1,10 @@ -- For support join my discord: https://discord.gg/Z9Mxu72zZ6 config = { - serverName = "Andy's Development", -- Server name to display on the ui. + serverName = "Andy's Development", characterLimit = 15, changeCharacterCommand = "changecharacter", -- this is the command to open the ui again and change your character. + customPauseMenu = true, -- this will create a custom pause menu. It will display your money, characters name. And server name in the pause menu. -- set your backgrounds, if you have more than 1 then it will randomly change everytime you open the ui. backgrounds = { @@ -12,13 +13,12 @@ config = { "https://i.imgur.com/ZWKfYD9.png" -- Credits: 2XRondo#6374 }, - -- set up the name of your departments and the discord role id for permission. A role id of 0 will allow anyone to choose that department. departments = { - ["CIV"] = {"0"}, - ["SAHP"] = {"0"}, - ["LSPD"] = {"0"}, - ["BCSO"] = {"0"}, - ["LSFD"] = {"0"} + ["CIV"] = {"872921520719142932"}, + ["SAHP"] = {"872921520719142932"}, + ["LSPD"] = {"872921520719142932"}, + ["BCSO"] = {"872921520719142932"}, + ["LSFD"] = {"872921520719142932"} }, -- set up the spawn buttons for each department. @@ -54,51 +54,14 @@ config = { -- Money related enableMoneySystem = true, - legacyMoneyDisplay = false, -- set to tru if you want to use the hud from my standalone money system. maxStartingCash = 2500, maxStartingBank = 8000, payCommand = "pay", -- Command to transfer someone money from bank account. giveCommand = "give", -- Command to give someone close money from wallet. - salaryAmount = 300, -- the daily amount that players will receive. - salaryInterval = 24, -- every x minutes the player will receive the salaryAmount. - - -- Area of Play - enableAopCommand = true, - aopCommand = "setaop", - checkAopCommand = "aop", - defaultAop = "Sandy Shores", - canChangeAOP = { -- Roles that can change the aop. - ["ADMIN"] = "0", - ["STAFF"] = "0" - }, - - -- Prority cooldown - enablePriorityCooldown = true, - enablePriorityDefaultHUD = true, -- this will remove the hud of the priority, if you're using ModernHUD set this to false and go into ModernHUD config and change it to true from there. - startPriorityCommand = "prio-start", - stopPriorityCommand = "prio-stop", - cooldownPriorityCommand = "prio-cd", - joinPriorityCommand = "prio-join", - leavePriorityCommand = "prio-leave", - cooldownAfterPriority = 10, -- This is how long a cooldown will start after a priority is stopped. - canSeePriority = { -- Departments that can see the priority status on their screen. (It's usually just useful for civs) - "CIV" - }, - - -- Dark web - enableDarkweb = true, - canSeeDarkweb = { -- Departments that can see and use the darkweb command. - "CIV" - }, - - -- Hide reticle or default gta money and ammo dispaly. WARNING: turning both to true will add a 0.01 to the resmon. - hideReticle = true, -- hide weapon reticle. - hideAmmoAndMoney = true, -- hides the default gta ammo & money. - customPauseMenu = true, -- this will create a custom pause menu. It will display your money, characters name. And server name in the pause menu. - + -- Discord Rich precence enableRichPrecence = true, - updateIntervall = 10, -- how many seconds delay until it updates status. + updateIntervall = 60, -- how many seconds delay until it updates status. appId = 858146067018416128, largeLogo = "andyyy", smallLogo = "andyyy", @@ -106,4 +69,4 @@ config = { firstButtonLink = "https://discord.gg/Z9Mxu72zZ6", secondButtonName = "TEBEX", secondButtonLink = "https://andyyy.tebex.io/category/fivem-scripts" -} +} \ No newline at end of file diff --git a/ND_Core/config_server.lua b/ND_Core/config_server.lua index 26c0217..76bc617 100644 --- a/ND_Core/config_server.lua +++ b/ND_Core/config_server.lua @@ -1,6 +1,6 @@ -- For support join my discord: https://discord.gg/Z9Mxu72zZ6 server_config = { - DiscordToken = "0", -- discord bot token for permissions - GuildId = "872496972454592523", -- discord guild id -} + discordServerToken = "OTAwODg1MDMxMDQ2Nzc0ODQ1.YXH0kQ.2m4oWEw5hYmqnM4YOGnd4bn2AKI", -- discord bot token for permissions + guildId = "872496972454592523", -- discord guild id +} \ No newline at end of file diff --git a/ND_Core/fxmanifest.lua b/ND_Core/fxmanifest.lua index acf4628..c0d34c1 100644 --- a/ND_Core/fxmanifest.lua +++ b/ND_Core/fxmanifest.lua @@ -1,8 +1,8 @@ -- For support join my discord: https://discord.gg/Z9Mxu72zZ6 author "Andyyy#7666" -description "ND Framework Core" -version "1.4.0" +description "ND-Core" +version "2.0.0" fx_version "cerulean" game "gta5" @@ -10,29 +10,22 @@ lua54 "yes" files { "source/ui/index.html", - "source/ui/js/jquery-3.6.0.min.js", - "source/ui/js/listener.js", - "source/ui/Logo.png", - "source/ui/style.css", + "source/ui/script.js", + "source/ui/style.css" } - ui_page "source/ui/index.html" shared_script "config_client.lua" +client_script "source/client.lua" server_scripts { "config_server.lua", - "source/server/discord.lua", - "source/server/main.lua", - "source/server/commands.lua" -} -client_scripts { - "source/client/main.lua", - "source/client/commands.lua" + "source/server.lua" } exports { - "getCharacterInfo", -- getCharacterInfo(infoType), 1 will return return FirstName, 2 LastName, 3 DateOfBirth, 4 Gender, 5 TwtName, 6 Department, 7 Cash, 8 Bank. 9 will return their character id. + "getCharacterInfo", } + server_exports { "transferBank", -- exports["ND_Core"]:transferBank(amount, player, target) "giveCashToClosestTarget", -- exports["ND_Core"]:giveCashToClosestTarget(amount, player) @@ -40,10 +33,11 @@ server_exports { "depositMoney", -- exports["ND_Core"]:depositMoney(amount, player) "deductMoney", -- exports["ND_Core"]:deductMoney(amount, player, from) "addMoney", -- exports["ND_Core"]:addMoney(amount, player, to) - "getCharacterTable" -- exports["ND_Core"]:getCharacterTable() this will return a table with all the online players and their info. View below on how to use this. } +dependency "oxmysql" + --[[ Keys in the getCharacterTable: @@ -60,4 +54,4 @@ server_exports { Usage: players = exports["ND_Core"]:getCharacterTable() print(players[3].bank) this will print the bank account of the player with id 3. -]] +]] \ No newline at end of file diff --git a/ND_Core/query.sql b/ND_Core/query.sql index f8b999e..99656ad 100644 --- a/ND_Core/query.sql +++ b/ND_Core/query.sql @@ -10,4 +10,4 @@ CREATE TABLE `characters` ( `cash` INT(10) NULL DEFAULT '0', `bank` INT(10) NULL DEFAULT '0', PRIMARY KEY (`character_id`) USING BTREE -); +); \ No newline at end of file diff --git a/ND_Core/source/client.lua b/ND_Core/source/client.lua index db8076f..3f96d4b 100644 --- a/ND_Core/source/client.lua +++ b/ND_Core/source/client.lua @@ -1,58 +1,92 @@ -- For support join my discord: https://discord.gg/Z9Mxu72zZ6 -local background = config.backgrounds[math.random(1, #config.backgrounds)] -local started = true -local priorityText = nil -registered = false -cash = nil -bank = nil +local selectedCharacter +local characterAmount = 0 + +function SetDisplay(bool, typeName, bg) + if not bg then + background = config.backgrounds[math.random(1, #config.backgrounds)] + end + SetNuiFocus(bool, bool) + SendNUIMessage({ + type = typeName, + background = background, + status = bool, + serverName = config.serverName, + characterAmount = characterAmount .. "/" .. config.characterLimit + }) +end + +function getCharacterInfo() + return selectedCharacter +end + +function start(switch) + TriggerServerEvent("checkPerms") + TriggerServerEvent("getCharacters") + TriggerServerEvent("getAop") + Citizen.Wait(100) + if switch then + local ped = PlayerPedId() + SwitchOutPlayer(ped, 0, 1) + FreezeEntityPosition(ped, true) + SetEntityVisible(ped, false, 0) + end + SendNUIMessage({ + type = "onStart", + enableMoneySystem = config.enableMoneySystem, + maxStartingBank = config.maxStartingBank, + maxStartingCash = config.maxStartingCash + }) +end + +AddEventHandler("onResourceStart", function(resourceName) + if (GetCurrentResourceName() ~= resourceName) then + return + end + Citizen.Wait(1000) + start(false) +end) + +AddEventHandler("playerSpawned", function() + print("^0This framework is created by ^5Andyyy#7666 ^0for support you can join the ^5discord: ^0https://discord.gg/Z9Mxu72zZ6") + start(true) +end) -- This is used to add department drop down on the ui. RegisterNetEvent("permsChecked") -AddEventHandler("permsChecked", function(role, rolePermission) - if rolePermission then +AddEventHandler("permsChecked", function(allowedRoles) + for _, dept in pairs(allowedRoles) do SendNUIMessage({ type = "givePerms", - deptRole = role + deptRole = dept }) end end) -RegisterNetEvent("refreshCharacters") -AddEventHandler("refreshCharacters", function() - TriggerServerEvent("getCharacters") +-- Notification when you recieve money. +RegisterNetEvent("receiveBank") +AddEventHandler("receiveBank", function(amount, playerSending, playerId) + BeginTextCommandThefeedPost("STRING") + AddTextComponentSubstringPlayerName("Received $" .. amount .. " from " .. playerSending .. " [".. playerId .."]") + EndTextCommandThefeedPostMessagetext("CHAR_BANK_FLEECA", "CHAR_BANK_FLEECA", true, 9,"FleecaBank", "") end) -Citizen.CreateThread(function() - while started do - Citizen.Wait(200) - local ped = PlayerPedId() - if IsPedOnFoot(ped) or IsPedInVehicle(ped, GetVehiclePedIsIn(ped, false), false) then - print("^0This framework is created by ^5Andyyy#7666 ^0for support you can join the ^5discord: ^0https://discord.gg/Z9Mxu72zZ6") - for departmentName in pairs(config.departments) do -- if you have an error that says attempt to index a nil value (global 'config') it's beacuse you have edited the config wrong. - TriggerServerEvent("checkPerms", departmentName) -- check permissions for each department with the department names. - end - TriggerServerEvent("getCharacters") - Citizen.Wait(100) - TriggerServerEvent("getAop") - SwitchOutPlayer(ped, 0, 1) - FreezeEntityPosition(ped, true) - SetEntityVisible(ped, false, 0) - started = false - SendNUIMessage({ - type = "onStart", - enableMoneySystem = config.enableMoneySystem, - maxStartingBank = config.maxStartingBank, - maxStartingCash = config.maxStartingCash - }) - end - end +-- Notification when you receive cash. +RegisterNetEvent("receiveCash") +AddEventHandler("receiveCash", function(amount, playerSending, playerId) + BeginTextCommandThefeedPost("STRING") + AddTextComponentSubstringPlayerName(playerSending .. " gave you $" .. amount .. ".") + EndTextCommandThefeedPostMessagetext("CHAR_DEFAULT", "CHAR_DEFAULT", true, 9, playerSending .. " [".. playerId .."]", "") end) -RegisterNUICallback("exitGame", function(data) - TriggerServerEvent("exitGame") +RegisterNetEvent("updateMoney") +AddEventHandler("updateMoney", function(cash, bank) + selectedCharacter.cash = cash + selectedCharacter.bank = bank end) +-- Gets all the characters and displays them on the ui. RegisterNetEvent("returnCharacters") AddEventHandler("returnCharacters", function(characters) characterAmount = 0 @@ -77,59 +111,21 @@ AddEventHandler("returnCharacters", function(characters) SetDisplay(true, "ui", background) end) --- Creating a character -RegisterNUICallback("newCharacter", function(data) - if characterAmount < config.characterLimit then - newCharacter = { - firstName = data.firstName, - lastName = data.lastName, - dateOfBirth = data.dateOfBirth, - gender = data.gender, - twtName = data.twtName, - department = data.department, - startingCash = data.startingCash, - startingBank = data.startingBank - } - TriggerServerEvent("newCharacter", newCharacter) - end -end) - --- editing a character -RegisterNUICallback("editCharacter", function(data) - newCharacter = { +-- Selecting a player from the iu. +RegisterNUICallback("setMainCharacter", function(data) + selectedCharacter = { firstName = data.firstName, lastName = data.lastName, - dateOfBirth = data.dateOfBirth, + dob = data.dateOfBirth, gender = data.gender, - twtName = data.twtName, + twt = data.twtName, department = data.department, - id = data.id + cash = data.startingCash, + bank = data.startingBank, + id = data.character } - TriggerServerEvent("editCharacter", newCharacter) -end) --- deleting a character -RegisterNUICallback("delCharacter", function(data) - TriggerServerEvent("delCharacter", data.character) - characterAmount = characterAmount -1 - SendNUIMessage({ - characterAmount = characterAmount .. "/" .. config.characterLimit - }) -end) - --- Once the player clicks on the character in the ui, it will be set as the main character or the current character. This info can be used later in exports or elsewhere in this resource. -RegisterNUICallback("setMainCharacter", function(data) - mainFirstName = data.firstName - mainLastName = data.lastName - mainDateOfBirth = data.dateOfBirth - mainGender = data.gender - mainTwtName = data.twtName - mainDepartment = data.department - mainStartingCash = data.startingCash - mainStartingBank = data.startingBank - mainCharaterId = data.character - - for _, spawn in pairs(config.spawns[mainDepartment]) do + for _, spawn in pairs(config.spawns[selectedCharacter.department]) do SendNUIMessage({ type = "setSpawns", x = spawn.x, @@ -139,74 +135,54 @@ RegisterNUICallback("setMainCharacter", function(data) }) end - TriggerServerEvent("characterOnline", mainCharaterId) - TriggerServerEvent("getPriority") - registered = true + TriggerServerEvent("characterOnline", selectedCharacter.id) + TriggerEvent("characterChanged", selectedCharacter) end) -if config.enableMoneySystem then - -- This will display the money that the player has. - RegisterNetEvent("returnMoney") - AddEventHandler("returnMoney", function(newCash, newBank) - while not registered do - Citizen.Wait(10) - end - cash = tostring(newCash) - bank = tostring(newBank) - if config.legacyMoneyDisplay then - if registered then - while true do - Citizen.Wait(0) - text("💵", 0.885, 0.028, 0.35, 7) - text("💳", 0.885, 0.068, 0.35, 7) - text("~g~$~w~".. cash, 0.91, 0.03, 0.55, 7) - text("~b~$~w~".. bank, 0.91, 0.07, 0.55, 7) - end - end - else - SendNUIMessage({ - type = "Money", - cash = "Cash: $" .. cash, - bank = "Bank: $" .. bank - }) - end - end) +-- Creating a character from the ui. +RegisterNUICallback("newCharacter", function(data) + if characterAmount < config.characterLimit then + TriggerServerEvent("newCharacter", { + firstName = data.firstName, + lastName = data.lastName, + dateOfBirth = data.dateOfBirth, + gender = data.gender, + twtName = data.twtName, + department = data.department, + startingCash = data.startingCash, + startingBank = data.startingBank + }) + end +end) - -- This is to update the players money on the ui. - RegisterNetEvent("updateMoney") - AddEventHandler("updateMoney", function() - TriggerServerEvent("getMoney", mainCharaterId) - end) +-- editing a character from the ui. +RegisterNUICallback("editCharacter", function(data) + TriggerServerEvent("editCharacter", { + firstName = data.firstName, + lastName = data.lastName, + dateOfBirth = data.dateOfBirth, + gender = data.gender, + twtName = data.twtName, + department = data.department, + id = data.id + }) +end) - -- Notification when you recieve money. - RegisterNetEvent("receiveBank") - AddEventHandler("receiveBank", function(amount, playerSending, playerId) - BeginTextCommandThefeedPost("STRING") - AddTextComponentSubstringPlayerName("Received $" .. amount .. " from " .. playerSending .. " [".. playerId .."]") - EndTextCommandThefeedPostMessagetext("CHAR_BANK_FLEECA", "CHAR_BANK_FLEECA", true, 9,"FleecaBank", "") - end) +-- deleting a character from the ui. +RegisterNUICallback("delCharacter", function(data) + TriggerServerEvent("delCharacter", data.character) + characterAmount = characterAmount -1 + SendNUIMessage({ + characterAmount = characterAmount .. "/" .. config.characterLimit + }) +end) - -- Notification when you receive cash. - RegisterNetEvent("receiveCash") - AddEventHandler("receiveCash", function(amount, playerSending, playerId) - BeginTextCommandThefeedPost("STRING") - AddTextComponentSubstringPlayerName(playerSending .. " gave you $" .. amount .. ".") - EndTextCommandThefeedPostMessagetext("CHAR_DEFAULT", "CHAR_DEFAULT", true, 9, playerSending .. " [".. playerId .."]", "") - end) +-- Quit button from ui. +RegisterNUICallback("exitGame", function(data) + TriggerServerEvent("exitGame") +end) - -- Notification when receiving salary. - RegisterNetEvent("receiveSalary") - AddEventHandler("receiveSalary", function(amount) - if registered then - BeginTextCommandThefeedPost("STRING") - AddTextComponentSubstringPlayerName("Daily Salary + $" .. config.salaryAmount) - EndTextCommandThefeedPostMessagetext("CHAR_BANK_FLEECA", "CHAR_BANK_FLEECA", true, 9,"FleecaBank", "") - TriggerServerEvent("getMoney", mainCharaterId) - end - end) -end - --- Teleporting +-- Teleporting using ui. RegisterNUICallback("tpToLocation", function(data) local ped = PlayerPedId() FreezeEntityPosition(ped, false) @@ -218,7 +194,7 @@ RegisterNUICallback("tpToLocation", function(data) Citizen.Wait(500) FreezeEntityPosition(ped, false) SetEntityVisible(ped, true, 0) - TriggerServerEvent("getMoney", mainCharaterId) + TriggerServerEvent("getMoney", selectedCharacter.id) end) -- Choosing the do not tp button. @@ -230,128 +206,61 @@ RegisterNUICallback("tpDoNot", function() Citizen.Wait(500) SetEntityVisible(ped, true, 0) FreezeEntityPosition(ped, false) - TriggerServerEvent("getMoney", mainCharaterId) + TriggerServerEvent("getMoney", selectedCharacter.id) end) -function SetDisplay(bool, typeName, bg) - if not bg then - background = config.backgrounds[math.random(1, #config.backgrounds)] - end - SetNuiFocus(bool, bool) - SendNUIMessage({ - type = typeName, - background = background, - status = bool, - serverName = config.serverName, - characterAmount = characterAmount .. "/" .. config.characterLimit - }) -end - +-- discord rich precense will show on a users profile. if config.enableRichPrecence then Citizen.CreateThread(function() while true do - Citizen.Wait(config.updateIntervall * 1000) SetDiscordAppId(config.appId) - if registered then - SetRichPresence(" Playing : " .. config.serverName .. " as " .. mainFirstName .. " " .. mainLastName) + if selectedCharacter then + SetRichPresence(" Playing : " .. config.serverName .. " as " .. selectedCharacter.firstName .. " " .. selectedCharacter.lastName) SetDiscordRichPresenceAsset(config.largeLogo) SetDiscordRichPresenceAssetText("Playing: " .. config.serverName) SetDiscordRichPresenceAssetSmall(config.smallLogo) - SetDiscordRichPresenceAssetSmallText("Playing as: " .. mainFirstName .. " " .. mainLastName) + SetDiscordRichPresenceAssetSmallText("Playing as: " .. selectedCharacter.firstName .. " " .. selectedCharacter.lastName) SetDiscordRichPresenceAction(0, config.firstButtonName, config.firstButtonLink) SetDiscordRichPresenceAction(1, config.secondButtonName, config.secondButtonLink) end + Citizen.Wait(config.updateIntervall * 1000) end end) end -if config.enablePriorityCooldown then - TriggerEvent("chat:addSuggestion", "/" .. config.startPriorityCommand, "Start a priority.") - TriggerEvent("chat:addSuggestion", "/" .. config.stopPriorityCommand, "Stop an active priority.") - TriggerEvent("chat:addSuggestion", "/" .. config.cooldownPriorityCommand, "Start a cooldown on priorities.", { - {name="Time", help="Time in minutes to start a cooldown"} - }) - - RegisterNetEvent("returnPriority") - AddEventHandler("returnPriority", function(priority) - priorityText = nil - for _, departmentName in pairs(config.canSeePriority) do - if departmentName == mainDepartment then - priorityText = priority - break - end - end - end) -end - -if config.hideAmmoAndMoney or config.hideReticle or config.customPauseMenu or config.enablePriorityCooldown then +-- show server name, first name, last name, and the amount of money the character has in the pause menu. +if config.customPauseMenu then Citizen.CreateThread(function() while true do Citizen.Wait(0) - if config.hideAmmoAndMoney then - HideHudComponentThisFrame(3) -- CASH - HideHudComponentThisFrame(4) -- MP_CASH - HideHudComponentThisFrame(13) -- CASH_CHANGE - HideHudComponentThisFrame(2) -- WEAPON_ICON - end - if config.hideReticle then - HideHudComponentThisFrame(14) -- RETICLE - end - if config.customPauseMenu and registered then + if selectedCharacter then if IsPauseMenuActive() then BeginScaleformMovieMethodOnFrontendHeader("SET_HEADING_DETAILS") AddTextEntry("FE_THDR_GTAO", config.serverName) - ScaleformMovieMethodAddParamPlayerNameString(mainFirstName .. " " .. mainLastName) - if registered and config.enableMoneySystem then - PushScaleformMovieFunctionParameterString("Cash: $" .. cash) - PushScaleformMovieFunctionParameterString("Bank: $" .. bank) + ScaleformMovieMethodAddParamPlayerNameString(selectedCharacter.firstName .. " " .. selectedCharacter.lastName) + if config.enableMoneySystem then + PushScaleformMovieFunctionParameterString("Cash: $" .. tostring(selectedCharacter.cash)) + PushScaleformMovieFunctionParameterString("Bank: $" .. tostring(selectedCharacter.bank)) end EndScaleformMovieMethod() end end - if config.enablePriorityCooldown and priorityText and config.enablePriorityDefaultHUD then - text(priorityText, 0.182, 0.891, 0.4, 4) - end end end) end --- Notification above the map. -function notify(message) - BeginTextCommandThefeedPost("STRING") - AddTextComponentSubstringPlayerName(message) - EndTextCommandThefeedPostTicker(0,1) -end +-- Change character command +RegisterCommand(config.changeCharacterCommand, function() + SwitchOutPlayer(PlayerPedId(), 0, 1) + Citizen.Wait(2000) + FreezeEntityPosition(ped, true) + SetEntityVisible(ped, false, 0) + SetDisplay(true, "ui") +end, false) -function getCharacterInfo(infoType) - if registered then - mainCharacter = { - mainFirstName, - mainLastName, - mainDateOfBirth, - mainGender, - mainTwtName, - mainDepartment, - cash, - bank, - mainCharaterId, - priorityText - } - return mainCharacter[infoType] - else - return "Error: Player not registered" - end -end - -function text(text, x, y, scale, font) - SetTextFont(font) - SetTextProportional(0) - SetTextScale(scale, scale) - SetTextEdge(1, 0, 0, 0, 255) - SetTextDropShadow(0, 0, 0, 0,255) - SetTextOutline() - SetTextJustification(1) - SetTextEntry("STRING") - AddTextComponentString(text) - DrawText(x, y) -end +-- chat suggestions +TriggerEvent("chat:addSuggestion", "/" .. config.changeCharacterCommand, "Switch your framework character.") +if config.enableMoneySystem then + TriggerEvent("chat:addSuggestion", "/" .. config.payCommand, "Transfer money to player", {{name="id", help="Player server id" }, {name="amount", help="amount to pay"}}) + TriggerEvent("chat:addSuggestion", "/" .. config.giveCommand, "Give money to closeby player", {{name="amount", help="amount to give"}}) +end \ No newline at end of file diff --git a/ND_Core/source/server.lua b/ND_Core/source/server.lua index a77ea7c..7d44b83 100644 --- a/ND_Core/source/server.lua +++ b/ND_Core/source/server.lua @@ -10,23 +10,26 @@ if resource ~= expectedName then end -- check if resource version is up to date -PerformHttpRequest("https://raw.githubusercontent.com/Andyyy7666/ND_Framework/main/ND_Core/fxmanifest.lua", function(error, res, head) - i, j = string.find(tostring(res), "version") - res = string.sub(tostring(res), i, j + 6) - res = string.gsub(res, "version ", "") - res = string.gsub(res, '"', "") - resp = tonumber(res) - verFile = GetResourceMetadata(expectedName, "version", 0) - - if verFile then - if tonumber(verFile) < resp then +PerformHttpRequest("https://raw.githubusercontent.com/Andyyy7666/ND_Framework/main/ND_Core/fxmanifest.lua", function(errorCode, resultData, resultHeaders) + i, j = string.find(tostring(resultData), "version") + resultData = string.sub(tostring(resultData), i, j + 12) + resultData = string.gsub(resultData, "version \"", "") + i, j = string.find(resultData, "\"") + resultData = string.sub(resultData, 1, i - 1) + local githubVersion = string.gsub(resultData, "%.", "") + local fileVersion = string.gsub(GetResourceMetadata(expectedName, "version", 0), "%.", "") + githubVersion = tonumber(githubVersion) + fileVersion = tonumber(fileVersion) + + if githubVersion and fileVersion then + if githubVersion > fileVersion then print("^1[^4" .. expectedName .. "^1] WARNING^0") - print("^4" .. expectedName .. " ^0is outdated. Please update it from ^5https://github.com/Andyyy7666/ND_Framework ^0| Current Version: ^1" .. verFile .. " ^0| New Version: ^2" .. resp .. " ^0|") - elseif tonumber(verFile) > tonumber(resp) then + print("^4" .. expectedName .. " ^0is outdated. Please update it from ^5https://github.com/Andyyy7666/ND_Framework ^0| Current Version: ^1" .. fileVersion .. " ^0| New Version: ^2" .. githubVersion .. " ^0|") + elseif githubVersion < fileVersion then print("^1[^4" .. expectedName .. "^1] WARNING^0") - print("^4" .. expectedName .. "s ^0version number is higher than we expected. | Current Version: ^3" .. verFile .. " ^0| Expected Version: ^2" .. resp .. " ^0|") + print("^4" .. expectedName .. " ^0version number is higher than expected | Current Version: ^3" .. fileVersion .. " ^0| Expected Version: ^2" .. githubVersion .. " ^0|") else - print("^4" .. expectedName .. " ^0is up to date | Current Version: ^2" .. verFile .. " ^0|") + print("^4" .. expectedName .. " ^0is up to date | Current Version: ^2" .. fileVersion .. " ^0|") end else print("^1[^4" .. expectedName .. "^1] WARNING^0") @@ -34,27 +37,43 @@ PerformHttpRequest("https://raw.githubusercontent.com/Andyyy7666/ND_Framework/ma end end) --- onlinePlayers table. -onlinePlayers = {} - --- Get player identifier function (This will not change the identifier all the time) -function GetPlayerIdentifierFromType(type, source) -- Credits: xander1998, Post: https://forum.cfx.re/t/solved-is-there-a-better-way-to-get-lic-steam-and-ip-than-getplayeridentifiers/236243/2?u=andyyy7666 - local identifiers = {} - local identifierCount = GetNumPlayerIdentifiers(source) - - for a = 0, identifierCount do - table.insert(identifiers, GetPlayerIdentifier(source, a)) - end - - for b = 1, #identifiers do - if string.find(identifiers[b], type, 1) then - return identifiers[b] - end - end - return nil +-- Used to retrive the players discord server nickname, discord name and tag, and the roles. +function getUserDiscordInfo(discordUserId) + local data + PerformHttpRequest("https://discordapp.com/api/guilds/" .. server_config.guildId .. "/members/" .. discordUserId, function(errorCode, resultData, resultHeaders) + if errorCode ~= 200 then + return + end + local result = json.decode(resultData) + local roles = {} + for _, roleId in pairs(result.roles) do + roles[roleId] = roleId + end + data = { + nickname = result.nick, + discordTag = tostring(result.user.username) .. "#" .. tostring(result.user.discriminator), + roles = roles + } + end, "GET", "", {["Content-Type"] = "application/json", ["Authorization"] = "Bot " .. server_config.discordServerToken}) + while not data do + Citizen.Wait(0) + end + return data end -function validateMoney(cash, bank) +-- Get player any identifier, available types: steam, license, xbl, ip, discord, live. +function GetPlayerIdentifierFromType(type, source) + local identifierCount = GetNumPlayerIdentifiers(source) + for count = 0, identifierCount do + local identifier = GetPlayerIdentifier(source, count) + if identifier and string.find(identifier, type) then + return identifier + end + end + return nil +end + +function validateMoney(cash, bank) if tonumber(cash) > config.maxStartingCash or tonumber(bank) > config.maxStartingBank then return false end @@ -62,12 +81,13 @@ function validateMoney(cash, bank) end function validateDepartment(player, department) - local rolePermission = false local departmentExists = config.departments[department] if departmentExists then - for i = 1, #departmentExists do - rolePermission = IsRolePresent(player, department, departmentExists[i], "start") - if rolePermission then + local discordUserId = string.gsub(GetPlayerIdentifierFromType("discord", player), "discord:", "") + local roles = getUserDiscordInfo(discordUserId).roles + + for _, roleId in pairs(departmentExists) do + if roles[roleId] or roleId == 0 then return true end end @@ -75,25 +95,22 @@ function validateDepartment(player, department) return false end --- Using the IsRolePresent function from discord.lua to check if the player has the roles. RegisterNetEvent("checkPerms") -AddEventHandler("checkPerms", function(role) +AddEventHandler("checkPerms", function() local player = source - local rolePermission = false - for i = 1, #config.departments[role] do - rolePermission = IsRolePresent(player, role, config.departments[role][i], "start") - if rolePermission then - break + local discordUserId = string.gsub(GetPlayerIdentifierFromType("discord", player), "discord:", "") + local allowedRoles = {} + local roles = getUserDiscordInfo(discordUserId).roles + + for dept, roleTable in pairs(config.departments) do + for _, roleId in pairs(roleTable) do + if roles[roleId] or roleId == 0 then + table.insert(allowedRoles, dept) + end end end - TriggerClientEvent("permsChecked", player, role, rolePermission) -end) --- Disconnecting a player -RegisterNetEvent("exitGame") -AddEventHandler("exitGame", function() - local player = source - DropPlayer(player, "Disconnected using framework.") + TriggerClientEvent("permsChecked", player, allowedRoles) end) -- Inserting the players characters into characters table @@ -124,7 +141,7 @@ AddEventHandler("newCharacter", function(newCharacter) local startingCash = newCharacter.startingCash local startingBank = newCharacter.startingBank - print(startingCash) + if config.enableMoneySystem then -- Don't trust the client, validate maximum amounts. local moneyCheck = validateMoney(startingCash, startingBank) @@ -177,51 +194,8 @@ AddEventHandler("editCharacter", function(newCharacter) exports.oxmysql:query("UPDATE characters SET first_name = ?, last_name = ?, dob = ?, gender = ?, twt = ?, department = ? WHERE license = ? AND character_id = ?", {newCharacter.firstName, newCharacter.lastName, newCharacter.dateOfBirth, newCharacter.gender, newCharacter.twtName, newCharacter.department, GetPlayerIdentifierFromType("license", player), newCharacter.id}) end) -if config.enableMoneySystem then - -- This is used to find out how much money the player has and use it in the client to show it on the ui. - RegisterNetEvent("getMoney") - AddEventHandler("getMoney", function(characterid) - local player = source - local license = GetPlayerIdentifierFromType("license", player) - exports.oxmysql:query("SELECT cash, bank FROM characters WHERE license = ? AND character_id = ?", {license, characterid}, function(result) - if result then - local cash = result[1].cash - local bank = result[1].bank - onlinePlayers[player].cash = cash - onlinePlayers[player].bank = bank - TriggerClientEvent("returnMoney", player, cash, bank) - end - end) - end) - - -- paying command. - RegisterCommand(config.payCommand, function(source, args, raw) - local player = source - local target = tonumber(args[1]) - local amount = tonumber(args[2]) - transferBank(amount, player, target) - end) - - -- Give money command. - RegisterCommand(config.giveCommand, function(source, args, raw) - local player = source - local amount = tonumber(args[1]) - giveCashToClosestTarget(amount, player) - end) - - -- Salary. - local salaryInterval = config.salaryInterval * 60000 - Citizen.CreateThread(function() - while true do - Citizen.Wait(salaryInterval) - for playerid, playerinfo in pairs(onlinePlayers) do - local license = GetPlayerIdentifierFromType("license", playerid) - exports.oxmysql:query("UPDATE characters SET bank = bank + ? WHERE license = ? AND character_id = ?", {config.salaryAmount, license, playerinfo.characterId}) - TriggerClientEvent("receiveSalary", playerid, config.salaryAmount) - end - end - end) -end +-- onlinePlayers table, this is used to store all the players current character info on the server. +onlinePlayers = {} -- add a player to the table. RegisterNetEvent("characterOnline") @@ -252,111 +226,174 @@ AddEventHandler("playerDropped", function(reason) onlinePlayers[player] = nil end) +-- Disconnecting a player +RegisterNetEvent("exitGame") +AddEventHandler("exitGame", function() + local player = source + DropPlayer(player, "Disconnected using framework.") +end) + +-- this is for the exports function getCharacterTable() return onlinePlayers end -function transferBank(amount, player, target) - exports.oxmysql:query("SELECT bank FROM characters WHERE license = ? AND character_id = ?", {GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}, function(result) +function updateMoney(player) + local player = tonumber(player) + local license = GetPlayerIdentifierFromType("license", player) + exports.oxmysql:query("SELECT cash, bank FROM characters WHERE license = ? AND character_id = ?", {license, onlinePlayers[player].characterId}, function(result) if result then - if player == target then - TriggerClientEvent("chat:addMessage", player, { - color = {255, 0, 0}, - args = {"Error", "You can't send money to yourself."} - }) - elseif GetPlayerPing(target) == 0 then - TriggerClientEvent("chat:addMessage", player, { - color = {255, 0, 0}, - args = {"Error", "That player does not exist."} - }) - elseif result[1].bank < amount then - TriggerClientEvent("chat:addMessage", player, { - color = {255, 0, 0}, - args = {"Error", "You don't have enough money."} - }) - else - exports.oxmysql:query("UPDATE characters SET bank = bank - ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) - TriggerClientEvent("updateMoney", player) - exports.oxmysql:query("UPDATE characters SET bank = bank + ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", target), onlinePlayers[target].characterId}) - TriggerClientEvent("updateMoney", target) - - TriggerClientEvent("chat:addMessage", player, { - color = {0, 255, 0}, - args = {"Success", "You paid " .. onlinePlayers[target].firstName .. " " .. onlinePlayers[target].lastName .. " $" .. amount .. "."} - }) - TriggerClientEvent("receiveBank", target, amount, onlinePlayers[player].firstName .. " " .. onlinePlayers[player].lastName, player) - end + local cash = result[1].cash + local bank = result[1].bank + onlinePlayers[player].cash = cash + onlinePlayers[player].bank = bank + TriggerClientEvent("updateMoney", player, cash, bank) end end) end +function transferBank(amount, player, target) + local amount = tonumber(amount) + local player = tonumber(player) + local target = tonumber(target) + if player == target then + TriggerClientEvent("chat:addMessage", player, { + color = {255, 0, 0}, + args = {"Error", "You can't send money to yourself."} + }) + return false + elseif GetPlayerPing(target) == 0 then + TriggerClientEvent("chat:addMessage", player, { + color = {255, 0, 0}, + args = {"Error", "That player does not exist."} + }) + return false + elseif onlinePlayers[player].bank < amount then + TriggerClientEvent("chat:addMessage", player, { + color = {255, 0, 0}, + args = {"Error", "You don't have enough money."} + }) + return false + else + exports.oxmysql:query("UPDATE characters SET bank = bank - ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) + updateMoney(player) + exports.oxmysql:query("UPDATE characters SET bank = bank + ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", target), onlinePlayers[target].characterId}) + updateMoney(target) + + TriggerClientEvent("chat:addMessage", player, { + color = {0, 255, 0}, + args = {"Success", "You paid " .. onlinePlayers[target].firstName .. " " .. onlinePlayers[target].lastName .. " $" .. amount .. "."} + }) + TriggerClientEvent("receiveBank", target, amount, onlinePlayers[player].firstName .. " " .. onlinePlayers[player].lastName, player) + return true + end +end + function giveCashToClosestTarget(amount, player) - exports.oxmysql:query("SELECT cash FROM characters WHERE license = ? AND character_id = ?", {GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}, function(result) - if result then - local playerFound = false - local playerCoords = GetEntityCoords(GetPlayerPed(player)) - if result[1].cash < amount then + local amount = tonumber(amount) + local player = tonumber(player) + local playerFound = false + local playerCoords = GetEntityCoords(GetPlayerPed(player)) + if onlinePlayers[player].cash < amount then + TriggerClientEvent("chat:addMessage", player, { + color = {255, 0, 0}, + args = {"Error", "You don't have enough money."} + }) + return false + else + for targetId, targetInfo in pairs(onlinePlayers) do + local targetCoords = GetEntityCoords(GetPlayerPed(targetId)) + if (#(playerCoords - targetCoords) < 2.0) and (targetId ~= player) and not playerFound then + exports.oxmysql:query("UPDATE characters SET cash = cash - ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) + updateMoney(player) + exports.oxmysql:query("UPDATE characters SET cash = cash + ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", targetId), tonumber(targetInfo.characterId)}) + updateMoney(targetId) + playerFound = true TriggerClientEvent("chat:addMessage", player, { - color = {255, 0, 0}, - args = {"Error", "You don't have enough money."} + color = {0, 255, 0}, + args = {"Success", "You gave " .. onlinePlayers[targetId].firstName .. " " .. onlinePlayers[targetId].lastName .. " $" .. amount .. "."} }) - else - for k, v in pairs(onlinePlayers) do - local targetCoords = GetEntityCoords(GetPlayerPed(k)) - if (#(playerCoords - targetCoords) < 2.0) and (k ~= player) and not playerFound then - exports.oxmysql:query("UPDATE characters SET cash = cash - ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) - TriggerClientEvent("updateMoney", player) - exports.oxmysql:query("UPDATE characters SET cash = cash + ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", k), tonumber(v.characterId)}) - TriggerClientEvent("updateMoney", k) - playerFound = true - TriggerClientEvent("chat:addMessage", player, { - color = {0, 255, 0}, - args = {"Success", "You gave " .. onlinePlayers[k].firstName .. " " .. onlinePlayers[k].lastName .. " $" .. amount .. "."} - }) - TriggerClientEvent("receiveCash", k, amount, onlinePlayers[player].firstName .. " " .. onlinePlayers[player].lastName, player) - break - end - end - if not playerFound then - TriggerClientEvent("chat:addMessage", player, { - color = {255, 0, 0}, - args = {"Error", "No players nearby."} - }) - end - playerFound = false - end + TriggerClientEvent("receiveCash", targetId, amount, onlinePlayers[player].firstName .. " " .. onlinePlayers[player].lastName, player) + break + end end - end) + if not playerFound then + TriggerClientEvent("chat:addMessage", player, { + color = {255, 0, 0}, + args = {"Error", "No players nearby."} + }) + return false + end + playerFound = false + return true + end end function withdrawMoney(amount, player) - exports.oxmysql:query("UPDATE characters SET bank = bank - ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) - exports.oxmysql:query("UPDATE characters SET cash = cash + ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) - TriggerClientEvent("updateMoney", player) + local amount = tonumber(amount) + local player = tonumber(player) + if onlinePlayers[player].bank >= amount then + exports.oxmysql:query("UPDATE characters SET bank = bank - ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) + exports.oxmysql:query("UPDATE characters SET cash = cash + ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) + Citizen.Wait(500) + updateMoney(player) + return true + end + return false end function depositMoney(amount, player) - exports.oxmysql:query("UPDATE characters SET cash = cash - ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) - exports.oxmysql:query("UPDATE characters SET bank = bank + ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) - TriggerClientEvent("updateMoney", player) + local amount = tonumber(amount) + local player = tonumber(player) + if onlinePlayers[player].cash >= amount then + exports.oxmysql:query("UPDATE characters SET cash = cash - ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) + exports.oxmysql:query("UPDATE characters SET bank = bank + ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) + Citizen.Wait(500) + updateMoney(player) + return true + end + return false end function deductMoney(amount, player, from) + local amount = tonumber(amount) + local player = tonumber(player) if from == "bank" then exports.oxmysql:query("UPDATE characters SET bank = bank - ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) - TriggerClientEvent("updateMoney", player) + Citizen.Wait(500) + updateMoney(player) elseif from == "cash" then exports.oxmysql:query("UPDATE characters SET cash = cash - ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) - TriggerClientEvent("updateMoney", player) + Citizen.Wait(500) + updateMoney(player) end end function addMoney(amount, player, to) + local amount = tonumber(amount) + local player = tonumber(player) if to == "bank" then exports.oxmysql:query("UPDATE characters SET bank = bank + ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) - TriggerClientEvent("updateMoney", player) + Citizen.Wait(500) + updateMoney(player) elseif to == "cash" then exports.oxmysql:query("UPDATE characters SET cash = cash + ? WHERE license = ? AND character_id = ?", {amount, GetPlayerIdentifierFromType("license", player), onlinePlayers[player].characterId}) - TriggerClientEvent("updateMoney", player) + Citizen.Wait(500) + updateMoney(player) end end + +-- paying command. +RegisterCommand(config.payCommand, function(source, args, raw) + local player = source + local target = tonumber(args[1]) + local amount = math.floor(tonumber(args[2])) + transferBank(amount, player, target) +end) + +-- Give money command. +RegisterCommand(config.giveCommand, function(source, args, raw) + local player = source + local amount = math.floor(tonumber(args[1])) + giveCashToClosestTarget(amount, player) +end) \ No newline at end of file diff --git a/ND_Core/source/ui/index.html b/ND_Core/source/ui/index.html index 5189486..4f09eab 100644 --- a/ND_Core/source/ui/index.html +++ b/ND_Core/source/ui/index.html @@ -4,42 +4,14 @@ - - + +
- -
+