1416 lines
		
	
	
	
		
			41 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			1416 lines
		
	
	
	
		
			41 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
local GetEntityCoords = GetEntityCoords
 | 
						|
local Wait = Wait
 | 
						|
local IsDisabledControlPressed = IsDisabledControlPressed
 | 
						|
local GetEntityBoneIndexByName = GetEntityBoneIndexByName
 | 
						|
local GetWorldPositionOfEntityBone = GetWorldPositionOfEntityBone
 | 
						|
local SetPauseMenuActive = SetPauseMenuActive
 | 
						|
local DisableAllControlActions = DisableAllControlActions
 | 
						|
local EnableControlAction = EnableControlAction
 | 
						|
local NetworkGetEntityIsNetworked = NetworkGetEntityIsNetworked
 | 
						|
local NetworkGetNetworkIdFromEntity = NetworkGetNetworkIdFromEntity
 | 
						|
local GetEntityModel = GetEntityModel
 | 
						|
local IsPedAPlayer = IsPedAPlayer
 | 
						|
local GetEntityType = GetEntityType
 | 
						|
local PlayerPedId = PlayerPedId
 | 
						|
local GetShapeTestResult = GetShapeTestResult
 | 
						|
local StartShapeTestLosProbe = StartShapeTestLosProbe
 | 
						|
local SetDrawOrigin = SetDrawOrigin
 | 
						|
local DrawSprite = DrawSprite
 | 
						|
local ClearDrawOrigin = ClearDrawOrigin
 | 
						|
local HasStreamedTextureDictLoaded = HasStreamedTextureDictLoaded
 | 
						|
local RequestStreamedTextureDict = RequestStreamedTextureDict
 | 
						|
local HasEntityClearLosToEntity = HasEntityClearLosToEntity
 | 
						|
local currentResourceName = GetCurrentResourceName()
 | 
						|
local Config, Types, Players, Entities, Models, Zones, nuiData, sendData, sendDistance = Config, { {}, {}, {} }, {}, {},
 | 
						|
	{}, {}, {}, {}, {}
 | 
						|
local playerPed, targetActive, hasFocus, success, pedsReady, allowTarget = PlayerPedId(), false, false, false, false,
 | 
						|
	true
 | 
						|
local screen = {}
 | 
						|
local table_wipe = table.wipe
 | 
						|
local pairs = pairs
 | 
						|
local pcall = pcall
 | 
						|
local CheckOptions = CheckOptions
 | 
						|
local Bones = Load('bones')
 | 
						|
local listSprite = {}
 | 
						|
 | 
						|
---------------------------------------
 | 
						|
--- Source: https://github.com/citizenfx/lua/blob/luaglm-dev/cfx/libs/scripts/examples/scripting_gta.lua
 | 
						|
--- Credits to gottfriedleibniz
 | 
						|
local glm = require 'glm'
 | 
						|
 | 
						|
-- Cache common functions
 | 
						|
local glm_rad = glm.rad
 | 
						|
local glm_quatEuler = glm.quatEulerAngleZYX
 | 
						|
local glm_rayPicking = glm.rayPicking
 | 
						|
 | 
						|
-- Cache direction vectors
 | 
						|
local glm_up = glm.up()
 | 
						|
local glm_forward = glm.forward()
 | 
						|
 | 
						|
local function ScreenPositionToCameraRay()
 | 
						|
	local pos = GetFinalRenderedCamCoord()
 | 
						|
	local rot = glm_rad(GetFinalRenderedCamRot(2))
 | 
						|
	local q = glm_quatEuler(rot.z, rot.y, rot.x)
 | 
						|
	return pos, glm_rayPicking(
 | 
						|
		q * glm_forward,
 | 
						|
		q * glm_up,
 | 
						|
		glm_rad(screen.fov),
 | 
						|
		screen.ratio,
 | 
						|
		0.10000, -- GetFinalRenderedCamNearClip(),
 | 
						|
		10000.0, -- GetFinalRenderedCamFarClip(),
 | 
						|
		0, 0
 | 
						|
	)
 | 
						|
end
 | 
						|
---------------------------------------
 | 
						|
 | 
						|
-- Functions
 | 
						|
 | 
						|
local function DrawTarget()
 | 
						|
	CreateThread(function()
 | 
						|
		while not HasStreamedTextureDictLoaded('shared') do
 | 
						|
			Wait(10)
 | 
						|
			RequestStreamedTextureDict('shared', true)
 | 
						|
		end
 | 
						|
		local sleep
 | 
						|
		local r, g, b, a
 | 
						|
		while targetActive do
 | 
						|
			sleep = 500
 | 
						|
			for _, zone in pairs(listSprite) do
 | 
						|
				sleep = 0
 | 
						|
 | 
						|
				r = zone.targetoptions.drawColor?[1] or Config.DrawColor[1]
 | 
						|
				g = zone.targetoptions.drawColor?[2] or Config.DrawColor[2]
 | 
						|
				b = zone.targetoptions.drawColor?[3] or Config.DrawColor[3]
 | 
						|
				a = zone.targetoptions.drawColor?[4] or Config.DrawColor[4]
 | 
						|
 | 
						|
				if zone.success then
 | 
						|
					r = zone.targetoptions.successDrawColor?[1] or Config.SuccessDrawColor[1]
 | 
						|
					g = zone.targetoptions.successDrawColor?[2] or Config.SuccessDrawColor[2]
 | 
						|
					b = zone.targetoptions.successDrawColor?[3] or Config.SuccessDrawColor[3]
 | 
						|
					a = zone.targetoptions.successDrawColor?[4] or Config.SuccessDrawColor[4]
 | 
						|
				end
 | 
						|
 | 
						|
				SetDrawOrigin(zone.center.x, zone.center.y, zone.center.z, 0)
 | 
						|
				DrawSprite('shared', 'emptydot_32', 0, 0, 0.01, 0.02, 0, r, g, b, a)
 | 
						|
				ClearDrawOrigin()
 | 
						|
			end
 | 
						|
			Wait(sleep)
 | 
						|
		end
 | 
						|
		listSprite = {}
 | 
						|
	end)
 | 
						|
end
 | 
						|
 | 
						|
local function RaycastCamera(flag, playerCoords)
 | 
						|
	if not playerPed then playerPed = PlayerPedId() end
 | 
						|
	if not playerCoords then playerCoords = GetEntityCoords(playerPed) end
 | 
						|
 | 
						|
	local rayPos, rayDir = ScreenPositionToCameraRay()
 | 
						|
	local destination = rayPos + 16 * rayDir
 | 
						|
	local rayHandle = StartShapeTestLosProbe(rayPos.x, rayPos.y, rayPos.z, destination.x, destination.y, destination.z,
 | 
						|
		flag or -1, playerPed, 4)
 | 
						|
 | 
						|
	while true do
 | 
						|
		local result, _, endCoords, _, entityHit = GetShapeTestResult(rayHandle)
 | 
						|
 | 
						|
		if result ~= 1 then
 | 
						|
			local distance = playerCoords and #(playerCoords - endCoords)
 | 
						|
 | 
						|
			if flag == 30 and entityHit then
 | 
						|
				entityHit = HasEntityClearLosToEntity(entityHit, playerPed, 7) and entityHit
 | 
						|
			end
 | 
						|
 | 
						|
			local entityType = entityHit and GetEntityType(entityHit)
 | 
						|
 | 
						|
			if entityType == 0 and pcall(GetEntityModel, entityHit) then
 | 
						|
				entityType = 3
 | 
						|
			end
 | 
						|
 | 
						|
			return endCoords, distance, entityHit, entityType or 0
 | 
						|
		end
 | 
						|
 | 
						|
		Wait(0)
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
exports('RaycastCamera', RaycastCamera)
 | 
						|
 | 
						|
local function DisableNUI()
 | 
						|
	SetNuiFocus(false, false)
 | 
						|
	SetNuiFocusKeepInput(false)
 | 
						|
	hasFocus = false
 | 
						|
end
 | 
						|
 | 
						|
exports('DisableNUI', DisableNUI)
 | 
						|
 | 
						|
local function EnableNUI(options)
 | 
						|
	if not targetActive or hasFocus then return end
 | 
						|
	SetCursorLocation(0.5, 0.5)
 | 
						|
	SetNuiFocus(true, true)
 | 
						|
	SetNuiFocusKeepInput(true)
 | 
						|
	hasFocus = true
 | 
						|
	SendNUIMessage({ response = 'validTarget', data = options })
 | 
						|
end
 | 
						|
 | 
						|
exports('EnableNUI', EnableNUI)
 | 
						|
 | 
						|
local function LeftTarget()
 | 
						|
	SetNuiFocus(false, false)
 | 
						|
	SetNuiFocusKeepInput(false)
 | 
						|
	success, hasFocus = false, false
 | 
						|
	table_wipe(sendData)
 | 
						|
	SendNUIMessage({ response = 'leftTarget' })
 | 
						|
end
 | 
						|
 | 
						|
exports('LeftTarget', LeftTarget)
 | 
						|
 | 
						|
local function DisableTarget(forcedisable)
 | 
						|
	if (not targetActive and hasFocus and not Config.Toggle) or not forcedisable then return end
 | 
						|
	SetNuiFocus(false, false)
 | 
						|
	SetNuiFocusKeepInput(false)
 | 
						|
	Wait(100)
 | 
						|
	targetActive, success, hasFocus = false, false, false
 | 
						|
	SendNUIMessage({ response = 'closeTarget' })
 | 
						|
end
 | 
						|
 | 
						|
exports('DisableTarget', DisableTarget)
 | 
						|
 | 
						|
local function DrawOutlineEntity(entity, bool)
 | 
						|
	if not Config.EnableOutline or IsEntityAPed(entity) then return end
 | 
						|
	SetEntityDrawOutline(entity, bool)
 | 
						|
	SetEntityDrawOutlineColor(Config.OutlineColor[1], Config.OutlineColor[2], Config.OutlineColor[3], Config.OutlineColor[4])
 | 
						|
end
 | 
						|
 | 
						|
exports('DrawOutlineEntity', DrawOutlineEntity)
 | 
						|
 | 
						|
local function SetupOptions(datatable, entity, distance, isZone)
 | 
						|
	if not isZone then table_wipe(sendDistance) end
 | 
						|
	table_wipe(nuiData)
 | 
						|
	local slot = 0
 | 
						|
	for _, data in pairs(datatable) do
 | 
						|
		if CheckOptions(data, entity, distance) then
 | 
						|
			slot = data.num or slot + 1
 | 
						|
			sendData[slot] = data
 | 
						|
			sendData[slot].entity = entity
 | 
						|
			nuiData[slot] = {
 | 
						|
				icon = data.icon,
 | 
						|
				targeticon = data.targeticon,
 | 
						|
				label = data.label
 | 
						|
			}
 | 
						|
			if not isZone then
 | 
						|
				sendDistance[data.distance] = true
 | 
						|
			end
 | 
						|
		else
 | 
						|
			if not isZone then
 | 
						|
				sendDistance[data.distance] = false
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
	return slot
 | 
						|
end
 | 
						|
 | 
						|
local function CheckEntity(flag, datatable, entity, distance)
 | 
						|
	if not next(datatable) then return end
 | 
						|
	local slot = SetupOptions(datatable, entity, distance)
 | 
						|
	if not next(nuiData) then
 | 
						|
		LeftTarget()
 | 
						|
		DrawOutlineEntity(entity, false)
 | 
						|
		return
 | 
						|
	end
 | 
						|
	success = true
 | 
						|
	SendNUIMessage({ response = 'foundTarget', data = nuiData[slot].targeticon, options = nuiData })
 | 
						|
	DrawOutlineEntity(entity, true)
 | 
						|
	while targetActive and success do
 | 
						|
		local _, dist, entity2 = RaycastCamera(flag)
 | 
						|
		if entity ~= entity2 then
 | 
						|
			LeftTarget()
 | 
						|
			DrawOutlineEntity(entity, false)
 | 
						|
			break
 | 
						|
		elseif not hasFocus and IsDisabledControlPressed(0, Config.MenuControlKey) then
 | 
						|
			EnableNUI(nuiData)
 | 
						|
			DrawOutlineEntity(entity, false)
 | 
						|
		else
 | 
						|
			for k, v in pairs(sendDistance) do
 | 
						|
				if v and dist > k then
 | 
						|
					LeftTarget()
 | 
						|
					DrawOutlineEntity(entity, false)
 | 
						|
					break
 | 
						|
				end
 | 
						|
			end
 | 
						|
		end
 | 
						|
		Wait(0)
 | 
						|
	end
 | 
						|
	LeftTarget()
 | 
						|
	DrawOutlineEntity(entity, false)
 | 
						|
end
 | 
						|
 | 
						|
exports('CheckEntity', CheckEntity)
 | 
						|
 | 
						|
local function CheckBones(coords, entity, bonelist)
 | 
						|
	local closestBone = -1
 | 
						|
	local closestDistance = 20
 | 
						|
	local closestPos, closestBoneName
 | 
						|
	for _, v in pairs(bonelist) do
 | 
						|
		if Bones.Options[v] then
 | 
						|
			local boneId = GetEntityBoneIndexByName(entity, v)
 | 
						|
			local bonePos = GetWorldPositionOfEntityBone(entity, boneId)
 | 
						|
			local distance = #(coords - bonePos)
 | 
						|
			if closestBone == -1 or distance < closestDistance then
 | 
						|
				closestBone, closestDistance, closestPos, closestBoneName = boneId, distance, bonePos, v
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
	if closestBone ~= -1 then
 | 
						|
		return closestBone, closestPos, closestBoneName
 | 
						|
	else
 | 
						|
		return false
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
exports('CheckBones', CheckBones)
 | 
						|
 | 
						|
local function EnableTarget()
 | 
						|
	if not allowTarget or success or (not Config.Standalone and not LocalPlayer.state['isLoggedIn']) or IsNuiFocused() or (Config.DisableInVehicle and IsPedInAnyVehicle(playerPed or PlayerPedId(), false)) then return end
 | 
						|
	if targetActive then return end
 | 
						|
 | 
						|
	targetActive = true
 | 
						|
	playerPed = PlayerPedId()
 | 
						|
	screen.ratio = GetAspectRatio(true)
 | 
						|
	screen.fov = GetFinalRenderedCamFov()
 | 
						|
	if Config.DrawSprite then DrawTarget() end
 | 
						|
 | 
						|
	SendNUIMessage({ response = 'openTarget' })
 | 
						|
	CreateThread(function()
 | 
						|
		repeat
 | 
						|
			SetPauseMenuActive(false)
 | 
						|
			if Config.DisableControls then
 | 
						|
				DisableAllControlActions(0)
 | 
						|
			else
 | 
						|
				DisableControlAction(0, 1, true) -- look left/right
 | 
						|
				DisableControlAction(0, 2, true) -- look up/down
 | 
						|
				DisableControlAction(0, 4, true) -- look down only
 | 
						|
				DisableControlAction(0, 5, true) -- look left only
 | 
						|
				DisableControlAction(0, 6, true) -- look right only
 | 
						|
				DisableControlAction(0, 25, true) -- input aim
 | 
						|
				DisableControlAction(0, 24, true) -- attack
 | 
						|
			end
 | 
						|
			EnableControlAction(0, 30, true) -- move left/right
 | 
						|
			EnableControlAction(0, 31, true) -- move forward/back
 | 
						|
 | 
						|
			if not hasFocus then
 | 
						|
				EnableControlAction(0, 1, true) -- look left/right
 | 
						|
				EnableControlAction(0, 2, true) -- look up/down
 | 
						|
			end
 | 
						|
 | 
						|
			Wait(0)
 | 
						|
		until not targetActive
 | 
						|
	end)
 | 
						|
 | 
						|
	local flag = 30
 | 
						|
 | 
						|
	while targetActive do
 | 
						|
		local sleep = 0
 | 
						|
		if flag == 30 then flag = -1 else flag = 30 end
 | 
						|
 | 
						|
		local coords, distance, entity, entityType = RaycastCamera(flag)
 | 
						|
		if distance <= Config.MaxDistance then
 | 
						|
			if entityType > 0 then
 | 
						|
				-- Local(non-net) entity targets
 | 
						|
				if Entities[entity] then
 | 
						|
					CheckEntity(flag, Entities[entity], entity, distance)
 | 
						|
				end
 | 
						|
 | 
						|
				-- Owned entity targets
 | 
						|
				if NetworkGetEntityIsNetworked(entity) then
 | 
						|
					local data = Entities[NetworkGetNetworkIdFromEntity(entity)]
 | 
						|
					if data then CheckEntity(flag, data, entity, distance) end
 | 
						|
				end
 | 
						|
 | 
						|
				-- Player and Ped targets
 | 
						|
				if entityType == 1 then
 | 
						|
					local data = Models[GetEntityModel(entity)]
 | 
						|
					if IsPedAPlayer(entity) then data = Players end
 | 
						|
					if data and next(data) then CheckEntity(flag, data, entity, distance) end
 | 
						|
 | 
						|
					-- Vehicle bones and models
 | 
						|
				elseif entityType == 2 then
 | 
						|
					local closestBone, _, closestBoneName = CheckBones(coords, entity, Bones.Vehicle)
 | 
						|
					local datatable = Bones.Options[closestBoneName]
 | 
						|
 | 
						|
					if datatable and next(datatable) and closestBone then
 | 
						|
						local slot = SetupOptions(datatable, entity, distance)
 | 
						|
						if next(nuiData) then
 | 
						|
							success = true
 | 
						|
							SendNUIMessage({ response = 'foundTarget', data = nuiData[slot].targeticon, options = nuiData })
 | 
						|
							DrawOutlineEntity(entity, true)
 | 
						|
							while targetActive and success do
 | 
						|
								local coords2, dist, entity2 = RaycastCamera(flag)
 | 
						|
								if entity == entity2 then
 | 
						|
									local closestBone2 = CheckBones(coords2, entity, Bones.Vehicle)
 | 
						|
									if closestBone ~= closestBone2 then
 | 
						|
										LeftTarget()
 | 
						|
										DrawOutlineEntity(entity, false)
 | 
						|
										break
 | 
						|
									elseif not hasFocus and IsDisabledControlPressed(0, Config.MenuControlKey) then
 | 
						|
										EnableNUI(nuiData)
 | 
						|
										DrawOutlineEntity(entity, false)
 | 
						|
									else
 | 
						|
										for k, v in pairs(sendDistance) do
 | 
						|
											if v and dist > k then
 | 
						|
												LeftTarget()
 | 
						|
												DrawOutlineEntity(entity, false)
 | 
						|
												break
 | 
						|
											end
 | 
						|
										end
 | 
						|
									end
 | 
						|
								else
 | 
						|
									LeftTarget()
 | 
						|
									DrawOutlineEntity(entity, false)
 | 
						|
									break
 | 
						|
								end
 | 
						|
								Wait(0)
 | 
						|
							end
 | 
						|
							LeftTarget()
 | 
						|
							DrawOutlineEntity(entity, false)
 | 
						|
						end
 | 
						|
					end
 | 
						|
 | 
						|
					-- Vehicle model targets
 | 
						|
					local data = Models[GetEntityModel(entity)]
 | 
						|
					if data then CheckEntity(flag, data, entity, distance) end
 | 
						|
 | 
						|
					-- Entity targets
 | 
						|
				elseif entityType > 2 then
 | 
						|
					local data = Models[GetEntityModel(entity)]
 | 
						|
					if data then CheckEntity(flag, data, entity, distance) end
 | 
						|
				end
 | 
						|
 | 
						|
				-- Generic targets
 | 
						|
				if not success then
 | 
						|
					local data = Types[entityType]
 | 
						|
					if data and next(data) then CheckEntity(flag, data, entity, distance) end
 | 
						|
				end
 | 
						|
			else
 | 
						|
				sleep = sleep + 20
 | 
						|
			end
 | 
						|
			if not success then
 | 
						|
				-- Zone targets
 | 
						|
				local closestDis, closestZone
 | 
						|
				for k, zone in pairs(Zones) do
 | 
						|
					if distance < (closestDis or Config.MaxDistance) and distance <= zone.targetoptions.distance and zone:isPointInside(coords) then
 | 
						|
						closestDis = distance
 | 
						|
						closestZone = zone
 | 
						|
					end
 | 
						|
					if Config.DrawSprite then
 | 
						|
						local testCentre = type(zone.center) == 'vector2' and vector3(zone.center.x, zone.center.y, zone.maxZ) or zone.center
 | 
						|
						if #(coords - testCentre) < (zone.targetoptions.drawDistance or Config.DrawDistance) then
 | 
						|
							listSprite[k] = zone
 | 
						|
						else
 | 
						|
							listSprite[k] = nil
 | 
						|
						end
 | 
						|
					end
 | 
						|
				end
 | 
						|
				if closestZone then
 | 
						|
					local slot = SetupOptions(closestZone.targetoptions.options, entity, distance, true)
 | 
						|
					if next(nuiData) then
 | 
						|
						success = true
 | 
						|
						SendNUIMessage({ response = 'foundTarget', data = nuiData[slot].targeticon, options = nuiData })
 | 
						|
						if Config.DrawSprite then
 | 
						|
							listSprite[closestZone.name].success = true
 | 
						|
						end
 | 
						|
						DrawOutlineEntity(entity, true)
 | 
						|
						while targetActive and success do
 | 
						|
							local newCoords, dist = RaycastCamera(flag)
 | 
						|
							if not closestZone:isPointInside(newCoords) or dist > closestZone.targetoptions.distance then
 | 
						|
								LeftTarget()
 | 
						|
								DrawOutlineEntity(entity, false)
 | 
						|
								break
 | 
						|
							elseif not hasFocus and IsDisabledControlPressed(0, Config.MenuControlKey) then
 | 
						|
								EnableNUI(nuiData)
 | 
						|
								DrawOutlineEntity(entity, false)
 | 
						|
							end
 | 
						|
							Wait(0)
 | 
						|
						end
 | 
						|
						if Config.DrawSprite and listSprite[closestZone.name] then -- Check for when the targetActive is false and it removes the zone from listSprite
 | 
						|
							listSprite[closestZone.name].success = false
 | 
						|
						end
 | 
						|
						LeftTarget()
 | 
						|
						DrawOutlineEntity(entity, false)
 | 
						|
					end
 | 
						|
				else
 | 
						|
					sleep = sleep + 20
 | 
						|
				end
 | 
						|
			else
 | 
						|
				LeftTarget()
 | 
						|
				DrawOutlineEntity(entity, false)
 | 
						|
			end
 | 
						|
		else
 | 
						|
			sleep = sleep + 20
 | 
						|
		end
 | 
						|
		Wait(sleep)
 | 
						|
	end
 | 
						|
	DisableTarget(false)
 | 
						|
end
 | 
						|
 | 
						|
local function AddCircleZone(name, center, radius, options, targetoptions)
 | 
						|
	local centerType = type(center)
 | 
						|
	center = (centerType == 'table' or centerType == 'vector4') and vec3(center.x, center.y, center.z) or center
 | 
						|
	Zones[name] = CircleZone:Create(center, radius, options)
 | 
						|
	targetoptions.distance = targetoptions.distance or Config.MaxDistance
 | 
						|
	Zones[name].targetoptions = targetoptions
 | 
						|
	return Zones[name]
 | 
						|
end
 | 
						|
 | 
						|
exports('AddCircleZone', AddCircleZone)
 | 
						|
 | 
						|
local function AddBoxZone(name, center, length, width, options, targetoptions)
 | 
						|
	local centerType = type(center)
 | 
						|
	center = (centerType == 'table' or centerType == 'vector4') and vec3(center.x, center.y, center.z) or center
 | 
						|
	Zones[name] = BoxZone:Create(center, length, width, options)
 | 
						|
	targetoptions.distance = targetoptions.distance or Config.MaxDistance
 | 
						|
	Zones[name].targetoptions = targetoptions
 | 
						|
	return Zones[name]
 | 
						|
end
 | 
						|
 | 
						|
exports('AddBoxZone', AddBoxZone)
 | 
						|
 | 
						|
local function AddPolyZone(name, points, options, targetoptions)
 | 
						|
	local _points = {}
 | 
						|
	local pointsType = type(points[1])
 | 
						|
	if pointsType == 'table' or pointsType == 'vector3' or pointsType == 'vector4' then
 | 
						|
		for i = 1, #points do
 | 
						|
			_points[i] = vec2(points[i].x, points[i].y)
 | 
						|
		end
 | 
						|
	end
 | 
						|
	Zones[name] = PolyZone:Create(#_points > 0 and _points or points, options)
 | 
						|
	targetoptions.distance = targetoptions.distance or Config.MaxDistance
 | 
						|
	Zones[name].targetoptions = targetoptions
 | 
						|
	return Zones[name]
 | 
						|
end
 | 
						|
 | 
						|
exports('AddPolyZone', AddPolyZone)
 | 
						|
 | 
						|
local function AddComboZone(zones, options, targetoptions)
 | 
						|
	Zones[options.name] = ComboZone:Create(zones, options)
 | 
						|
	targetoptions.distance = targetoptions.distance or Config.MaxDistance
 | 
						|
	Zones[options.name].targetoptions = targetoptions
 | 
						|
	return Zones[options.name]
 | 
						|
end
 | 
						|
 | 
						|
exports('AddComboZone', AddComboZone)
 | 
						|
 | 
						|
local function AddEntityZone(name, entity, options, targetoptions)
 | 
						|
	Zones[name] = EntityZone:Create(entity, options)
 | 
						|
	targetoptions.distance = targetoptions.distance or Config.MaxDistance
 | 
						|
	Zones[name].targetoptions = targetoptions
 | 
						|
	return Zones[name]
 | 
						|
end
 | 
						|
 | 
						|
exports('AddEntityZone', AddEntityZone)
 | 
						|
 | 
						|
local function RemoveZone(name)
 | 
						|
	if not Zones[name] then return end
 | 
						|
	if Zones[name].destroy then Zones[name]:destroy() end
 | 
						|
	Zones[name] = nil
 | 
						|
end
 | 
						|
 | 
						|
exports('RemoveZone', RemoveZone)
 | 
						|
 | 
						|
local function SetOptions(tbl, distance, options)
 | 
						|
	for _, v in pairs(options) do
 | 
						|
		if v.required_item then
 | 
						|
			v.item = v.required_item
 | 
						|
			v.required_item = nil
 | 
						|
		end
 | 
						|
		if not v.distance or v.distance > distance then v.distance = distance end
 | 
						|
		tbl[v.label] = v
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
local function AddTargetBone(bones, parameters)
 | 
						|
	local distance, options = parameters.distance or Config.MaxDistance, parameters.options
 | 
						|
	if type(bones) == 'table' then
 | 
						|
		for _, bone in pairs(bones) do
 | 
						|
			if not Bones.Options[bone] then Bones.Options[bone] = {} end
 | 
						|
			SetOptions(Bones.Options[bone], distance, options)
 | 
						|
		end
 | 
						|
	elseif type(bones) == 'string' then
 | 
						|
		if not Bones.Options[bones] then Bones.Options[bones] = {} end
 | 
						|
		SetOptions(Bones.Options[bones], distance, options)
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
exports('AddTargetBone', AddTargetBone)
 | 
						|
 | 
						|
local function RemoveTargetBone(bones, labels)
 | 
						|
	if type(bones) == 'table' then
 | 
						|
		for _, bone in pairs(bones) do
 | 
						|
			if labels then
 | 
						|
				if type(labels) == 'table' then
 | 
						|
					for _, v in pairs(labels) do
 | 
						|
						if Bones.Options[bone] then
 | 
						|
							Bones.Options[bone][v] = nil
 | 
						|
						end
 | 
						|
					end
 | 
						|
				elseif type(labels) == 'string' then
 | 
						|
					if Bones.Options[bone] then
 | 
						|
						Bones.Options[bone][labels] = nil
 | 
						|
					end
 | 
						|
				end
 | 
						|
			else
 | 
						|
				Bones.Options[bone] = nil
 | 
						|
			end
 | 
						|
		end
 | 
						|
	else
 | 
						|
		if labels then
 | 
						|
			if type(labels) == 'table' then
 | 
						|
				for _, v in pairs(labels) do
 | 
						|
					if Bones.Options[bones] then
 | 
						|
						Bones.Options[bones][v] = nil
 | 
						|
					end
 | 
						|
				end
 | 
						|
			elseif type(labels) == 'string' then
 | 
						|
				if Bones.Options[bones] then
 | 
						|
					Bones.Options[bones][labels] = nil
 | 
						|
				end
 | 
						|
			end
 | 
						|
		else
 | 
						|
			Bones.Options[bones] = nil
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
exports('RemoveTargetBone', RemoveTargetBone)
 | 
						|
 | 
						|
local function AddTargetEntity(entities, parameters)
 | 
						|
	local distance, options = parameters.distance or Config.MaxDistance, parameters.options
 | 
						|
	if type(entities) == 'table' then
 | 
						|
		for _, entity in pairs(entities) do
 | 
						|
			if NetworkGetEntityIsNetworked(entity) then entity = NetworkGetNetworkIdFromEntity(entity) end -- Allow non-networked entities to be targeted
 | 
						|
			if not Entities[entity] then Entities[entity] = {} end
 | 
						|
			SetOptions(Entities[entity], distance, options)
 | 
						|
		end
 | 
						|
	elseif type(entities) == 'number' then
 | 
						|
		if NetworkGetEntityIsNetworked(entities) then entities = NetworkGetNetworkIdFromEntity(entities) end -- Allow non-networked entities to be targeted
 | 
						|
		if not Entities[entities] then Entities[entities] = {} end
 | 
						|
		SetOptions(Entities[entities], distance, options)
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
exports('AddTargetEntity', AddTargetEntity)
 | 
						|
 | 
						|
local function RemoveTargetEntity(entities, labels)
 | 
						|
	if type(entities) == 'table' then
 | 
						|
		for _, entity in pairs(entities) do
 | 
						|
			if NetworkGetEntityIsNetworked(entity) then entity = NetworkGetNetworkIdFromEntity(entity) end -- Allow non-networked entities to be targeted
 | 
						|
			if labels then
 | 
						|
				if type(labels) == 'table' then
 | 
						|
					for _, v in pairs(labels) do
 | 
						|
						if Entities[entity] then
 | 
						|
							Entities[entity][v] = nil
 | 
						|
						end
 | 
						|
					end
 | 
						|
				elseif type(labels) == 'string' then
 | 
						|
					if Entities[entity] then
 | 
						|
						Entities[entity][labels] = nil
 | 
						|
					end
 | 
						|
				end
 | 
						|
			else
 | 
						|
				Entities[entity] = nil
 | 
						|
			end
 | 
						|
		end
 | 
						|
	elseif type(entities) == 'number' then
 | 
						|
		if NetworkGetEntityIsNetworked(entities) then entities = NetworkGetNetworkIdFromEntity(entities) end -- Allow non-networked entities to be targeted
 | 
						|
		if labels then
 | 
						|
			if type(labels) == 'table' then
 | 
						|
				for _, v in pairs(labels) do
 | 
						|
					if Entities[entities] then
 | 
						|
						Entities[entities][v] = nil
 | 
						|
					end
 | 
						|
				end
 | 
						|
			elseif type(labels) == 'string' then
 | 
						|
				if Entities[entities] then
 | 
						|
					Entities[entities][labels] = nil
 | 
						|
				end
 | 
						|
			end
 | 
						|
		else
 | 
						|
			Entities[entities] = nil
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
exports('RemoveTargetEntity', RemoveTargetEntity)
 | 
						|
 | 
						|
local function AddTargetModel(models, parameters)
 | 
						|
	local distance, options = parameters.distance or Config.MaxDistance, parameters.options
 | 
						|
	if type(models) == 'table' then
 | 
						|
		for _, model in pairs(models) do
 | 
						|
			if type(model) == 'string' then model = joaat(model) end
 | 
						|
			if not Models[model] then Models[model] = {} end
 | 
						|
			SetOptions(Models[model], distance, options)
 | 
						|
		end
 | 
						|
	else
 | 
						|
		if type(models) == 'string' then models = joaat(models) end
 | 
						|
		if not Models[models] then Models[models] = {} end
 | 
						|
		SetOptions(Models[models], distance, options)
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
exports('AddTargetModel', AddTargetModel)
 | 
						|
 | 
						|
local function RemoveTargetModel(models, labels)
 | 
						|
	if type(models) == 'table' then
 | 
						|
		for _, model in pairs(models) do
 | 
						|
			if type(model) == 'string' then model = joaat(model) end
 | 
						|
			if labels then
 | 
						|
				if type(labels) == 'table' then
 | 
						|
					for _, v in pairs(labels) do
 | 
						|
						if Models[model] then
 | 
						|
							Models[model][v] = nil
 | 
						|
						end
 | 
						|
					end
 | 
						|
				elseif type(labels) == 'string' then
 | 
						|
					if Models[model] then
 | 
						|
						Models[model][labels] = nil
 | 
						|
					end
 | 
						|
				end
 | 
						|
			else
 | 
						|
				Models[model] = nil
 | 
						|
			end
 | 
						|
		end
 | 
						|
	else
 | 
						|
		if type(models) == 'string' then models = joaat(models) end
 | 
						|
		if labels then
 | 
						|
			if type(labels) == 'table' then
 | 
						|
				for _, v in pairs(labels) do
 | 
						|
					if Models[models] then
 | 
						|
						Models[models][v] = nil
 | 
						|
					end
 | 
						|
				end
 | 
						|
			elseif type(labels) == 'string' then
 | 
						|
				if Models[models] then
 | 
						|
					Models[models][labels] = nil
 | 
						|
				end
 | 
						|
			end
 | 
						|
		else
 | 
						|
			Models[models] = nil
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
exports('RemoveTargetModel', RemoveTargetModel)
 | 
						|
 | 
						|
local function AddGlobalType(type, parameters)
 | 
						|
	local distance, options = parameters.distance or Config.MaxDistance, parameters.options
 | 
						|
	SetOptions(Types[type], distance, options)
 | 
						|
end
 | 
						|
 | 
						|
exports('AddGlobalType', AddGlobalType)
 | 
						|
 | 
						|
local function AddGlobalPed(parameters) AddGlobalType(1, parameters) end
 | 
						|
 | 
						|
exports('AddGlobalPed', AddGlobalPed)
 | 
						|
 | 
						|
local function AddGlobalVehicle(parameters) AddGlobalType(2, parameters) end
 | 
						|
 | 
						|
exports('AddGlobalVehicle', AddGlobalVehicle)
 | 
						|
 | 
						|
local function AddGlobalObject(parameters) AddGlobalType(3, parameters) end
 | 
						|
 | 
						|
exports('AddGlobalObject', AddGlobalObject)
 | 
						|
 | 
						|
local function AddGlobalPlayer(parameters)
 | 
						|
	local distance, options = parameters.distance or Config.MaxDistance, parameters.options
 | 
						|
	SetOptions(Players, distance, options)
 | 
						|
end
 | 
						|
 | 
						|
exports('AddGlobalPlayer', AddGlobalPlayer)
 | 
						|
 | 
						|
local function RemoveGlobalType(typ, labels)
 | 
						|
	if labels then
 | 
						|
		if type(labels) == 'table' then
 | 
						|
			for _, v in pairs(labels) do
 | 
						|
				Types[typ][v] = nil
 | 
						|
			end
 | 
						|
		elseif type(labels) == 'string' then
 | 
						|
			Types[typ][labels] = nil
 | 
						|
		end
 | 
						|
	else
 | 
						|
		Types[typ] = {}
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
exports('RemoveGlobalType', RemoveGlobalType)
 | 
						|
 | 
						|
local function RemoveGlobalPlayer(labels)
 | 
						|
	if labels then
 | 
						|
		if type(labels) == 'table' then
 | 
						|
			for _, v in pairs(labels) do
 | 
						|
				Players[v] = nil
 | 
						|
			end
 | 
						|
		elseif type(labels) == 'string' then
 | 
						|
			Players[labels] = nil
 | 
						|
		end
 | 
						|
	else
 | 
						|
		Players = {}
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
exports('RemoveGlobalPlayer', RemoveGlobalPlayer)
 | 
						|
 | 
						|
function SpawnPeds()
 | 
						|
	if pedsReady or not next(Config.Peds) then return end
 | 
						|
	for k, v in pairs(Config.Peds) do
 | 
						|
		if not v.currentpednumber or v.currentpednumber == 0 then
 | 
						|
			local spawnedped
 | 
						|
			RequestModel(v.model)
 | 
						|
			while not HasModelLoaded(v.model) do
 | 
						|
				Wait(0)
 | 
						|
			end
 | 
						|
 | 
						|
			if type(v.model) == 'string' then v.model = joaat(v.model) end
 | 
						|
 | 
						|
			if v.minusOne then
 | 
						|
				spawnedped = CreatePed(0, v.model, v.coords.x, v.coords.y, v.coords.z - 1.0, v.coords.w,
 | 
						|
					v.networked or false, false)
 | 
						|
			else
 | 
						|
				spawnedped = CreatePed(0, v.model, v.coords.x, v.coords.y, v.coords.z, v.coords.w, v.networked or false,
 | 
						|
					false)
 | 
						|
			end
 | 
						|
 | 
						|
			if v.freeze then
 | 
						|
				FreezeEntityPosition(spawnedped, true)
 | 
						|
			end
 | 
						|
 | 
						|
			if v.invincible then
 | 
						|
				SetEntityInvincible(spawnedped, true)
 | 
						|
			end
 | 
						|
 | 
						|
			if v.blockevents then
 | 
						|
				SetBlockingOfNonTemporaryEvents(spawnedped, true)
 | 
						|
			end
 | 
						|
 | 
						|
			if v.animDict and v.anim then
 | 
						|
				RequestAnimDict(v.animDict)
 | 
						|
				while not HasAnimDictLoaded(v.animDict) do
 | 
						|
					Wait(0)
 | 
						|
				end
 | 
						|
 | 
						|
				TaskPlayAnim(spawnedped, v.animDict, v.anim, 8.0, 0, -1, v.flag or 1, 0, false, false, false)
 | 
						|
			end
 | 
						|
 | 
						|
			if v.scenario then
 | 
						|
				SetPedCanPlayAmbientAnims(spawnedped, true)
 | 
						|
				TaskStartScenarioInPlace(spawnedped, v.scenario, 0, true)
 | 
						|
			end
 | 
						|
 | 
						|
			if v.pedrelations then
 | 
						|
				if type(v.pedrelations.groupname) ~= 'string' then error(v.pedrelations.groupname .. ' is not a string') end
 | 
						|
 | 
						|
				local pedgrouphash = joaat(v.pedrelations.groupname)
 | 
						|
 | 
						|
				if not DoesRelationshipGroupExist(pedgrouphash) then
 | 
						|
					AddRelationshipGroup(v.pedrelations.groupname)
 | 
						|
				end
 | 
						|
 | 
						|
				SetPedRelationshipGroupHash(spawnedped, pedgrouphash)
 | 
						|
				if v.pedrelations.toplayer then
 | 
						|
					SetRelationshipBetweenGroups(v.pedrelations.toplayer, pedgrouphash, joaat('PLAYER'))
 | 
						|
				end
 | 
						|
 | 
						|
				if v.pedrelations.toowngroup then
 | 
						|
					SetRelationshipBetweenGroups(v.pedrelations.toowngroup, pedgrouphash, pedgrouphash)
 | 
						|
				end
 | 
						|
			end
 | 
						|
 | 
						|
			if v.weapon then
 | 
						|
				if type(v.weapon.name) == 'string' then v.weapon.name = joaat(v.weapon.name) end
 | 
						|
 | 
						|
				if IsWeaponValid(v.weapon.name) then
 | 
						|
					SetCanPedEquipWeapon(spawnedped, v.weapon.name, true)
 | 
						|
					GiveWeaponToPed(spawnedped, v.weapon.name, v.weapon.ammo, v.weapon.hidden or false, true)
 | 
						|
					SetPedCurrentWeaponVisible(spawnedped, not v.weapon.hidden or false, true)
 | 
						|
				end
 | 
						|
			end
 | 
						|
 | 
						|
			if v.target then
 | 
						|
				if v.target.useModel then
 | 
						|
					AddTargetModel(v.model, {
 | 
						|
						options = v.target.options,
 | 
						|
						distance = v.target.distance
 | 
						|
					})
 | 
						|
				else
 | 
						|
					AddTargetEntity(spawnedped, {
 | 
						|
						options = v.target.options,
 | 
						|
						distance = v.target.distance
 | 
						|
					})
 | 
						|
				end
 | 
						|
			end
 | 
						|
 | 
						|
			if v.action then
 | 
						|
				v.action(v)
 | 
						|
			end
 | 
						|
 | 
						|
			Config.Peds[k].currentpednumber = spawnedped
 | 
						|
		end
 | 
						|
	end
 | 
						|
	pedsReady = true
 | 
						|
end
 | 
						|
 | 
						|
function DeletePeds()
 | 
						|
	if not pedsReady or not next(Config.Peds) then return end
 | 
						|
	for k, v in pairs(Config.Peds) do
 | 
						|
		DeletePed(v.currentpednumber)
 | 
						|
		Config.Peds[k].currentpednumber = 0
 | 
						|
	end
 | 
						|
	pedsReady = false
 | 
						|
end
 | 
						|
 | 
						|
exports('DeletePeds', DeletePeds)
 | 
						|
 | 
						|
local function SpawnPed(data)
 | 
						|
	local spawnedped
 | 
						|
	local key, value = next(data)
 | 
						|
	if type(value) == 'table' and type(key) ~= 'string' then
 | 
						|
		for _, v in pairs(data) do
 | 
						|
			if v.spawnNow then
 | 
						|
				RequestModel(v.model)
 | 
						|
				while not HasModelLoaded(v.model) do
 | 
						|
					Wait(0)
 | 
						|
				end
 | 
						|
 | 
						|
				if type(v.model) == 'string' then v.model = joaat(v.model) end
 | 
						|
 | 
						|
				if v.minusOne then
 | 
						|
					spawnedped = CreatePed(0, v.model, v.coords.x, v.coords.y, v.coords.z - 1.0, v.coords.w or 0.0,
 | 
						|
						v.networked or false, true)
 | 
						|
				else
 | 
						|
					spawnedped = CreatePed(0, v.model, v.coords.x, v.coords.y, v.coords.z, v.coords.w or 0.0,
 | 
						|
						v.networked or false, true)
 | 
						|
				end
 | 
						|
 | 
						|
				if v.freeze then
 | 
						|
					FreezeEntityPosition(spawnedped, true)
 | 
						|
				end
 | 
						|
 | 
						|
				if v.invincible then
 | 
						|
					SetEntityInvincible(spawnedped, true)
 | 
						|
				end
 | 
						|
 | 
						|
				if v.blockevents then
 | 
						|
					SetBlockingOfNonTemporaryEvents(spawnedped, true)
 | 
						|
				end
 | 
						|
 | 
						|
				if v.animDict and v.anim then
 | 
						|
					RequestAnimDict(v.animDict)
 | 
						|
					while not HasAnimDictLoaded(v.animDict) do
 | 
						|
						Wait(0)
 | 
						|
					end
 | 
						|
 | 
						|
					TaskPlayAnim(spawnedped, v.animDict, v.anim, 8.0, 0, -1, v.flag or 1, 0, false, false, false)
 | 
						|
				end
 | 
						|
 | 
						|
				if v.scenario then
 | 
						|
					SetPedCanPlayAmbientAnims(spawnedped, true)
 | 
						|
					TaskStartScenarioInPlace(spawnedped, v.scenario, 0, true)
 | 
						|
				end
 | 
						|
 | 
						|
				if v.pedrelations and type(v.pedrelations.groupname) == 'string' then
 | 
						|
					if type(v.pedrelations.groupname) ~= 'string' then
 | 
						|
						error(v.pedrelations.groupname ..
 | 
						|
							' is not a string')
 | 
						|
					end
 | 
						|
 | 
						|
					local pedgrouphash = joaat(v.pedrelations.groupname)
 | 
						|
 | 
						|
					if not DoesRelationshipGroupExist(pedgrouphash) then
 | 
						|
						AddRelationshipGroup(v.pedrelations.groupname)
 | 
						|
					end
 | 
						|
 | 
						|
					SetPedRelationshipGroupHash(spawnedped, pedgrouphash)
 | 
						|
					if v.pedrelations.toplayer then
 | 
						|
						SetRelationshipBetweenGroups(v.pedrelations.toplayer, pedgrouphash, joaat('PLAYER'))
 | 
						|
					end
 | 
						|
 | 
						|
					if v.pedrelations.toowngroup then
 | 
						|
						SetRelationshipBetweenGroups(v.pedrelations.toowngroup, pedgrouphash, pedgrouphash)
 | 
						|
					end
 | 
						|
				end
 | 
						|
 | 
						|
				if v.weapon then
 | 
						|
					if type(v.weapon.name) == 'string' then v.weapon.name = joaat(v.weapon.name) end
 | 
						|
 | 
						|
					if IsWeaponValid(v.weapon.name) then
 | 
						|
						SetCanPedEquipWeapon(spawnedped, v.weapon.name, true)
 | 
						|
						GiveWeaponToPed(spawnedped, v.weapon.name, v.weapon.ammo, v.weapon.hidden or false, true)
 | 
						|
						SetPedCurrentWeaponVisible(spawnedped, not v.weapon.hidden or false, true)
 | 
						|
					end
 | 
						|
				end
 | 
						|
 | 
						|
				if v.target then
 | 
						|
					if v.target.useModel then
 | 
						|
						AddTargetModel(v.model, {
 | 
						|
							options = v.target.options,
 | 
						|
							distance = v.target.distance
 | 
						|
						})
 | 
						|
					else
 | 
						|
						AddTargetEntity(spawnedped, {
 | 
						|
							options = v.target.options,
 | 
						|
							distance = v.target.distance
 | 
						|
						})
 | 
						|
					end
 | 
						|
				end
 | 
						|
 | 
						|
				v.currentpednumber = spawnedped
 | 
						|
 | 
						|
				if v.action then
 | 
						|
					v.action(v)
 | 
						|
				end
 | 
						|
			end
 | 
						|
 | 
						|
			local nextnumber = #Config.Peds + 1
 | 
						|
			if nextnumber <= 0 then nextnumber = 1 end
 | 
						|
 | 
						|
			Config.Peds[nextnumber] = v
 | 
						|
		end
 | 
						|
	else
 | 
						|
		if data.spawnNow then
 | 
						|
			RequestModel(data.model)
 | 
						|
			while not HasModelLoaded(data.model) do
 | 
						|
				Wait(0)
 | 
						|
			end
 | 
						|
 | 
						|
			if type(data.model) == 'string' then data.model = joaat(data.model) end
 | 
						|
 | 
						|
			if data.minusOne then
 | 
						|
				spawnedped = CreatePed(0, data.model, data.coords.x, data.coords.y, data.coords.z - 1.0, data.coords.w,
 | 
						|
					data.networked or false, true)
 | 
						|
			else
 | 
						|
				spawnedped = CreatePed(0, data.model, data.coords.x, data.coords.y, data.coords.z, data.coords.w,
 | 
						|
					data.networked or false, true)
 | 
						|
			end
 | 
						|
 | 
						|
			if data.freeze then
 | 
						|
				FreezeEntityPosition(spawnedped, true)
 | 
						|
			end
 | 
						|
 | 
						|
			if data.invincible then
 | 
						|
				SetEntityInvincible(spawnedped, true)
 | 
						|
			end
 | 
						|
 | 
						|
			if data.blockevents then
 | 
						|
				SetBlockingOfNonTemporaryEvents(spawnedped, true)
 | 
						|
			end
 | 
						|
 | 
						|
			if data.animDict and data.anim then
 | 
						|
				RequestAnimDict(data.animDict)
 | 
						|
				while not HasAnimDictLoaded(data.animDict) do
 | 
						|
					Wait(0)
 | 
						|
				end
 | 
						|
 | 
						|
				TaskPlayAnim(spawnedped, data.animDict, data.anim, 8.0, 0, -1, data.flag or 1, 0, false, false, false)
 | 
						|
			end
 | 
						|
 | 
						|
			if data.scenario then
 | 
						|
				SetPedCanPlayAmbientAnims(spawnedped, true)
 | 
						|
				TaskStartScenarioInPlace(spawnedped, data.scenario, 0, true)
 | 
						|
			end
 | 
						|
 | 
						|
			if data.pedrelations then
 | 
						|
				if type(data.pedrelations.groupname) ~= 'string' then
 | 
						|
					error(data.pedrelations.groupname ..
 | 
						|
						' is not a string')
 | 
						|
				end
 | 
						|
 | 
						|
				local pedgrouphash = joaat(data.pedrelations.groupname)
 | 
						|
 | 
						|
				if not DoesRelationshipGroupExist(pedgrouphash) then
 | 
						|
					AddRelationshipGroup(data.pedrelations.groupname)
 | 
						|
				end
 | 
						|
 | 
						|
				SetPedRelationshipGroupHash(spawnedped, pedgrouphash)
 | 
						|
				if data.pedrelations.toplayer then
 | 
						|
					SetRelationshipBetweenGroups(data.pedrelations.toplayer, pedgrouphash, joaat('PLAYER'))
 | 
						|
				end
 | 
						|
 | 
						|
				if data.pedrelations.toowngroup then
 | 
						|
					SetRelationshipBetweenGroups(data.pedrelations.toowngroup, pedgrouphash, pedgrouphash)
 | 
						|
				end
 | 
						|
			end
 | 
						|
 | 
						|
			if data.weapon then
 | 
						|
				if type(data.weapon.name) == 'string' then data.weapon.name = joaat(data.weapon.name) end
 | 
						|
 | 
						|
				if IsWeaponValid(data.weapon.name) then
 | 
						|
					SetCanPedEquipWeapon(spawnedped, data.weapon.name, true)
 | 
						|
					GiveWeaponToPed(spawnedped, data.weapon.name, data.weapon.ammo, data.weapon.hidden or false, true)
 | 
						|
					SetPedCurrentWeaponVisible(spawnedped, not data.weapon.hidden or false, true)
 | 
						|
				end
 | 
						|
			end
 | 
						|
 | 
						|
			if data.target then
 | 
						|
				if data.target.useModel then
 | 
						|
					AddTargetModel(data.model, {
 | 
						|
						options = data.target.options,
 | 
						|
						distance = data.target.distance
 | 
						|
					})
 | 
						|
				else
 | 
						|
					AddTargetEntity(spawnedped, {
 | 
						|
						options = data.target.options,
 | 
						|
						distance = data.target.distance
 | 
						|
					})
 | 
						|
				end
 | 
						|
			end
 | 
						|
 | 
						|
			data.currentpednumber = spawnedped
 | 
						|
 | 
						|
			if data.action then
 | 
						|
				data.action(data)
 | 
						|
			end
 | 
						|
		end
 | 
						|
 | 
						|
		local nextnumber = #Config.Peds + 1
 | 
						|
		if nextnumber <= 0 then nextnumber = 1 end
 | 
						|
 | 
						|
		Config.Peds[nextnumber] = data
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
exports('SpawnPed', SpawnPed)
 | 
						|
 | 
						|
local function RemovePed(peds)
 | 
						|
	if type(peds) == 'table' then
 | 
						|
		for k, v in pairs(peds) do
 | 
						|
			DeletePed(v)
 | 
						|
			if Config.Peds[k] then Config.Peds[k].currentpednumber = 0 end
 | 
						|
		end
 | 
						|
	elseif type(peds) == 'number' then
 | 
						|
		DeletePed(peds)
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
exports('RemoveSpawnedPed', RemovePed)
 | 
						|
 | 
						|
-- Misc. Exports
 | 
						|
 | 
						|
local function RemoveGlobalPed(labels) RemoveGlobalType(1, labels) end
 | 
						|
exports('RemoveGlobalPed', RemoveGlobalPed)
 | 
						|
 | 
						|
local function RemoveGlobalVehicle(labels) RemoveGlobalType(2, labels) end
 | 
						|
exports('RemoveGlobalVehicle', RemoveGlobalVehicle)
 | 
						|
 | 
						|
local function RemoveGlobalObject(labels) RemoveGlobalType(3, labels) end
 | 
						|
exports('RemoveGlobalObject', RemoveGlobalObject)
 | 
						|
 | 
						|
local function IsTargetActive() return targetActive end
 | 
						|
exports('IsTargetActive', IsTargetActive)
 | 
						|
 | 
						|
local function IsTargetSuccess() return success end
 | 
						|
exports('IsTargetSuccess', IsTargetSuccess)
 | 
						|
 | 
						|
local function GetGlobalTypeData(type, label) return Types[type][label] end
 | 
						|
exports('GetGlobalTypeData', GetGlobalTypeData)
 | 
						|
 | 
						|
local function GetZoneData(name) return Zones[name] end
 | 
						|
exports('GetZoneData', GetZoneData)
 | 
						|
 | 
						|
local function GetTargetBoneData(bone, label) return Bones.Options[bone][label] end
 | 
						|
exports('GetTargetBoneData', GetTargetBoneData)
 | 
						|
 | 
						|
local function GetTargetEntityData(entity, label) return Entities[entity][label] end
 | 
						|
exports('GetTargetEntityData', GetTargetEntityData)
 | 
						|
 | 
						|
local function GetTargetModelData(model, label) return Models[model][label] end
 | 
						|
exports('GetTargetModelData', GetTargetModelData)
 | 
						|
 | 
						|
local function GetGlobalPedData(label) return Types[1][label] end
 | 
						|
exports('GetGlobalPedData', GetGlobalPedData)
 | 
						|
 | 
						|
local function GetGlobalVehicleData(label) return Types[2][label] end
 | 
						|
exports('GetGlobalVehicleData', GetGlobalVehicleData)
 | 
						|
 | 
						|
local function GetGlobalObjectData(label) return Types[3][label] end
 | 
						|
exports('GetGlobalObjectData', GetGlobalObjectData)
 | 
						|
 | 
						|
local function GetGlobalPlayerData(label) return Players[label] end
 | 
						|
exports('GetGlobalPlayerData', GetGlobalPlayerData)
 | 
						|
 | 
						|
local function UpdateGlobalTypeData(type, label, data) Types[type][label] = data end
 | 
						|
exports('UpdateGlobalTypeData', UpdateGlobalTypeData)
 | 
						|
 | 
						|
local function UpdateZoneData(name, data)
 | 
						|
	data.distance = data.distance or Config.MaxDistance
 | 
						|
	Zones[name].targetoptions = data
 | 
						|
end
 | 
						|
exports('UpdateZoneData', UpdateZoneData)
 | 
						|
 | 
						|
local function UpdateTargetBoneData(bone, label, data) Bones.Options[bone][label] = data end
 | 
						|
exports('UpdateTargetBoneData', UpdateTargetBoneData)
 | 
						|
 | 
						|
local function UpdateTargetEntityData(entity, label, data) Entities[entity][label] = data end
 | 
						|
exports('UpdateTargetEntityData', UpdateTargetEntityData)
 | 
						|
 | 
						|
local function UpdateTargetModelData(model, label, data) Models[model][label] = data end
 | 
						|
exports('UpdateTargetModelData', UpdateTargetModelData)
 | 
						|
 | 
						|
local function UpdateGlobalPedData(label, data) Types[1][label] = data end
 | 
						|
exports('UpdateGlobalPedData', UpdateGlobalPedData)
 | 
						|
 | 
						|
local function UpdateGlobalVehicleData(label, data) Types[2][label] = data end
 | 
						|
exports('UpdateGlobalVehicleData', UpdateGlobalVehicleData)
 | 
						|
 | 
						|
local function UpdateGlobalObjectData(label, data) Types[3][label] = data end
 | 
						|
exports('UpdateGlobalObjectData', UpdateGlobalObjectData)
 | 
						|
 | 
						|
local function UpdateGlobalPlayerData(label, data) Players[label] = data end
 | 
						|
exports('UpdateGlobalPlayerData', UpdateGlobalPlayerData)
 | 
						|
 | 
						|
local function GetPeds() return Config.Peds end
 | 
						|
exports('GetPeds', GetPeds)
 | 
						|
 | 
						|
local function UpdatePedsData(index, data) Config.Peds[index] = data end
 | 
						|
exports('UpdatePedsData', UpdatePedsData)
 | 
						|
 | 
						|
local function AllowTargeting(bool)
 | 
						|
	allowTarget = bool
 | 
						|
 | 
						|
	if allowTarget then return end
 | 
						|
 | 
						|
	DisableTarget(true)
 | 
						|
end
 | 
						|
exports('AllowTargeting', AllowTargeting)
 | 
						|
 | 
						|
-- NUI Callbacks
 | 
						|
 | 
						|
RegisterNUICallback('selectTarget', function(option, cb)
 | 
						|
	option = tonumber(option) or option
 | 
						|
	SetNuiFocus(false, false)
 | 
						|
	SetNuiFocusKeepInput(false)
 | 
						|
	Wait(100)
 | 
						|
	targetActive, success, hasFocus = false, false, false
 | 
						|
	if not next(sendData) then return end
 | 
						|
	local data = sendData[option]
 | 
						|
	if not data then return end
 | 
						|
	table_wipe(sendData)
 | 
						|
	CreateThread(function()
 | 
						|
		Wait(0)
 | 
						|
		if data.entity ~= nil then
 | 
						|
			data.coords = GetEntityCoords(data.entity)
 | 
						|
		end
 | 
						|
		if data.action then
 | 
						|
			data.action(data.entity)
 | 
						|
		elseif data.event then
 | 
						|
			if data.type == 'client' then
 | 
						|
				TriggerEvent(data.event, data)
 | 
						|
			elseif data.type == 'server' then
 | 
						|
				TriggerServerEvent(data.event, data)
 | 
						|
			elseif data.type == 'command' then
 | 
						|
				ExecuteCommand(data.event)
 | 
						|
			elseif data.type == 'qbcommand' then
 | 
						|
				TriggerServerEvent('QBCore:CallCommand', data.event, data)
 | 
						|
			else
 | 
						|
				TriggerEvent(data.event, data)
 | 
						|
			end
 | 
						|
		else
 | 
						|
			error('No trigger setup')
 | 
						|
		end
 | 
						|
	end)
 | 
						|
	cb('ok')
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNUICallback('closeTarget', function(_, cb)
 | 
						|
	SetNuiFocus(false, false)
 | 
						|
	SetNuiFocusKeepInput(false)
 | 
						|
	Wait(100)
 | 
						|
	targetActive, success, hasFocus = false, false, false
 | 
						|
	cb('ok')
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNUICallback('leftTarget', function(_, cb)
 | 
						|
	if Config.Toggle then
 | 
						|
		SetNuiFocus(false, false)
 | 
						|
		SetNuiFocusKeepInput(false)
 | 
						|
		Wait(100)
 | 
						|
		table_wipe(sendData)
 | 
						|
		success, hasFocus = false, false
 | 
						|
	else
 | 
						|
		DisableTarget(true)
 | 
						|
	end
 | 
						|
	cb('ok')
 | 
						|
end)
 | 
						|
 | 
						|
-- Startup thread
 | 
						|
 | 
						|
CreateThread(function()
 | 
						|
	if Config.Toggle then
 | 
						|
		RegisterCommand('playerTarget', function()
 | 
						|
			if targetActive then
 | 
						|
				DisableTarget(true)
 | 
						|
			else
 | 
						|
				CreateThread(EnableTarget)
 | 
						|
			end
 | 
						|
		end, false)
 | 
						|
		RegisterKeyMapping('playerTarget', 'Toggle targeting', 'keyboard', Config.OpenKey)
 | 
						|
		TriggerEvent('chat:removeSuggestion', '/playerTarget')
 | 
						|
	else
 | 
						|
		RegisterCommand('+playerTarget', function()
 | 
						|
			CreateThread(EnableTarget)
 | 
						|
		end, false)
 | 
						|
		RegisterCommand('-playerTarget', DisableTarget, false)
 | 
						|
		RegisterKeyMapping('+playerTarget', 'Enable targeting', 'keyboard', Config.OpenKey)
 | 
						|
		TriggerEvent('chat:removeSuggestion', '/+playerTarget')
 | 
						|
		TriggerEvent('chat:removeSuggestion', '/-playerTarget')
 | 
						|
	end
 | 
						|
 | 
						|
	if table.type(Config.CircleZones) ~= 'empty' then
 | 
						|
		for _, v in pairs(Config.CircleZones) do
 | 
						|
			AddCircleZone(v.name, v.coords, v.radius, {
 | 
						|
				name = v.name,
 | 
						|
				debugPoly = v.debugPoly,
 | 
						|
				useZ = v.useZ,
 | 
						|
			}, {
 | 
						|
				options = v.options,
 | 
						|
				distance = v.distance
 | 
						|
			})
 | 
						|
		end
 | 
						|
	end
 | 
						|
 | 
						|
	if table.type(Config.BoxZones) ~= 'empty' then
 | 
						|
		for _, v in pairs(Config.BoxZones) do
 | 
						|
			AddBoxZone(v.name, v.coords, v.length, v.width, {
 | 
						|
				name = v.name,
 | 
						|
				heading = v.heading,
 | 
						|
				debugPoly = v.debugPoly,
 | 
						|
				minZ = v.minZ,
 | 
						|
				maxZ = v.maxZ
 | 
						|
			}, {
 | 
						|
				options = v.options,
 | 
						|
				distance = v.distance
 | 
						|
			})
 | 
						|
		end
 | 
						|
	end
 | 
						|
 | 
						|
	if table.type(Config.PolyZones) ~= 'empty' then
 | 
						|
		for _, v in pairs(Config.PolyZones) do
 | 
						|
			AddPolyZone(v.name, v.points, {
 | 
						|
				name = v.name,
 | 
						|
				debugPoly = v.debugPoly,
 | 
						|
				minZ = v.minZ,
 | 
						|
				maxZ = v.maxZ
 | 
						|
			}, {
 | 
						|
				options = v.options,
 | 
						|
				distance = v.distance
 | 
						|
			})
 | 
						|
		end
 | 
						|
	end
 | 
						|
 | 
						|
	if table.type(Config.TargetBones) ~= 'empty' then
 | 
						|
		for _, v in pairs(Config.TargetBones) do
 | 
						|
			AddTargetBone(v.bones, {
 | 
						|
				options = v.options,
 | 
						|
				distance = v.distance
 | 
						|
			})
 | 
						|
		end
 | 
						|
	end
 | 
						|
 | 
						|
	if table.type(Config.TargetModels) ~= 'empty' then
 | 
						|
		for _, v in pairs(Config.TargetModels) do
 | 
						|
			AddTargetModel(v.models, {
 | 
						|
				options = v.options,
 | 
						|
				distance = v.distance
 | 
						|
			})
 | 
						|
		end
 | 
						|
	end
 | 
						|
 | 
						|
	if table.type(Config.GlobalPedOptions) ~= 'empty' then
 | 
						|
		AddGlobalPed(Config.GlobalPedOptions)
 | 
						|
	end
 | 
						|
 | 
						|
	if table.type(Config.GlobalVehicleOptions) ~= 'empty' then
 | 
						|
		AddGlobalVehicle(Config.GlobalVehicleOptions)
 | 
						|
	end
 | 
						|
 | 
						|
	if table.type(Config.GlobalObjectOptions) ~= 'empty' then
 | 
						|
		AddGlobalObject(Config.GlobalObjectOptions)
 | 
						|
	end
 | 
						|
 | 
						|
	if table.type(Config.GlobalPlayerOptions) ~= 'empty' then
 | 
						|
		AddGlobalPlayer(Config.GlobalPlayerOptions)
 | 
						|
	end
 | 
						|
end)
 | 
						|
 | 
						|
-- Events
 | 
						|
 | 
						|
-- This is to make sure the peds spawn on restart too instead of only when you load/log-in.
 | 
						|
AddEventHandler('onResourceStart', function(resource)
 | 
						|
	if resource ~= currentResourceName then return end
 | 
						|
	SpawnPeds()
 | 
						|
end)
 | 
						|
 | 
						|
-- This will delete the peds when the resource stops to make sure you don't have random peds walking
 | 
						|
AddEventHandler('onResourceStop', function(resource)
 | 
						|
	if resource ~= currentResourceName then return end
 | 
						|
	DeletePeds()
 | 
						|
end)
 | 
						|
 | 
						|
-- Debug Option
 | 
						|
 | 
						|
if Config.Debug then Load('debug') end
 | 
						|
 | 
						|
-- qtarget interoperability
 | 
						|
 | 
						|
local qtargetExports = {
 | 
						|
	['raycast'] = RaycastCamera,
 | 
						|
	['DisableNUI'] = DisableNUI,
 | 
						|
	['LeaveTarget'] = LeftTarget,
 | 
						|
	['DisableTarget'] = DisableTarget,
 | 
						|
	['DrawOutlineEntity'] = DrawOutlineEntity,
 | 
						|
	['CheckEntity'] = CheckEntity,
 | 
						|
	['CheckBones'] = CheckBones,
 | 
						|
	['AddCircleZone'] = AddCircleZone,
 | 
						|
	['AddBoxZone'] = AddBoxZone,
 | 
						|
	['AddPolyZone'] = AddPolyZone,
 | 
						|
	['AddComboZone'] = AddComboZone,
 | 
						|
	['AddEntityZone'] = AddEntityZone,
 | 
						|
	['RemoveZone'] = RemoveZone,
 | 
						|
	['AddTargetBone'] = AddTargetBone,
 | 
						|
	['RemoveTargetBone'] = RemoveTargetBone,
 | 
						|
	['AddTargetEntity'] = AddTargetEntity,
 | 
						|
	['RemoveTargetEntity'] = RemoveTargetEntity,
 | 
						|
	['AddTargetModel'] = AddTargetModel,
 | 
						|
	['RemoveTargetModel'] = RemoveTargetModel,
 | 
						|
	['Ped'] = AddGlobalPed,
 | 
						|
	['Vehicle'] = AddGlobalVehicle,
 | 
						|
	['Object'] = AddGlobalObject,
 | 
						|
	['Player'] = AddGlobalPlayer,
 | 
						|
	['RemovePed'] = RemoveGlobalPed,
 | 
						|
	['RemoveVehicle'] = RemoveGlobalVehicle,
 | 
						|
	['RemoveObject'] = RemoveGlobalObject,
 | 
						|
	['RemovePlayer'] = RemoveGlobalPlayer,
 | 
						|
	['IsTargetActive'] = IsTargetActive,
 | 
						|
	['IsTargetSuccess'] = IsTargetSuccess,
 | 
						|
	['GetType'] = GetGlobalTypeData,
 | 
						|
	['GetZone'] = GetZoneData,
 | 
						|
	['GetTargetBone'] = GetTargetBoneData,
 | 
						|
	['GetTargetEntity'] = GetTargetEntityData,
 | 
						|
	['GetTargetModel'] = GetTargetModelData,
 | 
						|
	['GetPed'] = GetGlobalPedData,
 | 
						|
	['GetVehicle'] = GetGlobalVehicleData,
 | 
						|
	['GetObject'] = GetGlobalObjectData,
 | 
						|
	['GetPlayer'] = GetGlobalPlayerData,
 | 
						|
	['UpdateType'] = UpdateGlobalTypeData,
 | 
						|
	['UpdateZoneOptions'] = UpdateZoneData,
 | 
						|
	['UpdateTargetBone'] = UpdateTargetBoneData,
 | 
						|
	['UpdateTargetEntity'] = UpdateTargetEntityData,
 | 
						|
	['UpdateTargetModel'] = UpdateTargetModelData,
 | 
						|
	['UpdatePed'] = UpdateGlobalPedData,
 | 
						|
	['UpdateVehicle'] = UpdateGlobalVehicleData,
 | 
						|
	['UpdateObject'] = UpdateGlobalObjectData,
 | 
						|
	['UpdatePlayer'] = UpdateGlobalPlayerData,
 | 
						|
	['AllowTargeting'] = AllowTargeting
 | 
						|
}
 | 
						|
 | 
						|
for exportName, func in pairs(qtargetExports) do
 | 
						|
	AddEventHandler(('__cfx_export_qtarget_%s'):format(exportName), function(setCB)
 | 
						|
		setCB(func)
 | 
						|
	end)
 | 
						|
end
 |