11 Commits

Author SHA1 Message Date
Andy
539e522373 Merge pull request #57 from ND-Framework/fix/driving-locked-vehicle
fix(client/vehicle): vehicle keys issues
2024-01-16 23:31:40 +01:00
Andyyy7666
2bacdd2a20 fix(client/vehicle): vehicle keys issues 2024-01-16 23:31:12 +01:00
Andy
6242a44c0b Merge pull request #53 from realCallMeJ/main
feat: config for requiring discord server membership
2024-01-16 20:59:48 +01:00
Andyyy7666
74e4ccc2de feat: police vehicle callsigns mod 2024-01-15 19:48:24 +01:00
Andyyy7666
2fda7655b5 feat(server/player): save only one column 2024-01-11 00:36:18 +01:00
CallMeJ
ade82436a5 feat: config for requiring discord server membership 2024-01-09 15:50:09 -10:00
Andyyy7666
f512d0ed0c Update fxmanifest.lua 2024-01-09 13:27:11 +01:00
Andyyy7666
0a19fe8a33 fix(client(vehicle): hide weapon while using key 2024-01-09 13:03:42 +01:00
Andyyy7666
2882c7c1ae tweak:(database/characters): phonenumber column 2024-01-07 21:25:44 +01:00
Andyyy7666
6291690bd4 feat(database/characters): phonenumber column 2024-01-07 21:14:30 +01:00
Andyyy7666
af82c447c1 feat(server/player): phonenumber player data 2024-01-07 21:13:56 +01:00
8 changed files with 119 additions and 48 deletions

View File

@@ -10,8 +10,9 @@ Config = {
discordActionLink = GetConvar("discordActionLink", "https://discord.gg/Z9Mxu72zZ6"), discordActionLink = GetConvar("discordActionLink", "https://discord.gg/Z9Mxu72zZ6"),
discordActionText2 = GetConvar("core:discordActionText2", "STORE"), discordActionText2 = GetConvar("core:discordActionText2", "STORE"),
discordActionLink2 = GetConvar("core:discordActionLink2", "https://andyyy.tebex.io/category/fivem-scripts"), discordActionLink2 = GetConvar("core:discordActionLink2", "https://andyyy.tebex.io/category/fivem-scripts"),
randomUnlockedVehicleChance = GetConvarInt("core:randomUnlockedVehicleChance", 30),
disableVehicleAirControl = GetConvarInt("core:disableVehicleAirControl", 1) == 1, disableVehicleAirControl = GetConvarInt("core:disableVehicleAirControl", 1) == 1,
randomUnlockedVehicleChance = GetConvarInt("core:randomUnlockedVehicleChance", 30),
requireKeys = GetConvarInt("core:requireKeys", 1) == 1,
useInventoryForKeys = GetConvarInt("core:useInventoryForKeys", 1) == 1, useInventoryForKeys = GetConvarInt("core:useInventoryForKeys", 1) == 1,
groups = json.decode(GetConvar("core:groups", "[]")), groups = json.decode(GetConvar("core:groups", "[]")),
compatibility = json.decode(GetConvar("core:compatibility", "[]")) compatibility = json.decode(GetConvar("core:compatibility", "[]"))

View File

@@ -293,6 +293,7 @@ AddStateBagChangeHandler("props", nil, function(bagName, key, value, reserved, r
lib.setVehicleProperties(entity, props) lib.setVehicleProperties(entity, props)
end) end)
local playingKey = 0
local function playKeyFob(veh) local function playKeyFob(veh)
local keyFob local keyFob
local ped = cache.ped local ped = cache.ped
@@ -300,12 +301,21 @@ local function playKeyFob(veh)
if #(coords-GetEntityCoords(veh)) > 25.0 then return end if #(coords-GetEntityCoords(veh)) > 25.0 then return end
if not playerVehicle then if not playerVehicle then
playingKey += 1
SetPedCurrentWeaponVisible(ped, false, false)
ClearPedTasks(ped) ClearPedTasks(ped)
lib.requestAnimDict("anim@mp_player_intmenu@key_fob@") lib.requestAnimDict("anim@mp_player_intmenu@key_fob@")
TaskPlayAnim(ped, "anim@mp_player_intmenu@key_fob@", "fob_click_fp", 8.0, 8.0, -1, 48, 1, false, false, false) TaskPlayAnim(ped, "anim@mp_player_intmenu@key_fob@", "fob_click_fp", 8.0, 8.0, -1, 48, 1, false, false, false)
keyFob = CreateObject(`lr_prop_carkey_fob`, 0, 0, 0, true, true, true) keyFob = CreateObject(`lr_prop_carkey_fob`, 0, 0, 0, true, true, true)
AttachEntityToEntity(keyFob, ped, GetPedBoneIndex(ped, 0xDEAD), 0.12, 0.04, -0.025, -100.0, 100.0, 0.0, true, true, false, true, 1, true) AttachEntityToEntity(keyFob, ped, GetPedBoneIndex(ped, 0xDEAD), 0.12, 0.04, -0.025, -100.0, 100.0, 0.0, true, true, false, true, 1, true)
Wait(700) Wait(700)
SetTimeout(400, function()
playingKey -= 1
end)
SetTimeout(1200, function()
if playingKey > 0 then return end
SetPedCurrentWeaponVisible(ped, true, false)
end)
end end
PlaySoundFromEntity(-1, "Remote_Control_Fob", ped, "PI_Menu_Sounds", true, 0) PlaySoundFromEntity(-1, "Remote_Control_Fob", ped, "PI_Menu_Sounds", true, 0)
@@ -470,22 +480,35 @@ CreateThread(function()
local wait = 500 local wait = 500
while true do while true do
Wait(wait) Wait(wait)
local reset = true
playerVehicle = cache.seat == -1 and cache.vehicle playerVehicle = cache.seat == -1 and cache.vehicle
if playerVehicle then
local entering = GetVehiclePedIsEntering(cache.ped)
if entering and DoesEntityExist(entering) and IsVehicleNeedsToBeHotwired(entering) then
SetVehicleNeedsToBeHotwired(entering, false)
end
if not playerVehicle then goto skip end
if Config.disableVehicleAirControl and not vehicleClassNotDisableAirControl[GetVehicleClass(playerVehicle)] and (IsEntityInAir(playerVehicle) or IsEntityUpsidedown(playerVehicle)) then if Config.disableVehicleAirControl and not vehicleClassNotDisableAirControl[GetVehicleClass(playerVehicle)] and (IsEntityInAir(playerVehicle) or IsEntityUpsidedown(playerVehicle)) then
wait = 0 wait = 0
reset = false
DisableControlAction(0, 59) -- disable vehicle air control. DisableControlAction(0, 59) -- disable vehicle air control.
DisableControlAction(0, 60) DisableControlAction(0, 60)
elseif not GetIsVehicleEngineRunning(playerVehicle) and not hasVehicleKeysCheck(playerVehicle) then end
if Config.requireKeys and not GetIsVehicleEngineRunning(playerVehicle) and not hasVehicleKeysCheck(playerVehicle) then
wait = 0 wait = 0
reset = false
DisableControlAction(0, 59) DisableControlAction(0, 59)
DisableControlAction(0, 71)
if DoesEntityExist(playerVehicle) and IsVehicleEngineStarting(playerVehicle) then if DoesEntityExist(playerVehicle) and IsVehicleEngineStarting(playerVehicle) then
SetVehicleEngineOn(playerVehicle, false, true, true) -- don't turn on engine if no keys. SetVehicleEngineOn(playerVehicle, false, true, true) -- don't turn on engine if no keys.
end end
else
wait = 500
end end
elseif wait ~= 500 then
::skip::
if (reset or not playerVehicle) and wait ~= 500 then
wait = 500 wait = 500
end end
end end

View File

@@ -8,6 +8,7 @@ CREATE TABLE IF NOT EXISTS `nd_characters` (
`gender` VARCHAR(50) DEFAULT NULL, `gender` VARCHAR(50) DEFAULT NULL,
`cash` INT(10) DEFAULT '0', `cash` INT(10) DEFAULT '0',
`bank` INT(10) DEFAULT '0', `bank` INT(10) DEFAULT '0',
`phonenumber` VARCHAR(20) DEFAULT NULL,
`groups` LONGTEXT DEFAULT ('[]'), `groups` LONGTEXT DEFAULT ('[]'),
`metadata` LONGTEXT DEFAULT ('[]'), `metadata` LONGTEXT DEFAULT ('[]'),
`inventory` LONGTEXT DEFAULT ('[]'), `inventory` LONGTEXT DEFAULT ('[]'),

View File

@@ -2,7 +2,7 @@
author "Andyyy#7666" author "Andyyy#7666"
description "ND Framework Core" description "ND Framework Core"
version "2.0.2" version "2.1.2"
fx_version "cerulean" fx_version "cerulean"
game "gta5" game "gta5"

View File

@@ -7,6 +7,7 @@ local tempPlayersInfo = {}
Config = { Config = {
serverName = GetConvar("core:serverName", "Unconfigured ND-Core Server"), serverName = GetConvar("core:serverName", "Unconfigured ND-Core Server"),
discordInvite = GetConvar("core:discordInvite", "https://discord.gg/Z9Mxu72zZ6"), discordInvite = GetConvar("core:discordInvite", "https://discord.gg/Z9Mxu72zZ6"),
discordMemeberRequired = GetConvarInt("core:discordMemeberRequired", 1) == 1,
discordAppId = GetConvar("core:discordAppId", "858146067018416128"), discordAppId = GetConvar("core:discordAppId", "858146067018416128"),
discordAsset = GetConvar("core:discordAsset", "andyyy"), discordAsset = GetConvar("core:discordAsset", "andyyy"),
discordAssetSmall = GetConvar("core:discordAssetSmall", "andyyy"), discordAssetSmall = GetConvar("core:discordAssetSmall", "andyyy"),
@@ -101,7 +102,7 @@ AddEventHandler("playerConnecting", function(name, setKickReason, deferrals)
if mainIdentifier and Config.discordBotToken ~= "false" and Config.discordGuildId ~= "false" then if mainIdentifier and Config.discordBotToken ~= "false" and Config.discordGuildId ~= "false" then
discordInfo = checkDiscordIdentifier(identifiers) discordInfo = checkDiscordIdentifier(identifiers)
if not discordInfo then if not discordInfo and Config.discordMemeberRequired then
deferrals.done(("Your discord was not found, join our discord here: %s."):format(Config.discordInvite)) deferrals.done(("Your discord was not found, join our discord here: %s."):format(Config.discordInvite))
Wait(0) Wait(0)
end end

View File

@@ -25,6 +25,7 @@ local function createCharacterTable(info)
gender = info.gender, gender = info.gender,
cash = info.cash, cash = info.cash,
bank = info.bank, bank = info.bank,
phonenumber = info.phonenumber,
groups = info.groups, groups = info.groups,
metadata = info.metadata, metadata = info.metadata,
inventory = info.inventory inventory = info.inventory
@@ -164,8 +165,23 @@ local function createCharacterTable(info)
end end
-- Save character information to database -- Save character information to database
function self.save() function self.save(key)
local affectedRows = MySQL.update.await("UPDATE nd_characters SET name = ?, firstname = ?, lastname = ?, dob = ?, gender = ?, cash = ?, bank = ?, `groups` = ?, metadata = ? WHERE charid = ?", { if key then
local charData = self[key]
if not charData or type(charData) == "function" then
return lib.print.error(key, "Is not valid character data.")
end
if type(charData) == "table" then
charData = json.encode(charData)
end
local query = ("UPDATE nd_characters SET `%s` = ? WHERE charid = ?"):format(key)
local affectedRows = MySQL.update.await(query, {charData, self.id})
return affectedRows > 0
end
local affectedRows = MySQL.update.await("UPDATE nd_characters SET name = ?, firstname = ?, lastname = ?, dob = ?, gender = ?, cash = ?, bank = ?, phonenumber = ?, `groups` = ?, metadata = ? WHERE charid = ?", {
self.name, self.name,
self.firstname, self.firstname,
self.lastname, self.lastname,
@@ -173,6 +189,7 @@ local function createCharacterTable(info)
self.gender, self.gender,
self.cash, self.cash,
self.bank, self.bank,
self.phonenumber,
json.encode(self.groups), json.encode(self.groups),
json.encode(self.metadata), json.encode(self.metadata),
self.id self.id
@@ -407,12 +424,13 @@ function NDCore.newCharacter(src, info)
gender = info.gender or "", gender = info.gender or "",
cash = info.cash or 0, cash = info.cash or 0,
bank = info.bank or 0, bank = info.bank or 0,
phonenumber = info.phonenumber,
groups = info.groups or {}, groups = info.groups or {},
metadata = info.metadata or {}, metadata = info.metadata or {},
inventory = info.inventory or {}, inventory = info.inventory or {}
} }
charInfo.id = MySQL.insert.await("INSERT INTO nd_characters (identifier, name, firstname, lastname, dob, gender, cash, bank, `groups`, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", { charInfo.id = MySQL.insert.await("INSERT INTO nd_characters (identifier, name, firstname, lastname, dob, gender, cash, bank, phonenumber, `groups`, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", {
identifier, identifier,
charInfo.name, charInfo.name,
charInfo.firstname, charInfo.firstname,
@@ -421,6 +439,7 @@ function NDCore.newCharacter(src, info)
charInfo.gender, charInfo.gender,
charInfo.cash, charInfo.cash,
charInfo.bank, charInfo.bank,
charInfo.phonenumber,
json.encode(charInfo.groups), json.encode(charInfo.groups),
json.encode(charInfo.metadata) json.encode(charInfo.metadata)
}) })
@@ -451,6 +470,7 @@ function NDCore.fetchCharacter(id, src)
gender = info.gender, gender = info.gender,
cash = info.cash, cash = info.cash,
bank = info.bank, bank = info.bank,
phonenumber = info.phonenumber,
groups = json.decode(info.groups), groups = json.decode(info.groups),
metadata = json.decode(info.metadata), metadata = json.decode(info.metadata),
inventory = json.decode(info.inventory) inventory = json.decode(info.inventory)
@@ -476,9 +496,10 @@ function NDCore.fetchAllCharacters(src)
gender = info.gender, gender = info.gender,
cash = info.cash, cash = info.cash,
bank = info.bank, bank = info.bank,
phonenumber = info.phonenumber,
groups = json.decode(info.groups), groups = json.decode(info.groups),
metadata = json.decode(info.metadata), metadata = json.decode(info.metadata),
inventory = json.decode(info.inventory), inventory = json.decode(info.inventory)
}) })
end end
return characters return characters

View File

@@ -90,6 +90,9 @@ function NDCore.getVehicle(entity)
if saveProperties and self.id and self.owner then if saveProperties and self.id and self.owner then
local properties = lib.callback.await("ND_Vehicles:getProps", NetworkGetEntityOwner(entity), self.netId) local properties = lib.callback.await("ND_Vehicles:getProps", NetworkGetEntityOwner(entity), self.netId)
if properties then if properties then
if self.properties?.callsign then
properties.callsign = true
end
MySQL.query("UPDATE nd_vehicles SET properties = ? WHERE id = ?", {json.encode(properties), self.id}) MySQL.query("UPDATE nd_vehicles SET properties = ? WHERE id = ?", {json.encode(properties), self.id})
end end
end end
@@ -102,6 +105,11 @@ function NDCore.getVehicle(entity)
if not DoesEntityExist(entity) then return end if not DoesEntityExist(entity) then return end
local properties = type(props) == "string" and json.decode(props) or props local properties = type(props) == "string" and json.decode(props) or props
local state = Entity(entity).state local state = Entity(entity).state
if self.properties?.callsign then
properties.callsign = true
end
state.props = properties state.props = properties
self.properties = properties self.properties = properties
@@ -406,11 +414,27 @@ function NDCore.spawnOwnedVehicle(source, vehicleId, coords, heading)
if not vehicle or not vehicle.available or vehicle.owner ~= player.id then return end if not vehicle or not vehicle.available or vehicle.owner ~= player.id then return end
MySQL.query.await("UPDATE nd_vehicles SET stored = ? WHERE id = ?", {0, vehicleId}) MySQL.query.await("UPDATE nd_vehicles SET stored = ? WHERE id = ?", {0, vehicleId})
local properties = vehicle.properties
if properties.callsign then
local callsign = player.getMetadata("callsign")
if not callsign or callsign == "" then goto skip end
callsign = tostring(callsign)
if not callsign or callsign:len() ~= 3 then goto skip end
properties.modFender = tonumber(callsign:sub(1, 1))
properties.modRightFender = tonumber(callsign:sub(2, 2))
properties.modRoof = tonumber(callsign:sub(3, 3))
end
::skip::
return NDCore.createVehicle({ return NDCore.createVehicle({
owner = player.id, owner = player.id,
model = vehicle.properties.model, model = properties.model,
coords = vec4(coords.x, coords.y, coords.z, coords.w or coords.heading or heading), coords = vec4(coords.x, coords.y, coords.z, coords.w or coords.heading or heading),
properties = vehicle.properties, properties = properties,
vehicleId = vehicleId, vehicleId = vehicleId,
source = source source = source
}) })