forked from Simnation/Main
452 lines
18 KiB
Lua
452 lines
18 KiB
Lua
local FrozenEntities = {}
|
|
local EntityViewDistance = 10
|
|
local EntityViewEnabled = false
|
|
local EntityFreeAim = false
|
|
local EntityPedView = false
|
|
local EntityObjectView = false
|
|
local EntityVehicleView = false
|
|
local FreeAimEntity = nil
|
|
|
|
-- Configurable values
|
|
local FreeAimInfoBoxX = 0.60 -- X-axis (0.0 being left, 1.0 being right position of the screen)
|
|
local FreeAimInfoBoxY = 0.02 -- Y-axis (0.0 being up, 1.0 being down position of the screen)
|
|
local useKph = true -- True to display KPH or false to display MPH
|
|
|
|
local CanEntityBeUsed = function(ped)
|
|
if ped == PlayerPedId() then
|
|
return false
|
|
end
|
|
return true
|
|
end
|
|
|
|
local RoundFloat = function(number, num)
|
|
return math.floor(number * math.pow(10, num) + 0.5) / math.pow(10, num)
|
|
end
|
|
|
|
local RoundVector3 = function(vector, num)
|
|
return 'vector3(' .. RoundFloat(vector.x, num) .. ', ' .. RoundFloat(vector.y, num) .. ', ' .. RoundFloat(vector.z, num) .. ')'
|
|
end
|
|
|
|
|
|
local RelationshipTypes = { ['0'] = 'Companion', ['1'] = 'Respect', ['2'] = 'Like', ['3'] = 'Neutral', ['4'] = 'Dislike', ['5'] = 'Hate', ['255'] = 'Pedestrians' }
|
|
local GetPedRelationshipType = function(value)
|
|
value = tostring(value)
|
|
return RelationshipTypes[value] or 'Unknown'
|
|
end
|
|
|
|
local DrawTitle = function(text)
|
|
SetTextScale(0.50, 0.50)
|
|
SetTextFont(4)
|
|
SetTextDropshadow(1.0, 0, 0, 0, 255)
|
|
SetTextColour(255, 255, 255, 215)
|
|
SetTextJustification(0)
|
|
BeginTextCommandDisplayText('STRING')
|
|
AddTextComponentSubstringPlayerName(text)
|
|
EndTextCommandDisplayText(0.5, 0.02)
|
|
end
|
|
|
|
local RotationToDirection = function(rotation)
|
|
local adjustedRotation = {
|
|
x = (math.pi / 180) * rotation.x,
|
|
y = (math.pi / 180) * rotation.y,
|
|
z = (math.pi / 180) * rotation.z
|
|
}
|
|
local direction = {
|
|
x = -math.sin(adjustedRotation.z) * math.abs(math.cos(adjustedRotation.x)),
|
|
y = math.cos(adjustedRotation.z) * math.abs(math.cos(adjustedRotation.x)),
|
|
z = math.sin(adjustedRotation.x)
|
|
}
|
|
return direction
|
|
end
|
|
|
|
local RayCastGamePlayCamera = function(distance)
|
|
-- Checks to see if the Gameplay Cam is Rendering or another is rendering (no clip functionality)
|
|
local currentRenderingCam = false
|
|
if not IsGameplayCamRendering() then
|
|
currentRenderingCam = GetRenderingCam()
|
|
end
|
|
|
|
local cameraRotation = not currentRenderingCam and GetGameplayCamRot() or GetCamRot(currentRenderingCam, 2)
|
|
local cameraCoord = not currentRenderingCam and GetGameplayCamCoord() or GetCamCoord(currentRenderingCam)
|
|
local direction = RotationToDirection(cameraRotation)
|
|
local destination = {
|
|
x = cameraCoord.x + direction.x * distance,
|
|
y = cameraCoord.y + direction.y * distance,
|
|
z = cameraCoord.z + direction.z * distance
|
|
}
|
|
local _, b, c, _, e = GetShapeTestResult(StartShapeTestRay(cameraCoord.x, cameraCoord.y, cameraCoord.z, destination.x, destination.y, destination.z, -1, PlayerPedId(), 0))
|
|
return b, c, e
|
|
end
|
|
|
|
local DrawEntityBoundingBox = function(entity, color)
|
|
local model = GetEntityModel(entity)
|
|
local min, max = GetModelDimensions(model)
|
|
local rightVector, forwardVector, upVector, position = GetEntityMatrix(entity)
|
|
|
|
-- Calculate size
|
|
local dim = {
|
|
x = 0.5 * (max.x - min.x),
|
|
y = 0.5 * (max.y - min.y),
|
|
z = 0.5 * (max.z - min.z)
|
|
}
|
|
|
|
local FUR = {
|
|
x = position.x + dim.y * rightVector.x + dim.x * forwardVector.x + dim.z * upVector.x,
|
|
y = position.y + dim.y * rightVector.y + dim.x * forwardVector.y + dim.z * upVector.y,
|
|
z = 0
|
|
}
|
|
|
|
local _, FUR_z = GetGroundZFor_3dCoord(FUR.x, FUR.y, 1000.0, 0)
|
|
FUR.z = FUR_z
|
|
FUR.z = FUR.z + 2 * dim.z
|
|
|
|
local BLL = {
|
|
x = position.x - dim.y * rightVector.x - dim.x * forwardVector.x - dim.z * upVector.x,
|
|
y = position.y - dim.y * rightVector.y - dim.x * forwardVector.y - dim.z * upVector.y,
|
|
z = 0
|
|
}
|
|
local _, BLL_z = GetGroundZFor_3dCoord(FUR.x, FUR.y, 1000.0, 0)
|
|
BLL.z = BLL_z
|
|
|
|
-- DEBUG
|
|
local edge1 = BLL
|
|
local edge5 = FUR
|
|
|
|
local edge2 = {
|
|
x = edge1.x + 2 * dim.y * rightVector.x,
|
|
y = edge1.y + 2 * dim.y * rightVector.y,
|
|
z = edge1.z + 2 * dim.y * rightVector.z
|
|
}
|
|
|
|
local edge3 = {
|
|
x = edge2.x + 2 * dim.z * upVector.x,
|
|
y = edge2.y + 2 * dim.z * upVector.y,
|
|
z = edge2.z + 2 * dim.z * upVector.z
|
|
}
|
|
|
|
local edge4 = {
|
|
x = edge1.x + 2 * dim.z * upVector.x,
|
|
y = edge1.y + 2 * dim.z * upVector.y,
|
|
z = edge1.z + 2 * dim.z * upVector.z
|
|
}
|
|
|
|
local edge6 = {
|
|
x = edge5.x - 2 * dim.y * rightVector.x,
|
|
y = edge5.y - 2 * dim.y * rightVector.y,
|
|
z = edge5.z - 2 * dim.y * rightVector.z
|
|
}
|
|
|
|
local edge7 = {
|
|
x = edge6.x - 2 * dim.z * upVector.x,
|
|
y = edge6.y - 2 * dim.z * upVector.y,
|
|
z = edge6.z - 2 * dim.z * upVector.z
|
|
}
|
|
|
|
local edge8 = {
|
|
x = edge5.x - 2 * dim.z * upVector.x,
|
|
y = edge5.y - 2 * dim.z * upVector.y,
|
|
z = edge5.z - 2 * dim.z * upVector.z
|
|
}
|
|
color = (color == nil and { r = 255, g = 255, b = 255, a = 255 } or color)
|
|
DrawLine(edge1.x, edge1.y, edge1.z, edge2.x, edge2.y, edge2.z, color.r, color.g, color.b, color.a)
|
|
DrawLine(edge1.x, edge1.y, edge1.z, edge4.x, edge4.y, edge4.z, color.r, color.g, color.b, color.a)
|
|
DrawLine(edge2.x, edge2.y, edge2.z, edge3.x, edge3.y, edge3.z, color.r, color.g, color.b, color.a)
|
|
DrawLine(edge3.x, edge3.y, edge3.z, edge4.x, edge4.y, edge4.z, color.r, color.g, color.b, color.a)
|
|
DrawLine(edge5.x, edge5.y, edge5.z, edge6.x, edge6.y, edge6.z, color.r, color.g, color.b, color.a)
|
|
DrawLine(edge5.x, edge5.y, edge5.z, edge8.x, edge8.y, edge8.z, color.r, color.g, color.b, color.a)
|
|
DrawLine(edge6.x, edge6.y, edge6.z, edge7.x, edge7.y, edge7.z, color.r, color.g, color.b, color.a)
|
|
DrawLine(edge7.x, edge7.y, edge7.z, edge8.x, edge8.y, edge8.z, color.r, color.g, color.b, color.a)
|
|
DrawLine(edge1.x, edge1.y, edge1.z, edge7.x, edge7.y, edge7.z, color.r, color.g, color.b, color.a)
|
|
DrawLine(edge2.x, edge2.y, edge2.z, edge8.x, edge8.y, edge8.z, color.r, color.g, color.b, color.a)
|
|
DrawLine(edge3.x, edge3.y, edge3.z, edge5.x, edge5.y, edge5.z, color.r, color.g, color.b, color.a)
|
|
DrawLine(edge4.x, edge4.y, edge4.z, edge6.x, edge6.y, edge6.z, color.r, color.g, color.b, color.a)
|
|
end
|
|
|
|
local GetEntityInfo = function(entity)
|
|
local playerCoords = GetEntityCoords(PlayerPedId())
|
|
local entityType = GetEntityType(entity)
|
|
local entityHash = GetEntityModel(entity)
|
|
local entityName = Entities[entityHash] or Lang:t('info.obj_unknown')
|
|
local entityData = { '~y~' .. Lang:t('info.entity_view_info'), '', Lang:t('info.model_hash') .. ' ~y~' .. entityHash, ' ', Lang:t('info.ent_id') .. ' ~y~' .. entity, Lang:t('info.obj_name') .. ' ~y~' .. entityName, Lang:t('info.net_id') .. ' ~y~' .. (NetworkGetEntityIsNetworked(entity) and NetworkGetNetworkIdFromEntity(entity) or Lang:t('info.net_id_not_registered')), Lang:t('info.ent_owner') .. ' ~y~' .. GetPlayerServerId(NetworkGetEntityOwner(entity)), ' ' }
|
|
|
|
if entityType == 1 then
|
|
local pedRelationshipGroup = GetPedRelationshipGroupHash(entity)
|
|
entityData[#entityData + 1] = Lang:t('info.cur_health') .. ' ~y~' .. GetEntityHealth(entity)
|
|
entityData[#entityData + 1] = Lang:t('info.max_health') .. ' ~y~' .. GetPedMaxHealth(entity)
|
|
entityData[#entityData + 1] = Lang:t('info.armour') .. ' ~y~' .. GetPedArmour(entity)
|
|
entityData[#entityData + 1] = Lang:t('info.rel_group') .. ' ~y~' .. (Entities[pedRelationshipGroup] or Lang:t('info.rel_group_custom'))
|
|
entityData[#entityData + 1] = Lang:t('info.rel_to_player') .. ' ~y~' .. GetPedRelationshipType(GetRelationshipBetweenPeds(entity, PlayerPedId()))
|
|
elseif entityType == 2 then
|
|
entityData[#entityData + 1] = Lang:t('info.veh_rpm') .. ' ~y~' .. RoundFloat(GetVehicleCurrentRpm(entity), 2)
|
|
entityData[#entityData + 1] = (useKph and Lang:t('info.veh_speed_kph') or Lang:t('info.veh_speed_mph')) .. ' ~y~' .. RoundFloat((GetEntitySpeed(entity) * (useKph and 3.6 or 2.23694)), 0)
|
|
entityData[#entityData + 1] = Lang:t('info.veh_cur_gear') .. ' ~y~' .. GetVehicleCurrentGear(entity)
|
|
entityData[#entityData + 1] = Lang:t('info.veh_acceleration') .. ' ~y~' .. RoundFloat(GetVehicleAcceleration(entity), 2)
|
|
entityData[#entityData + 1] = Lang:t('info.body_health') .. ' ~y~' .. GetVehicleBodyHealth(entity)
|
|
entityData[#entityData + 1] = Lang:t('info.eng_health') .. ' ~y~' .. GetVehicleEngineHealth(entity)
|
|
elseif entityType == 3 then
|
|
entityData[#entityData + 1] = Lang:t('info.cur_health') .. ' ~y~' .. GetEntityHealth(entity)
|
|
end
|
|
local entityCoords = GetEntityCoords(entity)
|
|
|
|
entityData[#entityData + 1] = ' '
|
|
entityData[#entityData + 1] = Lang:t('info.dist_to_obj') .. ' ~y~' .. RoundFloat(#(playerCoords - entityCoords), 2)
|
|
entityData[#entityData + 1] = Lang:t('info.obj_heading') .. ' ~y~' .. RoundFloat(GetEntityHeading(entity), 2)
|
|
entityData[#entityData + 1] = Lang:t('info.obj_coords') .. ' ~y~' .. RoundVector3(entityCoords, 2)
|
|
entityData[#entityData + 1] = Lang:t('info.obj_rot') .. ' ~y~' .. RoundVector3(GetEntityRotation(entity), 2)
|
|
entityData[#entityData + 1] = Lang:t('info.obj_velocity') .. ' ~y~' .. RoundVector3(GetEntityVelocity(entity), 2)
|
|
|
|
return entityData
|
|
end
|
|
|
|
local DrawEntityViewText = function(entity)
|
|
local data = GetEntityInfo(entity)
|
|
local count = #data
|
|
|
|
local posX = FreeAimInfoBoxX
|
|
local posY = FreeAimInfoBoxY
|
|
local titleSpacing = 0.03
|
|
local textSpacing = 0.022
|
|
local titeLeftMargin = 0.05
|
|
local paddingTop = 0.02
|
|
local paddingLeft = 0.005
|
|
local rectWidth = 0.18
|
|
local heightOfContent = (((count) * textSpacing) + titleSpacing) / count
|
|
local rectHeight = ((count - 1) * heightOfContent) + paddingTop
|
|
|
|
DrawRect(posX + (rectWidth / 2), posY + ((rectHeight / 2) - posY / 2), rectWidth, rectHeight, 11, 11, 11, 200)
|
|
|
|
for k, v in ipairs(data) do
|
|
SetTextScale(0.35, 0.35)
|
|
SetTextFont(4)
|
|
SetTextDropshadow(1.0, 0, 0, 0, 255)
|
|
SetTextEdge(1, 0, 0, 0, 255)
|
|
SetTextColour(255, 255, 255, 215)
|
|
SetTextJustification(1)
|
|
BeginTextCommandDisplayText('STRING')
|
|
AddTextComponentSubstringPlayerName(v)
|
|
if k == 1 then
|
|
SetTextScale(0.50, 0.50)
|
|
EndTextCommandDisplayText(posX + titeLeftMargin, posY)
|
|
posY = posY + titleSpacing
|
|
else
|
|
SetTextScale(0.35, 0.35)
|
|
EndTextCommandDisplayText(posX + paddingLeft, posY)
|
|
posY = posY + textSpacing
|
|
end
|
|
end
|
|
end
|
|
|
|
local DrawEntityViewTextInWorld = function(entity, coords)
|
|
local onScreen, posX, posY = World3dToScreen2d(coords.x, coords.y, coords.z)
|
|
if onScreen then
|
|
local data = GetEntityInfo(entity)
|
|
local count = #data
|
|
local textOffsetY = 0.015
|
|
local leftPadding = 0.005
|
|
local topPadding = 0.01
|
|
local botPadding = 0.02
|
|
local offSetCount = (((count - 2) * textOffsetY)) / count
|
|
local rectWidth = 0.12
|
|
local rectHeight = ((count) * offSetCount) + botPadding
|
|
|
|
DrawRect(posX, posY, rectWidth, rectHeight, 11, 11, 11, 200)
|
|
|
|
for k, v in ipairs(data) do
|
|
if k ~= 1 and k ~= 2 then
|
|
SetTextScale(0.25, 0.25)
|
|
SetTextFont(4)
|
|
SetTextDropshadow(1.0, 0, 0, 0, 255)
|
|
SetTextEdge(1, 0, 0, 0, 255)
|
|
SetTextColour(255, 255, 255, 215)
|
|
SetTextJustification(1)
|
|
BeginTextCommandDisplayText('STRING')
|
|
AddTextComponentSubstringPlayerName(v)
|
|
EndTextCommandDisplayText(posX - rectWidth / 2 + leftPadding, posY - rectHeight / 2 + topPadding)
|
|
posY = posY + textOffsetY
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local GetVehicle = function(playerCoords)
|
|
local handle, vehicle = FindFirstVehicle()
|
|
local success
|
|
local rveh = nil
|
|
repeat
|
|
if vehicle ~= FreeAimEntity then
|
|
local pos = GetEntityCoords(vehicle)
|
|
local distance = #(playerCoords - pos)
|
|
if distance < EntityViewDistance and distance > 5.0 then
|
|
DrawEntityBoundingBox(vehicle)
|
|
elseif distance < 5.0 then
|
|
rveh = vehicle
|
|
DrawEntityViewTextInWorld(vehicle, pos)
|
|
end
|
|
end
|
|
success, vehicle = FindNextVehicle(handle)
|
|
until not success
|
|
EndFindVehicle(handle)
|
|
return rveh
|
|
end
|
|
|
|
local GetObject = function(playerCoords)
|
|
local handle, object = FindFirstObject()
|
|
local success
|
|
local robject = nil
|
|
repeat
|
|
if object ~= FreeAimEntity then
|
|
local pos = GetEntityCoords(object)
|
|
local distance = #(playerCoords - pos)
|
|
if distance < EntityViewDistance and distance > 5.0 then
|
|
DrawEntityBoundingBox(object)
|
|
elseif distance < 5.0 then
|
|
robject = object
|
|
DrawEntityViewTextInWorld(object, pos)
|
|
end
|
|
end
|
|
success, object = FindNextObject(handle)
|
|
until not success
|
|
EndFindObject(handle)
|
|
return robject
|
|
end
|
|
|
|
local GetNPC = function(playerCoords)
|
|
local handle, ped = FindFirstPed()
|
|
local success
|
|
local rped = nil
|
|
repeat
|
|
if ped ~= FreeAimEntity then
|
|
local pos = GetEntityCoords(ped)
|
|
local distance = #(playerCoords - pos)
|
|
if CanEntityBeUsed(ped) then
|
|
if distance < EntityViewDistance and distance > 5.0 then
|
|
DrawEntityBoundingBox(ped)
|
|
elseif distance < 5.0 then
|
|
rped = ped
|
|
DrawEntityViewTextInWorld(ped, pos)
|
|
end
|
|
end
|
|
end
|
|
success, ped = FindNextPed(handle)
|
|
until not success
|
|
EndFindPed(handle)
|
|
return rped
|
|
end
|
|
|
|
ToggleEntityFreeView = function()
|
|
EntityFreeAim = not EntityFreeAim
|
|
if EntityFreeAim and not EntityViewEnabled then
|
|
RunEntityViewThread()
|
|
end
|
|
end
|
|
|
|
ToggleEntityObjectView = function()
|
|
EntityObjectView = not EntityObjectView
|
|
if EntityObjectView and not EntityViewEnabled then
|
|
RunEntityViewThread()
|
|
end
|
|
end
|
|
|
|
ToggleEntityVehicleView = function()
|
|
EntityVehicleView = not EntityVehicleView
|
|
if EntityVehicleView and not EntityViewEnabled then
|
|
RunEntityViewThread()
|
|
end
|
|
end
|
|
|
|
ToggleEntityPedView = function()
|
|
EntityPedView = not EntityPedView
|
|
if EntityPedView and not EntityViewEnabled then
|
|
RunEntityViewThread()
|
|
end
|
|
end
|
|
|
|
GetCurrentEntityViewDistance = function()
|
|
return EntityViewDistance / 5
|
|
end
|
|
|
|
SetEntityViewDistance = function(data)
|
|
EntityViewDistance = tonumber(data)
|
|
end
|
|
|
|
GetFreeAimEntity = function()
|
|
return FreeAimEntity
|
|
end
|
|
|
|
RunEntityViewThread = function()
|
|
EntityViewEnabled = true
|
|
Citizen.CreateThread(function()
|
|
while EntityViewEnabled do
|
|
Citizen.Wait(0)
|
|
local playerPed = PlayerPedId()
|
|
local playerCoords = GetEntityCoords(playerPed)
|
|
|
|
if EntityPedView then
|
|
GetNPC(playerCoords)
|
|
end
|
|
|
|
if EntityObjectView then
|
|
GetObject(playerCoords)
|
|
end
|
|
|
|
if EntityVehicleView then
|
|
GetVehicle(playerCoords)
|
|
end
|
|
|
|
if EntityFreeAim then
|
|
DrawTitle('~y~' .. Lang:t('info.entity_view_title') .. '~w~\n[~y~E~w~] - ' .. Lang:t('info.entity_freeaim_delete') .. ' ~w~[~y~G~w~] - ' .. Lang:t('info.entity_freeaim_freeze') .. ' ~w~[~y~H~w~] - ' .. Lang:t('info.entity_freeaim_coords'))
|
|
local color = { r = 255, g = 255, b = 255, a = 200 }
|
|
local position = GetEntityCoords(playerPed)
|
|
local hit, coords, entity = RayCastGamePlayCamera(1000.0)
|
|
-- If entity is found then verify entity
|
|
if IsControlJustReleased(0, 74) then -- Copy Coords
|
|
local x = QBCore.Shared.Round(coords.x, 2)
|
|
local y = QBCore.Shared.Round(coords.y, 2)
|
|
local z = QBCore.Shared.Round(coords.z, 2)
|
|
SendNUIMessage({
|
|
string = string.format('vector3(%s, %s, %s)', x, y, z)
|
|
})
|
|
QBCore.Functions.Notify(Lang:t('info.coords_copied'), 'success')
|
|
end
|
|
if hit and (IsEntityAVehicle(entity) or IsEntityAPed(entity) or IsEntityAnObject(entity)) then
|
|
color = { r = 0, g = 255, b = 0, a = 200 }
|
|
FreeAimEntity = entity
|
|
DrawEntityBoundingBox(entity, color)
|
|
DrawEntityViewText(entity)
|
|
|
|
if IsControlJustReleased(0, 47) then -- Freeze entities
|
|
if FrozenEntities[entity] then
|
|
FrozenEntities[entity] = not FrozenEntities[entity]
|
|
else
|
|
FrozenEntities[entity] = true
|
|
end
|
|
|
|
FreezeEntityPosition(entity, FrozenEntities[entity])
|
|
QBCore.Functions.Notify(Lang:t('info.you_have') .. (FrozenEntities[entity] and Lang:t('info.entity_frozen') or Lang:t('info.entity_unfrozen')) .. Lang:t('info.freeaim_entity'), (FrozenEntities[entity] and 'success' or 'error'))
|
|
end
|
|
|
|
if IsControlJustReleased(0, 38) then -- Delete entity
|
|
-- Set as missionEntity so the object can be remove (Even map objects)
|
|
SetEntityAsMissionEntity(entity, true, true)
|
|
DeleteEntity(entity)
|
|
|
|
if not DoesEntityExist(entity) then
|
|
QBCore.Functions.Notify(Lang:t('info.entity_del'), 'success')
|
|
else
|
|
QBCore.Functions.Notify(Lang:t('info.entity_del_error'), 'error')
|
|
end
|
|
end
|
|
else
|
|
FreeAimEntity = nil
|
|
end
|
|
|
|
DrawLine(position.x, position.y, position.z, coords.x, coords.y, coords.z, color.r, color.g, color.b, color.a)
|
|
DrawMarker(28, coords.x, coords.y, coords.z, 0.0, 0.0, 0.0, 0.0, 180.0, 0.0, 0.1, 0.1, 0.1, color.r, color.g, color.b, color.a, false, true, 2, nil, nil, false, false)
|
|
end
|
|
|
|
if EntityPedView == false and EntityObjectView == false and EntityVehicleView == false and EntityFreeAim == false then
|
|
EntityViewEnabled = false
|
|
end
|
|
end
|
|
end)
|
|
end
|