M
Description
I dedicate any and all copyright interest in this software to the public domain. I make this dedication for the benefit of the public at large and to the detriment of my heirs and successors. I intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. https://unlicense.org/
GAMEFRONTLINES
UPDATEDOct 10, 2026
ACCESSKeyless
PLATFORMDesktop
Script source Luau
-- [[ BloxScripts Risk Notice ]]
-- This script has not been verified by BloxScripts.fun. Deal with caution.
--
-- Stay safe:
-- • Never log in on unofficial Roblox sites or lookalike domains.
-- • Real Roblox links use roblox.com (check the .com ending).
-- • Treat fake Roblox login / "claim reward" pages as phishing.
-- [[ End BloxScripts Risk Notice ]]
run_on_thread(getactorthreads()[1], [[
getrenv()._G.globals.fpv_sol_spread={spread=0}
local Players, Workspace = game:GetService'Players', workspace
local CurrentCamera = Workspace.CurrentCamera
local GlobalEnvironment = getrenv()._G
local GlobalVariables, ExecutionMap = GlobalEnvironment.globals, (getupvalues or debug and debug.getupvalues)(GlobalEnvironment.append_exe_set)[1]
local ClientState, SoldierTeams, SoldiersSpawned, SoldiersAlive, SoldierModels = GlobalVariables.cli_state, GlobalVariables.sol_teams, GlobalVariables.soldiers_spawned, GlobalVariables.soldiers_alive, GlobalVariables.soldier_models
local function GetClosestPlayer()
local ClosestPlayer, ClosestDistance, FirstPersonViewID = nil, math.huge, ClientState.fpv_sol_id
local MyTeam = SoldierTeams[FirstPersonViewID]
for PlayerID, IsSpawned in SoldiersSpawned do
if IsSpawned and SoldiersAlive[PlayerID] and PlayerID ~= FirstPersonViewID and SoldierTeams[PlayerID] ~= MyTeam then
local Character = SoldierModels[PlayerID]
if Character and Character.PrimaryPart then
local Head = Character:FindFirstChild'Head' or Character.PrimaryPart
local Distance = (Head.Position - CurrentCamera.CFrame.Position).Magnitude
if Distance < ClosestDistance then
ClosestDistance = Distance
ClosestPlayer = Head
end
end
end
end
return ClosestPlayer
end
local OriginalSpawnFunction = ExecutionMap[GlobalEnvironment.exe_func_t.SPAWN_FPV_SOL_BULLET]
ExecutionMap[GlobalEnvironment.exe_func_t.SPAWN_FPV_SOL_BULLET] = function(BulletID, BulletType, SpawnPosition, Velocity)
local Target = GetClosestPlayer()
if Target then
Velocity = (Target.Position - SpawnPosition).Unit * Velocity.Magnitude
end
return OriginalSpawnFunction(BulletID, BulletType, SpawnPosition, Velocity)
end
local ESP = {
Config = {
ZIndex = 2,
Enabled = true,
ShowHealthBars = true,
ShowNames = true,
ShowBoxes = true,
ShowDistance = true,
ShowTools = true,
BoxThickness = 1,
NameFont = 1,
FontSize = 12,
NameColor = Color3.new(1, 1, 1),
BoxColor = Color3.new(1, 1, 1),
HealthBarWidth = 2,
HealthBarHeight = 10,
MaxDistance = 100,
ToolIconSize = 16
},
Callbacks = {
getPartsToRenderCallback = nil,
partToHealthCallback = nil,
partToToolsToRenderCallback = nil
},
_activeObjects = {},
_drawingObjects = {},
_cache = {
parts = {},
health = {},
tools = {},
lastUpdate = 0,
updateInterval = 0.1
},
_connections = {}
}
if DrawingImmediate then
function ESP:WorldToScreen(worldPosition)
local camera = workspace.CurrentCamera;
if not camera then
return nil
end;
local vector, onScreen = camera:WorldToViewportPoint(worldPosition)
if onScreen and vector.Z > 0 then
return Vector2.new(vector.X, vector.Y), vector.Z
end;
return nil, nil
end;
function ESP:GetHealthColor(currentHealth, maxHealth)
if not currentHealth or not maxHealth or maxHealth <= 0 then
return Color3.new(1, 1, 1)
end;
local percent = currentHealth / maxHealth;
if percent > 0.7 then
return Color3.new(0, 1, 0)
elseif percent > 0.3 then
return Color3.new(1, 1, 0)
else
return Color3.new(1, 0, 0)
end
end;
function ESP:GetPartBoxSize(part)
if not part then
return 2, 2
end;
if part:IsA("Model") then
local size = part:GetExtentsSize()
return size.X * 2, size.Y * 2
end;
if part:IsA("BasePart") then
local size = part.Size;
return size.X, size.Y
end;
return 2, 2
end;
function ESP:GetPartPosition(part)
if part:IsA("Model") then
local primary = part.PrimaryPart;
if primary then
return primary.Position
end;
local total = Vector3.new(0, 0, 0)
local count = 0;
for _, child in ipairs(part:GetDescendants()) do
if child:IsA("BasePart") then
total = total + child.Position;
count = count + 1
end
end;
if count > 0 then
return total / count
end;
return part:GetPivot().Position
end;
if part:IsA("BasePart") then
return part.Position
end;
return Vector3.new(0, 0, 0)
end;
function ESP:DrawHealthBar(part, screenPos, boxWidth, boxHeight)
if not self.Config.ShowHealthBars then
return
end;
if not self.Callbacks.partToHealthCallback then
return
end;
local healthInfo = self.Callbacks.partToHealthCallback(part)
if not healthInfo then
return
end;
local currentHealth = healthInfo.currentHealth or healthInfo[1]
local maxHealth = healthInfo.maxHealth or healthInfo[2]
if not currentHealth or not maxHealth or maxHealth <= 0 then
return
end;
local healthPercent = math.clamp(currentHealth / maxHealth, 0, 1)
local barWidth = boxWidth * healthPercent;
local barPos = Vector2.new(screenPos.X - (boxWidth / 2), screenPos.Y - boxHeight - self.Config.HealthBarHeight - 2)
DrawingImmediate.Rectangle(barPos, Vector2.new(boxWidth, self.Config.HealthBarHeight), Color3.new(0.3, 0.3, 0.3), 0.8, 2, 1)
if barWidth > 0 then
DrawingImmediate.FilledRectangle(barPos, Vector2.new(barWidth, self.Config.HealthBarHeight), self:GetHealthColor(currentHealth, maxHealth), 1, 2)
end;
local healthText = string.format("%.0f/%.0f", currentHealth, maxHealth)
local textPos = Vector2.new(screenPos.X, barPos.Y - 2)
DrawingImmediate.OutlinedText(textPos, self.Config.NameFont, self.Config.FontSize - 2, Color3.new(1, 1, 1), 1, Color3.new(0, 0, 0), 1, healthText, true)
end;
function ESP:DrawTools(part, screenPos, boxWidth, boxHeight)
if not self.Config.ShowTools then
return
end;
if not self.Callbacks.partToToolsToRenderCallback then
return
end;
local tools = self.Callbacks.partToToolsToRenderCallback(part)
if not tools or #tools == 0 then
return
end;
local startX = screenPos.X - (boxWidth / 2)
local startY = screenPos.Y + boxHeight + 5;
local iconSize = self.Config.ToolIconSize;
local spacing = 5;
for i, tool in ipairs(tools) do
local toolPart = tool.toolPart or tool[1]
local toolName = tool.name or tool[2] or "Unknown"
if toolPart and toolPart:IsA("BasePart") then
local iconPos = Vector2.new(startX + (i - 1) * (iconSize + spacing), startY)
DrawingImmediate.FilledRectangle(iconPos, Vector2.new(iconSize, iconSize), Color3.new(0.2, 0.2, 0.2), 0.8, 3)
DrawingImmediate.Rectangle(iconPos, Vector2.new(iconSize, iconSize), Color3.new(1, 1, 1), 0.5, 3, 1)
DrawingImmediate.OutlinedText(Vector2.new(iconPos.X + iconSize / 2, iconPos.Y + iconSize + 2), self.Config.NameFont, self.Config.FontSize - 2, Color3.new(1, 1, 1), 1, Color3.new(0, 0, 0), 1, toolName, true)
local toolScreenPos = self:WorldToScreen(toolPart.Position)
if toolScreenPos then
DrawingImmediate.Line(screenPos, toolScreenPos, Color3.new(1, 1, 0), 0.5, 1)
end
end
end
end;
function ESP:DrawNameAndDistance(part, screenPos, partName, distance)
if not self.Config.ShowNames and not self.Config.ShowDistance then
return
end;
local text = ""
if self.Config.ShowNames then
text = partName or "Unknown"
end;
if self.Config.ShowDistance and distance then
local distText = string.format(" [%.0fm]", distance)
text = text .. distText
end;
if text ~= "" then
local textPos = Vector2.new(screenPos.X, screenPos.Y - 25)
DrawingImmediate.OutlinedText(textPos, self.Config.NameFont, self.Config.FontSize, self.Config.NameColor, 1, Color3.new(0, 0, 0), 1, text, true)
end
end;
function ESP:DrawBox(part, screenPos, boxWidth, boxHeight, distance)
if not self.Config.ShowBoxes then
return
end;
local topLeft = Vector2.new(screenPos.X - (boxWidth / 2), screenPos.Y - boxHeight)
local boxColor = self.Config.BoxColor;
if self.Config.ShowHealthBars and self.Callbacks.partToHealthCallback then
local healthInfo = self.Callbacks.partToHealthCallback(part)
if healthInfo then
local currentHealth = healthInfo.currentHealth or healthInfo[1]
local maxHealth = healthInfo.maxHealth or healthInfo[2]
if currentHealth and maxHealth then
boxColor = self:GetHealthColor(currentHealth, maxHealth)
end
end
end;
DrawingImmediate.Rectangle(topLeft, Vector2.new(boxWidth, boxHeight), boxColor, 1, 0, self.Config.BoxThickness)
local accentSize = math.min(10, boxWidth * 0.2)
local accentColor = Color3.new(1, 1, 1)
DrawingImmediate.Line(topLeft, Vector2.new(topLeft.X + accentSize, topLeft.Y), accentColor, 0.8, 2)
DrawingImmediate.Line(topLeft, Vector2.new(topLeft.X, topLeft.Y + accentSize), accentColor, 0.8, 2)
local topRight = Vector2.new(topLeft.X + boxWidth, topLeft.Y)
DrawingImmediate.Line(Vector2.new(topRight.X - accentSize, topRight.Y), topRight, accentColor, 0.8, 2)
DrawingImmediate.Line(topRight, Vector2.new(topRight.X, topRight.Y + accentSize), accentColor, 0.8, 2)
local bottomLeft = Vector2.new(topLeft.X, topLeft.Y + boxHeight)
DrawingImmediate.Line(bottomLeft, Vector2.new(bottomLeft.X + accentSize, bottomLeft.Y), accentColor, 0.8, 2)
DrawingImmediate.Line(bottomLeft, Vector2.new(bottomLeft.X, bottomLeft.Y - accentSize), accentColor, 0.8, 2)
local bottomRight = Vector2.new(topLeft.X + boxWidth, topLeft.Y + boxHeight)
DrawingImmediate.Line(Vector2.new(bottomRight.X - accentSize, bottomRight.Y), bottomRight, accentColor, 0.8, 2)
DrawingImmediate.Line(bottomRight, Vector2.new(bottomRight.X, bottomRight.Y - accentSize), accentColor, 0.8, 2)
end;
function ESP:_UpdateCache()
local currentTime = tick()
if currentTime - self._cache.lastUpdate < self._cache.updateInterval then
return
end;
self._cache.lastUpdate = currentTime;
self._cache.parts = {}
self._cache.health = {}
self._cache.tools = {}
if self.Callbacks.getPartsToRenderCallback then
local parts = self.Callbacks.getPartsToRenderCallback()
if parts then
for i, part in ipairs(parts) do
self._cache.parts[#self._cache.parts + 1] = part;
if self.Callbacks.partToHealthCallback then
local health = self.Callbacks.partToHealthCallback(part)
if health then
self._cache.health[part] = health
end
end;
if self.Callbacks.partToToolsToRenderCallback then
local tools = self.Callbacks.partToToolsToRenderCallback(part)
if tools then
self._cache.tools[part] = tools
end
end
end
end
end
end;
function ESP:_OnRender()
if not self.Config.Enabled then
return
end;
self:_UpdateCache()
for _, part in ipairs(self._cache.parts) do
if part and part.Parent then
local partPosition = self:GetPartPosition(part)
local screenPos, distance = self:WorldToScreen(partPosition)
if screenPos and distance <= self.Config.MaxDistance then
local boxWidth, boxHeight = self:GetPartBoxSize(part)
local partName = part.Name;
if part:IsA("Model") and part:FindFirstChild("Humanoid") then
local humanoid = part:FindFirstChild("Humanoid")
if humanoid.DisplayName and humanoid.DisplayName ~= "" then
partName = humanoid.DisplayName
end
end;
self:DrawBox(part, screenPos, boxWidth, boxHeight, distance)
self:DrawHealthBar(part, screenPos, boxWidth, boxHeight)
self:DrawNameAndDistance(part, screenPos, partName, distance)
self:DrawTools(part, screenPos, boxWidth, boxHeight)
end
end
end;
for _, obj in ipairs(self._activeObjects) do
if obj.type == "circle" and obj.position then
local screenPos = self:WorldToScreen(obj.position)
if screenPos then
DrawingImmediate.Circle(screenPos, obj.radius, obj.color, 1, 32, 2)
end
elseif obj.type == "line" and obj.from and obj.to then
local fromScreen = self:WorldToScreen(obj.from)
local toScreen = self:WorldToScreen(obj.to)
if fromScreen and toScreen then
DrawingImmediate.Line(fromScreen, toScreen, obj.color, 1, obj.thickness or 1)
end
end
end
end;
function ESP:SetGetPartsToRenderCallback(callback)
self.Callbacks.getPartsToRenderCallback = callback
end;
function ESP:SetPartToHealthCallback(callback)
self.Callbacks.partToHealthCallback = callback
end;
function ESP:SetPartToToolsToRenderCallback(callback)
self.Callbacks.partToToolsToRenderCallback = callback
end;
function ESP:ClearCallbacks()
self.Callbacks.getPartsToRenderCallback = nil;
self.Callbacks.partToHealthCallback = nil;
self.Callbacks.partToToolsToRenderCallback = nil
end;
function ESP:AddObject(object)
self._activeObjects[#self._activeObjects + 1] = object;
return object
end;
function ESP:RemoveObject(object)
for i, obj in ipairs(self._activeObjects) do
if obj == object then
table.remove(self._activeObjects, i)
break
end
end
end;
function ESP:ClearObjects()
self._activeObjects = {}
end;
function ESP:SetConfig(newConfig)
for k, v in pairs(newConfig) do
self.Config[k] = v
end
end;
function ESP:Toggle()
self.Config.Enabled = not self.Config.Enabled;
return self.Config.Enabled
end;
function ESP:Init()
if self._signal then
self:_Cleanup()
end;
self._signal = DrawingImmediate.GetPaint(self.Config.ZIndex)
local connection = self._signal:Connect(function()
self:_OnRender()
end)
self._connections[#self._connections + 1] = connection
end;
function ESP:_Cleanup()
for _, conn in ipairs(self._connections) do
conn:Disconnect()
end;
self._connections = {}
self._signal = nil
end;
function ESP:Destroy()
self:_Cleanup()
self._activeObjects = {}
self:ClearCallbacks()
self._cache = {
parts = {},
health = {},
tools = {},
lastUpdate = 0,
updateInterval = 0.1
}
end;
function ESP:ForceUpdate()
self._cache.lastUpdate = 0;
self:_UpdateCache()
end
else
if not Drawing then
local drawingUI = Instance.new("ScreenGui", game:GetService("CoreGui"))
drawingUI.Name = "Drawing"
drawingUI.IgnoreGuiInset = true
drawingUI.DisplayOrder = 0x7fffffff
local drawingIndex = 0
local baseDrawingObj = setmetatable({
Visible = true,
ZIndex = 0,
Transparency = 1,
Color = Color3.new(),
Remove = function(self)
setmetatable(self, nil)
end,
Destroy = function(self)
setmetatable(self, nil)
end
}, {
__add = function(t1, t2)
local result = table.clone(t1)
for index, value in t2 do
result[index] = value
end
return result
end
})
local drawingFontsEnum = {
[0] = Font.fromEnum(Enum.Font.Roboto),
[1] = Font.fromEnum(Enum.Font.Legacy),
[2] = Font.fromEnum(Enum.Font.SourceSans),
[3] = Font.fromEnum(Enum.Font.RobotoMono),
}
local function convertTransparency(transparency)
return math.clamp(1 - transparency, 0, 1)
end
local DrawingLib = {}
DrawingLib.Fonts = {
["UI"] = 0,
["System"] = 1,
["Plex"] = 2,
["Monospace"] = 3
}
function DrawingLib.new(drawingType)
drawingIndex += 1
if drawingType == "Line" then
local lineObj = ({
From = Vector2.zero,
To = Vector2.zero,
Thickness = 1
} + baseDrawingObj)
local lineFrame = Instance.new("Frame")
lineFrame.Name = drawingIndex
lineFrame.AnchorPoint = (Vector2.one * .5)
lineFrame.BorderSizePixel = 0
lineFrame.BackgroundColor3 = lineObj.Color
lineFrame.Visible = lineObj.Visible
lineFrame.ZIndex = lineObj.ZIndex
lineFrame.BackgroundTransparency = convertTransparency(lineObj.Transparency)
lineFrame.Size = UDim2.new()
lineFrame.Parent = drawingUI
return setmetatable({__type = "Drawing Object"}, {
__newindex = function(_, index, value)
if typeof(lineObj[index]) == "nil" then return end
if index == "From" then
local direction = (lineObj.To - value)
local center = (lineObj.To + value) / 2
local distance = direction.Magnitude
local theta = math.deg(math.atan2(direction.Y, direction.X))
lineFrame.Position = UDim2.fromOffset(center.X, center.Y)
lineFrame.Rotation = theta
lineFrame.Size = UDim2.fromOffset(distance, lineObj.Thickness)
elseif index == "To" then
local direction = (value - lineObj.From)
local center = (value + lineObj.From) / 2
local distance = direction.Magnitude
local theta = math.deg(math.atan2(direction.Y, direction.X))
lineFrame.Position = UDim2.fromOffset(center.X, center.Y)
lineFrame.Rotation = theta
lineFrame.Size = UDim2.fromOffset(distance, lineObj.Thickness)
elseif index == "Thickness" then
local distance = (lineObj.To - lineObj.From).Magnitude
lineFrame.Size = UDim2.fromOffset(distance, value)
elseif index == "Visible" then
lineFrame.Visible = value
elseif index == "ZIndex" then
lineFrame.ZIndex = value
elseif index == "Transparency" then
lineFrame.BackgroundTransparency = convertTransparency(value)
elseif index == "Color" then
lineFrame.BackgroundColor3 = value
end
lineObj[index] = value
end,
__index = function(self, index)
if index == "Remove" or index == "Destroy" then
return function()
lineFrame:Destroy()
lineObj.Remove(self)
return lineObj:Remove()
end
end
return lineObj[index]
end,
__tostring = function() return "Drawing" end
})
elseif drawingType == "Text" then
local textObj = ({
Text = "",
Font = DrawingLib.Fonts.UI,
Size = 0,
Position = Vector2.zero,
Center = false,
Outline = false,
OutlineColor = Color3.new()
} + baseDrawingObj)
local textLabel, uiStroke = Instance.new("TextLabel"), Instance.new("UIStroke")
textLabel.Name = drawingIndex
textLabel.AnchorPoint = (Vector2.one * .5)
textLabel.BorderSizePixel = 0
textLabel.BackgroundTransparency = 1
textLabel.Visible = textObj.Visible
textLabel.TextColor3 = textObj.Color
textLabel.TextTransparency = convertTransparency(textObj.Transparency)
textLabel.ZIndex = textObj.ZIndex
textLabel.FontFace = drawingFontsEnum[textObj.Font]
textLabel.TextSize = textObj.Size
textLabel:GetPropertyChangedSignal("TextBounds"):Connect(function()
local textBounds = textLabel.TextBounds
local offset = textBounds / 2
textLabel.Size = UDim2.fromOffset(textBounds.X, textBounds.Y)
textLabel.Position = UDim2.fromOffset(textObj.Position.X + (if not textObj.Center then offset.X else 0), textObj.Position.Y + offset.Y)
end)
uiStroke.Thickness = 1
uiStroke.Enabled = textObj.Outline
uiStroke.Color = textObj.Color
textLabel.Parent, uiStroke.Parent = drawingUI, textLabel
return setmetatable({__type = "Drawing Object"}, {
__newindex = function(_, index, value)
if typeof(textObj[index]) == "nil" then return end
if index == "Text" then
textLabel.Text = value
elseif index == "Font" then
value = math.clamp(value, 0, 3)
textLabel.FontFace = drawingFontsEnum[value]
elseif index == "Size" then
textLabel.TextSize = value
elseif index == "Position" then
local offset = textLabel.TextBounds / 2
textLabel.Position = UDim2.fromOffset(value.X + (if not textObj.Center then offset.X else 0), value.Y + offset.Y)
elseif index == "Center" then
local position = (
if value then
workspace.CurrentCamera.ViewportSize / 2
else
textObj.Position
)
textLabel.Position = UDim2.fromOffset(position.X, position.Y)
elseif index == "Outline" then
uiStroke.Enabled = value
elseif index == "OutlineColor" then
uiStroke.Color = value
elseif index == "Visible" then
textLabel.Visible = value
elseif index == "ZIndex" then
textLabel.ZIndex = value
elseif index == "Transparency" then
local transparency = convertTransparency(value)
textLabel.TextTransparency = transparency
uiStroke.Transparency = transparency
elseif index == "Color" then
textLabel.TextColor3 = value
end
textObj[index] = value
end,
__index = function(self, index)
if index == "Remove" or index == "Destroy" then
return function()
textLabel:Destroy()
textObj.Remove(self)
return textObj:Remove()
end
elseif index == "TextBounds" then
return textLabel.TextBounds
end
return textObj[index]
end,
__tostring = function() return "Drawing" end
})
elseif drawingType == "Circle" then
local circleObj = ({
Radius = 150,
Position = Vector2.zero,
Thickness = .7,
Filled = false
} + baseDrawingObj)
local circleFrame, uiCorner, uiStroke = Instance.new("Frame"), Instance.new("UICorner"), Instance.new("UIStroke")
circleFrame.Name = drawingIndex
circleFrame.AnchorPoint = (Vector2.one * .5)
circleFrame.BorderSizePixel = 0
circleFrame.BackgroundTransparency = (if circleObj.Filled then convertTransparency(circleObj.Transparency) else 1)
circleFrame.BackgroundColor3 = circleObj.Color
circleFrame.Visible = circleObj.Visible
circleFrame.ZIndex = circleObj.ZIndex
uiCorner.CornerRadius = UDim.new(1, 0)
circleFrame.Size = UDim2.fromOffset(circleObj.Radius, circleObj.Radius)
uiStroke.Thickness = circleObj.Thickness
uiStroke.Enabled = not circleObj.Filled
uiStroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Border
circleFrame.Parent, uiCorner.Parent, uiStroke.Parent = drawingUI, circleFrame, circleFrame
return setmetatable({__type = "Drawing Object"}, {
__newindex = function(_, index, value)
if typeof(circleObj[index]) == "nil" then return end
if index == "Radius" then
local radius = value * 2
circleFrame.Size = UDim2.fromOffset(radius, radius)
elseif index == "Position" then
circleFrame.Position = UDim2.fromOffset(value.X, value.Y)
elseif index == "Thickness" then
value = math.clamp(value, .6, 0x7fffffff)
uiStroke.Thickness = value
elseif index == "Filled" then
circleFrame.BackgroundTransparency = (if value then convertTransparency(circleObj.Transparency) else 1)
uiStroke.Enabled = not value
elseif index == "Visible" then
circleFrame.Visible = value
elseif index == "ZIndex" then
circleFrame.ZIndex = value
elseif index == "Transparency" then
local transparency = convertTransparency(value)
circleFrame.BackgroundTransparency = (if circleObj.Filled then transparency else 1)
uiStroke.Transparency = transparency
elseif index == "Color" then
circleFrame.BackgroundColor3 = value
uiStroke.Color = value
end
circleObj[index] = value
end,
__index = function(self, index)
if index == "Remove" or index == "Destroy" then
return function()
circleFrame:Destroy()
circleObj.Remove(self)
return circleObj:Remove()
end
end
return circleObj[index]
end,
__tostring = function() return "Drawing" end
})
elseif drawingType == "Square" then
local squareObj = ({
Size = Vector2.zero,
Position = Vector2.zero,
Thickness = .7,
Filled = false
} + baseDrawingObj)
local squareFrame, uiStroke = Instance.new("Frame"), Instance.new("UIStroke")
squareFrame.Name = drawingIndex
squareFrame.BorderSizePixel = 0
squareFrame.BackgroundTransparency = (if squareObj.Filled then convertTransparency(squareObj.Transparency) else 1)
squareFrame.ZIndex = squareObj.ZIndex
squareFrame.BackgroundColor3 = squareObj.Color
squareFrame.Visible = squareObj.Visible
uiStroke.Thickness = squareObj.Thickness
uiStroke.Enabled = not squareObj.Filled
uiStroke.LineJoinMode = Enum.LineJoinMode.Miter
squareFrame.Parent, uiStroke.Parent = drawingUI, squareFrame
return setmetatable({__type = "Drawing Object"}, {
__newindex = function(_, index, value)
if typeof(squareObj[index]) == "nil" then return end
if index == "Size" then
squareFrame.Size = UDim2.fromOffset(value.X, value.Y)
elseif index == "Position" then
squareFrame.Position = UDim2.fromOffset(value.X, value.Y)
elseif index == "Thickness" then
value = math.clamp(value, 0.6, 0x7fffffff)
uiStroke.Thickness = value
elseif index == "Filled" then
squareFrame.BackgroundTransparency = (if value then convertTransparency(squareObj.Transparency) else 1)
uiStroke.Enabled = not value
elseif index == "Visible" then
squareFrame.Visible = value
elseif index == "ZIndex" then
squareFrame.ZIndex = value
elseif index == "Transparency" then
local transparency = convertTransparency(value)
squareFrame.BackgroundTransparency = (if squareObj.Filled then transparency else 1)
uiStroke.Transparency = transparency
elseif index == "Color" then
uiStroke.Color = value
squareFrame.BackgroundColor3 = value
end
squareObj[index] = value
end,
__index = function(self, index)
if index == "Remove" or index == "Destroy" then
return function()
squareFrame:Destroy()
squareObj.Remove(self)
return squareObj:Remove()
end
end
return squareObj[index]
end,
__tostring = function() return "Drawing" end
})
elseif drawingType == "Image" then
local imageObj = ({
Data = "",
Size = Vector2.zero,
Position = Vector2.zero
} + baseDrawingObj)
local imageFrame = Instance.new("ImageLabel")
imageFrame.Name = drawingIndex
imageFrame.BorderSizePixel = 0
imageFrame.ScaleType = Enum.ScaleType.Stretch
imageFrame.BackgroundTransparency = 1
imageFrame.Visible = imageObj.Visible
imageFrame.ZIndex = imageObj.ZIndex
imageFrame.ImageTransparency = convertTransparency(imageObj.Transparency)
imageFrame.ImageColor3 = imageObj.Color
imageFrame.Parent = drawingUI
return setmetatable({__type = "Drawing Object"}, {
__newindex = function(_, index, value)
if typeof(imageObj[index]) == "nil" then return end
if index == "Data" then
imageFrame.Image = value
elseif index == "Size" then
imageFrame.Size = UDim2.fromOffset(value.X, value.Y)
elseif index == "Position" then
imageFrame.Position = UDim2.fromOffset(value.X, value.Y)
elseif index == "Visible" then
imageFrame.Visible = value
elseif index == "ZIndex" then
imageFrame.ZIndex = value
elseif index == "Transparency" then
imageFrame.ImageTransparency = convertTransparency(value)
elseif index == "Color" then
imageFrame.ImageColor3 = value
end
imageObj[index] = value
end,
__index = function(self, index)
if index == "Remove" or index == "Destroy" then
return function()
imageFrame:Destroy()
imageObj.Remove(self)
return imageObj:Remove()
end
end
return imageObj[index]
end,
__tostring = function() return "Drawing" end
})
elseif drawingType == "Quad" then
local QuadProperties = ({
Thickness = 1,
PointA = Vector2.new();
PointB = Vector2.new();
PointC = Vector2.new();
PointD = Vector2.new();
Filled = false;
} + baseDrawingObj)
local PointA = DrawingLib.new("Line")
local PointB = DrawingLib.new("Line")
local PointC = DrawingLib.new("Line")
local PointD = DrawingLib.new("Line")
return setmetatable({__type = "Drawing Object"}, {
__newindex = function(self, Property, Value)
if Property == "Thickness" then
PointA.Thickness = Value
PointB.Thickness = Value
PointC.Thickness = Value
PointD.Thickness = Value
end
if Property == "PointA" then
PointA.From = Value
PointB.To = Value
end
if Property == "PointB" then
PointB.From = Value
PointC.To = Value
end
if Property == "PointC" then
PointC.From = Value
PointD.To = Value
end
if Property == "PointD" then
PointD.From = Value
PointA.To = Value
end
if Property == "Visible" then
PointA.Visible = true
PointB.Visible = true
PointC.Visible = true
PointD.Visible = true
end
if Property == "Filled" then
PointA.BackgroundTransparency = 1
PointB.BackgroundTransparency = 1
PointC.BackgroundTransparency = 1
PointD.BackgroundTransparency = 1
end
if Property == "Color" then
PointA.Color = Value
PointB.Color = Value
PointC.Color = Value
PointD.Color = Value
end
if (Property == "ZIndex") then
PointA.ZIndex = Value
PointB.ZIndex = Value
PointC.ZIndex = Value
PointD.ZIndex = Value
end
end,
__index = function(self, Property)
if (string.lower(tostring(Property)) == "remove") then
return (function()
PointA:Remove();
PointB:Remove();
PointC:Remove();
PointD:Remove();
end)
end
return QuadProperties[Property]
end
});
elseif drawingType == "Triangle" then
local triangleObj = ({
PointA = Vector2.zero,
PointB = Vector2.zero,
PointC = Vector2.zero,
Thickness = 1,
Filled = false
} + baseDrawingObj)
local _linePoints = {}
_linePoints.A = DrawingLib.new("Line")
_linePoints.B = DrawingLib.new("Line")
_linePoints.C = DrawingLib.new("Line")
return setmetatable({__type = "Drawing Object"}, {
__tostring = function() return "Drawing" end,
__newindex = function(_, index, value)
if typeof(triangleObj[index]) == "nil" then return end
if index == "PointA" then
_linePoints.A.From = value
_linePoints.B.To = value
elseif index == "PointB" then
_linePoints.B.From = value
_linePoints.C.To = value
elseif index == "PointC" then
_linePoints.C.From = value
_linePoints.A.To = value
elseif (index == "Thickness" or index == "Visible" or index == "Color" or index == "ZIndex") then
for _, linePoint in _linePoints do
linePoint[index] = value
end
elseif index == "Filled" then
_linePoints.BackgroundTransparency = 1
end
triangleObj[index] = value
end,
__index = function(self, index)
if index == "Remove" or index == "Destroy" then
return function()
for _, linePoint in _linePoints do
linePoint:Remove()
end
triangleObj.Remove(self)
return triangleObj:Remove()
end
end
return triangleObj[index]
end
})
end
end
if not getgenv then
getfenv().getgenv = function() return getfenv(3) or getfenv(2) end
end
local isrenderobj = function(obj)
local s, r = pcall(function()
return obj.__type == "Drawing Object"
end)
return s and r
end
getgenv().isrenderobj = isrenderobj
getgenv().cleardrawcache = function()
drawingUI:ClearAllChildren()
end
getgenv().getrenderproperty = function(obj, prop)
assert(isrenderobj(obj), "Object must be a Drawing", 3)
return obj[prop]
end
getgenv().setrenderproperty = function(obj, prop, val)
assert(isrenderobj(obj), "Object must be a Drawing", 3)
obj[prop] = val
end
getgenv().Drawing = DrawingLib
end
function ESP:WorldToScreen(worldPosition)
local camera = workspace.CurrentCamera;
if not camera then
return nil
end;
local vector, onScreen = camera:WorldToViewportPoint(worldPosition)
if onScreen and vector.Z > 0 then
return Vector2.new(vector.X, vector.Y), vector.Z
end;
return nil, nil
end;
function ESP:GetHealthColor(currentHealth, maxHealth)
if not currentHealth or not maxHealth or maxHealth <= 0 then
return Color3.new(1, 1, 1)
end;
local percent = currentHealth / maxHealth;
if percent > 0.7 then
return Color3.new(0, 1, 0)
elseif percent > 0.3 then
return Color3.new(1, 1, 0)
else
return Color3.new(1, 0, 0)
end
end;
function ESP:GetPartBoxSize(part)
if not part then
return 2, 2
end;
if part:IsA("Model") then
local size = part:GetExtentsSize()
return size.X * 2, size.Y * 2
end;
if part:IsA("BasePart") then
local size = part.Size;
return size.X, size.Y
end;
return 2, 2
end;
function ESP:GetPartPosition(part)
if part:IsA("Model") then
local primary = part.PrimaryPart;
if primary then
return primary.Position
end;
local total = Vector3.new(0, 0, 0)
local count = 0;
for _, child in ipairs(part:GetDescendants()) do
if child:IsA("BasePart") then
total = total + child.Position;
count = count + 1
end
end;
if count > 0 then
return total / count
end;
return part:GetPivot().Position
end;
if part:IsA("BasePart") then
return part.Position
end;
return Vector3.new(0, 0, 0)
end;
function ESP:_CreateDrawingObject(type, properties)
local obj = Drawing.new(type)
for k, v in pairs(properties) do
obj[k] = v
end;
obj.Visible = true;
obj.ZIndex = self.Config.ZIndex;
table.insert(self._drawingObjects, obj)
return obj
end;
function ESP:_UpdateDrawingObject(obj, properties)
for k, v in pairs(properties) do
obj[k] = v
end
end;
function ESP:_ClearDrawingObjects()
for _, obj in ipairs(self._drawingObjects) do
obj:Remove()
end;
self._drawingObjects = {}
end;
function ESP:DrawHealthBar(part, screenPos, boxWidth, boxHeight)
if not self.Config.ShowHealthBars then
return
end;
if not self.Callbacks.partToHealthCallback then
return
end;
local healthInfo = self.Callbacks.partToHealthCallback(part)
if not healthInfo then
return
end;
local currentHealth = healthInfo.currentHealth or healthInfo[1]
local maxHealth = healthInfo.maxHealth or healthInfo[2]
if not currentHealth or not maxHealth or maxHealth <= 0 then
return
end;
local healthPercent = math.clamp(currentHealth / maxHealth, 0, 1)
local barWidth = boxWidth * healthPercent;
local barPos = Vector2.new(screenPos.X - (boxWidth / 2), screenPos.Y - boxHeight - self.Config.HealthBarHeight - 2)
local bgBar = self:_CreateDrawingObject("Square", {
Position = barPos,
Size = Vector2.new(boxWidth, self.Config.HealthBarHeight),
Color = Color3.new(0.3, 0.3, 0.3),
Transparency = 0.2,
Thickness = 1,
Filled = true
})
if barWidth > 0 then
local healthBar = self:_CreateDrawingObject("Square", {
Position = barPos,
Size = Vector2.new(barWidth, self.Config.HealthBarHeight),
Color = self:GetHealthColor(currentHealth, maxHealth),
Transparency = 0,
Thickness = 1,
Filled = true
})
end;
local healthText = string.format("%.0f/%.0f", currentHealth, maxHealth)
local textPos = Vector2.new(screenPos.X, barPos.Y - 2)
local textObj = self:_CreateDrawingObject("Text", {
Position = textPos,
Text = healthText,
Color = Color3.new(1, 1, 1),
Size = self.Config.FontSize - 2,
Center = true,
Font = self.Config.NameFont,
Transparency = 0
})
local outlineObj = self:_CreateDrawingObject("Text", {
Position = Vector2.new(textPos.X + 1, textPos.Y + 1),
Text = healthText,
Color = Color3.new(0, 0, 0),
Size = self.Config.FontSize - 2,
Center = true,
Font = self.Config.NameFont,
Transparency = 0
})
end;
function ESP:DrawTools(part, screenPos, boxWidth, boxHeight)
if not self.Config.ShowTools then
return
end;
if not self.Callbacks.partToToolsToRenderCallback then
return
end;
local tools = self.Callbacks.partToToolsToRenderCallback(part)
if not tools or #tools == 0 then
return
end;
local startX = screenPos.X - (boxWidth / 2)
local startY = screenPos.Y + boxHeight + 5;
local iconSize = self.Config.ToolIconSize;
local spacing = 5;
for i, tool in ipairs(tools) do
local toolPart = tool.toolPart or tool[1]
local toolName = tool.name or tool[2] or "Unknown"
if toolPart and toolPart:IsA("BasePart") then
local iconPos = Vector2.new(startX + (i - 1) * (iconSize + spacing), startY)
self:_CreateDrawingObject("Square", {
Position = iconPos,
Size = Vector2.new(iconSize, iconSize),
Color = Color3.new(0.2, 0.2, 0.2),
Transparency = 0.2,
Thickness = 1,
Filled = true
})
self:_CreateDrawingObject("Square", {
Position = iconPos,
Size = Vector2.new(iconSize, iconSize),
Color = Color3.new(1, 1, 1),
Transparency = 0.5,
Thickness = 1,
Filled = false
})
local textPos = Vector2.new(iconPos.X + iconSize / 2, iconPos.Y + iconSize + 2)
self:_CreateDrawingObject("Text", {
Position = textPos,
Text = toolName,
Color = Color3.new(1, 1, 1),
Size = self.Config.FontSize - 2,
Center = true,
Font = self.Config.NameFont,
Transparency = 0
})
local toolScreenPos = self:WorldToScreen(toolPart.Position)
if toolScreenPos then
self:_CreateDrawingObject("Line", {
From = screenPos,
To = toolScreenPos,
Color = Color3.new(1, 1, 0),
Transparency = 0.5,
Thickness = 1
})
end
end
end
end;
function ESP:DrawNameAndDistance(part, screenPos, partName, distance)
if not self.Config.ShowNames and not self.Config.ShowDistance then
return
end;
local text = ""
if self.Config.ShowNames then
text = partName or "Unknown"
end;
if self.Config.ShowDistance and distance then
local distText = string.format(" [%.0fm]", distance)
text = text .. distText
end;
if text ~= "" then
local textPos = Vector2.new(screenPos.X, screenPos.Y - 25)
self:_CreateDrawingObject("Text", {
Position = Vector2.new(textPos.X + 1, textPos.Y + 1),
Text = text,
Color = Color3.new(0, 0, 0),
Size = self.Config.FontSize,
Center = true,
Font = self.Config.NameFont,
Transparency = 0
})
self:_CreateDrawingObject("Text", {
Position = textPos,
Text = text,
Color = self.Config.NameColor,
Size = self.Config.FontSize,
Center = true,
Font = self.Config.NameFont,
Transparency = 0
})
end
end;
function ESP:DrawBox(part, screenPos, boxWidth, boxHeight, distance)
if not self.Config.ShowBoxes then
return
end;
local topLeft = Vector2.new(screenPos.X - (boxWidth / 2), screenPos.Y - boxHeight)
local boxColor = self.Config.BoxColor;
if self.Config.ShowHealthBars and self.Callbacks.partToHealthCallback then
local healthInfo = self.Callbacks.partToHealthCallback(part)
if healthInfo then
local currentHealth = healthInfo.currentHealth or healthInfo[1]
local maxHealth = healthInfo.maxHealth or healthInfo[2]
if currentHealth and maxHealth then
boxColor = self:GetHealthColor(currentHealth, maxHealth)
end
end
end;
self:_CreateDrawingObject("Square", {
Position = topLeft,
Size = Vector2.new(boxWidth, boxHeight),
Color = boxColor,
Transparency = 0,
Thickness = self.Config.BoxThickness,
Filled = false
})
local accentSize = math.min(10, boxWidth * 0.2)
local accentColor = Color3.new(1, 1, 1)
self:_CreateDrawingObject("Line", {
From = topLeft,
To = Vector2.new(topLeft.X + accentSize, topLeft.Y),
Color = accentColor,
Transparency = 0.2,
Thickness = 2
})
self:_CreateDrawingObject("Line", {
From = topLeft,
To = Vector2.new(topLeft.X, topLeft.Y + accentSize),
Color = accentColor,
Transparency = 0.2,
Thickness = 2
})
local topRight = Vector2.new(topLeft.X + boxWidth, topLeft.Y)
self:_CreateDrawingObject("Line", {
From = Vector2.new(topRight.X - accentSize, topRight.Y),
To = topRight,
Color = accentColor,
Transparency = 0.2,
Thickness = 2
})
self:_CreateDrawingObject("Line", {
From = topRight,
To = Vector2.new(topRight.X, topRight.Y + accentSize),
Color = accentColor,
Transparency = 0.2,
Thickness = 2
})
local bottomLeft = Vector2.new(topLeft.X, topLeft.Y + boxHeight)
self:_CreateDrawingObject("Line", {
From = bottomLeft,
To = Vector2.new(bottomLeft.X + accentSize, bottomLeft.Y),
Color = accentColor,
Transparency = 0.2,
Thickness = 2
})
self:_CreateDrawingObject("Line", {
From = bottomLeft,
To = Vector2.new(bottomLeft.X, bottomLeft.Y - accentSize),
Color = accentColor,
Transparency = 0.2,
Thickness = 2
})
local bottomRight = Vector2.new(topLeft.X + boxWidth, topLeft.Y + boxHeight)
self:_CreateDrawingObject("Line", {
From = Vector2.new(bottomRight.X - accentSize, bottomRight.Y),
To = bottomRight,
Color = accentColor,
Transparency = 0.2,
Thickness = 2
})
self:_CreateDrawingObject("Line", {
From = bottomRight,
To = Vector2.new(bottomRight.X, bottomRight.Y - accentSize),
Color = accentColor,
Transparency = 0.2,
Thickness = 2
})
end;
function ESP:_UpdateCache()
local currentTime = tick()
if currentTime - self._cache.lastUpdate < self._cache.updateInterval then
return
end;
self._cache.lastUpdate = currentTime;
self._cache.parts = {}
self._cache.health = {}
self._cache.tools = {}
if self.Callbacks.getPartsToRenderCallback then
local parts = self.Callbacks.getPartsToRenderCallback()
if parts then
for i, part in ipairs(parts) do
self._cache.parts[#self._cache.parts + 1] = part;
if self.Callbacks.partToHealthCallback then
local health = self.Callbacks.partToHealthCallback(part)
if health then
self._cache.health[part] = health
end
end;
if self.Callbacks.partToToolsToRenderCallback then
local tools = self.Callbacks.partToToolsToRenderCallback(part)
if tools then
self._cache.tools[part] = tools
end
end
end
end
end
end;
function ESP:_OnRender()
if not self.Config.Enabled then
return
end;
self:_ClearDrawingObjects()
self:_UpdateCache()
for _, part in ipairs(self._cache.parts) do
if part and part.Parent then
local partPosition = self:GetPartPosition(part)
local screenPos, distance = self:WorldToScreen(partPosition)
if screenPos and distance <= self.Config.MaxDistance then
local boxWidth, boxHeight = self:GetPartBoxSize(part)
local partName = part.Name;
if part:IsA("Model") and part:FindFirstChild("Humanoid") then
local humanoid = part:FindFirstChild("Humanoid")
if humanoid.DisplayName and humanoid.DisplayName ~= "" then
partName = humanoid.DisplayName
end
end;
self:DrawBox(part, screenPos, boxWidth, boxHeight, distance)
self:DrawHealthBar(part, screenPos, boxWidth, boxHeight)
self:DrawNameAndDistance(part, screenPos, partName, distance)
self:DrawTools(part, screenPos, boxWidth, boxHeight)
end
end
end;
for _, obj in ipairs(self._activeObjects) do
if obj.type == "circle" and obj.position then
local screenPos = self:WorldToScreen(obj.position)
if screenPos then
self:_CreateDrawingObject("Circle", {
Position = screenPos,
Radius = obj.radius,
Color = obj.color,
Transparency = obj.transparency or 0,
Thickness = obj.thickness or 2,
Filled = obj.filled or false,
NumSides = 32
})
end
elseif obj.type == "line" and obj.from and obj.to then
local fromScreen = self:WorldToScreen(obj.from)
local toScreen = self:WorldToScreen(obj.to)
if fromScreen and toScreen then
self:_CreateDrawingObject("Line", {
From = fromScreen,
To = toScreen,
Color = obj.color,
Transparency = obj.transparency or 0,
Thickness = obj.thickness or 1
})
end
end
end
end;
function ESP:SetGetPartsToRenderCallback(callback)
self.Callbacks.getPartsToRenderCallback = callback
end;
function ESP:SetPartToHealthCallback(callback)
self.Callbacks.partToHealthCallback = callback
end;
function ESP:SetPartToToolsToRenderCallback(callback)
self.Callbacks.partToToolsToRenderCallback = callback
end;
function ESP:ClearCallbacks()
self.Callbacks.getPartsToRenderCallback = nil;
self.Callbacks.partToHealthCallback = nil;
self.Callbacks.partToToolsToRenderCallback = nil
end;
function ESP:AddObject(object)
self._activeObjects[#self._activeObjects + 1] = object;
return object
end;
function ESP:RemoveObject(object)
for i, obj in ipairs(self._activeObjects) do
if obj == object then
table.remove(self._activeObjects, i)
break
end
end
end;
function ESP:ClearObjects()
self._activeObjects = {}
end;
function ESP:SetConfig(newConfig)
for k, v in pairs(newConfig) do
self.Config[k] = v
end
end;
function ESP:Toggle()
self.Config.Enabled = not self.Config.Enabled;
return self.Config.Enabled
end;
function ESP:Init()
if self._renderConnection then
self:_Cleanup()
end;
self._renderConnection = game:GetService("RunService").RenderStepped:Connect(function()
self:_OnRender()
end)
end;
function ESP:_Cleanup()
if self._renderConnection then
self._renderConnection:Disconnect()
self._renderConnection = nil
end;
self:_ClearDrawingObjects()
end;
function ESP:Destroy()
self:_Cleanup()
self._activeObjects = {}
self:ClearCallbacks()
self._cache = {
parts = {},
health = {},
tools = {},
lastUpdate = 0,
updateInterval = 0.1
}
end;
function ESP:ForceUpdate()
self._cache.lastUpdate = 0;
self:_UpdateCache()
end;
end
local Config = {
Enabled = true,
ShowHealthBars = false,
ShowNames = false,
ShowBoxes = true,
ShowDistance = false,
ShowTools = false,
BoxThickness = 2,
NameFont = 1,
FontSize = 14,
NameColor = Color3.new(1, 0, 0),
BoxColor = Color3.new(1, 0, 0),
HealthBarWidth = 2,
HealthBarHeight = 12,
MaxDistance = 999,
ToolIconSize = 16,
ZIndex = 2,
}
ESP:SetConfig(Config)
local function GetEnemySoldiers()
local Enemies, FirstPersonViewID = {}, ClientState.fpv_sol_id
local MyTeam = SoldierTeams[FirstPersonViewID]
for PlayerID, IsSpawned in SoldiersSpawned do
if IsSpawned and SoldiersAlive[PlayerID] and PlayerID ~= FirstPersonViewID then
local EnemyTeam = SoldierTeams[PlayerID]
if EnemyTeam and EnemyTeam ~= MyTeam then
local Character = SoldierModels[PlayerID]
if Character then
table.insert(Enemies, {
ID = PlayerID,
Character = Character,
Team = EnemyTeam,
})
end
end
end
end
return Enemies
end
ESP:SetGetPartsToRenderCallback(function()
local Parts, Enemies = {}, GetEnemySoldiers()
for _, Enemy in Enemies do
if Enemy.Character and Enemy.Character.PrimaryPart then
table.insert(Parts, Enemy.Character)
end
end
return Parts
end)
ESP:Init()
]])Review the source before using it. Executions count successful copies, capped at 10 per user and network per script in 24 hours.
Community discussion
0Start the conversation.


Your community, in one place