Documentation

Can-Check Hooks

Hook functions that run before towing actions are executed. Return false to deny with an optional reason.

Can-check hooks allow you to control player actions in zyke_towing before they execute. All hooks return true by default. Return false with an optional locale key to deny an action and notify the player.

#File Locations

SideFile
Serverserver/unlocked/can_checks.lua
Clientclient/unlocked/can_checks.lua

Both files are unencrypted and safe to edit directly. Edit the existing functions inside Towing.

Types / Classes

All types / classes can be found in types/types.lua. Vehicle arguments are entity handles; plyId is the requesting player's server ID. TowRecord describes a rope or cable connection.


#How Reason Strings Work

#Server-side reasons

The server returns the reason through the action callback. The client passes it to Z.notify(), so use a locale key. Missing reasons fall back to "noPermission".

#Client-side reasons

Client checks also use locale keys and fall back to "noPermission". They provide immediate feedback; enforce trusted restrictions in the corresponding server hook. Add custom reason keys to every resource locale.

This server-side example allows only steel cables when a player equips a material or requests an attachment.

Example:

lua
---@param plyId PlayerId
---@param material string
---@return boolean allowed
---@return string? reason
function CanUseTowRope(plyId, material)
    if (material ~= "metal") then return false, "noPermission" end

    return true
end

#Execution & Validation

Keep hooks synchronous and free of side effects. They may run repeatedly during target selection or winch heartbeats. Returning true continues the normal flow; built-in entity, inventory, access, and safety checks still apply.

Trusted server CreateTowRecord / RemoveTowRecord exports and automatic cleanup bypass player action hooks. Stopping a winch is always allowed.


#Server-Sided Hooks

All server-sided hooks are in server/unlocked/can_checks.lua.

#Can Use Tow Rope

Called when checking whether the player can equip a material and again before attaching vehicles. material is the key in Config.Settings.towing.ropeMaterials, such as rope or metal.

Example:

lua
---@param plyId PlayerId
---@param material string
---@return boolean allowed
---@return string? reason
function CanUseTowRope(plyId, material)
    return true
end

#Can Tow Vehicle

Called before a player attachment request creates a connection or consumes its item. tower is the pulling vehicle and towed is the load; bumper ends are front or rear.

Example:

lua
---@param plyId PlayerId
---@param tower integer @ Vehicle doing the pulling
---@param towed integer @ Vehicle being pulled
---@param material string
---@param towerEnd "rear" | "front"
---@param towedEnd "rear" | "front"
---@return boolean allowed
---@return string? reason
function CanTowVehicle(plyId, tower, towed, material, towerEnd, towedEnd)
    return true
end

#Can Detach Tow

Called before a player manually detaches a connection. tow is the active TowRecord. Returning true continues the normal item-refund and removal checks.

Example:

lua
---@param plyId PlayerId
---@param tow TowRecord
---@return boolean allowed
---@return string? reason
function CanDetachTow(plyId, tow)
    return true
end

#Can Winch Tow

Called on each reel-in or pay-out request, including hold heartbeats. direction is in or out. Use an inexpensive check; stopping the winch does not call this gate.

Example:

lua
---@param plyId PlayerId
---@param tow TowRecord
---@param direction "in" | "out"
---@return boolean allowed
---@return string? reason
function CanWinchTow(plyId, tow, direction)
    return true
end

#Can Change Tow Bed

Called before a player loads, unloads, or moves a bed vehicle. slot is the destination slot for loading/moving and the occupied slot for unloading. Indices are one-based. unload is true for unloading; fromSlot identifies the original slot when repositioning a loaded vehicle.

Example:

lua
---@param plyId PlayerId
---@param carrier integer
---@param vehicle integer
---@param slot integer
---@param unload boolean
---@param fromSlot? integer @ Existing slot when repositioning a loaded vehicle
---@return boolean allowed
---@return string? reason
function CanChangeTowBed(plyId, carrier, vehicle, slot, unload, fromSlot)
    return true
end

#Client-Sided Hooks

All client-sided hooks are in client/unlocked/can_checks.lua.

#Can Use Tow Rope

Called before starting the normal rope or cable carrying flow. The material key is rope or metal by default. The detach animation that shows and pockets a returned rope skips this check.

Example:

lua
---@param material string
---@return boolean allowed
---@return string? reason
function CanUseTowRope(material)
    return true
end

#Can Tow Vehicle

Called while validating attachment, including target selection and checks around the progress action. Keep it inexpensive. The vehicle arguments are local entity handles and each end is front or rear.

Example:

lua
---@param tower integer @ Vehicle doing the pulling
---@param towed integer @ Vehicle being pulled
---@param material string
---@param towerEnd "rear" | "front"
---@param towedEnd "rear" | "front"
---@return boolean allowed
---@return string? reason
function CanTowVehicle(tower, towed, material, towerEnd, towedEnd)
    return true
end

#Can Detach Tow

Called before the player starts the detachment progress action. tow is the selected connection. Server validation runs again when the player requests removal.

Example:

lua
---@param tow TowRecord
---@return boolean allowed
---@return string? reason
function CanDetachTow(tow)
    return true
end

#Can Winch Tow

Called before starting a local winch action. direction is in or out. The server hook independently checks subsequent hold requests.

Example:

lua
---@param tow TowRecord
---@param direction "in" | "out"
---@return boolean allowed
---@return string? reason
function CanWinchTow(tow, direction)
    return true
end

#Can Change Tow Bed

Called before requesting a bed load, unload, or slot move. slot is the one-based destination or unloading slot. unload is true for unloading; fromSlot is provided when moving a vehicle from another slot. The server independently validates the operation.

Example:

lua
---@param carrier integer
---@param vehicle integer
---@param slot integer
---@param unload boolean
---@param fromSlot? integer @ Existing slot when repositioning a loaded vehicle
---@return boolean allowed
---@return string? reason
function CanChangeTowBed(carrier, vehicle, slot, unload, fromSlot)
    return true
end

#Can Open Tow Bed Menu

Called before opening the carrier slot menu. This client-only hook controls menu access; enforce loading, unloading, and moving restrictions in the server CanChangeTowBed hook.

Example:

lua
---@param carrier integer
---@return boolean allowed
---@return string? reason
function CanOpenTowBedMenu(carrier)
    return true
end

#Common Patterns

#Restrict Player Attachments to Steel Cables

Edit the server attachment hook to require the metal material. Mirror the rule in the client hook for feedback during target selection.

Example:

lua
---@param plyId PlayerId
---@param tower integer @ Vehicle doing the pulling
---@param towed integer @ Vehicle being pulled
---@param material string
---@param towerEnd "rear" | "front"
---@param towedEnd "rear" | "front"
---@return boolean allowed
---@return string? reason
function CanTowVehicle(plyId, tower, towed, material, towerEnd, towedEnd)
    if (material ~= "metal") then return false, "noPermission" end

    return true
end

#Allow Bed Loading and Unloading but Deny Slot Moves

Use fromSlot to distinguish moving an already loaded vehicle from a new load or unload.

Example:

lua
---@param plyId PlayerId
---@param carrier integer
---@param vehicle integer
---@param slot integer
---@param unload boolean
---@param fromSlot? integer @ Existing slot when repositioning a loaded vehicle
---@return boolean allowed
---@return string? reason
function CanChangeTowBed(plyId, carrier, vehicle, slot, unload, fromSlot)
    if (fromSlot ~= nil) then return false, "noPermission" end

    return true
end