--[[ Experimental GTA In-World Text Prompts Targets Module ------------------------------------------------------- This module handles the creation, removal, and management of in-world text targets for interacting with entities and zones using GTA text prompts. It supports multiple targeting systems: OX Target, QB Target, or a fallback using DrawText3D. Available functionalities: • createEntityTarget - Creates a target for a specific entity. • createBoxTarget - Creates a box-shaped zone target. • createCircleTarget - Creates a circular zone target. • createModelTarget - Creates a target for specified models. • removeEntityTarget - Removes a target from an entity. • removeZoneTarget - Removes a zone target. Fallback: If no targeting system is detected (or if disabled via Config.System.DontUseTarget), the module uses DrawText3D prompts. This is experimental and may not work as expected. ]] local targetFunc = { { targetName = OXTargetExport, entityTarget = function(entity, opts, dist) local options = {} for i = 1, #opts do options[i] = { icon = opts[i].icon, label = opts[i].label, items = opts[i].item or nil, groups = opts[i].job or opts[i].gang, onSelect = opts[i].action, distance = dist, canInteract = opts[i].canInteract or nil, } end return exports[OXTargetExport]:addLocalEntity(entity, options) end, boxTarget = function(data, opts, dist) local options = {} for i = 1, #opts do options[i] = { icon = opts[i].icon, label = opts[i].label, items = opts[i].item or nil, groups = opts[i].groups or opts[i].job or opts[i].gang, onSelect = opts[i].onSelect or opts[i].action, distance = dist, canInteract = opts[i].canInteract or nil, } end data[5].maxZ = data[5].maxZ or (data[2].z + 0.80) data[5].minZ = data[5].minZ or data[2].z - 1.05 local thickness = ((data[5].maxZ / 2) - (data[5].minZ / 2)) * 2 local mid = data[5].maxZ - ((data[5].maxZ / 2) - (data[5].minZ / 2)) data[2] = vec3(data[2].x, data[2].y, mid) -- force the coord to middle of the minZ and maxZ local target = exports[OXTargetExport]:addBoxZone({ coords = data[2], size = vec3(data[4], data[3], thickness), -- size uses the math to determine how high it needs to be rotation = data[5].heading, debug = data[5].debugPoly, options = options }) return target end, circleTarget = function(data, opts, dist) local options = {} for i = 1, #opts do options[i] = { icon = opts[i].icon, label = opts[i].label, items = opts[i].item or nil, groups = opts[i].job or opts[i].gang, onSelect = opts[i].onSelect or opts[i].action, distance = dist, canInteract = opts[i].canInteract or nil, } end local target = exports[OXTargetExport]:addSphereZone({ coords = data[2], radius = data[3], debug = data[4].debugPoly, options = options }) return target end, modelTarget = function(models, opts, dist) local options = {} for i = 1, #opts do options[i] = { icon = opts[i].icon, label = opts[i].label, items = opts[i].item or nil, groups = opts[i].job or opts[i].gang, onSelect = opts[i].action, distance = dist, canInteract = opts[i].canInteract or nil, } end return exports[OXTargetExport]:addModel(models, options) end, removeTargetEntity = function(entity) exports[OXTargetExport]:removeLocalEntity(entity, nil) end, removeTargetZone = function(target) exports[OXTargetExport]:removeZone(target, true) end, removeTargetModel = function(model) exports[OXTargetExport]:removeModel(model, nil) end, }, { targetName = QBTargetExport, entityTarget = function(entity, opts, dist) local options = { options = opts, distance = dist } return exports[QBTargetExport]:AddTargetEntity(entity, options) end, boxTarget = function(data, opts, dist) local options = { options = opts, distance = dist } local target = exports[QBTargetExport]:AddBoxZone(data[1], data[2], data[3], data[4], data[5], options) return data[1] end, circleTarget = function(data, opts, dist) local options = { options = opts, distance = dist } local target = exports[QBTargetExport]:AddCircleZone(data[1], data[2], data[3], data[4], options) return data[1] end, modelTarget = function(models, opts, dist) local options = { options = opts, distance = dist } return exports[QBTargetExport]:AddTargetModel(models, options) end, removeTargetEntity = function(entity) exports[QBTargetExport]:RemoveTargetEntity(entity) end, removeTargetZone = function(target) exports[QBTargetExport]:RemoveZone(target) end, removeTargetModel = function(model) exports[QBTargetExport]:RemoveTargetModel(model, "Test") end, }, { targetName = "jim_bridge", entityTarget = function(entity, opts, dist) return exports.jim_bridge:createEntityTarget(entity, opts, dist) end, boxTarget = function(data, opts, dist) return exports.jim_bridge:createZoneTarget(data, opts, dist) end, circleTarget = function(data, opts, dist) return exports.jim_bridge:createZoneTarget(data, opts, dist) end, modelTarget = function(models, opts, dist) return exports.jim_bridge:createModelTarget(models, opts, dist) end, removeTargetEntity = function(entity) exports.jim_bridge:removeEntityTarget(entity) end, removeTargetZone = function(target) exports.jim_bridge:removeZoneTarget(target) end, removeTargetModel = function(model) exports.jim_bridge:removeZoneTarget(model) end, }, } ------------------------------------------------------------- -- Utility Data & Tables ------------------------------------------------------------- -- Tables for storing created targets for the fallback system and zone management. local targetEntities = {} -- For entity targets. local boxTargets = {} -- For box-shaped zone targets. local circleTargets = {} -- For circular zone targets. local modelTargets = {} ------------------------------------------------------------- -- Entity Target Creation ------------------------------------------------------------- --- Creates a target for an entity with specified options and interaction distance. --- Supports different targeting systems (OX Target, QB Target, or custom DrawText3D) --- based on the server configuration. --- --- @param entity number The entity ID for which the target is created. --- @param opts table Array of option tables. Each option should include: --- - icon (string): The icon to display. --- - label (string): The text label for the option. --- - item (string|nil): (Optional) An associated item. --- - job (string|nil): (Optional) The job required to interact. --- - gang (string|nil): (Optional) The gang required to interact. --- - action (function|nil): (Optional) The function executed on selection. --- @param dist number The interaction distance for the target. --- --- @usage --- ```lua ---createEntityTarget(entityId, { --- { --- action = function() --- openStorage() --- end, --- icon = "fas fa-box", --- job = "police", --- label = "Open Storage", --- }, ---}, 2.0) --- ``` function createEntityTarget(entity, opts, dist) -- Store the target entity for later cleanup. targetEntities[#targetEntities + 1] = entity -- if force target off, use jim_bridge built in target functions if Config.System.DontUseTarget then exports.jim_bridge:createEntityTarget(entity, opts, dist) debugPrint("^6Bridge^7: ^2Creating new ^3Entity ^2target with ^6jim_bridge ^2for entity ^7"..entity) return end -- Check for target script and use that for i = 1, #targetFunc do local script = targetFunc[i] if isStarted(script.targetName) then debugPrint("^6Bridge^7: ^2Creating new ^3Entity ^2target with ^6"..script.targetName.." ^2for entity ^7"..entity) return script.entityTarget(entity, opts, dist) end end end ------------------------------------------------------------- -- Box Zone Target Creation ------------------------------------------------------------- --- Creates a box-shaped target zone with specified options and interaction distance. --- Supports different targeting systems based on the server configuration. ---@param data table A table containing the box zone configuration. --- - name (`string`): The name identifier for the zone. --- - coords (`vector3`): The center coordinates of the box. --- - width (`number`): The width of the box. --- - height (`number`): The height of the box. --- - options (`table`): A table with additional options: --- - heading (`number`): The rotation angle of the box. --- - debugPoly (`boolean`): Whether to enable debug mode for the zone. --- ---@param opts table A table of option configurations for the target. --- - icon (`string`): The icon to display for the option. --- - label (`string`): The label text for the option. --- - item (`string|nil`): (Optional) The item associated with the option. --- - job (`string|nil`): (Optional) The job required to interact with the option. --- - gang (`string|nil`): (Optional) The gang required to interact with the option. --- - onSelect (`function|nil`): (Optional) The function to execute when the option is selected. ---@param dist number The interaction distance for the target. --- ---@return string|table name identifier or target object of the created zone. --- ---@usage ---```lua ---createBoxTarget( --- { --- 'storageBox', --- vector3(100.0, 200.0, 30.0), --- 2.0, --- 2.0, --- { --- name = 'storageBox', --- heading = 100.0, --- debugPoly = true, --- minZ = 27.0, --- maxZ = 32.0, --- }, --- }, ---{ --- { --- action = function() --- openStorage() --- end, --- icon = "fas fa-box", --- job = "police", --- label = "Open Storage", --- }, ---}, 2.0) ---``` function createBoxTarget(data, opts, dist) -- if force target off, use jim_bridge built in target functions if Config.System.DontUseTarget then debugPrint("^6Bridge^7: ^2Creating new ^3Box ^2target with ^6jim_bridge ^7"..data[1]) return exports.jim_bridge:createZoneTarget(data, opts, dist) end -- Check for target script and use that for i = 1, #targetFunc do local script = targetFunc[i] if isStarted(script.targetName) then debugPrint("^6Bridge^7: ^2Creating new ^3Box ^2target with ^6"..script.targetName.." ^7"..data[1]) if data[5].minZ or data[5].maxZ then local adMinZ, adMaxZ data[5].minZ, data[5].maxZ, adMinZ, adMaxZ = adjustMinMaxZ(data[2], { minZ = data[5].minZ, maxZ = data[5].maxZ }) if adMinZ or adMaxZ then print("^5Debug^7: ^2Auto adjusted ^7'^4"..data[1].."^7' ^2minZ and maxZ because ^1they weren't set correctly ^2remove or fix them for this target") end end local target = script.boxTarget(data, opts, dist) boxTargets[#boxTargets + 1] = target return target end end return nil end function createPropTarget(data, opts, dist) -- Audo create a location based on a coord and a prop models dimensions local width, depth, _ = GetPropDimensions(data[3]) local min, max = GetModelDimensions(data[3]) local coordAdjustment = data[2] - vec4(0, 0, 1.03, 0) local newData = { [1] = data[1], [2] = coordAdjustment.xyz, [3] = width + 0.1, [4] = depth + 0.1, [5] = { name = data[1], heading = coordAdjustment.w - 90.0, debugPoly = debugMode, minZ = coordAdjustment.z + (min.z) - 0.1, maxZ = coordAdjustment.z + (max.z) + 0.1, } } if data[3] then -- If spawning a prop, make entity target instead (ignores depth and width stuff) makeDistProp({ prop = data[3], coords = data[2] }, true, false) end -- if force target off, use jim_bridge built in target functions if Config.System.DontUseTarget then debugPrint("^6Bridge^7: ^2Creating new ^3Box ^2target with ^6jim_bridge ^7"..data[1]) return exports.jim_bridge:createZoneTarget(newData, opts, dist) end -- Check for target script and use that for i = 1, #targetFunc do local script = targetFunc[i] if isStarted(script.targetName) then debugPrint("^6Bridge^7: ^2Creating new ^3Box ^2target with ^6"..script.targetName.." ^7"..data[1]) local target = script.boxTarget(newData, opts, dist) boxTargets[#boxTargets + 1] = target return target end end return nil end ------------------------------------------------------------- -- Circle Zone Target Creation ------------------------------------------------------------- --- Creates a circular target zone with specified options and interaction distance. --- Supports different targeting systems based on server configuration. --- ---@param data table A table containing the circle zone configuration. --- - name (`string`): The name identifier for the zone. --- - coords (`vector3`): The center coordinates of the circle. --- - radius (`number`): The radius of the circle. --- - options (`table`): A table with additional options: --- - debugPoly (`boolean`): Whether to enable debug mode for the zone. --- ---@param opts table A table of option configurations for the target. --- - icon (`string`): The icon to display for the option. --- - label (`string`): The label text for the option. --- - item (`string|nil`): (Optional) The item associated with the option. --- - job (`string|nil`): (Optional) The job required to interact with the option. --- - gang (`string|nil`): (Optional) The gang required to interact with the option. --- - onSelect (`function|nil`): (Optional) The function to execute when the option is selected. ---@param dist number The interaction distance for the target. --- ---@return string|table name identifier or target object of the created zone. --- ---@usage --- ```lua --- createCircleTarget({ --- name = 'centralPark', --- coords = vector3(200.0, 300.0, 40.0), --- radius = 50.0, --- options = { debugPoly = false } --- }, { --- { icon = "fas fa-tree", label = "Relax", action = relaxAction } --- }, 2.0) --- ``` function createCircleTarget(data, opts, dist) -- if force target off, use jim_bridge built in target functions if Config.System.DontUseTarget then debugPrint("^6Bridge^7: ^2Creating new ^3Sphere ^2target with ^6jim_bridge ^7"..data[1]) return exports.jim_bridge:createZoneTarget(data, opts, dist) end -- Check for target script and use that for i = 1, #targetFunc do local script = targetFunc[i] if isStarted(script.targetName) then debugPrint("^6Bridge^7: ^2Creating new ^3Sphere ^2target with ^6"..script.targetName.." ^7"..data[1]) local target = script.circleTarget(data, opts, dist) circleTargets[#circleTargets + 1] = target return target end end return nil end ------------------------------------------------------------- -- Model Target Creation ------------------------------------------------------------- --- Creates a target for models with specified options and interaction distance. --- Supports different targeting systems (OX Target, QB Target) based on server configuration. --- --- @param models table Array of model identifiers. --- @param opts table Array of option tables (same structure as in createEntityTarget). --- @param dist number The interaction distance for the target. --- --- @usage --- ```lua ---createModelTarget({ model1, model2 }, ---{ --- { --- action = function() --- openStorage() --- end, --- icon = "fas fa-box", --- job = "police", --- label = "Open Storage", --- }, ---}, 2.0) ---``` function createModelTarget(models, opts, dist) -- if force target off, use jim_bridge built in target functions if Config.System.DontUseTarget then debugPrint("^6Bridge^7: ^2Creating new ^3Model ^2target with ^6jim_bridge^7") return exports.jim_bridge:createModelTarget(models, opts, dist) end -- Check for target script and use that for i = 1, #targetFunc do local script = targetFunc[i] if isStarted(script.targetName) then debugPrint("^6Bridge^7: ^2Creating new ^3Model ^2target with ^6"..script.targetName.."^7") local target = script.modelTarget(models, opts, dist) modelTargets[#modelTargets + 1] = target return target end end end ------------------------------------------------------------- -- Target Removal Functions ------------------------------------------------------------- --- Removes a previously created entity target. --- --- @param entity number The entity ID whose target should be removed. --- --- @usage --- ```lua --- removeEntityTarget(entityId) --- ``` function removeEntityTarget(entity) if Config.System.DontUseTarget then exports.jim_bridge:removeEntityTarget(entity) end -- Check for target script and use that for i = 1, #targetFunc do local script = targetFunc[i] if isStarted(script.targetName) then script.removeTargetEntity(entity) break end end end --- Removes a previously created zone target. --- --- @param target string|table The name identifier or target object of the zone to remove. --- --- @usage --- ```lua --- removeZoneTarget('centralPark') --- removeZoneTarget(targetObject) --- ``` function removeZoneTarget(target) if Config.System.DontUseTarget then exports.jim_bridge:removeZoneTarget(target) end -- Check for target script and use that for i = 1, #targetFunc do local script = targetFunc[i] if isStarted(script.targetName) then script.removeTargetZone(target) break end end end --- Removes a previously created model target. --- --- @param model table The model ID whose target should be removed. --- --- @usage --- ```lua --- removeModelTarget(model) --- ``` function removeModelTarget(model) if Config.System.DontUseTarget then exports.jim_bridge:removeZoneTarget(model) end -- Check for target script and use that for i = 1, #targetFunc do local script = targetFunc[i] if isStarted(script.targetName) then script.removeTargetModel(model) break 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 ------------------------------------------------------------- -- Cleanup on Resource Stop ------------------------------------------------------------- local function CleanupTargets() -- Remove entity targets. for i = 1, #targetEntities do if isStarted(OXTargetExport) then exports[OXTargetExport]:removeLocalEntity(targetEntities[i], nil) elseif isStarted(QBTargetExport) then exports[QBTargetExport]:RemoveTargetEntity(targetEntities[i]) end end -- Remove box zone targets. for i = 1, #boxTargets do if isStarted(OXTargetExport) then exports[OXTargetExport]:removeZone(boxTargets[i], true) elseif isStarted(QBTargetExport) then exports[QBTargetExport]:RemoveZone(boxTargets[i]) end end -- Remove circle zone targets. for i = 1, #circleTargets do if isStarted(OXTargetExport) then exports[OXTargetExport]:removeZone(circleTargets[i], true) elseif isStarted(QBTargetExport) then exports[QBTargetExport]:RemoveZone(circleTargets[i]) end end end onPlayerUnload(function() CleanupTargets() end) -- When the current resource stops, remove all targets. onResourceStop(function() CleanupTargets() end, true)