Turfwar/client/vehicles.lua

263 lines
7.5 KiB
Lua

-- client/vehicles.lua
print("^2[turfwar]^7 client/vehicles.lua LOADED (HQ marker + spawn + doSpawn mutex)")
Config = Config or {}
Config.Vehicles = Config.Vehicles or {}
Config.GANGS = Config.GANGS or {}
Config.JOIN_POINTS = Config.JOIN_POINTS or {}
local currentGang = 0
local myVehNetId = 0
local myVehBlip = 0
local nextSpawnAt = 0
local myVehGangId = 0
-- GLOBAL mutex shared across ALL client scripts
_G.__turfwar_doSpawnBusy = _G.__turfwar_doSpawnBusy or false
-- =========================
-- Helpers
-- =========================
local function Notify(msg)
BeginTextCommandThefeedPost("STRING")
AddTextComponentSubstringPlayerName(msg)
EndTextCommandThefeedPostTicker(false, false)
end
local function Draw3DText(x, y, z, text)
local onScreen, _x, _y = World3dToScreen2d(x, y, z)
if not onScreen then return end
SetTextScale(0.35, 0.35)
SetTextFont(4)
SetTextProportional(1)
SetTextEntry("STRING")
SetTextCentre(1)
AddTextComponentString(text)
DrawText(_x, _y)
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 loadModel(model)
local hash = type(model) == "number" and model or GetHashKey(model)
if not IsModelInCdimage(hash) then return nil end
RequestModel(hash)
local timeout = GetGameTimer() + 7000
while not HasModelLoaded(hash) do
Wait(10)
if GetGameTimer() > timeout then
return nil
end
end
return hash
end
local function getGangBlipColor(gangId)
gangId = tonumber(gangId) or 0
local g = Config.GANGS and Config.GANGS[gangId]
local c = g and g.blipColor
return tonumber(c) or 2
end
local function setMyBlipForVehicle(veh)
if DoesBlipExist(myVehBlip) then
RemoveBlip(myVehBlip)
myVehBlip = 0
end
if not veh or veh == 0 then return end
myVehBlip = AddBlipForEntity(veh)
SetBlipSprite(myVehBlip, 225)
SetBlipScale(myVehBlip, 0.75)
SetBlipColour(myVehBlip, getGangBlipColor(myVehGangId)) -- <- gang color
SetBlipAsShortRange(myVehBlip, false)
BeginTextCommandSetBlipName("STRING")
AddTextComponentString("Gang Vehicle")
EndTextCommandSetBlipName(myVehBlip)
end
-- =========================
-- Gang updates (MATCH YOUR SERVER)
-- =========================
local function setGang(gangId)
currentGang = tonumber(gangId) or 0
end
-- sent directly to the player on change
RegisterNetEvent("turfwar:gangUpdate", function(gangId)
setGang(gangId)
end)
-- compatibility event your server also triggers
RegisterNetEvent("turfwar:setFaction", function(gangId)
setGang(gangId)
end)
-- broadcast to all clients: (src, gangId)
RegisterNetEvent("turfwar:playerGang", function(src, gangId)
if src == GetPlayerServerId(PlayerId()) then
setGang(gangId)
end
end)
RegisterCommand("tw_gang", function()
print("^3[turfwar]^7 currentGang = " .. tostring(currentGang))
Notify("currentGang = " .. tostring(currentGang))
end)
-- On resource start, ask server for our current gang via existing requestFaction
CreateThread(function()
Wait(1000)
TriggerServerEvent("turfwar:requestFaction")
end)
-- =========================
-- Server -> Client spawn
-- =========================
RegisterNetEvent("turfwar:veh:doSpawn", function(data)
if _G.__turfwar_doSpawnBusy then
print("^1[turfwar]^7 Ignoring duplicate doSpawn (global mutex busy)")
return
end
_G.__turfwar_doSpawnBusy = true
local function done()
_G.__turfwar_doSpawnBusy = false
end
local ok, err = pcall(function()
if type(data) ~= "table" or not data.model then
print("^1[turfwar]^7 doSpawn: bad data")
done()
return
end
local hash = loadModel(data.model)
if not hash then
Notify("~r~Vehicle model failed to load.~s~")
done()
return
end
local x = tonumber(data.x) or 0.0
local y = tonumber(data.y) or 0.0
local z = tonumber(data.z) or 0.0
local h = tonumber(data.heading) or 0.0
local plate = tostring(data.plate or "GANG")
local veh = CreateVehicle(hash, x, y, z, h, true, false)
SetModelAsNoLongerNeeded(hash)
if not veh or veh == 0 then
Notify("~r~Vehicle spawn failed.~s~")
done()
return
end
SetVehicleOnGroundProperly(veh)
SetVehicleEngineOn(veh, true, true, false)
SetVehicleDirtLevel(veh, 0.0)
SetVehicleNumberPlateText(veh, plate)
-- Apply RGB if provided
if data.rgb and type(data.rgb) == "table" then
local r = tonumber(data.rgb[1]) or 255
local g = tonumber(data.rgb[2]) or 255
local b = tonumber(data.rgb[3]) or 255
SetVehicleCustomPrimaryColour(veh, r, g, b)
SetVehicleCustomSecondaryColour(veh, r, g, b)
end
local netId = NetworkGetNetworkIdFromEntity(veh)
SetNetworkIdCanMigrate(netId, true)
TriggerServerEvent("turfwar:veh:spawned", netId)
myVehNetId = netId
myVehGangId = tonumber(data.gangId) or currentGang or 0
setMyBlipForVehicle(veh)
done()
end)
if not ok then
print("^1[turfwar]^7 doSpawn crashed: " .. tostring(err))
_G.__turfwar_doSpawnBusy = false
end
end)
RegisterNetEvent("turfwar:veh:notify", function(msg)
Notify(msg)
end)
RegisterNetEvent("turfwar:veh:setLocal", function(netId, gangId)
myVehNetId = tonumber(netId) or 0
myVehGangId = tonumber(gangId) or 0
end)
RegisterNetEvent("turfwar:veh:clearLocal", function()
myVehNetId = 0
myVehGangId = 0
if DoesBlipExist(myVehBlip) then
RemoveBlip(myVehBlip)
myVehBlip = 0
end
end)
-- =========================
-- HQ marker + E to request spawn
-- (matches server validation against HQ join point)
-- =========================
CreateThread(function()
local useKey = (Config.Vehicles and Config.Vehicles.interactKey) or 38 -- E
local useDist = (Config.Vehicles and Config.Vehicles.interactDist) or 2.5
local markerDist = (Config.Vehicles and Config.Vehicles.markerDist) or 20.0
while true do
Wait(0)
if not currentGang or currentGang == 0 then
goto continue
end
local hq = getHQPosForGang(currentGang)
if not hq then
goto continue
end
local ped = PlayerPedId()
local p = GetEntityCoords(ped)
local d = #(p - hq)
if d < markerDist then
DrawMarker(1, hq.x, hq.y, hq.z - 1.0, 0,0,0, 0,0,0, 1.2,1.2,0.8, 255,255,255, 120, false,true,2, false,nil,nil,false)
if d < useDist then
Draw3DText(hq.x, hq.y, hq.z + 0.25, "~w~Gang Vehicle~n~~y~[E]~w~ Spawn / Replace")
if IsControlJustPressed(0, useKey) then
local now = GetGameTimer()
if now < nextSpawnAt then goto continue end
nextSpawnAt = now + 1200
local pcoords = { x = p.x, y = p.y, z = p.z }
TriggerServerEvent("turfwar:veh:requestSpawn", pcoords)
end
end
end
::continue::
end
end)