ed
This commit is contained in:
parent
6d22d5f77c
commit
63fbc60a00
86 changed files with 8352 additions and 3428 deletions
488
resources/[Developer]/mh_Parking/cl_utils.lua
Normal file
488
resources/[Developer]/mh_Parking/cl_utils.lua
Normal file
|
@ -0,0 +1,488 @@
|
|||
-- logs text to the console
|
||||
function Log(text)
|
||||
if (Config.isDebug) then
|
||||
Log(text)
|
||||
end
|
||||
end
|
||||
|
||||
-- Return all vehicle modifications in an array
|
||||
function GetVehicleModifications(vehicle)
|
||||
local color1, color2 = GetVehicleColours(vehicle)
|
||||
local pearlescentColor, wheelColor = GetVehicleExtraColours(vehicle)
|
||||
|
||||
local extras = {}
|
||||
for i = 0, 20, 1 do
|
||||
if (DoesExtraExist(vehicle, i)) then
|
||||
if (IsVehicleExtraTurnedOn(vehicle, i)) then
|
||||
table.insert(extras, { i, 0 })
|
||||
else
|
||||
table.insert(extras, { i, 1 })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local tiresBurst = {}
|
||||
for i = 0, 5, 1 do
|
||||
if (IsVehicleTyreBurst(vehicle, i, true)) then
|
||||
table.insert(tiresBurst, { i, true })
|
||||
elseif (IsVehicleTyreBurst(vehicle, i, false)) then
|
||||
table.insert(tiresBurst, { i, false })
|
||||
end
|
||||
end
|
||||
|
||||
local doorsMissing = {}
|
||||
for i = 0, 7, 1 do
|
||||
if (IsVehicleDoorDamaged(vehicle, i)) then
|
||||
table.insert(doorsMissing, i)
|
||||
end
|
||||
end
|
||||
|
||||
local windowsBroken = {}
|
||||
--for i = 0, 13, 1 do
|
||||
-- if (not IsVehicleWindowIntact(vehicle, i)) then
|
||||
-- table.insert(windowsBroken, i)
|
||||
-- end
|
||||
--end
|
||||
|
||||
-- custom colors
|
||||
local hasCustomPrimaryColor = GetIsVehiclePrimaryColourCustom(vehicle)
|
||||
local customPrimaryColor = nil
|
||||
if (hasCustomPrimaryColor) then
|
||||
local r, g, b = GetVehicleCustomPrimaryColour(vehicle)
|
||||
customPrimaryColor = { r, g, b }
|
||||
end
|
||||
|
||||
local hasCustomSecondaryColor = GetIsVehicleSecondaryColourCustom(vehicle)
|
||||
local customSecondaryColor = nil
|
||||
if (hasCustomSecondaryColor) then
|
||||
local r, g, b = GetVehicleCustomSecondaryColour(vehicle)
|
||||
customSecondaryColor = { r, g, b }
|
||||
end
|
||||
|
||||
return {
|
||||
-- 1 model
|
||||
GetEntityModel(vehicle),
|
||||
|
||||
-- 2 lockStatus
|
||||
GetVehicleDoorLockStatus(vehicle),
|
||||
|
||||
-- 3 health
|
||||
math.floor(GetEntityHealth(vehicle) * 10.0) / 10.0,
|
||||
-- 4 bodyHealth
|
||||
math.floor(GetVehicleBodyHealth(vehicle) * 10.0) / 10.0,
|
||||
-- 5 engineHealth
|
||||
math.floor(GetVehicleEngineHealth(vehicle) * 10.0) / 10.0,
|
||||
-- 6 petrolTankHealth
|
||||
math.floor(GetVehiclePetrolTankHealth(vehicle) * 10.0) / 10.0,
|
||||
|
||||
-- 7 dirtLevel
|
||||
math.floor(GetVehicleDirtLevel(vehicle) * 10.0) / 10.0,
|
||||
-- 8 fuelLevel
|
||||
math.floor(exports[Config.exports]:GetFuel(vehicle) * 10.0) / 10.0,
|
||||
|
||||
---------------------------------------------------------------------- Implementierung Miho
|
||||
--math.floor(DecorGetFloat(vehicle, Config.FuelDecor)*10) / 10.0,
|
||||
---------------------------------------------------------------------- Implementierung Miho ENDE
|
||||
|
||||
-- 9 plateIndex
|
||||
GetVehicleNumberPlateTextIndex(vehicle),
|
||||
|
||||
-- 10 primaryColor
|
||||
color1,
|
||||
-- 11 secondaryColor
|
||||
color2,
|
||||
-- 12 pearlescentColor
|
||||
pearlescentColor,
|
||||
-- 13 wheelColor
|
||||
wheelColor,
|
||||
|
||||
-- 14 wheelType
|
||||
GetVehicleWheelType(vehicle),
|
||||
-- 15 customWheelsFront
|
||||
GetVehicleModVariation(vehicle, 23);
|
||||
-- 16 customWheelsBack
|
||||
GetVehicleModVariation(vehicle, 24);
|
||||
-- 17 windowTint
|
||||
GetVehicleWindowTint(vehicle),
|
||||
-- 18 enabledNeon
|
||||
{
|
||||
IsVehicleNeonLightEnabled(vehicle, 0),
|
||||
IsVehicleNeonLightEnabled(vehicle, 1),
|
||||
IsVehicleNeonLightEnabled(vehicle, 2),
|
||||
IsVehicleNeonLightEnabled(vehicle, 3),
|
||||
},
|
||||
-- 19 neonColor
|
||||
table.pack(GetVehicleNeonLightsColour(vehicle)),
|
||||
-- 20 tireSmokeColor
|
||||
table.pack(GetVehicleTyreSmokeColor(vehicle)),
|
||||
|
||||
-- 21 extras
|
||||
extras,
|
||||
|
||||
-- 22-32 mods
|
||||
GetVehicleMod(vehicle, 0),
|
||||
GetVehicleMod(vehicle, 1),
|
||||
GetVehicleMod(vehicle, 2),
|
||||
GetVehicleMod(vehicle, 3),
|
||||
GetVehicleMod(vehicle, 4),
|
||||
GetVehicleMod(vehicle, 5),
|
||||
GetVehicleMod(vehicle, 6),
|
||||
GetVehicleMod(vehicle, 7),
|
||||
GetVehicleMod(vehicle, 8),
|
||||
GetVehicleMod(vehicle, 9),
|
||||
GetVehicleMod(vehicle, 10),
|
||||
|
||||
-- 33-38 mods
|
||||
GetVehicleMod(vehicle, 11),
|
||||
GetVehicleMod(vehicle, 12),
|
||||
GetVehicleMod(vehicle, 13),
|
||||
GetVehicleMod(vehicle, 14),
|
||||
GetVehicleMod(vehicle, 15),
|
||||
GetVehicleMod(vehicle, 16),
|
||||
|
||||
-- 39-41 mods
|
||||
IsToggleModOn(vehicle, 18),
|
||||
IsToggleModOn(vehicle, 20),
|
||||
IsToggleModOn(vehicle, 22),
|
||||
|
||||
-- 42-43 mods
|
||||
GetVehicleMod(vehicle, 23),
|
||||
GetVehicleMod(vehicle, 24),
|
||||
|
||||
-- 44-66 mods
|
||||
GetVehicleMod(vehicle, 25),
|
||||
GetVehicleMod(vehicle, 26),
|
||||
GetVehicleMod(vehicle, 27),
|
||||
GetVehicleMod(vehicle, 28),
|
||||
GetVehicleMod(vehicle, 29),
|
||||
GetVehicleMod(vehicle, 30),
|
||||
GetVehicleMod(vehicle, 31),
|
||||
GetVehicleMod(vehicle, 32),
|
||||
GetVehicleMod(vehicle, 33),
|
||||
GetVehicleMod(vehicle, 34),
|
||||
GetVehicleMod(vehicle, 35),
|
||||
GetVehicleMod(vehicle, 36),
|
||||
GetVehicleMod(vehicle, 37),
|
||||
GetVehicleMod(vehicle, 38),
|
||||
GetVehicleMod(vehicle, 39),
|
||||
GetVehicleMod(vehicle, 40),
|
||||
GetVehicleMod(vehicle, 41),
|
||||
GetVehicleMod(vehicle, 42),
|
||||
GetVehicleMod(vehicle, 43),
|
||||
GetVehicleMod(vehicle, 44),
|
||||
GetVehicleMod(vehicle, 45),
|
||||
GetVehicleMod(vehicle, 46),
|
||||
GetVehicleMod(vehicle, 48),
|
||||
|
||||
-- 67 livery
|
||||
GetVehicleLivery(vehicle),
|
||||
|
||||
-- 68 missingDoors
|
||||
doorsMissing,
|
||||
|
||||
-- 69 bulletproofTires
|
||||
not GetVehicleTyresCanBurst(vehicle),
|
||||
-- 70 tiresBurst
|
||||
tiresBurst,
|
||||
|
||||
-- 71 brokenWindows
|
||||
windowsBroken,
|
||||
|
||||
-- 72 xenon lights
|
||||
GetVehicleXenonLightsColour(vehicle),
|
||||
|
||||
-- 73 custom primary color
|
||||
customPrimaryColor,
|
||||
-- 74 custom secondary color
|
||||
customSecondaryColor,
|
||||
|
||||
-- 75 interior color
|
||||
GetVehicleInteriorColor(vehicle)
|
||||
}
|
||||
end
|
||||
|
||||
-- Apply all modifications to a vehicle entity
|
||||
function SetVehicleModifications(vehicle, plate, modifications)
|
||||
SetVehicleModKit(vehicle, 0)
|
||||
|
||||
-- plate
|
||||
SetVehicleNumberPlateText(vehicle, plate)
|
||||
SetVehicleNumberPlateTextIndex(vehicle, modifications[9])
|
||||
|
||||
-- lockStatus
|
||||
SetVehicleDoorsLocked(vehicle, modifications[2])
|
||||
|
||||
-- colours
|
||||
SetVehicleColours(vehicle, modifications[10], modifications[11])
|
||||
if (modifications[73]) then
|
||||
SetVehicleCustomPrimaryColour(vehicle, modifications[73][1], modifications[73][2], modifications[73][3])
|
||||
end
|
||||
if (modifications[74]) then
|
||||
SetVehicleCustomSecondaryColour(vehicle, modifications[74][1], modifications[74][2], modifications[74][3])
|
||||
end
|
||||
if (modifications[75]) then
|
||||
SetVehicleInteriorColor(vehicle, modifications[75])
|
||||
end
|
||||
|
||||
SetVehicleExtraColours(vehicle, modifications[12], modifications[13])
|
||||
|
||||
SetVehicleTyreSmokeColor(vehicle, modifications[20][1], modifications[20][2], modifications[20][3])
|
||||
|
||||
-- wheels
|
||||
SetVehicleWheelType(vehicle, modifications[14])
|
||||
|
||||
-- windows
|
||||
SetVehicleWindowTint(vehicle, modifications[17])
|
||||
|
||||
-- neonlight
|
||||
SetVehicleNeonLightEnabled(vehicle, 0, modifications[18][1])
|
||||
SetVehicleNeonLightEnabled(vehicle, 1, modifications[18][2])
|
||||
SetVehicleNeonLightEnabled(vehicle, 2, modifications[18][3])
|
||||
SetVehicleNeonLightEnabled(vehicle, 3, modifications[18][4])
|
||||
|
||||
SetVehicleNeonLightsColour(vehicle, modifications[19][1], modifications[19][2], modifications[19][3])
|
||||
|
||||
-- mods
|
||||
SetVehicleMod(vehicle, 0, modifications[22], modifications[15])
|
||||
SetVehicleMod(vehicle, 1, modifications[23], modifications[15])
|
||||
SetVehicleMod(vehicle, 2, modifications[24], modifications[15])
|
||||
SetVehicleMod(vehicle, 3, modifications[25], modifications[15])
|
||||
SetVehicleMod(vehicle, 4, modifications[26], modifications[15])
|
||||
SetVehicleMod(vehicle, 5, modifications[27], modifications[15])
|
||||
SetVehicleMod(vehicle, 6, modifications[28], modifications[15])
|
||||
SetVehicleMod(vehicle, 7, modifications[29], modifications[15])
|
||||
SetVehicleMod(vehicle, 8, modifications[30], modifications[15])
|
||||
SetVehicleMod(vehicle, 9, modifications[31], modifications[15])
|
||||
SetVehicleMod(vehicle, 10, modifications[32], modifications[15])
|
||||
|
||||
SetVehicleMod(vehicle, 11, modifications[33], modifications[15])
|
||||
SetVehicleMod(vehicle, 12, modifications[34], modifications[15])
|
||||
SetVehicleMod(vehicle, 13, modifications[35], modifications[15])
|
||||
|
||||
SetVehicleMod(vehicle, 14, modifications[36], modifications[15])
|
||||
|
||||
SetVehicleMod(vehicle, 15, modifications[37], modifications[15])
|
||||
SetVehicleMod(vehicle, 16, modifications[38], modifications[15])
|
||||
|
||||
ToggleVehicleMod(vehicle, 18, modifications[39])
|
||||
ToggleVehicleMod(vehicle, 20, modifications[40])
|
||||
ToggleVehicleMod(vehicle, 22, modifications[41])
|
||||
|
||||
SetVehicleMod(vehicle, 23, modifications[42], modifications[15])
|
||||
SetVehicleMod(vehicle, 24, modifications[43], modifications[16])
|
||||
|
||||
SetVehicleMod(vehicle, 25, modifications[44], modifications[15])
|
||||
SetVehicleMod(vehicle, 26, modifications[45], modifications[15])
|
||||
SetVehicleMod(vehicle, 27, modifications[46], modifications[15])
|
||||
SetVehicleMod(vehicle, 28, modifications[47], modifications[15])
|
||||
SetVehicleMod(vehicle, 29, modifications[48], modifications[15])
|
||||
SetVehicleMod(vehicle, 30, modifications[49], modifications[15])
|
||||
SetVehicleMod(vehicle, 31, modifications[50], modifications[15])
|
||||
SetVehicleMod(vehicle, 32, modifications[51], modifications[15])
|
||||
SetVehicleMod(vehicle, 33, modifications[52], modifications[15])
|
||||
SetVehicleMod(vehicle, 34, modifications[53], modifications[15])
|
||||
SetVehicleMod(vehicle, 35, modifications[54], modifications[15])
|
||||
SetVehicleMod(vehicle, 36, modifications[55], modifications[15])
|
||||
SetVehicleMod(vehicle, 37, modifications[56], modifications[15])
|
||||
SetVehicleMod(vehicle, 38, modifications[57], modifications[15])
|
||||
SetVehicleMod(vehicle, 39, modifications[58], modifications[15])
|
||||
SetVehicleMod(vehicle, 40, modifications[59], modifications[15])
|
||||
SetVehicleMod(vehicle, 41, modifications[60], modifications[15])
|
||||
SetVehicleMod(vehicle, 42, modifications[61], modifications[15])
|
||||
SetVehicleMod(vehicle, 43, modifications[62], modifications[15])
|
||||
SetVehicleMod(vehicle, 44, modifications[63], modifications[15])
|
||||
SetVehicleMod(vehicle, 45, modifications[64], modifications[15])
|
||||
SetVehicleMod(vehicle, 46, modifications[65], modifications[15])
|
||||
SetVehicleMod(vehicle, 48, modifications[66], modifications[15])
|
||||
|
||||
SetVehicleLivery(vehicle, modifications[67])
|
||||
|
||||
-- extras
|
||||
for i = 1, #modifications[21], 1 do
|
||||
SetVehicleExtra(vehicle, modifications[21][i][1], modifications[21][i][2])
|
||||
end
|
||||
|
||||
-- stats
|
||||
SetEntityHealth(vehicle, modifications[3])
|
||||
SetVehicleBodyHealth(vehicle, modifications[4])
|
||||
SetVehicleEngineHealth(vehicle, modifications[5])
|
||||
SetVehiclePetrolTankHealth(vehicle, modifications[6])
|
||||
if (Config.renderScorched and (modifications[5] < -3999.0 or modifications[6] < -999.0)) then
|
||||
TriggerServerEvent("mh_Parking:renderScorched", NetworkGetNetworkIdFromEntity(vehicle), true)
|
||||
end
|
||||
|
||||
SetVehicleDirtLevel(vehicle, modifications[7])
|
||||
exports[Config.exports]:SetFuel(vehicle, modifications[8])
|
||||
|
||||
---------------------------------------------------------------------- Implementierung Miho
|
||||
--[[
|
||||
fuel = modifications[8]
|
||||
if type(fuel) == 'number' and fuel >= 0 and fuel <= 100 then
|
||||
SetVehicleFuelLevel(vehicle, fuel + 0.0)
|
||||
DecorSetFloat(vehicle, Config.FuelDecor, GetVehicleFuelLevel(vehicle))
|
||||
end
|
||||
]]
|
||||
---------------------------------------------------------------------- Implementierung Miho ENDE
|
||||
|
||||
|
||||
-- doors
|
||||
for i = 1, #modifications[68], 1 do
|
||||
SetVehicleDoorBroken(vehicle, modifications[68][i], true)
|
||||
end
|
||||
|
||||
-- tires
|
||||
SetVehicleTyresCanBurst(vehicle, not modifications[69])
|
||||
if (not modifications[69]) then
|
||||
for i = 1, #modifications[70], 1 do
|
||||
SetVehicleTyreBurst(vehicle, modifications[70][i][1], modifications[70][i][2], 1000.0)
|
||||
end
|
||||
end
|
||||
|
||||
-- windows
|
||||
for i = 1, #modifications[71], 1 do
|
||||
SmashVehicleWindow(vehicle, modifications[71][i])
|
||||
end
|
||||
|
||||
-- xenon lights
|
||||
if (modifications[72]) then
|
||||
SetVehicleXenonLightsColour(vehicle, modifications[72])
|
||||
end
|
||||
end
|
||||
|
||||
-- Return closest loaded vehicle entity or nil if no vehicle is found
|
||||
function GetClosestVehicle(position, maxRadius)
|
||||
local vehicles = GetAllVehicles()
|
||||
local dist = maxRadius
|
||||
local closestVehicle = nil
|
||||
|
||||
for i=1, #vehicles, 1 do
|
||||
local vehicleCoords = GetEntityCoords(vehicles[i])
|
||||
local tempDist = Vdist(vehicleCoords.x, vehicleCoords.y, vehicleCoords.z, position.x, position.y, position.z)
|
||||
if (tempDist < dist) then
|
||||
dist = tempDist
|
||||
closestVehicle = vehicles[i]
|
||||
end
|
||||
end
|
||||
|
||||
if (closestVehicle ~= nil and DoesEntityExist(closestVehicle)) then
|
||||
return closestVehicle
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns all loaded vehicles on client side
|
||||
function GetAllVehicles()
|
||||
local vehicles = {}
|
||||
|
||||
for vehicle in EnumerateVehicles() do
|
||||
table.insert(vehicles, vehicle)
|
||||
end
|
||||
|
||||
return vehicles
|
||||
end
|
||||
|
||||
function IsVehicleBlacklisted(vehicle)
|
||||
-- check class
|
||||
local class = GetVehicleClass(vehicle)
|
||||
for i = 1, #Config.classesBlacklist, 1 do
|
||||
if (class == Config.classesBlacklist[i]) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- check model
|
||||
local modelHash = GetEntityModel(vehicle)
|
||||
for i = 1, #Config.vehiclesBlacklist, 1 do
|
||||
if (modelHash == Config.vehiclesBlacklist[i]) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function GetVehiclePosition(plate)
|
||||
if (GetResourceState("kimi_callbacks") ~= "started") then
|
||||
Log("^1[ERROR] \"kimi_callbacks\" is either not installed properly or hasn't been started!")
|
||||
Log("^1[ERROR] The export \"GetVehiclePosition\" can only be used when having this resource installed.")
|
||||
return nil
|
||||
end
|
||||
|
||||
if (plate == nil) then
|
||||
Log("^1[ERROR] \"plate\" was nil while trying to call export \"GetVehiclePosition\"!")
|
||||
return nil
|
||||
end
|
||||
|
||||
if (type(plate) ~= "string") then
|
||||
Log("^1[ERROR] \"plate\" (\"" .. plate .. "\") needs to be of type string when calling export \"GetVehiclePosition\"!")
|
||||
return nil
|
||||
end
|
||||
|
||||
local position = exports["kimi_callbacks"]:Trigger("AP:getVehiclePosition", plate:upper())
|
||||
|
||||
return position
|
||||
end
|
||||
|
||||
function GetVehiclePositions(...)
|
||||
if (GetResourceState("kimi_callbacks") ~= "started") then
|
||||
Log("^1[ERROR] \"kimi_callbacks\" is either not installed properly or hasn't been started!")
|
||||
Log("^1[ERROR] The export \"GetVehiclePositions\" can only be used when having this resource installed.")
|
||||
return nil
|
||||
end
|
||||
|
||||
local plates = { ... }
|
||||
|
||||
for i, plate in ipairs(plates) do
|
||||
if (plate == nil) then
|
||||
Log("^1[ERROR] \"plate\" (Index: \"" .. i .. "\") was nil while trying to call export \"GetVehiclePositions\"!")
|
||||
return nil
|
||||
end
|
||||
|
||||
if (type(plate) ~= "string") then
|
||||
Log("^1[ERROR] \"plate\" (\"" .. plate .. "\") (Index: " .. i .. ") needs to be of type string when calling export \"GetVehiclePositions\"!")
|
||||
return nil
|
||||
end
|
||||
|
||||
plates[i] = plates[i]:upper()
|
||||
end
|
||||
|
||||
local data = exports["kimi_callbacks"]:Trigger("AP:getVehiclePositions", plates)
|
||||
|
||||
return data
|
||||
end
|
||||
|
||||
-- getting all vehicles
|
||||
function EnumerateVehicles()
|
||||
return EnumerateEntities(FindFirstVehicle, FindNextVehicle, EndFindVehicle)
|
||||
end
|
||||
function EnumerateEntities(initFunc, moveFunc, disposeFunc)
|
||||
return coroutine.wrap(function()
|
||||
local iter, id = initFunc()
|
||||
if not id or id == 0 then
|
||||
disposeFunc(iter)
|
||||
return
|
||||
end
|
||||
|
||||
local enum = {handle = iter, destructor = disposeFunc}
|
||||
setmetatable(enum, entityEnumerator)
|
||||
|
||||
local next = true
|
||||
repeat
|
||||
coroutine.yield(id)
|
||||
next, id = moveFunc(iter)
|
||||
until not next
|
||||
|
||||
enum.destructor, enum.handle = nil, nil
|
||||
disposeFunc(iter)
|
||||
end)
|
||||
end
|
||||
local entityEnumerator = {
|
||||
__gc = function(enum)
|
||||
if enum.destructor and enum.handle then
|
||||
enum.destructor(enum.handle)
|
||||
end
|
||||
enum.destructor = nil
|
||||
enum.handle = nil
|
||||
end
|
||||
}
|
210
resources/[Developer]/mh_Parking/client.lua
Normal file
210
resources/[Developer]/mh_Parking/client.lua
Normal file
|
@ -0,0 +1,210 @@
|
|||
local enabled = true
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while (true) do
|
||||
local playerPed = PlayerPedId()
|
||||
if (DoesEntityExist(playerPed)) then
|
||||
TriggerServerEvent("mh_Parking:syncPlayerPosition", GetEntityCoords(playerPed))
|
||||
end
|
||||
|
||||
Citizen.Wait(3000)
|
||||
end
|
||||
end)
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while (true) do
|
||||
Citizen.Wait(5 * 60 * 1000)
|
||||
|
||||
local vehicle = GetVehiclePedIsIn(PlayerPedId())
|
||||
if (DoesEntityExist(vehicle)) then
|
||||
TriggerEvent("mh_Parking:updateVehicle", vehicle)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
Citizen.Wait(3000)
|
||||
|
||||
local isInVehicle = false
|
||||
local currentVehiclePlate = nil
|
||||
local wasDead = false
|
||||
|
||||
while (true) do
|
||||
Citizen.Wait(50)
|
||||
|
||||
local playerPed = PlayerPedId()
|
||||
|
||||
if (not isInVehicle and IsPedInAnyVehicle(playerPed)) then
|
||||
-- entered vehicle
|
||||
|
||||
isInVehicle = true
|
||||
|
||||
if (enabled) then
|
||||
local vehicle = GetVehiclePedIsIn(playerPed, false)
|
||||
if (NetworkGetEntityIsNetworked(vehicle) and not IsVehicleBlacklisted(vehicle)) then
|
||||
local networkId = NetworkGetNetworkIdFromEntity(vehicle)
|
||||
SetNetworkIdCanMigrate(netId, true)
|
||||
local modifications = GetVehicleModifications(vehicle)
|
||||
|
||||
currentVehiclePlate = GetVehicleNumberPlateText(vehicle)
|
||||
|
||||
TriggerServerEvent("mh_Parking:enteredVehicle", networkId, currentVehiclePlate, modifications)
|
||||
|
||||
Log("Vehicle " .. currentVehiclePlate .. " entered")
|
||||
end
|
||||
end
|
||||
elseif (isInVehicle and not IsPedInAnyVehicle(playerPed, false)) then
|
||||
-- left vehicle
|
||||
|
||||
isInVehicle = false
|
||||
|
||||
if (enabled and not wasDead) then
|
||||
local vehicle = GetVehiclePedIsIn(playerPed, true)
|
||||
|
||||
if (vehicle ~= 0) then
|
||||
if (NetworkGetEntityIsNetworked(vehicle) and not IsVehicleBlacklisted(vehicle)) then
|
||||
local networkId = NetworkGetNetworkIdFromEntity(vehicle)
|
||||
SetNetworkIdCanMigrate(netId, true)
|
||||
local modifications = GetVehicleModifications(vehicle)
|
||||
|
||||
TriggerServerEvent("mh_Parking:leftVehicle", networkId, modifications)
|
||||
|
||||
Log("Vehicle " .. GetVehicleNumberPlateText(vehicle) .. " left")
|
||||
|
||||
-- if vehicle is deleted soon after
|
||||
Citizen.CreateThread(function()
|
||||
local veh = vehicle
|
||||
local plate = GetVehicleNumberPlateText(veh)
|
||||
local startTime = GetGameTimer()
|
||||
local playerPed = PlayerPedId()
|
||||
local playerPos
|
||||
|
||||
while (true) do
|
||||
Citizen.Wait(0)
|
||||
|
||||
if (GetGameTimer() - startTime >= 1000) then
|
||||
break
|
||||
end
|
||||
|
||||
if (not DoesEntityExist(veh)) then
|
||||
TriggerServerEvent("mh_Parking:deleteVehicle", plate, false)
|
||||
|
||||
Log("Vehicle " .. currentVehiclePlate .. " left and deleted after exit")
|
||||
|
||||
currentVehiclePlate = nil
|
||||
break
|
||||
end
|
||||
|
||||
playerPed = PlayerPedId()
|
||||
playerPos = GetEntityCoords(playerPed)
|
||||
vehPos = GetEntityCoords(veh)
|
||||
|
||||
if (Vdist(playerPos.x, playerPos.y, playerPos.z, vehPos.x, vehPos.y, vehPos.z) > 50.0) then
|
||||
currentVehiclePlate = nil
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
currentVehiclePlate = nil
|
||||
end)
|
||||
end
|
||||
elseif (currentVehiclePlate) then
|
||||
TriggerServerEvent("mh_Parking:deleteVehicle", currentVehiclePlate, false)
|
||||
|
||||
Log("Vehicle " .. currentVehiclePlate .. " left and deleted")
|
||||
|
||||
currentVehiclePlate = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (not wasDead and IsPlayerDead(PlayerId())) then
|
||||
wasDead = true
|
||||
elseif (wasDead and not IsPlayerDead(PlayerId())) then
|
||||
Citizen.CreateThread(function()
|
||||
Citizen.Wait(1000)
|
||||
|
||||
wasDead = false
|
||||
end)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("mh_Parking:setVehicleMods")
|
||||
AddEventHandler("mh_Parking:setVehicleMods", function(netId, plate, modifications)
|
||||
if (not IsModelInCdimage(modifications[1])) then
|
||||
Log("Setting mods for " .. plate .. " failed. The model does NOT exist.")
|
||||
TriggerServerEvent("mh_Parking:modelDoesNotExist", plate)
|
||||
return
|
||||
end
|
||||
|
||||
local timer = GetGameTimer()
|
||||
while (not NetworkDoesEntityExistWithNetworkId(netId)) do
|
||||
Citizen.Wait(0)
|
||||
|
||||
if (GetGameTimer() - 10000 > timer) then
|
||||
Log("Setting mods for " .. plate .. " failed after 10s")
|
||||
TriggerServerEvent("mh_Parking:setVehicleModsFailed", plate)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local vehicle = NetworkGetEntityFromNetworkId(netId)
|
||||
|
||||
if (DoesEntityExist(vehicle) and NetworkHasControlOfEntity(vehicle)) then
|
||||
Log("Setting modifications for vehicle " .. plate)
|
||||
|
||||
SetVehicleModifications(vehicle, plate, modifications)
|
||||
TriggerServerEvent("mh_Parking:setVehicleModsSuccess", plate)
|
||||
else
|
||||
Log("Setting mods failed for vehicle " .. plate .. ". Vehicle does not exist")
|
||||
TriggerServerEvent("mh_Parking:setVehicleModsFailed", plate)
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler("mh_Parking:updateVehicle", function(vehicle)
|
||||
if (vehicle == nil) then
|
||||
Log("^1[ERROR] \"vehicle\" was nil while trying to update a vehicle!")
|
||||
return
|
||||
end
|
||||
|
||||
if (DoesEntityExist(vehicle) and NetworkGetEntityIsNetworked(vehicle) and not IsVehicleBlacklisted(vehicle)) then
|
||||
Log("Triggering manual update of vehicle")
|
||||
|
||||
local networkId = NetworkGetNetworkIdFromEntity(vehicle)
|
||||
local modifications = GetVehicleModifications(vehicle)
|
||||
|
||||
TriggerServerEvent("mh_Parking:updateVehicle", networkId, modifications)
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("mh_Parking:enable")
|
||||
AddEventHandler("mh_Parking:enable", function(enable)
|
||||
if (enable == nil) then
|
||||
Log("^1[ERROR] \"enable\" was nil while trying to enable/disable script!")
|
||||
return
|
||||
end
|
||||
|
||||
enabled = enable
|
||||
|
||||
if (enabled) then
|
||||
Log("AdvancedParking enabled")
|
||||
else
|
||||
Log("AdvancedParking disabled")
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("mh_Parking:notification")
|
||||
AddEventHandler("mh_Parking:notification", function(msg)
|
||||
SetNotificationTextEntry('STRING')
|
||||
AddTextComponentSubstringPlayerName(msg)
|
||||
DrawNotification(false, true)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("mh_Parking:renderScorched")
|
||||
AddEventHandler("mh_Parking:renderScorched", function(vehicleNetId, scorched)
|
||||
local vehicle = NetworkGetEntityFromNetworkId(vehicleNetId)
|
||||
if (DoesEntityExist(vehicle)) then
|
||||
SetEntityRenderScorched(vehicle, scorched)
|
||||
end
|
||||
end)
|
64
resources/[Developer]/mh_Parking/config.lua
Normal file
64
resources/[Developer]/mh_Parking/config.lua
Normal file
|
@ -0,0 +1,64 @@
|
|||
Config = {}
|
||||
|
||||
Config.exports = "lc_fuel" -- LegacyFuel
|
||||
|
||||
-- set this to true if you want to see debug messages on client and server side
|
||||
Config.isDebug = false
|
||||
|
||||
-- this controls the distance at which vehicles will spawn to the closest player
|
||||
-- (in meters)
|
||||
Config.spawnDistance = 200.0
|
||||
|
||||
-- this controls when a vehicle will be removed from the database table when
|
||||
-- calling the cleanup function (in hours; so 24 * 7 = one week)
|
||||
Config.cleanUpThresholdTime = 24 * 7
|
||||
|
||||
-- set this to false if you do not want entities render as scorched when they
|
||||
-- are completely broken
|
||||
Config.renderScorched = true
|
||||
|
||||
-- vehicle classes that you do not want to save go here (remove the -- in front
|
||||
-- of the number if you want it blacklisted)
|
||||
Config.classesBlacklist = {
|
||||
-- 0, -- Compacts
|
||||
-- 1, -- Sedans
|
||||
-- 2, -- SUVs
|
||||
-- 3, -- Coupes
|
||||
-- 4, -- Muscle
|
||||
-- 5, -- Sports Classics
|
||||
-- 6, -- Sports
|
||||
-- 7, -- Super
|
||||
-- 8, -- Motorcycles
|
||||
-- 9, -- Off-road
|
||||
--10, -- Industrial
|
||||
--11, -- Utility
|
||||
--12, -- Vans
|
||||
--13, -- Cycles
|
||||
--14, -- Boats
|
||||
--15, -- Helicopters
|
||||
--16, -- Planes
|
||||
--17, -- Service
|
||||
--18, -- Emergency
|
||||
--19, -- Military
|
||||
--20, -- Commercial
|
||||
21, -- Trains
|
||||
}
|
||||
-- other vehicles that you do not want to save can be inserted here (use `MODELNAME`
|
||||
-- when you put them in there)
|
||||
Config.vehiclesBlacklist = {
|
||||
--`blista`,
|
||||
}
|
||||
|
||||
-- this lets you control if vehicles should be deleted (in minutes; 0 if you do not
|
||||
-- want to use it; this is useful for large servers with a lot of players)
|
||||
Config.deleteTimer = 0
|
||||
-- despawns all vehicles that are more than x meters away from a player
|
||||
Config.deleteDistance = 25.0
|
||||
-- when the notifications should be shown before the despawning
|
||||
-- needs to be in descending order in minutes and lower than Config.deleteTimer
|
||||
Config.deleteNotificationTimes = { 5, 3, 2, 1 }
|
||||
-- notification to show players before deleting vehicles
|
||||
-- (use %s as placeholder for time left in minutes)
|
||||
Config.timeLeftNotification = "Fahrzeuge Despawn in %s Minuten."
|
||||
-- notification to show players when deleting vehicles
|
||||
Config.deleteNotification = "Lösche Fahrzeuge..."
|
24
resources/[Developer]/mh_Parking/fxmanifest.lua
Normal file
24
resources/[Developer]/mh_Parking/fxmanifest.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
fx_version 'cerulean'
|
||||
games { 'gta5' }
|
||||
|
||||
author 'Mîhó'
|
||||
description 'Park all your vehicles anywhere!'
|
||||
version '1.0.0'
|
||||
|
||||
server_scripts {
|
||||
'@oxmysql/lib/MySQL.lua',
|
||||
'config.lua',
|
||||
'sv_utils.lua',
|
||||
'server.lua'
|
||||
}
|
||||
|
||||
client_scripts {
|
||||
'config.lua',
|
||||
'cl_utils.lua',
|
||||
'client.lua'
|
||||
}
|
||||
|
||||
exports {
|
||||
'GetVehiclePosition',
|
||||
'GetVehiclePositions'
|
||||
}
|
32
resources/[Developer]/mh_Parking/mh_Parking.sql
Normal file
32
resources/[Developer]/mh_Parking/mh_Parking.sql
Normal file
|
@ -0,0 +1,32 @@
|
|||
-- --------------------------------------------------------
|
||||
-- Host: 127.0.0.1
|
||||
-- Server version: 10.1.28-MariaDB - mariadb.org binary distribution
|
||||
-- Server OS: Win32
|
||||
-- HeidiSQL Version: 11.0.0.5919
|
||||
-- --------------------------------------------------------
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!50503 SET NAMES utf8mb4 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
|
||||
-- Dumping structure for table fivem_testserver.vehicle_parking
|
||||
CREATE TABLE IF NOT EXISTS `vehicle_parking` (
|
||||
`plate` varchar(8) NOT NULL,
|
||||
`modifications` text NOT NULL,
|
||||
`posX` float NOT NULL,
|
||||
`posY` float NOT NULL,
|
||||
`posZ` float NOT NULL,
|
||||
`rotX` float NOT NULL,
|
||||
`rotY` float NOT NULL,
|
||||
`rotZ` float NOT NULL,
|
||||
`lastUpdate` int(11) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`plate`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
-- Data exporting was unselected.
|
||||
|
||||
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
770
resources/[Developer]/mh_Parking/server.lua
Normal file
770
resources/[Developer]/mh_Parking/server.lua
Normal file
|
@ -0,0 +1,770 @@
|
|||
local vehicles = {}
|
||||
local DB_vehicles = {}
|
||||
|
||||
-- Command to delete ALL vehicles from the database table. Needs to be executed twice for security reason.
|
||||
local deleteSavedVehicles = false
|
||||
RegisterCommand("deleteSavedVehicles", function(source, args, raw)
|
||||
if (deleteSavedVehicles) then
|
||||
MySQL.query("DELETE FROM vehicle_parking", { })
|
||||
|
||||
vehicles = {}
|
||||
|
||||
Log("Deleted all vehicles from the vehicle_parking table.")
|
||||
else
|
||||
Log("Are you sure that you want to delete all vehicles from the parking list?\nIf yes, type the command a second time!")
|
||||
end
|
||||
|
||||
deleteSavedVehicles = not deleteSavedVehicles
|
||||
end, true)
|
||||
|
||||
-- read all vehicles from the database on startup and do a cleanup check
|
||||
MySQL.ready(function()
|
||||
-- fetch all database results
|
||||
MySQL.query("SELECT plate, posX, posY, posZ, rotX, rotY, rotZ, modifications, lastUpdate FROM vehicle_parking", {}, function(results)
|
||||
Log("Found " .. #results .. " saved vehicles in vehicle_parking.")
|
||||
|
||||
for i = 1, #results do
|
||||
vehicles[results[i].plate] = {
|
||||
handle = nil,
|
||||
position = vector3(results[i].posX, results[i].posY, results[i].posZ),
|
||||
rotation = vector3(results[i].rotX, results[i].rotY, results[i].rotZ),
|
||||
modifications = json.decode(results[i].modifications),
|
||||
lastUpdate = results[i].lastUpdate,
|
||||
spawning = false,
|
||||
spawningPlayer = nil,
|
||||
faultyModel = false
|
||||
}
|
||||
end
|
||||
|
||||
--CleanUp()
|
||||
end)
|
||||
end)
|
||||
|
||||
-- Default CleanUp function. Deletes vehicles from the database after a specific amount of time has passed (configurable in config)
|
||||
function CleanUp()
|
||||
local currentTime = os.time()
|
||||
local threshold = 60 * 60 * Config.cleanUpThresholdTime
|
||||
|
||||
local toDelete = {}
|
||||
|
||||
for plate, vehicle in pairs(vehicles) do
|
||||
if (vehicle.lastUpdate < os.difftime(currentTime, threshold)) then
|
||||
|
||||
MySQL.query("DELETE FROM vehicle_parking WHERE plate = @plate",
|
||||
{
|
||||
["@plate"] = plate
|
||||
})
|
||||
|
||||
table.insert(toDelete, plate)
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, #toDelete, 1 do
|
||||
local plate = toDelete[i]
|
||||
vehicles[plate] = nil
|
||||
end
|
||||
|
||||
Log("CleanUp complete. Deleted " .. #toDelete .. " entries.")
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- loop to spawn vehicles near players
|
||||
Citizen.CreateThread(function()
|
||||
while (true) do
|
||||
Citizen.Wait(5000)
|
||||
|
||||
if (GetActivePlayerCount() > 0) then
|
||||
TrySpawnVehicles()
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while (true) do
|
||||
CallDB_Vehicles()
|
||||
Citizen.Wait(60000 * 5)
|
||||
end
|
||||
end)
|
||||
|
||||
-- loop to delete vehicles
|
||||
Citizen.CreateThread(function()
|
||||
if (Config.deleteTimer <= 0) then
|
||||
return
|
||||
end
|
||||
|
||||
while (true) do
|
||||
Citizen.Wait(60000 * (Config.deleteTimer - Config.deleteNotificationTimes[1]))
|
||||
|
||||
TriggerClientEvent("mh_Parking:notification", -1, string.format(Config.timeLeftNotification, Config.deleteNotificationTimes[1]))
|
||||
for i = 2, #Config.deleteNotificationTimes, 1 do
|
||||
Citizen.Wait(60000 * (Config.deleteNotificationTimes[i - 1] - Config.deleteNotificationTimes[i]))
|
||||
TriggerClientEvent("mh_Parking:notification", -1, string.format(Config.timeLeftNotification, Config.deleteNotificationTimes[i]))
|
||||
end
|
||||
Citizen.Wait(60000 * Config.deleteNotificationTimes[#Config.deleteNotificationTimes])
|
||||
|
||||
DeleteAllVehicles()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
-- sync player position
|
||||
RegisterServerEvent("mh_Parking:syncPlayerPosition")
|
||||
AddEventHandler("mh_Parking:syncPlayerPosition", function(position)
|
||||
activePlayerPositions[source] = position
|
||||
end)
|
||||
|
||||
-- player disconnected
|
||||
AddEventHandler("playerDropped", function(disconnectReason)
|
||||
activePlayerPositions[source] = nil
|
||||
end)
|
||||
|
||||
-- player entered a vehicle
|
||||
RegisterServerEvent("mh_Parking:enteredVehicle")
|
||||
AddEventHandler("mh_Parking:enteredVehicle", function(networkId, plate, modifications)
|
||||
local vehicle = NetworkGetEntityFromNetworkId(networkId)
|
||||
|
||||
if (DoesEntityExist(vehicle)) then
|
||||
local currentTime = os.time()
|
||||
|
||||
local position = GetEntityCoords(vehicle)
|
||||
position = vector3(math.floor(position.x * 100.0) / 100.0, math.floor(position.y * 100.0) / 100.0, math.floor(position.z * 100.0) / 100.0)
|
||||
local rotation = GetEntityRotation(vehicle)
|
||||
rotation = vector3(math.floor(rotation.x * 100.0) / 100.0, math.floor(rotation.y * 100.0) / 100.0, math.floor(rotation.z * 100.0) / 100.0)
|
||||
|
||||
if (vehicles[plate]) then
|
||||
-- already on server list
|
||||
|
||||
Log("Entered vehicle " .. plate .. ". Updating...")
|
||||
|
||||
if (vehicles[plate].handle ~= vehicle) then
|
||||
if (DoesEntityExist(vehicles[plate].handle)) then
|
||||
DeleteEntity(vehicles[plate].handle)
|
||||
end
|
||||
|
||||
vehicles[plate].handle = vehicle
|
||||
end
|
||||
|
||||
vehicles[plate].position = position
|
||||
vehicles[plate].rotation = rotation
|
||||
vehicles[plate].modifications = modifications
|
||||
vehicles[plate].lastUpdate = currentTime
|
||||
|
||||
MySQL.query("UPDATE vehicle_parking SET posX = @posX, posY = @posY, posZ = @posZ, rotX = @rotX, rotY = @rotY, rotZ = @rotZ, modifications = @modifications, lastUpdate = @lastUpdate WHERE plate = @plate", {
|
||||
["@plate"] = plate,
|
||||
["@posX"] = vehicles[plate].position.x,
|
||||
["@posY"] = vehicles[plate].position.y,
|
||||
["@posZ"] = vehicles[plate].position.z,
|
||||
["@rotX"] = vehicles[plate].rotation.x,
|
||||
["@rotY"] = vehicles[plate].rotation.y,
|
||||
["@rotZ"] = vehicles[plate].rotation.z,
|
||||
["@modifications"] = json.encode(vehicles[plate].modifications),
|
||||
["@lastUpdate"] = vehicles[plate].lastUpdate
|
||||
})
|
||||
else
|
||||
-- insert in db
|
||||
|
||||
Log("Entered vehicle " .. plate .. ". Inserting new...")
|
||||
|
||||
vehicles[plate] = {
|
||||
handle = vehicle,
|
||||
position = position,
|
||||
rotation = rotation,
|
||||
modifications = modifications,
|
||||
lastUpdate = currentTime,
|
||||
spawning = false,
|
||||
spawningPlayer = nil
|
||||
}
|
||||
|
||||
MySQL.query('SELECT * FROM player_vehicles WHERE plate = @plate', { ['@plate'] = plate }, function(rs)
|
||||
Log(json.encode(rs))
|
||||
if rs[1] then
|
||||
Log("FOUND OWNER FROM VEHICLE")
|
||||
|
||||
MySQL.query("INSERT INTO vehicle_parking (plate, posX, posY, posZ, rotX, rotY, rotZ, modifications, lastUpdate) VALUES (@plate, @posX, @posY, @posZ, @rotX, @rotY, @rotZ, @modifications, @lastUpdate)", {
|
||||
["@plate"] = plate,
|
||||
["@posX"] = vehicles[plate].position.x,
|
||||
["@posY"] = vehicles[plate].position.y,
|
||||
["@posZ"] = vehicles[plate].position.z,
|
||||
["@rotX"] = vehicles[plate].rotation.x,
|
||||
["@rotY"] = vehicles[plate].rotation.y,
|
||||
["@rotZ"] = vehicles[plate].rotation.z,
|
||||
["@modifications"] = json.encode(vehicles[plate].modifications),
|
||||
["@lastUpdate"] = vehicles[plate].lastUpdate
|
||||
})
|
||||
else
|
||||
Log("1: NO VEHICLE FOUND")
|
||||
end
|
||||
end)
|
||||
end
|
||||
else
|
||||
Log("Vehicle does not exist. Might be a Onesync error.")
|
||||
end
|
||||
end)
|
||||
|
||||
-- player left a vehicle
|
||||
RegisterServerEvent("mh_Parking:leftVehicle")
|
||||
AddEventHandler("mh_Parking:leftVehicle", function(networkId, modifications)
|
||||
local vehicle = NetworkGetEntityFromNetworkId(networkId)
|
||||
|
||||
if (DoesEntityExist(vehicle)) then
|
||||
local currentTime = os.time()
|
||||
|
||||
local plate = GetVehicleNumberPlateText(vehicle)
|
||||
|
||||
local position = GetEntityCoords(vehicle)
|
||||
position = vector3(math.floor(position.x * 100.0) / 100.0, math.floor(position.y * 100.0) / 100.0, math.floor(position.z * 100.0) / 100.0)
|
||||
local rotation = GetEntityRotation(vehicle)
|
||||
rotation = vector3(math.floor(rotation.x * 100.0) / 100.0, math.floor(rotation.y * 100.0) / 100.0, math.floor(rotation.z * 100.0) / 100.0)
|
||||
|
||||
if (vehicles[plate]) then
|
||||
-- already on server list
|
||||
|
||||
Log("Left vehicle " .. plate .. ". Updating...")
|
||||
|
||||
if (vehicles[plate].handle ~= vehicle) then
|
||||
if (DoesEntityExist(vehicles[plate].handle)) then
|
||||
DeleteEntity(vehicles[plate].handle)
|
||||
end
|
||||
|
||||
vehicles[plate].handle = vehicle
|
||||
end
|
||||
|
||||
vehicles[plate].position = position
|
||||
vehicles[plate].rotation = rotation
|
||||
vehicles[plate].modifications = modifications
|
||||
vehicles[plate].lastUpdate = currentTime
|
||||
|
||||
MySQL.query("UPDATE vehicle_parking SET posX = @posX, posY = @posY, posZ = @posZ, rotX = @rotX, rotY = @rotY, rotZ = @rotZ, modifications = @modifications, lastUpdate = @lastUpdate WHERE plate = @plate",{
|
||||
["@plate"] = plate,
|
||||
["@posX"] = vehicles[plate].position.x,
|
||||
["@posY"] = vehicles[plate].position.y,
|
||||
["@posZ"] = vehicles[plate].position.z,
|
||||
["@rotX"] = vehicles[plate].rotation.x,
|
||||
["@rotY"] = vehicles[plate].rotation.y,
|
||||
["@rotZ"] = vehicles[plate].rotation.z,
|
||||
["@modifications"] = json.encode(vehicles[plate].modifications),
|
||||
["@lastUpdate"] = currentTime
|
||||
})
|
||||
else
|
||||
-- insert in db
|
||||
|
||||
Log("Left vehicle " .. plate .. ". Inserting new...")
|
||||
|
||||
vehicles[plate] = {
|
||||
handle = vehicle,
|
||||
position = position,
|
||||
rotation = rotation,
|
||||
modifications = modifications,
|
||||
lastUpdate = currentTime,
|
||||
spawning = false,
|
||||
spawningPlayer = nil
|
||||
}
|
||||
|
||||
MySQL.query('SELECT * FROM player_vehicles WHERE plate = @plate', { ['@plate'] = plate }, function(rs)
|
||||
if rs[1] then
|
||||
Log("FOUND OWNER FROM VEHICLE")
|
||||
|
||||
MySQL.query("INSERT INTO vehicle_parking (plate, posX, posY, posZ, rotX, rotY, rotZ, modifications, lastUpdate) VALUES (@plate, @posX, @posY, @posZ, @rotX, @rotY, @rotZ, @modifications, @lastUpdate)",{
|
||||
["@plate"] = plate,
|
||||
["@posX"] = vehicles[plate].position.x,
|
||||
["@posY"] = vehicles[plate].position.y,
|
||||
["@posZ"] = vehicles[plate].position.z,
|
||||
["@rotX"] = vehicles[plate].rotation.x,
|
||||
["@rotY"] = vehicles[plate].rotation.y,
|
||||
["@rotZ"] = vehicles[plate].rotation.z,
|
||||
["@modifications"] = json.encode(vehicles[plate].modifications),
|
||||
["@lastUpdate"] = vehicles[plate].lastUpdate
|
||||
})
|
||||
else
|
||||
Log("2: NO VEHICLE FOUND")
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- update a vehicle with its modifications
|
||||
RegisterServerEvent("mh_Parking:updateVehicle")
|
||||
AddEventHandler("mh_Parking:updateVehicle", function(networkId, modifications)
|
||||
local vehicle = NetworkGetEntityFromNetworkId(networkId)
|
||||
|
||||
if (DoesEntityExist(vehicle)) then
|
||||
local currentTime = os.time()
|
||||
|
||||
local plate = GetVehicleNumberPlateText(vehicle)
|
||||
|
||||
local position = GetEntityCoords(vehicle)
|
||||
position = vector3(math.floor(position.x * 100.0) / 100.0, math.floor(position.y * 100.0) / 100.0, math.floor(position.z * 100.0) / 100.0)
|
||||
local rotation = GetEntityRotation(vehicle)
|
||||
rotation = vector3(math.floor(rotation.x * 100.0) / 100.0, math.floor(rotation.y * 100.0) / 100.0, math.floor(rotation.z * 100.0) / 100.0)
|
||||
|
||||
if (vehicles[plate] ~= nil) then
|
||||
-- already on server list
|
||||
|
||||
Log("Updating vehicle " .. plate)
|
||||
|
||||
if (vehicles[plate].handle ~= vehicle) then
|
||||
if (DoesEntityExist(vehicles[plate].handle)) then
|
||||
DeleteEntity(vehicles[plate].handle)
|
||||
end
|
||||
|
||||
vehicles[plate].handle = vehicle
|
||||
end
|
||||
|
||||
vehicles[plate].position = position
|
||||
vehicles[plate].rotation = rotation
|
||||
vehicles[plate].modifications = modifications
|
||||
vehicles[plate].lastUpdate = currentTime
|
||||
|
||||
MySQL.query("UPDATE vehicle_parking SET posX = @posX, posY = @posY, posZ = @posZ, rotX = @rotX, rotY = @rotY, rotZ = @rotZ, modifications = @modifications, lastUpdate = @lastUpdate WHERE plate = @plate",{
|
||||
["@plate"] = plate,
|
||||
["@posX"] = vehicles[plate].position.x,
|
||||
["@posY"] = vehicles[plate].position.y,
|
||||
["@posZ"] = vehicles[plate].position.z,
|
||||
["@rotX"] = vehicles[plate].rotation.x,
|
||||
["@rotY"] = vehicles[plate].rotation.y,
|
||||
["@rotZ"] = vehicles[plate].rotation.z,
|
||||
["@modifications"] = json.encode(vehicles[plate].modifications),
|
||||
["@lastUpdate"] = vehicles[plate].lastUpdate
|
||||
})
|
||||
else
|
||||
-- insert in db
|
||||
|
||||
Log("Updating vehicle " .. plate .. ". Inserting new...")
|
||||
|
||||
vehicles[plate] = {
|
||||
handle = vehicle,
|
||||
position = position,
|
||||
rotation = rotation,
|
||||
modifications = modifications,
|
||||
lastUpdate = currentTime,
|
||||
spawning = false,
|
||||
spawningPlayer = nil
|
||||
}
|
||||
|
||||
MySQL.query('SELECT * FROM player_vehicles WHERE plate = @plate', { ['@plate'] = plate }, function(rs)
|
||||
if rs[1] then
|
||||
Log("FOUND OWNER FROM VEHICLE")
|
||||
|
||||
MySQL.query("INSERT INTO vehicle_parking (plate, posX, posY, posZ, rotX, rotY, rotZ, modifications, lastUpdate) VALUES (@plate, @posX, @posY, @posZ, @rotX, @rotY, @rotZ, @modifications, @lastUpdate)",{
|
||||
["@plate"] = plate,
|
||||
["@posX"] = vehicles[plate].position.x,
|
||||
["@posY"] = vehicles[plate].position.y,
|
||||
["@posZ"] = vehicles[plate].position.z,
|
||||
["@rotX"] = vehicles[plate].rotation.x,
|
||||
["@rotY"] = vehicles[plate].rotation.y,
|
||||
["@rotZ"] = vehicles[plate].rotation.z,
|
||||
["@modifications"] = json.encode(vehicles[plate].modifications),
|
||||
["@lastUpdate"] = vehicles[plate].lastUpdate
|
||||
})
|
||||
else
|
||||
Log("3: NO VEHICLE FOUND")
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- delete a vehicle from the table (and world) with its plate
|
||||
RegisterServerEvent("mh_Parking:deleteVehicle")
|
||||
AddEventHandler("mh_Parking:deleteVehicle", function(plate, deleteEntity)
|
||||
if (plate == nil) then
|
||||
Log("^1mh_Parking: \"plate\" was nil while trying to delete vehicle!")
|
||||
return
|
||||
end
|
||||
|
||||
Log("Trying to delete " .. tostring(plate))
|
||||
|
||||
if (vehicles[plate] ~= nil) then
|
||||
if (deleteEntity and DoesEntityExist(vehicles[plate].handle)) then
|
||||
DeleteEntity(vehicles[plate].handle)
|
||||
end
|
||||
|
||||
vehicles[plate] = nil
|
||||
|
||||
MySQL.query("DELETE FROM vehicle_parking WHERE plate = @plate",
|
||||
{
|
||||
["@plate"] = plate
|
||||
})
|
||||
else
|
||||
local loadedVehicles = GetAllVehicles()
|
||||
local loadedVehicle = TryGetLoadedVehicle(plate, loadedVehicles)
|
||||
|
||||
if (loadedVehicle ~= nil) then
|
||||
if (deleteEntity and DoesEntityExist(loadedVehicle)) then
|
||||
DeleteEntity(loadedVehicle)
|
||||
end
|
||||
|
||||
MySQL.query("DELETE FROM vehicle_parking WHERE plate = @plate",
|
||||
{
|
||||
["@plate"] = plate
|
||||
})
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- checks if vehicles have to be spawned and spawns them if necessary
|
||||
function TrySpawnVehicles()
|
||||
local loadedVehicles = GetAllVehicles()
|
||||
|
||||
local playerVehiclePlates = {}
|
||||
for id, position in pairs(activePlayerPositions) do
|
||||
local ped = GetPlayerPed(id)
|
||||
local veh = GetVehiclePedIsIn(ped, false)
|
||||
|
||||
if (DoesEntityExist(veh)) then
|
||||
table.insert(playerVehiclePlates, GetVehicleNumberPlateText(veh))
|
||||
end
|
||||
end
|
||||
|
||||
-- check, if vehicles need to be spawned
|
||||
for plate, vehicleData in pairs(vehicles) do
|
||||
local plateCheck = CheckPlate(plate)
|
||||
if (plateCheck ~= false) then
|
||||
|
||||
if (not vehicleData.faultyModel) then
|
||||
if (not vehicleData.spawning) then
|
||||
local closestPlayer, dist = GetClosestPlayerId(vehicleData.position)
|
||||
|
||||
if (closestPlayer ~= nil and dist < Config.spawnDistance and not ContainsPlate(plate, playerVehiclePlates)) then
|
||||
if (vehicleData.handle ~= nil and DoesEntityExist(vehicleData.handle)) then
|
||||
-- vehicle found on server side
|
||||
|
||||
UpdateVehicle(plate)
|
||||
else
|
||||
-- vehicle not found on server side
|
||||
-- check, if it is loaded differently
|
||||
|
||||
local loadedVehicle = TryGetLoadedVehicle(plate, loadedVehicles)
|
||||
if (loadedVehicle ~= nil) then
|
||||
-- vehicle found
|
||||
|
||||
vehicleData.handle = loadedVehicle
|
||||
|
||||
UpdateVehicle(plate)
|
||||
else
|
||||
-- vehicle not found
|
||||
-- try and spawn it
|
||||
|
||||
local playerId, distance = GetClosestPlayerId(vehicleData.position)
|
||||
if (playerId and distance < Config.spawnDistance) then
|
||||
vehicleData.spawning = true
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
local vec4 = vector4(vehicleData.position.x, vehicleData.position.y, vehicleData.position.z, vehicleData.rotation.z)
|
||||
local vehicle = Citizen.InvokeNative(GetHashKey("CREATE_AUTOMOBILE"), vehicleData.modifications[1], vec4.xyzw)
|
||||
|
||||
while (not DoesEntityExist(vehicle)) do
|
||||
Citizen.Wait(0)
|
||||
end
|
||||
|
||||
SetEntityCoords(vehicle, vehicleData.position.x, vehicleData.position.y, vehicleData.position.z)
|
||||
SetEntityRotation(vehicle, vehicleData.rotation.x, vehicleData.rotation.y, vehicleData.rotation.z)
|
||||
|
||||
vehicleData.handle = vehicle
|
||||
|
||||
local networkOwner = -1
|
||||
while (networkOwner == -1) do
|
||||
Citizen.Wait(0)
|
||||
networkOwner = NetworkGetEntityOwner(vehicleData.handle)
|
||||
end
|
||||
|
||||
vehicleData.spawningPlayer = GetPlayerIdentifiersSorted(networkOwner)["license"]
|
||||
|
||||
Log("Creating vehicle " .. plate .. " at " .. tostring(vehicleData.position) .. " at entity owner " .. tostring(networkOwner))
|
||||
|
||||
TriggerClientEvent("mh_Parking:setVehicleMods", networkOwner, NetworkGetNetworkIdFromEntity(vehicleData.handle), plate, vehicleData.modifications)
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif (vehicleData.spawningPlayer) then
|
||||
-- if vehicle is currently spawning check if responsible player is still connected
|
||||
if (not IsPlayerWithLicenseActive(vehicleData.spawningPlayer)) then
|
||||
TriggerEvent("mh_Parking:setVehicleModsFailed", plate)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RegisterServerEvent("mh_Parking:setVehicleModsSuccess")
|
||||
AddEventHandler("mh_Parking:setVehicleModsSuccess", function(plate)
|
||||
Log("Setting mods successful...")
|
||||
|
||||
if (vehicles[plate]) then
|
||||
vehicles[plate].spawning = false
|
||||
vehicles[plate].spawningPlayer = nil
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterServerEvent("mh_Parking:setVehicleModsFailed")
|
||||
AddEventHandler("mh_Parking:setVehicleModsFailed", function(plate)
|
||||
Log("Setting mods for " .. plate .. " failed... retrying...")
|
||||
|
||||
if (vehicles[plate] and vehicles[plate].handle and DoesEntityExist(vehicles[plate].handle)) then
|
||||
local networkOwner = -1
|
||||
while (networkOwner == -1) do
|
||||
Citizen.Wait(0)
|
||||
networkOwner = NetworkGetEntityOwner(vehicles[plate].handle)
|
||||
end
|
||||
|
||||
local netOwnerLicense = GetPlayerIdentifiersSorted(networkOwner)["license"]
|
||||
if (netOwnerLicense ~= nil) then
|
||||
vehicles[plate].spawningPlayer = GetPlayerIdentifiersSorted(networkOwner)["license"]
|
||||
|
||||
TriggerClientEvent("mh_Parking:setVehicleMods", networkOwner, NetworkGetNetworkIdFromEntity(vehicles[plate].handle), plate, vehicles[plate].modifications)
|
||||
else
|
||||
Log("Something went wrong while trying to get player license for spawning vehicle " .. tostring(plate) .. ". Despawning vehicle")
|
||||
|
||||
DeleteEntity(vehicles[plate].handle)
|
||||
|
||||
vehicles[plate].handle = nil
|
||||
vehicles[plate].spawningPlayer = nil
|
||||
vehicles[plate].spawning = false
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterServerEvent("mh_Parking:modelDoesNotExist")
|
||||
AddEventHandler("mh_Parking:modelDoesNotExist", function(plate)
|
||||
if (vehicles[plate] == nil) then
|
||||
return
|
||||
end
|
||||
|
||||
if (DoesEntityExist(vehicles[plate].handle)) then
|
||||
DeleteEntity(vehicles[plate].handle)
|
||||
end
|
||||
vehicles[plate].handle = nil
|
||||
vehicles[plate].spawningPlayer = nil
|
||||
vehicles[plate].spawning = false
|
||||
|
||||
Log("The model for vehicle " .. tostring(plate) .. " does not exist. Removing from spawn pool...")
|
||||
|
||||
vehicles[plate].faultyModel = true
|
||||
end)
|
||||
|
||||
RegisterServerEvent("mh_Parking:updatePlate")
|
||||
AddEventHandler("mh_Parking:updatePlate", function(oldPlate, newPlate)
|
||||
if (oldPlate == nil or newPlate == nil) then
|
||||
Log("^1mh_Parking: \"oldPlate\" or \"newPlate\" was nil while trying to update a plate!")
|
||||
return
|
||||
end
|
||||
|
||||
if (vehicles[oldPlate]) then
|
||||
if (vehicles[newPlate]) then
|
||||
Log("Updating plate failed. New plate was already there!")
|
||||
else
|
||||
vehicles[newPlate] = vehicles[oldPlate]
|
||||
vehicles[oldPlate] = nil
|
||||
|
||||
Log("Updating plate successful!")
|
||||
|
||||
MySQL.query("UPDATE vehicle_parking SET plate = @newPlate WHERE plate = @oldPlate",
|
||||
{
|
||||
["@newPlate"] = newPlate,
|
||||
["@oldPlate"] = oldPlate
|
||||
})
|
||||
end
|
||||
else
|
||||
Log("Updating plate failed or unnecessary. Old plate was not found!")
|
||||
end
|
||||
end)
|
||||
|
||||
function UpdateVehicle(plate)
|
||||
local newPos = GetEntityCoords(vehicles[plate].handle)
|
||||
local newRot = GetEntityRotation(vehicles[plate].handle)
|
||||
newPos = vector3(math.floor(newPos.x * 100.0) * 0.01, math.floor(newPos.y * 100.0) * 0.01, math.floor(newPos.z * 100.0) * 0.01)
|
||||
newRot = vector3(math.floor(newRot.x * 100.0) * 0.01, math.floor(newRot.y * 100.0) * 0.01, math.floor(newRot.z * 100.0) * 0.01)
|
||||
|
||||
local newLockStatus = GetVehicleDoorLockStatus(vehicles[plate].handle)
|
||||
local newEngineHealth = math.floor(GetVehicleEngineHealth(vehicles[plate].handle) * 10.0) * 0.1
|
||||
local newTankHealth = math.floor(GetVehiclePetrolTankHealth(vehicles[plate].handle) * 10.0) * 0.1
|
||||
if (Vector3DistFast(vehicles[plate].position, newPos) > 1.0
|
||||
or GetRotationDifference(vehicles[plate].rotation, newRot) > 15.0
|
||||
or newLockStatus ~= vehicles[plate].modifications[2]
|
||||
or math.abs(newEngineHealth - vehicles[plate].modifications[5]) > 5.0
|
||||
or math.abs(newTankHealth - vehicles[plate].modifications[6]) > 5.0
|
||||
) then
|
||||
vehicles[plate].modifications[2] = newLockStatus
|
||||
vehicles[plate].modifications[5] = newEngineHealth
|
||||
vehicles[plate].modifications[6] = newTankHealth
|
||||
|
||||
Log("Updating vehicle " .. plate)
|
||||
|
||||
vehicles[plate].position = newPos
|
||||
vehicles[plate].rotation = newRot
|
||||
|
||||
MySQL.query("UPDATE vehicle_parking SET posX = @posX, posY = @posY, posZ = @posZ, rotX = @rotX, rotY = @rotY, rotZ = @rotZ, modifications = @modifications WHERE plate = @plate",
|
||||
{
|
||||
["@posX"] = vehicles[plate].position.x,
|
||||
["@posY"] = vehicles[plate].position.y,
|
||||
["@posZ"] = vehicles[plate].position.z,
|
||||
["@rotX"] = vehicles[plate].rotation.x,
|
||||
["@rotY"] = vehicles[plate].rotation.y,
|
||||
["@rotZ"] = vehicles[plate].rotation.z,
|
||||
["@modifications"] = json.encode(vehicles[plate].modifications),
|
||||
["@plate"] = plate
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function DeleteAllVehicles()
|
||||
TriggerClientEvent("mh_Parking:notification", -1, Config.deleteNotification)
|
||||
|
||||
local peds = GetAllPeds()
|
||||
local playerPeds = {}
|
||||
for i = 1, #peds, 1 do
|
||||
if (IsPedAPlayer(peds[i])) then
|
||||
table.insert(playerPeds, peds[i])
|
||||
end
|
||||
end
|
||||
|
||||
if (#playerPeds == 0) then
|
||||
return
|
||||
end
|
||||
|
||||
local time = GetGameTimer()
|
||||
|
||||
local vehs = GetAllVehicles()
|
||||
local deleted = 0
|
||||
for i = 1, #vehs, 1 do
|
||||
if (not IsAnyPlayerInsideVehicle(vehs[i], playerPeds)) then
|
||||
local closestPlayer, distance = GetClosestPlayerPed(GetEntityCoords(vehs[i]), playerPeds)
|
||||
if (closestPlayer ~= nil and distance > Config.deleteDistance) then
|
||||
local plate = GetVehicleNumberPlateText(vehs[i])
|
||||
if (vehicles[plate] ~= nil) then
|
||||
vehicles[plate] = nil
|
||||
|
||||
MySQL.query("DELETE FROM vehicle_parking WHERE plate = @plate",
|
||||
{
|
||||
["@plate"] = plate
|
||||
})
|
||||
end
|
||||
|
||||
DeleteEntity(vehs[i])
|
||||
|
||||
deleted = deleted + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Log("Deleted " .. tostring(deleted) .. "/" .. tostring(#vehs) .. " vehicles. Took " .. tostring((GetGameTimer() - time) / 1000.0) .. "sec")
|
||||
end
|
||||
|
||||
AddEventHandler("onResourceStop", function(name)
|
||||
if (name ~= GetCurrentResourceName()) then
|
||||
return
|
||||
end
|
||||
|
||||
-- delete vehicles that are still being spawned before actually stopping the resource
|
||||
for plate, vehicleData in pairs(vehicles) do
|
||||
if (vehicleData.spawning and DoesEntityExist(vehicleData.handle)) then
|
||||
DeleteEntity(vehicleData.handle)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- render entity scorched (trigger with netid of the vehicle and false when repairing)
|
||||
RegisterServerEvent("mh_Parking:renderScorched")
|
||||
AddEventHandler("mh_Parking:renderScorched", function(vehicleNetId, scorched)
|
||||
local vehicleHandle = NetworkGetEntityFromNetworkId(vehicleNetId)
|
||||
if (DoesEntityExist(vehicleHandle)) then
|
||||
TriggerClientEvent("mh_Parking:renderScorched", -1, vehicleNetId, scorched)
|
||||
end
|
||||
end)
|
||||
|
||||
if (GetResourceState("kimi_callbacks") == "started") then
|
||||
exports["kimi_callbacks"]:Register("AP:getVehiclePosition", function(source, plate)
|
||||
local vehs = GetAllVehicles()
|
||||
|
||||
for i, veh in ipairs(vehs) do
|
||||
local vehPlate = GetVehicleNumberPlateText(veh)
|
||||
if (plate == vehPlate or plate == string.gsub(vehPlate, "^%s*(.-)%s*$", "%1")) then
|
||||
return GetEntityCoords(veh)
|
||||
end
|
||||
end
|
||||
|
||||
for vehPlate, vehData in pairs(vehicles) do
|
||||
if (plate == vehPlate or plate == string.gsub(vehPlate, "^%s*(.-)%s*$", "%1")) then
|
||||
return vehData.position
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end)
|
||||
|
||||
exports["kimi_callbacks"]:Register("AP:getVehiclePositions", function(source, plates)
|
||||
local platePositions = {}
|
||||
|
||||
Log("Looking for plates:")
|
||||
for i, plate in ipairs(plates) do
|
||||
Log("\"" .. plate .. "\"")
|
||||
end
|
||||
|
||||
local vehs = GetAllVehicles()
|
||||
for i, veh in ipairs(vehs) do
|
||||
local vehPlate = GetVehicleNumberPlateText(veh)
|
||||
local trimmedVehPlate = string.gsub(vehPlate, "^%s*(.-)%s*$", "%1")
|
||||
|
||||
for j, plate in ipairs(plates) do
|
||||
if (plate == vehPlate or plate == trimmedVehPlate) then
|
||||
platePositions[plate] = GetEntityCoords(veh)
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i, plate in ipairs(plates) do
|
||||
if (platePositions[plate] == nil) then
|
||||
for vehPlate, vehData in pairs(vehicles) do
|
||||
local trimmedVehPlate = string.gsub(vehPlate, "^%s*(.-)%s*$", "%1")
|
||||
|
||||
if (plate == vehPlate or plate == trimmedVehPlate) then
|
||||
platePositions[plate] = vehData.position
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return platePositions
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
RegisterNetEvent('mh_Parking:removeVehicle')
|
||||
AddEventHandler('mh_Parking:removeVehicle', function(plate)
|
||||
print("mh_parking: "..plate)
|
||||
vehicles[plate] = nil
|
||||
end)
|
||||
|
||||
function CallDB_Vehicles()
|
||||
DB_vehicles = {}
|
||||
MySQL.query('SELECT * FROM player_vehicles', {}, function(rs)
|
||||
for k, v in pairs(rs) do
|
||||
table.insert(DB_vehicles, v)
|
||||
end
|
||||
end) --DB_vehicles
|
||||
end
|
||||
|
||||
function CheckPlate(plate) -- DB_Players
|
||||
for k, v in pairs(DB_vehicles) do
|
||||
if Config.isDebug then
|
||||
Log(json.encode(v))
|
||||
Log(plate)
|
||||
Log(v.plate)
|
||||
end
|
||||
|
||||
if v.plate == plate then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
151
resources/[Developer]/mh_Parking/sv_utils.lua
Normal file
151
resources/[Developer]/mh_Parking/sv_utils.lua
Normal file
|
@ -0,0 +1,151 @@
|
|||
activePlayerPositions = {}
|
||||
|
||||
-- returns a loaded vehicled with a given number plate
|
||||
function TryGetLoadedVehicle(plate, loadedVehicles)
|
||||
for i = 1, #loadedVehicles, 1 do
|
||||
if (plate == GetVehicleNumberPlateText(loadedVehicles[i]) and DoesEntityExist(loadedVehicles[i])) then
|
||||
return loadedVehicles[i]
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function ContainsPlate(plate, vehiclePlates)
|
||||
for i = 1, #vehiclePlates, 1 do
|
||||
if (plate == vehiclePlates[i]) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- Logs text to the server console
|
||||
function Log(text)
|
||||
if (Config.isDebug) then
|
||||
Print(GetCurrentResourceName() .. ": " .. text)
|
||||
end
|
||||
end
|
||||
|
||||
-- return the distance between two positions (Vector3)
|
||||
function Vector3Dist(v1, v2)
|
||||
return math.sqrt( (v2.x - v1.x) * (v2.x - v1.x) + (v2.y - v1.y) * (v2.y - v1.y) + (v2.z - v1.z) * (v2.z - v1.z) )
|
||||
end
|
||||
|
||||
-- return the distance between two positions without sqrt (Vector3)
|
||||
function Vector3DistFast(v1, v2)
|
||||
return (v2.x - v1.x) * (v2.x - v1.x) + (v2.y - v1.y) * (v2.y - v1.y) + (v2.z - v1.z) * (v2.z - v1.z)
|
||||
end
|
||||
|
||||
-- returns the difference in degrees from the axis with the highest difference
|
||||
function GetRotationDifference(r1, r2)
|
||||
local x = math.abs(r1.x - r2.x)
|
||||
local y = math.abs(r1.y - r2.y)
|
||||
local z = math.abs(r1.z - r2.z)
|
||||
|
||||
if (x > y and x > z) then
|
||||
return x
|
||||
elseif (y > z) then
|
||||
return y
|
||||
else
|
||||
return z
|
||||
end
|
||||
end
|
||||
|
||||
-- get the amount of currently active players
|
||||
function GetActivePlayerCount()
|
||||
local playerCount = 0
|
||||
for k, v in pairs(activePlayerPositions) do
|
||||
playerCount = playerCount + 1
|
||||
end
|
||||
return playerCount
|
||||
end
|
||||
|
||||
-- return the ID of the closest player
|
||||
function GetClosestPlayerId(position)
|
||||
local closestDistance = 1000000.0
|
||||
local closestPlayerID = nil
|
||||
local closestPos = nil
|
||||
|
||||
for playerID, pos in pairs(activePlayerPositions) do
|
||||
local distance = Vector3DistFast(position, pos)
|
||||
|
||||
if (distance < closestDistance) then
|
||||
closestDistance = distance
|
||||
closestPlayerID = playerID
|
||||
closestPos = pos
|
||||
end
|
||||
end
|
||||
|
||||
local distance = nil
|
||||
if (closestPlayerID ~= nil) then
|
||||
distance = Vector3Dist(position, closestPos)
|
||||
end
|
||||
|
||||
return closestPlayerID, distance
|
||||
end
|
||||
|
||||
function IsAnyPlayerInsideVehicle(vehicle, playerPeds)
|
||||
for i = 1, #playerPeds, 1 do
|
||||
local veh = GetVehiclePedIsIn(playerPeds[i], false)
|
||||
|
||||
if (DoesEntityExist(veh) and veh == vehicle) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- return the ped of the closest player
|
||||
function GetClosestPlayerPed(position, playerPeds)
|
||||
local closestDistance = 1000000.0
|
||||
local closestPlayerPed = nil
|
||||
local closestPos = nil
|
||||
|
||||
for k, playerPed in pairs(playerPeds) do
|
||||
local pos = GetEntityCoords(playerPed)
|
||||
local distance = Vector3DistFast(position, pos)
|
||||
|
||||
if (distance < closestDistance) then
|
||||
closestDistance = distance
|
||||
closestPlayerPed = playerPed
|
||||
closestPos = pos
|
||||
end
|
||||
end
|
||||
|
||||
local distance = 0.0
|
||||
if (closestPlayerPed ~= nil) then
|
||||
distance = Vector3Dist(position, closestPos)
|
||||
end
|
||||
|
||||
return closestPlayerPed, distance
|
||||
end
|
||||
|
||||
-- returns true if a player is active on the server with the specified license
|
||||
function IsPlayerWithLicenseActive(license)
|
||||
for playerId, playerPos in pairs(activePlayerPositions) do
|
||||
if (GetPlayerIdentifiersSorted(playerId)["license"] == license) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- Return an array with all identifiers - e.g. ids["license"] = license:xxxxxxxxxxxxxxxx
|
||||
function GetPlayerIdentifiersSorted(playerServerId)
|
||||
local ids = {}
|
||||
|
||||
local identifiers = GetPlayerIdentifiers(playerServerId)
|
||||
|
||||
for k, identifier in pairs (identifiers) do
|
||||
local i, j = string.find(identifier, ":")
|
||||
local idType = string.sub(identifier, 1, i-1)
|
||||
|
||||
ids[idType] = identifier
|
||||
end
|
||||
|
||||
return ids
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue