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