mirror of
https://github.com/ND-Framework/ND_Core.git
synced 2026-08-17 13:56:02 +01:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
898b9aefe9 | ||
|
|
5545650dd5 | ||
|
|
f4f01a5b1c | ||
|
|
3252118f93 | ||
|
|
9d4708a1f8 | ||
|
|
d0d04ae282 | ||
|
|
c005c1b28b | ||
|
|
590044b5d6 | ||
|
|
3146172c0c | ||
|
|
2ce47ef8d1 | ||
|
|
6258651d8b | ||
|
|
eecbc8f690 | ||
|
|
1d25b54e0f | ||
|
|
e18389a52a | ||
|
|
539e522373 | ||
|
|
2bacdd2a20 | ||
|
|
6242a44c0b | ||
|
|
74e4ccc2de | ||
|
|
2fda7655b5 | ||
|
|
ade82436a5 | ||
|
|
f512d0ed0c | ||
|
|
0a19fe8a33 | ||
|
|
2882c7c1ae | ||
|
|
6291690bd4 | ||
|
|
af82c447c1 | ||
|
|
46f4bdbd64 | ||
|
|
4870d639d4 | ||
|
|
ed895b4e6d | ||
|
|
5d2925d0c3 | ||
|
|
0500cef32f | ||
|
|
0e1fb43cd2 | ||
|
|
3260aa01f2 | ||
|
|
71a54be704 | ||
|
|
d939607d64 | ||
|
|
5cb038819c | ||
|
|
9f5bb34bdd | ||
|
|
29006870c3 | ||
|
|
a60e1b9e32 | ||
|
|
7fe7901a13 | ||
|
|
ca8f4369f6 | ||
|
|
e1d4b2fcff | ||
|
|
8b0f2b010d | ||
|
|
24e8874050 | ||
|
|
289d040b5c | ||
|
|
3f0c47c2d0 | ||
|
|
543b23a644 | ||
|
|
4b106d3688 | ||
|
|
db5c54f2d8 | ||
|
|
a1150bb821 | ||
|
|
8f7c52130a | ||
|
|
6e71142970 |
16
README.md
16
README.md
@@ -16,9 +16,13 @@
|
|||||||
* [oxmysql](https://github.com/overextended/oxmysql/releases)
|
* [oxmysql](https://github.com/overextended/oxmysql/releases)
|
||||||
* [ox_lib](https://github.com/overextended/ox_lib/releases)
|
* [ox_lib](https://github.com/overextended/ox_lib/releases)
|
||||||
|
|
||||||
## v2 Addons
|
## Addons
|
||||||
* [Character selection](https://github.com/ND-Framework/ND_Characters/tree/wip-v2)
|
* [Character selection](https://github.com/ND-Framework/ND_Characters/releases)
|
||||||
* [Banking](https://github.com/ND-Framework/ND_Banking/tree/wip-v2)
|
* [Banking](https://github.com/ND-Framework/ND_Banking/releases)
|
||||||
* [Appearance shops](https://github.com/ND-Framework/ND_AppearanceShops/tree/wip-v2)
|
* [Appearance shops](https://github.com/ND-Framework/ND_AppearanceShops/releases)
|
||||||
* [Dealership](https://github.com/ND-Framework/ND_Dealership/tree/v2)
|
* [Dealership](https://github.com/ND-Framework/ND_Dealership/releases)
|
||||||
* [Inventory](https://github.com/overextended/ox_inventory/pull/1403)
|
* [Inventory](https://github.com/overextended/ox_inventory/releases)
|
||||||
|
* [Ambulance job](https://github.com/ND-Framework/ND_Ambulance/releases)
|
||||||
|
* [Casino](https://github.com/ND-Framework/ND_Casino/releases)
|
||||||
|
* [Blackjack](https://github.com/ND-Framework/ND_Blackjack/releases)
|
||||||
|
* [Nitro](https://github.com/ND-Framework/ND_Nitro/releases)
|
||||||
|
|||||||
@@ -29,15 +29,14 @@ AddEventHandler("gameEventTriggered", function(name, args)
|
|||||||
local victim = args[1]
|
local victim = args[1]
|
||||||
if not IsPedAPlayer(victim) or NetworkGetPlayerIndexFromPed(victim) ~= cache.playerId then return end
|
if not IsPedAPlayer(victim) or NetworkGetPlayerIndexFromPed(victim) ~= cache.playerId then return end
|
||||||
|
|
||||||
if not IsPedDeadOrDying(victim, true) and GetEntityHealth(victim) > 0 then
|
|
||||||
local hit, bone = GetPedLastDamageBone(victim)
|
local hit, bone = GetPedLastDamageBone(victim)
|
||||||
if hit and usingAmbulance then
|
if hit and usingAmbulance then
|
||||||
local damageWeapon = ambulance:getLastDamagingWeapon(victim)
|
local damageWeapon = ambulance:getLastDamagingWeapon(victim)
|
||||||
return damageWeapon and ambulance:updateBodyDamage(bone, damageWeapon)
|
ambulance:updateBodyDamage(bone, damageWeapon)
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not IsPedDeadOrDying(victim, true) or GetEntityHealth(victim) > 100 then return end
|
||||||
|
|
||||||
local killerEntity, deathCause = GetPedSourceOfDeath(cache.ped), GetPedCauseOfDeath(cache.ped)
|
local killerEntity, deathCause = GetPedSourceOfDeath(cache.ped), GetPedCauseOfDeath(cache.ped)
|
||||||
local killerClientId = NetworkGetPlayerIndexFromPed(killerEntity)
|
local killerClientId = NetworkGetPlayerIndexFromPed(killerEntity)
|
||||||
if killerEntity ~= cache.ped and killerClientId and NetworkIsPlayerActive(killerClientId) then
|
if killerEntity ~= cache.ped and killerClientId and NetworkIsPlayerActive(killerClientId) then
|
||||||
|
|||||||
@@ -22,5 +22,50 @@ RegisterNetEvent("ND:updateLastLocation", function(location)
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
RegisterNetEvent("ND:revivePlayer", function()
|
RegisterNetEvent("ND:revivePlayer", function()
|
||||||
NDCore.revivePlayer(true)
|
if source == "" then return end
|
||||||
|
local veh = GetVehiclePedIsIn(cache.ped)
|
||||||
|
local seat = cache.seat
|
||||||
|
local coords = GetEntityCoords(cache.ped)
|
||||||
|
NetworkResurrectLocalPlayer(coords.x, coords.y, coords.z, GetEntityHeading(cache.ped), true, true, false)
|
||||||
|
|
||||||
|
local ped = PlayerPedId()
|
||||||
|
if cache.ped ~= ped then
|
||||||
|
DeleteEntity(cache.ped)
|
||||||
|
ClearAreaOfPeds(coords.x, coords.y, coords.z, 0.2, false)
|
||||||
|
end
|
||||||
|
|
||||||
|
SetEntityInvincible(ped, false)
|
||||||
|
FreezeEntityPosition(ped, false)
|
||||||
|
SetEntityVisible(ped, true)
|
||||||
|
SetEveryoneIgnorePlayer(ped, false)
|
||||||
|
SetPedCanBeTargetted(ped, true)
|
||||||
|
SetEntityCanBeDamaged(ped, true)
|
||||||
|
SetBlockingOfNonTemporaryEvents(ped, false)
|
||||||
|
SetPedCanRagdollFromPlayerImpact(ped, true)
|
||||||
|
ClearPedTasksImmediately(ped)
|
||||||
|
|
||||||
|
if veh and veh ~= 0 then
|
||||||
|
SetPedIntoVehicle(ped, veh, seat)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent("ND:characterUnloaded")
|
||||||
|
|
||||||
|
RegisterNetEvent("ND:clothingMenu", function()
|
||||||
|
if GetResourceState("fivem-appearance") ~= "started" then return end
|
||||||
|
|
||||||
|
local function customize(appearance)
|
||||||
|
if not appearance then return end
|
||||||
|
TriggerServerEvent("ND:updateClothing", appearance)
|
||||||
|
end
|
||||||
|
|
||||||
|
exports["fivem-appearance"]:startPlayerCustomization(customize, {
|
||||||
|
ped = false,
|
||||||
|
headBlend = true,
|
||||||
|
faceFeatures = true,
|
||||||
|
headOverlays = true,
|
||||||
|
components = true,
|
||||||
|
props = true,
|
||||||
|
tattoos = true
|
||||||
|
})
|
||||||
end)
|
end)
|
||||||
|
|||||||
@@ -26,56 +26,15 @@ function NDCore.getPlayersFromCoords(distance, coords)
|
|||||||
return closePlayers
|
return closePlayers
|
||||||
end
|
end
|
||||||
|
|
||||||
function NDCore.revivePlayer(reset, keepDead)
|
function NDCore.getConfig(info)
|
||||||
local usingAmbulance = GetResourceState("ND_Ambulance") == "started"
|
if not info then
|
||||||
if not keepDead then
|
return Config
|
||||||
LocalPlayer.state.dead = false
|
|
||||||
if usingAmbulance then
|
|
||||||
local state = Player(cache.serverId).state
|
|
||||||
state:set("isDead", false, true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local veh = GetVehiclePedIsIn(cache.ped)
|
|
||||||
local seat = cache.seat
|
|
||||||
local coords = GetEntityCoords(cache.ped)
|
|
||||||
NetworkResurrectLocalPlayer(coords.x, coords.y, coords.z, GetEntityHeading(cache.ped), true, true, false)
|
|
||||||
|
|
||||||
local ped = PlayerPedId()
|
|
||||||
if cache.ped ~= ped then
|
|
||||||
DeleteEntity(cache.ped)
|
|
||||||
ClearAreaOfPeds(coords.x, coords.y, coords.z, 0.2, false)
|
|
||||||
end
|
|
||||||
|
|
||||||
SetEntityInvincible(ped, false)
|
|
||||||
FreezeEntityPosition(ped, false)
|
|
||||||
SetEntityVisible(ped, true)
|
|
||||||
SetEveryoneIgnorePlayer(ped, false)
|
|
||||||
SetPedCanBeTargetted(ped, true)
|
|
||||||
SetEntityCanBeDamaged(ped, true)
|
|
||||||
SetBlockingOfNonTemporaryEvents(ped, false)
|
|
||||||
SetPedCanRagdollFromPlayerImpact(ped, true)
|
|
||||||
ClearPedTasksImmediately(ped)
|
|
||||||
|
|
||||||
if veh and veh ~= 0 then
|
|
||||||
SetPedIntoVehicle(ped, veh, seat)
|
|
||||||
end
|
|
||||||
if reset and GetPedMovementClipset(ped) == `move_m@injured` then
|
|
||||||
ClearEntityLastDamageEntity(ped)
|
|
||||||
SetPedMoveRateOverride(ped, 1.0)
|
|
||||||
ResetPedMovementClipset(ped, 0)
|
|
||||||
end
|
|
||||||
if reset and usingAmbulance then
|
|
||||||
exports["ND_Ambulance"]:resetBodyDamage()
|
|
||||||
end
|
end
|
||||||
|
return Config[info]
|
||||||
end
|
end
|
||||||
|
|
||||||
function NDCore.notify(...)
|
function NDCore.notify(...)
|
||||||
if GetResourceState("ModernHUD") == "started" then
|
|
||||||
exports["ModernHUD"]:notify(...)
|
|
||||||
elseif GetResourceState("ox_lib") == "started" then
|
|
||||||
lib.notify(...)
|
lib.notify(...)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
for name, func in pairs(NDCore) do
|
for name, func in pairs(NDCore) do
|
||||||
|
|||||||
@@ -7,11 +7,12 @@ Config = {
|
|||||||
discordAsset = GetConvar("core:discordAsset", "andyyy"),
|
discordAsset = GetConvar("core:discordAsset", "andyyy"),
|
||||||
discordAssetSmall = GetConvar("core:discordAssetSmall", "andyyy"),
|
discordAssetSmall = GetConvar("core:discordAssetSmall", "andyyy"),
|
||||||
discordActionText = GetConvar("core:discordActionText", "DISCORD"),
|
discordActionText = GetConvar("core:discordActionText", "DISCORD"),
|
||||||
discordActionLink = GetConvar("discordActionLink", "https://discord.gg/Z9Mxu72zZ6"),
|
discordActionLink = GetConvar("core: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", "[]"))
|
||||||
|
|||||||
@@ -218,10 +218,10 @@ end)
|
|||||||
RegisterCommand("getclothing", function(source, args, rawCommand)
|
RegisterCommand("getclothing", function(source, args, rawCommand)
|
||||||
local info = ""
|
local info = ""
|
||||||
for k, v in pairs(clothingComponents) do
|
for k, v in pairs(clothingComponents) do
|
||||||
info = ("%s\n%s = {\n drawable = %s,\n texture = %s\n},"):format(info, k, GetPedDrawableVariation(cache.ped, v), GetPedTextureVariation(cache.ped, v))
|
info = ("%s\n%s = { drawable = %s, texture = %s },"):format(info, k, GetPedDrawableVariation(cache.ped, v), GetPedTextureVariation(cache.ped, v))
|
||||||
end
|
end
|
||||||
for k, v in pairs(clothingProps) do
|
for k, v in pairs(clothingProps) do
|
||||||
info = ("%s\n%s = {\n drawable = %s,\n texture = %s\n},"):format(info, k, GetPedPropIndex(cache.ped, v), GetPedPropTextureIndex(cache.ped, v))
|
info = ("%s\n%s = { drawable = %s, texture = %s },"):format(info, k, GetPedPropIndex(cache.ped, v), GetPedPropTextureIndex(cache.ped, v))
|
||||||
end
|
end
|
||||||
lib.setClipboard(info)
|
lib.setClipboard(info)
|
||||||
end, false)
|
end, false)
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -697,9 +720,14 @@ lib.addKeybind({
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
if not playerVehicle then return end
|
if not playerVehicle then return end
|
||||||
|
|
||||||
|
local speed = math.floor(GetEntitySpeed(playerVehicle) * 2.236936)
|
||||||
|
if speed < 10 then return end
|
||||||
|
|
||||||
cruiseControlEnabled = true
|
cruiseControlEnabled = true
|
||||||
cruiseSpeedVehicle = math.floor(GetEntitySpeed(playerVehicle) * 2.236936)
|
cruiseSpeedVehicle = speed
|
||||||
cruiseSpeedSet = cruiseSpeedVehicle
|
cruiseSpeedSet = cruiseSpeedVehicle
|
||||||
|
|
||||||
lib.notify({
|
lib.notify({
|
||||||
title = "Cruise control",
|
title = "Cruise control",
|
||||||
description = ("Set to %d mph."):format(math.floor(cruiseSpeedSet)),
|
description = ("Set to %d mph."):format(math.floor(cruiseSpeedSet)),
|
||||||
|
|||||||
@@ -5,13 +5,32 @@ exports("GetCoreObject", function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
NDCore.Functions = {}
|
NDCore.Functions = {}
|
||||||
NDCore.Functions.GetPlayer = NDCore.getPlayer
|
|
||||||
NDCore.Functions.GetPlayers = NDCore.getPlayers
|
NDCore.Functions.GetPlayers = NDCore.getPlayers
|
||||||
NDCore.Functions.GetUserDiscordInfo = NDCore.getDiscordInfo
|
NDCore.Functions.GetUserDiscordInfo = NDCore.getDiscordInfo
|
||||||
NDCore.Functions.SetActiveCharacter = NDCore.setActiveCharacter
|
NDCore.Functions.SetActiveCharacter = NDCore.setActiveCharacter
|
||||||
NDCore.Functions.GetPlayerCharacters = NDCore.fetchAllCharacters
|
NDCore.Functions.GetPlayerCharacters = NDCore.fetchAllCharacters
|
||||||
NDCore.Functions.GetPlayerByCharacterId = NDCore.fetchCharacter
|
NDCore.Functions.GetPlayerByCharacterId = NDCore.fetchCharacter
|
||||||
|
|
||||||
|
function NDCore.Functions.GetPlayer(src)
|
||||||
|
local player = NDCore.getPlayer(src)
|
||||||
|
return {
|
||||||
|
source = player.source,
|
||||||
|
id = player.id,
|
||||||
|
firstName = player.firstname,
|
||||||
|
lastName = player.lastname,
|
||||||
|
dob = player.dob,
|
||||||
|
gender = player.gender,
|
||||||
|
cash = player.cash,
|
||||||
|
bank = player.bank,
|
||||||
|
phoneNumber = player.metadata.phone,
|
||||||
|
lastLocation = player.metadata.lastLocation,
|
||||||
|
inventory = player.inventory,
|
||||||
|
discordInfo = player.discordInfo,
|
||||||
|
data = player.metadata,
|
||||||
|
job = player.job
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
function NDCore.Functions.GetPlayerIdentifierFromType(identifierType, src)
|
function NDCore.Functions.GetPlayerIdentifierFromType(identifierType, src)
|
||||||
return GetPlayerIdentifierByType(src, identifierType)
|
return GetPlayerIdentifierByType(src, identifierType)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ function NDCore.GetPlayerData()
|
|||||||
|
|
||||||
player.coords = GetEntityCoords(cache.ped)
|
player.coords = GetEntityCoords(cache.ped)
|
||||||
player.loadout = {}
|
player.loadout = {}
|
||||||
player.maxWeight = exports.ox_inventory:GetPlayerMaxWeight()
|
player.maxWeight = GetResourceState("ox_inventory") == "started" and exports.ox_inventory:GetPlayerMaxWeight() or 0
|
||||||
player.money = player.Accounts.Money
|
player.money = player.Accounts.Money
|
||||||
player.sex = player.gender
|
player.sex = player.gender
|
||||||
player.firstName = player.firstname
|
player.firstName = player.firstname
|
||||||
@@ -112,7 +112,7 @@ function NDCore.Progressbar(message, lenght, options)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function NDCore.SearchInventory(item, count)
|
function NDCore.SearchInventory(item, count)
|
||||||
local itemCount = exports.ox_inventory:Search(item)
|
local itemCount = GetResourceState("ox_inventory") == "started" and exports.ox_inventory:Search(item) or 0
|
||||||
return itemCount >= count and itemCount
|
return itemCount >= count and itemCount
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ function NDCore.ShowHelpNotification()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function NDCore.ShowInventory()
|
function NDCore.ShowInventory()
|
||||||
exports.ox_inventory:openInventory("player", cache.serverId)
|
return GetResourceState("ox_inventory") == "started" and exports.ox_inventory:openInventory("player", cache.serverId)
|
||||||
end
|
end
|
||||||
|
|
||||||
function NDCore.ShowNotification(msg, type, time)
|
function NDCore.ShowNotification(msg, type, time)
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ local registeredItems = {}
|
|||||||
|
|
||||||
local function getAmmoFromWeapon(weapon)
|
local function getAmmoFromWeapon(weapon)
|
||||||
if not weapon then return end
|
if not weapon then return end
|
||||||
for item, data in pairs(exports.ox_inventory:Items()) do
|
local items = GetResourceState("ox_inventory") == "started" and exports.ox_inventory:Items() or {}
|
||||||
|
for item, data in pairs(items) do
|
||||||
if data.weapon and data.model and data.model:lower() == weapon:lower() then
|
if data.weapon and data.model and data.model:lower() == weapon:lower() then
|
||||||
return data.ammoname
|
return data.ammoname
|
||||||
end
|
end
|
||||||
@@ -60,7 +61,7 @@ local function createPlayerFunctions(self)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function self.addInventoryItem(item, count)
|
function self.addInventoryItem(item, count)
|
||||||
exports.ox_inventory:AddItem(self.source, item, count)
|
return GetResourceState("ox_inventory") == "started" and exports.ox_inventory:AddItem(self.source, item, count)
|
||||||
end
|
end
|
||||||
|
|
||||||
function self.addMoney(amount)
|
function self.addMoney(amount)
|
||||||
@@ -100,11 +101,11 @@ local function createPlayerFunctions(self)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function self.canCarryItem(item, count)
|
function self.canCarryItem(item, count)
|
||||||
return exports.ox_inventory:CanCarryItem(self.source, item, count)
|
return GetResourceState("ox_inventory") == "started" and exports.ox_inventory:CanCarryItem(self.source, item, count)
|
||||||
end
|
end
|
||||||
|
|
||||||
function self.canSwapItem(firstItem, firstItemCount, testItem, testItemCount)
|
function self.canSwapItem(firstItem, firstItemCount, testItem, testItemCount)
|
||||||
exports.ox_inventory:CanSwapItem(self.source, firstItem, firstItemCount, testItem, testItemCount)
|
return GetResourceState("ox_inventory") == "started" and exports.ox_inventory:CanSwapItem(self.source, firstItem, firstItemCount, testItem, testItemCount)
|
||||||
end
|
end
|
||||||
|
|
||||||
function self.clearMeta(index)
|
function self.clearMeta(index)
|
||||||
@@ -137,7 +138,7 @@ local function createPlayerFunctions(self)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function self.getInventory(minimal)
|
function self.getInventory(minimal)
|
||||||
local playerItems = exports.ox_inventory:GetInventoryItems(self.source)
|
local playerItems = GetResourceState("ox_inventory") == "started" and exports.ox_inventory:GetInventoryItems(self.source) or {}
|
||||||
if not minimal then
|
if not minimal then
|
||||||
return playerItems
|
return playerItems
|
||||||
end
|
end
|
||||||
@@ -145,7 +146,7 @@ local function createPlayerFunctions(self)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function self.getInventoryItem(item)
|
function self.getInventoryItem(item)
|
||||||
local playerItems = exports.ox_inventory:GetInventoryItems(self.source)
|
local playerItems = GetResourceState("ox_inventory") == "started" and exports.ox_inventory:GetInventoryItems(self.source) or {}
|
||||||
for name, data in pairs(playerItems) do
|
for name, data in pairs(playerItems) do
|
||||||
if name == item then
|
if name == item then
|
||||||
return data
|
return data
|
||||||
@@ -162,11 +163,11 @@ local function createPlayerFunctions(self)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function self.hasItem(item, metadata)
|
function self.hasItem(item, metadata)
|
||||||
return exports.ox_inventory:GetItem(self.source, item, metadata)
|
return GetResourceState("ox_inventory") == "started" and exports.ox_inventory:GetItem(self.source, item, metadata)
|
||||||
end
|
end
|
||||||
|
|
||||||
function self.removeInventoryItem(item, count)
|
function self.removeInventoryItem(item, count)
|
||||||
exports.ox_inventory:RemoveItem(self.source, item, count)
|
return GetResourceState("ox_inventory") == "started" and exports.ox_inventory:RemoveItem(self.source, item, count)
|
||||||
end
|
end
|
||||||
|
|
||||||
function self.removeMoney(amount)
|
function self.removeMoney(amount)
|
||||||
@@ -304,7 +305,8 @@ end
|
|||||||
function NDCore.GetItemLabel(item)
|
function NDCore.GetItemLabel(item)
|
||||||
if not itemNames then
|
if not itemNames then
|
||||||
itemNames = {}
|
itemNames = {}
|
||||||
for item, data in pairs(exports.ox_inventory:Items()) do
|
local items = GetResourceState("ox_inventory") == "started" and exports.ox_inventory:Items() or {}
|
||||||
|
for item, data in pairs(items) do
|
||||||
itemNames[item] = data.label
|
itemNames[item] = data.label
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ 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',
|
||||||
`groups` LONGTEXT DEFAULT '[]',
|
`phonenumber` VARCHAR(20) DEFAULT NULL,
|
||||||
`metadata` LONGTEXT DEFAULT '[]',
|
`groups` LONGTEXT DEFAULT ('[]'),
|
||||||
`inventory` LONGTEXT DEFAULT '[]',
|
`metadata` LONGTEXT DEFAULT ('[]'),
|
||||||
|
`inventory` LONGTEXT DEFAULT ('[]'),
|
||||||
PRIMARY KEY (`charid`) USING BTREE
|
PRIMARY KEY (`charid`) USING BTREE
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ CREATE TABLE IF NOT EXISTS `nd_vehicles` (
|
|||||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||||
`owner` INT(11) DEFAULT NULL,
|
`owner` INT(11) DEFAULT NULL,
|
||||||
`plate` VARCHAR(255) DEFAULT NULL,
|
`plate` VARCHAR(255) DEFAULT NULL,
|
||||||
`glovebox` LONGTEXT DEFAULT '[]',
|
`glovebox` LONGTEXT DEFAULT ('[]'),
|
||||||
`trunk` LONGTEXT DEFAULT '[]',
|
`trunk` LONGTEXT DEFAULT ('[]'),
|
||||||
`properties` LONGTEXT DEFAULT '[]',
|
`properties` LONGTEXT DEFAULT ('[]'),
|
||||||
`stored` INT(11) DEFAULT '1',
|
`stored` INT(11) DEFAULT '1',
|
||||||
`impounded` INT(11) DEFAULT '0',
|
`impounded` INT(11) DEFAULT '0',
|
||||||
`stolen` INT(11) DEFAULT '0',
|
`stolen` INT(11) DEFAULT '0',
|
||||||
`metadata` LONGTEXT DEFAULT '[]',
|
`metadata` LONGTEXT DEFAULT ('[]'),
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
INDEX `owner` (`owner`) USING BTREE,
|
INDEX `owner` (`owner`) USING BTREE,
|
||||||
CONSTRAINT `vehowner` FOREIGN KEY (`owner`) REFERENCES `nd_characters` (`charid`) ON UPDATE CASCADE ON DELETE CASCADE
|
CONSTRAINT `vehowner` FOREIGN KEY (`owner`) REFERENCES `nd_characters` (`charid`) ON UPDATE CASCADE ON DELETE CASCADE
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
author "Andyyy#7666"
|
author "Andyyy#7666"
|
||||||
description "ND Framework Core"
|
description "ND Framework Core"
|
||||||
version "2.0.0"
|
version "2.1.2"
|
||||||
|
|
||||||
fx_version "cerulean"
|
fx_version "cerulean"
|
||||||
game "gta5"
|
game "gta5"
|
||||||
@@ -38,5 +38,7 @@ files {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependency "oxmysql"
|
dependency "oxmysql"
|
||||||
|
|
||||||
|
-- below were used with backwards compatibility but could interfere with resources checking if the resources are started.
|
||||||
-- provide "es_extended"
|
-- provide "es_extended"
|
||||||
-- provide "qb-Core"
|
-- provide "qb-Core"
|
||||||
|
|||||||
@@ -194,27 +194,50 @@ end)
|
|||||||
lib.addCommand("pay", {
|
lib.addCommand("pay", {
|
||||||
help = "give money to nearby player.",
|
help = "give money to nearby player.",
|
||||||
params = {
|
params = {
|
||||||
|
{
|
||||||
|
name = "target",
|
||||||
|
type = "playerId",
|
||||||
|
help = "Target player's server id"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name = "amount",
|
name = "amount",
|
||||||
type = "number"
|
type = "number",
|
||||||
|
help = "Amount of cash to give"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, function(source, args, raw)
|
}, function(source, args, raw)
|
||||||
if not source then return end
|
if not source then return end
|
||||||
local targetPlayer
|
|
||||||
local pedCoords = GetEntityCoords(GetPlayerPed(source))
|
|
||||||
for targetId, targetInfo in pairs(NDCore.players) do
|
|
||||||
local targetCoords = GetEntityCoords(GetPlayerPed(targetId))
|
|
||||||
if #(pedCoords-targetCoords) < 2.0 and targetId ~= source then
|
|
||||||
targetPlayer = targetInfo
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local player = NDCore.getPlayer(source)
|
local player = NDCore.getPlayer(source)
|
||||||
if not player then return end
|
local targetPlayer = NDCore.getPlayer(args.target)
|
||||||
local success = player.deductMoney("cash", args.amount)
|
|
||||||
|
|
||||||
|
if not player or not targetPlayer then
|
||||||
|
return player.notify({
|
||||||
|
title = "Error",
|
||||||
|
description = "No player found",
|
||||||
|
type = "error"
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if player.cash < args.amount then
|
||||||
|
return player.notify({
|
||||||
|
title = "Error",
|
||||||
|
description = "You don't have enough cash",
|
||||||
|
type = "error"
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
local playerCoords = GetEntityCoords(GetPlayerPed(player.source))
|
||||||
|
local targetCoords = GetEntityCoords(GetPlayerPed(targetPlayer.source))
|
||||||
|
if #(playerCoords-targetCoords) > 2.0 then
|
||||||
|
return player.notify({
|
||||||
|
title = "Error",
|
||||||
|
description = "Player is not nearby",
|
||||||
|
type = "error"
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
local success = player.deductMoney("cash", args.amount) and targetPlayer.addMoney("cash", args.amount)
|
||||||
if not success then
|
if not success then
|
||||||
return player.notify({
|
return player.notify({
|
||||||
title = "Couldn't give money",
|
title = "Couldn't give money",
|
||||||
@@ -223,24 +246,23 @@ lib.addCommand("pay", {
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
if not targetPlayer or not targetPlayer.addMoney("cash", args.amount) then return end
|
|
||||||
targetPlayer.notify({
|
targetPlayer.notify({
|
||||||
title = "Money received",
|
title = "Money received",
|
||||||
description = ("Received $%d in cash"):format(args.amount),
|
description = ("Received $%d in cash"):format(args.amount),
|
||||||
type = "inform",
|
type = "inform",
|
||||||
duration = 10000
|
duration = 5000
|
||||||
})
|
})
|
||||||
|
|
||||||
player.notify({
|
player.notify({
|
||||||
title = "Money given",
|
title = "Money given",
|
||||||
description = ("You gave someone $%d in cash"):format(args.amount),
|
description = ("You gave $%d in cash"):format(args.amount),
|
||||||
type = "inform",
|
type = "inform",
|
||||||
duration = 10000
|
duration = 5000
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
lib.addCommand("unlock", {
|
lib.addCommand("unlock", {
|
||||||
help = "Admin force unlock vehicles",
|
help = "Admin Command, force unlock vehicle.",
|
||||||
restricted = "group.admin",
|
restricted = "group.admin",
|
||||||
}, function(source, args, raw)
|
}, function(source, args, raw)
|
||||||
local ped = GetPlayerPed(source)
|
local ped = GetPlayerPed(source)
|
||||||
@@ -287,13 +309,13 @@ lib.addCommand("revive", {
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
lib.addCommand("dv", {
|
lib.addCommand("dv", {
|
||||||
help = "Admin command, delete vehicles within the range.",
|
help = "Admin command, delete vehicles within the range or the closest.",
|
||||||
restricted = "group.admin",
|
restricted = "group.admin",
|
||||||
params = {
|
params = {
|
||||||
{
|
{
|
||||||
name = "range",
|
name = "range",
|
||||||
type = "number",
|
type = "number",
|
||||||
help = "The range to select vehicles for deleteion from",
|
help = "Range to delete vehicles in",
|
||||||
optional = true
|
optional = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,13 @@ function NDCore.getPlayerServerInfo(source)
|
|||||||
return PlayersInfo[source]
|
return PlayersInfo[source]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function NDCore.getConfig(info)
|
||||||
|
if not info then
|
||||||
|
return Config
|
||||||
|
end
|
||||||
|
return Config[info]
|
||||||
|
end
|
||||||
|
|
||||||
---@param fileLocation string|tabale
|
---@param fileLocation string|tabale
|
||||||
---@return boolean
|
---@return boolean
|
||||||
function NDCore.loadSQL(fileLocation, resource)
|
function NDCore.loadSQL(fileLocation, resource)
|
||||||
|
|||||||
@@ -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"),
|
||||||
@@ -46,8 +47,9 @@ end
|
|||||||
|
|
||||||
AddEventHandler("playerJoining", function(oldId)
|
AddEventHandler("playerJoining", function(oldId)
|
||||||
local src = source
|
local src = source
|
||||||
PlayersInfo[src] = tempPlayersInfo[oldId]
|
local oldTempId = tonumber(oldId)
|
||||||
tempPlayersInfo[oldId] = nil
|
PlayersInfo[src] = tempPlayersInfo[oldTempId]
|
||||||
|
tempPlayersInfo[oldTempId] = nil
|
||||||
|
|
||||||
if Config.multiCharacter then return end
|
if Config.multiCharacter then return end
|
||||||
Wait(3000)
|
Wait(3000)
|
||||||
@@ -93,14 +95,14 @@ AddEventHandler("playerConnecting", function(name, setKickReason, deferrals)
|
|||||||
local tempSrc = source
|
local tempSrc = source
|
||||||
local identifiers = getIdentifierList(tempSrc)
|
local identifiers = getIdentifierList(tempSrc)
|
||||||
local mainIdentifier = identifiers[Config.characterIdentifier]
|
local mainIdentifier = identifiers[Config.characterIdentifier]
|
||||||
local discordInfo = {}
|
local discordInfo = nil
|
||||||
|
|
||||||
deferrals.defer()
|
deferrals.defer()
|
||||||
Wait(0)
|
Wait(0)
|
||||||
|
|
||||||
if mainIdentifier and Config.discordBotToken ~= "false" and Config.discordGuildId ~= "false" and not discordInfo 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
|
||||||
@@ -152,3 +154,10 @@ RegisterNetEvent("ND:playerEliminated", function(info)
|
|||||||
deathInfo = info
|
deathInfo = info
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent("ND::updateClothing", function(clothing)
|
||||||
|
local src = source
|
||||||
|
local player = NDCore.getPlayer(src)
|
||||||
|
if not player or not clothing or type(clothing) ~= "table" then return end
|
||||||
|
player.setMetadata("clothing", clothing)
|
||||||
|
end)
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -113,6 +114,7 @@ local function createCharacterTable(info)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.triggerEvent("ND:updateCharacter", removeCharacterFunctions(self))
|
self.triggerEvent("ND:updateCharacter", removeCharacterFunctions(self))
|
||||||
|
TriggerEvent("ND:updateCharacter", self)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param key string|table
|
---@param key string|table
|
||||||
@@ -127,6 +129,7 @@ local function createCharacterTable(info)
|
|||||||
self.metadata[key] = value
|
self.metadata[key] = value
|
||||||
end
|
end
|
||||||
self.triggerEvent("ND:updateCharacter", removeCharacterFunctions(self))
|
self.triggerEvent("ND:updateCharacter", removeCharacterFunctions(self))
|
||||||
|
TriggerEvent("ND:updateCharacter", self)
|
||||||
return self.metadata
|
return self.metadata
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -164,8 +167,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 +191,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
|
||||||
@@ -207,6 +226,7 @@ local function createCharacterTable(info)
|
|||||||
self.metadata.licenses = {license}
|
self.metadata.licenses = {license}
|
||||||
end
|
end
|
||||||
self.triggerEvent("ND:updateCharacter", removeCharacterFunctions(self))
|
self.triggerEvent("ND:updateCharacter", removeCharacterFunctions(self))
|
||||||
|
TriggerEvent("ND:updateCharacter", self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function self.getLicense(identifier)
|
function self.getLicense(identifier)
|
||||||
@@ -252,11 +272,7 @@ local function createCharacterTable(info)
|
|||||||
|
|
||||||
function self.notify(...)
|
function self.notify(...)
|
||||||
if not self.source then return end
|
if not self.source then return end
|
||||||
if GetResourceState("ModernHUD") == "started" then
|
|
||||||
TriggerClientEvent("ModernHUD:notify", self.source, ...)
|
|
||||||
elseif GetResourceState("ox_lib") == "started" then
|
|
||||||
TriggerClientEvent("ox_lib:notify", self.source, ...)
|
TriggerClientEvent("ox_lib:notify", self.source, ...)
|
||||||
end
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -309,21 +325,32 @@ local function createCharacterTable(info)
|
|||||||
---@return boolean
|
---@return boolean
|
||||||
function self.addGroup(name, rank, isJob)
|
function self.addGroup(name, rank, isJob)
|
||||||
local groupRank = tonumber(rank) or 1
|
local groupRank = tonumber(rank) or 1
|
||||||
local groupInfo = Config.groups[name]
|
local groupInfo = Config.groups?[name]
|
||||||
|
local bossRank = groupInfo and groupInfo.minimumBossRank
|
||||||
|
|
||||||
-- if not groupInfo then return end
|
-- if not groupInfo then return end
|
||||||
if isJob then
|
if isJob then
|
||||||
for _, group in pairs(self.groups) do
|
for _, group in pairs(self.groups) do
|
||||||
group.isJob = nil
|
group.isJob = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self.groups[name] = {
|
self.groups[name] = {
|
||||||
|
name = name,
|
||||||
label = groupInfo and groupInfo.label or name,
|
label = groupInfo and groupInfo.label or name,
|
||||||
rankName = groupInfo and groupInfo.ranks[groupRank] or groupRank,
|
rankName = groupInfo and groupInfo.ranks[groupRank] or groupRank,
|
||||||
rank = groupRank,
|
rank = groupRank,
|
||||||
isJob = isJob
|
isJob = isJob,
|
||||||
|
isBoss = bossRank and groupRank >= bossRank
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if not isJob then
|
||||||
self.triggerEvent("ND:updateCharacter", removeCharacterFunctions(self))
|
self.triggerEvent("ND:updateCharacter", removeCharacterFunctions(self))
|
||||||
|
TriggerEvent("ND:updateCharacter", self)
|
||||||
|
end
|
||||||
|
|
||||||
lib.addPrincipal(self.source, ("group.%s"):format(name))
|
lib.addPrincipal(self.source, ("group.%s"):format(name))
|
||||||
|
|
||||||
return self.groups[name]
|
return self.groups[name]
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -337,8 +364,15 @@ local function createCharacterTable(info)
|
|||||||
function self.removeGroup(name)
|
function self.removeGroup(name)
|
||||||
local group = self.groups[name]
|
local group = self.groups[name]
|
||||||
if not group then return end
|
if not group then return end
|
||||||
|
|
||||||
|
if self.job == name then
|
||||||
|
self.job = nil
|
||||||
|
self.jobInfo = nil
|
||||||
|
end
|
||||||
|
|
||||||
self.groups[name] = nil
|
self.groups[name] = nil
|
||||||
self.triggerEvent("ND:updateCharacter", removeCharacterFunctions(self))
|
self.triggerEvent("ND:updateCharacter", removeCharacterFunctions(self))
|
||||||
|
TriggerEvent("ND:updateCharacter", self)
|
||||||
lib.removePrincipal(self.source, ("group.%s"):format(name))
|
lib.removePrincipal(self.source, ("group.%s"):format(name))
|
||||||
return group
|
return group
|
||||||
end
|
end
|
||||||
@@ -349,11 +383,12 @@ local function createCharacterTable(info)
|
|||||||
function self.setJob(name, rank)
|
function self.setJob(name, rank)
|
||||||
self.removeGroup(self.job)
|
self.removeGroup(self.job)
|
||||||
local job = self.addGroup(name, rank, true)
|
local job = self.addGroup(name, rank, true)
|
||||||
local jobName, jobInfo = self.getJob()
|
if job then
|
||||||
if jobInfo then
|
self.job = job.name
|
||||||
self.job = jobName
|
self.jobInfo = job
|
||||||
self.jobInfo = jobInfo
|
|
||||||
end
|
end
|
||||||
|
self.triggerEvent("ND:updateCharacter", removeCharacterFunctions(self))
|
||||||
|
TriggerEvent("ND:updateCharacter", self)
|
||||||
return job
|
return job
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -393,12 +428,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, inventory) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", {
|
||||||
identifier,
|
identifier,
|
||||||
charInfo.name,
|
charInfo.name,
|
||||||
charInfo.firstname,
|
charInfo.firstname,
|
||||||
@@ -407,8 +443,10 @@ 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),
|
||||||
|
json.encode(charInfo.inventory)
|
||||||
})
|
})
|
||||||
|
|
||||||
return createCharacterTable(charInfo)
|
return createCharacterTable(charInfo)
|
||||||
@@ -437,6 +475,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)
|
||||||
@@ -462,9 +501,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
|
||||||
|
|||||||
@@ -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
|
||||||
})
|
})
|
||||||
@@ -567,12 +591,24 @@ RegisterNetEvent("ND_Vehicles:toggleVehicleLock", function(netId)
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
-- locking of npc vehicles, if the players spawns inside a vehicle it won't be locked.
|
-- locking of npc vehicles, if the players spawns inside a vehicle it won't be locked.
|
||||||
RegisterNetEvent("entityCreated", function(entity)
|
AddEventHandler("entityCreated", function(entity)
|
||||||
|
local time = os.time()
|
||||||
|
while not DoesEntityExist(entity) and os.time()-time < 5 do Wait(50) end
|
||||||
|
|
||||||
if not DoesEntityExist(entity) or GetEntityType(entity) ~= 2 then return end
|
if not DoesEntityExist(entity) or GetEntityType(entity) ~= 2 then return end
|
||||||
|
|
||||||
local state = Entity(entity).state
|
local state = Entity(entity).state
|
||||||
if state.owner or state.locked ~= nil then return end
|
if state.owner or state.locked ~= nil then return end
|
||||||
|
|
||||||
|
time = os.time()
|
||||||
local driver = GetPedInVehicleSeat(entity, -1)
|
local driver = GetPedInVehicleSeat(entity, -1)
|
||||||
|
while DoesEntityExist(entity) and driver == 0 and os.time()-time < 2 do
|
||||||
|
driver = GetPedInVehicleSeat(entity, -1)
|
||||||
|
Wait(100)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not DoesEntityExist(entity) then return end
|
||||||
|
|
||||||
if DoesEntityExist(driver) and IsPedAPlayer(driver) then
|
if DoesEntityExist(driver) and IsPedAPlayer(driver) then
|
||||||
state.locked = false
|
state.locked = false
|
||||||
state.hotwired = true
|
state.hotwired = true
|
||||||
@@ -694,3 +730,30 @@ lib.callback.register("ND_Vehicles:getOwnedVehicles", function(src)
|
|||||||
if not player then return end
|
if not player then return end
|
||||||
return NDCore.getVehicles(player.id)
|
return NDCore.getVehicles(player.id)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
AddEventHandler("ND:characterLoaded", function(player)
|
||||||
|
local ownedExistingVehicles = {}
|
||||||
|
local ownedVehicles = NDCore.getVehicles(player.id)
|
||||||
|
local vehicles = GetAllVehicles()
|
||||||
|
local vehiclesToImpound = {}
|
||||||
|
|
||||||
|
for i=1, #vehicles do
|
||||||
|
local veh = vehicles[i]
|
||||||
|
local state = Entity(veh).state
|
||||||
|
if state.owner == player.id then
|
||||||
|
ownedExistingVehicles[#ownedExistingVehicles+1] = state.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for i=1, #ownedVehicles do
|
||||||
|
local veh = ownedVehicles[i]
|
||||||
|
if veh and not veh.stored and not veh.impounded and not lib.table.contains(ownedExistingVehicles, veh.id) then
|
||||||
|
vehiclesToImpound[#vehiclesToImpound+1] = veh.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #vehiclesToImpound == 0 then return end
|
||||||
|
|
||||||
|
local query = ("UPDATE nd_vehicles SET impounded = ? WHERE owner = ? AND id IN (%s)"):format(table.concat(vehiclesToImpound, ", "))
|
||||||
|
MySQL.rawExecute(query, {1, player.id})
|
||||||
|
end)
|
||||||
|
|||||||
Reference in New Issue
Block a user