Render a triangle to the screen based on a world coordinate.
It’s not perfect, but it does the job.
It’s not perfect, but it does the job.
Nice idea
Could be used for any sort of direction indicator, most notably damage indicator or where a grenade has landed etc.
Great job!
hope you dont mind, here is a edited version that always points towards a active waypoint on the map
offscreen.lua (3.3 KB)
That is really cool! What about the performance?
The performance is not that great, but not terrible, It is 0.06ms when rendering.
I have made a damage indicator with it (and yes the color is red )
local damageIndicators = {}
local debugMode = true
local function draw_line(first, second, width, color)
local x,y = GetActiveScreenResolution()
DrawLine_2d(first.x / x, first.y / y, second.x / x, second.y / y, width, color.r, color.g, color.b, color.a)
end
local function sign(x)
return x > 0 and 1 or x < 0 and -1 or 0
end
local function rotate_point(point, cos, sin)
return vec2(point.x * cos - point.y * sin, point.x * sin + point.y * cos)
end
local function get_camera_forward()
local cam_rot = GetFinalRenderedCamRot(2)
local heading = math.rad(cam_rot.z)
local pitch = math.rad(cam_rot.x)
return vec3(-math.sin(heading) * math.cos(pitch), math.cos(heading) * math.cos(pitch), math.sin(pitch))
end
local function draw_triangle(worldVec, width, color, ignoreScreen)
local on_screen, screen_x, screen_y = GetScreenCoordFromWorldCoord(worldVec.x, worldVec.y, worldVec.z)
if not on_screen and not ignoreScreen then return end
local res_x, res_y = GetActiveScreenResolution()
local res_center_x = res_x * 0.5
local res_center_y = res_y * 0.5
local player_position = GetEntityCoords(PlayerPedId())
local delta = worldVec - player_position
delta = norm(delta)
local forward = get_camera_forward()
local dotted = dot(delta, forward)
local crossed = cross(delta, forward)
local angle = math.atan2(#crossed, dotted)
local sign = sign(crossed.z)
angle = angle + 1.570796251
if sign == 1 then angle = math.pi - angle end
local sin_angle = math.sin(angle)
local cos_angle = math.cos(angle)
local radius = 120.0
local triangle_size = 14
local triangle_center = vec2(res_center_x + radius * cos_angle, res_center_y - radius * sin_angle)
local triangle_point_one = rotate_point(vec2(1.0, 0.0), cos_angle, -sin_angle) * triangle_size
local triangle_point_two = rotate_point(vec2(-1.0, 0.75), cos_angle, -sin_angle) * triangle_size
local triangle_point_three = rotate_point(vec2(-1.0, -0.75), cos_angle, -sin_angle) * triangle_size
draw_line(triangle_center + triangle_point_one, triangle_center + triangle_point_two, width, color)
draw_line(triangle_center + triangle_point_two, triangle_center + triangle_point_three, width, color)
draw_line(triangle_center + triangle_point_three, triangle_center + triangle_point_one, width, color)
end
local function AddDamageIndicator(attacker)
local attackerPos = GetEntityCoords(attacker)
table.insert(damageIndicators, {
position = attackerPos,
color = {r = 255, g = 0, b = 0, a = 255},
width = 0.0005,
timeAdded = GetGameTimer(),
duration = 2000
})
end
local function SpawnAttackingPed()
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
local spawnDistance = 10.0
local spawnAngle = math.random() * 2 * math.pi
local spawnX = playerCoords.x + spawnDistance * math.cos(spawnAngle)
local spawnY = playerCoords.y + spawnDistance * math.sin(spawnAngle)
local pedHash = GetHashKey("s_m_y_swat_01")
RequestModel(pedHash)
while not HasModelLoaded(pedHash) do
Wait(1)
end
local ped = CreatePed(4, pedHash, spawnX, spawnY, playerCoords.z, 0.0, true, true)
SetPedArmour(ped, 100)
SetPedAccuracy(ped, 50)
SetPedCombatAttributes(ped, 46, true)
SetPedCombatAbility(ped, 100)
local weaponHash = GetHashKey("WEAPON_PISTOL")
GiveWeaponToPed(ped, weaponHash, 999, false, true)
TaskCombatPed(ped, playerPed, 0, 16)
Citizen.SetTimeout(10000, function()
if DoesEntityExist(ped) then
DeleteEntity(ped)
end
end)
end
AddEventHandler('gameEventTriggered', function(name, args)
if name == "CEventNetworkEntityDamage" then
local victim = args[1]
local attacker = args[2]
local isDead = args[4]
local weapon = args[7]
if victim == PlayerPedId() and DoesEntityExist(attacker) then
AddDamageIndicator(attacker)
end
end
end)
Citizen.CreateThread(function()
while true do
local currentTime = GetGameTimer()
for i = #damageIndicators, 1, -1 do
local indicator = damageIndicators[i]
local timeAlive = currentTime - indicator.timeAdded
if timeAlive < indicator.duration then
indicator.color.a = math.floor(255 * (1 - (timeAlive / indicator.duration)))
draw_triangle(indicator.position, indicator.width, indicator.color, true)
else
table.remove(damageIndicators, i)
end
end
Wait(0)
end
end)
Citizen.CreateThread(function()
while debugMode do
SpawnAttackingPed()
Wait(10000)
end
end)