Turfwar/server/vehicles.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)