adding new mlos
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
fx_version 'cerulean'
|
||||
game 'gta5'
|
||||
|
||||
lua54 'yes'
|
||||
author 'John Chin'
|
||||
description 'Weigh Station Shared Props'
|
||||
version '1.0.0'
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+189
@@ -0,0 +1,189 @@
|
||||
-- =============================================
|
||||
-- Optimized Weigh Station 03 Lights
|
||||
-- =============================================
|
||||
local redLightModel, greenLightModel = `jd_weighstation_lightred`, `jd_weighstation_lightgreen`
|
||||
|
||||
local activeLights03 = { LaneA = {}, LaneB = {} }
|
||||
local laneStates03 = { LaneA = nil, LaneB = nil }
|
||||
local isInRange03, playerAllowed03 = false, false
|
||||
|
||||
local autoTrack03 = {
|
||||
LaneA = { detected = false, thread = nil },
|
||||
LaneB = { detected = false, thread = nil }
|
||||
}
|
||||
|
||||
local laneTriggerCenters03 = {
|
||||
LaneA = vector3(-2481.8938, 3854.9802, 20.4138),
|
||||
LaneB = vector3(-2489.8101, 3858.9575, 20.4138)
|
||||
}
|
||||
local laneRadius03, leaveThreshold03 = 4.0, 10.0
|
||||
|
||||
-- Localized natives
|
||||
local PlayerPedId, GetEntityCoords, GetVehiclePedIsIn, GetPedInVehicleSeat, GetVehicleClass, GetEntityModel =
|
||||
PlayerPedId, GetEntityCoords, GetVehiclePedIsIn, GetPedInVehicleSeat, GetVehicleClass, GetEntityModel
|
||||
local DoesEntityExist, CreateObjectNoOffset, SetEntityCoordsNoOffset, SetEntityRotation, FreezeEntityPosition, SetEntityInvincible, DeleteEntity =
|
||||
DoesEntityExist, CreateObjectNoOffset, SetEntityCoordsNoOffset, SetEntityRotation, FreezeEntityPosition, SetEntityInvincible, DeleteEntity
|
||||
local HasModelLoaded, RequestModel, GetGameTimer, SetEntityAsMissionEntity, FindFirstObject, FindNextObject, EndFindObject =
|
||||
HasModelLoaded, RequestModel, GetGameTimer, SetEntityAsMissionEntity, FindFirstObject, FindNextObject, EndFindObject
|
||||
|
||||
-- ============================================================
|
||||
-- Cleanup existing lights
|
||||
-- ============================================================
|
||||
local function ForceCleanUp03()
|
||||
for _, model in ipairs({redLightModel, greenLightModel}) do
|
||||
local handle, obj = FindFirstObject()
|
||||
local success
|
||||
repeat
|
||||
if GetEntityModel(obj) == model then
|
||||
SetEntityAsMissionEntity(obj,true,true)
|
||||
DeleteEntity(obj)
|
||||
end
|
||||
success, obj = FindNextObject(handle)
|
||||
until not success
|
||||
EndFindObject(handle)
|
||||
end
|
||||
end
|
||||
|
||||
-- ============================================================
|
||||
-- Model loading helper
|
||||
-- ============================================================
|
||||
local function loadModel03(model)
|
||||
if HasModelLoaded(model) then return end
|
||||
RequestModel(model)
|
||||
local t0 = GetGameTimer()
|
||||
while not HasModelLoaded(model) do
|
||||
Wait(10)
|
||||
if GetGameTimer() - t0 > 5000 then RequestModel(model) end
|
||||
end
|
||||
end
|
||||
|
||||
-- ============================================================
|
||||
-- Spawn / Clear lane lights
|
||||
-- ============================================================
|
||||
local function clearLaneObjects03(lane)
|
||||
for _, obj in ipairs(activeLights03[lane]) do
|
||||
if DoesEntityExist(obj) then
|
||||
SetEntityAsMissionEntity(obj,true,true)
|
||||
DeleteEntity(obj)
|
||||
end
|
||||
end
|
||||
activeLights03[lane] = {}
|
||||
end
|
||||
|
||||
local function spawnLaneLight03(lane, model)
|
||||
if not Config.MainLights.Lanes[lane] then return end
|
||||
clearLaneObjects03(lane)
|
||||
loadModel03(model)
|
||||
|
||||
for _, light in ipairs(Config.MainLights.Lanes[lane].Lights) do
|
||||
local pos = light.coords
|
||||
local obj = CreateObjectNoOffset(model,pos.x,pos.y,pos.z,false,false,false)
|
||||
SetEntityCoordsNoOffset(obj,pos.x,pos.y,pos.z)
|
||||
if light.rotation then SetEntityRotation(obj, light.rotation.x, light.rotation.y, light.rotation.z, 2, true) end
|
||||
FreezeEntityPosition(obj,true)
|
||||
SetEntityInvincible(obj,true)
|
||||
table.insert(activeLights03[lane], obj)
|
||||
end
|
||||
end
|
||||
|
||||
local function refreshLane03(lane)
|
||||
local state = laneStates03[lane]
|
||||
if state == nil then
|
||||
clearLaneObjects03(lane)
|
||||
else
|
||||
spawnLaneLight03(lane, state and greenLightModel or redLightModel)
|
||||
end
|
||||
end
|
||||
|
||||
-- ============================================================
|
||||
-- Events
|
||||
-- ============================================================
|
||||
RegisterNetEvent("jd_weighlight03:setLaneState", function(lane, state)
|
||||
laneStates03[lane] = state
|
||||
if isInRange03 then refreshLane03(lane) end
|
||||
end)
|
||||
|
||||
-- Initial setup
|
||||
CreateThread(function()
|
||||
ForceCleanUp03()
|
||||
Wait(1000)
|
||||
TriggerServerEvent("jd_weighlight03:requestState")
|
||||
if Config.ACL.UseACL then
|
||||
TriggerServerEvent("jd_weighlight03:checkPermission")
|
||||
else
|
||||
playerAllowed03 = true
|
||||
end
|
||||
end)
|
||||
|
||||
-- ============================================================
|
||||
-- AutoMode detection
|
||||
-- ============================================================
|
||||
local function isVehicleAllowed03(vehicle)
|
||||
if not DoesEntityExist(vehicle) then return false end
|
||||
local model, vClass = GetEntityModel(vehicle), GetVehicleClass(vehicle)
|
||||
|
||||
for _, m in ipairs(Config.RampLight.AllowedModels) do
|
||||
if model == GetHashKey(m) then return true end
|
||||
end
|
||||
return Config.RampLight.AllowedClasses and Config.RampLight.AllowedClasses[vClass]
|
||||
end
|
||||
|
||||
local function startLaneAutoThread03(lane)
|
||||
local track = autoTrack03[lane]
|
||||
if not track or track.thread then return end
|
||||
|
||||
track.thread = CreateThread(function()
|
||||
while true do
|
||||
Wait(400)
|
||||
if not isInRange03 then goto continue end
|
||||
|
||||
local ped = PlayerPedId()
|
||||
local veh = GetVehiclePedIsIn(ped,false)
|
||||
if veh ~= 0 and GetPedInVehicleSeat(veh,-1) == ped and isVehicleAllowed03(veh) then
|
||||
local dist = #(GetEntityCoords(veh) - laneTriggerCenters03[lane])
|
||||
if dist <= laneRadius03 and not track.detected then
|
||||
track.detected = true
|
||||
TriggerServerEvent("jd_weighlight03:autoTrigger", lane)
|
||||
elseif dist > leaveThreshold03 and track.detected then
|
||||
track.detected = false
|
||||
TriggerServerEvent("jd_weighlight03:setLaneState", lane,true)
|
||||
end
|
||||
end
|
||||
::continue::
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
if Config.MainLights and Config.MainLights.AutoMode then
|
||||
CreateThread(function()
|
||||
Wait(2000)
|
||||
startLaneAutoThread03("LaneA")
|
||||
startLaneAutoThread03("LaneB")
|
||||
end)
|
||||
end
|
||||
|
||||
-- ============================================================
|
||||
-- Spawn/Despawn range check
|
||||
-- ============================================================
|
||||
CreateThread(function()
|
||||
while true do
|
||||
Wait(1000)
|
||||
local pCoords = GetEntityCoords(PlayerPedId())
|
||||
local nearAny = false
|
||||
for _, lane in pairs(Config.MainLights.Lanes) do
|
||||
if #(pCoords - lane.Lights[1].coords) < 200.0 then
|
||||
nearAny = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if nearAny and not isInRange03 then
|
||||
isInRange03 = true
|
||||
TriggerServerEvent("jd_weighlight03:requestState")
|
||||
elseif not nearAny and isInRange03 then
|
||||
isInRange03 = false
|
||||
clearLaneObjects03("LaneA")
|
||||
clearLaneObjects03("LaneB")
|
||||
end
|
||||
end
|
||||
end)
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
-- =============================================
|
||||
-- Optimized Station 03 Lane Logic
|
||||
-- =============================================
|
||||
local laneStates03 = {
|
||||
LaneA = Config.MainLights and Config.MainLights.AutoMode and true or nil,
|
||||
LaneB = Config.MainLights and Config.MainLights.AutoMode and true or nil
|
||||
}
|
||||
|
||||
local autoTimers03 = { LaneA = false, LaneB = false }
|
||||
|
||||
local UseACL = Config.ACL and Config.ACL.UseACL
|
||||
local aceMainLights = Config.ACL and Config.ACL.MainLights
|
||||
|
||||
-- Localize functions
|
||||
local TriggerClientEvent, IsPlayerAceAllowed = TriggerClientEvent, IsPlayerAceAllowed
|
||||
local CreateThread, Wait = CreateThread, Wait
|
||||
|
||||
-- ============================================================
|
||||
-- Send current lane states to requesting player
|
||||
-- ============================================================
|
||||
RegisterNetEvent("jd_weighlight03:requestState", function()
|
||||
local src = source
|
||||
for lane, state in pairs(laneStates03) do
|
||||
TriggerClientEvent("jd_weighlight03:setLaneState", src, lane, state)
|
||||
end
|
||||
end)
|
||||
|
||||
-- ============================================================
|
||||
-- Set lane state (with ACL check)
|
||||
-- ============================================================
|
||||
RegisterNetEvent("jd_weighlight03:setLaneState", function(lane, state)
|
||||
local src = source
|
||||
|
||||
-- Validate lane
|
||||
if laneStates03[lane] == nil then
|
||||
print(("[weigh_lights03] Invalid lane name from player %d: %s"):format(src, tostring(lane)))
|
||||
return
|
||||
end
|
||||
|
||||
-- ACL check
|
||||
if UseACL and not IsPlayerAceAllowed(src, aceMainLights) then
|
||||
print(("[weigh_lights03] Player %d tried to edit lane %s without permission!"):format(src, lane))
|
||||
return
|
||||
end
|
||||
|
||||
-- Update and sync
|
||||
laneStates03[lane] = state
|
||||
TriggerClientEvent("jd_weighlight03:setLaneState", -1, lane, state)
|
||||
end)
|
||||
|
||||
-- ============================================================
|
||||
-- AutoMode trigger
|
||||
-- ============================================================
|
||||
RegisterNetEvent("jd_weighlight03:autoTrigger", function(lane)
|
||||
if not Config.MainLights.AutoMode or laneStates03[lane] == nil or autoTimers03[lane] then return end
|
||||
|
||||
-- Force RED immediately
|
||||
laneStates03[lane] = false
|
||||
TriggerClientEvent("jd_weighlight03:setLaneState", -1, lane, false)
|
||||
|
||||
-- Start reset timer
|
||||
autoTimers03[lane] = true
|
||||
CreateThread(function()
|
||||
Wait(30000)
|
||||
autoTimers03[lane] = false
|
||||
|
||||
-- Only reset to GREEN if still RED
|
||||
if laneStates03[lane] == false then
|
||||
laneStates03[lane] = true
|
||||
TriggerClientEvent("jd_weighlight03:setLaneState", -1, lane, true)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
-- ============================================================
|
||||
-- Check ACL permission
|
||||
-- ============================================================
|
||||
RegisterNetEvent("weigh_lights03:checkPermissionMain", function()
|
||||
local src = source
|
||||
local allowed = not UseACL or IsPlayerAceAllowed(src, aceMainLights)
|
||||
TriggerClientEvent("weigh_lights03:permissionResultMain", src, allowed)
|
||||
end)
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
-- WeighStation03/RampLight/client.lua
|
||||
local spawnedObjects03 = {}
|
||||
local lastState03 = nil
|
||||
|
||||
-- ============================================================
|
||||
-- FIX: HELPER FUNCTIONS (NOW INCLUDED)
|
||||
-- ============================================================
|
||||
local function listContains(list, hash)
|
||||
for _, v in ipairs(list or {}) do
|
||||
if GetHashKey(v) == hash then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function vehicleIsAllowed(veh)
|
||||
local model = GetEntityModel(veh)
|
||||
local vClass = GetVehicleClass(veh)
|
||||
if listContains(Config.RampLight.AllowedModels, model) then return true end
|
||||
return (Config.RampLight and Config.RampLight.AllowedClasses and Config.RampLight.AllowedClasses[vClass])
|
||||
end
|
||||
|
||||
-- ============================================================
|
||||
-- CLEANUP & SPAWNING
|
||||
-- ============================================================
|
||||
local function ForceCleanUp03()
|
||||
local models = { GetHashKey(Config.RampLight.ModelRed), GetHashKey(Config.RampLight.ModelGreen) }
|
||||
for _, model in ipairs(models) do
|
||||
local handle, entity = FindFirstObject()
|
||||
local success
|
||||
repeat
|
||||
if GetEntityModel(entity) == model then
|
||||
SetEntityAsMissionEntity(entity, true, true)
|
||||
DeleteEntity(entity)
|
||||
end
|
||||
success, entity = FindNextObject(handle)
|
||||
until not success
|
||||
EndFindObject(handle)
|
||||
end
|
||||
end
|
||||
|
||||
RegisterNetEvent("jd_ramplight03:updateLights", function(state)
|
||||
-- Clean up Station 03 lights only
|
||||
for _, obj in ipairs(spawnedObjects03) do
|
||||
if DoesEntityExist(obj) then DeleteEntity(obj) end
|
||||
end
|
||||
spawnedObjects03 = {}
|
||||
|
||||
if state == nil then return end
|
||||
|
||||
RequestModel(Config.RampLight.ModelGreen)
|
||||
RequestModel(Config.RampLight.ModelRed)
|
||||
while not HasModelLoaded(Config.RampLight.ModelGreen) or not HasModelLoaded(Config.RampLight.ModelRed) do Wait(0) end
|
||||
|
||||
local posRed = Config.RampLight.RedCoords
|
||||
local posGreen = Config.RampLight.GreenCoords
|
||||
|
||||
local function finalize03(obj, rot)
|
||||
if obj then
|
||||
SetEntityRotation(obj, rot.x, rot.y, rot.z, 2, true)
|
||||
FreezeEntityPosition(obj, true)
|
||||
SetEntityInvincible(obj, true)
|
||||
table.insert(spawnedObjects03, obj)
|
||||
end
|
||||
end
|
||||
|
||||
if state == "heavy" then
|
||||
local rObj = CreateObjectNoOffset(Config.RampLight.ModelRed, posRed.x, posRed.y, posRed.z, false, false, false)
|
||||
local gObj = CreateObjectNoOffset(Config.RampLight.ModelGreen, posGreen.x, posGreen.y, posGreen.z, false, false, false)
|
||||
finalize03(rObj, Config.RampLight.RedRotation)
|
||||
finalize03(gObj, Config.RampLight.GreenRotation)
|
||||
elseif state == "light" then
|
||||
local gObj = CreateObjectNoOffset(Config.RampLight.ModelGreen, posRed.x, posRed.y, posRed.z, false, false, false)
|
||||
local rObj = CreateObjectNoOffset(Config.RampLight.ModelRed, posGreen.x, posGreen.y, posGreen.z, false, false, false)
|
||||
finalize03(gObj, Config.RampLight.RedRotation)
|
||||
finalize03(rObj, Config.RampLight.GreenRotation)
|
||||
end
|
||||
end)
|
||||
|
||||
-- ============================================================
|
||||
-- DETECTION THREAD (STATION 03)
|
||||
-- ============================================================
|
||||
CreateThread(function()
|
||||
ForceCleanUp03()
|
||||
while true do
|
||||
Wait(500)
|
||||
local ped = PlayerPedId()
|
||||
local pCoords = GetEntityCoords(ped)
|
||||
local veh = GetVehiclePedIsIn(ped, false)
|
||||
|
||||
local dist = #(pCoords - Config.RampLight.CenterPoint)
|
||||
local state = nil
|
||||
|
||||
if veh ~= 0 and GetPedInVehicleSeat(veh, -1) == ped and vehicleIsAllowed(veh) then
|
||||
if dist <= Config.RampLight.DetectionDistance then
|
||||
state = "light"
|
||||
local hasTrailer, trailer = GetVehicleTrailerVehicle(veh)
|
||||
if hasTrailer and trailer then
|
||||
local tModel = GetEntityModel(trailer)
|
||||
if listContains(Config.RampLight.HeavyModels, tModel) then
|
||||
state = "heavy"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if state ~= lastState03 then
|
||||
lastState03 = state
|
||||
TriggerServerEvent("jd_ramplight03:requestSync", state, dist)
|
||||
end
|
||||
end
|
||||
end)
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
-- WeighStation03/RampLight/server.lua
|
||||
local currentOwner03 = nil
|
||||
local ownerDist03 = 999.0
|
||||
local currentState03 = nil
|
||||
|
||||
-- ============================================================
|
||||
-- SYNC REQUEST (STATION 03)
|
||||
-- ============================================================
|
||||
RegisterNetEvent("jd_ramplight03:requestSync")
|
||||
AddEventHandler("jd_ramplight03:requestSync", function(state, dist)
|
||||
local src = source
|
||||
|
||||
-- Only update if no one owns it, or this player is closer to Station 03
|
||||
if currentOwner03 == nil or src == currentOwner03 or dist < ownerDist03 then
|
||||
currentOwner03 = src
|
||||
ownerDist03 = dist
|
||||
currentState03 = state
|
||||
|
||||
-- Broadcast specifically to Station 03 listeners
|
||||
TriggerClientEvent("jd_ramplight03:updateLights", -1, currentState03)
|
||||
end
|
||||
end)
|
||||
|
||||
-- ============================================================
|
||||
-- OWNER VALIDATION LOOP
|
||||
-- ============================================================
|
||||
CreateThread(function()
|
||||
while true do
|
||||
Wait(2000)
|
||||
if currentOwner03 then
|
||||
local ped = GetPlayerPed(currentOwner03)
|
||||
-- Check if player still exists and is near Station 03 coordinates
|
||||
if ped == 0 then
|
||||
currentOwner03 = nil
|
||||
TriggerClientEvent("jd_ramplight03:updateLights", -1, nil)
|
||||
else
|
||||
local coords = GetEntityCoords(ped)
|
||||
local dist = #(coords - Config.RampLight.CenterPoint)
|
||||
|
||||
if dist > Config.RampLight.DetectionDistance then
|
||||
currentOwner03 = nil
|
||||
ownerDist03 = 999.0
|
||||
currentState03 = nil
|
||||
TriggerClientEvent("jd_ramplight03:updateLights", -1, nil)
|
||||
else
|
||||
ownerDist03 = dist
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('playerDropped', function()
|
||||
if source == currentOwner03 then
|
||||
currentOwner03 = nil
|
||||
ownerDist03 = 999.0
|
||||
TriggerClientEvent("jd_ramplight03:updateLights", -1, nil)
|
||||
end
|
||||
end)
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
-- =============================================
|
||||
-- Station 03 Amber Lights Client Logic
|
||||
-- =============================================
|
||||
local lightSets03, playerAllowed03 = {}, false
|
||||
|
||||
-- Localize natives
|
||||
local CreateThread, Wait, table_insert = CreateThread, Wait, table.insert
|
||||
local IsControlJustPressed, vector3 = IsControlJustPressed, vector3
|
||||
local CreateObject, SetEntityRotation, SetEntityVisible, FreezeEntityPosition, DoesEntityExist, DeleteEntity =
|
||||
CreateObject, SetEntityRotation, SetEntityVisible, FreezeEntityPosition, DoesEntityExist, DeleteEntity
|
||||
|
||||
-- ============================================================
|
||||
-- REQUEST PERMISSION (Station 03)
|
||||
-- ============================================================
|
||||
CreateThread(function()
|
||||
if Config.ACL.UseACL then
|
||||
TriggerServerEvent("weigh_lights03:checkPermission")
|
||||
else
|
||||
playerAllowed03 = true
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("weigh_lights03:permissionResult", function(allowed)
|
||||
playerAllowed03 = allowed
|
||||
end)
|
||||
|
||||
-- ============================================================
|
||||
-- LOAD LIGHT SETS (Station 03)
|
||||
-- ============================================================
|
||||
CreateThread(function()
|
||||
for _, cfg in ipairs(Config.RoadSigns.LightSets) do
|
||||
table_insert(lightSets03, {
|
||||
name = cfg.name,
|
||||
model = cfg.model,
|
||||
coordsA = cfg.coordsA,
|
||||
coordsB = cfg.coordsB,
|
||||
rotA = cfg.rotA or vector3(0,0,0),
|
||||
rotB = cfg.rotB or vector3(0,0,0),
|
||||
control = cfg.control,
|
||||
distance = cfg.distance or 2.0,
|
||||
propA = nil,
|
||||
propB = nil,
|
||||
flashing = false,
|
||||
pointCreated = false
|
||||
})
|
||||
end
|
||||
end)
|
||||
|
||||
-- ============================================================
|
||||
-- SYNC LOGIC (Station 03)
|
||||
-- ============================================================
|
||||
CreateThread(function()
|
||||
Wait(1000)
|
||||
TriggerServerEvent("weigh_lights03:requestSync")
|
||||
end)
|
||||
|
||||
RegisterNetEvent("weigh_lights03:syncAll", function(states)
|
||||
for name, state in pairs(states) do
|
||||
for _, set in ipairs(lightSets03) do
|
||||
if set.name == name then
|
||||
if state then StartFlashing03(set) else StopFlashing03(set) end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent("weigh_lights03:syncSingle", function(setName, newState)
|
||||
for _, set in ipairs(lightSets03) do
|
||||
if set.name == setName then
|
||||
if newState then StartFlashing03(set) else StopFlashing03(set) end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- ============================================================
|
||||
-- FLASHING LOGIC (Station 03)
|
||||
-- ============================================================
|
||||
function StartFlashing03(set)
|
||||
if set.flashing then return end
|
||||
set.flashing = true
|
||||
|
||||
CreateThread(function()
|
||||
local zOffset = -0.09
|
||||
set.propA = CreateObject(set.model, set.coordsA.x, set.coordsA.y, set.coordsA.z + zOffset, false, false, false)
|
||||
set.propB = CreateObject(set.model, set.coordsB.x, set.coordsB.y, set.coordsB.z + zOffset, false, false, false)
|
||||
|
||||
SetEntityRotation(set.propA, set.rotA.x, set.rotA.y, set.rotA.z, 2, true)
|
||||
SetEntityRotation(set.propB, set.rotB.x, set.rotB.y, set.rotB.z, 2, true)
|
||||
FreezeEntityPosition(set.propA, true)
|
||||
FreezeEntityPosition(set.propB, true)
|
||||
|
||||
local visible = true
|
||||
while set.flashing do
|
||||
visible = not visible
|
||||
SetEntityVisible(set.propA, visible, false)
|
||||
SetEntityVisible(set.propB, not visible, false)
|
||||
Wait(500)
|
||||
end
|
||||
|
||||
if DoesEntityExist(set.propA) then DeleteEntity(set.propA) end
|
||||
if DoesEntityExist(set.propB) then DeleteEntity(set.propB) end
|
||||
set.propA, set.propB = nil, nil
|
||||
end)
|
||||
end
|
||||
|
||||
function StopFlashing03(set)
|
||||
set.flashing = false
|
||||
end
|
||||
|
||||
-- ============================================================
|
||||
-- INTERACTION (E-KEY) (Station 03)
|
||||
-- ============================================================
|
||||
CreateThread(function()
|
||||
while #lightSets03 == 0 do Wait(100) end
|
||||
if Config.ACL.UseACL then
|
||||
while not playerAllowed03 do Wait(100) end
|
||||
end
|
||||
|
||||
for _, set in ipairs(lightSets03) do
|
||||
if set.control and not set.pointCreated then
|
||||
local point = lib.points.new(set.control, set.distance)
|
||||
set.pointCreated = true
|
||||
|
||||
function point:nearby()
|
||||
if Config.ACL.UseACL and not playerAllowed03 then
|
||||
lib.hideTextUI()
|
||||
return
|
||||
end
|
||||
|
||||
if self.currentDistance < set.distance then
|
||||
lib.showTextUI("[E] Toggle Amber Light: " .. set.name)
|
||||
if IsControlJustPressed(0, 38) then
|
||||
TriggerServerEvent("weigh_lights03:toggleLight", set.name, not set.flashing)
|
||||
end
|
||||
else
|
||||
lib.hideTextUI()
|
||||
end
|
||||
end
|
||||
|
||||
function point:onExit()
|
||||
lib.hideTextUI()
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
-- =============================================
|
||||
-- Station 03 Amber Lights Server Logic
|
||||
-- =============================================
|
||||
local lightStates03 = {}
|
||||
|
||||
-- Localize functions
|
||||
local TriggerClientEvent, IsPlayerAceAllowed, print = TriggerClientEvent, IsPlayerAceAllowed, print
|
||||
|
||||
-- ============================================================
|
||||
-- REQUEST SYNC (Station 03)
|
||||
-- ============================================================
|
||||
RegisterNetEvent("weigh_lights03:requestSync", function()
|
||||
TriggerClientEvent("weigh_lights03:syncAll", source, lightStates03)
|
||||
end)
|
||||
|
||||
-- ============================================================
|
||||
-- TOGGLE LIGHT (Station 03)
|
||||
-- ============================================================
|
||||
RegisterNetEvent("weigh_lights03:toggleLight", function(setName, newState)
|
||||
local src = source
|
||||
|
||||
if Config.ACL.UseACL and not IsPlayerAceAllowed(src, Config.ACL.AmberLights) then
|
||||
print(("[weigh_lights03] Player %d tried to toggle light '%s' without permission!"):format(src, setName))
|
||||
return
|
||||
end
|
||||
|
||||
-- Update only if the state actually changed
|
||||
if lightStates03[setName] ~= newState then
|
||||
lightStates03[setName] = newState
|
||||
TriggerClientEvent("weigh_lights03:syncSingle", -1, setName, newState)
|
||||
end
|
||||
end)
|
||||
|
||||
-- ============================================================
|
||||
-- CHECK PERMISSION (Station 03)
|
||||
-- ============================================================
|
||||
RegisterNetEvent("weigh_lights03:checkPermission", function()
|
||||
local src = source
|
||||
local allowed = not Config.ACL.UseACL or IsPlayerAceAllowed(src, Config.ACL.AmberLights)
|
||||
TriggerClientEvent("weigh_lights03:permissionResult", src, allowed)
|
||||
end)
|
||||
@@ -0,0 +1,194 @@
|
||||
-- =============================================
|
||||
-- Optimized Client logic for weigh station 03
|
||||
-- =============================================
|
||||
|
||||
local uiOpen = false
|
||||
local checkDistance = 12.0
|
||||
local truckWeights = {}
|
||||
local truckTrailers = {}
|
||||
local lastLaneWeight = {}
|
||||
local serverCallbacks03 = {}
|
||||
local laneCenters = {}
|
||||
|
||||
-- FIXED: Localize frequently used natives correctly (Removed illegal # operator)
|
||||
local GetEntityCoords = GetEntityCoords
|
||||
local PlayerPedId = PlayerPedId
|
||||
local DoesEntityExist = DoesEntityExist
|
||||
local GetEntityModel = GetEntityModel
|
||||
local GetVehicleTrailerVehicle = GetVehicleTrailerVehicle
|
||||
local GetVehicleNumberPlateText = GetVehicleNumberPlateText
|
||||
local GetGamePool = GetGamePool
|
||||
|
||||
-- =========================
|
||||
-- Helper: Server callback
|
||||
-- =========================
|
||||
function TriggerServerCallback03(name, cb, ...)
|
||||
local id = math.random(1, 999999)
|
||||
serverCallbacks03[id] = cb
|
||||
TriggerServerEvent(name, id, ...)
|
||||
end
|
||||
|
||||
RegisterNetEvent("weighstation03:serverCallback", function(id, ...)
|
||||
if serverCallbacks03[id] then
|
||||
serverCallbacks03[id](...)
|
||||
serverCallbacks03[id] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
-- =========================
|
||||
-- Helpers & Initializations
|
||||
-- =========================
|
||||
local function IsModelInList(modelHash, list)
|
||||
if not list then return false end
|
||||
for i = 1, #list do
|
||||
if GetHashKey(list[i]) == modelHash then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Pre-calculate lane centers once to save CPU during loops
|
||||
CreateThread(function()
|
||||
while not Config or not Config.MainLights do Wait(100) end
|
||||
for laneName, laneData in pairs(Config.MainLights.Lanes) do
|
||||
lastLaneWeight[laneName] = nil
|
||||
local sum = vector3(0.0, 0.0, 0.0)
|
||||
local count = 0
|
||||
for _, light in ipairs(laneData.Lights) do
|
||||
sum = sum + light.coords
|
||||
count = count + 1
|
||||
end
|
||||
laneCenters[laneName] = sum / count
|
||||
end
|
||||
end)
|
||||
|
||||
-- =========================
|
||||
-- Control Point Detection (Dynamic Sleep)
|
||||
-- =========================
|
||||
CreateThread(function()
|
||||
while true do
|
||||
local sleep = 1000 -- Idle sleep
|
||||
local ped = PlayerPedId()
|
||||
local pos = GetEntityCoords(ped)
|
||||
local controlCoords = Config.MainLights.ControlCoords
|
||||
local dist = #(pos - controlCoords)
|
||||
|
||||
if dist < 10.0 then
|
||||
sleep = 0 -- Wake up for input detection
|
||||
if dist < (Config.MainLights.ControlDistance or 2.0) then
|
||||
SendNUIMessage({ action = "showPopup", text = "[G] Open Weigh Station 03" })
|
||||
if IsControlJustPressed(0, 47) and not uiOpen then
|
||||
uiOpen = true
|
||||
SetNuiFocus(true, true)
|
||||
SendNUIMessage({ action = "showUI" })
|
||||
|
||||
TriggerServerCallback03("weighstation03:getRecentVehicles", function(recent)
|
||||
SendNUIMessage({ action = "updateRecentVehicles", recent = recent })
|
||||
end)
|
||||
end
|
||||
else
|
||||
SendNUIMessage({ action = "hidePopup" })
|
||||
end
|
||||
end
|
||||
Wait(sleep)
|
||||
end
|
||||
end)
|
||||
|
||||
-- =========================
|
||||
-- MAIN TRUCK DETECTION (Low Resmon)
|
||||
-- =========================
|
||||
CreateThread(function()
|
||||
while true do
|
||||
-- Check distance to the station center to decide if we even need to scan vehicles
|
||||
local ped = PlayerPedId()
|
||||
local pPos = GetEntityCoords(ped)
|
||||
local distToStation = #(pPos - vector3(-2487.0051, 3855.9683, 20.7139)) -- Station center
|
||||
|
||||
if distToStation > 150.0 then
|
||||
-- Far away: Sleep for 3 seconds
|
||||
Wait(3000)
|
||||
else
|
||||
-- Near station: Scan every 1 second
|
||||
Wait(1000)
|
||||
|
||||
local vehicles = GetGamePool('CVehicle')
|
||||
local tickResults = {}
|
||||
local activeVehiclesThisTick = {}
|
||||
|
||||
for laneName, _ in pairs(Config.MainLights.Lanes) do
|
||||
tickResults[laneName] = { weight = 0, truck = nil, minDist = checkDistance + 0.1 }
|
||||
end
|
||||
|
||||
for i = 1, #vehicles do
|
||||
local vehicle = vehicles[i]
|
||||
if DoesEntityExist(vehicle) then
|
||||
local model = GetEntityModel(vehicle)
|
||||
|
||||
if IsModelInList(model, Config.RampLight.AllowedModels) then
|
||||
local vehiclePos = GetEntityCoords(vehicle)
|
||||
local nearestLaneName = nil
|
||||
local nearestLaneDist = checkDistance
|
||||
|
||||
for laneName, center in pairs(laneCenters) do
|
||||
local distToLane = #(vehiclePos - center)
|
||||
if distToLane < nearestLaneDist then
|
||||
nearestLaneDist = distToLane
|
||||
nearestLaneName = laneName
|
||||
end
|
||||
end
|
||||
|
||||
if nearestLaneName then
|
||||
activeVehiclesThisTick[vehicle] = true
|
||||
local _, trailer = GetVehicleTrailerVehicle(vehicle)
|
||||
|
||||
-- Generate weight logic
|
||||
if not truckWeights[vehicle] or truckTrailers[vehicle] ~= trailer then
|
||||
local plate = GetVehicleNumberPlateText(vehicle)
|
||||
local truckModelName = GetDisplayNameFromVehicleModel(model)
|
||||
|
||||
-- Weight generation
|
||||
truckWeights[vehicle] = math.random(35000, 100000)
|
||||
truckTrailers[vehicle] = trailer
|
||||
|
||||
TriggerServerEvent("weighstation03:logTruck", plate, truckModelName, truckWeights[vehicle])
|
||||
end
|
||||
|
||||
if nearestLaneDist < tickResults[nearestLaneName].minDist then
|
||||
tickResults[nearestLaneName].weight = truckWeights[vehicle]
|
||||
tickResults[nearestLaneName].truck = vehicle
|
||||
tickResults[nearestLaneName].minDist = nearestLaneDist
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Memory Cleanup
|
||||
for veh, _ in pairs(truckWeights) do
|
||||
if not DoesEntityExist(veh) or not activeVehiclesThisTick[veh] then
|
||||
truckWeights[veh] = nil
|
||||
truckTrailers[veh] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Update UI
|
||||
for laneName, data in pairs(tickResults) do
|
||||
if lastLaneWeight[laneName] ~= data.weight then
|
||||
lastLaneWeight[laneName] = data.weight
|
||||
SendNUIMessage({
|
||||
action = "updateWeight",
|
||||
lane = laneName,
|
||||
weight = data.weight,
|
||||
vehicle = data.truck or nil
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNUICallback('closeUI', function(data, cb)
|
||||
uiOpen = false
|
||||
SetNuiFocus(false, false)
|
||||
SendNUIMessage({ action = "hideUI" })
|
||||
cb('ok')
|
||||
end)
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const win = document.getElementById("browser-window");
|
||||
const closeBtn = document.getElementById("close-btn");
|
||||
|
||||
// Lane status
|
||||
const statusLaneA = document.getElementById("status-laneA");
|
||||
const statusLaneB = document.getElementById("status-laneB");
|
||||
|
||||
// Recent vehicles log
|
||||
const recentVehicles = document.getElementById("recent-vehicles");
|
||||
|
||||
// Totals / Summary
|
||||
const totalTrucksEl = document.getElementById("total-trucks");
|
||||
const avgWeightEl = document.getElementById("avg-weight");
|
||||
const overweightCountEl = document.getElementById("overweight-count");
|
||||
|
||||
// Popup
|
||||
const popup = document.createElement("div");
|
||||
popup.id = "popup";
|
||||
popup.style.position = "fixed";
|
||||
popup.style.top = "20px";
|
||||
popup.style.left = "20px";
|
||||
popup.style.padding = "10px 20px";
|
||||
popup.style.backgroundColor = "#000080";
|
||||
popup.style.color = "#fff";
|
||||
popup.style.fontFamily = "MS Sans Serif, Arial, sans-serif";
|
||||
popup.style.fontSize = "14px";
|
||||
popup.style.fontWeight = "bold";
|
||||
popup.style.border = "2px solid #000";
|
||||
popup.style.display = "none";
|
||||
popup.style.zIndex = "9999";
|
||||
popup.style.borderRadius = "4px";
|
||||
document.body.appendChild(popup);
|
||||
|
||||
// Tracking
|
||||
let recentVehiclesData = [];
|
||||
let totalTrucks = 0;
|
||||
let totalWeight = 0;
|
||||
let overweightCount = 0;
|
||||
let loggedVehicles = {}; // track by unique vehicle ID
|
||||
|
||||
window.addEventListener("message", (event) => {
|
||||
const data = event.data;
|
||||
|
||||
if (data.action === "showUI") {
|
||||
win.style.display = "block";
|
||||
document.body.style.cursor = "default";
|
||||
} else if (data.action === "hideUI") {
|
||||
win.style.display = "none";
|
||||
document.body.style.cursor = "none";
|
||||
} else if (data.action === "showPopup") {
|
||||
popup.innerText = data.text;
|
||||
popup.style.display = "block";
|
||||
} else if (data.action === "hidePopup") {
|
||||
popup.style.display = "none";
|
||||
} else if (data.action === "updateWeight") {
|
||||
const laneWeightEl = data.lane === "LaneA" ? document.getElementById("laneA-weight") : document.getElementById("laneB-weight");
|
||||
laneWeightEl.innerText = data.weight ? data.weight + " LBS" : "-- LBS";
|
||||
|
||||
const statusEl = data.lane === "LaneA" ? statusLaneA : statusLaneB;
|
||||
if (data.weight) {
|
||||
statusEl.innerText = data.weight > 80000 ? `${data.lane}: ⚠️ Overweight` : `${data.lane}: Occupied`;
|
||||
} else {
|
||||
statusEl.innerText = `${data.lane}: Open`;
|
||||
}
|
||||
|
||||
// Only log new vehicles once globally
|
||||
if (data.vehicle && data.weight && !loggedVehicles[data.vehicle]) {
|
||||
loggedVehicles[data.vehicle] = true;
|
||||
|
||||
totalTrucks++;
|
||||
totalWeight += data.weight;
|
||||
if (data.weight > 80000) overweightCount++;
|
||||
|
||||
totalTrucksEl.innerText = totalTrucks;
|
||||
avgWeightEl.innerText = Math.floor(totalWeight / totalTrucks);
|
||||
overweightCountEl.innerText = overweightCount;
|
||||
|
||||
const entry = `${new Date().toLocaleTimeString()} - ${data.lane} - ${data.weight} LBS`;
|
||||
recentVehiclesData.unshift(entry);
|
||||
if (recentVehiclesData.length > 10) recentVehiclesData.pop();
|
||||
recentVehicles.innerHTML = recentVehiclesData.map(e => `<li>${e}</li>`).join("");
|
||||
}
|
||||
|
||||
// Remove from logged if lane is empty
|
||||
if (!data.weight && data.vehicle) {
|
||||
loggedVehicles[data.vehicle] = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
closeBtn.addEventListener("click", () => {
|
||||
fetch(`https://${GetParentResourceName()}/closeUI`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({})
|
||||
}).finally(() => {
|
||||
win.style.display = "none";
|
||||
document.body.style.cursor = "none";
|
||||
});
|
||||
});
|
||||
});
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
body {
|
||||
font-family: "MS Sans Serif", Arial, sans-serif;
|
||||
background-color: transparent;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Browser window */
|
||||
#browser-window {
|
||||
width: 800px;
|
||||
height: 600px;
|
||||
background-color: #c0c0c0;
|
||||
border: 3px solid #000;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
display: none;
|
||||
box-shadow: 7px 7px 0px #000;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Top bar */
|
||||
#browser-topbar {
|
||||
height: 30px;
|
||||
background-color: #000080;
|
||||
color: #fff;
|
||||
padding: 6px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* URL tab */
|
||||
#tab {
|
||||
font-weight: normal;
|
||||
background-color: #c0c0c0;
|
||||
color: #000;
|
||||
padding: 4px 8px;
|
||||
border: 2px inset #fff;
|
||||
margin-left: 4px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* Close button */
|
||||
#close-btn {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
#close-btn:hover {
|
||||
background: #ff0000;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Menu buttons */
|
||||
#browser-menu {
|
||||
display: flex;
|
||||
height: 30px;
|
||||
background-color: #c0c0c0;
|
||||
border-bottom: 2px inset #fff;
|
||||
}
|
||||
.menu-btn {
|
||||
border: 2px outset #fff;
|
||||
margin: 2px;
|
||||
padding: 4px 10px;
|
||||
background-color: #c0c0c0;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
}
|
||||
.menu-btn:active {
|
||||
border-style: inset;
|
||||
}
|
||||
|
||||
/* Content area */
|
||||
#browser-content {
|
||||
background-color: #e0e0e0;
|
||||
padding: 30px;
|
||||
font-size: 16px;
|
||||
border-top: 2px solid #fff;
|
||||
border-bottom: 2px solid #000;
|
||||
height: calc(100% - 30px - 30px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Lane boxes */
|
||||
.lane {
|
||||
margin-top: 15px;
|
||||
padding: 10px;
|
||||
border: 2px inset #fff;
|
||||
background-color: #c0c0c0;
|
||||
font-size: 16px;
|
||||
}
|
||||
.lane-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Lane status, log, summary */
|
||||
.lane-status, .log, .summary {
|
||||
margin-top: 20px;
|
||||
padding: 10px;
|
||||
border: 2px inset #fff;
|
||||
background-color: #c0c0c0;
|
||||
}
|
||||
.lane-status h3, .log h3, .summary h3 {
|
||||
margin: 0 0 5px 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
.log ul {
|
||||
padding-left: 20px;
|
||||
margin: 0;
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Weigh Station UI</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="browser-window">
|
||||
<!-- Top bar -->
|
||||
<div id="browser-topbar">
|
||||
<span id="tab">www.sanandreasdot.gov/panel</span>
|
||||
<button id="close-btn">X</button>
|
||||
</div>
|
||||
|
||||
<!-- Menu buttons -->
|
||||
<div id="browser-menu">
|
||||
<button class="menu-btn">File</button>
|
||||
<button class="menu-btn">Edit</button>
|
||||
<button class="menu-btn">View</button>
|
||||
<button class="menu-btn">Help</button>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<div id="browser-content">
|
||||
<h2>Weigh Station Panel</h2>
|
||||
|
||||
<!-- Lanes -->
|
||||
<div class="lane">
|
||||
<span class="lane-name">Lane A:</span> <span id="laneA-weight">-- LBS</span>
|
||||
</div>
|
||||
<div class="lane">
|
||||
<span class="lane-name">Lane B:</span> <span id="laneB-weight">-- LBS</span>
|
||||
</div>
|
||||
|
||||
<!-- Lane Status -->
|
||||
<div class="lane-status">
|
||||
<h3>Lane Status</h3>
|
||||
<div id="status-laneA">Lane A: Open</div>
|
||||
<div id="status-laneB">Lane B: Open</div>
|
||||
</div>
|
||||
|
||||
<!-- Recent Vehicles Log -->
|
||||
<div class="log">
|
||||
<h3>Recent Vehicles</h3>
|
||||
<ul id="recent-vehicles">
|
||||
<!-- dynamically updated -->
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Totals / Summary -->
|
||||
<div class="summary">
|
||||
<h3>Summary</h3>
|
||||
<div>Total Trucks Today: <span id="total-trucks">0</span></div>
|
||||
<div>Average Weight: <span id="avg-weight">0</span> LBS</div>
|
||||
<div>Overweight Trucks: <span id="overweight-count">0</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,30 @@
|
||||
local lightStates03 = {}
|
||||
|
||||
-- ============================================================
|
||||
-- OPTIMIZED SYNC
|
||||
-- ============================================================
|
||||
RegisterNetEvent("weigh_lights03:requestSync", function()
|
||||
local src = source
|
||||
TriggerClientEvent("weigh_lights03:syncAll", src, lightStates03)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("weigh_lights03:toggleLight", function(setName, newState)
|
||||
local src = source
|
||||
|
||||
if Config.ACL.UseACL then
|
||||
if not IsPlayerAceAllowed(src, Config.ACL.AmberLights) then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
lightStates03[setName] = newState
|
||||
-- Only broadcast to others to save bandwidth
|
||||
TriggerClientEvent("weigh_lights03:syncSingle", -1, setName, newState)
|
||||
end)
|
||||
|
||||
-- Optimized Permission Check
|
||||
RegisterNetEvent("weigh_lights03:checkPermission", function()
|
||||
local src = source
|
||||
local allowed = not Config.ACL.UseACL or IsPlayerAceAllowed(src, Config.ACL.AmberLights)
|
||||
TriggerClientEvent("weigh_lights03:permissionResult", src, allowed)
|
||||
end)
|
||||
@@ -0,0 +1,105 @@
|
||||
Config = {}
|
||||
|
||||
-- =============================================
|
||||
-- ACE PERMISSIONS
|
||||
-- =============================================
|
||||
Config.ACL = {
|
||||
UseACL = false, -- set to false to disable ACE checks allowing anyone to use the light controls
|
||||
MainLights = "weighstation.mainlights",
|
||||
AmberLights = "weighstation.amberlights"
|
||||
}
|
||||
|
||||
-- =============================================
|
||||
-- MAIN WEIGH STATION TRAFFIC LIGHTS
|
||||
-- =============================================
|
||||
Config.MainLights = {
|
||||
AutoMode = true,
|
||||
Lanes = {
|
||||
LaneA = {
|
||||
Lights = {
|
||||
{
|
||||
coords = vector3(-2475.057373, 3873.079346, 26.406738),
|
||||
rotation = vector3(0.0, 0.0, 135.0)
|
||||
},
|
||||
{
|
||||
coords = vector3(-2480.732422, 3852.302246, 24.777773),
|
||||
rotation = vector3(20.0, -90.0, 150.00)
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
LaneB = {
|
||||
Lights = {
|
||||
{
|
||||
coords = vector3(-2481.596680, 3876.128662, 26.406738),
|
||||
rotation = vector3(0.0, 0.0, 135.00)
|
||||
},
|
||||
{
|
||||
coords = vector3(-2487.283691, 3855.302734, 24.777773),
|
||||
rotation = vector3(20.0, -90.0, 150.00)
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
ControlCoords = vector3(-2516.8596, 3859.7903, 20.6101),
|
||||
ControlDistance = 1.0,
|
||||
LightSpawnRange = 200.0,
|
||||
ResyncTime = 60000
|
||||
}
|
||||
|
||||
|
||||
-- =============================================
|
||||
-- ROAD SIGN / AMBER LIGHT SETS
|
||||
-- =============================================
|
||||
Config.RoadSigns = {
|
||||
LightSets = {
|
||||
{
|
||||
name = "Great Ocean Hwy S",
|
||||
model = `jd_weighstation_lightamber`,
|
||||
coordsA = vector3(-2237.833740, 4307.489746, 50.284489),
|
||||
rotA = vector3(0.0, 0.0, 145.0),
|
||||
coordsB = vector3(-2238.857666, 4308.206543, 50.284489),
|
||||
rotB = vector3(0.0, 0.0, 145.0),
|
||||
|
||||
control = vector3(-2238.4390, 4307.7974, 47.8325),
|
||||
distance = 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- =============================================
|
||||
-- WEIGH STATION RAMP LIGHT SYSTEM
|
||||
-- =============================================
|
||||
Config.RampLight = {
|
||||
CenterPoint = vector3(-2441.3560, 3919.4810, 19.9648),
|
||||
DetectionDistance = 19.0,
|
||||
ModelGreen = `jd_weightstation03_greencheck`,
|
||||
ModelRed = `jd_weightstation03_redx`,
|
||||
RedCoords = vector3(-2432.925049, 3914.801270, 28.507784),
|
||||
GreenCoords = vector3(-2435.523193, 3916.300537, 28.507784),
|
||||
|
||||
RedRotation = vector3(0.0, 0.0, 10.0),
|
||||
GreenRotation = vector3(0.0, 0.0, 10.0),
|
||||
|
||||
AllowedClasses = {
|
||||
[18] = false,
|
||||
[20] = false,
|
||||
},
|
||||
AllowedModels = { "phantom", "hauler", "packer", "phantom3", "hauler2", "packer2" }, -- ← container truck models
|
||||
|
||||
HeavyModels = {
|
||||
"TRAILER", -- ← container heavy trailers
|
||||
"TRAILERS", "TRAILER2", "TRAILER3", "TRAILER4",
|
||||
"trailers", "trailers2", "trailers3", "trailers4",
|
||||
"freighttrailer", "armytanker", "docktrailer"
|
||||
},
|
||||
|
||||
LightModels = {
|
||||
"tr2", "tr3", "tr4", "trflat", -- ← container light trailers
|
||||
"tanker", "tanker2", "trailerlogs",
|
||||
"tvtrailer", "baletrailer", "graintrailer"
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
fx_version 'cerulean'
|
||||
game 'gta5'
|
||||
|
||||
lua54 'yes'
|
||||
author 'John Chin'
|
||||
description 'Weigh Stations (3rd Location)'
|
||||
version '1.0.0'
|
||||
|
||||
shared_scripts {
|
||||
'@ox_lib/init.lua',
|
||||
'config.lua'
|
||||
}
|
||||
|
||||
client_scripts {
|
||||
'MainLights/client.lua',
|
||||
'RoadSignLights/client.lua',
|
||||
'RampLight/client.lua',
|
||||
'WeighUi/client.lua'
|
||||
}
|
||||
|
||||
server_scripts {
|
||||
'MainLights/server.lua',
|
||||
'RoadSignLights/server.lua',
|
||||
'RampLight/server.lua',
|
||||
'WeighUi/server.lua'
|
||||
}
|
||||
|
||||
ui_page 'WeighUi/html/ui.html'
|
||||
|
||||
files {
|
||||
'WeighUi/html/ui.html',
|
||||
'WeighUi/html/style.css',
|
||||
'WeighUi/html/script.js'
|
||||
}
|
||||
BIN
Binary file not shown.
LFS
BIN
Binary file not shown.
LFS
BIN
Binary file not shown.
LFS
BIN
Binary file not shown.
LFS
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
LFS
BIN
Binary file not shown.
LFS
BIN
Binary file not shown.
LFS
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
LFS
BIN
Binary file not shown.
BIN
Binary file not shown.
resources/[EGRP-Map-Addons]/[jd-weighstation03]/jd-weighstation03/stream/jd_weighstation03_ext02.ydr
LFS
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user