mirror of
https://github.com/jimathy/jim_bridge.git
synced 2026-08-19 06:46:04 +01:00
Enhance drawtext feature
This commit is contained in:
@@ -20,6 +20,8 @@
|
|||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
-- Utility Data & Tables
|
-- Utility Data & Tables
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
|
---
|
||||||
|
local KEY_TABLE = { 38, 29, 47, 23, 45, }
|
||||||
|
|
||||||
-- Mapping of key codes to human-readable key names.
|
-- Mapping of key codes to human-readable key names.
|
||||||
local Keys = {
|
local Keys = {
|
||||||
@@ -77,13 +79,12 @@ local circleTargets = {} -- For circular zone targets.
|
|||||||
function createEntityTarget(entity, opts, dist)
|
function createEntityTarget(entity, opts, dist)
|
||||||
-- Store the target entity for later cleanup.
|
-- Store the target entity for later cleanup.
|
||||||
targetEntities[#targetEntities + 1] = entity
|
targetEntities[#targetEntities + 1] = entity
|
||||||
local entityCoords = GetEntityCoords(entity)
|
|
||||||
|
|
||||||
-- Fallback: Use DrawText3D if targeting systems are disabled or unavailable.
|
-- Fallback: Use DrawText3D if targeting systems are disabled or unavailable.
|
||||||
if Config.System.DontUseTarget or (not isStarted(OXTargetExport) and not isStarted(QBTargetExport)) then
|
if Config.System.DontUseTarget or (not isStarted(OXTargetExport) and not isStarted(QBTargetExport)) then
|
||||||
|
local entityCoords = GetEntityCoords(entity)
|
||||||
debugPrint("^6Bridge^7: ^2Creating new ^3Entity^2 target with DrawText for entity ^7"..entity)
|
debugPrint("^6Bridge^7: ^2Creating new ^3Entity^2 target with DrawText for entity ^7"..entity)
|
||||||
local existingTarget = nil
|
local existingTarget = nil
|
||||||
-- Check if a target already exists at similar coordinates.
|
|
||||||
for _, target in pairs(TextTargets) do
|
for _, target in pairs(TextTargets) do
|
||||||
if #(target.coords - entityCoords) < 0.01 then
|
if #(target.coords - entityCoords) < 0.01 then
|
||||||
existingTarget = target
|
existingTarget = target
|
||||||
@@ -91,23 +92,27 @@ function createEntityTarget(entity, opts, dist)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local keyTable = { 38, 29, 303, 45, 46, 47, 48 } -- Predefined key codes for options.
|
|
||||||
if existingTarget then
|
if existingTarget then
|
||||||
-- Append new options to the existing target.
|
|
||||||
for i = 1, #opts do
|
for i = 1, #opts do
|
||||||
local key = keyTable[#existingTarget.options + i]
|
local key = KEY_TABLE[#existingTarget.options + i]
|
||||||
opts[i].key = key
|
opts[i].key = key
|
||||||
existingTarget.buttontext[#existingTarget.buttontext + 1] = " ~b~[~w~"..Keys[key].."~b~] ~w~"..opts[i].label
|
existingTarget.buttontext[#existingTarget.buttontext + 1] = " ~b~[~w~" .. Keys[key] .. "~b~] ~w~" .. opts[i].label
|
||||||
existingTarget.options[#existingTarget.options + 1] = opts[i]
|
existingTarget.options[#existingTarget.options + 1] = opts[i]
|
||||||
end
|
end
|
||||||
|
updateCachedText(existingTarget)
|
||||||
else
|
else
|
||||||
-- Create a new target entry.
|
|
||||||
local tempText = {}
|
local tempText = {}
|
||||||
for i = 1, #opts do
|
for i = 1, #opts do
|
||||||
opts[i].key = keyTable[i]
|
opts[i].key = KEY_TABLE[i]
|
||||||
tempText[#tempText + 1] = " ~b~[~w~"..Keys[opts[i].key].."~b~] ~w~"..opts[i].label
|
tempText[#tempText + 1] = " ~b~[~w~" .. Keys[opts[i].key] .. "~b~] ~w~" .. opts[i].label
|
||||||
end
|
end
|
||||||
TextTargets[entity] = { coords = vec3(entityCoords.x, entityCoords.y, entityCoords.z), buttontext = tempText, options = opts, dist = dist }
|
TextTargets[entity] = {
|
||||||
|
coords = vec3(entityCoords.x, entityCoords.y, entityCoords.z),
|
||||||
|
buttontext = tempText,
|
||||||
|
options = opts,
|
||||||
|
dist = dist,
|
||||||
|
text = table.concat(tempText, "\n")
|
||||||
|
}
|
||||||
end
|
end
|
||||||
elseif isStarted(OXTargetExport) then
|
elseif isStarted(OXTargetExport) then
|
||||||
debugPrint("^6Bridge^7: ^2Creating new ^3Entity ^2target with ^6"..OXTargetExport.." ^2for entity ^7"..entity)
|
debugPrint("^6Bridge^7: ^2Creating new ^3Entity ^2target with ^6"..OXTargetExport.." ^2for entity ^7"..entity)
|
||||||
@@ -195,21 +200,27 @@ function createBoxTarget(data, opts, dist)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local keyTable = { 38, 29, 303, 45, 46, 47, 48 }
|
|
||||||
if existingTarget then
|
if existingTarget then
|
||||||
for i = 1, #opts do
|
for i = 1, #opts do
|
||||||
local key = keyTable[#existingTarget.options + i]
|
local key = KEY_TABLE[#existingTarget.options + i]
|
||||||
opts[i].key = key
|
opts[i].key = key
|
||||||
existingTarget.buttontext[#existingTarget.buttontext + 1] = " ~b~[~w~"..Keys[key].."~b~] ~w~"..opts[i].label
|
existingTarget.buttontext[#existingTarget.buttontext + 1] = " ~b~[~w~" .. Keys[key] .. "~b~] ~w~" .. opts[i].label
|
||||||
existingTarget.options[#existingTarget.options + 1] = opts[i]
|
existingTarget.options[#existingTarget.options + 1] = opts[i]
|
||||||
end
|
end
|
||||||
|
updateCachedText(existingTarget)
|
||||||
else
|
else
|
||||||
local tempText = {}
|
local tempText = {}
|
||||||
for i = 1, #opts do
|
for i = 1, #opts do
|
||||||
opts[i].key = keyTable[i]
|
opts[i].key = KEY_TABLE[i]
|
||||||
tempText[#tempText + 1] = " ~b~[~w~"..Keys[opts[i].key].."~b~] ~w~"..opts[i].label
|
tempText[#tempText + 1] = " ~b~[~w~" .. Keys[opts[i].key] .. "~b~] ~w~" .. opts[i].label
|
||||||
end
|
end
|
||||||
TextTargets[data[1]] = { coords = data[2], buttontext = tempText, options = opts, dist = dist }
|
TextTargets[data[1]] = {
|
||||||
|
coords = data[2],
|
||||||
|
buttontext = tempText,
|
||||||
|
options = opts,
|
||||||
|
dist = dist,
|
||||||
|
text = table.concat(tempText, "\n")
|
||||||
|
}
|
||||||
end
|
end
|
||||||
return data[1]
|
return data[1]
|
||||||
elseif isStarted(OXTargetExport) then
|
elseif isStarted(OXTargetExport) then
|
||||||
@@ -295,21 +306,27 @@ function createCircleTarget(data, opts, dist)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local keyTable = { 38, 29, 303, 45, 46, 47, 48 }
|
|
||||||
if existingTarget then
|
if existingTarget then
|
||||||
for i = 1, #opts do
|
for i = 1, #opts do
|
||||||
local key = keyTable[#existingTarget.options + i]
|
local key = KEY_TABLE[#existingTarget.options + i]
|
||||||
opts[i].key = key
|
opts[i].key = key
|
||||||
existingTarget.buttontext[#existingTarget.buttontext + 1] = " ~b~[~w~"..Keys[key].."~b~] ~w~"..opts[i].label
|
existingTarget.buttontext[#existingTarget.buttontext + 1] = " ~b~[~w~" .. Keys[key] .. "~b~] ~w~" .. opts[i].label
|
||||||
existingTarget.options[#existingTarget.options + 1] = opts[i]
|
existingTarget.options[#existingTarget.options + 1] = opts[i]
|
||||||
end
|
end
|
||||||
|
updateCachedText(existingTarget)
|
||||||
else
|
else
|
||||||
local tempText = {}
|
local tempText = {}
|
||||||
for i = 1, #opts do
|
for i = 1, #opts do
|
||||||
opts[i].key = keyTable[i]
|
opts[i].key = KEY_TABLE[i]
|
||||||
tempText[#tempText + 1] = " ~b~[~w~"..Keys[opts[i].key].."~b~] ~w~"..opts[i].label
|
tempText[#tempText + 1] = " ~b~[~w~" .. Keys[opts[i].key] .. "~b~] ~w~" .. opts[i].label
|
||||||
end
|
end
|
||||||
TextTargets[data[1]] = { coords = data[2], buttontext = tempText, options = opts, dist = dist }
|
TextTargets[data[1]] = {
|
||||||
|
coords = data[2],
|
||||||
|
buttontext = tempText,
|
||||||
|
options = opts,
|
||||||
|
dist = dist,
|
||||||
|
text = table.concat(tempText, "\n")
|
||||||
|
}
|
||||||
end
|
end
|
||||||
return data[1]
|
return data[1]
|
||||||
elseif isStarted(OXTargetExport) then
|
elseif isStarted(OXTargetExport) then
|
||||||
@@ -371,7 +388,30 @@ end
|
|||||||
---```
|
---```
|
||||||
function createModelTarget(models, opts, dist)
|
function createModelTarget(models, opts, dist)
|
||||||
if Config.System.DontUseTarget or (not isStarted(OXTargetExport) and not isStarted(QBTargetExport)) then
|
if Config.System.DontUseTarget or (not isStarted(OXTargetExport) and not isStarted(QBTargetExport)) then
|
||||||
-- Fallback for model targets is not implemented.
|
if type(models) ~= "table" then
|
||||||
|
models = { models }
|
||||||
|
end
|
||||||
|
|
||||||
|
local tempText = {}
|
||||||
|
for i = 1, #opts do
|
||||||
|
opts[i].key = KEY_TABLE[i]
|
||||||
|
tempText[#tempText + 1] = " ~b~[~w~" .. Keys[opts[i].key] .. "~b~] ~w~" .. opts[i].label
|
||||||
|
end
|
||||||
|
|
||||||
|
local keyStr = ""
|
||||||
|
for i, m in ipairs(models) do
|
||||||
|
keyStr = keyStr .. tostring(m) .. (i < #models and "_" or "")
|
||||||
|
end
|
||||||
|
local targetKey = "model_" .. keyStr
|
||||||
|
|
||||||
|
TextTargets[targetKey] = {
|
||||||
|
models = models,
|
||||||
|
buttontext = tempText,
|
||||||
|
options = opts,
|
||||||
|
dist = dist,
|
||||||
|
coords = vec3(0, 0, 0),
|
||||||
|
text = table.concat(tempText, "\n")
|
||||||
|
}
|
||||||
elseif isStarted(OXTargetExport) then
|
elseif isStarted(OXTargetExport) then
|
||||||
debugPrint("^6Bridge^7: ^2Creating new ^3Model^2 target with ^6"..OXTargetExport)
|
debugPrint("^6Bridge^7: ^2Creating new ^3Model^2 target with ^6"..OXTargetExport)
|
||||||
local options = {}
|
local options = {}
|
||||||
@@ -465,60 +505,81 @@ end
|
|||||||
-- If no targeting system is detected and this is a client script, use DrawText3D for targets.
|
-- If no targeting system is detected and this is a client script, use DrawText3D for targets.
|
||||||
if (Config.System.DontUseTarget or (not isStarted(OXTargetExport) and not isStarted(QBTargetExport))) and not isServer() then
|
if (Config.System.DontUseTarget or (not isStarted(OXTargetExport) and not isStarted(QBTargetExport))) and not isServer() then
|
||||||
CreateThread(function()
|
CreateThread(function()
|
||||||
|
local wait = 1000
|
||||||
while true do
|
while true do
|
||||||
local pedCoords = GetEntityCoords(PlayerPedId())
|
local pedCoords = GetEntityCoords(PlayerPedId())
|
||||||
local camCoords = GetGameplayCamCoord()
|
local camCoords = GetGameplayCamCoord()
|
||||||
local camRotation = GetGameplayCamRot(2) -- Camera rotation (degrees)
|
local camRot = GetGameplayCamRot(2)
|
||||||
local camForwardVector = RotationToDirection(camRotation) -- Convert rotation to direction
|
local camForward = RotationToDirection(camRot)
|
||||||
|
local closestTarget, closestDist = nil, math.huge
|
||||||
local closestTarget = nil
|
local notificationShown = false
|
||||||
local closestDist = math.huge
|
local targetEntity = nil
|
||||||
|
-- Update model targets and determine the closest target.
|
||||||
-- Create a shallow copy of TextTargets
|
for _, target in pairs(TextTargets) do
|
||||||
local targetsCopy = {}
|
if target.models then
|
||||||
for k, target in pairs(TextTargets) do
|
for _, model in ipairs(target.models) do
|
||||||
targetsCopy[k] = target
|
local entity = GetClosestObjectOfType(pedCoords.x, pedCoords.y, pedCoords.z, target.dist, model, false, false, false)
|
||||||
|
if entity and entity ~= 0 then
|
||||||
|
target.coords = GetEntityCoords(entity)
|
||||||
|
targetEntity = entity
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Identify the closest target in front of the camera.
|
|
||||||
for _, target in pairs(targetsCopy) do
|
|
||||||
local dist = #(pedCoords - target.coords)
|
local dist = #(pedCoords - target.coords)
|
||||||
|
if dist <= target.dist then
|
||||||
local vecToTarget = target.coords - camCoords
|
local vecToTarget = target.coords - camCoords
|
||||||
local vecToTargetNormalized = normalizeVector(vecToTarget)
|
local normVec = normalizeVector(vecToTarget)
|
||||||
local dot = camForwardVector.x * vecToTargetNormalized.x +
|
local dot = camForward.x * normVec.x + camForward.y * normVec.y + camForward.z * normVec.z
|
||||||
camForwardVector.y * vecToTargetNormalized.y +
|
if dot > 0.5 and dist < closestDist then
|
||||||
camForwardVector.z * vecToTargetNormalized.z
|
|
||||||
local isFacingTarget = dot > 0.5 -- Threshold for facing target.
|
|
||||||
|
|
||||||
if dist <= target.dist and isFacingTarget then
|
|
||||||
if dist < closestDist then
|
|
||||||
closestDist = dist
|
closestDist = dist
|
||||||
closestTarget = target
|
closestTarget = target
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Render the DrawText3D targets and listen for key presses.
|
-- Render targets, listen for key presses and display the help notification.
|
||||||
for _, target in pairs(targetsCopy) do
|
for key, target in pairs(TextTargets) do
|
||||||
local isClosest = (target == closestTarget)
|
|
||||||
if #(pedCoords - target.coords) <= target.dist then
|
if #(pedCoords - target.coords) <= target.dist then
|
||||||
for i = 1, #target.options do
|
local isClosest = (target == closestTarget)
|
||||||
if IsControlJustPressed(0, target.options[i].key) and isClosest then
|
for i, opt in ipairs(target.options) do
|
||||||
if target.options[i].onSelect then target.options[i].onSelect() end
|
if IsControlJustPressed(0, opt.key) and isClosest then
|
||||||
if target.options[i].action then target.options[i].action() end
|
if opt.onSelect then opt.onSelect(targetEntity) end
|
||||||
end
|
if opt.action then opt.action(targetEntity) end
|
||||||
end
|
|
||||||
DrawText3D(vec3(target.coords.x, target.coords.y, target.coords.z + 0.7),
|
|
||||||
concatenateText(target.buttontext),
|
|
||||||
isClosest)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Wait(0)
|
notificationShown = true
|
||||||
|
ShowFloatingHelpNotification(vec3(target.coords.x, target.coords.y, target.coords.z + 0.7), target.text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If no notification was drawn this frame, clear help messages.
|
||||||
|
if notificationShown then
|
||||||
|
wait = 0
|
||||||
|
else
|
||||||
|
ClearAllHelpMessages()
|
||||||
|
wait = 1000
|
||||||
|
end
|
||||||
|
|
||||||
|
Wait(wait)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function ShowFloatingHelpNotification(coord, text, highlight)
|
||||||
|
AddTextEntry("FloatingText", text)
|
||||||
|
SetFloatingHelpTextWorldPosition(1, coord.x, coord.y, coord.z)
|
||||||
|
SetFloatingHelpTextStyle(1, 1, 62, -1, 3, 0)
|
||||||
|
BeginTextCommandDisplayHelp("FloatingText")
|
||||||
|
EndTextCommandDisplayHelp(2, false, false, -1)
|
||||||
|
end
|
||||||
|
|
||||||
|
function updateCachedText(target)
|
||||||
|
target.text = table.concat(target.buttontext, "\n")
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
-- Cleanup on Resource Stop
|
-- Cleanup on Resource Stop
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user