Skip to content

glue: resource for attaching players (and/or) vehicles to a vehicle #657

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions [gameplay]/glue/config/ShVehicleAttachConfig.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
-- #######################################
-- ## Project: Glue ##
-- ## Author: MTA contributors ##
-- ## Version: 1.3.1 ##
-- #######################################

IS_SERVER = (not triggerServerEvent) -- do not touch — constant; helper bool which checks whether it's a server or client environment

GLUE_WEAPON_SLOTS = {} -- do not touch — constant; used to verify whether passed weapon slot is in valid range (0-12), this is used to restore currently held weapon, because MTA resets weapon slot on attach
GLUE_CLIENT_ATTACH_DATA_SIZE = 6 -- do not touch, unless you modify data sent from client via triggerServerEvent (onServerVehicleAttachElement)
GLUE_ELEMENT_TYPES_AND_EVENTS = { -- do not touch — constant; controls which events would be added for glue logic based on allowed element type
["player"] = "onPlayerWasted",
["vehicle"] = "onVehicleExplode",
}

GLUE_ALLOWED_ELEMENTS = {"player", "vehicle"} -- elements which could be attached to vehicle (supported: "player", "vehicle")
GLUE_VEHICLE_TYPES = { -- only relevant if GLUE_ALLOWED_ELEMENTS contains "vehicle", specifies which vehicle types are allowed to glue
"Automobile",
--"Plane",
"Bike",
"Helicopter",
--"Boat",
"Train",
"Trailer",
"BMX",
"Monster Truck",
"Quad",
}

GLUE_VEHICLE_WHITELIST = { -- only relevant if GLUE_ALLOWED_ELEMENTS contains "vehicle", ignores GLUE_VEHICLE_TYPES; specifies which vehicle models are allowed to glue
500, -- mesa
411, -- infernus
443, -- packer
487, -- maverick
}

GLUE_ATTACH_OVER_VEHICLE = false -- if true, vehicles will attach over the top of target vehicle. if false, vehicles will attach but will maintain original position (seamless, precise glue'ing)
GLUE_DETACH_ON_VEHICLE_EXPLOSION = true -- specifies whether attached elements would be automatically detached, when attachedTo vehicle explodes
GLUE_ATTACH_ON_TOP_OFFSETS = {0, 0, 1.5} -- only relevant if GLUE_ATTACH_OVER_VEHICLE is set to true, specifies static position for attaching vehicle over vehicle
GLUE_ATTACH_VEHICLE_MAX_DISTANCE = 5 -- specifies maximum distance for nearby vehicle to be glued (also serves anti-cheat purpose, so only nearby vehicle could be attached)
GLUE_ATTACH_PLAYER_MAX_DISTANCE = 10 -- ditto

GLUE_PREVENT_CONTROLS = false -- prevent players from shooting their guns while attached to vehicle
GLUE_PREVENT_CONTROLS_LIST = {"fire", "action"} -- only relevant GLUE_PREVENT_CONTROLS is set to true, specifies which controls will be toggled on/off

GLUE_SYNC_CORRECTION = true -- whether attached player positions should be sanity corrected by server, this exists to prevents positional desyncs (e.g: during vehicle teleporting on long distances), which causes player to behave like a ghost (roam freely around SA, while still appearing glued to vehicle for other players)
GLUE_SYNC_CORRECTION_INTERVAL = 3500 -- only relevant if GLUE_SYNC_CORRECTION is set to true, how often glued player position should be corrected, do not set it too low, otherwise you will face weapon aiming interruption (this was constant issue when this variable was set to 1000 before)

GLUE_MESSAGE_PREFIX = "[Glue]:" -- shown in all glue messages
GLUE_MESSAGE_PREFIX_COLOR = "#c68ff8" -- color used by prefix
GLUE_MESSAGE_HIGHLIGHT_COLOR = "#c68ff8" -- color used in message highlights
GLUE_SHOW_ONE_TIME_HINT = true -- whether player should receive one-time (till resource restart) hint, regarding glue keybindings and settings, upon entering a vehicle

GLUE_ALLOW_ATTACH_TOGGLING = true -- should players be able to control attach lock on their vehicle (as a driver)
GLUE_ALLOW_DETACHING_ELEMENTS = true -- should players be able to detach already attached elements (as a driver)

GLUE_ATTACH_DETACH_KEY = "X" -- used to attach/detach yourself/vehicle
GLUE_ATTACH_TOGGLE_KEY = "C" -- only relevant if GLUE_ALLOW_ATTACH_TOGGLING is set to true; specifies whether players can disable attaching to vehicle which are driver of
GLUE_DETACH_ELEMENTS_KEY = "B" -- only relevant if GLUE_ALLOW_DETACHING_ELEMENTS is set to true; controls whether vehicle driver is able to detach elements currently attached to vehicle

GLUE_ATTACH_DETACH_DELAY = 300 -- how often player can attach/detach yourself/vehicle
GLUE_ATTACH_TOGGLE_DELAY = 300 -- only relevant if GLUE_ALLOW_ATTACH_TOGGLING is set to true; how often player can toggle vehicle attach lock
GLUE_DETACH_ELEMENTS_DELAY = 1000 -- only relevant if GLUE_ALLOW_DETACHING_ELEMENTS is set to true; how often player can detach all currently attached elements

do
local vehicleModelsWhitelist = {}
local vehicleTypesWhitelist = {}

for vehicleModelID = 1, #GLUE_VEHICLE_WHITELIST do
local vehicleModel = GLUE_VEHICLE_WHITELIST[vehicleModelID]

vehicleModelsWhitelist[vehicleModel] = true
end

for vehicleTypeID = 1, #GLUE_VEHICLE_TYPES do
local vehicleType = GLUE_VEHICLE_TYPES[vehicleTypeID]

vehicleTypesWhitelist[vehicleType] = true
end

GLUE_VEHICLE_WHITELIST = vehicleModelsWhitelist
GLUE_VEHICLE_TYPES = vehicleTypesWhitelist

local weaponSlotMin = 0
local weaponSlotMax = 12

for weaponSlotID = weaponSlotMin, weaponSlotMax do
GLUE_WEAPON_SLOTS[weaponSlotID] = true
end
end
218 changes: 218 additions & 0 deletions [gameplay]/glue/logic/CVehicleAttach.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
-- #######################################
-- ## Project: Glue ##
-- ## Author: MTA contributors ##
-- ## Version: 1.3.1 ##
-- #######################################

local glueHintsDisplayed = false

local function handleGlueAttachAndDetach()
local playerVehicle = getPedOccupiedVehicle(localPlayer)

if (playerVehicle) then
local playerVehicleToDetach = playerVehicle
local playerVehicleType = getVehicleType(playerVehicle)
local playerVehicleHelicopter = (playerVehicleType == "Helicopter")

if (playerVehicleHelicopter) then
local playerHelicopterAttachedVehicle = getAttachedVehicle(playerVehicle)

if (playerHelicopterAttachedVehicle) then
playerVehicleToDetach = playerHelicopterAttachedVehicle
end
end

if (playerVehicleToDetach) then
local playerVehicleCanDetach = canPlayerDetachElementFromVehicle(localPlayer, playerVehicleToDetach)

if (playerVehicleCanDetach) then
triggerServerEvent("onServerVehicleDetachElement", localPlayer, playerVehicleToDetach)

return true
end
end

local vehicleNearby = getNearestVehicleFromVehicle(playerVehicle)

if (not vehicleNearby) then
return false
end

local playerVehicleAttach = (playerVehicleHelicopter and vehicleNearby or playerVehicle)
local playerVehicleAttachTo = (playerVehicleHelicopter and playerVehicle or vehicleNearby)
local playerCanAttachVehicleToVehicle = canPlayerAttachElementToVehicle(localPlayer, playerVehicleAttach, playerVehicleAttachTo)

if (not playerCanAttachVehicleToVehicle) then
return false
end

local vehicleAttachX, vehicleAttachY, vehicleAttachZ, vehicleAttachRX, vehicleAttachRY, vehicleAttachRZ = getVehicleAttachData(playerVehicleAttach, playerVehicleAttachTo)

if (playerVehicleHelicopter) then
local helicopterAttachX, helicopterAttachY, helicopterAttachZ = 0, 0, -1.5
local helicopterAttachRX, helicopterAttachRY, helicopterAttachRZ = 0, 0, 0

vehicleAttachX, vehicleAttachY, vehicleAttachZ = helicopterAttachX, helicopterAttachY, helicopterAttachZ
vehicleAttachRX, vehicleAttachRY, vehicleAttachRZ = helicopterAttachRX, helicopterAttachRY, helicopterAttachRZ
end

local vehicleAttachData = {vehicleAttachX, vehicleAttachY, vehicleAttachZ, vehicleAttachRX, vehicleAttachRY, vehicleAttachRZ}

triggerServerEvent("onServerVehicleAttachElement", localPlayer, playerVehicleAttach, playerVehicleAttachTo, vehicleAttachData)

return false
end

if (not playerVehicle) then
local playerAttachedTo = getElementAttachedTo(localPlayer)

if (playerAttachedTo) then
local playerCanDetach = canPlayerDetachElementFromVehicle(localPlayer, localPlayer)

if (not playerCanDetach) then
return false
end

triggerServerEvent("onServerVehicleDetachElement", localPlayer, localPlayer)

return true
end

local playerContactElement = getPedContactElement(localPlayer)
local playerContactVehicle = isElementType(playerContactElement, "vehicle")

if (not playerContactVehicle) then
return false
end

local playerCanAttach = canPlayerAttachElementToVehicle(localPlayer, localPlayer, playerContactElement)

if (not playerCanAttach) then
return false
end

local playerX, playerY, playerZ = getElementPosition(localPlayer)
local playerVehicleMatrix = getElementMatrix(playerContactElement)
local playerPosition = {playerX, playerY, playerZ}
local playerAttachX, playerAttachY, playerAttachZ = getOffsetFromXYZ(playerVehicleMatrix, playerPosition)
local playerAttachRX, playerAttachRY, playerAttachRZ = 0, 0, 0
local playerAttachData = {playerAttachX, playerAttachY, playerAttachZ, playerAttachRX, playerAttachRY, playerAttachRZ}
local playerWeaponSlot = getPedWeaponSlot(localPlayer)

triggerServerEvent("onServerVehicleAttachElement", localPlayer, localPlayer, playerContactElement, playerAttachData, playerWeaponSlot)
end
end
bindKey(GLUE_ATTACH_DETACH_KEY, "down", handleGlueAttachAndDetach)

local function handleGlueAttachLock()
local canToggleVehicleAttachLock = canPlayerToggleVehicleAttachLock(localPlayer)

if (canToggleVehicleAttachLock) then
triggerServerEvent("onServerVehicleToggleAttachLock", localPlayer)
end
end
if (GLUE_ALLOW_ATTACH_TOGGLING) then
bindKey(GLUE_ATTACH_TOGGLE_KEY, "down", handleGlueAttachLock)
end

local function handleGlueDetachElements()
local canDetachVehicleElements = canPlayerDetachElementsFromVehicle(localPlayer)

if (canDetachVehicleElements) then
triggerServerEvent("onServerVehicleDetachElements", localPlayer)
end
end
if (GLUE_ALLOW_DETACHING_ELEMENTS) then
bindKey(GLUE_DETACH_ELEMENTS_KEY, "down", handleGlueDetachElements)
end

local function toggleCombatControls(forcedState)
for controlID = 1, #GLUE_PREVENT_CONTROLS_LIST do
local controlName = GLUE_PREVENT_CONTROLS_LIST[controlID]
local controlState = isControlEnabled(controlName)
local controlStateNeedsUpdate = (controlState ~= forcedState)

if (controlStateNeedsUpdate) then
toggleControl(controlName, forcedState)
end
end

return true
end

local function restoreCombatControlsOnEvent(vehicleElement)
local playerAttachedTo = getElementAttachedTo(localPlayer)

if (not playerAttachedTo) then
return false
end

if (vehicleElement) then
local playerAttachedElementMatching = (playerAttachedTo == vehicleElement)

if (not playerAttachedElementMatching) then
return false
end
end

toggleCombatControls(true)

return true
end

local function restoreCombatControlsOnVehicleDestroy()
restoreCombatControlsOnEvent(source)
end
if (GLUE_PREVENT_CONTROLS) then
addEventHandler("onClientElementDestroy", root, restoreCombatControlsOnVehicleDestroy)
end

local function restoreCombatControlsOnResourceStop()
restoreCombatControlsOnEvent()
end
if (GLUE_PREVENT_CONTROLS) then
addEventHandler("onClientResourceStop", root, restoreCombatControlsOnResourceStop)
end

local function displayGlueHintsOnVehicleEnter()
if (glueHintsDisplayed) then
return false
end

local glueHintCanAttachVehicle = findInTable(GLUE_ALLOWED_ELEMENTS, "vehicle")
local glueHintCanAttachPlayer = findInTable(GLUE_ALLOWED_ELEMENTS, "player")

if (not glueHintCanAttachVehicle and not glueHintCanAttachPlayer) then
return false
end

local glueHintAttachVehicles = glueHintCanAttachVehicle and GLUE_MESSAGE_HIGHLIGHT_COLOR.."current/nearby vehicle#ffffff" or ""
local glueHintAttachYourself = glueHintCanAttachPlayer and GLUE_MESSAGE_HIGHLIGHT_COLOR.."yourself#ffffff"..(glueHintCanAttachVehicle and " or " or "") or ""
local glueHintAttachLock = (GLUE_ALLOW_ATTACH_TOGGLING and "#ffffff'"..GLUE_MESSAGE_HIGHLIGHT_COLOR..GLUE_ATTACH_TOGGLE_KEY.."#ffffff' is used to disable/enable attaching to your vehicle. " or "")
local glueHintDetachElements = (GLUE_ALLOW_DETACHING_ELEMENTS and "#ffffff'"..GLUE_MESSAGE_HIGHLIGHT_COLOR..GLUE_DETACH_ELEMENTS_KEY.."#ffffff' to detach all currently attached elements." or "")

local glueHintA = "Press '"..GLUE_MESSAGE_HIGHLIGHT_COLOR..GLUE_ATTACH_DETACH_KEY.."#ffffff' to attach "..glueHintAttachYourself..glueHintAttachVehicles.." to (nearby/current) vehicle."
local glueHintB = glueHintAttachLock
local glueHintC = glueHintDetachElements

sendGlueMessage(glueHintA)
sendGlueMessage(glueHintB, nil, "*")
sendGlueMessage(glueHintC, nil, "*")

glueHintsDisplayed = true
end
if (GLUE_SHOW_ONE_TIME_HINT) then
addEventHandler("onClientPlayerVehicleEnter", localPlayer, displayGlueHintsOnVehicleEnter)
end

function onClientAttachStateChanged(playerAttached)
if (not GLUE_PREVENT_CONTROLS) then
return false
end

local toggleControlState = (not playerAttached)

toggleCombatControls(toggleControlState)
end
addEvent("onClientAttachStateChanged", true)
addEventHandler("onClientAttachStateChanged", localPlayer, onClientAttachStateChanged)
Loading