if isServer() then return end require("TowBar/WreckerTimedAction") if not TowBarMod then TowBarMod = {} end TowBarMod.WreckerUI = TowBarMod.WreckerUI or {} local UI = TowBarMod.WreckerUI local Wrecker = TowBarMod.Wrecker local AttachDuration = 300 local DetachDuration = 200 local function sendAttachCommand(playerObj, wrecker, target) if not playerObj or not wrecker or not target then return end sendClientCommand(playerObj, "towbar", "attachWrecker", { wrecker = wrecker:getId(), target = target:getId() }) end local function sendDetachCommand(playerObj, wrecker, target) if not playerObj or not wrecker or not target then return end sendClientCommand(playerObj, "towbar", "detachWrecker", { wrecker = wrecker:getId(), target = target:getId() }) end local function isAttachStillValid(playerObj, wrecker, target) if not playerObj or not wrecker or not target then return false end if not wrecker:isDriver(playerObj) or not Wrecker.isSupportedWrecker(wrecker) then return false end if wrecker:getVehicleTowing() or wrecker:getVehicleTowedBy() or target:getVehicleTowing() or target:getVehicleTowedBy() then return false end local nearest = Wrecker.resolveNearestTarget(wrecker, Wrecker.getWorldVehicles()) return nearest ~= nil and nearest.vehicle == target end local function isDetachStillValid(playerObj, wrecker, target) if not playerObj or not wrecker or not target or not wrecker:isDriver(playerObj) then return false end local md = wrecker:getModData() return wrecker:getVehicleTowing() == target or (md and tonumber(md.wreckerTowedVehicleId) == target:getId()) end local function requestAttach(playerObj, wrecker, target) if not isAttachStillValid(playerObj, wrecker, target) then return end ISTimedActionQueue.add(WreckerTimedAction:new( playerObj, AttachDuration, isAttachStillValid, sendAttachCommand, wrecker, target )) end local function requestDetach(playerObj, wrecker, target) if not isDetachStillValid(playerObj, wrecker, target) then return end ISTimedActionQueue.add(WreckerTimedAction:new( playerObj, DetachDuration, isDetachStillValid, sendDetachCommand, wrecker, target )) end local function requestHeight(playerObj, wrecker, direction) if not playerObj or not wrecker then return end sendClientCommand(playerObj, "towbar", "adjustWreckerHeight", { wrecker = wrecker:getId(), direction = direction }) end function UI.addOptionsToMenu(playerObj, wrecker) if not playerObj or not wrecker or not Wrecker.isSupportedWrecker(wrecker) then return false end if not wrecker:isDriver(playerObj) then return false end local menu = getPlayerRadialMenu(playerObj:getPlayerNum()) if not menu then return false end local md = wrecker:getModData() local targetId = md and tonumber(md.wreckerTowedVehicleId) or nil local target = targetId and getVehicleById(targetId) or wrecker:getVehicleTowing() if target and (target == wrecker:getVehicleTowing() or targetId == target:getId()) then TowBarMod.UI.removeDefaultDetachOption(playerObj) local level = tonumber(md.wreckerHeightLevel) or 0 if level < Wrecker.MaxHeightLevel then menu:addSlice( getText("UI_Text_Towing_heightUp"), getTexture("media/textures/arrow_up.png"), requestHeight, playerObj, wrecker, 1 ) end if level > Wrecker.MinHeightLevel then menu:addSlice( getText("UI_Text_Towing_heightDown"), getTexture("media/textures/arrow_down.png"), requestHeight, playerObj, wrecker, -1 ) end menu:addSlice( getText("UI_Text_Towing_detachHook", ISVehicleMenu.getVehicleDisplayName(target)), getTexture("media/textures/untow_car_icon.png"), requestDetach, playerObj, wrecker, target ) return true end if wrecker:getVehicleTowing() or wrecker:getVehicleTowedBy() then return false end local nearest = Wrecker.resolveNearestTarget(wrecker, Wrecker.getWorldVehicles()) if not nearest then return false end menu:addSlice( getText("UI_Text_Towing_attachHook", ISVehicleMenu.getVehicleDisplayName(nearest.vehicle)), getTexture("media/textures/tow_car_icon.png"), requestAttach, playerObj, wrecker, nearest.vehicle ) return true end