1
0
Fork 0
forked from Simnation/Main
This commit is contained in:
Nordi98 2025-07-12 13:10:51 +02:00
parent 26ed285540
commit 4c95214808
53 changed files with 694 additions and 2507 deletions

Binary file not shown.

View file

@ -0,0 +1,34 @@
# KQ_TOWING2 INSTALLATION GUIDE
This guide will provide step-by-step instructions on how to install and set up the KQ_TOWING2 script for FiveM.
## Step 1:
After downloading the script, unzip the folder and place it in the `resources` directory on your FiveM server.
## Step 2:
Add the script to your `server.cfg` file. Make sure that it's added **after** the framework of choice if using any.
## Step 3:
Open the `config.lua` file in the script folder and make sure that the correct framework is enabled. (If using ESX or QBCore)
## Framework specific setup
### ESX
- Import the SQL file located inside the `/esx` folder to your database to add the items or change the item names in the config to match existing items.
### QBCore
- Add the items located in the `/qb` folder to your qb-core shared.lua file `qb-core/shared/items.lua` or `qb-core/shared.lua` or change the item names in the config to match existing items.
### QBOX / OX_INVENTORY (When not using ESX or QBCore)
- Add the items located in the `/ox` folder to your ox_inventory items list, and make sure that `kq_towing2` starts BEFORE ox_inventory
### Extra
- If using an anti-cheat make sure to whitelist a prop: `prop_roadpole_01a`. This prop is required for the rope to work properly
## Done
Enjoy the script
- https://kuzquality.com/
- https://discord.gg/fZsyam7Rvz
- https://www.youtube.com/@KuzQuality

View file

@ -0,0 +1,2 @@
INSERT INTO `items` (`name`, `label`, `weight`, `rare`, `can_remove`) VALUES ('kq_tow_rope', 'Towing rope', 2, 0, 1);
INSERT INTO `items` (`name`, `label`, `weight`, `rare`, `can_remove`) VALUES ('kq_winch', 'Car winch', 4, 0, 1);

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View file

@ -0,0 +1,22 @@
["kq_tow_rope"] = {
label = "Towing rope",
weight = 2000,
stack = true,
close = true,
consume = 0,
server = {
export = 'kq_towing2.UseTowRope',
},
},
["kq_winch"] = {
label = "Car winch",
weight = 4000,
stack = true,
close = true,
consume = 0,
server = {
export = 'kq_towing2.UseWinch',
},
},

View file

@ -0,0 +1,3 @@
["kq_tow_rope"] = {["name"] = "kq_tow_rope", ["label"] = "Towing rope", ["weight"] = 2000, ["type"] = "item", ["image"] = "kq_tow_rope.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Rope used for towing vehicles"},
["kq_winch"] = {["name"] = "kq_winch", ["label"] = "Car winch", ["weight"] = 4000, ["type"] = "item", ["image"] = "kq_winch.png", ["unique"] = false, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = "Car winch made to winch heavy vehicles"},

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,131 @@
-- This function is responsible for drawing all the 3d texts ('Press [E] to take off the wheel' e.g)
function Draw3DText(coords, textInput, scaleX)
scaleX = scaleX * Config.textScale
local px, py, pz = table.unpack(GetGameplayCamCoords())
local dist = GetDistanceBetweenCoords(px, py, pz, coords, true)
local scale = (1 / dist) * 20
local fov = (1 / GetGameplayCamFov()) * 100
scale = scale * fov
SetTextScale(scaleX * scale, scaleX * scale)
SetTextFont(Config.textFont or 4)
SetTextProportional(1)
SetTextDropshadow(1, 1, 1, 1, 255)
SetTextEdge(2, 0, 0, 0, 150)
SetTextDropShadow()
SetTextOutline()
SetTextEntry("STRING")
SetTextCentre(1)
AddTextComponentString(textInput)
SetDrawOrigin(coords, 0)
DrawText(0.0, 0.0)
ClearDrawOrigin()
end
function KeybindTip(message)
SetTextComponentFormat("STRING")
AddTextComponentString(message)
EndTextCommandDisplayHelp(0, 0, 0, 200)
end
function IsPlayerUnreachable()
local playerPed = PlayerPedId()
return IsPedInAnyVehicle(playerPed) or IsPedRagdoll(playerPed) or IsEntityDead(playerPed)
end
function RemoveHandWeapons()
SetCurrentPedWeapon(PlayerPedId(), -1569615261, true)
end
function DisableInputs()
-- https://docs.fivem.net/docs/game-references/controls/#controls
local inputs = {14, 15, 16, 17, 23, 24, 25, 44, 45, 140, 141, 142, 143, 261, 262, 263, 264}
for k, input in pairs(inputs) do
DisableControlAction(0, input, true)
end
end
function IsVehicleLocked(entity)
if not IsEntityAVehicle(entity) then
return false
end
local lockStatus = GetVehicleDoorLockStatus(entity)
return lockStatus == 2 or lockStatus == 3 or lockStatus == 4 or lockStatus == 10
end
function PlayAnim(dict, anim, flag, duration)
Citizen.CreateThread(function()
RequestAnimDict(dict)
local timeout = 0
while not HasAnimDictLoaded(dict) do
Citizen.Wait(50)
timeout = timeout + 1
if timeout > 100 then
return
end
end
TaskPlayAnim(PlayerPedId(), dict, anim, 1.5, 1.0, duration or -1, flag or 1, 0, false, false, false)
RemoveAnimDict(dict)
end)
end
function ShowTooltip(message)
SetTextComponentFormat("STRING")
AddTextComponentString(message)
EndTextCommandDisplayHelp(0, 0, 1, -1)
end
CURRENT_KEYBIND_TIP = nil
function SetKeybindTip(message)
if CURRENT_KEYBIND_TIP == message then
return
end
CURRENT_KEYBIND_TIP = message
Citizen.CreateThread(function()
while CURRENT_KEYBIND_TIP == message do
local sleep = 100
if CURRENT_KEYBIND_TIP then
sleep = 1
ShowKeybindTip(CURRENT_KEYBIND_TIP)
end
Citizen.Wait(sleep)
end
end)
end
function ResetKeybindTip()
if CURRENT_KEYBIND_TIP ~= nil then
CURRENT_KEYBIND_TIP = nil
end
end
function ShowKeybindTip(message)
SetTextComponentFormat("STRING")
AddTextComponentString(message)
EndTextCommandDisplayHelp(0, 0, 0, -1)
end
RegisterNetEvent('kq_towing:client:notify')
AddEventHandler('kq_towing:client:notify', function(message)
Notify(message)
end)
function Notify(message)
SetTextComponentFormat("STRING")
AddTextComponentString(message)
EndTextCommandDisplayHelp(0, 0, 0, 2000)
end
-- Call this event to cancel the placement of a rope
RegisterNetEvent('kq_towing:client:cancelPlacement')
AddEventHandler('kq_towing:client:cancelPlacement', function()
PLACING_ROPE = false
end)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,176 @@
Config = {}
Config.debug = false
-------------------------------------------------
--- FRAMEWORK SETTINGS
-------------------------------------------------
Config.esxSettings = {
enabled = false,
-- Whether or not to use the new ESX export method
useNewESXExport = true,
-- Enable this if you're using a very old version of ESX
oldEsx = false,
}
Config.qbSettings = {
enabled = false,
-- Whether or not to use the new QBCore export method
useNewQBExport = true,
}
-- Only enable when NOT using ESX or QBCore
Config.oxInventory = {
enabled = false,
}
-- Item config
Config.items = {
towingRope = 'kq_tow_rope',
winch = 'kq_winch',
}
-- Commands used to trigger rope placements
Config.commands = {
towing = {
enabled = true,
command = 'towrope',
},
winch = {
enabled = true,
command = 'winch',
}
}
-- Max speed (in MPH) of vehicles which are towing or being towed (set to -1 to disable speed limiting)
Config.maxTowingSpeed = 50
-- Time between each rope refreshing
-- Time in seconds
Config.ropeRefreshTime = 10
-- Makes towing a vehicle with no player in the back easier. The car will steer and brake automatically when towed
Config.toweeAutopilot = true
-- If script is used in standalone mode. Make sure to disable all the job whitelists!
-- Job whitelist
Config.jobWhitelist = {
towing = {
enabled = false,
jobs = {
'mechanic',
'police',
'marshal',
},
},
winch = {
enabled = false,
jobs = {
'mechanic',
'police',
'marshal',
},
},
}
-- Whether to disallow attaching ropes to vehicles which are locked
Config.disallowLockedVehicles = false
-- The MAXIMUM length of a tow rope
Config.ropeLength = 10.0
-- The MAXIMUM length of a winch
Config.winchLength = 16.0
-- Props which will be visible in players hands upon usage of the rope/winch item (or command)
Config.ropeProps = {
towing = {
prop = 'prop_rope_family_3',
bone = 4089,
offset = vector3(0.26, -0.11, 0.0),
rotation = vector3(0.0, -7.0, 200.0),
},
winch = {
prop = 'prop_stag_do_rope',
bone = 4089,
offset = vector3(0.24, -0.11, 0.0),
rotation = vector3(0.0, -7.0, 200.0),
}
}
-- '3d-text', 'top-left', 'help-text'
Config.inputType = '3d-text'
-- Scale of the 3d text
Config.textScale = 1
-- Font used for the 3d text
Config.textFont = 4
-- Scale used for the 3d text
Config.textScale = 1.0
-- https://docs.fivem.net/docs/game-references/controls/
-- Use the input index for the "input" value
Config.keybinds = {
confirm = {
label = 'E',
name = 'INPUT_PICKUP',
input = 38,
},
winch = {
label = 'Left Shift',
name = 'INPUT_SPRINT',
input = 21,
},
remove = {
label = 'E',
name = 'INPUT_PICKUP',
input = 38,
duration = 3000,
},
cancel = {
label = 'X',
name = 'INPUT_VEH_DUCK',
input = 73,
},
}
-- Classes of which vehicles may not be towed or tow another vehicle
Config.blacklistedClasses = {
8, -- Motorcycles
13, -- Cycles
14, -- Boats
15, -- Helicopters
16, -- Planes
21, -- Trains
}
--[[ All vehicle classes
0: Compacts
1: Sedans
2: SUVs
3: Coupes
4: Muscle
5: Sports Classics
6: Sports
7: Super
8: Motorcycles
9: Off-road
10: Industrial
11: Utility
12: Vans
13: Cycles
14: Boats
15: Helicopters
16: Planes
17: Service
18: Emergency
19: Military
20: Commercial
21: Trains
]]

View file

@ -0,0 +1,52 @@
fx_version 'cerulean'
games { 'gta5' }
lua54 'yes'
author 'KuzQuality | Kuzkay'
description 'Towing & winching made by KuzQuality'
version '2.3.2'
--
-- Server
--
server_scripts {
'locale.lua',
'mixed/constants.lua',
'config.lua',
'server/server.lua',
'server/editable/esx.lua',
'server/editable/qb.lua',
'server/editable/ox.lua',
'server/editable/editable.lua',
}
--
-- Client
--
client_scripts {
'config.lua',
'locale.lua',
'mixed/constants.lua',
'client/editable/editable.lua',
'client/cache.lua',
'client/inputs.lua',
'client/removing.lua',
'client/functions.lua',
'client/raycast.lua',
'client/client.lua',
'client/ropes.lua',
'client/winch.lua',
'client/towing.lua',
}
escrow_ignore {
'config.lua',
'locale.lua',
'client/editable/*.lua',
'server/editable/*.lua',
}
dependency '/assetpacks'

View file

@ -0,0 +1,24 @@
-- Only edit the value on the right. Leave the value between the square brackets as is. <!>
Locale = {
['~w~Press ~g~[~w~{INPUT}~g~]~w~ to attach the rope'] = '~w~Press ~g~[~w~{INPUT}~g~]~w~ to attach the rope',
['~w~Press ~{INPUT}~ to attach the rope'] = '~w~Press ~{INPUT}~ to attach the rope',
['~w~Press ~g~[~w~{INPUT}~g~]~w~ to tie the rope'] = '~w~Press ~g~[~w~{INPUT}~g~]~w~ to tie the rope',
['~w~Press ~{INPUT}~ to tie the rope'] = '~w~Press ~{INPUT}~ to tie the rope',
['Press ~{INPUT}~ to cancel'] = 'Press ~{INPUT}~ to cancel',
['~r~Too far'] = '~r~Too far',
['~y~You can not tie the rope to the ground'] = '~y~You can not tie the rope to the ground',
['~r~This vehicle can not be towed'] = '~r~This vehicle can not be towed',
['~w~Hold ~r~[~w~{INPUT}~r~]~w~ to detach the rope'] = '~w~Hold ~r~[~w~{INPUT}~r~]~w~ to detach the rope',
['~w~Hold ~{INPUT}~ to detach the rope'] = '~w~Hold ~{INPUT}~ to detach the rope',
['~w~Hold ~{INPUT}~ to winch'] = '~w~Hold ~{INPUT}~ to winch',
['~w~Release ~{INPUT}~ to stop winching'] = '~w~Release ~{INPUT}~ to stop winching',
['~r~You may not use this item'] = '~r~You may not use this item',
}

Binary file not shown.

View file

@ -0,0 +1,22 @@
if Config.commands.towing.enabled then
RegisterCommand(Config.commands.towing.command, function(source)
if Config.jobWhitelist.towing.enabled then
if not IsPlayerJobWhitelisted(source, Config.jobWhitelist.towing.jobs) then
return TriggerClientEvent('kq_towing:client:notify', source, L('~r~You may not use this item'))
end
end
TriggerClientEvent('kq_towing:client:startRope', source, false, false)
end)
end
if Config.commands.winch.enabled then
RegisterCommand(Config.commands.winch.command, function(source)
if Config.jobWhitelist.winch.enabled then
if not IsPlayerJobWhitelisted(source, Config.jobWhitelist.winch.jobs) then
return TriggerClientEvent('kq_towing:client:notify', source, L('~r~You may not use this item'))
end
end
TriggerClientEvent('kq_towing:client:startRope', source, true, false)
end)
end

View file

@ -0,0 +1,85 @@
if Config.esxSettings.enabled then
ESX = nil
if Config.esxSettings.useNewESXExport then
ESX = exports['es_extended']:getSharedObject()
else
TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
end
ESX.RegisterUsableItem(Config.items.towingRope, function(source)
if Config.jobWhitelist.towing.enabled then
if not IsPlayerJobWhitelisted(source, Config.jobWhitelist.towing.jobs) then
return TriggerClientEvent('kq_towing:client:notify', source, L('~r~You may not use this item'))
end
end
TriggerClientEvent('kq_towing:client:startRope', source, false, true)
end)
ESX.RegisterUsableItem(Config.items.winch, function(source)
if Config.jobWhitelist.winch.enabled then
if not IsPlayerJobWhitelisted(source, Config.jobWhitelist.winch.jobs) then
return TriggerClientEvent('kq_towing:client:notify', source, L('~r~You may not use this item'))
end
end
TriggerClientEvent('kq_towing:client:startRope', source, true, true)
end)
function IsPlayerJobWhitelisted(player, jobs)
local xPlayer = ESX.GetPlayerFromId(player)
if not xPlayer then
return false
end
local job = xPlayer.getJob()
return Contains(jobs, job.name)
end
function GetPlayerItemData(player, item)
local xPlayer = ESX.GetPlayerFromId(player)
return xPlayer.getInventoryItem(item)
end
function GetPlayerItemCount(player, item)
local data = GetPlayerItemData(player, item)
if not data then
return 0
end
return data.count or data.amount or 0
end
function RemovePlayerItem(player, item, amount)
if GetPlayerItemCount(player, item) < amount then
return false
end
local xPlayer = ESX.GetPlayerFromId(player)
xPlayer.removeInventoryItem(item, amount or 1)
return true
end
function AddPlayerItem(player, item, amount)
local xPlayer = ESX.GetPlayerFromId(tonumber(player))
-- Support for old esx which didn't use weight for inventory size but rather item limit per item type
if Config.esxSettings.oldEsx then
local esxItem = xPlayer.getInventoryItem(item)
if esxItem.limit == -1 or (esxItem.count + amount) <= esxItem.limit then
xPlayer.addInventoryItem(item, amount or 1)
return true
else
return false
end
else
if xPlayer.canCarryItem(item, amount or 1) then
xPlayer.addInventoryItem(item, amount or 1)
return true
else
return false
end
end
end
end

View file

@ -0,0 +1,35 @@
if Config.oxInventory.enabled then
-- Usable items
-- Export used for ox_inventory
exports('UseTowRope', function(event, item, inventory)
if event == 'usingItem' then
local player = inventory.id
TriggerClientEvent('kq_towing:client:startRope', player, false, true)
return true
end
end)
exports('UseWinch', function(event, item, inventory)
if event == 'usingItem' then
local player = inventory.id
TriggerClientEvent('kq_towing:client:startRope', player, true, true)
return true
end
end)
function IsPlayerJobWhitelisted(player, jobs)
return true
end
function AddPlayerItem(player, item, amount, meta)
local success, response = exports['ox_inventory']:AddItem(player, item, amount or 1, meta)
return success
end
function RemovePlayerItem(player, item, amount)
local success, response = exports['ox_inventory']:RemoveItem(player, item, amount or 1)
return success
end
end

View file

@ -0,0 +1,46 @@
if Config.qbSettings.enabled then
if Config.qbSettings.useNewQBExport then
QBCore = exports['qb-core']:GetCoreObject()
end
QBCore.Functions.CreateUseableItem(Config.items.towingRope, function(source)
if Config.jobWhitelist.towing.enabled then
if not IsPlayerJobWhitelisted(source, Config.jobWhitelist.towing.jobs) then
return TriggerClientEvent('kq_towing:client:notify', source, L('~r~You may not use this item'))
end
end
TriggerClientEvent('kq_towing:client:startRope', source, false, true)
end)
QBCore.Functions.CreateUseableItem(Config.items.winch, function(source)
if Config.jobWhitelist.winch.enabled then
if not IsPlayerJobWhitelisted(source, Config.jobWhitelist.winch.jobs) then
return TriggerClientEvent('kq_towing:client:notify', source, L('~r~You may not use this item'))
end
end
TriggerClientEvent('kq_towing:client:startRope', source, true, true)
end)
function IsPlayerJobWhitelisted(player, jobs)
local xPlayer = QBCore.Functions.GetPlayer(player)
if not xPlayer then
return false
end
local job = xPlayer.PlayerData.job
return Contains(jobs, job.name)
end
function RemovePlayerItem(player, item, amount)
local xPlayer = QBCore.Functions.GetPlayer(tonumber(player))
return xPlayer.Functions.RemoveItem(item, amount or 1)
end
function AddPlayerItem(player, item, amount)
local xPlayer = QBCore.Functions.GetPlayer(tonumber(player))
return xPlayer.Functions.AddItem(item, amount or 1)
end
end

Binary file not shown.