-- client/gang_shop_points.lua (DEBUG) print("^2[turfwar]^7 gang_shop_points.lua loaded (DEBUG markers + blips)") Config = Config or {} Config.ShopPoints = Config.ShopPoints or {} Config.Shops = Config.Shops or {} local currentGang = 0 local showAll = false local debug = false -- Menu state local menuOpen = false local menuType = nil local menuItems = {} local NumKey = { [1]=157,[2]=158,[3]=160,[4]=164,[5]=165,[6]=159,[7]=161,[8]=162,[9]=163 } 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 allowedGang(gangId) return gangId ~= 0 and gangId ~= 3 end -- ====== DEBUG COMMANDS ====== RegisterCommand("tw_shop_debug", function() debug = not debug Notify(("Shop debug: %s"):format(debug and "~g~ON~s~" or "~r~OFF~s~")) end) RegisterCommand("tw_shop_showall", function() showAll = not showAll Notify(("Show ALL shop points: %s"):format(showAll and "~g~ON~s~" or "~r~OFF~s~")) end) RegisterCommand("tw_shop_where", function() local p = GetEntityCoords(PlayerPedId()) local msg = ("You are at: vector3(%.3f, %.3f, %.3f) gang=%d"):format(p.x, p.y, p.z, currentGang) print("^3[turfwar]^7 " .. msg) Notify(msg) end) -- ====== Gang update hook ====== RegisterNetEvent("turfwar:myGang", function(gangId) currentGang = tonumber(gangId) or 0 if debug then print(("^3[turfwar]^7 myGang received -> %s"):format(currentGang)) end end) -- ====== Blip so you can FIND it ====== local shopBlip = 0 local function refreshBlip() if DoesBlipExist(shopBlip) then RemoveBlip(shopBlip) shopBlip = 0 end local p = Config.ShopPoints.ByGang and Config.ShopPoints.ByGang[currentGang] if not p then if debug then print("^1[turfwar]^7 No shop point found for gangId=" .. tostring(currentGang)) end return end shopBlip = AddBlipForCoord(p.x, p.y, p.z) SetBlipSprite(shopBlip, 52) -- safe generic blip SetBlipScale(shopBlip, 0.8) SetBlipColour(shopBlip, 2) SetBlipAsShortRange(shopBlip, false) BeginTextCommandSetBlipName("STRING") AddTextComponentString("Gang Shop Point") EndTextCommandSetBlipName(shopBlip) if debug then print(("^2[turfwar]^7 Shop blip set for gang %d at %.3f %.3f %.3f"):format(currentGang, p.x, p.y, p.z)) end end RegisterCommand("tw_shop_blip", function() refreshBlip() Notify("Shop blip refreshed.") end) -- Auto refresh blip occasionally (in case gang changes) CreateThread(function() Wait(2000) refreshBlip() while true do Wait(5000) if shopBlip == 0 and currentGang ~= 0 then refreshBlip() end end end) -- ====== Menu (unchanged) ====== local function printMenuToConsole() print(("^3[turfwar]^7 ====== %s SHOP (1-9 buy, BACKSPACE close) ======"):format(menuType:upper())) for i, it in ipairs(menuItems) do if i > 9 then break end print(("^3[turfwar]^7 [%d] %s ^2$%d^7 (id: %s)"):format(i, it.label or it.id, tonumber(it.price) or 0, it.id)) end end local function openMenu(kind) if menuOpen then return end menuOpen = true menuType = kind if kind == "weapons" then menuItems = Config.Shops.WeaponList or {} Notify("~y~Weapon Shop~s~ opened. Check F8. 1-9 buy. BACKSPACE closes.") else menuItems = Config.Shops.VehicleList or {} Notify("~y~Vehicle Shop~s~ opened. Check F8. 1-9 buy. BACKSPACE closes.") end printMenuToConsole() end local function closeMenu() if not menuOpen then return end menuOpen = false menuType = nil menuItems = {} Notify("~r~Shop closed.~s~") end local function buyIndex(idx) if not menuOpen then return end local it = menuItems[idx] if not it then return end if menuType == "weapons" then TriggerServerEvent("turfwar:shop:buyWeapon", it.id) else TriggerServerEvent("turfwar:shop:buyVehicle", it.id) end end CreateThread(function() while true do Wait(0) if not menuOpen then goto continue end if IsControlJustPressed(0, 177) then closeMenu() end -- backspace for i = 1, 9 do if IsControlJustPressed(0, NumKey[i]) then buyIndex(i) end end ::continue:: end end) local function RequestMyGang() TriggerServerEvent("turfwar:gang:requestMyGang") end CreateThread(function() Wait(1500) RequestMyGang() end) AddEventHandler("playerSpawned", function() -- give other systems time to set gang on server if needed Wait(1500) RequestMyGang() end) -- ====== Marker draw ====== CreateThread(function() local useKey = 38 -- E local vehKey = 47 -- G local useDist = 3.0 -- increased for easier testing local markerDist = 150.0 -- increased so you can confirm it's working from farther away while true do Wait(0) local ped = PlayerPedId() local p = GetEntityCoords(ped) if not Config.ShopPoints.ByGang then if debug then Draw3DText(p.x, p.y, p.z + 1.0, "~r~Config.ShopPoints.ByGang is NIL~s~ (config not loaded)") end goto continue end local function drawAt(pos, label) local d = #(p - pos) if d < markerDist then DrawMarker(1, pos.x, pos.y, pos.z - 1.0, 0,0,0, 0,0,0, 1.2,1.2,0.8, 255,255,255, 140, false,true,2, false,nil,nil,false) if d < useDist then Draw3DText(pos.x, pos.y, pos.z + 0.25, ("~w~%s~n~~y~[E]~w~ Weapons ~y~[G]~w~ Vehicles"):format(label)) if IsControlJustPressed(0, useKey) then openMenu("weapons") end if IsControlJustPressed(0, vehKey) then openMenu("vehicles") end end end end if showAll then for gangId, pos in pairs(Config.ShopPoints.ByGang) do drawAt(pos, ("Shop GANG[%s]"):format(gangId)) end else if not allowedGang(currentGang) then if debug then Draw3DText(p.x, p.y, p.z + 1.0, ("~y~No marker: gang=%d (needs not 0/3)~s~"):format(currentGang)) end goto continue end local pos = Config.ShopPoints.ByGang[currentGang] if not pos then if debug then Draw3DText(p.x, p.y, p.z + 1.0, ("~r~No point for gang=%d~s~"):format(currentGang)) end goto continue end local label = (Config.ShopPoints.LabelByGang and Config.ShopPoints.LabelByGang[currentGang]) or ("Gang Shop %d"):format(currentGang) drawAt(pos, label) end ::continue:: end end)