179 lines
5.3 KiB
Lua
179 lines
5.3 KiB
Lua
-- server/vehicles.lua
|
|
print("^2[turfwar]^7 server/vehicles.lua LOADED (config spawn pads)")
|
|
|
|
VehicleSpawner = VehicleSpawner or {}
|
|
|
|
-- ActiveVeh[src] = { netId=number, gangId=number }
|
|
local ActiveVeh = {}
|
|
|
|
-- PendingSpawn[src] = { gangId=number, model=string, plate=string }
|
|
local PendingSpawn = {}
|
|
|
|
local function gangFromSrc(src)
|
|
if PlayerGang and PlayerGang[src] then
|
|
return tonumber(PlayerGang[src]) or 0
|
|
end
|
|
return 0
|
|
end
|
|
|
|
local function getGangRGB(gangId)
|
|
local g = Config and Config.GANGS and Config.GANGS[gangId]
|
|
local rgb = g and g.rgb
|
|
if rgb and rgb[1] and rgb[2] and rgb[3] then
|
|
return tonumber(rgb[1]) or 255, tonumber(rgb[2]) or 255, tonumber(rgb[3]) or 255
|
|
end
|
|
return 255, 255, 255
|
|
end
|
|
|
|
local function getHQPosForGang(gangId)
|
|
for _, jp in ipairs(Config.JOIN_POINTS or {}) do
|
|
if tonumber(jp.gangId) == tonumber(gangId) then
|
|
return jp.pos
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function getSpawnPadForGang(gangId)
|
|
local sp = Config and Config.GANG_VEHICLE_SPAWNS and Config.GANG_VEHICLE_SPAWNS[gangId]
|
|
if not sp then return nil end
|
|
return {
|
|
x = tonumber(sp.x) or 0.0,
|
|
y = tonumber(sp.y) or 0.0,
|
|
z = tonumber(sp.z) or 0.0,
|
|
h = tonumber(sp.w) or 0.0
|
|
}
|
|
end
|
|
|
|
local function dist(a, b)
|
|
local dx = (a.x - b.x)
|
|
local dy = (a.y - b.y)
|
|
local dz = (a.z - b.z)
|
|
return math.sqrt(dx*dx + dy*dy + dz*dz)
|
|
end
|
|
|
|
local function deleteVehicleFor(src)
|
|
local entry = ActiveVeh[src]
|
|
if not entry then return end
|
|
|
|
if entry.netId and entry.netId ~= 0 then
|
|
local e = NetworkGetEntityFromNetworkId(entry.netId)
|
|
if e and DoesEntityExist(e) then
|
|
DeleteEntity(e)
|
|
end
|
|
end
|
|
|
|
TriggerClientEvent("turfwar:veh:clearLocal", src)
|
|
ActiveVeh[src] = nil
|
|
end
|
|
|
|
local function setPendingTimeout(src)
|
|
SetTimeout(8000, function()
|
|
if PendingSpawn[src] then
|
|
PendingSpawn[src] = nil
|
|
TriggerClientEvent("turfwar:veh:notify", src, "~y~Spawn timed out. Try again.~s~")
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- Called from server/main.lua on gang change:
|
|
function VehicleSpawner.OnGangChanged(src, oldGang, newGang)
|
|
oldGang = tonumber(oldGang) or 0
|
|
newGang = tonumber(newGang) or 0
|
|
if oldGang ~= newGang then
|
|
deleteVehicleFor(src)
|
|
end
|
|
end
|
|
|
|
-- =========================================================
|
|
-- EXTERNAL SPAWN (for vehicle shop purchases)
|
|
-- =========================================================
|
|
function VehicleSpawner.SpawnModelFor(src, modelName, opts)
|
|
opts = opts or {}
|
|
|
|
-- HARD BLOCK: prevent double spawns from double-trigger / spam
|
|
if PendingSpawn[src] then
|
|
TriggerClientEvent("turfwar:veh:notify", src, "~y~Spawn already in progress...~s~")
|
|
return false, "pending"
|
|
end
|
|
|
|
local gangId = gangFromSrc(src)
|
|
if gangId == 0 then
|
|
TriggerClientEvent("turfwar:veh:notify", src, "~r~You are Neutral.~s~")
|
|
return false, "neutral"
|
|
end
|
|
|
|
if gangId == 3 then
|
|
TriggerClientEvent("turfwar:veh:notify", src, "~r~Police can't use this system.~s~")
|
|
return false, "police"
|
|
end
|
|
|
|
if type(modelName) ~= "string" or modelName == "" then
|
|
TriggerClientEvent("turfwar:veh:notify", src, "~r~Bad vehicle model.~s~")
|
|
return false, "bad_model"
|
|
end
|
|
|
|
local pad = getSpawnPadForGang(gangId)
|
|
if not pad then
|
|
TriggerClientEvent("turfwar:veh:notify", src, "~r~No vehicle spawn pad set for your gang.~s~")
|
|
print(("^1[turfwar]^7 Missing Config.GANG_VEHICLE_SPAWNS[%s]"):format(gangId))
|
|
return false, "no_pad"
|
|
end
|
|
|
|
if ActiveVeh[src] then
|
|
deleteVehicleFor(src)
|
|
end
|
|
|
|
local r, g, b = getGangRGB(gangId)
|
|
local prefix = opts.platePrefix
|
|
or ((Config.Vehicles and Config.Vehicles.platePrefix and Config.Vehicles.platePrefix[gangId]) or ("G"..tostring(gangId)))
|
|
local plate = (prefix .. tostring(src)):sub(1, 8)
|
|
|
|
PendingSpawn[src] = { gangId = gangId, model = modelName, plate = plate }
|
|
setPendingTimeout(src)
|
|
|
|
print(("^3[turfwar]^7 doSpawn(shop) -> src=%d gang=%d model=%s plate=%s"):format(src, gangId, modelName, plate))
|
|
|
|
TriggerClientEvent("turfwar:veh:doSpawn", src, {
|
|
gangId = gangId,
|
|
model = modelName,
|
|
x = pad.x,
|
|
y = pad.y,
|
|
z = pad.z,
|
|
heading = pad.h,
|
|
rgb = { r, g, b },
|
|
plate = plate
|
|
})
|
|
|
|
return true
|
|
end
|
|
|
|
RegisterNetEvent("turfwar:veh:spawned", function(netId)
|
|
local src = source
|
|
netId = tonumber(netId) or 0
|
|
|
|
local req = PendingSpawn[src]
|
|
PendingSpawn[src] = nil
|
|
|
|
if not req then
|
|
TriggerClientEvent("turfwar:veh:notify", src, "~r~Spawn rejected (no pending request).~s~")
|
|
return
|
|
end
|
|
|
|
if netId == 0 then
|
|
TriggerClientEvent("turfwar:veh:notify", src, "~r~Vehicle spawn failed (netId=0).~s~")
|
|
return
|
|
end
|
|
|
|
ActiveVeh[src] = { netId = netId, gangId = req.gangId }
|
|
|
|
TriggerClientEvent("turfwar:veh:setLocal", src, netId, req.gangId)
|
|
TriggerClientEvent("turfwar:veh:notify", src, "~g~Gang vehicle spawned.~s~")
|
|
end)
|
|
|
|
AddEventHandler("playerDropped", function()
|
|
local src = source
|
|
deleteVehicleFor(src)
|
|
PendingSpawn[src] = nil
|
|
end)
|