local createdRope = nil local ropeLength = 10.0 local minRopeLength = 1.0 local lengthTick = 0.02 local enteredCloseVehicle = false local closestTrailer = nil local closestBoat = nil local hasTakenRope = false local hookedToBoat = false local controlRope = false local colObj = nil local boatOnTrailer = false local function getTrailerOffset(trailer) local model = GetEntityModel(trailer) if model == `yftrailer` then return vector3(0.0, 1.5, 0.3) -- Angepasste Werte für yftrailer else return vector3(0.0, 1.8, 0.0) -- Original boattrailer Werte end end local function getBoatAttachmentOffset(trailer) local model = GetEntityModel(trailer) if model == `yftrailer` then return vector3(0.0, -1.0, 0.25) -- Angepasste Werte für yftrailer else return vector3(0.0, -1.02, 0.3) -- Original boattrailer Werte end end local function isSupportedBoat(closest) for _, model in pairs(Config.SupportedBoats) do if GetEntityModel(closest) == model then return true end end end local function isTrailer(vehicle) local model = GetEntityModel(vehicle) return model == `boattrailer` or model == `yftrailer` end local function getClosestVehicle(coords, maxDistance) local vehicles = GetGamePool('CVehicle') local closestVehicle, closestCoords maxDistance = maxDistance or 2.0 for i = 1, #vehicles do local vehicle = vehicles[i] local vehicleCoords = GetEntityCoords(vehicle) local distance = #(coords - vehicleCoords) if distance < maxDistance then maxDistance = distance closestVehicle = vehicle closestCoords = vehicleCoords end end return closestVehicle, closestCoords end local function notify(text) SetNotificationTextEntry("STRING") AddTextComponentString(text) DrawNotification(true, false) end CreateThread(function() while true do Wait(1000) local playerPed = PlayerPedId() local playerCoords = GetEntityCoords(playerPed) local closestVehicle, closestCoords = getClosestVehicle(playerCoords, 3.0) if closestVehicle ~= nil and #(playerCoords - closestCoords) < 3.0 then if not enteredCloseVehicle then local isBoat = isSupportedBoat(closestVehicle) if isTrailer(closestVehicle) then closestTrailer = closestVehicle elseif isBoat then closestBoat = closestVehicle end end enteredCloseVehicle = true else enteredCloseVehicle = false end end end) CreateThread(function() if GetResourceState('qb-target') == 'started' then exports['qb-target']:AddGlobalVehicle({ options = { { type = "client", event = "re_boat_winch:client:takeRope", icon = 'fas fa-clipboard', label = "Take the rope", canInteract = function(entity) if closestTrailer ~= entity or not isTrailer(entity) then return false end return not boatOnTrailer and not hookedToBoat and not hasTakenRope end }, { type = "client", event = "re_boat_winch:client:returnRope", icon = 'fas fa-clipboard', label = "Return the rope", canInteract = function(entity) if closestTrailer ~= entity or not isTrailer(entity) then return false end return hasTakenRope and not hookedToBoat and not boatOnTrailer end }, { type = "client", event = "re_boat_winch:client:controlRope", icon = 'fas fa-clipboard', label = "Control the rope", canInteract = function(entity) if closestTrailer ~= entity or not isTrailer(entity) then return false end return not hasTakenRope and hookedToBoat end }, { type = "client", event = "re_boat_winch:client:detachBoat", icon = 'fas fa-clipboard', label = "Detach boat from trailer", canInteract = function(entity) if closestTrailer ~= entity or not isTrailer(entity) then return false end return boatOnTrailer end }, { type = "client", event = "re_boat_winch:client:hookUpRope", icon = 'fas fa-clipboard', label = "Hook up the rope", canInteract = function(entity) if closestBoat ~= entity or not isSupportedBoat(entity) then return false end return hasTakenRope and not hookedToBoat end }, { type = "client", event = "re_boat_winch:client:unHookRope", icon = 'fas fa-clipboard', label = "Unhook the rope", canInteract = function(entity) if closestBoat ~= entity or not isSupportedBoat(entity) then return false end return not hasTakenRope and hookedToBoat and createdRope end } }, distance = 2.5 }) else exports.ox_target:addGlobalVehicle({ { event = "re_boat_winch:client:takeRope", icon = 'fas fa-clipboard', label = "Take the rope", name = "re_boat_winch:client:takeRope", distance = 2.5, canInteract = function(entity) if closestTrailer ~= entity or not isTrailer(entity) then return false end return not boatOnTrailer and not hookedToBoat and not hasTakenRope end }, { event = "re_boat_winch:client:returnRope", icon = 'fas fa-clipboard', label = "Return the rope", name = "re_boat_winch:client:returnRope", distance = 2.5, canInteract = function(entity) if closestTrailer ~= entity or not isTrailer(entity) then return false end return hasTakenRope and not hookedToBoat and not boatOnTrailer end }, { event = "re_boat_winch:client:controlRope", icon = 'fas fa-clipboard', label = "Control the rope", name = "re_boat_winch:client:controlRope", distance = 2.5, canInteract = function(entity) if closestTrailer ~= entity or not isTrailer(entity) then return false end return not hasTakenRope and hookedToBoat end }, { event = "re_boat_winch:client:detachBoat", icon = 'fas fa-clipboard', label = "Detach boat from trailer", name = "re_boat_winch:client:detachBoat", distance = 2.5, canInteract = function(entity) if closestTrailer ~= entity or not isTrailer(entity) then return false end return boatOnTrailer end }, { event = "re_boat_winch:client:hookUpRope", icon = 'fas fa-clipboard', label = "Hook up the rope", name = "re_boat_winch:client:hookUpRope", distance = 2.5, canInteract = function(entity) if closestBoat ~= entity or not isSupportedBoat(entity) then return false end return hasTakenRope and not hookedToBoat end }, { event = "re_boat_winch:client:unHookRope", icon = 'fas fa-clipboard', label = "Unhook the rope", name = "re_boat_winch:client:unHookRope", distance = 2.5, canInteract = function(entity) if closestBoat ~= entity or not isSupportedBoat(entity) then return false end return not hasTakenRope and hookedToBoat and createdRope end } }) end end) AddEventHandler('onResourceStop', function(resourceName) if resourceName ~= "re_boat_winch" then return end if GetResourceState('qb-target') == 'started' then exports['qb-target']:RemoveGlobalVehicle("Nimm das Seil") exports['qb-target']:RemoveGlobalVehicle("Häng das SEil zurück") exports['qb-target']:RemoveGlobalVehicle("Winde kontrollieren") exports['qb-target']:RemoveGlobalVehicle("Boot vom Anhänger lösen") exports['qb-target']:RemoveGlobalVehicle("Seil einhängen") exports['qb-target']:RemoveGlobalVehicle("Seil aushängen") else exports.ox_target:removeGlobalVehicle("re_boat_winch:client:takeRope") exports.ox_target:removeGlobalVehicle("re_boat_winch:client:returnRope") exports.ox_target:removeGlobalVehicle("re_boat_winch:client:controlRope") exports.ox_target:removeGlobalVehicle("re_boat_winch:client:detachBoat") exports.ox_target:removeGlobalVehicle("re_boat_winch:client:hookUpRope") exports.ox_target:removeGlobalVehicle("re_boat_winch:client:unHookRope") end end) local function createRope(obj1, obj2, obj1Coords, obj2Coords, lenght) DeleteRope(createdRope) RopeLoadTextures() while not RopeAreTexturesLoaded() do Wait(0) RopeLoadTextures() end RopeLoadTextures() createdRope = AddRope(obj1Coords.x, obj1Coords.y, obj1Coords.z, 0.0, 0.0, 0.0, lenght, 1, Config.MaxRopeLength, 1.0, 1.0, false, true, false, 5.0, false, 0) while not createdRope do Wait(0) end ActivatePhysics(createdRope) Wait(50) AttachEntitiesToRope(createdRope, obj1, obj2, obj1Coords.x, obj1Coords.y, obj1Coords.z, obj2Coords.x, obj2Coords.y, obj2Coords.z, lenght, false, false, nil, nil) end RegisterNetEvent('re_boat_winch:client:unHookRope', function() hookedToBoat = false controlRope = false hasTakenRope = true notify("Du hast das Seil ausgehakt") local playerPed = PlayerPedId() local trailerOffset = getTrailerOffset(closestTrailer) local trailerCoords = GetOffsetFromEntityInWorldCoords(closestTrailer, trailerOffset.x, trailerOffset.y, trailerOffset.z) local boneIndex = GetPedBoneIndex(playerPed, 0x49D9) ropeLength = 5.0 colObj = CreateObject(`xm3_prop_xm3_hook_01a`, 0, 0, 0, true, true, true) AttachEntityToEntity(colObj, playerPed, boneIndex, 0.11, 0.02, 0.02, -80.0, -90.0, 15.0, true, true, false, true, 1, true) local objCoords = GetEntityCoords(colObj) createRope(closestTrailer, colObj, trailerCoords, objCoords, ropeLength) end) RegisterNetEvent('re_boat_winch:client:returnRope', function() hasTakenRope = false DeleteEntity(colObj) DeleteRope(createdRope) end) RegisterNetEvent('re_boat_winch:client:detachBoat', function() boatOnTrailer = false DetachEntity(closestBoat, true, true) local trailerOffset = getTrailerOffset(closestTrailer) local trailerCoords = GetOffsetFromEntityInWorldCoords(closestTrailer, 0.0, -8.0, 0.0) SetEntityCoords(closestBoat, trailerCoords.x, trailerCoords.y, trailerCoords.z) end) RegisterNetEvent('re_boat_winch:client:takeRope', function() hasTakenRope = true FreezeEntityPosition(closestTrailer, true) SetEntityInvincible(closestTrailer, true) local playerPed = PlayerPedId() local playerCoords = GetEntityCoords(playerPed) local trailerOffset = getTrailerOffset(closestTrailer) local trailerCoords = GetOffsetFromEntityInWorldCoords(closestTrailer, trailerOffset.x, trailerOffset.y, trailerOffset.z) local coordsDiff = #(trailerCoords - playerCoords) local boneIndex = GetPedBoneIndex(playerPed, 0x49D9) ropeLength = coordsDiff colObj = CreateObject(`xm3_prop_xm3_hook_01a`, 0, 0, 0, true, true, true) AttachEntityToEntity(colObj, playerPed, boneIndex, 0.11, 0.02, 0.02, -80.0, -90.0, 15.0, true, true, false, true, 1, true) local objCoords = GetEntityCoords(colObj) createRope(closestTrailer, colObj, trailerCoords, objCoords, ropeLength) end) RegisterNetEvent('re_boat_winch:client:hookUpRope', function() hookedToBoat = true hasTakenRope = false notify("Du hast den Haken genommen") local trailerOffset = getTrailerOffset(closestTrailer) local trailerCoords = GetOffsetFromEntityInWorldCoords(closestTrailer, trailerOffset.x, trailerOffset.y, trailerOffset.z) local boatCoords = GetOffsetFromEntityInWorldCoords(closestBoat, 0.0, 3.9, 0.9) local coordsDiff = #(trailerCoords - boatCoords) ropeLength = coordsDiff SetEntityInvincible(closestBoat, true) DeleteEntity(colObj) createRope(closestTrailer, closestBoat, trailerCoords, boatCoords, ropeLength) end) RegisterNetEvent('re_boat_winch:client:controlRope', function() controlRope = true notify("Du kontrollierst die Winde") end) local function attachBoatToTrailer() if not DoesEntityExist(closestTrailer) or not DoesEntityExist(closestBoat) then return end local attachOffset = getBoatAttachmentOffset(closestTrailer) AttachEntityToEntity(closestBoat, closestTrailer, 0, attachOffset.x, attachOffset.y, attachOffset.z, 0.0, 0.0, 0.0, false, false, false, false, 2, true) DeleteRope(createdRope) FreezeEntityPosition(closestTrailer, false) SetEntityInvincible(closestTrailer, false) SetEntityInvincible(closestBoat, false) hasTakenRope = false hookedToBoat = false controlRope = false createdRope = nil colObj = nil boatOnTrailer = true end CreateThread(function() while true do Wait(createdRope and controlRope and 0 or 1000) if createdRope and controlRope then if ropeLength == 1.0 then attachBoatToTrailer() ropeLength = 10.0 end if IsControlPressed(0, 172) then ropeLength = ropeLength + lengthTick if ropeLength > Config.MaxRopeLength then ropeLength = Config.MaxRopeLength end StopRopeWinding(createdRope) StartRopeUnwindingFront(createdRope) RopeForceLength(createdRope, ropeLength) elseif IsControlJustReleased(0, 172) then StopRopeUnwindingFront(createdRope) StopRopeWinding(createdRope) RopeConvertToSimple(createdRope) elseif IsControlPressed(0, 173) then ropeLength = ropeLength - lengthTick if ropeLength < minRopeLength then ropeLength = minRopeLength end StopRopeUnwindingFront(createdRope) StartRopeWinding(createdRope) RopeForceLength(createdRope, ropeLength) elseif IsControlJustReleased(0, 173) then StopRopeUnwindingFront(createdRope) StopRopeWinding(createdRope) RopeConvertToSimple(createdRope) end end if createdRope and hasTakenRope then local playerPed = PlayerPedId() local playerCoords = GetEntityCoords(playerPed) local trailerOffset = getTrailerOffset(closestTrailer) local trailerCoords = GetOffsetFromEntityInWorldCoords(closestTrailer, trailerOffset.x, trailerOffset.y, trailerOffset.z) local coordsDiff = #(trailerCoords - playerCoords) if coordsDiff > Config.MaxRopeLength then notify("Du bist zu weit vom Anhänger weg") DeleteRope(createdRope) DeleteEntity(colObj) FreezeEntityPosition(closestTrailer, false) SetEntityInvincible(closestTrailer, false) SetEntityInvincible(closestBoat, false) closestTrailer = nil closestBoat = nil hasTakenRope = false hookedToBoat = false controlRope = false colObj = nil boatOnTrailer = false end end end end)