5 Commits

Author SHA1 Message Date
0111ff3b6e character creation CLIENT/SERVER 2025-11-15 00:20:57 +01:00
be881f79b2 Disabled WANTED, Enable PVP 2025-11-13 02:58:19 +01:00
5653247e3b NEW: CALL GB.NEW: CALLBACKS
NEW: FUNCTIONS
NEW: EVENTS
NEW: SQL
NEW: ADMIN
NEW: COMMANDS
NEW: GROUPS
2025-11-13 02:47:59 +01:00
4dd4da3482 NEW: 'CALL GB."
NEW: 'KEYS'
NEW: 'ADMIN [BASIC]'
NEW: 'CALLBACKS'
NEW: 'OTHER
2025-11-13 02:15:28 +01:00
d288c43ef7 NEW: Core Setup 2025-11-13 01:53:27 +01:00
10 changed files with 625 additions and 0 deletions

136
character/cl_character.lua Normal file
View File

@@ -0,0 +1,136 @@
local selectedCharacter = false
local camera = nil
local camera2 = nil
local bannedNames = {}
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
if NetworkIsSessionStarted() then
TriggerServerEvent('gb-core:character:joined')
TriggerEvent('gb-core:character:startCamera')
TriggerEvent('gb-core:client:closeCharacterUI')
TriggerEvent('gb-core:playerLogin')
selectedCharacter(true)
return
end
end
end)
RegisterNetEvent('gb-core:character:selecting')
AddEventHandler('gb-core:character:selecting', function()
selectedCharacter(true)
end)
getCID = function(source, cb)
local src = source
TriggerServerEvent('gb-core:getID', src)
end
RegisterNUICallback('createCharacter', function(data)
local characterData = data.CharacterData
for theData, value in pairs(characterData) do
if theData == 'firstname' or theData == 'lastname' then
reason = verifyName(value)
print(reason) -- Make sure this prints out correctly (comment // or remove later.)
if reason ~= '' then
break
end
end
end
if reason == '' then
TriggerServerEvent('gb-core:server:createCharacter', characterData)
end
end)
function verifyName(name)
for k, v in ipairs(bannedNames) do
if name == v then
local reason = 'Trying to use an inappropriate name. Please think about your decisions.'
TriggerServerEvent('gb-admin:disconnect', reason)
end
end
local nameLength = string.len(name)
if nameLength > 25 or nameLength < 2 then
local reason = 'Name too short.'
end
let count = 0
for i in name:gmatch("[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-]") do
count = count + 1
end
if count ~= nameLength then
return "Your player name contains special characters. (a-z,A-Z add -)"
end
local spacesInName = 0
local spacesWithUpper = 0
for word in string.gmatch(name, "%S+") do
if string.match(word, "%u") then
spacesWithUpper = spacesWithUpper + 1
end
spacesInName = spacesInName + 1
end
if spacesInName > 1 then
return "Name contains more then 1 space."
end
if spacesWithUpper ~= spacesInName then
return "Name must start with a capital letter."
end
return ""
end
RegisterNUICallback('deleteCharacter', function(data)
local characterData = data
TriggerServerEvent('gb-core:deleteCharacter', characterData)
end)
RegisterNetEvent('gb-core:character:setupCharacter')
AddEventHandler('gb-core:character:setupCharacter', fuction(data)
GB.Functions.TriggerServerCallback('gb-core:getCharacter', function(data)
SendNUIMessage({type = 'setupCharacters', characters = data})
end)
end)
RegisterNUICallback('selectCharacters', function(data)
local cid = tonumber(data.cid)
selectedCharacter(false)
TriggerServerEvent('gb-core:character:serverSelect', cid)
TriggerEvent('gb-core:openMenu')
SetTimecycleModifier('default')
SetCamActive(camera, false)
DestroyCam(camera, false)
end)
RegisterNUICallback('closeCharacter', function(data)
selectedCharacter(false)
end)
function selectedCharacter(value)
SetNuiFocus(value, value)
SendNUIMessage({
type = 'characterSelect',
status = value
})
selectingCharacter = false
end
RegisterNetEvent('gb-core:character:startCamera')
AddEventHandler('gb-core:character:startCamera', function()
DoScreenFadeIn(10)
SetTimecycleModifier('hud_def_blur')
SetTimecycleModifierStrength(1.0)
FreezeEntityPosition(GetPlayerPed(-1), true)
cam = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", -358.56, -981.96, 286.25, 320.00, 0.00, -50.00, 90.00, false, 0)
SetCamActive(camera, true)
RenderScriptCams(true, false, 1, true, true)
end)

View File

View File

@@ -0,0 +1,81 @@
RegisterNetEvent('gb-core:character:join')
AddEventHandler('gb-core:character:join', function()
local src = source
local id
for k, v in ipairs(GetPlayerIdentifier(src)) do
if string.sub(v, 1, string.len('discord:')) == 'discord:' then
id=v
break
end
end
if not id then
DropPlayer(src, 'Identifier not found, Make sure discord is running and your are in the server.')
else
TriggerClientEvent('gb-core:character:setupCharacters', src)
end
end)
RegisterNetEvent('gb-core:character:serverSelect')
AddEventHandler('gb-core:character:serverSelect', function(cid) -- CID is for character slot from UI
local src = source
local identifier = GetPlayerIdentifierByType(src, "discord") -- Get's discord id
local license = GetPlayerIdentifierByType(src, "fivem") -- Get's fivem license
GB.DB.LoadCharacter(src, license, identifier, cid) -- ensure we get the correct player
end)
GB.Functions.RegisterServerCallback('gb-core:getCharacter', function(source, cb) -- Send back every created character (by said person)
local id = GetPlayerIdentifierByType(src, "discord") -- Get's discord id
exports['ghmattimysql']:execute('SELECT * FROM players WHERE identifier = @identifier', {['@identifier'] = id}, function(result)
if result then
cb(result)
end
end)
end)
RegisterNetEvent('gb-core:deleteCharacter')
AddEventHandler('gb-core:deleteCharacter', function(characterData)
local cid = characterData.cid -- Passing right player slot
local name = 'First: ' .. characterData.firstname .. ' Last: ' .. characterData.lastname .. ''
local src = source
local identifier = GetPlayerIdentifierByType(src, "discord")
local characterName = 'First: ' .. characterData.firstname .. ' Last: ' .. characterData.lastname .. ''
local citizenID = '' .. cid .. '-' .. identifier .. '' -- 1-Discord
-- TODO: Add discord logs
TriggerClientEvent('gb-core:character:setupCharacters', src) -- refresh menu
end)
RegisterNetEvent('gb-core:server:createCharacter')
AddEventHandler('gb-core:server:createCharacter', function(cData)
local src = source
local identifier = GetPlayerIdentifierByType(src, "discord")
local license = GetPlayerIdentifierByType(src, "fivem")
local name = GetPlayerName(src)
local cid = cData.cid
local citizenId = '' .. cData.cid .. '-' .. identifier .. ''
local characterName = 'First: ' .. cData.firstname .. ' Last: ' .. cData.lastname .. ''
exports['ghmattimysql']:execute('INSERT INTO players (`identifier`, `license`, `name`, `cid`, `cash`, `bank`, `firstname`, `lastname`, `sex`, `dob`, `citizenid`) VALUES (@identifier, @license, @name, @cid, @cash, @bank, @firstname, @lastname, @sex, @dob, @citizenid)'. {
['identifier'] = identifier,
['license'] = license,
['name'] = name,
['cid'] = cid,
['cash'] = GB.Starting.Cash,
['bank'] = GB.Starting.Bank,
['firstname'] = cData.firstname,
['lastname'] = cData.lastname,
['sex'] = cData.sex,
['dob'] = cData.dob,
['citizenid'] = citizenid -- Used to callback everything related to sql and saving per player
})
-- TODO: Logs for creation
TriggerClientEvent('gb-core:character:setupCharacters', src) -- refresh menu
end)

19
core/cl_core.lua Normal file
View File

@@ -0,0 +1,19 @@
function GB.Core.Start(self)
Citizen.CreateThread(function()
while true do
if NetworkIsSessionStarted() then
TriggerEvent('gb-core:start')
TriggerServerEvent('gb-core:serverStart')
break
end
end
end)
end
GB.Core.Start(self)
RegisterNetEvent('gb-core:client:getObject')
AddEventHandler('gb-core:client:getObject', function(callback)
callback(GB)
print('Called back ' .. GB .. )
end)

35
core/sv_core.lua Normal file
View File

@@ -0,0 +1,35 @@
RegisterServerEvent('gb-core:serverStart')
AddEventHandler('gb-core:serverStart', function()
local src = source
Citizen.CreateThread(function()
local identifier = GetPlayerIdentifiers(src)[1] -- gets IDENTIFIER:1234567890
if not identifier then
DropPlayer(src, "Identifier not located.") -- Removes player if not found
end
return
end)
end)
RegisterNetEvent('gb-core:server:getObject')
AddEventHandler('gb-core:server:getObject', function(callback)
callback(GB)
end)
--// COMMANDS \\--
AddEventHandler('gb-core:addCommand', function(command, callback, suggestion, args)
GB.Functions.addCommand(command, callback, suggestion, args)
end)
AddEventHandler('gb-core:addGroupCommand', function(command, group, callback, callbackfailed, suggestion, args)
GB.Functions.addGroupCommand(command, group, callback, callbackfailed, suggestion, args)
end)
--// CALLBACK SERVER \\--
RegisterServerEvent('gb-core:server:triggerServerCallback')
AddEventHandler('gb-core:server:triggerServerCallback', function(name, requestId, ...)
local src = source
GB.Functions.TriggerServerCallback(name, requestId, src, function(...)
TriggerClientEvent('gb-core:client:serverCallback', src, requestId, ...)
end, ...)
end)

118
events/cl_events.lua Normal file
View File

@@ -0,0 +1,118 @@
--// CALL GB.\\--
GB.Functions = GB.Functions or {}
GB.RequestID = GB.RequestID or {}
GB.ServerCallback = GB.ServerCallback or {}
GB.ServerCallbacks = {}
GB.CurrentRequestId = 0
GB.Functions.GetKey = function(key)
local Keys = {
["ESC"] = 322, ["F1"] = 288, ["F2"] = 289, ["F3"] = 170, ["F4"] = 166, ["F5"] = 167, ["F6"] = 168, ["F7"] = 169, ["F8"] = 56, ["F9"] = 57, ["F10"] = 165,
["~"] = 243, ["1"] = 157, ["2"] = 158, ["3"] = 159, ["4"] = 160, ["5"] = 164, ["6"] = 161, ["7"] = 162, ["8"] = 163, ["9"] = 84, ["0"] = 83, ["-"] = 245, ["="] = 246,
["BACKSPACE"] = 177, ["TAB"] = 37, ["Q"] = 44, ["W"] = 32, ["E"] = 38, ["R"] = 45, ["T"] = 245, ["Y"] = 246, ["U"] = 303, ["I"] = 199, ["O"] = 39, ["P"] = 40,
["["] = 39, ["]"] = 40, ["ENTER"] = 18, ["CAPS"] = 137, ["A"] = 34, ["S"] = 8, ["D"] = 9, ["F"] = 23, ["G"] = 47, ["H"] = 74, ["J"] = 311, ["K"] = 311, ["L"] = 182,
["LEFTSHIFT"] = 21, ["Z"] = 20, ["X"] = 73, ["C"] = 26, ["V"] = 0, ["B"] = 29, ["N"] = 249, ["M"] = 244, [","] = 82, ["."] = 81, ["RIGHTSHIFT"] = 21,
["LEFTCTRL"] = 36, ["LEFTALT"] = 19, ["SPACE"] = 22, ["RIGHTCTRL"] = 70, ["HOME"] = 213, ["PAGEUP"] = 10, ["PAGEDOWN"] = 11, ["DELETE"] = 178,
["LEFT"] = 174, ["RIGHT"] = 175, ["TOP"] = 27, ["DOWN"] = 173,
["NENTER"] = 201, ["N4"] = 108, ["N5"] = 60, ["N6"] = 107, ["N7"] = 117, ["N8"] = 61, ["N9"] = 118, ["N+"] = 96, ["N-"] = 97
}
return Keys[key]
end
GB.Functions.GetPlayerData() = function(source) -- get all data from the database for the player
return GB.GetPlayerData
end
--// ADMIN [BASIC] \\--
GB.Functions.DeleteVehicle = function(vehicle)
SetEntityAsMissionEntity(vehicle, false, true)
DeleteVehicle(vehicle)
end
GB.Functions.GetVehicleDirection = function()
local src = PlayerPedId()
local srcCoords = GetEntityCoords(src)
local inDirection = GetOffsetFromEntityInWorldCoords(src, 0, 10, 0)
local rayHandle = StartShapeTestRay(srcCoords, inDirection, 10, src, 0)
local numRayHandle, hit, endCoords, surfaceNormal, entityHit = GetShapeTestResult(rayHandle)
if hit == 1 and GetEntityType(entityHit) == 2 then
return entityHit
end
return nil
end
GB.Functions.DeleteObject = function(obj)
SetEntityAsMissionEntity(obj, false, true)
DeleteObject(obj)
end
GB.Functions.GetClosestPlayer = function(coords)
local players = GB.Functions.GetPlayers()
local closestDistance = -1
local closestPlayer = -1
local coords = coords
local usePlayerPed = false
local src = PlayerPedId()
local srcID = PlayerId()
if coords == nil then
usePlayerPed = true
coords = GetEntityCoords(src)
end
for i = 1, #players, 1 do
local target = GetPlayerPed(players[i])
if not usePlayerPed() or (usePlayerPed and players[i] ~= PlayerId) then
local targetCoords = GetEntityCoords(target)
local distance = GetDistanceBetweenCoords(targetCoords, coords.x, coords.y, coords.z, true)
if closestDistance == -1 or closestDistance > distance then
closestPlayer = players[i]
closestDistance = distance
end
end
end
return closestPlayer, closestDistance
end
--// CALLBACKS \\--
GB.Functions.TriggerServerCallback = function(name, cb, ...)
GB.ServerCallbacks[GB.CurrentRequestId] = cb
TriggerServerEvent('gb-core:server:triggerServerCallback', name, GB.CurrentRequestId, ...)
if GB.CurrentRequestId < 65535 then
GB.CurrentRequestId = GB.CurrentRequestId + 1
else
GB.CurrentRequestId = 0
end
end
GB.Functions.GetPlayers = function()
local MaxPlayer = 120
local players = {}
for i = 0, MaxPlayer, 1 do
local src = GetPlayerPed(i)
if DoesEntityExist(src) then
table.insert(players, i)
end
end
return players
end
RegisterNetEvent('gb-core:client:serverCallback')
AddEventHandler('gb-core:client:serverCallback', function(requestId, ...)
GB.ServerCallbacks[requestId](...)
GB.ServerCallbacks[requestId] = nil
end)
--// OTHER \\--
RegisterNetEvent('gb-setCharacterData')
AddEventHandler('gb-setCharacterData', function(Player)
pData = Player
end)

153
events/sv_events.lua Normal file
View File

@@ -0,0 +1,153 @@
--// CALL GB.\\--
GB.Functions = GB.Functions or {}
GB.Commands = {}
GB.CommandsSuggestions = {}
GB.ServerCallbacks = GB.ServerCallbacks or {}
GB.ServerCallback = {}
--// CALLBACKS \\--
GB.Functions.RegisterServerCallback = function(name, cb)
GB.ServerCallback[name] = cb
end
GB.Functions.TriggerServerCallback = function(name, requestId, source, cb, ...)
if GB.ServerCallbacks[name] ~= nil then
GB.ServerCallbacks[name](source, cb, ...)
end
end
--// FUNCTIONS \\--
GB.Functions.getPlayer() = function(source)
if GB.Players[source] ~= nil then
return GB.Players[source]
end
end
GB.Functions.AdminPlayer = function (source) -- ADMIN
if GB.APlayers[source] ~= nil then
return GB.APlayers[source]
end
end
--// EVENTS \\--
RegisterNetEvent('gb-core:server:updatePlayer')
AddEventHandler('gb-core:server:updatePlayer', function()
local src = source
local player = GB.Functions.GetPlayer(src)
if player then
Player.Functions.Save()
end
end)
--// SQL \\--
GB.Functions.CreatePlayer = function(source, Data)
exports['ghmattimysql']:execute(`INSERT INTO players (`Identifier`, `license`, `name`, `cash`, `bank`) VALUES (@identifier), (@license), (@name), (@cash), (@bank)`, {
['identifier'] = Data.identifier,
['license'] = Data.license,
['name'] = Data.name,
['cash'] = Data.cash,
['bank'] = Data.bank
})
print('[GB-Core] ' ..Data.name..' was created successfully')
GB.Functions.LoadPlayer(source, Data)
end
GB.Functions.LoadPlayer = function(source, pData, cid)
local src = source
local identifier = pData.identifier
Citizen.Wait(7)
exports['ghmattimysql']:execute(`SELECT * FROM players WHERE identifier = @identifier AND cid = @cid`, {['@identifier'] = identifier, ['@cid'] = cid}, function(result)
-- SERVER
exports['ghmattimysql']:execute(`UPDATE players SET name = @name WHERE identifier = @identifier AND cid = @cid`, {['@identifier'] = identifier, ['@name'] = pData.name ['@cid'] = cid})
GB.Player.LoadData(source, identifier, cid)
Citizen.Wait(7)
local player = GB.Functions.getPlayer(source)
TriggerClientEvent('gb-setCharacterData', source {
identifier = result[1].identifier,
license = result[1].license,
cid = result[1].cid,
name = result[1].name,
cash = result[1].cash,
bank = result[1].bank,
citizenId = result[1].citizenId,
})
TriggerClientEvent('gb-core:playerLoaded', source)
-- TODO: TriggerClientEvent() for UI
-- TODO: Trigger for ADMIN
end)
end
--// COMMANDS \\--
GB.Functions.addCommand = function(command, callback, suggestion, args)
GB.Commands[command] = {}
GB.Commands[command].perm = math.maxInteger
GB.Commands[command].group = group
GB.Commands[command].cmd = callback
GB.Commands[command].callbackfailed = callbackfailed
GB.Commands[command].arguments = arguments or -1
if suggestion then
if not suggestion.params or not type(suggestion.params) == "table" then suggestion.params = {} end
if not suggestion.help or not type(suggestion.help) == "string" then suggestion.help = "" end
GB.CommandsSuggestions[command] = suggestion
end
ExecuteCommand('add_ace group.' .. group .. ' command.' .. command .. ' allow')
RegisterCommand(command, function(source, args)
local src = source
local pData = GB.Functions.AgetPlayer(src)
if (src ~= 0) then
if pData ~= then
if pData.Data.usergroup == GB.Commands[command].group then
if ((#args <= GB.Commands[command].arguments and #args == GB.Commands[command].arguments) or GB.Commands[command].arguments == -1) then
callback(src, args, GB.Players[src])
else
callbackfailed(src, args, GB.Players[src])
end
end
else
if ((#args <= GB.Commands[command].arguments and #args == GB.Commands[command].arguments) or GB.Commands[command].arguments == -1) then
callback(src, args, GB.Players[src])
end
end
end
end, true)
end
--// GROUPS \\--
GB.Functions.setupAdmin = function(player, group)
local identifier = player.Data.identifier
local pCid = player.Data.cid
exports['ghmattimysql']:execute(`DELETE FROM ranking WHERE identifier = @identifier`, {['@identifier'] = identifier})
Wait(1000)
exports['ghmattimysql']:execute(`INSERT INTO ranking (`usergroup`, `identifier`) VALUES (@usergroup, @identifier)`, {
['@usergroup'] = group,
['@identifier'] = identifier
})
print('[GB-Core] Function Group: ' .. group)
TriggerClientEvent('gb-admin:updateGroup', player.Data.PlayerId, group)
end
GB.function.BuildCommands = function(source)
local src = source
for k, v in pairs(GB.CommandsSuggestions) do
TriggerClientEvent('chat:addSuggestion', src, '/'..k, v.help, v.params)
end
end
GB.function.ClearCommands = function(source)
local src = source
for k, v in pairs(GB.CommandsSuggestions) do
TriggerClientEvent('chat:addSuggestion', src, '/'..k, v.help, v.params)
end
end

19
fxmanifest.lua Normal file
View File

@@ -0,0 +1,19 @@
fx_version 'cerulean'
games 'gta5'
author 'gb-framework'
description 'n/a'
version '0.0.1'
dependency 'ghmattimysql'
client_scripts {
'core/cl_core.lua',
'events/cl_events.lua'
}
server_scripts {
'core/sv_core.lua',
'events/sv_events.lua'
}

42
gameplay/gameplay.lua Normal file
View File

@@ -0,0 +1,42 @@
local function StartingRoleplay()
Citizen.CreateThread(function()
for i = 1, 25 do
EnableDispatchService(i, 25)
end
for i = 0, 255 do
if NetworkIsPlayerConnected(i) then
if NetworkIsPlayerConnected(i) and GetPlayerPed(i) ~= nil then
SetCanAttackFriendly(GetPlayerPed(i), true, true)
end
end
end
end)
Citizen.CreateThread(function()
while true do
Wait(1000)
local Player = PlayerId()
SetPlayerWantedLevel(Player, 0, false)
SetPlayerWantedLevelNow(Player, false)
end
end)
Citizen.CreateThread(function()
while true do
Citizen.Wait(1000)
local pos = GetEntityCoords(PlayerPedId(), false)
local dist = GetDistanceBetweenCoords(GetEntityCoords(GetPlayerPed(-1)), 2729.47, 1514.56, 23.7, false)
if dist > 150.0 then
ClearAreaOfCops(pos, 400.0)
else
Wait(5000)
end
end
end)
end
AddEventHandler('gb-core:start', function()
StartingRoleplay()
end)

22
shared/shared.lua Normal file
View File

@@ -0,0 +1,22 @@
GB = GB or {}
GB.Core = GB.Core or {}
GB.Player = GB.Player or {}
GB.Players = GB.Players or {}
GB.APlayer = GB.APlayer or {}
GB.APlayers = GB.APlayers or {}
GB.Functions = GB.Functions or {}
GB.PlayerData = GB.PlayerData or {}
GB.Commands = GB.Commands or {}
GB.Admin = GB.Admin or {}
GB.NewCharacter = {
Cash = 50,
Bank = 0
}
GB.UserGroups = {
['user'] = {label = 'User'},
['mod'] = {label = 'Moderator'},
['admin'] = {label = 'Admin'},
['dev'] = {label = 'Developer'}
}