Frontlines Demo Script | ESP (WITH OFFSCREEN ARROWS AND SMOOTH FADING)

Created by integerisqt

Features:

local robloxG = getrenv()._G

local f_globals = robloxG.globals
local f_utils = robloxG.utils
local f_consts = robloxG.consts
local f_enums = robloxG.enums

local gbl_sol_state = f_globals.gbl_sol_state


local gbus = f_utils.gbus
local EVENT_ENUM = gbus.EVENT_ENUM
local TASK_ENUM = gbus.TASK_ENUM
local task_tables = debug.getupvalue(gbus.add_task, 1)
local net_msg_util = f_utils.net_msg_util


local old_trig_event

local runService = game:GetService("RunService")
local players = game:GetService("Players")




local camera = workspace.CurrentCamera
local localPlayer = players.LocalPlayer
local robloxWorldToViewportPoint = camera.WorldToViewportPoint

local espObjects = {}
local signal = loadstring(game:HttpGet("https://raw.githubusercontent.com/Quenty/NevermoreEngine/23c4c96158a582b30f13d58ebb8b9f8139aca130/src/signal/src/Shared/Signal.lua"))()


local function DEBUG_PRINT(text, color)
   color = color or Color3.new(1, 1, 1)
   return printconsole(tostring(text), color.r*255, color.g*255, color.b*255)
end

local function createDrawing(type, prop)
   local object = Drawing.new(type)
   if prop then
       for i,v in next, prop do
           object[i] = v
       end
   end
   return object
end

local function mapValue(x, start0, stop0, start1, stop1)
   return start1 + (stop1 - start1)*(x - start0)/(stop0 - start0)
end


local function applyEsp(player, id)
   local esp = {}
   esp.fadingPassed = 0
   esp.alphaChanged = signal.new()
   esp.drawingObjects = {
       onScreen = {},
       offScreen = {},
       boxOutline = createDrawing("Square", {Thickness = 3, Color = Color3.new(0, 0, 0), Transparency = 1, Visible = false}),
       box = createDrawing("Square", {Thickness = 1, Color = Color3.new(1, 1, 1), Transparency = 1, Visible = false}),
       healthBarOutline = createDrawing("Square", {Thickness = 1, Filled = true, Color = Color3.fromRGB(20, 20, 20), Transparency = 1, Visible = false}),
       healthBar = createDrawing("Square", {Thickness = 1, Filled = true, Color = Color3.new(0, 1, 0), Transparency = 1, Visible = false}),
       nameTag = createDrawing("Text", {Font = 2, Size = 13, Outline = true, Center = true, Color = Color3.new(1, 1, 1), Text = player.Name, Visible = false}),
       oofArrow = createDrawing("Triangle", {Filled = true, Color = Color3.new(1, 0, 0), Visible = false})
   }
   esp.renderingOnScreen = false
   esp.renderingOffScreen = false
   esp.chamsObjects = {}
   esp.fading = false
   esp.model = nil
   esp.data = {
       health = 100,
       maxHealth = 100,
       boundingCf = CFrame.new(),
       boundingSize = Vector3.new()
   }--used for rendering esp
   esp.id = id

   for i,v in next, {"boxOutline", "box", "healthBarOutline", "healthBar", "nameTag"} do
       table.insert(esp.drawingObjects.onScreen, esp.drawingObjects[v])
       esp.alphaChanged:Connect(function(transparency)
           esp.drawingObjects[v].Transparency = 1 - transparency
       end)
   end
   for i,v in next, {"oofArrow"} do
       table.insert(esp.drawingObjects.offScreen, esp.drawingObjects[v])
       esp.alphaChanged:Connect(function(transparency)
           esp.drawingObjects[v].Transparency = 1 - transparency
       end)
   end

   function esp:setTrans(trans)
       esp.alphaChanged:Fire(trans)
   end

   function esp.onSpawn(model)
       esp.model = model
   end

   function esp.onDeath()
       esp.model = nil
       esp.fadingPassed = 0
       esp.fading = true
       esp.fadingStep = runService.RenderStepped:Connect(function(deltaTime)
           esp.fadingPassed = esp.fadingPassed + deltaTime
           esp:setTrans(mapValue(esp.fadingPassed, 0, 0.6, 0, 1))
           if esp.fadingPassed >= 0.6 then
               esp.fading = false
               esp.fadingPassed = 0
               esp:setTrans(0)
               if esp.fadingStep then
                   esp.fadingStep:Disconnect()
                   esp.fadingStep = nil
               end
           end
       end)
   end

   esp.step = runService.RenderStepped:Connect(function(deltaTime)
       if (esp.model or esp.fading) and f_globals.cli_teams[f_globals.cli_state.id] ~= f_globals.cli_teams[id]  then
           if esp.model then
               local health = f_globals.gbl_sol_healths[id]
               esp.data.boundingCf, esp.data.boundingSize = esp.model:GetBoundingBox()
               esp.data.health = health
               esp.data.maxHealth = 100
           end

           local _, onScreen = robloxWorldToViewportPoint(camera, esp.data.boundingCf.p)
           if onScreen then
               esp.renderingOnScreen = true
               if esp.renderingOffScreen then
                   for i = 1, #esp.drawingObjects.offScreen do
                       esp.drawingObjects.offScreen[i].Visible = false
                   end
                   esp.renderingOffScreen = false
               end
               local boxOutline = esp.drawingObjects.boxOutline
               local box = esp.drawingObjects.box
               local healthBarOutline = esp.drawingObjects.healthBarOutline
               local healthBar = esp.drawingObjects.healthBar
               local nameTag = esp.drawingObjects.nameTag

               local topLeft = robloxWorldToViewportPoint(camera, esp.data.boundingCf * Vector3.new(esp.data.boundingSize.x/2, esp.data.boundingSize.y/2, 0))
               local bottomRight = robloxWorldToViewportPoint(camera, esp.data.boundingCf * Vector3.new(-esp.data.boundingSize.x/2, -esp.data.boundingSize.y/2, 0))

               local boxPos = Vector2.new(math.floor(topLeft.x), math.floor(topLeft.y))
               local boxSize = Vector2.new(math.abs(math.floor(bottomRight.x - topLeft.x)), math.abs(math.floor(bottomRight.y - topLeft.y)))

               box.Position = boxPos
               box.Size = boxSize
               boxOutline.Position = boxPos
               boxOutline.Size = boxSize

               box.Visible = true
               boxOutline.Visible = true

               healthBarOutline.Position = Vector2.new(boxPos.x - 1 - 1 - 1 - 2 - 1, boxPos.y - 1)
               healthBarOutline.Size = Vector2.new(4, boxSize.y + 1 + 1)

               local healthPercentage = esp.data.health/esp.data.maxHealth
               healthBar.Size = Vector2.new(2, boxSize.y*healthPercentage)
               healthBar.Position = Vector2.new(healthBarOutline.Position.x + 1, boxPos.y + boxSize.y - healthBar.Size.y)
               healthBar.Color = Color3.new(1, 0, 0):Lerp(Color3.new(0, 1, 0), healthPercentage)

               healthBar.Visible = true
               healthBarOutline.Visible = true

               nameTag.Position = Vector2.new(boxPos.x + math.floor(boxSize.x/2), boxPos.y - 1 - nameTag.TextBounds.y)
               
               nameTag.Visible = true
           else
               esp.renderingOffScreen = true
               if esp.renderingOnScreen then
                   for i = 1, #esp.drawingObjects.onScreen do
                       esp.drawingObjects.onScreen[i].Visible = false
                   end
                   esp.renderingOnScreen = false
               end
               local oofArrow = esp.drawingObjects.oofArrow

               local camCf = camera.CFrame
               camCf = CFrame.lookAt(camCf.p, camCf.p + camCf.LookVector * Vector3.new(1, 0, 1)) --make the pitch 0

               local projected = camCf:PointToObjectSpace(esp.data.boundingCf.p)
               local angle = math.atan2(projected.z, projected.x)

               local cx, sy = math.cos(angle), math.sin(angle)
               local cx1, sy1 = math.cos(angle + math.pi/2), math.sin(angle + math.pi/2)
               local cx2, sy2 = math.cos(angle + math.pi/2*3), math.sin(angle + math.pi/2*3)

               local viewport = camera.ViewportSize

               local big, small = math.max(viewport.x, viewport.y), math.min(viewport.x, viewport.y)

               local arrowOrigin = viewport/2 + Vector2.new(cx * big * 75/200, sy * small * 75/200)

               oofArrow.PointA = arrowOrigin + Vector2.new(30 * cx, 30 * sy)
               oofArrow.PointB = arrowOrigin + Vector2.new(15 * cx1, 15 * sy1)
               oofArrow.PointC = arrowOrigin + Vector2.new(15 * cx2, 15 * sy2)
               oofArrow.Visible = true
           end
       else
           if esp.renderingOnScreen then
               for i = 1, #esp.drawingObjects.onScreen do
                   esp.drawingObjects.onScreen[i].Visible = false
               end
               esp.renderingOnScreen = false
           end
           if esp.renderingOffScreen then
               for i = 1, #esp.drawingObjects.offScreen do
                   esp.drawingObjects.offScreen[i].Visible = false
               end
               esp.renderingOffScreen = false
           end
       end
   end)

   if f_globals.gbl_sol_state.r15_models[id] then
       task.spawn(esp.onSpawn, f_globals.gbl_sol_state.r15_models[id])
   end

   espObjects[player] = esp
end

local function removeEsp(player)
   local esp = espObjects[player]
   if esp then
       esp.onDeath()
       repeat
           task.wait()
       until not esp.fading
       esp.step:Disconnect()
       for i = #esp.drawingObjects.onScreen, 1, -1 do
           table.remove(esp.drawingObjects.onScreen, i):Remove()
       end
       for i = #esp.drawingObjects.offScreen, 1, -1 do
           table.remove(esp.drawingObjects.offScreen, i):Remove()
       end
       table.clear(esp)
       espObjects[player] = nil
       esp = nil
   end
end

local function proxy_trig_event(event_enum, ...)
   local args = {...}
   if event_enum == EVENT_ENUM.TPV_SOL_MODEL_SPAWN then
       old_trig_event(event_enum, ...)
       local player = players:FindFirstChild(f_globals.cli_names[args[1]])
       if player then
           local esp = espObjects[player]
           if esp then
               task.spawn(esp.onSpawn, args[2])
           end
       end
       return
   end
   return old_trig_event(event_enum, ...)
end

old_trig_event = hookfunction(gbus.trig_event, function(...)
   return proxy_trig_event(...)
end)

local original_tpv_sol_gui = task_tables[TASK_ENUM.DEINIT_TPV_SOL_GUI][3]
task_tables[TASK_ENUM.DEINIT_TPV_SOL_GUI][3] = function(index)
   local player = players:FindFirstChild(f_globals.cli_names[index])
   if player then
       local esp = espObjects[player]
       if esp then
           task.spawn(esp.onDeath)
       end
   end
   return original_tpv_sol_gui(index)
end


for i,v in next, f_globals.cli_names do
   local plr = players:FindFirstChild(v)
   if plr then
       task.spawn(applyEsp, plr, i)
   end
end

players.PlayerRemoving:Connect(removeEsp)
players.PlayerAdded:Connect(function(player)
   task.wait(1)
   for i,v in next, f_globals.cli_names do
       if v == player.Name then
           print("ok!")
           applyEsp(player, i)
           break
       end
   end
end)