mirror of
https://github.com/ND-Framework/ND_Core.git
synced 2026-08-16 21:46:03 +01:00
refactor(vehicles): move garages to separate resource keep api
- Moved traffic locking to client - removed garages (moved to ND_Garages resource) - optimized and improved the api - fixed smaller bugs
This commit is contained in:
@@ -242,30 +242,36 @@ local function getVehicleBlipSprite(entity)
|
||||
end
|
||||
|
||||
local function getVehFromNetId(netId)
|
||||
local time = GetCloudTimeAsInt()
|
||||
while not NetworkDoesNetworkIdExist(netId) or not NetworkDoesEntityExistWithNetworkId(netId) and time-GetCloudTimeAsInt() < 5 do
|
||||
local startTime = GetCloudTimeAsInt()
|
||||
while (not NetworkDoesNetworkIdExist(netId) or not NetworkDoesEntityExistWithNetworkId(netId)) and (GetCloudTimeAsInt() - startTime < 5) do
|
||||
Wait(100)
|
||||
end
|
||||
return NetToVeh(netId)
|
||||
end
|
||||
|
||||
RegisterNetEvent("ND_Vehicles:blip", function(netId, status)
|
||||
local veh = getVehFromNetId(netId)
|
||||
if not veh then return end
|
||||
if not status then
|
||||
local blip = GetBlipFromEntity(veh)
|
||||
if not blip or not DoesBlipExist(blip) then return end
|
||||
return RemoveBlip(blip)
|
||||
|
||||
local function setVehicleBlip(veh, status, groupVehicle)
|
||||
local currentBlip = GetBlipFromEntity(veh)
|
||||
if currentBlip and DoesBlipExist(currentBlip) then
|
||||
RemoveBlip(currentBlip)
|
||||
end
|
||||
|
||||
if not status then return end
|
||||
|
||||
local blip = AddBlipForEntity(veh)
|
||||
SetBlipSprite(blip, getVehicleBlipSprite(veh))
|
||||
SetBlipColour(blip, 0)
|
||||
SetBlipScale(blip, 0.8)
|
||||
SetBlipAsShortRange(blip, true)
|
||||
BeginTextCommandSetBlipName("STRING")
|
||||
AddTextComponentSubstringPlayerName(locale("personal_vehicle"))
|
||||
AddTextComponentSubstringPlayerName(groupVehicle and locale("group_vehicle") or locale("personal_vehicle"))
|
||||
EndTextCommandSetBlipName(blip)
|
||||
end
|
||||
|
||||
RegisterNetEvent("ND_Vehicles:blip", function(netId, status, groupVehicle)
|
||||
local veh = getVehFromNetId(netId)
|
||||
if not veh then return end
|
||||
setVehicleBlip(veh, status, groupVehicle)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("ND_Vehicles:syncAlarm", function(netId)
|
||||
@@ -284,13 +290,39 @@ RegisterNetEvent("ND_VehicleSystem:setOwnedIfNot", function(netId)
|
||||
end)
|
||||
|
||||
AddStateBagChangeHandler("props", nil, function(bagName, key, value, reserved, replicated)
|
||||
local entity = GetEntityFromStateBagName(bagName)
|
||||
if not value or not DoesEntityExist(entity) or NetworkGetEntityOwner(entity) ~= cache.playerId then return end
|
||||
if not value then return end
|
||||
|
||||
local props = value
|
||||
if type(value) == "string" then
|
||||
props = json.decode(value)
|
||||
end
|
||||
|
||||
if not props or type(props) ~= "table" then return end
|
||||
|
||||
local entity = GetEntityFromStateBagName(bagName)
|
||||
if not DoesEntityExist(entity) or NetworkGetEntityOwner(entity) ~= cache.playerId then return end
|
||||
|
||||
lib.setVehicleProperties(entity, props)
|
||||
TriggerServerEvent("ND_Vehicles:propsApplied", DoesEntityExist(entity) and NetworkGetNetworkIdFromEntity(entity))
|
||||
end)
|
||||
|
||||
local function hasBlipGroup(player, groups)
|
||||
groups = groups or {}
|
||||
for i=1, #groups do
|
||||
local group = groups[i]
|
||||
if player.groups[group] then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
AddStateBagChangeHandler("blipGroups", nil, function(bagName, key, value, reserved, replicated)
|
||||
local entity = GetEntityFromStateBagName(bagName)
|
||||
if not value or not DoesEntityExist(entity) then return end
|
||||
|
||||
local player = NDCore.getPlayer()
|
||||
if not player then return end
|
||||
setVehicleBlip(entity, hasBlipGroup(player, value), true)
|
||||
end)
|
||||
|
||||
local playingKey = 0
|
||||
@@ -411,6 +443,17 @@ local function hasVehicleKeys(veh, checkEngine)
|
||||
return hasKey or checkEngine and state.hotwired
|
||||
end
|
||||
|
||||
AddStateBagChangeHandler("owner", nil, function(bagName, key, value, reserved, replicated)
|
||||
local entity = GetEntityFromStateBagName(bagName)
|
||||
if not value or not DoesEntityExist(entity) or GetEntityType(entity) ~= 2 then return end
|
||||
|
||||
local player = NDCore.getPlayer()
|
||||
if not player or player.id ~= value then return end
|
||||
|
||||
local hasKey = hasVehicleKeys(entity)
|
||||
setVehicleBlip(entity, hasKey)
|
||||
end)
|
||||
|
||||
local function hasVehicleKeysCheck(veh)
|
||||
local time = GetCloudTimeAsInt()
|
||||
if time-keyCheckTime.lastCheck < 5 then
|
||||
@@ -526,6 +569,33 @@ CreateThread(function()
|
||||
end
|
||||
end)
|
||||
|
||||
CreateThread(function()
|
||||
while true do
|
||||
Wait(100)
|
||||
local veh = cache.vehicle
|
||||
if veh then goto skip end
|
||||
|
||||
local ped = cache.ped
|
||||
local vehEntering = GetVehiclePedIsEntering(ped)
|
||||
if not DoesEntityExist(vehEntering) or NetworkGetEntityOwner(vehEntering) == cache.serverId then goto skip end
|
||||
|
||||
local state = Entity(vehEntering).state
|
||||
if state.owner or state.locked ~= nil then goto skip end
|
||||
|
||||
local driver = GetPedInVehicleSeat(vehEntering, -1)
|
||||
if DoesEntityExist(driver) and IsPedAPlayer(driver) then
|
||||
state.locked = false
|
||||
state.hotwired = true
|
||||
goto skip
|
||||
end
|
||||
|
||||
if math.random(1, 100) <= Config.randomUnlockedVehicleChance then return end
|
||||
state.locked = true
|
||||
|
||||
::skip::
|
||||
end
|
||||
end)
|
||||
|
||||
local function hotwireVehicle()
|
||||
local state = playerVehicle and Entity(playerVehicle).state
|
||||
if not playerVehicle or state.hotwired then return end
|
||||
@@ -597,6 +667,17 @@ local function lockpickVehicle()
|
||||
local veh = lib.getClosestVehicle(pos, 2.5, false)
|
||||
if not veh then return end
|
||||
|
||||
local lockPickResource = GetResourceState("lockpick") == "started" and "lockpick" or GetResourceState("t3_lockpick") == "started" and "t3_lockpick"
|
||||
if lockPickResource then
|
||||
local success = exports[lockPickResource]:startLockpick("lockpick_vehicle", 4, Config.lockpickTries)
|
||||
if not success or not DoesEntityExist(veh) or #(pos-GetEntityCoords(veh)) > 2.5 then
|
||||
TriggerServerEvent("ND_Vehicles:lockpick", VehToNet(veh), false)
|
||||
if success == nil then -- nil would mean the minigame was cancelled
|
||||
return false, false
|
||||
end
|
||||
return false, true
|
||||
end
|
||||
else
|
||||
local dificulties = {
|
||||
"easy",
|
||||
"medium",
|
||||
@@ -619,12 +700,18 @@ local function lockpickVehicle()
|
||||
end
|
||||
Wait(dificultyTime[dificulty])
|
||||
end
|
||||
end
|
||||
|
||||
veh = lib.getClosestVehicle(pos, 2.5, false)
|
||||
if not veh then return false, true end
|
||||
TriggerServerEvent("ND_Vehicles:lockpick", VehToNet(veh), true)
|
||||
PlaySoundFromEntity(-1, "Remote_Control_Fob", cache.ped, "PI_Menu_Sounds", true, 0)
|
||||
|
||||
if lockPickResource then
|
||||
return true, false
|
||||
else
|
||||
return true, true
|
||||
end
|
||||
end
|
||||
|
||||
exports("lockpick", function(data, slot)
|
||||
@@ -1,301 +0,0 @@
|
||||
return {
|
||||
{
|
||||
garageType = "land",
|
||||
groups = {"lsfd"},
|
||||
ped = vector4(370.9027, -593.8090, 28.8681, 73.6009),
|
||||
vehicleSpawns = {
|
||||
vec4(366.7840, -591.4883, 28.7261, 339.6823),
|
||||
vec4(365.0753, -582.8641, 28.7156, 135.0064),
|
||||
vec4(357.4239, -604.7719, 28.6767, 177.1355),
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "land",
|
||||
groups = {"sahp", "lspd", "bcso"},
|
||||
ped = vector4(452.83, -1027.79, 28.54, 2.49),
|
||||
vehicleSpawns = {
|
||||
vector4(446.19, -1025.47, 28.24, 185.96),
|
||||
vector4(438.75, -1026.09, 28.38, 184.29),
|
||||
vector4(434.98, -1026.61, 28.46, 185.99),
|
||||
vector4(431.26, -1027.31, 28.53, 185.59),
|
||||
vector4(427.52, -1026.84, 28.58, 184.25)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "land",
|
||||
impound = true,
|
||||
ped = vector4(407.99, -1624.74, 29.29, 229.93),
|
||||
vehicleSpawns = {
|
||||
vector4(396.34, -1644.28, 28.86, 319.10),
|
||||
vector4(398.56, -1646.42, 28.8616, 319.18),
|
||||
vector4(400.68, -1648.86, 28.86, 140.78),
|
||||
vector4(403.32, -1650.54, 28.86, 319.92),
|
||||
vector4(403.21, -1650.68, 28.86, 139.40)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "plane",
|
||||
ped = vector4(-941.05, -2966.04, 13.95, 136.06),
|
||||
vehicleSpawns = {
|
||||
vector4(-974.98, -2977.90, 14.55, 59.91)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "heli",
|
||||
ped = vector4(-731.00, -1394.54, 5.00, 245.52),
|
||||
vehicleSpawns = {
|
||||
vector4(-746.01, -1469.39, 5.68, 139.27),
|
||||
vector4(-725.26, -1444.72, 5.68, 139.58)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "plane",
|
||||
ped = vector4(1742.77, 3298.25, 41.22, 132.91),
|
||||
vehicleSpawns = {
|
||||
vector4(1734.26, 3250.98, 41.96, 81.11),
|
||||
vector4(1729.32, 3270.69, 41.74, 145.39)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "plane",
|
||||
ped = vector4(-1241.26, -3391.48, 13.94, 35.03),
|
||||
vehicleSpawns = {
|
||||
vector4(-1254.71, -3388.15, 14.54, 330.04),
|
||||
vector4(-1270.36, -3378.80, 14.54, 330.20),
|
||||
vector4(-1286.05, -3369.44, 14.54, 329.99)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "plane",
|
||||
ped = vector4(-1621.10, -3151.63, 13.99, 41.26),
|
||||
vehicleSpawns = {
|
||||
vector4(-1634.04, -3147.84, 14.60, 330.28),
|
||||
vector4(-1649.75, -3138.34, 14.60, 329.20),
|
||||
vector4(-1665.42, -3129.26, 14.60, 330.10)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "heli",
|
||||
ped = vector4(-1121.87, -2839.88, 13.95, 150.58),
|
||||
vehicleSpawns = {
|
||||
vector4(-1178.71, -2846.51, 14.62, 150.16),
|
||||
vector4(-1146.40, -2865.22, 14.62, 151.08),
|
||||
vector4(-1112.85, -2884.66, 14.62, 149.70)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "water",
|
||||
ped = vector4(-831.03, -1359.53, 5.00, 299.80),
|
||||
vehicleSpawns = {
|
||||
vector4(-846.16, -1362.07, 0.39, 110.54),
|
||||
vector4(-842.53, -1372.00, 0.39, 111.54),
|
||||
vector4(-849.29, -1353.26, 0.38, 109.53),
|
||||
vector4(-852.26, -1345.09, 0.41, 110.52),
|
||||
vector4(-855.49, -1336.60, 0.40, 107.43),
|
||||
vector4(-858.63, -1328.30, 0.40, 109.82),
|
||||
vector4(-839.35, -1380.30, 0.39, 109.27),
|
||||
vector4(-836.38, -1388.93, 0.41, 110.11),
|
||||
vector4(-833.29, -1397.32, 0.40, 110.80),
|
||||
vector4(-830.34, -1405.65, 0.37, 110.16)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "land",
|
||||
ped = vector4(-280.32, -888.42, 31.32, 250.68),
|
||||
vehicleSpawns = {
|
||||
vector4(-282.36, -915.11, 30.38, 68.81),
|
||||
vector4(-284.27, -918.37, 30.38, 70.58),
|
||||
vector4(-285.44, -921.82, 30.38, 250.22),
|
||||
vector4(-285.70, -887.62, 30.38, 167.04),
|
||||
vector4(-292.70, -885.93, 30.38, 167.09),
|
||||
vector4(-285.76, -887.47, 30.38, 169.59),
|
||||
vector4(-300.44, -885.14, 30.38, 347.05),
|
||||
vector4(-303.59, -883.71, 30.38, 167.69),
|
||||
vector4(-309.38, -896.88, 30.38, 167.15),
|
||||
vector4(-312.98, -896.30, 30.38, 166.46),
|
||||
vector4(-316.68, -896.26, 30.37, 347.94),
|
||||
vector4(-311.06, -881.94, 30.38, 168.21),
|
||||
vector4(-314.78, -881.86, 30.37, 348.45)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "land",
|
||||
ped = vector4(597.53, 91.08, 93.13, 250.54),
|
||||
vehicleSpawns = {
|
||||
vector4(598.53, 98.37, 92.27, 69.47),
|
||||
vector4(599.79, 102.00, 92.27, 249.38),
|
||||
vector4(608.21, 103.90, 92.18, 248.98),
|
||||
vector4(600.60, 111.38, 92.27, 73.07),
|
||||
vector4(609.91, 107.59, 92.23, 68.77),
|
||||
vector4(601.36, 114.99, 92.27, 250.19),
|
||||
vector4(611.07, 111.39, 92.29, 249.69),
|
||||
vector4(603.52, 118.52, 92.26, 67.62),
|
||||
vector4(612.74, 114.94, 92.28, 69.01),
|
||||
vector4(604.00, 122.58, 92.27, 249.76),
|
||||
vector4(613.78, 118.83, 92.29, 248.82),
|
||||
vector4(622.43, 115.48, 91.99, 70.39),
|
||||
vector4(628.56, 110.25, 91.47, 249.30),
|
||||
vector4(620.67, 111.89, 92.03, 250.24),
|
||||
vector4(618.41, 104.51, 91.97, 72.22),
|
||||
vector4(624.87, 99.25, 91.36, 63.32),
|
||||
vector4(616.59, 100.82, 91.97, 249.00)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "land",
|
||||
ped = vector4(100.64, -1072.88, 29.37, 341.55),
|
||||
vehicleSpawns = {
|
||||
vector4(106.13, -1063.24, 28.51, 66.86),
|
||||
vector4(107.82, -1059.73, 28.51, 66.99),
|
||||
vector4(112.39, -1049.71, 28.52, 67.40),
|
||||
vector4(110.76, -1053.09, 28.51, 68.13),
|
||||
vector4(109.06, -1056.38, 28.51, 66.45),
|
||||
vector4(117.53, -1081.03, 28.50, 181.40),
|
||||
vector4(119.09, -1069.44, 28.50, 181.12),
|
||||
vector4(121.22, -1081.42, 28.50, 0.57),
|
||||
vector4(122.32, -1070.46, 28.50, 0.67),
|
||||
vector4(125.62, -1069.54, 28.50, 179.25),
|
||||
vector4(124.83, -1081.17, 28.50, 180.37),
|
||||
vector4(128.62, -1081.71, 28.50, 1.36),
|
||||
vector4(128.93, -1070.62, 28.50, 359.89),
|
||||
vector4(132.24, -1069.35, 28.50, 181.54),
|
||||
vector4(132.31, -1081.45, 28.50, 180.86),
|
||||
vector4(135.93, -1081.35, 28.50, 358.82),
|
||||
vector4(135.64, -1070.75, 28.50, 0.43),
|
||||
vector4(139.75, -1081.91, 28.50, 182.18),
|
||||
vector4(138.86, -1070.37, 28.50, 181.90),
|
||||
vector4(143.55, -1081.41, 28.50, 0.89),
|
||||
vector4(147.13, -1081.48, 28.50, 179.02),
|
||||
vector4(150.95, -1081.49, 28.50, 358.79),
|
||||
vector4(154.64, -1081.32, 28.50, 179.51),
|
||||
vector4(158.38, -1082.03, 28.50, 1.57),
|
||||
vector4(162.10, -1081.32, 28.50, 179.88)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "land",
|
||||
ped = vector4(214.84, -806.24, 30.81, 342.23),
|
||||
vehicleSpawns = {
|
||||
vector4(251.26, -774.63, 29.98, 67.34),
|
||||
vector4(245.36, -772.34, 30.02, 66.81),
|
||||
vector4(219.19, -765.93, 30.14, 249.78),
|
||||
vector4(228.11, -768.94, 30.10, 249.66),
|
||||
vector4(233.68, -771.18, 30.07, 249.82),
|
||||
vector4(244.01, -775.06, 29.99, 249.41),
|
||||
vector4(249.53, -777.07, 29.95, 251.09),
|
||||
vector4(248.74, -779.52, 29.92, 69.14),
|
||||
vector4(243.64, -777.63, 29.96, 69.23),
|
||||
vector4(233.47, -773.91, 30.05, 69.88),
|
||||
vector4(218.62, -768.58, 30.14, 69.81),
|
||||
vector4(217.02, -770.83, 30.16, 248.11),
|
||||
vector4(226.09, -773.95, 30.09, 249.30),
|
||||
vector4(231.82, -776.14, 30.04, 249.17),
|
||||
vector4(242.05, -779.91, 29.93, 246.99),
|
||||
vector4(247.72, -782.02, 29.88, 251.04),
|
||||
vector4(216.19, -773.65, 30.16, 67.90),
|
||||
vector4(225.82, -776.85, 30.08, 65.64),
|
||||
vector4(230.77, -778.89, 30.03, 69.40),
|
||||
vector4(241.72, -782.84, 29.90, 69.13),
|
||||
vector4(247.12, -784.93, 29.84, 67.56),
|
||||
vector4(246.23, -787.13, 29.82, 247.56),
|
||||
vector4(239.40, -784.68, 29.90, 248.06),
|
||||
vector4(230.42, -781.41, 30.01, 247.48),
|
||||
vector4(224.14, -779.01, 30.07, 247.39),
|
||||
vector4(215.32, -775.95, 30.17, 248.99),
|
||||
vector4(243.81, -792.19, 29.77, 246.23),
|
||||
vector4(238.08, -789.95, 29.85, 250.62),
|
||||
vector4(228.14, -786.30, 30.01, 249.07),
|
||||
vector4(221.98, -783.92, 30.08, 248.25),
|
||||
vector4(213.41, -781.01, 30.19, 249.21),
|
||||
vector4(214.77, -778.70, 30.17, 67.86),
|
||||
vector4(224.02, -781.91, 30.07, 68.82),
|
||||
vector4(229.34, -784.05, 30.01, 66.57),
|
||||
vector4(239.87, -787.83, 29.86, 69.37),
|
||||
vector4(245.18, -789.87, 29.79, 68.00),
|
||||
vector4(241.85, -797.20, 29.72, 245.51),
|
||||
vector4(236.57, -795.07, 29.82, 247.54),
|
||||
vector4(226.12, -791.34, 29.99, 247.84),
|
||||
vector4(220.61, -789.19, 30.08, 248.09),
|
||||
vector4(212.00, -786.22, 30.21, 248.93),
|
||||
vector4(212.91, -783.71, 30.19, 68.61),
|
||||
vector4(222.11, -786.89, 30.07, 70.10),
|
||||
vector4(227.84, -789.16, 29.99, 67.55),
|
||||
vector4(237.73, -792.73, 29.82, 69.40),
|
||||
vector4(243.54, -794.88, 29.73, 68.74),
|
||||
vector4(237.03, -812.64, 29.59, 243.63),
|
||||
vector4(207.66, -798.70, 30.29, 70.06),
|
||||
vector4(216.56, -801.92, 30.10, 70.31),
|
||||
vector4(222.28, -804.17, 29.98, 69.97),
|
||||
vector4(232.41, -807.95, 29.74, 69.42),
|
||||
vector4(238.16, -810.17, 29.60, 68.95),
|
||||
vector4(238.32, -807.43, 29.63, 248.28),
|
||||
vector4(233.32, -805.44, 29.75, 248.13),
|
||||
vector4(222.46, -801.41, 29.98, 248.50),
|
||||
vector4(216.85, -799.11, 30.10, 248.54),
|
||||
vector4(207.60, -795.90, 30.29, 248.64),
|
||||
vector4(209.28, -793.74, 30.25, 69.82),
|
||||
vector4(218.31, -796.92, 30.08, 68.55),
|
||||
vector4(224.50, -799.34, 29.96, 68.63),
|
||||
vector4(234.40, -803.02, 29.76, 66.67),
|
||||
vector4(240.09, -805.27, 29.64, 69.02),
|
||||
vector4(240.53, -802.44, 29.67, 248.95),
|
||||
vector4(234.46, -800.13, 29.79, 249.40),
|
||||
vector4(224.30, -796.51, 29.98, 248.31),
|
||||
vector4(218.23, -794.00, 30.09, 249.09),
|
||||
vector4(209.84, -791.10, 30.24, 251.56),
|
||||
vector4(211.09, -788.68, 30.22, 69.53),
|
||||
vector4(220.17, -791.73, 30.06, 70.56),
|
||||
vector4(225.84, -794.12, 29.98, 67.53),
|
||||
vector4(236.38, -797.85, 29.79, 69.39),
|
||||
vector4(216.56, -801.90, 30.79, 69.39)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "land",
|
||||
ped = vector4(587.5941, 2744.2844, 42.0691, 181.0514),
|
||||
vehicleSpawns = {
|
||||
vector4(584.3921, 2721.3599, 41.6483, 184.3260),
|
||||
vector4(577.1069, 2736.2322, 41.6097, 184.6912),
|
||||
vector4(577.9459, 2721.0010, 41.6481, 185.1414),
|
||||
vector4(574.1685, 2735.7288, 41.6397, 184.5562)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "land",
|
||||
ped = vector4(2746.1726, 3458.7378, 55.8272, 245.1009),
|
||||
vehicleSpawns = {
|
||||
vector4(2768.2136, 3456.2710, 55.2840, 67.7897),
|
||||
vector4(2759.3218, 3451.1448, 55.4786, 248.0150),
|
||||
vector4(2763.6526, 3445.0544, 55.4741, 66.9754),
|
||||
vector4(2787.2947, 3467.1001, 54.9407, 247.4356),
|
||||
vector4(2773.9514, 3471.6238, 55.0407, 246.8264)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "land",
|
||||
ped = vector4(120.4042, 6623.5190, 31.9593, 228.8283),
|
||||
vehicleSpawns = {
|
||||
vector4(155.9047, 6593.3252, 31.4343, 359.3789),
|
||||
vector4(155.7900, 6602.6978, 31.4463, 358.8232),
|
||||
vector4(145.8267, 6614.0996, 31.4007, 178.7948),
|
||||
vector4(145.6977, 6602.8950, 31.4397, 181.0616),
|
||||
vector4(132.4042, 6585.2139, 31.5501, 91.0906)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "heli",
|
||||
groups = {"lspd"},
|
||||
ped = vector4(465.6194, -985.4730, 43.6918, 0.8591),
|
||||
vehicleSpawns = {
|
||||
vector4(449.3105, -981.1057, 44.0788, 359.6042)
|
||||
}
|
||||
},
|
||||
{
|
||||
garageType = "heli",
|
||||
groups = {"lsfd"},
|
||||
ped = vector4(339.6271, -581.0325, 74.1656, 267.8232),
|
||||
vehicleSpawns = {
|
||||
vector4(351.3463, -588.1304, 74.1698, 108.5617)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,291 +0,0 @@
|
||||
local locations = require "client.vehicle.data"
|
||||
local sprite = {
|
||||
["water"] = 356,
|
||||
["heli"] = 360,
|
||||
["plane"] = 359,
|
||||
["land"] = 357
|
||||
}
|
||||
local garageTypes = {
|
||||
["water"] = 14,
|
||||
["heli"] = 15,
|
||||
["plane"] = 16
|
||||
}
|
||||
|
||||
local clothing = {
|
||||
{
|
||||
face = {
|
||||
drawable = 1,
|
||||
texture = 1
|
||||
},
|
||||
undershirt = {
|
||||
drawable = 0,
|
||||
texture = 0
|
||||
},
|
||||
torso = {
|
||||
drawable = 1,
|
||||
texture = 1
|
||||
},
|
||||
leg = {
|
||||
drawable = 0,
|
||||
texture = 0
|
||||
},
|
||||
glasses = {
|
||||
drawable = 1,
|
||||
texture = 0
|
||||
},
|
||||
hat = {
|
||||
drawable = -1,
|
||||
texture = -1
|
||||
},
|
||||
},
|
||||
{
|
||||
leg = {
|
||||
drawable = 0,
|
||||
texture = 1
|
||||
},
|
||||
undershirt = {
|
||||
drawable = 0,
|
||||
texture = 0
|
||||
},
|
||||
face = {
|
||||
drawable = 0,
|
||||
texture = 0
|
||||
},
|
||||
torso = {
|
||||
drawable = 0,
|
||||
texture = 2
|
||||
},
|
||||
glasses = {
|
||||
drawable = -1,
|
||||
texture = -1
|
||||
},
|
||||
hat = {
|
||||
drawable = 0,
|
||||
texture = 0
|
||||
},
|
||||
},
|
||||
{
|
||||
face = {
|
||||
drawable = 0,
|
||||
texture = 2
|
||||
},
|
||||
undershirt = {
|
||||
drawable = 0,
|
||||
texture = 0
|
||||
},
|
||||
torso = {
|
||||
drawable = 1,
|
||||
texture = 2
|
||||
},
|
||||
leg = {
|
||||
drawable = 0,
|
||||
texture = 0
|
||||
},
|
||||
hat = {
|
||||
drawable = -1,
|
||||
texture = -1
|
||||
},
|
||||
glasses = {
|
||||
drawable = -1,
|
||||
texture = -1
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
local function getClosestOwnedVehicle()
|
||||
local coords = GetEntityCoords(cache.ped)
|
||||
local vehicles = lib.getNearbyVehicles(coords, 50.0, true)
|
||||
local nearestVeh = {}
|
||||
|
||||
local function setNearestVehicle(veh)
|
||||
local state = Entity(veh.vehicle).state
|
||||
if not state.owner or state.owner ~= NDCore.player?.id then return end
|
||||
|
||||
local nearestDist = nearestVeh.dist
|
||||
local dist = #(coords-veh.coords)
|
||||
if not nearestDist or dist < nearestDist then
|
||||
nearestVeh.dist = dist
|
||||
nearestVeh.coords = veh.coords
|
||||
nearestVeh.entity = veh.vehicle
|
||||
end
|
||||
end
|
||||
|
||||
for i=1, #vehicles do
|
||||
setNearestVehicle(vehicles[i])
|
||||
end
|
||||
return nearestVeh.entity, nearestVeh.coords, nearestVeh.dist
|
||||
end
|
||||
|
||||
local function parkVehicle(veh)
|
||||
if not veh or not DoesEntityExist(veh) then
|
||||
return NDCore.notify({
|
||||
title = locale("garage"),
|
||||
description = locale("no_owned_veh_nearby"),
|
||||
type = "error",
|
||||
position = "bottom",
|
||||
duration = 3000
|
||||
})
|
||||
end
|
||||
if GetPedInVehicleSeat(veh, -1) ~= 0 then
|
||||
NDCore.notify({
|
||||
title = locale("garage"),
|
||||
description = locale("player_in_veh"),
|
||||
type = "error",
|
||||
position = "bottom",
|
||||
duration = 3000
|
||||
})
|
||||
return
|
||||
end
|
||||
|
||||
local properties = lib.getVehicleProperties(veh)
|
||||
properties.class = GetVehicleClass(veh)
|
||||
TriggerServerEvent("ND_Vehicles:storeVehicle", VehToNet(veh))
|
||||
end
|
||||
|
||||
local function isVehicleAvailable(vehicle, garageType, impound)
|
||||
local class = vehicle.properties.class
|
||||
local available = vehicle.available and not impound or vehicle.impounded and impound
|
||||
if available and not garageTypes[garageType] then return true end
|
||||
|
||||
for garType, garClass in pairs(garageTypes) do
|
||||
if available and garType == garageType and garClass == class then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function getEngineStatus(health)
|
||||
if health > 950 then
|
||||
return locale("perfect")
|
||||
elseif health > 750 then
|
||||
return locale("good")
|
||||
elseif health > 500 then
|
||||
return locale("bad")
|
||||
end
|
||||
return locale("very_bad")
|
||||
end
|
||||
|
||||
local function createMenuOptions(vehicle, vehicleSpawns)
|
||||
local props = vehicle.properties
|
||||
local makeName = GetLabelText(GetMakeNameFromVehicleModel(props.model))
|
||||
local modelName = GetLabelText(GetDisplayNameFromVehicleModel(props.model))
|
||||
local metadata = {}
|
||||
|
||||
if not makeName or makeName == "NULL" then
|
||||
makeName = ""
|
||||
else
|
||||
metadata[#metadata+1] = {label = locale("veh_make_brand"), value = makeName}
|
||||
makeName = makeName .. " "
|
||||
end
|
||||
if not modelName or modelName == "NULL" then
|
||||
modelName = ""
|
||||
else
|
||||
metadata[#metadata+1] = {label = locale("veh_model"), value = modelName}
|
||||
end
|
||||
|
||||
if props?.plate then
|
||||
metadata[#metadata+1] = {label = locale("veh_plate"), value = props.plate}
|
||||
end
|
||||
if props?.engineHealth then
|
||||
metadata[#metadata+1] = {
|
||||
label = locale("engine_status"),
|
||||
value = getEngineStatus(props.engineHealth),
|
||||
progress = props.engineHealth/10,
|
||||
colorScheme = "blue"
|
||||
}
|
||||
end
|
||||
|
||||
if props?.fuelLevel then
|
||||
metadata[#metadata+1] = {
|
||||
label = "Fuel",
|
||||
value = ("%d%s"):format(props.fuelLevel, "%"),
|
||||
progress = props.fuelLevel,
|
||||
colorScheme = "yellow"
|
||||
}
|
||||
end
|
||||
|
||||
return {
|
||||
title = ("%s: %s%s\n%s: %s"):format(locale("vehicle"), makeName, modelName, locale("veh_plate"), props?.plate or locale("not_found")),
|
||||
metadata = metadata,
|
||||
onSelect = function(args)
|
||||
TriggerServerEvent("ND_Vehicles:takeVehicle", vehicle.id, vehicleSpawns)
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
local function createMenu(vehicles, garageType, vehicleSpawns, impound)
|
||||
local options = {}
|
||||
if not impound then
|
||||
options[#options+1] = {
|
||||
title = locale("park_veh"),
|
||||
onSelect = function(args)
|
||||
local veh = getClosestOwnedVehicle()
|
||||
parkVehicle(veh)
|
||||
end
|
||||
}
|
||||
end
|
||||
for _, vehicle in ipairs(vehicles) do
|
||||
if isVehicleAvailable(vehicle, garageType, impound) then
|
||||
options[#options+1] = createMenuOptions(vehicle, vehicleSpawns)
|
||||
end
|
||||
end
|
||||
if impound and #options == 0 then
|
||||
options[#options+1] = {
|
||||
title = locale("no_vehs_found"),
|
||||
readOnly = true
|
||||
}
|
||||
end
|
||||
return {
|
||||
id = ("garage_%s"):format(garageType),
|
||||
title = impound and locale("vehicle_impound") or locale("parking_garage"),
|
||||
options = options,
|
||||
onExit = function()
|
||||
garageOpen = false
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
for i=1, #locations do
|
||||
local location = locations[i]
|
||||
NDCore.createAiPed({
|
||||
model = `s_m_y_airworker`,
|
||||
coords = location.ped,
|
||||
distance = 45.0,
|
||||
clothing = clothing[math.random(1, #clothing)],
|
||||
blip = {
|
||||
label = location.impound and locale("impound_w_location", location.garageType) or locale("garage_w_location", location.garageType),
|
||||
sprite = location.impound and 285 or sprite[location.garageType],
|
||||
scale = 0.7,
|
||||
color = 3,
|
||||
groups = location.groups
|
||||
},
|
||||
anim = {
|
||||
dict = "anim@amb@casino@valet_scenario@pose_d@",
|
||||
clip = "base_a_m_y_vinewood_01"
|
||||
},
|
||||
options = {
|
||||
{
|
||||
name = "nd_core:garagePed",
|
||||
icon = "fa-solid fa-warehouse",
|
||||
label = location.impound and locale("view_impounded_vehs") or locale("view_garage"),
|
||||
distance = 2.0,
|
||||
canInteract = function(entity, distance, coords, name, bone)
|
||||
if not location.groups then return true end
|
||||
local groups = location.groups
|
||||
local playerGroups = NDCore.player?.groups
|
||||
for i=1, #groups do
|
||||
if playerGroups?[groups[i]] then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end,
|
||||
onSelect = function(data)
|
||||
local vehicles = lib.callback.await("ND_Vehicles:getOwnedVehicles") or {}
|
||||
local menu = createMenu(vehicles, location.garageType, location.vehicleSpawns, location.impound)
|
||||
lib.registerContext(menu)
|
||||
lib.showContext(menu.id)
|
||||
end
|
||||
}
|
||||
},
|
||||
})
|
||||
end
|
||||
@@ -8,16 +8,25 @@ fx_version "cerulean"
|
||||
game "gta5"
|
||||
lua54 "yes"
|
||||
|
||||
files {
|
||||
"init.lua",
|
||||
"compatibility/**/locale.lua",
|
||||
"locales/*.json",
|
||||
"ui/**"
|
||||
}
|
||||
|
||||
ui_page "ui/index.html"
|
||||
|
||||
shared_script "@ox_lib/init.lua"
|
||||
client_scripts {
|
||||
"client/main.lua",
|
||||
"shared/functions.lua",
|
||||
"client/peds.lua",
|
||||
"client/vehicle/main.lua",
|
||||
"client/vehicle/garages.lua",
|
||||
"client/vehicle.lua",
|
||||
"client/functions.lua",
|
||||
"client/events.lua",
|
||||
"client/death.lua",
|
||||
"client/groupadmin.lua",
|
||||
"compatibility/**/client.lua"
|
||||
}
|
||||
server_scripts {
|
||||
@@ -27,17 +36,12 @@ server_scripts {
|
||||
"server/player.lua",
|
||||
"server/vehicle.lua",
|
||||
"server/functions.lua",
|
||||
"server/groups.lua",
|
||||
"server/groupadmin.lua",
|
||||
"compatibility/**/server.lua",
|
||||
"server/commands.lua"
|
||||
}
|
||||
|
||||
files {
|
||||
"init.lua",
|
||||
"client/vehicle/data.lua",
|
||||
"compatibility/**/locale.lua",
|
||||
"locales/*.json"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
"ox_lib",
|
||||
"oxmysql"
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
"view_impounded_vehs": "View impounded vehicles",
|
||||
"view_garage": "View garage",
|
||||
"personal_vehicle": "Personal vehicle",
|
||||
"group_vehicle": "Vehicle",
|
||||
"keybind_carkey": "Unlock/lock vehicle (double click)",
|
||||
"progress_hotwiring": "Hotwiring",
|
||||
"cruise_control": "Cruise control",
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
"view_impounded_vehs": "Visa beslagtagna fordon",
|
||||
"view_garage": "Visa garage",
|
||||
"personal_vehicle": "Personligt fordon",
|
||||
"group_vehicle": "Fordon",
|
||||
"keybind_carkey": "Lås/öppna fordon (dubbelklick)",
|
||||
"progress_hotwiring": "Kopplar om",
|
||||
"cruise_control": "Farthållare",
|
||||
|
||||
@@ -84,11 +84,14 @@ local function getVehicleDatabaseInfo(vehicle)
|
||||
if not vehicle then return end
|
||||
local stored = vehicle.stored == 1
|
||||
local impounded = vehicle.impounded == 1
|
||||
local properties = json.decode(vehicle.properties) or {}
|
||||
properties.plate = vehicle.plate
|
||||
|
||||
return {
|
||||
id = vehicle.id,
|
||||
owner = vehicle.owner,
|
||||
plate = vehicle.plate,
|
||||
properties = json.decode(vehicle.properties) or {},
|
||||
properties = properties,
|
||||
stored = stored,
|
||||
impounded = impounded,
|
||||
stolen = vehicle.stolen == 1,
|
||||
@@ -97,6 +100,14 @@ local function getVehicleDatabaseInfo(vehicle)
|
||||
}
|
||||
end
|
||||
|
||||
function NDCore.generateVehiclePlate()
|
||||
return generatePlate()
|
||||
end
|
||||
|
||||
function NDCore.generateUniqueVehiclePlate()
|
||||
return generateVehiclePlate()
|
||||
end
|
||||
|
||||
--- get vehicle information queried from the database by the vehicle id
|
||||
---@param vehicleId string | numb
|
||||
---@return table | nil
|
||||
@@ -124,20 +135,45 @@ function NDCore.getVehicle(entity)
|
||||
netId = NetworkGetNetworkIdFromEntity(entity)
|
||||
}
|
||||
|
||||
--- delete the vehicle
|
||||
function self.delete(saveProperties)
|
||||
if not DoesEntityExist(entity) then return end
|
||||
if saveProperties and self.id and self.owner then
|
||||
local properties = lib.callback.await("ND_Vehicles:getProps", NetworkGetEntityOwner(entity), self.netId)
|
||||
if properties then
|
||||
-- save properties to db
|
||||
function self.saveProperties(props, propsToSave)
|
||||
local properties = {}
|
||||
local vehProps = props or lib.callback.await("ND_Vehicles:getProps", NetworkGetEntityOwner(entity), self.netId)
|
||||
|
||||
if propsToSave then
|
||||
properties = self.properties
|
||||
if vehProps then
|
||||
for prop, value in pairs(vehProps) do
|
||||
if lib.table.contains(propsToSave, prop) then
|
||||
properties[prop] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
properties = vehProps
|
||||
end
|
||||
|
||||
if self.properties?.callsign then
|
||||
properties.callsign = true
|
||||
end
|
||||
|
||||
self.properties = properties
|
||||
state.props = properties
|
||||
|
||||
MySQL.query("UPDATE nd_vehicles SET properties = ? WHERE id = ?", {json.encode(properties), self.id})
|
||||
end
|
||||
|
||||
--- delete the vehicle
|
||||
function self.delete(saveProperties, propsToSave)
|
||||
if not DoesEntityExist(entity) then return end
|
||||
if saveProperties and self.id and self.owner then
|
||||
self.saveProperties(false, propsToSave)
|
||||
end
|
||||
if DoesEntityExist(entity) then
|
||||
DeleteEntity(entity)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
-- remvoe vehicle from db.
|
||||
@@ -159,11 +195,12 @@ function NDCore.getVehicle(entity)
|
||||
properties.callsign = true
|
||||
end
|
||||
|
||||
state.allPropsApplied = false
|
||||
state.props = properties
|
||||
self.properties = properties
|
||||
|
||||
if not self.id or not self.owner then return end
|
||||
MySQL.query("UPDATE nd_vehicles SET properties = ? WHERE id = ?", {json.encode(properties), self.id})
|
||||
self.saveProperties(properties)
|
||||
end
|
||||
|
||||
--- set vehicle locked/unlocked
|
||||
@@ -183,6 +220,7 @@ function NDCore.getVehicle(entity)
|
||||
if self.properties then
|
||||
self.properties.plate = plate
|
||||
local state = Entity(entity).state
|
||||
state.allPropsApplied = false
|
||||
state.props = self.properties
|
||||
end
|
||||
|
||||
@@ -194,9 +232,9 @@ function NDCore.getVehicle(entity)
|
||||
--- set the vehicle availability status
|
||||
---@param statusType string
|
||||
---@param status boolean
|
||||
function self.setStatus(statusType, status)
|
||||
function self.setStatus(statusType, status, keepEntity)
|
||||
if not lib.table.contains({"stored", "impounded", "stolen"}, statusType) then return end
|
||||
if statusType ~= "stolen" then self.delete(true) end
|
||||
if statusType ~= "stolen" and not keepEntity then self.delete(true) end
|
||||
if not self.id or not self.owner then return end
|
||||
local query = ("UPDATE nd_vehicles SET %s = ? WHERE id = ?"):format(statusType)
|
||||
MySQL.query(query, {status and 1 or 0, self.id})
|
||||
@@ -271,14 +309,15 @@ function NDCore.giveVehicleAccess(source, vehicle, access, info)
|
||||
end
|
||||
|
||||
if not inventoryStarted or not Config.useInventoryForKeys then return end
|
||||
local plate = info?.plate or GetVehicleNumberPlateText(vehicle)
|
||||
local model = info?.model or GetEntityModel(vehicle)
|
||||
local modelName = info?.modelName or model and lib.callback.await("ND_Vehicles:getVehicleModelMakeLabel", source, model) or ""
|
||||
local hasKey = ox_inventory:GetSlotIdWithItem(source, "keys", {
|
||||
vehId = vehicleId
|
||||
})
|
||||
|
||||
if access and not hasKey then
|
||||
local plate = info?.plate or GetVehicleNumberPlateText(vehicle)
|
||||
local model = info?.model or GetEntityModel(vehicle)
|
||||
local modelName = info?.modelName or model and lib.callback.await("ND_Vehicles:getVehicleModelMakeLabel", source, model) or ""
|
||||
|
||||
ox_inventory:AddItem(source, "keys", 1, {
|
||||
vehOwner = owner or state.owner,
|
||||
vehId = vehicleId,
|
||||
@@ -328,17 +367,24 @@ function NDCore.createVehicle(info)
|
||||
state.locked = true
|
||||
local keys = info.keys or {}
|
||||
|
||||
if not properties.plate then
|
||||
properties.plate = generateVehiclePlate()
|
||||
if not properties.plate or info.plate then
|
||||
properties.plate = info.plate or generateVehiclePlate()
|
||||
end
|
||||
if owner then
|
||||
keys[owner] = true
|
||||
state.owner = owner
|
||||
end
|
||||
if info.blipGroups then
|
||||
state.blipGroups = info.blipGroups
|
||||
end
|
||||
|
||||
state.keys = keys
|
||||
state.props = properties
|
||||
state.id = vehicleId
|
||||
|
||||
if not info.ignoreProps then
|
||||
state.props = properties
|
||||
end
|
||||
|
||||
local vehicleName
|
||||
if inventoryStarted and Config.useInventoryForKeys then
|
||||
for charId, _ in pairs(keys) do
|
||||
@@ -354,7 +400,7 @@ function NDCore.createVehicle(info)
|
||||
NDCore.giveVehicleAccess(playerSource, veh, true, {
|
||||
vehicleId = vehicleId,
|
||||
netId = netId,
|
||||
plate = properties?.plate,
|
||||
plate = info.plate or properties?.plate,
|
||||
model = model,
|
||||
vehicleName = vehicleName,
|
||||
owner = owner
|
||||
@@ -363,6 +409,13 @@ function NDCore.createVehicle(info)
|
||||
end
|
||||
end
|
||||
|
||||
for i=1, 3 do
|
||||
if DoesEntityExist(veh) then
|
||||
SetVehicleNumberPlateText(veh, properties.plate)
|
||||
end
|
||||
Wait(500)
|
||||
end
|
||||
|
||||
return NDCore.getVehicle(veh)
|
||||
end
|
||||
|
||||
@@ -423,8 +476,8 @@ end
|
||||
---@param properties table
|
||||
---@param stored boolean
|
||||
---@return vehicleId number
|
||||
function NDCore.setVehicleOwned(playerId, properties, stored)
|
||||
local plate = generateVehiclePlate()
|
||||
function NDCore.setVehicleOwned(playerId, properties, stored, setPlate)
|
||||
local plate = setPlate or generateVehiclePlate()
|
||||
properties.plate = plate
|
||||
return MySQL.insert.await("INSERT INTO nd_vehicles (owner, plate, properties, stored) VALUES (?, ?, ?, ?)", {playerId, plate, json.encode(properties), stored and 1 or 0})
|
||||
end
|
||||
@@ -464,11 +517,11 @@ end
|
||||
---@param vehicleId number
|
||||
---@param coords vector4
|
||||
---@return table
|
||||
function NDCore.spawnOwnedVehicle(source, vehicleId, coords, heading)
|
||||
function NDCore.spawnOwnedVehicle(source, vehicleId, coords, heading, _vehicle)
|
||||
local player = NDCore.getPlayer(source)
|
||||
if not player then return end
|
||||
|
||||
local vehicle = NDCore.getVehicleById(vehicleId)
|
||||
local vehicle = _vehicle or NDCore.getVehicleById(vehicleId)
|
||||
if not vehicle or vehicle.owner ~= player.id then return end
|
||||
if not vehicle.available and not vehicle.impounded then return end
|
||||
|
||||
@@ -577,6 +630,16 @@ local function lockNearestVehicle(source, vehId, metadata)
|
||||
end
|
||||
end
|
||||
|
||||
local function hasBlipGroup(player, groups)
|
||||
groups = groups or {}
|
||||
for i=1, #groups do
|
||||
local group = groups[i]
|
||||
if player.groups[group] then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- inventory keys using item.
|
||||
exports("keys", function(event, item, inventory, slot, data)
|
||||
if event ~= "usingItem" or not Config.useInventoryForKeys or not inventoryStarted then return end
|
||||
@@ -603,7 +666,9 @@ RegisterCommand("getkeys", function(source, args, rawCommand)
|
||||
local player = NDCore.getPlayer(source)
|
||||
local state = Entity(veh).state
|
||||
local owner = state.owner
|
||||
if not owner or owner ~= player.id then return end
|
||||
local blipGroups = state.blipGroups
|
||||
|
||||
if not state.id or (not owner or owner ~= player.id) and (not hasBlipGroup(player, blipGroups)) then return end
|
||||
|
||||
local props = state.props
|
||||
ox_inventory:AddItem(source, "keys", 1, {
|
||||
@@ -650,32 +715,32 @@ RegisterNetEvent("ND_Vehicles:toggleVehicleLock", function(netId)
|
||||
end)
|
||||
|
||||
-- locking of npc vehicles, if the players spawns inside a vehicle it won't be locked.
|
||||
AddEventHandler("entityCreated", function(entity)
|
||||
local time = os.time()
|
||||
while not DoesEntityExist(entity) and os.time()-time < 5 do Wait(50) end
|
||||
-- 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
|
||||
if state.owner or state.locked ~= nil then return end
|
||||
-- local state = Entity(entity).state
|
||||
-- if state.owner or state.locked ~= nil then return end
|
||||
|
||||
time = os.time()
|
||||
local driver = GetPedInVehicleSeat(entity, -1)
|
||||
while DoesEntityExist(entity) and driver == 0 and os.time()-time < 2 do
|
||||
driver = GetPedInVehicleSeat(entity, -1)
|
||||
Wait(100)
|
||||
end
|
||||
-- time = os.time()
|
||||
-- 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 not DoesEntityExist(entity) then return end
|
||||
|
||||
if DoesEntityExist(driver) and IsPedAPlayer(driver) then
|
||||
state.locked = false
|
||||
state.hotwired = true
|
||||
end
|
||||
-- if DoesEntityExist(driver) and IsPedAPlayer(driver) then
|
||||
-- state.locked = false
|
||||
-- state.hotwired = true
|
||||
-- end
|
||||
|
||||
if math.random(1, 100) <= Config.randomUnlockedVehicleChance then return end
|
||||
state.locked = true
|
||||
end)
|
||||
-- if math.random(1, 100) <= Config.randomUnlockedVehicleChance then return end
|
||||
-- state.locked = true
|
||||
-- end)
|
||||
|
||||
-- disables inventory vehicles keys, disabled vehicles keys can no longer be used. Kinda like taking the battery out.
|
||||
RegisterNetEvent("ND_Vehicles:disableKey", function(slot)
|
||||
@@ -717,72 +782,12 @@ RegisterNetEvent("ND_Vehicles:hotwire", function(netId)
|
||||
state.hotwired = true
|
||||
end)
|
||||
|
||||
RegisterNetEvent("ND_Vehicles:storeVehicle", function(netId)
|
||||
local src = source
|
||||
local vehicle = NDCore.getVehicle(NetworkGetEntityFromNetworkId(netId))
|
||||
if not vehicle then return end
|
||||
RegisterNetEvent("ND_Vehicles:propsApplied", function(netId)
|
||||
local veh = NetworkGetEntityFromNetworkId(netId)
|
||||
if not veh or not DoesEntityExist(veh) then return end
|
||||
|
||||
local player = NDCore.getPlayer(src)
|
||||
if not vehicle.setStatus("stored", true) or not player or player.id ~= vehicle.owner then
|
||||
return player.notify({
|
||||
title = locale("garage"),
|
||||
description = locale("no_owned_veh_nearby"),
|
||||
type = "error",
|
||||
position = "bottom",
|
||||
duration = 3000
|
||||
})
|
||||
end
|
||||
player.notify({
|
||||
title = locale("garage"),
|
||||
description = locale("veh_stored_in_garage"),
|
||||
type = "success",
|
||||
position = "bottom",
|
||||
duration = 3000
|
||||
})
|
||||
NDCore.giveVehicleAccess(src, vehicle.entity, false, {
|
||||
vehicleId = vehicle.id,
|
||||
netId = vehicle.netId,
|
||||
owner = vehicle.owner
|
||||
})
|
||||
end)
|
||||
|
||||
local function isParkingAvailable(locations)
|
||||
for i=1, #locations do
|
||||
local loc = locations[math.random(1, #locations)]
|
||||
if #getNearbyVehicles(vec3(loc.x, loc.y, loc.z), 2.0) == 0 then
|
||||
return loc
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RegisterNetEvent("ND_Vehicles:takeVehicle", function(vehId, locations)
|
||||
local src = source
|
||||
local vehicle = NDCore.getVehicleById(vehId)
|
||||
local player = NDCore.getPlayer(src)
|
||||
if not player or not vehicle or vehicle.owner ~= player.id then return end
|
||||
|
||||
local info = NDCore.spawnOwnedVehicle(src, vehicle.id, isParkingAvailable(locations))
|
||||
if not info then return end
|
||||
TriggerClientEvent("ND_Vehicles:blip", src, info.netId, true)
|
||||
|
||||
if vehicle.impounded then
|
||||
local reclaimPrice = vehicle.metadata.impoundReclaimPrice or 200
|
||||
if not player.deductMoney("bank", reclaimPrice, locale("impound_reclaim")) then
|
||||
return player.notify({
|
||||
title = locale("impound"),
|
||||
description = locale("impound_not_enough", reclaimPrice),
|
||||
type = "error",
|
||||
position = "bottom"
|
||||
})
|
||||
end
|
||||
player.notify({
|
||||
title = locale("impound"),
|
||||
description = locale("impound_paid", reclaimPrice),
|
||||
type = "success",
|
||||
position = "bottom"
|
||||
})
|
||||
MySQL.query.await("UPDATE nd_vehicles SET impounded = ? WHERE id = ?", {0, vehicle.id})
|
||||
end
|
||||
local state = Entity(veh).state
|
||||
state:set("allPropsApplied", true, true)
|
||||
end)
|
||||
|
||||
lib.callback.register("ND_Vehicles:getOwnedVehicles", function(src)
|
||||
@@ -814,6 +819,6 @@ AddEventHandler("ND:characterLoaded", function(player)
|
||||
|
||||
if #vehiclesToImpound == 0 then return end
|
||||
|
||||
local query = ("UPDATE nd_vehicles SET impounded = ? WHERE owner = ? AND id IN (%s)"):format(table.concat(vehiclesToImpound, ", "))
|
||||
local query = ("UPDATE nd_vehicles SET stored = ? WHERE owner = ? AND id IN (%s)"):format(table.concat(vehiclesToImpound, ", "))
|
||||
MySQL.rawExecute(query, {1, player.id})
|
||||
end)
|
||||
|
||||
Reference in New Issue
Block a user