Script
-- NOVA v3.38 / Native adapters and shared shooter controls.
local Players=game:GetService("Players")
local UIS=game:GetService("UserInputService")
local Run=game:GetService("RunService")
local Tween=game:GetService("TweenService")
local Http=game:GetService("HttpService")
local LP=Players.LocalPlayer
if not LP then return end
local FORCE_MOBILE=nil -- nil = automatic device detection.
local TEST_VIEWPORT=nil -- Internal layout test only.
local preferredTouch=false
pcall(function()preferredTouch=UIS.PreferredInput==Enum.PreferredInput.Touch end)
local mobile=UIS.TouchEnabled and (preferredTouch or not UIS.KeyboardEnabled or not UIS.MouseEnabled)
if FORCE_MOBILE~=nil then mobile=FORCE_MOBILE end
if not mobile and (not UIS.KeyboardEnabled or not UIS.MouseEnabled) then warn("NOVA requires touch or keyboard/mouse.");return end
local deviceName=mobile and "MOBILE" or "PC"
local pg=LP:WaitForChild("PlayerGui")
local saved={}
for _,name in ipairs({"NovaPC","NovaPC2"}) do local old=pg:FindFirstChild(name); if old then saved=old:GetAttributes(); old:Destroy() end end
local C={InfiniteAmmo=false,AutoReload=false,AutoClicker=false,ClickRate=10,NoCooldown=false,TriggerBot=false,AutoShoot=false,FireRate=6,FireDelay=80,FireAngle=2.5,FPSDetails=true,FPSGraph=true,FPSCorner="Top left",WatermarkDetails=true,WatermarkCorner="Top left",HUDScale=100,HUDOpacity=88,
AimThroughWalls=false,PlayerTarget="",PlayerStandOff=5,AimPriority="Crosshair",AimFallback=true,AimResponse="Smooth",
AimPrediction=false,AimLead=60,AimRetention=35,Fly=false,FlySpeed=50,FlyVerticalSpeed=35,FlyBoost=2,
Hitboxes=false,HitboxDisplay=true,HitboxPart="Head",HitboxSize=18,HitboxOpacity=65,HitboxTeams=false,WallShots=false,
TravelSlot="1",TravelHeight=0,TravelForward=0,TravelFacing=true,TravelStop=true,
TravelRemember=false,TravelMarker=false,SpeedOverride=false,WalkSpeed=16,
JumpOverride=false,JumpPower=50,JumpHeight=7,GravityOverride=false,Gravity=196.2,
AutoRotateOverride=false,AutoRotate=true,ZoomOverride=false,MinZoom=0.5,MaxZoom=128,
ViewMode="Game default",CameraOffsetOverride=false,CameraHeight=0,CameraSide=0,
Aim=false,ESP=true,ESPAll=true,ESPUnlimited=true,ESPInterval=50,Names=true,Health=true,Distance=true,Through=true,Teams=false,Visibility=true,
Circle=true,Sticky=true,FOV=180,Speed=16,Range=1500,Opacity=70,Part="Head",Mode="Hold RMB",
Origin="Screen center",Color="Silver",Motion=true,Backdrop=68,
AnimationSpeed=100,Parallax=true,Notifications=true,Background="Chrome",
FullBright=false,CustomLight=false,LightBrightness=2,LightExposure=0,AmbientLevel=70,
TimeLock=false,DayTime=14,NoShadows=false,NoFog=false,NoBloom=false,NoBlur=false,
NoSunRays=false,NoColor=false,NoDOF=false,CameraOverride=false,CameraFOV=70,
ShowStatus=true,ShowFPS=true,Watermark=true,QuickCursor=true,ShowAimPad=true,
AimPadSize=76,UISize=100,HideRingMenu=true,Crosshair=false,CrosshairSize=8,CrosshairGap=4,
CrosshairStyle="Plus",LabelSize=12,LabelHeight=3,LabelRange=1500,OutlineFade=5}
for k,v in pairs(C) do if typeof(saved[k])==typeof(v) then C[k]=saved[k] end end
for key,value in pairs(C)do if type(value)=="boolean"then C[key]=false end end
C.ViewMode="Game default"
C.Color="Background"
C.Fly=false;C.WallShots=false;C.TriggerBot=false;C.AutoShoot=false;C.NoCooldown=false;C.InfiniteAmmo=false;C.AutoReload=false;C.AutoClicker=false
if saved.Version~="3.14" and saved.Version~="3.15" and saved.Version~="3.16" and saved.Version~="3.17" and saved.Version~="3.18" and saved.Version~="3.19" then C.FPSCorner="Top left";C.WatermarkCorner="Top left" end
if C.HitboxPart=="HumanoidRootPart" then C.HitboxPart="Head" end
if saved.Version~="3.9" and saved.Version~="3.10" and saved.Version~="3.11" and saved.Version~="3.12" and saved.Version~="3.13" and saved.Version~="3.14" and saved.Version~="3.15" and saved.Version~="3.16" and saved.Version~="3.17" and saved.Version~="3.18" and saved.Version~="3.19" then C.HitboxSize=math.max(18,C.HitboxSize);C.Speed=32 end
if mobile then
if C.Mode=="Hold RMB" then C.Mode="Hold AIM" elseif C.Mode=="Toggle RMB" then C.Mode="Toggle AIM" end
C.Origin="Screen center"
elseif C.Mode=="Hold AIM" then C.Mode="Hold RMB"
elseif C.Mode=="Toggle AIM" then C.Mode="Toggle RMB" end
local backgroundList={
{name="Chrome",file="liquid-metal.png"},
{name="Pearl",file="pearl.png"},
{name="Neon Tide",file="neon-tide.png"},
{name="Violet Haze",file="violet-haze.png",stretch=true},
{name="Ember",file="ember.png"},
{name="Nebula",file="nebula.png"},
{name="Lava Glow",file="lava-glow.png"}
}
local backgroundIndex={}
for i,entry in ipairs(backgroundList) do backgroundIndex[entry.name]=i end
if not backgroundIndex[C.Background] then C.Background="Chrome" end
local themeProfiles={
Chrome={primary=Color3.fromRGB(234,237,244),muted=Color3.fromRGB(154,160,176),accent=Color3.fromRGB(223,226,233)},
Pearl={primary=Color3.fromRGB(247,237,255),muted=Color3.fromRGB(195,179,211),accent=Color3.fromRGB(227,207,249)},
["Neon Tide"]={primary=Color3.fromRGB(143,248,222),muted=Color3.fromRGB(129,189,194),accent=Color3.fromRGB(83,232,202)},
["Violet Haze"]={primary=Color3.fromRGB(227,198,255),muted=Color3.fromRGB(177,150,204),accent=Color3.fromRGB(190,142,249)},
Ember={primary=Color3.fromRGB(255,213,156),muted=Color3.fromRGB(207,166,125),accent=Color3.fromRGB(255,170,81)},
Nebula={primary=Color3.fromRGB(250,185,232),muted=Color3.fromRGB(191,150,205),accent=Color3.fromRGB(237,131,213)},
["Lava Glow"]={primary=Color3.fromRGB(255,207,142),muted=Color3.fromRGB(205,149,178),accent=Color3.fromRGB(255,151,83)}
}
local currentTheme=themeProfiles[C.Background]
local palettes={Silver=Color3.fromRGB(223,226,233),Violet=Color3.fromRGB(174,153,255),
Cyan=Color3.fromRGB(126,224,239),Rose=Color3.fromRGB(244,151,185),Lime=Color3.fromRGB(188,232,166)}
palettes.Background=currentTheme.accent
local ink=currentTheme.primary
local muted=currentTheme.muted
local bg=Color3.fromRGB(10,11,14)
local card=Color3.fromRGB(23,24,29)
local cons,records,paints={}, {}, {}
local applyWorld,restoreWorld
local notify
local switchBackground
local applyTheme
local tabNames={"Game","Aim","Combat","Visuals","Travel","Extras","Commands","Bot","World","Interface","Tools","Settings"}
local alive,free,focus,latch=true,true,true,false
local selected,drag,sliding
local aimTouch,touchHolding=nil,false
local menuOpen=true
local lastMouse,lastIcon=UIS.MouseBehavior,UIS.MouseIconEnabled
local uniqueId=tostring(LP.UserId).."_"..tostring(os.clock()):gsub("%W","")
pcall(function()uniqueId=Http:GenerateGUID(false)end)
local binding="Nova2_"..uniqueId
local traceError=(debug and debug.traceback) or function(err)return tostring(err)end
local function make(kind,props,parent)
local o=Instance.new(kind);for k,v in pairs(props) do o[k]=v end;if o:IsA("GuiObject") and props.BackgroundColor3==ink then o:SetAttribute("ThemeFill","Primary") end
o.Parent=parent;return o
end
local function on(signal,fn) local c=signal:Connect(fn);table.insert(cons,c);return c end
local function round(o,r) make("UICorner",{CornerRadius=UDim.new(0,r or 12)},o) end
local anims={}
local function motionDuration(value) return C.Motion and value/math.max(.5,C.AnimationSpeed/100) or 0 end
local function animate(o,props,duration,easing)
if not alive or not o.Parent then return end
local state=anims[o];if not state then state={};anims[o]=state end
for property,value in pairs(props) do
if state[property] then state[property]:Cancel() end
if not C.Motion or duration==0 then
o[property]=value;state[property]=nil
else
local tw=Tween:Create(o,TweenInfo.new(motionDuration(duration or .24),easing or Enum.EasingStyle.Quint,Enum.EasingDirection.Out),{[property]=value})
anims[o]=state;state[property]=tw
tw.Completed:Once(function()
if state[property]==tw then state[property]=nil end
if next(state)==nil and anims[o]==state then anims[o]=nil end
end)
tw:Play()
end
end
if next(state)==nil then anims[o]=nil end
end
local function text(parent,value,size,color,pos,dimensions)
local label=make("TextLabel",{BackgroundTransparency=1,Text=value,TextSize=size or 13,
TextColor3=color or ink,Font=Enum.Font.GothamMedium,TextXAlignment=Enum.TextXAlignment.Left,
TextTruncate=Enum.TextTruncate.AtEnd,Position=pos or UDim2.new(),Size=dimensions or UDim2.new(1,0,1,0)},parent)
label:SetAttribute("ThemeRole",color==muted and "Muted" or "Primary")
return label
end
local function outline(o,transparency)
local edge=make("UIStroke",{Color=muted,Transparency=transparency or .85,Thickness=1},o)
edge:SetAttribute("ThemeEdge",true);return edge
end
local function button(parent,name,value,pos,size)
local b=make("TextButton",{Name=name,Text=value,Position=pos,Size=size,
Font=Enum.Font.GothamMedium,TextSize=11,TextColor3=ink,AutoButtonColor=false,
BackgroundColor3=card,BackgroundTransparency=.15,BorderSizePixel=0,ClipsDescendants=true},parent)
round(b,10)
b:SetAttribute("ThemeRole","Primary")
if parent:IsA("ScreenGui") then b.ZIndex=10 end
b:SetAttribute("RestColor",card);b:SetAttribute("RestAlpha",.15)
local border=outline(b,.82);border.Name="ButtonEdge"
local press=make("UIScale",{Name="Press",Scale=1},b)
local hovered=false
local function paintHover()
local col=b:GetAttribute("RestColor") or card
animate(b,{BackgroundColor3=hovered and col:Lerp(ink,.12) or col,
BackgroundTransparency=hovered and .06 or (b:GetAttribute("RestAlpha") or .15)},.2)
animate(border,{Transparency=hovered and .34 or .82},.2)
end
on(b.MouseEnter,function() hovered=true;paintHover() end)
on(b.MouseLeave,function() hovered=false;paintHover();animate(press,{Scale=1},.25,Enum.EasingStyle.Back) end)
on(b.InputBegan,function(i)
if i.UserInputType==Enum.UserInputType.MouseButton1 or i.UserInputType==Enum.UserInputType.Touch then animate(press,{Scale=.96},.1) end
end)
on(b.InputEnded,function(i)
if i.UserInputType==Enum.UserInputType.MouseButton1 or i.UserInputType==Enum.UserInputType.Touch then animate(press,{Scale=1},.3,Enum.EasingStyle.Back) end
end)
local ripple
on(b.Activated,function(input)
animate(press,{Scale=1},.3,Enum.EasingStyle.Back)
if not C.Motion then return end
if ripple then ripple:Destroy() end
local p=Vector2.new(b.AbsoluteSize.X/2,b.AbsoluteSize.Y/2)
if input then p=Vector2.new(input.Position.X,input.Position.Y)-b.AbsolutePosition end
ripple=make("Frame",{Name="Ripple",AnchorPoint=Vector2.new(.5,.5),Position=UDim2.fromOffset(p.X,p.Y),
Size=UDim2.fromOffset(2,2),BorderSizePixel=0,BackgroundColor3=ink,BackgroundTransparency=.82,
ZIndex=3},b);round(ripple,1000)
local current=ripple;local diameter=math.max(b.AbsoluteSize.X,b.AbsoluteSize.Y)*2.1
animate(current,{Size=UDim2.fromOffset(diameter,diameter),BackgroundTransparency=1},.55)
task.delay(motionDuration(.58),function() if current.Parent then current:Destroy() end end)
end)
return b
end
local gui=make("ScreenGui",{Name="NovaPC2",IgnoreGuiInset=true,ResetOnSpawn=false,
DisplayOrder=1000,ZIndexBehavior=Enum.ZIndexBehavior.Sibling},pg)
if mobile then pcall(function()gui.ScreenInsets=Enum.ScreenInsets.CoreUISafeInsets end)end
local world=make("Folder",{Name=binding},workspace)
local overlay=make("Frame",{Name="Overlay",Size=UDim2.fromScale(1,1),BackgroundTransparency=1},gui)
local root=make("CanvasGroup",{Name="Window",AnchorPoint=Vector2.new(.5,.5),
Position=UDim2.fromScale(.5,.5),Size=UDim2.fromOffset(880,680),GroupTransparency=1,
BackgroundColor3=bg,BorderSizePixel=0,ZIndex=5},gui)
round(root,20)
local halo=make("Frame",{Name="ChromeHalo",BackgroundTransparency=1,AnchorPoint=Vector2.new(.5,.5),
Size=UDim2.fromOffset(836,626),Position=root.Position,ZIndex=4,BorderSizePixel=0},gui);round(halo,25)
local haloEdge=outline(halo,.92);haloEdge.Thickness=8
local scale=make("UIScale",{Scale=1},root)
local reveal=make("NumberValue",{Name="Reveal",Value=.93},gui)
local border=outline(root,.32)
make("UIGradient",{Color=ColorSequence.new({
ColorSequenceKeypoint.new(0,Color3.fromRGB(88,89,99)),
ColorSequenceKeypoint.new(.28,Color3.fromRGB(245,245,250)),
ColorSequenceKeypoint.new(.55,Color3.fromRGB(76,77,88)),
ColorSequenceKeypoint.new(1,Color3.fromRGB(197,200,211))}),Rotation=25},border)
local assetCache={}
local function backgroundAsset(entry)
if assetCache[entry.name] then return assetCache[entry.name] end
local providers={getcustomasset,getsynasset,get_custom_asset}
for i=1,3 do
local provider=providers[i]
if type(provider)=="function" then
local ok,result=pcall(provider,"NOVA/"..entry.file)
if ok and type(result)=="string" and result~="" then
assetCache[entry.name]=result
return result
end
end
end
gui:SetAttribute("CompatibilityNote","Custom image API or installed image unavailable. Matching colors remain enabled.")
return ""
end
local initialBackground=backgroundList[backgroundIndex[C.Background]]
local image=backgroundAsset(initialBackground)
local liquid=make("ImageLabel",{Name="LiquidMetal",BackgroundTransparency=1,Image=image,
ScaleType=Enum.ScaleType.Crop,ImageTransparency=.12,Position=UDim2.fromScale(-.04,-.035),
Size=UDim2.new(1.08,0,0,280)},root)
local liquidSwap=make("ImageLabel",{Name="BackgroundBlend",BackgroundTransparency=1,Image=image,
ScaleType=initialBackground.stretch and Enum.ScaleType.Stretch or Enum.ScaleType.Crop,
ImageTransparency=1,Position=liquid.Position,Size=liquid.Size},root)
local backgroundMix=make("NumberValue",{Name="BackgroundMix",Value=1},gui)
local activeBackground=C.Background
local mist=make("ImageLabel",{Name="Reflections",BackgroundTransparency=1,Image=image,
ImageTransparency=.91,Rotation=180,ScaleType=Enum.ScaleType.Crop,
Position=UDim2.fromScale(-.03,.26),Size=UDim2.fromScale(1.08,.8)},root)
local veil=make("Frame",{Name="Vignette",BackgroundColor3=bg,BorderSizePixel=0,Size=UDim2.fromScale(1,1)},root)
make("UIGradient",{Rotation=90,Transparency=NumberSequence.new({
NumberSequenceKeypoint.new(0,.68),NumberSequenceKeypoint.new(.17,.62),
NumberSequenceKeypoint.new(.38,.04),NumberSequenceKeypoint.new(1,.02)})},veil)
local surface=make("Frame",{Name="GlassSweep",BackgroundColor3=ink,BackgroundTransparency=.94,
BorderSizePixel=0,Size=UDim2.fromScale(1,1)},root)
local surfaceLight=make("UIGradient",{Rotation=24,Offset=Vector2.new(-1,0),Transparency=NumberSequence.new({
NumberSequenceKeypoint.new(0,1),NumberSequenceKeypoint.new(.42,1),NumberSequenceKeypoint.new(.5,.15),
NumberSequenceKeypoint.new(.58,1),NumberSequenceKeypoint.new(1,1)})},surface)
local topLine=make("Frame",{BackgroundColor3=ink,BorderSizePixel=0,Position=UDim2.fromOffset(22,0),
Size=UDim2.new(1,-44,0,1)},root)
local shine=make("UIGradient",{Transparency=NumberSequence.new({
NumberSequenceKeypoint.new(0,1),NumberSequenceKeypoint.new(.4,1),
NumberSequenceKeypoint.new(.5,.05),NumberSequenceKeypoint.new(.6,1),NumberSequenceKeypoint.new(1,1)})},topLine)
local brand=text(root,"NOVA",35,ink,UDim2.fromOffset(25,27),UDim2.fromOffset(260,48))
brand.Font=Enum.Font.GothamBold
local chrome=make("UIGradient",{Rotation=75,Color=ColorSequence.new({
ColorSequenceKeypoint.new(0,Color3.fromRGB(255,255,255)),
ColorSequenceKeypoint.new(.45,Color3.fromRGB(182,185,195)),
ColorSequenceKeypoint.new(.54,Color3.fromRGB(250,250,255)),
ColorSequenceKeypoint.new(1,Color3.fromRGB(137,140,153))})},brand)
text(root,"S H O O T E R E D I T I O N / 3 . 3 8",9,Color3.fromRGB(188,191,201),
UDim2.fromOffset(28,78),UDim2.fromOffset(360,22))
local liveDot=make("Frame",{BackgroundColor3=ink,BorderSizePixel=0,
Position=UDim2.fromOffset(28,116),Size=UDim2.fromOffset(5,5)},root);round(liveDot,3)
local deviceBadge=text(root,deviceName.." CONNECTED",9,muted,UDim2.fromOffset(41,108),UDim2.fromOffset(190,20))
local header=make("Frame",{Name="Drag",BackgroundTransparency=1,Active=true,
Size=UDim2.new(1,-300,0,135)},root)
local cursor=button(root,"Cursor","",UDim2.new(1,-270,0,28),UDim2.fromOffset(158,32))
local minimize=button(root,"Minimize","—",UDim2.new(1,-100,0,28),UDim2.fromOffset(32,32))
local unload=button(root,"Unload","×",UDim2.new(1,-56,0,28),UDim2.fromOffset(32,32))
local heroTag=text(root,C.Background:upper(),10,Color3.fromRGB(177,180,193),
UDim2.new(1,-250,0,90),UDim2.fromOffset(225,24));heroTag.TextXAlignment=Enum.TextXAlignment.Right
make("Frame",{BackgroundColor3=ink,BackgroundTransparency=.9,BorderSizePixel=0,
Position=UDim2.fromOffset(24,143),Size=UDim2.new(1,-48,0,1)},root)
local side=make("ScrollingFrame",{Name="Navigation",BackgroundTransparency=1,BorderSizePixel=0,CanvasSize=UDim2.fromOffset(0,#tabNames*54+40),ScrollBarThickness=2,ScrollingEnabled=true,ScrollingDirection=Enum.ScrollingDirection.Y,
Position=UDim2.fromOffset(20,164),Size=UDim2.new(0,171,1,-224)},root)
text(side,"CONTROL ROOM",9,muted,UDim2.fromOffset(10,0),UDim2.fromOffset(150,20))
local rail=make("Frame",{BackgroundColor3=ink,BackgroundTransparency=.93,
Position=UDim2.fromOffset(191,166),Size=UDim2.new(0,1,1,-222),BorderSizePixel=0},root)
local pages,tabs={},{}
local ui={}
function ui.pointerBlocked(position)
for _,object in ipairs(pg:GetGuiObjectsAtPosition(position.X,position.Y)) do
if object:IsDescendantOf(gui) then
local node=object
while node and node~=gui do
if node:IsA("GuiButton") or node:IsA("TextBox") then return true end
node=node.Parent
end
end
end
return false
end
local activeTab="Aim"
local indicator=make("Frame",{Name="ActiveRail",BackgroundColor3=ink,BorderSizePixel=0,
Position=UDim2.fromOffset(1,44),Size=UDim2.fromOffset(2,20)},side);round(indicator,1)
local tabIndex={};for i,name in ipairs(tabNames) do tabIndex[name]=i end
local uiPagePosition=UDim2.fromOffset(214,208)
local compact=false
ui.searchBar=make("Frame",{Name="SearchBar",BackgroundColor3=Color3.fromRGB(19,22,29),BackgroundTransparency=.08,BorderSizePixel=0,
Position=UDim2.fromOffset(214,157),Size=UDim2.new(1,-238,0,38)},root);round(ui.searchBar,11);outline(ui.searchBar,.7)
text(ui.searchBar,"⌕",20,muted,UDim2.fromOffset(12,0),UDim2.fromOffset(24,38))
ui.search=make("TextBox",{Name="SearchControls",BackgroundTransparency=1,Text="",ClearTextOnFocus=false,
PlaceholderText="Search this tab...",PlaceholderColor3=muted,TextColor3=ink,Font=Enum.Font.Gotham,
TextSize=12,TextXAlignment=Enum.TextXAlignment.Left,Position=UDim2.fromOffset(40,0),Size=UDim2.new(1,-162,1,0)},ui.searchBar)
ui.searchCount=text(ui.searchBar,"",10,muted,UDim2.new(1,-112,0,0),UDim2.fromOffset(70,38));ui.searchCount.TextXAlignment=Enum.TextXAlignment.Right
ui.clear=button(ui.searchBar,"ClearSearch","×",UDim2.new(1,-34,0,5),UDim2.fromOffset(28,28));ui.clear.Visible=false
ui.empty=text(root,"No matching controls.\nTry another word or clear the search.",13,muted,UDim2.fromOffset(230,235),UDim2.new(1,-270,0,66))
ui.empty.Name="SearchEmpty";ui.empty.Visible=false;ui.empty.TextWrapped=true
function ui.applyFilter()
local page=pages[activeTab]
if not page then return end
local query=ui.search.Text:lower():match("^%s*(.-)%s*$")
local terms={};for word in query:gmatch("%S+") do terms[#terms+1]=word end
local count=0
for _,item in ipairs(page:GetChildren()) do
if item:IsA("GuiObject") then
if item.Name=="Heading" then item.Visible=query=="" and (not mobile or overlay.AbsoluteSize.Y>460)
else
local content=item.Name
if item:IsA("TextButton") then content..=" "..item.Text end
for _,label in ipairs(item:GetDescendants()) do
if label:IsA("TextLabel") then content..=" "..label.Text end
end
content=content:lower()
local match=item:GetAttribute("SearchBaseVisible")~=false
for _,term in ipairs(terms) do if not content:find(term,1,true) then match=false;break end end
item.Visible=match
if match then count+=1 end
end
end
end
ui.searchCount.Text=tostring(count)..(query=="" and " controls" or " found")
ui.clear.Visible=query~="";ui.empty.Visible=query~="" and count==0
gui:SetAttribute("SearchResults",count);gui:SetAttribute("SearchQuery",ui.search.Text)
end
function ui.layoutSearch()
ui.searchBar.Position=mobile and UDim2.fromOffset(14,140) or UDim2.fromOffset(214,157)
ui.searchBar.Size=mobile and UDim2.new(1,-28,0,36) or UDim2.new(1,-238,0,38)
ui.empty.Position=mobile and UDim2.fromOffset(20,210) or UDim2.fromOffset(230,235)
ui.empty.Size=mobile and UDim2.new(1,-40,0,66) or UDim2.new(1,-270,0,66)
end
on(ui.search:GetPropertyChangedSignal("Text"),function()if pages[activeTab] then pages[activeTab].CanvasPosition=Vector2.zero end;ui.applyFilter()end)
on(ui.clear.Activated,function()ui.search.Text="";ui.search:ReleaseFocus();ui.applyFilter()end)
local function selectTab(name)
activeTab=name
ui.search.Text="";ui.search.PlaceholderText="Search "..name:lower().." controls..."
heroTag.Text=name:upper().." / "..C.Background:upper()
for n,p in pairs(pages) do
p.Visible=n==name
tabs[n].TextColor3=n==name and ink or muted
tabs[n]:SetAttribute("RestAlpha",n==name and .08 or 1)
tabs[n]:SetAttribute("RestColor",n==name and Color3.fromRGB(46,47,55) or card)
animate(tabs[n],{BackgroundTransparency=n==name and .08 or 1,
BackgroundColor3=n==name and Color3.fromRGB(46,47,55) or card},.24)
for _,label in ipairs(tabs[n]:GetChildren()) do
if label:IsA("TextLabel") then label:SetAttribute("ThemeRole",n==name and "Primary" or "Muted");animate(label,{TextColor3=n==name and ink or muted},.2) end
end
end
if compact then
animate(indicator,{Position=UDim2.fromOffset((tabIndex[name]-1)*112+6,43),Size=UDim2.fromOffset(100,2)},.3)
side.CanvasPosition=Vector2.new(math.clamp((tabIndex[name]-1)*112-12,0,math.max(0,#tabNames*112-side.AbsoluteSize.X)),0)
else
side.CanvasPosition=Vector2.new(0,math.clamp(32+(tabIndex[name]-1)*54-80,0,math.max(0,#tabNames*54+40-side.AbsoluteSize.Y)))
animate(indicator,{Position=UDim2.fromOffset(1,44+(tabIndex[name]-1)*54),Size=UDim2.fromOffset(2,20)},.3)
end
gui:SetAttribute("ActiveTab",name)
local page=pages[name]
local index=0
for _,item in ipairs(page:GetChildren()) do
if item:IsA("GuiObject") then
local rowScale=item:FindFirstChild("RowReveal")
if rowScale then rowScale.Scale=C.Motion and .978 or 1 end
local visible=item.AbsolutePosition.Y+item.AbsoluteSize.Y>=page.AbsolutePosition.Y and item.AbsolutePosition.Y<page.AbsolutePosition.Y+page.AbsoluteSize.Y
if visible and C.Motion then
index+=1;local delayTime=math.min(index-1,5)*.028
for _,label in ipairs(item:GetDescendants()) do if label:IsA("TextLabel") then label.TextTransparency=1 end end
task.delay(motionDuration(delayTime),function()
if not alive or activeTab~=name or not item.Parent then return end
if rowScale then animate(rowScale,{Scale=1},.36,Enum.EasingStyle.Back) end
for _,label in ipairs(item:GetDescendants()) do if label:IsA("TextLabel") then animate(label,{TextTransparency=0},.3) end end
end)
else
if rowScale then rowScale.Scale=1 end
for _,label in ipairs(item:GetDescendants()) do if label:IsA("TextLabel") then label.TextTransparency=0 end end
end
end
end
page.Position=UDim2.new(uiPagePosition.X.Scale,uiPagePosition.X.Offset+12,uiPagePosition.Y.Scale,uiPagePosition.Y.Offset)
animate(page,{Position=uiPagePosition},.4)
ui.applyFilter()
end
for i,name in ipairs(tabNames) do
local glyph=({"◈","◎","▣","◈","⌖","✦","›","◉","☼","◇","⌘","⚙"})[i]
local tab=button(side,name,"",UDim2.fromOffset(8,32+(i-1)*54),UDim2.fromOffset(151,44))
tabs[name]=tab
local icon=text(tab,glyph,20,ink,UDim2.fromOffset(12,0),UDim2.fromOffset(28,44))
text(tab,name:upper(),10,ink,UDim2.fromOffset(44,0),UDim2.fromOffset(100,44))
tab.BackgroundTransparency=name==activeTab and .15 or 1
local page=make("ScrollingFrame",{Name=name,BackgroundTransparency=1,BorderSizePixel=0,
Position=uiPagePosition,Size=UDim2.new(1,-238,1,-270),
ScrollBarThickness=2,ScrollBarImageColor3=Color3.fromRGB(160,164,178),
ScrollBarImageTransparency=.5,CanvasSize=UDim2.new(),AutomaticCanvasSize=Enum.AutomaticSize.Y,
ScrollingDirection=Enum.ScrollingDirection.Y,Visible=name==activeTab},root)
make("UIListLayout",{Padding=UDim.new(0,8),SortOrder=Enum.SortOrder.LayoutOrder},page)
make("UIPadding",{PaddingRight=UDim.new(0,9),PaddingBottom=UDim.new(0,12)},page)
pages[name]=page
on(tab.Activated,function() selectTab(name) end)
end
local keybox=make("Frame",{BackgroundColor3=Color3.fromRGB(18,19,23),BackgroundTransparency=.15,
BorderSizePixel=0,Position=UDim2.fromOffset(8,239),Size=UDim2.fromOffset(151,132)},side);round(keybox,10);outline(keybox,.9)
keybox.Visible=false
text(keybox,"QUICK KEYS",9,muted,UDim2.fromOffset(12,10),UDim2.fromOffset(130,20))
for i,pair in ipairs({{"RMB","Aim"},{"U","Free cursor"},{"RSHIFT","Menu"}}) do
text(keybox,pair[1],9,ink,UDim2.fromOffset(12,39+(i-1)*27),UDim2.fromOffset(56,18))
text(keybox,pair[2],10,muted,UDim2.fromOffset(69,39+(i-1)*27),UDim2.fromOffset(80,18))
end
make("Frame",{BackgroundColor3=ink,BackgroundTransparency=.92,BorderSizePixel=0,
Position=UDim2.new(0,24,1,-46),Size=UDim2.new(1,-48,0,1)},root)
local status=text(root,"Initializing...",10,muted,UDim2.new(0,37,1,-34),UDim2.new(1,-164,0,21))
local statusDot=make("Frame",{BackgroundColor3=ink,BorderSizePixel=0,
Position=UDim2.new(0,25,1,-26),Size=UDim2.fromOffset(4,4)},root);round(statusDot,3)
text(root,"N / 03",10,muted,UDim2.new(1,-74,1,-34),UDim2.fromOffset(50,21))
local mini=button(gui,"Open","N O V A / OPEN",UDim2.fromOffset(20,20),UDim2.fromOffset(152,36))
mini.Visible=false
local floating=button(gui,"FreeMouse","",UDim2.fromOffset(183,20),UDim2.fromOffset(198,36))
local touchAim=button(gui,"TouchAim","HOLD AIM",UDim2.new(1,-98,1,-190),UDim2.fromOffset(76,76))
round(touchAim,38)
touchAim.Visible=mobile and not menuOpen and C.ShowAimPad
local function releaseTouch()
aimTouch=nil;touchHolding=false;latch=false
gui:SetAttribute("TouchHolding",false)
end
local function updateAimPad()
touchAim.Visible=mobile and not menuOpen and C.ShowAimPad
if mobile then touchAim.Size=UDim2.fromOffset(C.AimPadSize,C.AimPadSize);touchAim.AnchorPoint=Vector2.new(1,1) end
touchAim.Text=not C.Aim and "AIM\nOFF" or C.Mode=="Toggle AIM" and (latch and "AIM\nON" or "TAP\nAIM")
or C.Mode=="Always" and "AUTO\nAIM" or "HOLD\nAIM"
touchAim.TextColor3=(touchHolding or latch) and Color3.fromRGB(140,235,180) or ink
end
on(touchAim.InputBegan,function(i)
if mobile and C.Aim and not menuOpen and i.UserInputType==Enum.UserInputType.Touch and not aimTouch then
aimTouch=i;touchHolding=true;gui:SetAttribute("TouchHolding",true);updateAimPad()
end
end)
on(touchAim.InputEnded,function(i)
if i==aimTouch then aimTouch=nil;touchHolding=false;gui:SetAttribute("TouchHolding",false);updateAimPad() end
end)
on(touchAim.Activated,function()
if mobile and C.Mode=="Toggle AIM" and C.Aim and not menuOpen then latch=not latch;updateAimPad() end
end)
local function refresh()
if ui.enforceCapabilities then ui.enforceCapabilities() end
if switchBackground then switchBackground(C.Background) end
for k,v in pairs(C) do gui:SetAttribute(k,v) end
gui:SetAttribute("CursorFree",free)
cursor.Text=mobile and "CLOSE MENU" or (free and "◉ CURSOR FREE / U" or "◎ UNLOCK MOUSE / U")
floating.Text=free and "◉ MOUSE FREE / U TO LOCK" or "◎ UNLOCK MOUSE / U"
cursor.Modal=not mobile and free and root.Visible;floating.Modal=not mobile and free
floating.Visible=not mobile and C.QuickCursor
updateAimPad()
for _,fn in ipairs(paints) do fn() end
status.Visible=C.ShowStatus;statusDot.Visible=C.ShowStatus
if applyWorld then applyWorld() end
end
local toast=make("CanvasGroup",{Name="SettingToast",AnchorPoint=Vector2.new(.5,1),
Position=UDim2.new(.5,0,1,-36),Size=UDim2.fromOffset(290,70),GroupTransparency=1,
BackgroundColor3=Color3.fromRGB(23,24,30),BorderSizePixel=0,Visible=false,ZIndex=30},gui)
round(toast,13);outline(toast,.52)
local toastTitle=text(toast,"",13,ink,UDim2.fromOffset(16,10),UDim2.new(1,-32,0,23))
local toastValue=text(toast,"",11,muted,UDim2.fromOffset(16,34),UDim2.new(1,-32,0,20))
local toastLine=make("Frame",{BackgroundColor3=ink,BorderSizePixel=0,
Position=UDim2.new(0,0,1,-2),Size=UDim2.new(1,0,0,2)},toast)
local toastSerial=0
notify=function(title,value)
toastSerial+=1;local serial=toastSerial
if not C.Notifications then toast.Visible=false;return end
toastTitle.Text=title;toastValue.Text=value
toast.Visible=true;toast.GroupTransparency=1;toast.Position=UDim2.new(.5,0,1,-16)
toastLine.Size=UDim2.new(1,0,0,2)
animate(toast,{GroupTransparency=0,Position=UDim2.new(.5,0,1,-36)},.28)
animate(toastLine,{Size=UDim2.new(0,0,0,2)},1.6)
task.delay(math.max(1,motionDuration(1.6)),function()
if not alive or serial~=toastSerial then return end
animate(toast,{GroupTransparency=1,Position=UDim2.new(.5,0,1,-20)},.24)
task.delay(motionDuration(.26),function() if alive and serial==toastSerial then toast.Visible=false end end)
end)
end
local function setFree(value)
free=value;latch=false;selected=nil
if not mobile then
UIS.MouseBehavior=free and Enum.MouseBehavior.Default or Enum.MouseBehavior.LockCenter
UIS.MouseIconEnabled=free or lastIcon
end
refresh()
end
local transition=0
local function showMenu(value)
if value and C.EditorOpen then C.EditorOpen=false;local editor=gui:FindFirstChild("ScriptStudio");if editor then editor.Visible=false end end
transition+=1;local current=transition
menuOpen=value;gui:SetAttribute("MenuOpen",value);releaseTouch()
mini.Visible=mobile or not value;setFree(value)
if mobile then mini.Text=value and "CLOSE MENU" or "NOVA / MENU" end
if value then
root.Visible=true;root.GroupTransparency=1;reveal.Value=.94
animate(root,{GroupTransparency=0},.34);animate(reveal,{Value=1},.5,Enum.EasingStyle.Back)
else
animate(root,{GroupTransparency=1},.2);animate(reveal,{Value=.95},.2)
task.delay(motionDuration(.22),function() if alive and transition==current then root.Visible=false end end)
end
end
on(cursor.Activated,function() if mobile then showMenu(false) else setFree(not free) end end)
on(floating.Activated,function() setFree(not free) end)
on(minimize.Activated,function() showMenu(false) end)
on(mini.Activated,function() if mobile then showMenu(not menuOpen) else showMenu(true) end end)
local function heading(page,titleValue,subtitle)
local box=make("Frame",{Name="Heading",Size=UDim2.new(1,0,0,mobile and 66 or 72),BackgroundTransparency=1},page)
text(box,titleValue,mobile and 20 or 23,ink,UDim2.fromOffset(0,0),UDim2.new(1,0,0,32)).Font=Enum.Font.GothamBold
local sub=text(box,subtitle,11,muted,UDim2.fromOffset(1,34),UDim2.new(1,-4,0,30));sub.TextWrapped=true;sub.TextTruncate=Enum.TextTruncate.None
text(box,"/",11,muted,UDim2.new(1,-16,0,0),UDim2.fromOffset(16,28))
end
local function row(page,key,titleValue,detail,height)
local box=make("Frame",{Name=key.."Row",BackgroundColor3=Color3.fromRGB(22,23,28),BackgroundTransparency=.1,
BorderSizePixel=0,Size=UDim2.new(1,0,0,mobile and math.max(82,height or 82) or (height or 78))},page);round(box,11)
local stroke=outline(box,.89)
local rowScale=make("UIScale",{Name="RowReveal",Scale=1},box)
local rowTitle=text(box,titleValue,14,ink,UDim2.fromOffset(16,12),UDim2.new(1,-166,0,20));rowTitle.Name="RowTitle"
local rowDetail=text(box,detail,11,muted,UDim2.fromOffset(16,mobile and 48 or 38),UDim2.new(1,-32,0,28));rowDetail.Name="Detail";rowDetail.TextWrapped=true;rowDetail.TextYAlignment=Enum.TextYAlignment.Top;rowDetail.TextTruncate=Enum.TextTruncate.None
on(box.MouseEnter,function() animate(stroke,{Transparency=.56},.2);animate(rowScale,{Scale=1.004},.24) end)
on(box.MouseLeave,function() animate(stroke,{Transparency=.89},.3);animate(rowScale,{Scale=1},.3) end)
return box
end
local function toggle(page,key,titleValue,detail)
C[key]=false -- Every toggle is opt-in on each fresh execution.
local box=row(page,key,titleValue,detail)
local b=button(box,key,"",UDim2.new(1,mobile and -78 or -64,0,mobile and 3 or 13),UDim2.fromOffset(mobile and 62 or 46,mobile and 44 or 24))
local knob=make("Frame",{Name="Knob",BackgroundColor3=ink,BorderSizePixel=0,
Position=UDim2.fromOffset(4,mobile and 10 or 4),Size=UDim2.fromOffset(mobile and 24 or 16,mobile and 24 or 16)},b);round(knob,12)
box.RowTitle.Size=UDim2.new(1,-146,0,22)
local stateText=text(box,"OFF",9,muted,UDim2.new(1,mobile and -115 or -101,0,16),UDim2.fromOffset(30,18));stateText.Name="ToggleState"
local last
local function paint()
if last==C[key] then return end;last=C[key]
stateText.Text=C[key] and "ON" or "OFF";stateText.TextColor3=C[key] and ink or muted
local edge=box:FindFirstChildOfClass("UIStroke");if edge then edge.Color=C[key] and ink or muted;edge.Transparency=C[key] and .63 or .88 end
animate(knob,{Position=UDim2.fromOffset(C[key] and (mobile and 34 or 26) or 4,mobile and 10 or 4),
BackgroundColor3=C[key] and ink or Color3.fromRGB(100,103,116)},.34,Enum.EasingStyle.Back)
b:SetAttribute("RestColor",C[key] and Color3.fromRGB(76,79,91) or card)
animate(b,{BackgroundColor3=b:GetAttribute("RestColor")},.24)
end
table.insert(paints,paint)
on(b.Activated,function() if ui.canToggle and not ui.canToggle(key) then return end;C[key]=not C[key];selected=nil;refresh();if notify then notify(titleValue,C[key] and "Enabled" or "Disabled") end end)
end
local function cycle(page,key,titleValue,detail,values)
local box=row(page,key,titleValue,detail)
local b=button(box,key,"",UDim2.new(1,-160,0,mobile and 0 or 9),UDim2.fromOffset(142,mobile and 44 or 32))
table.insert(paints,function() b.Text=tostring(C[key]).." ›";b.TextColor3=ink end)
on(b.Activated,function()
local at=table.find(values,C[key]) or 0;C[key]=values[at % #values+1];selected=nil;refresh();if notify then notify(titleValue,tostring(C[key])) end
end)
end
local function slider(page,key,titleValue,detail,lo,hi,step)
local box=row(page,key,titleValue,detail,95)
if mobile then box.Detail.Position=UDim2.fromOffset(16,34);box.Detail.Size=UDim2.new(1,-32,0,26) end
local valueLabel=text(box,"",12,ink,UDim2.new(1,-90,0,12),UDim2.fromOffset(71,20))
valueLabel.TextXAlignment=Enum.TextXAlignment.Right
local displayed=make("NumberValue",{Value=C[key]},box)
valueLabel.Text=tostring(C[key])
on(displayed.Changed,function(value) valueLabel.Text=step<1 and string.format("%.1f",value) or tostring(math.floor(value+.5)) end)
local track=make("TextButton",{Name=key,Text="",AutoButtonColor=false,BackgroundColor3=Color3.fromRGB(51,53,63),
BorderSizePixel=0,BackgroundTransparency=1,Position=UDim2.new(0,17,0,mobile and 52 or 60),Size=UDim2.new(1,-34,0,mobile and 44 or 32)},box)
local trackLine=make("Frame",{BackgroundColor3=Color3.fromRGB(51,53,63),BorderSizePixel=0,
AnchorPoint=Vector2.new(0,.5),Position=UDim2.fromScale(0,.5),Size=UDim2.new(1,0,0,5)},track);round(trackLine,3)
local fill=make("Frame",{BackgroundColor3=ink,BorderSizePixel=0,AnchorPoint=Vector2.new(0,.5),Position=UDim2.fromScale(0,.5),Size=UDim2.new(0,0,0,5)},track);round(fill,3)
make("UIGradient",{Color=ColorSequence.new(Color3.fromRGB(111,114,128),ink)},fill)
local knob=make("Frame",{Name="Knob",AnchorPoint=Vector2.new(.5,.5),Size=UDim2.fromOffset(mobile and 20 or 12,mobile and 20 or 12),
BackgroundColor3=ink,BorderSizePixel=0,Position=UDim2.fromScale(0,.5)},track);round(knob,6)
outline(knob,.4)
local last
table.insert(paints,function()
if last==C[key] then return end;last=C[key]
local a=(C[key]-lo)/(hi-lo)
animate(fill,{Size=UDim2.new(a,0,0,5)},.18);animate(knob,{Position=UDim2.fromScale(a,.5)},.18)
animate(displayed,{Value=C[key]},.2)
end)
local function update(x)
local a=math.clamp((x-track.AbsolutePosition.X)/math.max(1,track.AbsoluteSize.X),0,1)
C[key]=math.clamp(math.floor((lo+a*(hi-lo))/step+.5)*step,lo,hi);refresh()
end
on(track.InputEnded,function(i)
if sliding and sliding.input==i then
sliding=nil;for _,p in pairs(pages) do p.ScrollingEnabled=true end
end
end)
on(track.InputBegan,function(i) if i.UserInputType==Enum.UserInputType.MouseButton1 or i.UserInputType==Enum.UserInputType.Touch then
sliding={update=update,input=i};page.ScrollingEnabled=false;update(i.Position.X)
end end)
end
-- Travel slots are scoped to this place; disk persistence is opt-in.
local travel={spots={},previous=nil,marker=nil,folder="nova-spots",loaded=false}
pcall(function()
local stash=saved.TravelSpots
if type(stash)=="string" then travel.spots=Http:JSONDecode(stash) end
end)
travel.path=travel.folder.."/"..tostring(game.PlaceId)..".json"
function travel.character()
local ch=LP.Character
local hrp=ch and ch:FindFirstChild("HumanoidRootPart")
local hum=ch and ch:FindFirstChildOfClass("Humanoid")
if not hrp or not hum or hum.Health<=0 then return nil end
return ch,hrp,hum
end
function travel.persist()
if not C.TravelRemember then return end
local ok,err=pcall(function()
assert(type(writefile)=="function" and type(makefolder)=="function","File saving unavailable")
if type(isfolder)~="function" or not isfolder(travel.folder) then pcall(makefolder,travel.folder) end
writefile(travel.path,Http:JSONEncode(travel.spots))
end)
if not ok and notify then notify("Spot storage",tostring(err)) end
end
function travel.load()
if travel.loaded or not C.TravelRemember then return end
travel.loaded=true
pcall(function()
if type(readfile)~="function" then return end
local parsed=Http:JSONDecode(readfile(travel.path))
if type(parsed)~="table" then return end
for i=1,8 do
local value=parsed[tostring(i)]
local valid=type(value)=="table" and #value==12
if valid then for _,n in ipairs(value) do if type(n)~="number" or n~=n or math.abs(n)==math.huge then valid=false;break end end end
if valid and not travel.spots[tostring(i)] then travel.spots[tostring(i)]=value end
end
end)
end
function travel.move(target,exact)
local ch,hrp=travel.character()
if not ch then notify("Teleport","Wait for your character to spawn.");return false end
local destination=exact and target or target+Vector3.new(0,C.TravelHeight,0)+target.LookVector*C.TravelForward
if not C.TravelFacing then destination=CFrame.new(destination.Position)*hrp.CFrame.Rotation end
local old=hrp.CFrame
local ok,err=pcall(function()
ch:PivotTo(destination*hrp.CFrame:ToObjectSpace(ch:GetPivot()))
if C.TravelStop then hrp.AssemblyLinearVelocity=Vector3.zero;hrp.AssemblyAngularVelocity=Vector3.zero end
end)
if not ok then notify("Teleport",tostring(err));return false end
travel.previous=old
notify("Teleport","Moved locally. The game server may adjust your position.")
return true
end
function travel.action(name,label,callback)
local b=button(pages.Travel,name,label,UDim2.new(),UDim2.new(1,0,0,48))
on(b.Activated,callback)
end
-- Live player selector; identities use UserId so display-name changes are safe.
travel.playerRow=row(pages.Travel,"PlayerTarget","Choose player","Tap NEXT to cycle through players in this server.",96)
travel.playerRow.RowTitle.Size=UDim2.new(1,-110,0,24)
travel.playerNext=button(travel.playerRow,"NextPlayer","NEXT",UDim2.new(1,-94,0,8),UDim2.fromOffset(78,36))
function travel.targetPlayer()
local id=tonumber(C.PlayerTarget)
if not id then return nil end
return Players:GetPlayerByUserId(id)
end
function travel.playerStatus()
local p=travel.targetPlayer()
local ch=p and p.Character
local h=ch and ch:FindFirstChildOfClass("Humanoid")
travel.playerRow.RowTitle.Text=p and p.DisplayName or "Choose player"
travel.playerRow.Detail.Text=p and ("@"..p.Name.." / "..(h and h.Health>0 and "Ready" or "Waiting for respawn")) or "Tap NEXT to cycle through players in this server."
gui:SetAttribute("TeleportTargetUserId",p and p.UserId or 0)
end
on(travel.playerNext.Activated,function()
local list={}
for _,p in ipairs(Players:GetPlayers()) do if p~=LP then table.insert(list,p) end end
table.sort(list,function(a,b)return a.Name:lower()<b.Name:lower()end)
if #list==0 then C.PlayerTarget="";travel.playerStatus();notify("Player travel","No other players are in this server.");return end
local at=0
for i,p in ipairs(list) do if tostring(p.UserId)==C.PlayerTarget then at=i;break end end
C.PlayerTarget=tostring(list[at%#list+1].UserId);travel.playerStatus();refresh()
end)
travel.action("GoToPlayer","GO TO SELECTED PLAYER",function()
local p=travel.targetPlayer()
if not p or p==LP then notify("Player travel","Choose a player with NEXT first.");return end
local ch=p.Character
local root=ch and ch:FindFirstChild("HumanoidRootPart")
local h=ch and ch:FindFirstChildOfClass("Humanoid")
if not root or not h or h.Health<=0 then notify("Player travel","This player has not spawned yet.");return end
travel.move(root.CFrame*CFrame.new(0,2,C.PlayerStandOff),true)
end)
slider(pages.Travel,"PlayerStandOff","Player arrival distance","Arrive behind the selected player, in studs.",2,25,1)
heading(pages.Travel,"Travel & movement","Save up to eight locations in this place. Options start disabled.")
cycle(pages.Travel,"TravelSlot","Saved spot slot","Select a slot before saving or travelling.",{"1","2","3","4","5","6","7","8"})
local spotInfo=row(pages.Travel,"SpotStatus","Selected location","Empty slot: save your current position first.")
travel.action("SaveTeleportSpot","SAVE TELEPORT SPOT",function()
travel.load()
local ch,hrp=travel.character()
if not ch then notify("Save spot","Wait for your character to spawn.");return end
travel.spots[C.TravelSlot]={hrp.CFrame:GetComponents()};travel.persist()
refresh();notify("Spot saved","Slot "..C.TravelSlot.." updated.")
end)
travel.action("GoToTeleportSpot","GO TO TELEPORT SPOT",function()
travel.load();local spot=travel.spots[C.TravelSlot]
if not spot then notify("Empty slot","Save a spot in slot "..C.TravelSlot.." first.");return end
travel.move(CFrame.new(table.unpack(spot)))
end)
travel.action("ReturnPreviousSpot","RETURN TO PREVIOUS POSITION",function()
if not travel.previous then notify("Return","Use Go to teleport spot first.");return end
travel.move(travel.previous,true)
end)
travel.action("ClearTeleportSpot","CLEAR SELECTED SPOT",function()
travel.spots[C.TravelSlot]=nil;travel.persist();refresh();notify("Spot cleared","Slot "..C.TravelSlot)
end)
toggle(pages.Travel,"TravelRemember","Remember saved spots","Opt in to saving these eight slots to a local file per place.")
toggle(pages.Travel,"TravelMarker","Saved spot marker","Show a local neon marker at the selected saved location.")
toggle(pages.Travel,"TravelFacing","Use saved direction","Face the same direction as when you saved the spot.")
toggle(pages.Travel,"TravelStop","Stop teleport momentum","Clear linear and angular velocity after moving.")
slider(pages.Travel,"TravelHeight","Arrival height offset","Extra vertical distance above the saved location.",0,30,1)
slider(pages.Travel,"TravelForward","Arrival forward offset","Move along the saved facing direction in studs.",-20,20,1)
heading(pages.Travel,"Movement controls","Local overrides can be limited by the game server.")
toggle(pages.Travel,"SpeedOverride","Walk speed override","Enable the walk speed slider below.")
slider(pages.Travel,"WalkSpeed","Walk speed","Character walking speed in studs per second.",0,150,1)
toggle(pages.Travel,"JumpOverride","Jump override","Uses the jump mode selected by the game.")
slider(pages.Travel,"JumpPower","Jump power","Used when the character uses JumpPower.",0,150,5)
slider(pages.Travel,"JumpHeight","Jump height","Used when the character uses JumpHeight.",0,50,1)
toggle(pages.Travel,"GravityOverride","Gravity override","Adjust local gravity. Restore by disabling.")
slider(pages.Travel,"Gravity","Gravity","Lower values produce slower falls.",0,300,5)
toggle(pages.Travel,"AutoRotateOverride","Rotation override","Enable the auto-rotate option below.")
toggle(pages.Travel,"AutoRotate","Auto rotate character","Turn the character toward movement when override is enabled.")
heading(pages.Travel,"Camera controls","Zoom limits and camera offsets restore when disabled.")
cycle(pages.Travel,"ViewMode","Camera perspective","Use the game default or force a camera perspective.",{"Game default","First person","Third person"})
toggle(pages.Travel,"ZoomOverride","Zoom distance override","Apply minimum and maximum camera zoom distances.")
slider(pages.Travel,"MinZoom","Minimum zoom","Maximum zoom is clamped above this distance.",0.5,30,0.5)
slider(pages.Travel,"MaxZoom","Maximum zoom","Maximum camera distance in studs.",1,500,1)
toggle(pages.Travel,"CameraOffsetOverride","Camera offset override","Adjust character camera height and shoulder offset.")
slider(pages.Travel,"CameraHeight","Camera height offset","Vertical offset from the normal camera position.",-5,15,0.5)
slider(pages.Travel,"CameraSide","Camera shoulder offset","Horizontal camera offset in studs.",-10,10,0.5)
travel.action("ResetTravelOverrides","RESTORE MOVEMENT & CAMERA",function()
for _,k in ipairs({"SpeedOverride","JumpOverride","GravityOverride","AutoRotateOverride","ZoomOverride","CameraOffsetOverride"}) do C[k]=false end
C.ViewMode="Game default";C.TravelMarker=false;refresh()
end)
function travel.update(own)
travel.playerStatus()
travel.load()
gui:SetAttribute("TravelSpots",Http:JSONEncode(travel.spots))
local spot=travel.spots[C.TravelSlot]
spotInfo.Detail.Text=spot and string.format("Slot %s: X %.1f / Y %.1f / Z %.1f",C.TravelSlot,spot[1],spot[2],spot[3]) or "Empty slot: save your current position first."
gui:SetAttribute("TravelSlot",C.TravelSlot);gui:SetAttribute("TravelSpotSaved",spot~=nil)
if C.TravelMarker and spot then
if not travel.marker then
travel.marker=make("Part",{Name="NovaSavedSpot",Anchored=true,CanCollide=false,CanTouch=false,CanQuery=false,
Material=Enum.Material.Neon,Shape=Enum.PartType.Ball,Size=Vector3.new(1,1,1),Transparency=.35},workspace)
end
travel.marker.CFrame=CFrame.new(spot[1],spot[2],spot[3]);travel.marker.Color=ink
elseif travel.marker then travel.marker:Destroy();travel.marker=nil end
local ch,hrp,hum=travel.character()
if hum then
if C.SpeedOverride then own(hum,"WalkSpeed",C.WalkSpeed) end
if C.JumpOverride then own(hum,hum.UseJumpPower and "JumpPower" or "JumpHeight",hum.UseJumpPower and C.JumpPower or C.JumpHeight) end
if C.AutoRotateOverride then own(hum,"AutoRotate",C.AutoRotate) end
if C.CameraOffsetOverride then own(hum,"CameraOffset",Vector3.new(C.CameraSide,C.CameraHeight,0)) end
end
if C.GravityOverride then own(workspace,"Gravity",C.Gravity) end
if C.ZoomOverride then
if LP.CameraMinZoomDistance>math.max(C.MinZoom,C.MaxZoom) then own(LP,"CameraMinZoomDistance",C.MinZoom) end
own(LP,"CameraMaxZoomDistance",math.max(C.MinZoom,C.MaxZoom));own(LP,"CameraMinZoomDistance",C.MinZoom)
end
if C.ViewMode~="Game default" then own(LP,"CameraMode",C.ViewMode=="First person" and Enum.CameraMode.LockFirstPerson or Enum.CameraMode.Classic) end
end
-- Flight and local weapon adapters are isolated from normal ESP updates.
local flight={state=nil,up={},down={}}
function flight.setStatus(value)
if not alive then return end
if gui:GetAttribute("FlyStatus")~=value then gui:SetAttribute("FlyStatus",value) end
if flight.status then flight.status.Detail.Text=value end
end
function flight.stop()
local state=flight.state
if not state then return end
flight.state=nil
for _,key in ipairs({"velocity","orientation","attachment"}) do if state[key] then pcall(function()state[key]:Destroy()end) end end
pcall(function()
if state.hum.PlatformStand then state.hum.PlatformStand=state.platform end
if not state.hum.AutoRotate then state.hum.AutoRotate=state.rotate end
if state.root.Parent then state.root.AssemblyLinearVelocity=Vector3.zero;state.root.AssemblyAngularVelocity=Vector3.zero end
end)
gui:SetAttribute("FlyActive",false)
end
flight.rise=button(gui,"FlyUp","FLY UP",UDim2.new(0,16,1,-184),UDim2.fromOffset(80,52))
flight.fall=button(gui,"FlyDown","FLY DOWN",UDim2.new(0,16,1,-122),UDim2.fromOffset(80,52))
flight.rise.Visible=false;flight.fall.Visible=false
for _,entry in ipairs({{flight.rise,flight.up},{flight.fall,flight.down}}) do
on(entry[1].InputBegan,function(input)
if input.UserInputType==Enum.UserInputType.Touch or input.UserInputType==Enum.UserInputType.MouseButton1 then entry[2][input]=true end
end)
end
on(UIS.InputEnded,function(input) flight.up[input]=nil;flight.down[input]=nil end)
on(UIS.WindowFocusReleased,function() table.clear(flight.up);table.clear(flight.down) end)
function flight.step(dt,cam)
flight.rise.Visible=mobile and C.Fly and not menuOpen
flight.fall.Visible=flight.rise.Visible
if not C.Fly then flight.stop();flight.waiting=false;flight.setStatus("Disabled");return end
local ch,hrp,hum=travel.character()
if not ch then
flight.stop();flight.setStatus("Armed - waiting for your character to respawn.")
if not flight.waiting then flight.waiting=true;notify("Fly","Waiting for a living character. Fly will resume after respawn.") end
return
end
flight.waiting=false
if hrp.Anchored then flight.stop();flight.setStatus("Waiting - the game has anchored your character.");return end
local state=flight.state
if state and (state.root~=hrp or not state.velocity.Parent or not state.orientation.Parent) then flight.stop();state=nil end
if not state then
state={root=hrp,hum=hum,platform=hum.PlatformStand,rotate=hum.AutoRotate}
flight.state=state
local created,createError=pcall(function()
state.attachment=make("Attachment",{Name="NovaFlightAttachment"},hrp)
state.velocity=make("LinearVelocity",{Name="NovaFlightVelocity",Attachment0=state.attachment,
VelocityConstraintMode=Enum.VelocityConstraintMode.Vector,RelativeTo=Enum.ActuatorRelativeTo.World,
ForceLimitsEnabled=false,VectorVelocity=Vector3.zero},hrp)
state.orientation=make("AlignOrientation",{Name="NovaFlightOrientation",Attachment0=state.attachment,
Mode=Enum.OrientationAlignmentMode.OneAttachment,MaxTorque=math.huge,Responsiveness=25,
CFrame=hrp.CFrame.Rotation},hrp)
end)
if not created then flight.stop();C.Fly=false;flight.setStatus("Flight setup failed: "..tostring(createError));refresh();return end
end
hum.PlatformStand=true;hum.AutoRotate=false
local flat=Vector3.new(cam.CFrame.LookVector.X,0,cam.CFrame.LookVector.Z)
if flat.Magnitude<.001 then flat=Vector3.new(hrp.CFrame.LookVector.X,0,hrp.CFrame.LookVector.Z) end
if flat.Magnitude<.001 then flat=Vector3.new(0,0,-1) end
flat=flat.Unit
local right=Vector3.new(-flat.Z,0,flat.X)
local move=Vector3.zero
local vertical,boost=0,1
if focus and not menuOpen and not UIS:GetFocusedTextBox() then
if mobile then move=hum.MoveDirection else
if UIS:IsKeyDown(Enum.KeyCode.W) then move+=flat end
if UIS:IsKeyDown(Enum.KeyCode.S) then move-=flat end
if UIS:IsKeyDown(Enum.KeyCode.D) then move+=right end
if UIS:IsKeyDown(Enum.KeyCode.A) then move-=right end
end
if next(flight.up) or UIS:IsKeyDown(Enum.KeyCode.Space) or UIS:IsKeyDown(Enum.KeyCode.E) then vertical+=1 end
if next(flight.down) or UIS:IsKeyDown(Enum.KeyCode.LeftControl) or UIS:IsKeyDown(Enum.KeyCode.Q) then vertical-=1 end
if UIS:IsKeyDown(Enum.KeyCode.LeftShift) then boost=C.FlyBoost end
end
if move.Magnitude>1 then move=move.Unit end
state.velocity.VectorVelocity=(move*C.FlySpeed+Vector3.new(0,vertical*C.FlyVerticalSpeed,0))*boost
state.orientation.CFrame=CFrame.lookAt(Vector3.zero,flat)
gui:SetAttribute("FlyActive",true)
flight.setStatus(menuOpen and "Hovering - close the menu to move." or not focus and "Hovering - game window is unfocused." or "Flying / Space or E: up / Ctrl or Q: down")
end
local combat={patches={},newPatch=nil,wasWall=false,module=nil,overlays={}}
combat.displayFolder=make("Folder",{Name="NovaHitboxDisplay_"..uniqueId},workspace)
function combat.drawBox(part,seen)
if not C.HitboxDisplay then return end
local visual=combat.overlays[part]
if not visual then
visual={}
visual.fill=make("BoxHandleAdornment",{Name="HitboxFill",Adornee=part,
AlwaysOnTop=true,ZIndex=4,Transparency=.86,Color3=Color3.fromRGB(40,230,255),
Size=part.Size},combat.displayFolder)
visual.edge=make("SelectionBox",{Name="HitboxOutline",Adornee=part,
Color3=Color3.fromRGB(40,230,255),LineThickness=.045,SurfaceTransparency=1},combat.displayFolder)
combat.overlays[part]=visual
end
visual.fill.Size=part.Size
seen[part]=true
end
function combat.clearBoxes(seen)
local count=0
for part,visual in pairs(combat.overlays) do
if not seen or not seen[part] or not part.Parent then
visual.fill:Destroy();visual.edge:Destroy();combat.overlays[part]=nil
else count+=1 end
end
gui:SetAttribute("HitboxDisplays",count)
end
function combat.hitPart(ch)
local part=ch and ch:FindFirstChild(C.HitboxPart)
if not part and ch and (C.HitboxPart=="Torso" or C.HitboxPart=="UpperTorso" or C.HitboxPart=="LowerTorso") then
part=ch:FindFirstChild("UpperTorso") or ch:FindFirstChild("Torso") or ch:FindFirstChild("LowerTorso")
end
return part and part:IsA("BasePart") and part or nil
end
combat.targets={};combat.targetStamp=-math.huge;combat.targetCount=0
combat.rayParams=RaycastParams.new()
combat.rayParams.FilterType=Enum.RaycastFilterType.Include;combat.rayParams.IgnoreWater=true
pcall(function()combat.rayParams.CollisionGroup="Raycast"end)
function combat.refreshTargets(force)
if not force and os.clock()-combat.targetStamp<.12 then return end
combat.targetStamp=os.clock()
local parts,seen,count={},{},0
local function add(ch)
if not ch or ch==LP.Character or seen[ch] or not ch:IsDescendantOf(workspace) then return end
seen[ch]=true
local hum=ch:FindFirstChildOfClass("Humanoid")
if not hum or hum.Health<=0 then return end
local found=false
for _,part in ipairs(ch:GetChildren()) do
if part:IsA("BasePart") and part.Name~="HumanoidRootPart" then parts[#parts+1]=part;found=true end
end
if found then count+=1 end
end
for _,p in ipairs(Players:GetPlayers()) do if p~=LP then add(p.Character) end end
local characters=workspace:FindFirstChild("Characters")
if characters then for _,ch in ipairs(characters:GetChildren()) do if ch:IsA("Model") then add(ch) end end end
combat.targets=parts;combat.targetCount=count
combat.rayParams.FilterDescendantsInstances=parts
gui:SetAttribute("WallShotsTargets",count)
end
function combat.raycast(self,origin,direction)
assert(typeof(origin)=="Vector3" and typeof(direction)=="Vector3","Invalid gun ray arguments")
assert(origin.X==origin.X and origin.Y==origin.Y and origin.Z==origin.Z and direction.X==direction.X and direction.Y==direction.Y and direction.Z==direction.Z,"Invalid gun ray values")
if direction.Magnitude<.001 then return nil end
combat.refreshTargets(false)
if #combat.targets==0 then return nil end
local settings=type(self)=="table" and rawget(self,"Settings")
local size=type(settings)=="table" and settings.BulletSize
if typeof(size)=="Vector3" and size.X>0 and size.Y>0 and size.Z>0 then
return workspace:Blockcast(CFrame.new(origin),size,direction,combat.rayParams)
end
return workspace:Raycast(origin,direction,combat.rayParams)
end
function combat.patchGun(gun)
if type(gun)~="table" or type(rawget(gun,"Raycast"))~="function" or type(rawget(gun,"AttemptToHit"))~="function" or type(rawget(gun,"Settings"))~="table" then return end
for _,entry in ipairs(combat.patches) do if entry.gun==gun then return end end
local original=gun.Raycast
local wrapper=function(self,origin,direction,...)
if alive and C.WallShots then
local ok,result=pcall(combat.raycast,self,origin,direction)
if ok then
gui:SetAttribute("WallShotsLastQuery",result and "Local target intersection" or "No local intersection")
return result
end
gui:SetAttribute("WallShotsAdapterError",tostring(result))
gui:SetAttribute("WallShotsFallbacks",(gui:GetAttribute("WallShotsFallbacks") or 0)+1)
end
return original(self,origin,direction,...)
end
local ok=pcall(function()gun.Raycast=wrapper end)
if ok then table.insert(combat.patches,{gun=gun,original=original,wrapper=wrapper}) end
end
function combat.restore()
for _,entry in ipairs(combat.patches) do
pcall(function()if entry.gun.Raycast==entry.wrapper then entry.gun.Raycast=entry.original end end)
end
combat.patches={}
local entry=combat.newPatch
if entry then pcall(function()if entry.module.new==entry.wrapper then entry.module.new=entry.original end end) end
combat.newPatch=nil;combat.wasWall=false;combat.module=nil
end
function combat.enableWalls()
combat.wasWall=true
local ok,err=pcall(function()
local rs=game:GetService("ReplicatedStorage")
local client=rs:FindFirstChild("Client")
local modules=client and client:FindFirstChild("Modules")
local managers=modules and modules:FindFirstChild("Managers")
local guns=managers and managers:FindFirstChild("Guns")
local script=guns and guns:FindFirstChild("GunManager")
assert(script and script:IsA("ModuleScript"),"This game's weapon system is unsupported.")
local module=require(script)
assert(type(module)=="table" and type(module.Tools)=="table","Unsupported gun registry.")
combat.module=module
for _,gun in pairs(module.Tools) do combat.patchGun(gun) end
gui:SetAttribute("WallShotsStatus",#combat.patches>0 and "Client raycast adapter active; server damage unverified" or "Adapter ready; equip a gun. Server damage unverified")
end)
if not ok then
combat.restore();combat.wasWall=true;combat.module=nil
gui:SetAttribute("WallShotsStatus","Unavailable: "..tostring(err));notify("Wall shots",tostring(err))
else notify("Wall shots","Experimental client raycasts enabled. Server damage is unverified.") end
end
local cooldown={controlled={},registry=nil,retry=0,keys={"FireCooldown","BurstFireCooldown","BurstBulletCooldown","FireDelay"}}
function cooldown.restoreOne(settings,state)
for key,record in pairs(state.fields) do
pcall(function()if rawget(settings,key)==record.last then settings[key]=record.original end end)
end
end
function cooldown.restore()
for settings,state in pairs(cooldown.controlled) do cooldown.restoreOne(settings,state) end
cooldown.controlled={}
end
function cooldown.status(value,tables,fields)
if not alive then return end
gui:SetAttribute("NoCooldownStatus",value)
gui:SetAttribute("NoCooldownTables",tables or 0);gui:SetAttribute("NoCooldownFields",fields or 0)
if cooldown.row then cooldown.row.Detail.Text=value end
end
function cooldown.findRegistry()
if cooldown.registry then return cooldown.registry end
if os.clock()<cooldown.retry then return nil end
cooldown.retry=os.clock()+2
local ok,value=pcall(function()
local rs=game:GetService("ReplicatedStorage")
local client=rs:FindFirstChild("Client")
local modules=client and client:FindFirstChild("Modules")
local managers=modules and modules:FindFirstChild("Managers")
local guns=managers and managers:FindFirstChild("Guns")
local script=guns and guns:FindFirstChild("GunManager")
if not script then return nil end
local registry=require(script)
if type(registry)=="table" and type(registry.Tools)=="table" then return registry end
end)
if ok then cooldown.registry=value end
return cooldown.registry
end
function cooldown.update()
if not C.NoCooldown then
if next(cooldown.controlled) then cooldown.restore() end
cooldown.status("Disabled - original gun timing restored.")
return
end
local registry=cooldown.findRegistry()
if not registry then cooldown.restore();cooldown.status("Unsupported weapon system. Server cooldown cannot be overridden here.");return end
local active={}
for _,gun in pairs(registry.Tools) do
local settings=type(gun)=="table" and rawget(gun,"Settings")
if type(settings)=="table" then active[settings]=true end
end
local tables,fields,failures=0,0,0
for settings in pairs(active) do
local state=cooldown.controlled[settings]
if not state then state={fields={}};cooldown.controlled[settings]=state end
local handled=0
for _,key in ipairs(cooldown.keys) do
local value=rawget(settings,key)
if type(value)=="number" and value>=0 and value<math.huge then
local record=state.fields[key] or {original=value}
if record.last~=nil and value~=record.last then record.original=value end
local ok=pcall(function()settings[key]=0 end)
if ok then record.last=rawget(settings,key);state.fields[key]=record;handled+=1;fields+=1
else failures+=1 end
end
end
if handled>0 then tables+=1 end
end
for settings,state in pairs(cooldown.controlled) do
if not active[settings] then cooldown.restoreOne(settings,state);cooldown.controlled[settings]=nil end
end
local message
if tables>0 then message=tables.." gun profiles / "..fields.." client delays removed. Server firing limits unverified."
elseif not next(active) then message="Ready - equip a compatible gun. Server firing limits remain authoritative."
elseif failures>0 then message="Unavailable - the gun timing settings are read-only."
else message="Unsupported gun - no recognized cooldown settings were found." end
if failures>0 and tables>0 then message..=" Some settings are read-only." end
cooldown.status(message,tables,fields)
end
function combat.update(own)
cooldown.update()
local count=0
local displayed={}
if C.Hitboxes then
for _,p in ipairs(Players:GetPlayers()) do
local ch=p.Character
local h=ch and ch:FindFirstChildOfClass("Humanoid")
local part=combat.hitPart(ch)
local teammate=not LP.Neutral and not p.Neutral and LP.Team~=nil and LP.Team==p.Team
if p~=LP and h and h.Health>0 and part and part:IsA("BasePart") and (C.HitboxTeams or not teammate) then
own(part,"Size",Vector3.new(C.HitboxSize,C.HitboxSize,C.HitboxSize))
own(part,"CanCollide",false);own(part,"Massless",true);own(part,"CanQuery",true)
own(part,"Transparency",C.HitboxOpacity/100);own(part,"Color",ink)
combat.drawBox(part,displayed)
count+=1
end
end
end
combat.clearBoxes(displayed)
gui:SetAttribute("HitboxesChanged",count)
if combat.hitStatus then combat.hitStatus.Detail.Text=not C.Hitboxes and "Resizing is OFF. Enable Change hitboxes above." or count==0 and "No eligible living characters loaded. Waiting for players / respawn." or (tostring(count).." resized / "..C.HitboxPart.." / "..C.HitboxSize.." studs / boxes "..(C.HitboxDisplay and "ON" or "OFF")..". Damage unverified.") end
if C.WallShots and not combat.wasWall then combat.enableWalls()
elseif not C.WallShots and combat.wasWall then combat.restore();gui:SetAttribute("WallShotsStatus","Disabled") end
if C.WallShots and combat.module then
combat.refreshTargets(false)
local activeGuns={}
for _,gun in pairs(combat.module.Tools) do if type(gun)=="table" then activeGuns[gun]=true end end
for i=#combat.patches,1,-1 do
local entry=combat.patches[i]
if not activeGuns[entry.gun] or rawget(entry.gun,"Raycast")~=entry.wrapper then
if not activeGuns[entry.gun] then pcall(function()if entry.gun.Raycast==entry.wrapper then entry.gun.Raycast=entry.original end end) end
table.remove(combat.patches,i)
end
end
for _,gun in pairs(combat.module.Tools) do combat.patchGun(gun) end
gui:SetAttribute("WallShotsPatchedGuns",#combat.patches)
gui:SetAttribute("WallShotsStatus",#combat.patches>0 and (#combat.patches.." guns / "..combat.targetCount.." living targets. Local adapter active; damage unverified.") or "Ready - equip a compatible gun. Server damage unverified.")
end
if combat.status then combat.status.Detail.Text=gui:GetAttribute("WallShotsStatus") or "Experimental adapter for this game's guns; server damage unverified." end
end
-- Compatibility checks never send damage or weapon remotes.
function combat.checkResize()
local target
for _,p in ipairs(Players:GetPlayers()) do
local ch=p.Character
local h=ch and ch:FindFirstChildOfClass("Humanoid")
local teammate=not LP.Neutral and not p.Neutral and LP.Team~=nil and LP.Team==p.Team
if p~=LP and h and h.Health>0 and (C.HitboxTeams or not teammate) then
target=combat.hitPart(ch);if target then break end
end
end
if not target then return "NOT TESTED - no eligible living target", "NOT TESTED" end
local original=target.Size
local desired=Vector3.new(C.HitboxSize,C.HitboxSize,C.HitboxSize)
local query=false
local ok,err=pcall(function()
target.Size=desired
assert((target.Size-desired).Magnitude<.01,"Game did not retain requested size")
local params=RaycastParams.new()
params.FilterType=Enum.RaycastFilterType.Include;params.FilterDescendantsInstances={target}
pcall(function()params.CollisionGroup="Raycast"end)
local origin=target.Position+target.CFrame.RightVector*(desired.X/2+8)
local hit=workspace:Raycast(origin,target.Position-origin,params)
query=hit~=nil and hit.Instance==target
end)
local restored,restoreError=pcall(function()target.Size=original end)
if not restored then return "ERROR - could not restore test size: "..tostring(restoreError),"NOT TESTED" end
if not ok then return "FAIL - "..tostring(err),"NOT TESTED" end
return "PASS locally ("..C.HitboxPart..", "..C.HitboxSize.." studs)",query and "PASS locally" or "FAIL - part excluded from local rays"
end
function combat.checkWeapons()
local rs=game:GetService("ReplicatedStorage")
local client=rs:FindFirstChild("Client")
local modules=client and client:FindFirstChild("Modules")
local managers=modules and modules:FindFirstChild("Managers")
local guns=managers and managers:FindFirstChild("Guns")
local script=guns and guns:FindFirstChild("GunManager")
if not script or not script:IsA("ModuleScript") then return "UNSUPPORTED weapon system",false end
local ok,module=pcall(require,script)
if not ok or type(module)~="table" or type(module.Tools)~="table" then return "UNSUPPORTED gun registry",false end
local count=0
for _,gun in pairs(module.Tools) do
if type(gun)=="table" and type(rawget(gun,"Raycast"))=="function" and type(rawget(gun,"AttemptToHit"))=="function" then count+=1 end
end
return count>0 and ("READY - "..count.." compatible guns loaded") or "READY - equip a gun to attach",true
end
function combat.checkWallFilter()
local characters=workspace:FindFirstChild("Characters")
if not characters then return "NOT TESTED - character container unavailable" end
local scratch=Instance.new("Folder")
scratch.Name="NovaCompatibilityProbe_"..uniqueId;scratch.Parent=workspace
local model=Instance.new("Model")
model.Name="NovaCompatibilityTarget_"..uniqueId
local ok,err=xpcall(function()
local hum=Instance.new("Humanoid");hum.Parent=model
local target=Instance.new("Part");target.Name="Head";target.Anchored=true
target.CanCollide=false;target.CanTouch=false;target.Transparency=1
target.Size=Vector3.new(4,4,4);target.Position=Vector3.new(64000,32000,64000);target.Parent=model
model.Parent=characters
local wall=Instance.new("Part");wall.Name="TestBarrier";wall.Anchored=true
wall.CanCollide=false;wall.CanTouch=false;wall.Transparency=1
wall.Size=Vector3.new(12,12,2);wall.Position=Vector3.new(64000,32000,64020);wall.Parent=scratch
local origin=Vector3.new(64000,32000,64040);local direction=Vector3.new(0,0,-80)
local params=RaycastParams.new();params.FilterType=Enum.RaycastFilterType.Include
params.FilterDescendantsInstances={wall,target}
local normal=workspace:Raycast(origin,direction,params)
assert(normal and normal.Instance==wall,"Test barrier query failed")
combat.refreshTargets(true)
local bypass=combat.raycast(nil,origin,direction)
assert(bypass and bypass.Instance==target,"Client wall filter did not reach the test target")
end,traceError)
model:Destroy();scratch:Destroy();combat.refreshTargets(true)
return ok and "PASS on a local test target" or ("FAIL - "..tostring(err):sub(1,160))
end
function combat.checkCompatibility()
if combat.checking then return end
combat.checking=true;combat.report.Visible=true;combat.report:SetAttribute("SearchBaseVisible",true);combat.reportHide.Visible=true;combat.reportHide:SetAttribute("SearchBaseVisible",true);combat.checkButton.Text="CHECKING..."
combat.report.Detail.Text="Checking local resize, ray queries, and the gun adapter..."
task.defer(function()
local ok,err=xpcall(function()
local resize,query=combat.checkResize()
local weapons,supported=combat.checkWeapons()
local walls=supported and combat.checkWallFilter() or "UNSUPPORTED weapon system"
gui:SetAttribute("CompatibilityResize",resize)
gui:SetAttribute("CompatibilityRayQuery",query)
gui:SetAttribute("CompatibilityWeapons",weapons)
gui:SetAttribute("CompatibilityWallFilter",walls)
gui:SetAttribute("CompatibilityServerDamage","UNVERIFIED")
gui:SetAttribute("CompatibilityPlaceId",tostring(game.PlaceId))
if alive then
combat.report.Detail.Text="Place: "..game.PlaceId.." / "..os.date("!%H:%M:%S UTC")..
"\nHitbox size: "..resize.."\nHitbox ray query: "..query..
"\nGun adapter: "..weapons.."\nWall filter: "..walls..
"\nServer damage: UNVERIFIED. These checks do not fire shots or prove server acceptance."
end
end,traceError)
combat.checking=false
if alive then
combat.checkButton.Text="CHECK GAME COMPATIBILITY"
if not ok then combat.report.Detail.Text="Check failed: "..tostring(err):sub(1,300);gui:SetAttribute("CompatibilityCheckError",tostring(err))
else gui:SetAttribute("CompatibilityCheckError",nil);notify("Compatibility check","Results are shown below the button. Server damage remains unverified.") end
end
end)
end
-- Use the supported weapon's normal fire function; no OS mouse holds or damage remotes.
local autofire={lastFire=-math.huge,target=nil,since=0,busy=false,nextRegistry=0,registry=nil}
function autofire.status(value)
if not alive then return end
if gui:GetAttribute("AutoFireStatus")~=value then gui:SetAttribute("AutoFireStatus",value) end
if autofire.row then autofire.row.Detail.Text=value end
end
function autofire.reset(value)
autofire.target=nil;autofire.since=0;autofire.status(value)
end
function autofire.playerForHit(hit)
local object=hit and hit.Instance
while object and object~=workspace do
if object:IsA("Model") then
local p=Players:GetPlayerFromCharacter(object)
local h=object:FindFirstChildOfClass("Humanoid")
if p and p~=LP and h and h.Health>0 then
local teammate=not LP.Neutral and not p.Neutral and LP.Team~=nil and LP.Team==p.Team
if C.Teams and teammate then return nil end
return p
end
end
object=object.Parent
end
end
function autofire.registryForGame()
if autofire.registry then return autofire.registry end
if os.clock()<autofire.nextRegistry then return nil end
autofire.nextRegistry=os.clock()+2
local ok,value=pcall(function()
local client=game:GetService("ReplicatedStorage"):FindFirstChild("Client")
local modules=client and client:FindFirstChild("Modules")
local managers=modules and modules:FindFirstChild("Managers")
local guns=managers and managers:FindFirstChild("Guns")
local script=guns and guns:FindFirstChild("GunManager")
if not script then return nil end
local registry=require(script)
if type(registry)=="table" and type(registry.Tools)=="table" then return registry end
end)
if ok then autofire.registry=value end
return autofire.registry
end
function autofire.crosshair(cam)
local origin=cam.CFrame.Position
local direction=cam.CFrame.LookVector*C.Range
local hit
if C.WallShots then
local ok,value=pcall(combat.raycast,nil,origin,direction)
if ok then hit=value end
else
local params=RaycastParams.new();params.FilterType=Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances={LP.Character,cam}
pcall(function()params.CollisionGroup="Raycast"end)
hit=workspace:Raycast(origin,direction,params)
end
return autofire.playerForHit(hit)
end
function autofire.step(cam,chosen,point)
if C.EditorOpen then autofire.reset("Paused for script editor");return end
if C.Healing then autofire.reset("Paused for healing");return end
if not alive or not (C.TriggerBot or C.AutoShoot) then autofire.reset("Disabled");return end
if menuOpen or not mobile and free or not focus or UIS:GetFocusedTextBox() then autofire.reset("Paused - menu, cursor, or text input.");return end
if type(iswindowactive)=="function" then
local ok,active=pcall(iswindowactive)
if not ok or not active then autofire.reset("Paused - game window is not active.");return end
end
local ch=LP.Character
local hum=ch and ch:FindFirstChildOfClass("Humanoid")
if not hum or hum.Health<=0 then autofire.reset("Waiting for a living character.");return end
local tool=autofire.currentTool and autofire.currentTool() or ch:FindFirstChildOfClass("Tool")
if not tool then autofire.reset("Equip a compatible gun.");return end
if not tool.Enabled or tool:GetAttribute("Ammo")==0 then autofire.reset("Weapon unavailable or out of ammo.");return end
local registry=autofire.registryForGame()
local gun=registry and registry.Tools[tool]
if type(gun)~="table" or type(gun.DoFire)~="function" then autofire.reset("Unsupported weapon - no native fire adapter.");return end
local target
local crosshair=autofire.crosshair(cam)
if C.TriggerBot and crosshair then target=crosshair end
if not target and C.AutoShoot and chosen and point then
local direction=point-cam.CFrame.Position
if direction.Magnitude>.001 and cam.CFrame.LookVector:Dot(direction.Unit)>=math.cos(math.rad(C.FireAngle)) and crosshair==chosen then target=chosen end
end
if not target then autofire.reset(C.AutoShoot and "Waiting for aim alignment or crosshair target." or "Waiting for a crosshair target.");return end
local now=os.clock()
if target~=autofire.target then autofire.target=target;autofire.since=now end
if (now-autofire.since)*1000<C.FireDelay then autofire.status("Target acquired - waiting for firing delay.");return end
if autofire.busy or now-autofire.lastFire<1/math.max(1,C.FireRate) then return end
autofire.lastFire=now;autofire.busy=true;autofire.status("Native fire request / "..target.Name)
task.spawn(function()
if alive and tool.Parent==LP.Character and (C.TriggerBot or C.AutoShoot) and not menuOpen and focus then
local ok,err=pcall(gun.DoFire,gun)
if not ok then gui:SetAttribute("AutoFireError",tostring(err));autofire.status("Native fire failed: "..tostring(err):sub(1,100)) end
end
autofire.busy=false
end)
end
-- Utilities own their state so reruns/unloading stop scheduled actions.
local utility={alive=true,nextStep=0,nextClick=0,nextReload=0,busy=false,reloadBusy=false,tools=setmetatable({},{__mode="k"})}
function utility.status(message)
if not alive then return end
if utility.row then utility.row.Detail.Text=message end
gui:SetAttribute("AmmoStatus",message)
end
function utility.current()
local ch=LP.Character
local h=ch and ch:FindFirstChildOfClass("Humanoid")
if not h or h.Health<=0 then return nil end
return ch:FindFirstChildOfClass("Tool")
end
function utility.gun(tool)
local registry=autofire.registryForGame()
return registry and registry.Tools[tool]
end
function utility.capacity(tool)
local gun=utility.gun(tool)
local settings=type(gun)=="table" and gun.Settings
if type(settings)=="table" and type(settings.Ammo)=="number" and settings.Ammo>0 and settings.Ammo<100000 then
return math.floor(settings.Ammo),gun
end
return nil,gun
end
function utility.inspect()
local tool=utility.current()
if not tool then utility.status("Equip a gun. Ammo support is checked again automatically.");return end
local ammo,mags=tool:GetAttribute("Ammo"),tool:GetAttribute("Mags")
local cap=utility.capacity(tool)
local server=tool:GetAttribute("ServerAmmo")
gui:SetAttribute("AmmoWeapon",tool.Name)
gui:SetAttribute("AmmoCapacity",cap or 0)
gui:SetAttribute("AmmoServerVerified",false)
if type(ammo)~="number" or not cap then
utility.status(tool.Name..": unsupported ammo system. Local refill is unavailable.")
elseif type(server)=="number" then
utility.status(tool.Name.." | local "..tostring(ammo).."/"..cap.." | server "..tostring(server).." | reserve "..tostring(mags)..". Local refill cannot guarantee server ammo.")
else
utility.status(tool.Name.." | local "..tostring(ammo).."/"..cap.." | reserve "..tostring(mags)..". Server acceptance is unverified.")
end
end
function utility.refill(tool)
local cap=utility.capacity(tool)
local ammo=tool:GetAttribute("Ammo")
if not cap or type(ammo)~="number" then return end
if ammo<cap then tool:SetAttribute("Ammo",cap) end
end
function utility.watch(tool)
if utility.tools[tool] then return end
utility.tools[tool]=true
on(tool:GetAttributeChangedSignal("Ammo"),function()
if not alive or not C.InfiniteAmmo then return end
task.defer(function()
if alive and C.InfiniteAmmo and tool==utility.current() then
local ok,err=pcall(utility.refill,tool)
if not ok then utility.status("Local refill failed: "..tostring(err):sub(1,90)) end
end
end)
end)
end
function utility.reload()
local tool=utility.current()
if not tool then utility.status("Equip a gun before reloading.");return end
local cap,gun=utility.capacity(tool)
if not cap or type(gun)~="table" or type(gun.DoReload)~="function" then utility.status("Reload unavailable: unsupported weapon.");return end
if utility.reloadBusy then return end
if (tonumber(tool:GetAttribute("Mags")) or 0)<=0 then utility.status("No reserve ammo. Reload requires ammunition supplied by the game.");return end
if (tonumber(tool:GetAttribute("Ammo")) or cap)>=cap then return end
utility.reloadBusy=true
task.spawn(function()
local ok,err=pcall(function()if alive and tool==utility.current() then gun:DoReload() end end)
utility.reloadBusy=false
if not ok and alive then utility.status("Reload failed: "..tostring(err):sub(1,100)) end
end)
end
function utility.click()
if C.EditorOpen or C.Healing or C.Bot or not C.AutoClicker or utility.busy or menuOpen or not focus or UIS:GetFocusedTextBox() then return end
if type(mouse1click)~="function" or type(iswindowactive)~="function" then
C.AutoClicker=false;refresh();utility.clickRow.Detail.Text="Mouse input unavailable in this executor.";return
end
local ok,active=pcall(iswindowactive)
if not ok or not active then return end
local position=UIS:GetMouseLocation()
if ui.pointerBlocked(position) then return end
local now=os.clock()
if now<utility.nextClick then return end
utility.nextClick=now+1/math.clamp(C.ClickRate,1,20)
utility.busy=true
task.spawn(function()
local success,err=pcall(function()
if alive and C.AutoClicker and not menuOpen and focus and not UIS:GetFocusedTextBox() and iswindowactive() then mouse1click() end
end)
utility.busy=false
if not success and alive then C.AutoClicker=false;refresh();utility.clickRow.Detail.Text="Click failed: "..tostring(err):sub(1,80) end
end)
end
function utility.step()
utility.click()
local now=os.clock()
if now<utility.nextStep then return end
utility.nextStep=now+.2
local tool=utility.current()
if tool then
utility.watch(tool)
if C.InfiniteAmmo then utility.refill(tool) end
if C.AutoReload and not C.InfiniteAmmo and not menuOpen and focus and not UIS:GetFocusedTextBox() and now>=utility.nextReload then
if tool:GetAttribute("Ammo")==0 then utility.nextReload=now+1;utility.reload() end
end
end
utility.inspect()
end
heading(pages.Combat,"Ammo and clicking","Ammo requires game support. Mouse clicking works independently of the weapon adapter.")
toggle(pages.Combat,"InfiniteAmmo","Infinite ammo (local only)","Experimental magazine refill. Server ammo and accepted shots are not guaranteed. Does not create reserve ammo.")
toggle(pages.Combat,"AutoReload","Automatic reload","Reload an empty supported gun using the game's reload function and existing reserve ammo.")
utility.row=row(pages.Combat,"AmmoDiagnostics","Ammo diagnostics","Equip a gun to check its ammo system.",mobile and 150 or 125)
utility.row.RowTitle.Size=UDim2.new(1,-32,0,22);utility.row.Detail.Size=UDim2.new(1,-32,1,-48)
local ammoCheck=button(pages.Combat,"CheckAmmo","CHECK AMMO SUPPORT",UDim2.new(),UDim2.new(1,0,0,44))
on(ammoCheck.Activated,function()utility.inspect()end)
local reloadNow=button(pages.Combat,"ReloadNow","RELOAD NOW",UDim2.new(),UDim2.new(1,0,0,44))
on(reloadNow.Activated,function()utility.reload()end)
toggle(pages.Combat,"AutoClicker","Auto clicker","Repeat left clicks while the menu is closed. Pauses over Nova, during typing, and when the game loses focus. F6 toggles.")
slider(pages.Combat,"ClickRate","Clicks per second","Independent of weapon cooldown and trigger bot.",1,20,1)
utility.clickRow=row(pages.Combat,"ClickerHelp","Auto clicker control","Close the menu to begin clicking. Press F6 to stop.",100)
utility.clickRow.RowTitle.Size=UDim2.new(1,-32,0,22);utility.clickRow.Detail.Size=UDim2.new(1,-32,1,-48)
local stopUtilities=button(pages.Combat,"StopUtilities","STOP AMMO AND AUTO CLICKER",UDim2.new(),UDim2.new(1,0,0,44))
on(stopUtilities.Activated,function()C.AutoClicker=false;C.InfiniteAmmo=false;C.AutoReload=false;refresh();utility.status("Ammo refill, automatic reload, and auto clicker stopped.")end)
on(UIS.InputBegan,function(key,processed)
if not processed and not UIS:GetFocusedTextBox() and key.KeyCode==Enum.KeyCode.F6 then
C.AutoClicker=not C.AutoClicker;refresh();notify("Auto clicker",C.AutoClicker and "Enabled; close the menu to click." or "Disabled")
end
end)
heading(pages.Combat,"Combat controls","Local weapon support, visible hitboxes, and game compatibility.")
toggle(pages.Combat,"NoCooldown","No gun cooldown (local)","Remove supported client shot and burst delays. The server may still enforce cooldowns.")
cooldown.row=row(pages.Combat,"NoCooldownStatus","Gun cooldown status","Disabled",110)
cooldown.row.RowTitle.Size=UDim2.new(1,-32,0,22);cooldown.row.Detail.Size=UDim2.new(1,-32,1,-48);cooldown.row.Detail.TextWrapped=true
toggle(pages.Combat,"TriggerBot","Trigger bot","Fire the equipped gun when a living target is under the center crosshair.")
toggle(pages.Combat,"AutoShoot","Auto shoot","Fire when aim tracking has aligned with a target. Enable Aim in the Aim tab.")
slider(pages.Combat,"FireRate","Auto fire limit","Maximum requests per second; the weapon still controls its actual fire rate.",1,12,1)
slider(pages.Combat,"FireDelay","Target firing delay","Wait this many milliseconds after acquiring a target.",0,300,10)
slider(pages.Combat,"FireAngle","Aim alignment tolerance","Auto shoot requires the camera to align within this angle.",0.5,5,0.5)
autofire.row=row(pages.Combat,"AutoFireStatus","Automatic firing status","Disabled",110)
autofire.row.RowTitle.Size=UDim2.new(1,-32,0,22);autofire.row.Detail.Size=UDim2.new(1,-32,1,-48);autofire.row.Detail.TextWrapped=true
local godInfo=button(pages.Combat,"GodModeUnavailable","GOD MODE - SERVER SUPPORT REQUIRED",UDim2.new(),UDim2.new(1,0,0,44))
on(godInfo.Activated,function()notify("God mode unavailable","This client cannot grant server-side invulnerability.")end)
toggle(pages.Combat,"WallShots","Shoot through walls","Experimental local gun adapter. Server damage remains unverified.")
combat.status=row(pages.Combat,"WallShotsStatus","Weapon status","Disabled. Enable Shoot through walls above.",110)
combat.status.RowTitle.Size=UDim2.new(1,-32,0,22)
combat.status.Detail.Size=UDim2.new(1,-32,1,-48);combat.status.Detail.TextWrapped=true;combat.status.Detail.TextYAlignment=Enum.TextYAlignment.Top
toggle(pages.Combat,"Hitboxes","Change hitboxes","Resize the chosen body part locally. Disable to restore.")
toggle(pages.Combat,"HitboxDisplay","Show hitbox boxes","Cyan bounds show the selected part through walls.")
cycle(pages.Combat,"HitboxPart","Hitbox body part","Choose Head or Torso; torso supports both character rigs.",{"Head","Torso","UpperTorso","LowerTorso"})
slider(pages.Combat,"HitboxSize","Hitbox size","Local part size. Server damage is not guaranteed.",2,100,2)
slider(pages.Combat,"HitboxOpacity","Hitbox transparency","Independent of the cyan box display.",0,100,5)
toggle(pages.Combat,"HitboxTeams","Include teammates","Also resize players on your team.")
combat.hitStatus=row(pages.Combat,"HitboxStatus","Hitbox status","Waiting for a character.",96)
combat.hitStatus.RowTitle.Size=UDim2.new(1,-32,0,22)
combat.hitStatus.Detail.Size=UDim2.new(1,-32,1,-44);combat.hitStatus.Detail.TextWrapped=true
combat.checkButton=button(pages.Combat,"CheckCompatibility","CHECK GAME COMPATIBILITY",UDim2.new(),UDim2.new(1,0,0,48))
on(combat.checkButton.Activated,combat.checkCompatibility)
combat.report=row(pages.Combat,"CompatibilityReport","Local compatibility results","Run a check to see results.",mobile and 340 or 270)
combat.report.RowTitle.Size=UDim2.new(1,-32,0,22)
combat.report.Detail.Position=UDim2.fromOffset(16,42);combat.report.Detail.Size=UDim2.new(1,-32,1,-54)
combat.report.Detail.TextWrapped=true;combat.report.Detail.TextYAlignment=Enum.TextYAlignment.Top
combat.report.Visible=false;combat.report:SetAttribute("SearchBaseVisible",false)
combat.reportHide=button(pages.Combat,"HideCompatibility","HIDE CHECK RESULTS",UDim2.new(),UDim2.new(1,0,0,36))
combat.reportHide.Visible=false;combat.reportHide:SetAttribute("SearchBaseVisible",false)
on(combat.reportHide.Activated,function()combat.report.Visible=false;combat.report:SetAttribute("SearchBaseVisible",false);combat.reportHide.Visible=false;combat.reportHide:SetAttribute("SearchBaseVisible",false);ui.applyFilter()end)
heading(pages.Travel,"Flight","Close the menu to move. WASD; Space/E up; Ctrl/Q down; Shift boost.")
toggle(pages.Travel,"Fly","Fly","Hover and move freely. Touch uses the joystick and UP / DOWN buttons.")
slider(pages.Travel,"FlySpeed","Fly speed","Horizontal flight speed in studs per second.",5,150,5)
slider(pages.Travel,"FlyVerticalSpeed","Fly vertical speed","Ascend and descend speed in studs per second.",5,100,5)
slider(pages.Travel,"FlyBoost","Fly boost multiplier","Hold Left Shift on PC to temporarily increase flight speed.",1,4,0.5)
flight.status=row(pages.Travel,"FlyStatus","Flight status","Disabled",100)
flight.status.RowTitle.Size=UDim2.new(1,-32,0,22);flight.status.Detail.Size=UDim2.new(1,-32,1,-44);flight.status.Detail.TextWrapped=true
local extras={parts={},character=nil,checkpoint=nil,nextScan=0,nextHop=0,rows=0}
extras.defaults={Noclip=false,InfiniteJump=false,BunnyHop=false,Sprint=false,SlowFall=false,Spin=false,AutoWalk=false,
SelfLight=false,Ghost=false,HideAccessories=false,HideTool=false,SelfOutline=false,Coordinates=false,Compass=false,AirPlatform=false,
SprintSpeed=32,FallLimit=18,SpinRate=120,GhostOpacity=65,StepDistance=8}
for key,value in pairs(extras.defaults) do C[key]=value end
function extras.characterParts()
local ch=LP.Character
local hum=ch and ch:FindFirstChildOfClass("Humanoid")
local hrp=ch and ch:FindFirstChild("HumanoidRootPart")
if hum and hum.Health>0 and hrp then return ch,hum,hrp end
end
function extras.active()
return alive and focus and not menuOpen and not UIS:GetFocusedTextBox()
end
function extras.message(value)
if extras.statusRow then extras.statusRow.Detail.Text=value end
gui:SetAttribute("ExtrasStatus",value)
end
function extras.scan(ch)
if extras.character~=ch or os.clock()>=extras.nextScan then
extras.character=ch;extras.nextScan=os.clock()+1;table.clear(extras.parts)
if ch then for _,object in ipairs(ch:GetDescendants()) do if object:IsA("BasePart") then table.insert(extras.parts,object) end end end
end
end
function extras.apply(own)
extras.own=own
local ch,hum,hrp=extras.characterParts()
extras.scan(ch)
if ch then
for _,part in ipairs(extras.parts) do if part.Parent and part:IsDescendantOf(ch) then
if C.Noclip then own(part,"CanCollide",false) end
local hidden=C.HideAccessories and part:FindFirstAncestorOfClass("Accessory") or C.HideTool and part:FindFirstAncestorOfClass("Tool")
if hidden then own(part,"LocalTransparencyModifier",1)
elseif C.Ghost then own(part,"LocalTransparencyModifier",C.GhostOpacity/100) end
end end
if C.Sprint and extras.active() and (mobile and hum.MoveDirection.Magnitude>.1 or UIS:IsKeyDown(Enum.KeyCode.LeftShift)) and not C.Fly then
own(hum,"WalkSpeed",C.SprintSpeed)
end
if C.Spin and extras.active() and not C.Fly then own(hum,"AutoRotate",false) end
end
if C.SelfLight and hrp then
if not extras.light or extras.light.Parent~=hrp then
if extras.light then extras.light:Destroy() end
extras.light=make("PointLight",{Name="NovaHeadlight",Brightness=2,Range=40,Shadows=false,Color=Color3.new(1,1,1)},hrp)
end
elseif extras.light then extras.light:Destroy();extras.light=nil end
if C.SelfOutline and ch then
if not extras.outline then extras.outline=make("Highlight",{Name="NovaSelfOutline",FillTransparency=1,OutlineTransparency=.1,DepthMode=Enum.HighlightDepthMode.AlwaysOnTop},world) end
extras.outline.Adornee=ch;extras.outline.OutlineColor=ink
elseif extras.outline then extras.outline:Destroy();extras.outline=nil end
end
function extras.step(dt,cam)
if extras.own then extras.apply(extras.own) end
local ch,hum,hrp=extras.characterParts()
local active=extras.active()
if hrp then
if active and not C.Fly then
if C.SlowFall then
local v=hrp.AssemblyLinearVelocity
if v.Y < -C.FallLimit then hrp.AssemblyLinearVelocity=Vector3.new(v.X,-C.FallLimit,v.Z) end
end
if C.Spin then hrp.CFrame=hrp.CFrame*CFrame.Angles(0,math.rad(C.SpinRate)*math.min(dt,.1),0) end
if C.AutoWalk then
local direction=Vector3.new(cam.CFrame.LookVector.X,0,cam.CFrame.LookVector.Z)
if direction.Magnitude>.01 then hum:Move(direction.Unit,false) end
end
if C.BunnyHop and hum.MoveDirection.Magnitude>.1 and hum.FloorMaterial~=Enum.Material.Air and os.clock()>=extras.nextHop then
extras.nextHop=os.clock()+.2;hum.Jump=true
end
end
if C.AirPlatform and not C.Noclip then
if not extras.platform then
extras.platform=make("Part",{Name="NovaAirPlatform",Anchored=true,CanCollide=true,CanTouch=false,CanQuery=false,Size=Vector3.new(7,.3,7),Material=Enum.Material.Neon,Transparency=.65},world)
end
extras.platform.Color=ink;extras.platform.CFrame=CFrame.new(hrp.Position-Vector3.new(0,hum.HipHeight+hrp.Size.Y/2+.25,0))
elseif extras.platform then extras.platform:Destroy();extras.platform=nil end
extras.coords.Text=string.format("X %.1f Y %.1f Z %.1f",hrp.Position.X,hrp.Position.Y,hrp.Position.Z)
elseif extras.platform then extras.platform:Destroy();extras.platform=nil end
extras.coords.Visible=C.Coordinates and hrp~=nil
local look=cam.CFrame.LookVector
local degrees=(math.deg(math.atan2(look.X,-look.Z))+360)%360
extras.compass.Text=({"N","NE","E","SE","S","SW","W","NW"})[math.floor((degrees+22.5)/45)%8+1].." "..math.floor(degrees).."°"
extras.compass.Visible=C.Compass
end
function extras.resetMovement()
for _,key in ipairs({"Noclip","InfiniteJump","BunnyHop","Sprint","SlowFall","Spin","AutoWalk","AirPlatform","Fly","SpeedOverride","JumpOverride","GravityOverride","AutoRotateOverride"}) do C[key]=false end
flight.stop()
local _,hum,hrp=extras.characterParts()
if hum then hum:Move(Vector3.zero,false) end
if hrp then hrp.AssemblyLinearVelocity=Vector3.zero;hrp.AssemblyAngularVelocity=Vector3.zero end
refresh();extras.message("Movement controls stopped and original properties restored.")
end
function extras.panic()
extras.resetMovement()
for key,value in pairs(C) do if type(value)=="boolean" then C[key]=false end end
C.ViewMode="Game default";C.Mode=mobile and "Hold AIM" or "Hold RMB"
autofire.reset("Emergency stop");cooldown.restore();combat.restore();combat.clearBoxes()
if restoreWorld then restoreWorld() end
refresh();extras.message("Emergency stop: toggles disabled. F8 is always available.")
end
function extras.destroy()
for _,key in ipairs({"light","outline","platform"}) do if extras[key] then extras[key]:Destroy();extras[key]=nil end end
end
function extras.action(key,label,fn)
extras.rows+=1
local b=button(pages.Extras,key,label,UDim2.new(),UDim2.new(1,0,0,44))
on(b.Activated,function()
local ok,err=pcall(fn)
if not ok then extras.message("Action failed: "..tostring(err):sub(1,100)) end
end)
end
function extras.toggle(key,titleValue,detail)
extras.rows+=1;toggle(pages.Extras,key,titleValue,detail)
end
function extras.slider(key,titleValue,detail,lo,hi,step)
extras.rows+=1;slider(pages.Extras,key,titleValue,detail,lo,hi,step)
end
function extras.move(offset)
local _,_,hrp=extras.characterParts()
if not hrp then extras.message("Wait for a living character.");return end
hrp.CFrame=hrp.CFrame*CFrame.new(offset)
hrp.AssemblyLinearVelocity=Vector3.zero;hrp.AssemblyAngularVelocity=Vector3.zero
extras.message("Moved locally. The game server may correct movement.")
end
extras.coords=text(gui,"",11,ink,UDim2.new(1,-290,1,-92),UDim2.fromOffset(274,24));extras.coords.Name="CoordinatesHUD";extras.coords.Visible=false;extras.coords.TextXAlignment=Enum.TextXAlignment.Right
extras.compass=text(gui,"",15,ink,UDim2.new(.5,-80,0,12),UDim2.fromOffset(160,28));extras.compass.Name="CompassHUD";extras.compass.Visible=false
extras.ammo=button(gui,"QuickInfiniteAmmo","INF AMMO: OFF",UDim2.new(1,-16,.5,-22),UDim2.fromOffset(174,44))
extras.ammo.AnchorPoint=Vector2.new(1,0);extras.ammo.ZIndex=25
on(extras.ammo.Activated,function()
C.InfiniteAmmo=not C.InfiniteAmmo;refresh();utility.inspect()
notify("Infinite ammo",C.InfiniteAmmo and "Local refill enabled; check Combat for server ammo status." or "Disabled")
end)
table.insert(paints,function()
extras.ammo.Text="INF AMMO: "..(C.InfiniteAmmo and "ON" or "OFF")
extras.ammo.BackgroundColor3=C.InfiniteAmmo and Color3.fromRGB(28,133,94) or Color3.fromRGB(31,34,43)
end)
heading(pages.Extras,"Extra controls","Local movement, appearance, quick presets, and recovery. Features start disabled; servers may limit movement.")
extras.toggle("Noclip","Noclip","Disable local character collisions. Turn off to restore original collision properties.")
extras.toggle("InfiniteJump","Infinite jump","Request another jump while airborne. Close the menu first.")
extras.toggle("BunnyHop","Bunny hop","Automatically jump when moving on the ground.")
extras.toggle("Sprint","Sprint","Hold Left Shift to sprint. Touch: sprint while moving.")
extras.slider("SprintSpeed","Sprint speed","Applies while sprint is active.",16,100,2)
extras.toggle("SlowFall","Slow fall","Limit local falling speed while the menu is closed.")
extras.slider("FallLimit","Fall speed limit","Downward speed cap in studs per second.",5,80,1)
extras.toggle("Spin","Spin character","Rotate the character during play; disabled while flying.")
extras.slider("SpinRate","Spin speed","Degrees per second.",30,720,30)
extras.toggle("AutoWalk","Auto walk","Move forward in the camera direction while the menu is closed.")
extras.toggle("AirPlatform","Air platform","Create a visible local platform under your character. Paused while noclip is on.")
heading(pages.Extras,"Local appearance","These appearance controls affect your view.")
extras.toggle("SelfLight","Personal light","Attach a local light to your character.")
extras.toggle("Ghost","Transparent character","Fade your own character locally; does not make you invisible to other players.")
extras.slider("GhostOpacity","Character transparency","Amount of local fading.",10,100,5)
extras.toggle("HideAccessories","Hide accessories","Hide your accessories locally and restore them when disabled.")
extras.toggle("HideTool","Hide equipped tool","Hide the equipped tool model locally.")
extras.toggle("SelfOutline","Self outline","Outline your own character using the current theme color.")
extras.toggle("Coordinates","Coordinates HUD","Show your current X, Y, and Z at the bottom right.")
extras.toggle("Compass","Compass HUD","Show the camera compass heading at the top center.")
heading(pages.Extras,"Quick movement","Short moves and one-click presets. Teleports are local and may be corrected by the server.")
extras.slider("StepDistance","Step distance","Distance used by the five directional step buttons.",1,30,1)
extras.action("StepForward","STEP FORWARD",function()extras.move(Vector3.new(0,0,-C.StepDistance))end)
extras.action("StepBack","STEP BACK",function()extras.move(Vector3.new(0,0,C.StepDistance))end)
extras.action("StepLeft","STEP LEFT",function()extras.move(Vector3.new(-C.StepDistance,0,0))end)
extras.action("StepRight","STEP RIGHT",function()extras.move(Vector3.new(C.StepDistance,0,0))end)
extras.action("StepUp","STEP UP",function()extras.move(Vector3.new(0,C.StepDistance,0))end)
extras.action("Brake","STOP MOMENTUM",function()local _,_,r=extras.characterParts();if r then r.AssemblyLinearVelocity=Vector3.zero;r.AssemblyAngularVelocity=Vector3.zero;extras.message("Momentum stopped.")end end)
extras.action("SitDown","SIT DOWN",function()local _,h=extras.characterParts();if h then h.Sit=true end end)
extras.action("StandUp","STAND UP",function()local _,h=extras.characterParts();if h then h.Sit=false;h:ChangeState(Enum.HumanoidStateType.GettingUp)end end)
extras.action("SaveCheckpoint","SAVE QUICK CHECKPOINT",function()local _,_,r=extras.characterParts();if r then extras.checkpoint=r.CFrame;extras.message("Session checkpoint saved.")end end)
extras.action("ReturnCheckpoint","RETURN TO CHECKPOINT",function()local _,_,r=extras.characterParts();if r and extras.checkpoint then r.CFrame=extras.checkpoint;r.AssemblyLinearVelocity=Vector3.zero;extras.message("Returned to checkpoint.")else extras.message("Save a checkpoint first.")end end)
extras.action("ClearCheckpoint","CLEAR QUICK CHECKPOINT",function()extras.checkpoint=nil;extras.message("Checkpoint cleared.")end)
extras.action("FastWalkPreset","FAST WALK PRESET",function()C.SpeedOverride=true;C.WalkSpeed=40;refresh();extras.message("Walk speed set to 40.")end)
extras.action("SuperJumpPreset","SUPER JUMP PRESET",function()C.JumpOverride=true;C.JumpPower=85;C.JumpHeight=18;refresh();extras.message("Higher jump preset enabled.")end)
extras.action("MoonGravityPreset","MOON GRAVITY PRESET",function()C.GravityOverride=true;C.Gravity=55;refresh();extras.message("Local gravity set to 55.")end)
extras.action("ResetMovementExtras","RESET MOVEMENT",extras.resetMovement)
heading(pages.Extras,"Quick view presets","Presets use the existing World, Visuals, and Travel settings.")
extras.action("DayPreset","DAYTIME",function()C.TimeLock=true;C.DayTime=12;refresh()end)
extras.action("NightPreset","NIGHTTIME",function()C.TimeLock=true;C.DayTime=0;refresh()end)
extras.action("SunsetPreset","SUNSET",function()C.TimeLock=true;C.DayTime=18;refresh()end)
extras.action("ClearViewPreset","CLEAR VIEW PRESET",function()C.NoFog=true;C.NoBlur=true;C.NoDOF=true;C.NoBloom=true;refresh()end)
extras.action("WideFovPreset","WIDE CAMERA FOV",function()C.CameraOverride=true;C.CameraFOV=100;refresh()end)
extras.action("FirstPersonPreset","FIRST PERSON",function()C.ViewMode="First person";refresh()end)
extras.action("ThirdPersonPreset","THIRD PERSON",function()C.ViewMode="Third person";refresh()end)
extras.action("ResetCameraExtras","RESET CAMERA",function()C.ViewMode="Game default";C.CameraOverride=false;C.CameraOffsetOverride=false;C.ZoomOverride=false;refresh()end)
extras.action("OutlinePreset","OUTLINE ESP PRESET",function()C.ESP=true;C.Opacity=100;C.OutlineFade=0;C.Names=false;C.Health=false;C.Distance=false;refresh()end)
extras.action("LabelsPreset","PLAYER LABELS PRESET",function()C.ESP=true;C.Names=true;C.Health=true;C.Distance=true;C.Opacity=80;refresh()end)
extras.action("ResetAppearanceExtras","RESTORE LOCAL APPEARANCE",function()for _,k in ipairs({"Ghost","HideAccessories","HideTool","SelfLight","SelfOutline"})do C[k]=false end;refresh();extras.message("Local appearance restored.")end)
extras.action("PanicExtras","EMERGENCY STOP / F8",extras.panic)
extras.statusRow=row(pages.Extras,"ExtrasStatus","Extra controls status","Ready. F8 disables active toggles.",110)
extras.statusRow.RowTitle.Size=UDim2.new(1,-32,0,22);extras.statusRow.Detail.Size=UDim2.new(1,-32,1,-48)
gui:SetAttribute("ExtraControlCount",extras.rows)
on(UIS.JumpRequest,function()
if C.InfiniteJump and extras.active() and not C.Fly then
local _,hum=extras.characterParts()
if hum then hum:ChangeState(Enum.HumanoidStateType.Jumping)end
end
end)
on(UIS.InputBegan,function(key,processed)
if not processed and not UIS:GetFocusedTextBox() and key.KeyCode==Enum.KeyCode.F8 then extras.panic()end
end)
local shooter={commands={},order={},history={},recoil={"RecoilForce","CameraRecoilForce"},kick={"RecoilFOV","CameraRecoilFOV"}}
C.NoRecoil=false;C.NoSpread=false;C.NoAimKick=false
C.InputSensitivity=false;C.AimSensitivity=1
function shooter.apply(own)
if C.InputSensitivity and not mobile then own(UIS,"MouseDeltaSensitivity",C.AimSensitivity) end
local count,fields=0,0
if C.NoRecoil or C.NoSpread or C.NoAimKick then
local registry=autofire.registryForGame()
for _,gun in pairs(registry and registry.Tools or {}) do
local settings=type(gun)=="table" and gun.Settings
if type(settings)=="table" then
local matched=false
for _,group in ipairs({{enabled=C.NoRecoil,keys=shooter.recoil},{enabled=C.NoAimKick,keys=shooter.kick}}) do
if group.enabled then for _,key in ipairs(group.keys) do
if type(rawget(settings,key))=="number" then own(settings,key,0);fields+=1;matched=true end
end end
end
if C.NoSpread then
local spread=rawget(settings,"BulletSpread")
if type(spread)=="table" and type(rawget(spread,1))=="number" and type(rawget(spread,2))=="number" then
own(spread,1,0);own(spread,2,0);fields+=2;matched=true
elseif type(spread)=="number" then own(settings,"BulletSpread",0);fields+=1;matched=true end
end
if matched then count+=1 end
end
end
end
local message=not (C.NoRecoil or C.NoSpread or C.NoAimKick) and "Weapon modifiers off. Original settings restored."
or count>0 and (count.." compatible gun profiles / "..fields.." recognized local fields. Server shot validation remains unverified.")
or "Unsupported weapon settings. Equip a compatible gun; no universal weapon override is available."
if shooter.weaponRow then shooter.weaponRow.Detail.Text=message end
gui:SetAttribute("ShooterWeaponStatus",message);gui:SetAttribute("ShooterProfiles",count)
end
function shooter.log(message)
table.insert(shooter.history,1,tostring(message):sub(1,240))
while #shooter.history>4 do table.remove(shooter.history)end
shooter.output.Detail.Text=table.concat(shooter.history,"\n")
gui:SetAttribute("CommandResult",tostring(message))
end
function shooter.add(name,example,description,fn)
shooter.commands[name]={run=fn,example=example,description=description}
table.insert(shooter.order,name)
end
function shooter.number(value,lo,hi)
local number=tonumber(value)
if not number or number~=number or number<lo or number>hi then error("Expected a number from "..lo.." to "..hi,0)end
return number
end
function shooter.switch(value)
if value=="on" then return true elseif value=="off" then return false end
error("Use on or off.",0)
end
function shooter.setting(name,key,description)
shooter.add(name,name.." on",description,function(args)C[key]=shooter.switch(args[1]);return name.." "..args[1]end)
end
function shooter.execute(raw)
if type(raw)~="string" or #raw>120 then shooter.log("Command must be 120 characters or fewer.");return end
local tokens={};for word in raw:lower():gsub("^%s*[/%.]",""):gmatch("%S+") do table.insert(tokens,word)end
local name=table.remove(tokens,1)
local command=name and shooter.commands[name]
if not command then shooter.log("Unknown command. Type help or use a button below.");return end
local expected=0;for _ in command.example:gmatch("%S+")do expected+=1 end
if #tokens~=expected-1 then shooter.log("Usage: "..command.example);return end
local ok,result=pcall(command.run,tokens)
if ok then refresh();shooter.log(result or (name.." applied."))else shooter.log("Command error: "..tostring(result))end
end
heading(pages.Commands,"Shooter commands","Run commands locally in Nova. Nothing is sent to game chat. Click preset buttons or enter a command.")
shooter.entry=row(pages.Commands,"CommandEntry","Command input","Examples: sniper, dot, norecoil on, cps 10, stopfire",140)
shooter.entry.RowTitle.Size=UDim2.new(1,-32,0,22)
shooter.input=make("TextBox",{Name="CommandInput",Text="",ClearTextOnFocus=false,PlaceholderText="Type a Nova command...",Font=Enum.Font.Gotham,TextSize=13,TextColor3=ink,
PlaceholderColor3=muted,BackgroundColor3=Color3.fromRGB(13,15,20),BorderSizePixel=0,TextXAlignment=Enum.TextXAlignment.Left,
Position=UDim2.fromOffset(16,83),Size=UDim2.new(1,-112,0,40)},shooter.entry);round(shooter.input,8)
make("UIPadding",{PaddingLeft=UDim.new(0,9),PaddingRight=UDim.new(0,6)},shooter.input)
shooter.run=button(shooter.entry,"RunCommand","RUN",UDim2.new(1,-87,0,83),UDim2.fromOffset(71,40))
on(shooter.run.Activated,function()shooter.execute(shooter.input.Text)end)
on(shooter.input.FocusLost,function(enter)if enter then shooter.execute(shooter.input.Text)end end)
shooter.output=row(pages.Commands,"CommandOutput","Recent command results","Ready. Use help to list commands.",210)
shooter.output.RowTitle.Size=UDim2.new(1,-32,0,22);shooter.output.Detail.Size=UDim2.new(1,-32,1,-48)
heading(pages.Commands,"Weapon controls","Compatible local settings only. Modifiers start disabled and restore when turned off or Nova unloads.")
toggle(pages.Commands,"NoRecoil","No recoil (local)","Set recognized recoil-force fields to zero on supported gun profiles.")
toggle(pages.Commands,"NoSpread","No spread (local)","Zero the recognized BulletSpread range. Server accuracy may still differ.")
toggle(pages.Commands,"NoAimKick","No FOV kick (local)","Remove recognized weapon camera FOV pulses.")
shooter.weaponRow=row(pages.Commands,"ShooterWeaponStatus","Weapon modifier status","Waiting for compatible gun profiles.",120)
shooter.weaponRow.RowTitle.Size=UDim2.new(1,-32,0,22);shooter.weaponRow.Detail.Size=UDim2.new(1,-32,1,-48)
toggle(pages.Commands,"InputSensitivity","Mouse sensitivity override","PC: scale camera mouse movement. Restore original sensitivity by disabling.")
slider(pages.Commands,"AimSensitivity","Mouse sensitivity multiplier","0.2 is slow; 1 is normal. Does not change the weapon's aim-assist code.",.1,2,.1)
shooter.add("help","help","Show help and command examples.",function()return #shooter.order.." commands. Browse the buttons below. Examples: sniper / dot / norecoil on / cps 10 / stopfire. Use on or off for toggles."end)
shooter.add("status","status","Show the equipped weapon's ammo diagnostics.",function()utility.inspect();return gui:GetAttribute("AmmoStatus")end)
shooter.setting("aim","Aim","Enable or disable aim tracking with the selected activation key.")
shooter.setting("esp","ESP","Enable or disable player highlights.")
shooter.setting("names","Names","Toggle player names.")
shooter.setting("health","Health","Toggle player health labels.")
shooter.setting("distance","Distance","Toggle player distance labels.")
shooter.setting("predict","AimPrediction","Toggle velocity lead for projectile aiming.")
shooter.setting("visible","Visibility","Toggle aim visibility checks.")
shooter.setting("teamfilter","Teams","Toggle teammate filtering for aim.")
shooter.setting("ring","Circle","Toggle the aim radius circle.")
shooter.setting("norecoil","NoRecoil","Toggle supported local recoil-force removal.")
shooter.setting("nospread","NoSpread","Toggle supported local spread removal.")
shooter.setting("nokick","NoAimKick","Toggle supported local camera FOV-kick removal.")
shooter.setting("ammo","InfiniteAmmo","Toggle local ammo refill. Server acceptance is unverified.")
shooter.setting("autoreload","AutoReload","Reload an empty supported weapon using existing reserve ammo.")
shooter.setting("clicker","AutoClicker","Toggle repeated mouse clicks. Close the menu to start; F6 stops.")
shooter.setting("trigger","TriggerBot","Toggle firing when a target is under the crosshair.")
shooter.setting("autoshoot","AutoShoot","Toggle firing when current aim is aligned with a target.")
shooter.add("smooth","smooth","Smooth aim preset; hold your chosen aim key during play.",function()C.Aim=true;C.AimResponse="Smooth";C.Speed=18;C.FOV=140;C.AimThroughWalls=false;C.Visibility=true;C.AimPrediction=false;C.Mode=mobile and "Hold AIM" or "Hold RMB"end)
shooter.add("sniper","sniper","Tight aim radius and slow response for precision weapons.",function()C.Aim=true;C.FOV=75;C.Speed=12;C.Part="Head";C.AimPrediction=false;C.Visibility=true;C.AimThroughWalls=false;C.AimResponse="Smooth";C.Mode=mobile and "Hold AIM" or "Hold RMB"end)
shooter.add("close","close","Wider aim radius and faster response for close range.",function()C.Aim=true;C.FOV=240;C.Speed=35;C.Part="UpperTorso";C.AimResponse="Smooth";C.Visibility=true;C.AimThroughWalls=false;C.Mode=mobile and "Hold AIM" or "Hold RMB"end)
shooter.add("tracking","tracking","Torso tracking with target retention and smooth response.",function()C.Aim=true;C.Part="UpperTorso";C.Sticky=true;C.AimRetention=50;C.Speed=24;C.FOV=180;C.AimResponse="Smooth";C.Visibility=true;C.AimThroughWalls=false;C.Mode=mobile and "Hold AIM" or "Hold RMB"end)
shooter.add("head","head","Select the head as the aim target.",function()C.Part="Head"end)
shooter.add("torso","torso","Select the upper torso as the aim target.",function()C.Part="UpperTorso"end)
shooter.add("fov","fov 120","Set aim radius: 40 to 600 pixels.",function(a)C.FOV=shooter.number(a[1],40,600)end)
shooter.add("response","response 24","Set aim response speed: 2 to 100.",function(a)C.Speed=shooter.number(a[1],2,100)end)
shooter.add("lead","lead 60","Set prediction lead: 0 to 200 milliseconds.",function(a)C.AimLead=shooter.number(a[1],0,200);C.AimPrediction=true end)
shooter.add("dot","dot","Use a small center-dot crosshair.",function()C.Crosshair=true;C.CrosshairStyle="Dot";C.CrosshairSize=4;C.CrosshairGap=0 end)
shooter.add("cross","cross","Use a compact plus crosshair.",function()C.Crosshair=true;C.CrosshairStyle="Plus";C.CrosshairSize=6;C.CrosshairGap=3 end)
shooter.add("outline","outline","Outline-only player ESP preset.",function()C.ESP=true;C.Opacity=100;C.OutlineFade=0;C.Names=false;C.Health=false;C.Distance=false end)
shooter.add("labels","labels","Player names, health, and distance preset.",function()C.ESP=true;C.Names=true;C.Health=true;C.Distance=true;C.Opacity=80 end)
shooter.add("clear","clear","Clear fog, blur, bloom, and depth of field locally.",function()C.NoFog=true;C.NoBlur=true;C.NoDOF=true;C.NoBloom=true end)
shooter.add("day","day","Lock the local scene to midday.",function()C.TimeLock=true;C.DayTime=12 end)
shooter.add("night","night","Lock the local scene to midnight.",function()C.TimeLock=true;C.DayTime=0 end)
shooter.add("camera","camera 90","Set camera FOV: 40 to 120 degrees.",function(a)C.CameraFOV=shooter.number(a[1],40,120);C.CameraOverride=true end)
shooter.add("scope","scope on","Use a narrow camera FOV. This does not add weapon zoom mechanics.",function(a)C.CameraOverride=shooter.switch(a[1]);if C.CameraOverride then C.CameraFOV=40 end end)
shooter.add("shoulder","shoulder right","Camera shoulder: left, right, or off.",function(a)if a[1]=="off"then C.CameraOffsetOverride=false elseif a[1]=="left"or a[1]=="right"then C.CameraOffsetOverride=true;C.CameraSide=a[1]=="left"and -2 or 2 else error("Use left, right, or off.",0)end end)
shooter.add("sensitivity","sensitivity 0.5","Set PC mouse sensitivity: 0.1 to 2.",function(a)if mobile then error("Mouse sensitivity requires PC mouse input.",0)end;C.AimSensitivity=shooter.number(a[1],.1,2);C.InputSensitivity=true end)
shooter.add("resetinput","resetinput","Restore original mouse sensitivity.",function()C.InputSensitivity=false end)
shooter.add("reload","reload","Request the equipped compatible weapon's native reload.",function()utility.reload();return "Reload requested; see Combat ammo status for compatibility."end)
shooter.add("cps","cps 10","Set auto-clicker rate: 1 to 20 clicks per second.",function(a)C.ClickRate=shooter.number(a[1],1,20)end)
shooter.add("mark","mark","Save a quick session checkpoint.",function()local _,_,r=extras.characterParts();if not r then error("No living character.",0)end;extras.checkpoint=r.CFrame end)
shooter.add("back","back","Return to the saved quick checkpoint.",function()local _,_,r=extras.characterParts();if not r or not extras.checkpoint then error("Save a checkpoint with mark first.",0)end;r.CFrame=extras.checkpoint;r.AssemblyLinearVelocity=Vector3.zero end)
shooter.add("walk","walk 32","Set a local walk-speed override: 0 to 100.",function(a)C.WalkSpeed=shooter.number(a[1],0,100);C.SpeedOverride=true end)
shooter.add("jump","jump 80","Set local jump power: 0 to 150, with jump-height fallback.",function(a)local n=shooter.number(a[1],0,150);C.JumpPower=n;C.JumpHeight=math.clamp(n*n/(2*math.max(1,workspace.Gravity)),0,50);C.JumpOverride=true end)
shooter.add("resetweapon","resetweapon","Restore local recoil, spread, camera-kick, and cooldown settings.",function()C.NoRecoil=false;C.NoSpread=false;C.NoAimKick=false;C.NoCooldown=false;cooldown.restore()end)
shooter.add("stopfire","stopfire","Disable all automatic firing and clicking immediately.",function()C.AutoClicker=false;C.TriggerBot=false;C.AutoShoot=false;autofire.reset("Stopped by command")end)
shooter.add("panic","panic","Disable active toggles and restore properties. F8 also works.",function()extras.panic()end)
heading(pages.Commands,"Command buttons","Each button runs the example shown. Use the command box to choose other values or turn options off.")
for _,name in ipairs(shooter.order) do
local command=shooter.commands[name]
local box=row(pages.Commands,"Command_"..name,command.example,command.description,100)
box.RowTitle.Size=UDim2.new(1,-110,0,22)
local run=button(box,"Cmd_"..name,"RUN",UDim2.new(1,-86,0,10),UDim2.fromOffset(70,32))
on(run.Activated,function()shooter.execute(command.example)end)
end
gui:SetAttribute("ShooterCommandCount",#shooter.order)
local bot={epoch=0,active=false,scanAt=0,pathAt=0,moveAt=0,shotAt=0,reloadAt=0,target=nil,waypoints=nil,index=1,pathBusy=false,fireBusy=false,reloadBusy=false,strafesAt=0,strafeSign=1,goal=nil,smoothed=Vector3.zero,random=Random.new(),progressAt=0,unstuckAt=0,pauseUntil=0}
C.Bot=false;C.BotMove=true;C.BotEquip=true;C.BotReload=true;C.BotStrafe=true;C.BotSmooth=true;C.BotRange=1000;C.BotDistance=70;C.BotRate=6;C.BotAimSpeed=16
function bot.status(message)
if not alive then return end
gui:SetAttribute("BotStatus",message)
if bot.row then bot.row.Detail.Text=message end
end
function bot.stopMovement()
bot.goal=nil;bot.smoothed=Vector3.zero;bot.jumpUntil=0;bot.jumpPlan=nil
local _,hum,root=extras.characterParts()
if hum and root then hum:Move(Vector3.zero,false)end
end
function bot.stop(message)
if bot.setADS then bot.setADS(nil,false)end
bot.epoch+=1;bot.active=false;bot.target=nil;bot.waypoints=nil;bot.pathBusy=false;bot.fireBusy=false;bot.reloadBusy=false;bot.progressPosition=nil;bot.progressAt=0;bot.pauseUntil=0
bot.stopMovement();gui:SetAttribute("BotTarget","");bot.status(message or "Disabled. F7 enables bot; F10 stops bot.")
end
function bot.team(p)
return not LP.Neutral and not p.Neutral and LP.Team~=nil and LP.Team==p.Team
end
function bot.visible(ch,cam)
local params=RaycastParams.new();params.FilterType=Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances={LP.Character,world}
pcall(function()params.CollisionGroup="Raycast"end)
for _,name in ipairs({"Head","UpperTorso","Torso","HumanoidRootPart"})do
local part=ch:FindFirstChild(name)
if part and part:IsA("BasePart")then
local direction=part.Position-cam.CFrame.Position
if direction.Magnitude>.01 then
local hit=workspace:Raycast(cam.CFrame.Position,direction,params)
if not hit or hit.Instance:IsDescendantOf(ch)then return part end
end
end
end
end
function bot.choose(root,cam)
local best,chosen,part=math.huge,nil,nil
for _,p in ipairs(Players:GetPlayers())do
if p~=LP and not bot.team(p)then
local ch=p.Character
local h=ch and ch:FindFirstChildOfClass("Humanoid")
local r=ch and ch:FindFirstChild("HumanoidRootPart")
if h and h.Health>0 and r and not ch:FindFirstChildOfClass("ForceField")then
local distance=(r.Position-root.Position).Magnitude
if distance<=C.BotRange then
local visible=bot.visible(ch,cam)
local score=distance+(visible and 0 or C.BotRange)
if p==bot.target then score*=.85 end
if score<best then best=score;chosen=p;part=visible end
end
end
end
end
return chosen,part
end
function bot.weapon(hum,ch)
local registry=autofire.registryForGame()
if not registry then return nil,nil,"Unsupported game: no native weapon adapter."end
local current=ch:FindFirstChildOfClass("Tool")
local gun=current and registry.Tools[current]
if type(gun)=="table" and type(gun.DoFire)=="function" and ((tonumber(current:GetAttribute("Ammo"))or 0)>0 or (tonumber(current:GetAttribute("Mags"))or 0)>0)then return current,gun end
if C.BotEquip then
for tool,entry in pairs(registry.Tools)do
if typeof(tool)=="Instance" and tool:IsA("Tool") and (tool.Parent==LP.Backpack or tool.Parent==ch)and type(entry)=="table" and type(entry.DoFire)=="function"then
if (tonumber(tool:GetAttribute("Ammo"))or 0)>0 or (tonumber(tool:GetAttribute("Mags"))or 0)>0 then
hum:EquipTool(tool);return tool,entry
end
end
end
end
return nil,nil,"Equip a supported gun with ammo or reserve magazines."
end
function bot.path(root,destination)
if bot.pathBusy or os.clock()<bot.pathAt then return end
bot.pathAt=os.clock()+1.3;bot.pathBusy=true
local token=bot.epoch
local target=bot.target
local start=root.Position
task.spawn(function()
local ok,result=pcall(function()
local path=game:GetService("PathfindingService"):CreatePath({AgentRadius=2,AgentHeight=5,AgentCanJump=true,WaypointSpacing=5})
path:ComputeAsync(start,destination)
return path.Status==Enum.PathStatus.Success and path:GetWaypoints()or nil
end)
if token~=bot.epoch or not alive or not C.Bot then return end
bot.pathBusy=false
if target~=bot.target then return end
if ok and result and #result>1 then
bot.waypoints=result;bot.index=2
gui:SetAttribute("BotPathStatus","Ready: "..#result.." waypoints")
else bot.waypoints=nil;gui:SetAttribute("BotPathStatus",ok and "No navigable path"or tostring(result):sub(1,120))end
end)
end
function bot.walk(hum,root,enemy,visible)
if not C.BotMove then bot.stopMovement();return end
local now=os.clock()
if now<bot.moveAt then return end
bot.moveAt=now+.12
if bot.jumpPlan then bot.goal=bot.jumpPlan.goal;return end
if C.BotShortcut and now<(bot.shortcutUntil or 0)and bot.shortcutGoal then bot.goal=bot.shortcutGoal;return end
local delta=enemy.Position-root.Position
local horizontal=Vector3.new(delta.X,0,delta.Z)
if visible and horizontal.Magnitude>.01 then
local forward=horizontal.Unit
local distance=horizontal.Magnitude
local step=distance>C.BotDistance+10 and 9 or distance<C.BotDistance*.5 and -7 or 0
if now>bot.strafesAt then
bot.strafesAt=now+(C.BotSmooth and bot.random:NextNumber(.9,1.6)or 1.3)
bot.strafeUntil=now+(C.BotSmooth and bot.random:NextNumber(.35,.7)or 1.3)
bot.strafeSign=-bot.strafeSign
end
local side=C.BotStrafe and now<(bot.strafeUntil or 0)and Vector3.new(-forward.Z,0,forward.X)*(C.BotSmooth and 3 or 4)*bot.strafeSign or Vector3.zero
local destination=root.Position+forward*step+side
local params=RaycastParams.new();params.FilterType=Enum.RaycastFilterType.Exclude;params.FilterDescendantsInstances={LP.Character,world,enemy.Parent}
local ground=workspace:Raycast(destination+Vector3.new(0,2,0),Vector3.new(0,-12,0),params)
local block=workspace:Raycast(root.Position,destination-root.Position,params)
if ground and not block then
bot.waypoints=nil
bot.goal=(destination-root.Position).Magnitude>1 and Vector3.new(destination.X,ground.Position.Y,destination.Z)or nil
return
end
end
if C.BotShortcut then
local jumped,landing=bot.checkObstacle(hum,root,enemy.Position-root.Position)
if jumped then bot.shortcutGoal=landing;bot.shortcutUntil=now+.7;bot.goal=landing;return end
end
bot.path(root,enemy.Position)
local waypoint=bot.waypoints and bot.waypoints[bot.index]
if waypoint then
local flat=Vector3.new(root.Position.X-waypoint.Position.X,0,root.Position.Z-waypoint.Position.Z)
if flat.Magnitude<2.5 and math.abs(root.Position.Y-waypoint.Position.Y)<6 then bot.index+=1;waypoint=bot.waypoints[bot.index]end
if waypoint then
if waypoint.Action==Enum.PathWaypointAction.Jump then bot.requestJump(hum,"Path waypoint")end
bot.goal=waypoint.Position
else bot.stopMovement()end
else
if horizontal.Magnitude>1 then bot.goal=root.Position+horizontal.Unit*math.min(8,horizontal.Magnitude)else bot.stopMovement()end
end
end
function bot.drive(hum,root,dt)
bot.updateJump(hum,root)
local now=os.clock()
local wanted=Vector3.zero
local distance=0
if bot.goal and C.BotMove then
local delta=Vector3.new(bot.goal.X-root.Position.X,0,bot.goal.Z-root.Position.Z)
distance=delta.Magnitude
if distance>(bot.jumpPlan and .2 or 1)then wanted=delta.Unit end
end
local avoiding=false
if wanted.Magnitude>.1 then bot.checkObstacle(hum,root,wanted);if not bot.jumpPlan then wanted,avoiding=bot.steer(hum,root,wanted)end end
if bot.obstacleRow then bot.obstacleRow.Detail.Text=gui:GetAttribute("BotObstacleStatus")or "Ready: scanning low obstacles while moving."end
if C.BotSmooth and now<bot.pauseUntil then wanted=Vector3.zero end
if bot.jumpPlan or avoiding then bot.smoothed=wanted
elseif C.BotSmooth then
bot.smoothed=bot.smoothed:Lerp(wanted,1-math.exp(-9*math.min(dt,.1)))
else bot.smoothed=wanted end
if bot.smoothed.Magnitude<.025 then bot.smoothed=Vector3.zero end
-- Apply after PlayerModule's render update; MoveTo is canceled by default controls.
hum:Move(bot.smoothed,false)
if now<(bot.jumpUntil or 0)and hum.FloorMaterial~=Enum.Material.Air then hum.Jump=true end
if hum.FloorMaterial==Enum.Material.Air or root.AssemblyLinearVelocity.Y>2 then bot.jumpUntil=0 end
gui:SetAttribute("BotMovementInput",bot.smoothed.Magnitude)
gui:SetAttribute("BotPosition",root.Position)
if now>=bot.progressAt then
local progress=bot.progressPosition and (root.Position-bot.progressPosition).Magnitude or 10
if wanted.Magnitude>.5 and distance>4 and progress<.8 and now>=bot.unstuckAt then
bot.unstuckAt=now+2.5;bot.pathAt=0;bot.waypoints=nil
if hum.FloorMaterial~=Enum.Material.Air then bot.requestJump(hum,"Obstacle recovery")end
if C.BotSmooth then bot.pauseUntil=now+.18 end
gui:SetAttribute("BotNavigation","Blocked: jumping once and computing a new path")
else gui:SetAttribute("BotNavigation",wanted.Magnitude>.1 and "Following path / progress "..string.format("%.1f",progress).." studs"or "Holding position")end
bot.progressPosition=root.Position;bot.progressAt=now+1
end
end
function bot.step(dt,cam)
if C.EditorOpen then bot.setADS(nil,false);bot.stopMovement();bot.status("Paused for script editor");return end
if C.Healing then bot.setADS(nil,false);bot.stopMovement();bot.status("Paused for healing");return end
if not C.Bot then if bot.active then bot.stop()end;return end
if not bot.active then
if ui.prepareBot and not ui.prepareBot() then C.Bot=false;bot.stop("Equip a firearm Tool before starting; this game may require a custom weapon adapter.");refresh();return end
C.BotAvoid=true;C.BotMove=true;C.BotSmooth=true;C.BotStrafe=true;C.BotReload=true;C.BotADS=true;C.BotFollowCamera=true;C.BotObstacleJump=true;C.BotJumpAssist=true
if ui.enforceCapabilities then ui.enforceCapabilities() end
bot.active=true;bot.epoch+=1;bot.scanAt=0;bot.pathAt=0
C.AutoClicker=false;C.TriggerBot=false;C.AutoShoot=false;C.Aim=false
for _,key in ipairs({"Fly","Spin","AutoWalk","Noclip","AirPlatform","BunnyHop","Hitboxes"})do C[key]=false end
if C.BotADS then C.CameraOverride=false end
flight.stop();refresh();showMenu(false)
end
if not extras.active()then bot.setADS(nil,false);bot.stopMovement();bot.status("Paused: close the menu, focus the game, and finish typing. F10 stops bot.");return end
if type(iswindowactive)=="function"then local ok,focused=pcall(iswindowactive);if not ok or not focused then bot.setADS(nil,false);bot.stopMovement();bot.status("Paused: game window is not focused.");return end end
local ch,hum,root=extras.characterParts()
if not ch then bot.setADS(nil,false);bot.status("Waiting for a living character.");return end
if bot.character~=ch then bot.character=ch;bot.epoch+=1;bot.target=nil;bot.waypoints=nil;bot.pathBusy=false;bot.fireBusy=false;bot.reloadBusy=false end
local tool,gun,message=bot.weapon(hum,ch)
if not tool then bot.setADS(nil,false);bot.stopMovement();bot.status(message);return end
if tool:GetAttribute("Ammo")==0 then
bot.setADS(nil,false)
bot.stopMovement()
if C.BotReload and (tonumber(tool:GetAttribute("Mags"))or 0)>0 and type(gun.DoReload)=="function"then
bot.status("Reloading "..tool.Name.." using available reserve ammo.")
if not bot.reloadBusy and os.clock()>=bot.reloadAt then
bot.reloadBusy=true;bot.reloadAt=os.clock()+1
local token=bot.epoch
task.spawn(function()
local ok,err=pcall(function()if alive and C.Bot and token==bot.epoch then gun:DoReload()end end)
if token==bot.epoch then bot.reloadBusy=false;if not ok then bot.status("Reload failed: "..tostring(err):sub(1,100))end end
end)
end
else bot.status("Out of ammo. Bot cannot create server ammunition.")end
return
end
local now=os.clock()
if now>=bot.scanAt then
bot.scanAt=now+.2
local target=bot.choose(root,cam)
if target~=bot.target then bot.target=target;bot.waypoints=nil;bot.pathAt=0 end
end
local enemy=bot.target and bot.target.Character
local enemyHum=enemy and enemy:FindFirstChildOfClass("Humanoid")
local enemyRoot=enemy and enemy:FindFirstChild("HumanoidRootPart")
if not enemyRoot or not enemyHum or enemyHum.Health<=0 then bot.target=nil;bot.setADS(nil,false);bot.stopMovement();bot.status("Searching for a living opponent within "..C.BotRange.." studs.");return end
gui:SetAttribute("BotTarget",bot.target.Name)
local part=bot.visible(enemy,cam)
bot.walk(hum,root,enemyRoot,part~=nil)
bot.drive(hum,root,dt)
if not part then
bot.setADS(nil,false)
bot.routeCamera(cam,root,dt,enemyRoot.Position)
local navigation=gui:GetAttribute("BotNavigation")or gui:GetAttribute("BotPathStatus")or "Planning a route"
bot.status("Seeking "..bot.target.Name.." / "..navigation..". No clear shot.");return
end
bot.setADS(gun,true)
if bot.adsRow then bot.adsRow.Detail.Text=gui:GetAttribute("BotADSStatus")or "Ready"end
local direction=part.Position-cam.CFrame.Position
if direction.Magnitude<.01 then return end
gui:SetAttribute("BotCameraStatus","Tracking visible target")
cam.CFrame=cam.CFrame:Lerp(CFrame.lookAt(cam.CFrame.Position,part.Position),1-math.exp(-C.BotAimSpeed*dt))
bot.status("Tracking "..bot.target.Name.." / "..tool.Name..". Native weapon cooldowns apply. F10 stops.")
if bot.fireBusy or bot.reloadBusy or now<bot.shotAt or cam.CFrame.LookVector:Dot(direction.Unit)<math.cos(math.rad(3))then return end
bot.shotAt=now+1/math.max(1,C.BotRate);bot.fireBusy=true
local token=bot.epoch
task.spawn(function()
local ok,err=pcall(function()
if alive and C.Bot and token==bot.epoch and extras.active()and tool.Parent==LP.Character and enemyHum.Health>0 and bot.visible(enemy,cam)then gun:DoFire()end
end)
if token==bot.epoch then bot.fireBusy=false;if not ok then bot.status("Native firing failed: "..tostring(err):sub(1,100))end end
end)
end
heading(pages.Bot,"Auto-play bot","Opt-in target search, camera aiming, native firing, reloading, and pathfinding. Requires a compatible game weapon adapter.")
toggle(pages.Bot,"Bot","Auto-play bot / F7","Starts disabled. Starting enables movement, camera follow, jump assistance and supported ADS/reload, then closes the menu. Reopen the menu to pause. F10 stops only the bot; F8 stops everything.")
toggle(pages.Bot,"BotMove","Bot movement","Use paths when targets are behind cover; approach or retreat to your preferred distance.")
toggle(pages.Bot,"BotEquip","Auto equip compatible gun","Choose an owned, compatible gun with ammo or reserve magazines.")
toggle(pages.Bot,"BotReload","Bot reload","Use the weapon's native reload with existing reserve ammo.")
toggle(pages.Bot,"BotStrafe","Bot strafe","Alternate short side steps while fighting visible targets. Requires Bot movement.")
toggle(pages.Bot,"BotSmooth","Natural movement","Ease direction changes, take shorter side steps, and pause briefly when recovering from obstacles.")
slider(pages.Bot,"BotRange","Opponent search range","Nearest visible opponent is preferred. Teammates and spawn-protected players are skipped.",100,2000,50)
slider(pages.Bot,"BotDistance","Preferred fighting distance","Distance from a visible target, in studs.",15,200,5)
slider(pages.Bot,"BotRate","Bot fire request limit","Maximum attempts per second. Native weapon cooldowns still apply.",1,12,1)
slider(pages.Bot,"BotAimSpeed","Bot aim response","Higher values align the camera faster.",4,35,1)
bot.row=row(pages.Bot,"BotStatus","Bot status","Disabled. F7 toggles bot; F10 stops bot; F8 stops all active toggles.",140)
bot.row.RowTitle.Size=UDim2.new(1,-32,0,22);bot.row.Detail.Size=UDim2.new(1,-32,1,-48)
bot.stopButton=button(pages.Bot,"StopBot","STOP BOT / F10",UDim2.new(),UDim2.new(1,0,0,48))
on(bot.stopButton.Activated,function()C.Bot=false;bot.stop("Stopped by button. F7 enables bot again.");refresh()end)
on(UIS.InputBegan,function(key,processed)
if processed or UIS:GetFocusedTextBox()then return end
if key.KeyCode==Enum.KeyCode.F7 then C.Bot=not C.Bot;if not C.Bot then bot.stop("Stopped with F7.")end;refresh()
elseif key.KeyCode==Enum.KeyCode.F10 then C.Bot=false;bot.stop("Stopped with F10. F8 remains emergency stop.");refresh()end
end)
heading(pages.Aim,"Precision control",mobile and "Close the menu, then hold or tap the AIM pad." or "Configure your targeting. Free cursor pauses aiming.")
toggle(pages.Aim,"Aim","Aim assist","Smooth camera tracking while activated.")
cycle(pages.Aim,"Mode","Activation","Choose hold, toggle, or always active.",mobile and {"Hold AIM","Toggle AIM","Always"} or {"Hold RMB","Toggle RMB","Always"})
cycle(pages.Aim,"Part","Target bone","Automatically falls back for custom rigs.",{"Head","HumanoidRootPart","UpperTorso"})
cycle(pages.Aim,"Origin","FOV origin","Track from your crosshair or cursor.",mobile and {"Screen center"} or {"Screen center","Mouse"})
slider(pages.Aim,"FOV","Field of view","Target selection radius in screen pixels.",40,600,10)
slider(pages.Aim,"Speed","Response speed","Higher values follow targets faster; independent of frame rate.",2,100,1)
cycle(pages.Aim,"AimPriority","Target priority","Choose the closest crosshair, nearest player, or lowest health.",{"Crosshair","Nearest","Lowest health"})
cycle(pages.Aim,"AimResponse","Tracking response","Smooth follows at your response speed. Instant points directly at the target.",{"Smooth","Instant"})
toggle(pages.Aim,"AimFallback","Visible body-part fallback","Try head and torso alternatives when the selected part is blocked.")
toggle(pages.Aim,"AimPrediction","Movement prediction","Optional velocity lead; leave disabled for hitscan guns.")
slider(pages.Aim,"AimLead","Prediction lead","Milliseconds of motion lead when prediction is enabled.",0,200,10)
slider(pages.Aim,"AimRetention","Target retention strength","Prefer your current target without permanently locking it.",0,80,5)
local responsive=button(pages.Aim,"ResponsiveAim","APPLY RESPONSIVE AIM PRESET",UDim2.new(),UDim2.new(1,0,0,48))
on(responsive.Activated,function()
C.Aim=true;C.Speed=32;C.FOV=250;C.Sticky=true;C.AimRetention=35
C.AimPriority="Crosshair";C.AimFallback=true;C.AimResponse="Smooth";C.AimPrediction=false
selected=nil;refresh();notify("Aim preset","Enabled. Close the menu and use your selected activation mode.")
end)
slider(pages.Aim,"Range","Detection range","Maximum aim distance; ESP has separate distance controls.",100,5000,50)
toggle(pages.Aim,"AimThroughWalls","Aim through walls","Track players behind walls. Does not guarantee shots pass through them.")
toggle(pages.Aim,"Visibility","Visibility check","Skip blocked targets while Aim through walls is disabled.")
toggle(pages.Aim,"Teams","Ignore teammates","Neutral players remain eligible.")
toggle(pages.Aim,"Sticky","Target retention","Stay on one target while it remains valid.")
toggle(pages.Aim,"Circle","FOV circle","Display your targeting radius.")
heading(pages.Visuals,"Visual intelligence","Fine-tune character highlights and player information.")
toggle(pages.Visuals,"ESP","Character highlights","Outline player characters available on your client.")
toggle(pages.Visuals,"ESPAll","Show every player","Include teammates independently of your aim team filter.")
toggle(pages.Visuals,"ESPUnlimited","Unlimited ESP distance","Remove the aim and label distance limits from ESP.")
slider(pages.Visuals,"ESPInterval","ESP refresh interval","Milliseconds between text updates. Outlines follow players every frame.",25,200,25)
toggle(pages.Visuals,"Names","Identity labels","Display name and username.")
toggle(pages.Visuals,"Health","Health display","Health bar with current and maximum HP.")
toggle(pages.Visuals,"Distance","Distance markers","Player distance measured in studs.")
toggle(pages.Visuals,"Through","Through walls","Keep highlights and labels visible behind geometry.")
slider(pages.Visuals,"Opacity","Fill transparency","Solid fill at 0. Outline only at 100.",0,100,5)
cycle(pages.Visuals,"Color","Visual accent","Choose the highlight and FOV color.",{"Background","Silver","Violet","Cyan","Rose","Lime"})
heading(pages.Interface,"Interface","Liquid chrome / "..deviceName.." controls")
local appliedTheme=nil
applyTheme=function(name)
if appliedTheme==name then return end
local profile=themeProfiles[name] or themeProfiles.Chrome
appliedTheme=name;currentTheme=profile
ink=profile.primary;muted=profile.muted;palettes.Background=profile.accent
gui:SetAttribute("ThemePrimary",ink);gui:SetAttribute("ThemeMuted",muted);gui:SetAttribute("ThemeAccent",profile.accent)
for _,object in ipairs(gui:GetDescendants())do
if object:IsA("TextLabel") or object:IsA("TextButton") then
local role=object:GetAttribute("ThemeRole")
if role then animate(object,{TextColor3=role=="Muted" and muted or ink},.34) end
elseif object:IsA("GuiObject") and object:GetAttribute("ThemeFill")=="Primary" then
animate(object,{BackgroundColor3=ink},.34)
elseif object:IsA("UIStroke") and object:GetAttribute("ThemeEdge") then
animate(object,{Color=profile.accent},.34)
end
end
chrome.Color=ColorSequence.new({
ColorSequenceKeypoint.new(0,ink),ColorSequenceKeypoint.new(.45,profile.accent:Lerp(Color3.new(0,0,0),.32)),
ColorSequenceKeypoint.new(.54,ink),ColorSequenceKeypoint.new(1,profile.accent:Lerp(Color3.new(0,0,0),.48))})
local gradient=border:FindFirstChildOfClass("UIGradient")
if gradient then gradient.Color=ColorSequence.new({
ColorSequenceKeypoint.new(0,profile.accent:Lerp(Color3.new(0,0,0),.65)),
ColorSequenceKeypoint.new(.28,ink),
ColorSequenceKeypoint.new(.55,profile.accent:Lerp(Color3.new(0,0,0),.7)),
ColorSequenceKeypoint.new(1,profile.accent)}) end
end
local function chooseBackground(name)
if not backgroundIndex[name] then return end
C.Background=name;refresh()
if notify then notify("Background",name) end
end
local function stepBackground(delta)
local at=backgroundIndex[C.Background] or 1
chooseBackground(backgroundList[(at-1+delta)%#backgroundList+1].name)
end
local prevBG=button(root,"PreviousBackground","‹",UDim2.new(1,-100,0,88),UDim2.fromOffset(32,28))
local nextBG=button(root,"NextBackground","›",UDim2.new(1,-56,0,88),UDim2.fromOffset(32,28))
prevBG.Visible=not mobile;nextBG.Visible=not mobile
heroTag.Position=UDim2.new(1,-290,0,90);heroTag.Size=UDim2.fromOffset(175,24)
on(prevBG.Activated,function()stepBackground(-1)end)
on(nextBG.Activated,function()stepBackground(1)end)
switchBackground=function(name)
local entry=backgroundList[backgroundIndex[name] or 1]
heroTag.Text=entry.name:upper()
if applyTheme then applyTheme(entry.name) end
if entry.name==activeBackground then return end
local nextImage=backgroundAsset(entry)
if nextImage=="" then
gui:SetAttribute("BackgroundError","Background asset unavailable: "..entry.name)
return
end
liquid.Image=liquidSwap.Image;liquid.ScaleType=liquidSwap.ScaleType
liquidSwap.Image=nextImage
liquidSwap.ScaleType=entry.stretch and Enum.ScaleType.Stretch or Enum.ScaleType.Crop
mist.Image=nextImage;mist.ScaleType=liquidSwap.ScaleType
image=nextImage;activeBackground=entry.name
backgroundMix.Value=0;animate(backgroundMix,{Value=1},.5)
gui:SetAttribute("BackgroundError",nil)
gui:SetAttribute("BackgroundAsset",entry.file)
end
local columns=mobile and 2 or 3
local gridRows=math.ceil(#backgroundList/columns)
local gridHeight=gridRows*82+(gridRows-1)*8
local gallery=make("Frame",{Name="BackgroundGallery",BackgroundTransparency=1,
Size=UDim2.new(1,0,0,gridHeight+32)},pages.Interface)
text(gallery,"CHOOSE YOUR BACKGROUND",10,muted,UDim2.new(),UDim2.new(1,0,0,22))
local grid=make("Frame",{Name="Previews",BackgroundTransparency=1,Position=UDim2.fromOffset(0,30),
Size=UDim2.new(1,0,0,gridHeight)},gallery)
make("UIGridLayout",{CellSize=UDim2.new(1/columns,-8*(columns-1)/columns-2,0,82),
CellPadding=UDim2.fromOffset(8,8),FillDirectionMaxCells=columns,
SortOrder=Enum.SortOrder.LayoutOrder},grid)
for i,entry in ipairs(backgroundList)do
local preview=button(grid,entry.name,"",UDim2.new(),UDim2.fromOffset(150,82))
preview.LayoutOrder=i
local photo=make("ImageLabel",{Name="PreviewImage",BackgroundTransparency=1,
Image=backgroundAsset(entry),Size=UDim2.fromScale(1,1),
ScaleType=entry.stretch and Enum.ScaleType.Stretch or Enum.ScaleType.Crop},preview)
local strip=make("Frame",{BackgroundColor3=Color3.fromRGB(9,10,14),BackgroundTransparency=.12,
BorderSizePixel=0,Position=UDim2.new(0,0,1,-25),Size=UDim2.new(1,0,0,25)},preview)
local caption=text(strip,entry.name,11,ink,UDim2.fromOffset(9,0),UDim2.new(1,-30,1,0))
local check=text(strip,"✓",12,ink,UDim2.new(1,-23,0,0),UDim2.fromOffset(20,25))
local selectedFrame=make("Frame",{Name="Selection",BackgroundTransparency=1,
Position=UDim2.fromOffset(1,1),Size=UDim2.new(1,-2,1,-2),ZIndex=2},preview);round(selectedFrame,9)
local selectedEdge=outline(selectedFrame,1);selectedEdge.Color=ink;selectedEdge.Thickness=1.5
table.insert(paints,function()
local chosen=C.Background==entry.name
preview:SetAttribute("Selected",chosen)
check.Visible=chosen
animate(selectedEdge,{Transparency=chosen and .05 or 1},.2)
caption:SetAttribute("ThemeRole",chosen and "Primary" or "Muted")
animate(caption,{TextColor3=chosen and ink or muted},.34)
end)
on(preview.Activated,function()chooseBackground(entry.name)end)
end
gui:SetAttribute("BackgroundAsset",initialBackground.file)
toggle(pages.Interface,"Motion","Interface animations","Background drift, chrome shimmer, and transitions.")
slider(pages.Interface,"Backdrop","Backdrop intensity","Adjust the brightness of your liquid-metal image.",0,100,5)
-- Visibility and label tuning.
slider(pages.Visuals,"OutlineFade","Outline transparency","0 = solid outline; 100 = hidden outline.",0,100,5)
slider(pages.Visuals,"LabelSize","Label text size","Resize player names, distance, and health text.",10,20,1)
slider(pages.Visuals,"LabelHeight","Label height","Move player labels above their characters.",2,8,.5)
slider(pages.Visuals,"LabelRange","Label distance","Limit information labels separately from highlights.",100,5000,100)
heading(pages.World,"World & lighting","Local visual adjustments. Original settings restore on unload.")
toggle(pages.World,"FullBright","Full Bright","Bright ambient light with shadows removed.")
toggle(pages.World,"NoFog","Clear fog & atmosphere","Remove fog, haze, density, and atmospheric glare.")
toggle(pages.World,"NoShadows","Remove shadows","Disable global shadows independently.")
toggle(pages.World,"TimeLock","Lock time of day","Keep the sun at your chosen time.")
slider(pages.World,"DayTime","Time of day","0 = midnight; 12 = noon; 18 = evening.",0,24,.5)
toggle(pages.World,"CustomLight","Custom lighting","Enable the three controls below. Full Bright takes priority.")
slider(pages.World,"LightBrightness","Brightness","Applied when Custom lighting is enabled.",0,10,.5)
slider(pages.World,"LightExposure","Exposure","Adjust scene exposure with Custom lighting enabled.",-3,3,.1)
slider(pages.World,"AmbientLevel","Ambient light","Ambient fill strength with Custom lighting enabled.",0,100,5)
toggle(pages.World,"NoBloom","Disable bloom","Remove bright bloom glow.")
toggle(pages.World,"NoBlur","Disable blur","Remove BlurEffect post-processing.")
toggle(pages.World,"NoDOF","Disable depth of field","Remove near / far camera blur.")
toggle(pages.World,"NoSunRays","Disable sun rays","Remove post-processing sun rays.")
toggle(pages.World,"NoColor","Disable color filters","Remove game ColorCorrectionEffect filters.")
toggle(pages.World,"CameraOverride","Camera FOV override","Use your selected camera field of view.")
slider(pages.World,"CameraFOV","Camera field of view","Camera zoom angle; separate from aim selection radius.",40,120,5)
local worldKeys={"FullBright","CustomLight","TimeLock","NoShadows","NoFog","NoBloom","NoBlur","NoSunRays","NoColor","NoDOF","CameraOverride"}
local restoreButton=button(pages.World,"RestoreWorld","RESTORE ORIGINAL WORLD",UDim2.new(),UDim2.new(1,0,0,44))
on(restoreButton.Activated,function()
for _,key in ipairs(worldKeys) do C[key]=false end
if restoreWorld then restoreWorld() end
refresh()
end)
toggle(pages.Interface,"ShowStatus","Status footer","Show tracking and player-count information.")
toggle(pages.Interface,"ShowFPS","FPS performance panel","Live FPS, frame time, ping, and a recent performance graph.")
toggle(pages.Interface,"FPSDetails","FPS details","Show frame time and ping. Clicking the FPS panel also switches this.")
toggle(pages.Interface,"FPSGraph","FPS history graph","Show the most recent six seconds of sampled FPS.")
cycle(pages.Interface,"FPSCorner","FPS position","Choose the screen corner for your performance panel.",{"Top right","Top left","Bottom right","Bottom left"})
toggle(pages.Interface,"Watermark","NOVA watermark","Show the new Nova brand panel with version and session information.")
toggle(pages.Interface,"WatermarkDetails","Watermark details","Show device, player count, and session time. Click the watermark to switch.")
cycle(pages.Interface,"WatermarkCorner","Watermark position","Panels automatically stack when you select the same corner.",{"Top left","Top right","Bottom left","Bottom right"})
slider(pages.Interface,"HUDScale","Overlay size","Scale the FPS and watermark panels; automatically fit narrow screens.",75,125,5)
slider(pages.Interface,"HUDOpacity","Overlay opacity","Background opacity for both panels.",20,100,5)
toggle(pages.Interface,"QuickCursor","Floating cursor button","PC: show the extra mouse-unlock button.")
toggle(pages.Interface,"ShowAimPad","Touch AIM pad","Mobile: show or hide the gameplay AIM pad.")
slider(pages.Interface,"AimPadSize","Touch pad size","Mobile AIM button diameter in pixels.",56,112,4)
slider(pages.Interface,"UISize","Desktop panel size","Desktop scale percentage; stays within the screen.",75,125,5)
toggle(pages.Interface,"HideRingMenu","Hide FOV in menu","Keep the circle out of the way while adjusting controls.")
toggle(pages.Interface,"Crosshair","Custom crosshair","Show a crosshair at the camera center during play.")
cycle(pages.Interface,"CrosshairStyle","Crosshair style","Plus, diagonal cross, or a single center dot.",{"Plus","Cross","Dot"})
slider(pages.Interface,"CrosshairSize","Crosshair size","Length of the crosshair arms, in pixels.",3,24,1)
slider(pages.Interface,"CrosshairGap","Crosshair gap","Space between the center and crosshair arms.",0,12,1)
slider(pages.Interface,"AnimationSpeed","Animation speed","50 = slower; 100 = normal; 175 = faster.",50,175,25)
toggle(pages.Interface,"Parallax","Cursor parallax","Desktop: reflections gently follow the cursor.")
toggle(pages.Interface,"Notifications","Setting notifications","Show a small confirmation when changing a toggle.")
local preset={previous=nil,profile="Not applied"}
function preset.describe(message)
preset.status.Detail.Text=message
gui:SetAttribute("GamePresetStatus",message)
end
function preset.detect()
local tool=utility.current()
local gun=tool and utility.gun(tool)
local settings=type(gun)=="table" and gun.Settings
if type(settings)~="table"then
local registry=autofire.registryForGame()
for candidate,entry in pairs(registry and registry.Tools or {})do
if typeof(candidate)=="Instance"and candidate:IsA("Tool")and candidate.Parent==LP.Backpack and type(entry)=="table"and type(entry.Settings)=="table"and type(entry.DoFire)=="function"then
tool=candidate;gun=entry;settings=entry.Settings;break
end
end
end
local supported=type(settings)=="table"
local kind="General shooter"
if supported then
local name=tool.Name:lower()
if settings.ShotgunReload or settings.ShotgunPumpEnabled or (tonumber(settings.BulletAmount)or 1)>1 or name:find("shotgun",1,true)or name:find("sawn",1,true)or name:find("870",1,true)then kind="Shotgun"
elseif name:find("barrett",1,true)or name:find("sniper",1,true)or name:find("awm",1,true)then kind="Precision"
elseif type(settings.Modes)=="table"and table.find(settings.Modes,"Automatic")then kind="Automatic"
else kind="Single fire"end
end
return tool,gun,settings,kind
end
function preset.apply()
local tool,gun,settings,kind=preset.detect()
local values={Aim=true,Mode="Always",AimResponse="Smooth",AimPrediction=false,
AimFallback=true,AimPriority="Crosshair",Sticky=true,AimRetention=35,Visibility=true,AimThroughWalls=false,Teams=true,
ESP=true,ESPAll=true,Names=true,Health=true,Distance=true,Through=true,Opacity=100,OutlineFade=10,
Crosshair=true,CrosshairStyle="Plus",CrosshairSize=6,CrosshairGap=3,LabelSize=12,
Hitboxes=true,HitboxDisplay=true,HitboxSize=12,HitboxPart="Head",HitboxOpacity=75,HitboxTeams=false,
WallShots=false,NoCooldown=false,InfiniteAmmo=false,AutoShoot=false,TriggerBot=false,AutoClicker=false,Bot=false,
NoRecoil=false,NoSpread=false,NoAimKick=false,AutoReload=false,FireRate=6,FireDelay=80,FireAngle=2.5,
BotSmooth=true,BotStrafe=true,BotMove=true,BotReload=true,BotEquip=true,BotRange=1000,BotDistance=70,BotRate=6,
InputSensitivity=false,FOV=150,Speed=20,Part="UpperTorso"}
if type(settings)=="table"then
values.NoRecoil=type(settings.RecoilForce)=="number"or type(settings.CameraRecoilForce)=="number"
local spread=settings.BulletSpread
values.NoSpread=type(spread)=="number"or type(spread)=="table"and type(spread[1])=="number"and type(spread[2])=="number"
values.NoAimKick=type(settings.RecoilFOV)=="number"or type(settings.CameraRecoilFOV)=="number"
values.AutoReload=type(gun.DoReload)=="function"
values.AutoShoot=type(gun.DoFire)=="function";values.TriggerBot=values.AutoShoot
values.InfiniteAmmo=type(settings.Ammo)=="number"and type(tool:GetAttribute("Ammo"))=="number"
values.WallShots=type(gun.Raycast)=="function"
values.AimThroughWalls=values.WallShots;values.Visibility=not values.WallShots
for _,key in ipairs(cooldown.keys)do if type(settings[key])=="number"then values.NoCooldown=true;break end end
end
if kind=="Shotgun"then values.FOV=200;values.Speed=26;values.Part="UpperTorso";values.BotDistance=35;values.BotRate=3
elseif kind=="Precision"then values.FOV=85;values.Speed=12;values.Part="Head";values.BotDistance=140;values.BotRate=2
elseif kind=="Automatic"then values.FOV=165;values.Speed=25;values.BotDistance=60
elseif kind=="Single fire"then values.FOV=125;values.Speed=18;values.Part="Head";values.BotDistance=80 end
-- Keep the first pre-preset snapshot until restored; repeated clicks do not erase it.
if not preset.previous then preset.previous={};for key in pairs(values)do preset.previous[key]=C[key]end end
for key,value in pairs(values)do C[key]=value end
bot.stop("Game preset applied; bot remains off.");autofire.reset("Game preset applied");cooldown.restore()
refresh()
preset.profile=(game.PlaceId==126210570846701 and "Sanguine Fields"or (game.PlaceId==120189115846709 or game.GameId==10090256806) and "TTK Testing"or "Detected game").." / "..kind
gui:SetAttribute("GamePresetProfile",preset.profile)
gui:SetAttribute("GamePresetWeapon",tool and tool.Name or "No equipped gun")
local enabled={};for _,entry in ipairs({{"AutoShoot","auto shoot"},{"TriggerBot","trigger bot"},{"Hitboxes","hitboxes"},{"InfiniteAmmo","local ammo"},{"NoRecoil","no recoil"},{"NoSpread","no spread"},{"NoAimKick","no FOV kick"},{"NoCooldown","no cooldown"},{"WallShots","local wall shots"},{"AutoReload","auto reload"}})do if C[entry[1]]then table.insert(enabled,entry[2])end end
gui:SetAttribute("GamePresetEnabled",table.concat(enabled,", "))
preset.describe(preset.profile..(tool and " / "..tool.Name or "")..". ON: "..table.concat(enabled,", ")..". Equip a gun and close the menu to engage. Ammo and wall-shot server acceptance remain unverified.")
notify("Combat preset applied",kind.." / "..#enabled.." combat controls enabled.")
end
function preset.restore()
if not preset.previous then preset.describe("No preset snapshot yet. Apply Game Preset first.");return end
for key,value in pairs(preset.previous)do C[key]=value end
preset.previous=nil;preset.profile="Restored"
refresh();gui:SetAttribute("GamePresetProfile","Restored")
preset.describe("Your settings from before the preset have been restored.")
notify("Settings restored","Returned to your pre-preset settings.")
end
preset.quick=button(gui,"ApplyGamePresetQuick","AIM/FIRE PRESET",UDim2.new(1,-16,.5,28),UDim2.fromOffset(174,44))
preset.quick.AnchorPoint=Vector2.new(1,0);preset.quick.ZIndex=25
on(preset.quick.Activated,function()preset.apply()end)
heading(pages.Settings,"Game preset","Enable supported combat features together, including automatic aiming and shooting. Close the menu to engage. Apply again after switching weapon types.")
preset.applyButton=button(pages.Settings,"ApplyGamePreset","APPLY AIM/FIRE SETTINGS (BOT STAYS OFF)",UDim2.new(),UDim2.new(1,0,0,48))
on(preset.applyButton.Activated,function()preset.apply()end)
preset.restoreButton=button(pages.Settings,"RestoreGamePreset","RESTORE PREVIOUS SETTINGS",UDim2.new(),UDim2.new(1,0,0,44))
on(preset.restoreButton.Activated,preset.restore)
preset.status=row(pages.Settings,"GamePresetStatus","Game preset status","Not applied. Press Game Preset to enable supported combat controls together.",230)
preset.status.RowTitle.Size=UDim2.new(1,-32,0,22);preset.status.Detail.Size=UDim2.new(1,-32,1,-48)
local healing={busy=false,epoch=0}
C.Healing=false
function healing.status(message)
if not alive then return end
gui:SetAttribute("HealStatus",message)
if healing.row then healing.row.Detail.Text=message end
if healing.quick then healing.quick.Text=C.Healing and "HEALING..."or "HEAL TO FULL"end
end
function healing.find()
local best,score=nil,0
for _,root in ipairs({LP.Backpack,LP.Character})do if root then for _,tool in ipairs(root:GetChildren())do
if tool:IsA("Tool")then
local name=tool.Name:lower()
local rank=(name:find("first aid",1,true)or name:find("medkit",1,true))and 3 or name:find("healing potion",1,true)and 2 or name=="bandage"and 1 or 0
if rank>score and tool:FindFirstChild("Settings")then best=tool;score=rank end
end
end end end
return best
end
function healing.wait(seconds,token,hum,tool)
local finish=os.clock()+seconds
repeat
if not alive or not C.Healing or healing.epoch~=token or hum.Health<=0 or hum.Parent~=LP.Character or tool and tool.Parent~=LP.Character then return false end
task.wait(.05)
until os.clock()>=finish
return true
end
function healing.release()
if healing.signal then pcall(function()healing.signal:Fire(false)end);healing.signal=nil end
if healing.controller and type(healing.controller.DoStop)=="function"then pcall(healing.controller.DoStop,healing.controller)end
healing.controller=nil
Run:UnbindFromRenderStep(binding.."_HealSelf")
if healing.camera and healing.camera.Parent and healing.cameraFrame then healing.camera.CFrame=healing.cameraFrame end
healing.camera=nil;healing.cameraFrame=nil
end
function healing.run()
if healing.busy then healing.status("Healing is already in progress. Use Cancel heal to stop.");return end
local ch,hum=extras.characterParts()
if not hum then healing.status("Wait for a living character. This button cannot revive a dead character.");return end
if hum.Health>=hum.MaxHealth then healing.status("Already at full health: "..math.floor(hum.Health).." / "..math.floor(hum.MaxHealth));return end
if game.PlaceId~=126210570846701 then healing.status("This game has no verified healing adapter. The button cannot grant server health.");return end
if not healing.find()then healing.status("No healing items. Obtain a healing potion, first aid kit, or bandage first.");return end
healing.busy=true;C.Healing=true;healing.epoch+=1;local token=healing.epoch
local original=ch:FindFirstChildOfClass("Tool")
local equipped
task.spawn(function()
local ok,err=pcall(function()
local network=require(game.ReplicatedStorage.Shared.Modules.Dependencies.Network)
local manager=require(game.ReplicatedStorage.Client.Modules.Managers.ConsumableManager)
local attempted={}
for attempt=1,8 do
if not alive or not C.Healing or token~=healing.epoch or hum.Health<=0 then break end
if hum.Health>=hum.MaxHealth then healing.status("Full health confirmed: "..math.floor(hum.Health).." / "..math.floor(hum.MaxHealth));return end
local tool=healing.find()
if not tool then healing.status("No healing items left. Health: "..math.floor(hum.Health).." / "..math.floor(hum.MaxHealth));return end
if attempted[tool]then healing.status("The healing item was not consumed. Try using it manually or obtain another item.");return end
attempted[tool]=true
local settings=require(tool.Settings)
local equip=math.clamp(tonumber(settings.EquipTime)or 1,.15,10)
local use=math.clamp(tonumber(settings.UseSelfTime)or 3,.2,30)
local before=hum.Health
equipped=tool;hum:EquipTool(tool)
healing.status("Using "..tool.Name.." on yourself. Health "..math.floor(before).." / "..math.floor(hum.MaxHealth))
if not healing.wait(equip+.25,token,hum,tool)then healing.status("Healing canceled during equip.");return end
local controller=manager.Tools[tool]
if type(controller)~="table"or type(controller.DoStart)~="function"then healing.status("This item has no ready native consumable controller. Re-equip it and try again.");return end
healing.controller=controller
-- Aim at open space while the native controller chooses self vs another player.
local cam=workspace.CurrentCamera
healing.camera=cam;healing.cameraFrame=cam.CFrame
local up=CFrame.lookAt(cam.CFrame.Position,cam.CFrame.Position+Vector3.new(0,1,.001))
Run:BindToRenderStep(binding.."_HealSelf",Enum.RenderPriority.Last.Value+200,function()if alive and C.Healing then cam.CFrame=up end end)
if not healing.wait(.1,token,hum,tool)then healing.status("Healing canceled.");return end
healing.signal=network.Signals.MobileAttack
healing.signal:Fire(true)
if not healing.wait(.15,token,hum,nil)then healing.status("Healing canceled.");return end
Run:UnbindFromRenderStep(binding.."_HealSelf");cam.CFrame=healing.cameraFrame;healing.camera=nil;healing.cameraFrame=nil
local mouseGui=LP.PlayerGui:FindFirstChild("Mouse")
local markers=mouseGui and mouseGui:FindFirstChild("Markers")
local indicator=markers and markers:FindFirstChild("Consumable")
if indicator and indicator.Visible and not indicator.Text:find(" ON "..LP.Name:upper(),1,true)then
healing.status("Native action selected another player. Healing canceled; aim at open space and retry.");return
end
if not healing.wait(use+.5,token,hum,nil)then healing.status("Healing canceled.");return end
healing.release()
if not healing.wait(3,token,hum,nil)then healing.status("Healing canceled.");return end
if hum.Health<=before then healing.status("Healing was not confirmed by the game. Health "..math.floor(hum.Health).." / "..math.floor(hum.MaxHealth));return end
if tool.Parent==ch and hum.Health<hum.MaxHealth then
healing.status("Healing applied. Wait for item removal before using another item.");return
end
end
healing.status(hum.Health>=hum.MaxHealth and "Full health confirmed."or "Healing stopped. Health "..math.floor(hum.Health).." / "..math.floor(hum.MaxHealth))
end)
healing.release()
C.Healing=false;healing.busy=false
if not ok then healing.status("Healing unavailable: "..tostring(err):sub(1,140))end
if alive and LP.Character==ch and hum.Health>0 then
if not ch:FindFirstChildOfClass("Tool")or ch:FindFirstChildOfClass("Tool")==equipped then
if original and original.Parent==LP.Backpack then hum:EquipTool(original)
elseif equipped and equipped.Parent==ch then hum:UnequipTools()end
end
end
if alive then healing.quick.Text="HEAL TO FULL"end
end)
end
function healing.cancel()
C.Healing=false;healing.epoch+=1;healing.release();healing.status("Healing canceled. No further items will be used.")
end
healing.quick=button(gui,"HealFullQuick","HEAL TO FULL",UDim2.new(1,-16,.5,78),UDim2.fromOffset(174,44))
healing.quick.AnchorPoint=Vector2.new(1,0);healing.quick.ZIndex=25
on(healing.quick.Activated,healing.run)
heading(pages.Combat,"Healing","Use owned healing items on yourself. Health is confirmed from the game; healing cannot be granted without game support.")
healing.button=button(pages.Combat,"HealFull","HEAL TO FULL",UDim2.new(),UDim2.new(1,0,0,48))
on(healing.button.Activated,healing.run)
healing.cancelButton=button(pages.Combat,"CancelHeal","CANCEL HEAL",UDim2.new(),UDim2.new(1,0,0,40))
on(healing.cancelButton.Activated,healing.cancel)
healing.row=row(pages.Combat,"HealStatus","Healing status","Ready. Healing uses items in your inventory; it cannot create health or supplies.",130)
healing.row.RowTitle.Size=UDim2.new(1,-32,0,22);healing.row.Detail.Size=UDim2.new(1,-32,1,-48)
local defense={elapsed=0,retryAt=0}
C.DefenseAssist=false;C.DefenseThreshold=85
function defense.status(message)
if not alive then return end
gui:SetAttribute("DefenseStatus",message)
if defense.row then defense.row.Detail.Text=message end
end
function defense.toggle()
C.DefenseAssist=not C.DefenseAssist;defense.retryAt=0;refresh()
defense.status(C.DefenseAssist and "Enabled. Healing items will be used below "..C.DefenseThreshold.."% health. Incoming damage is unchanged."or "Disabled. No additional automatic healing will start.")
end
function defense.tick(dt)
defense.elapsed+=dt;if defense.elapsed<.4 then return end;defense.elapsed=0
if not C.DefenseAssist then defense.status("Disabled. This feature uses owned healing supplies; it does not grant damage immunity.");return end
local _,hum=extras.characterParts()
if not hum then defense.status("Waiting for a living character. Cannot prevent death or revive you.");return end
if game.PlaceId~=126210570846701 then defense.status("Unavailable: no verified healing adapter for this game.");return end
if C.Healing or healing.busy then defense.status("Healing in progress. Automatic firing and bot actions are paused.");return end
local ratio=hum.Health/math.max(1,hum.MaxHealth)*100
if ratio>=C.DefenseThreshold then
defense.status("Ready: "..math.floor(hum.Health).." / "..math.floor(hum.MaxHealth).." HP. Heal trigger "..C.DefenseThreshold.."%. Incoming damage is unchanged.");return
end
if not healing.find()then defense.status("Low health, but no healing supplies remain. Obtain a first aid kit, potion, or bandage.");return end
if os.clock()<defense.retryAt then return end
defense.retryAt=os.clock()+10
defense.status("Low health: using a healing item. This takes the game's normal use time.")
healing.run()
end
defense.quick=button(gui,"DefenseAssistQuick","DEFENSE: OFF",UDim2.new(1,-16,.5,128),UDim2.fromOffset(174,44))
defense.quick.AnchorPoint=Vector2.new(1,0);defense.quick.ZIndex=25
on(defense.quick.Activated,defense.toggle)
table.insert(paints,function()
defense.quick.Text="DEFENSE: "..(C.DefenseAssist and "ON"or "OFF")
defense.quick.BackgroundColor3=C.DefenseAssist and Color3.fromRGB(28,133,94)or Color3.fromRGB(31,34,43)
end)
heading(pages.Combat,"Defense assist","Automatic use of owned healing supplies. Server damage and death rules are unchanged.")
toggle(pages.Combat,"DefenseAssist","Defense assist","Use a healing item when health falls below the selected percentage. F8 stops it.")
slider(pages.Combat,"DefenseThreshold","Auto-heal health threshold","Percentage of maximum health that triggers automatic healing.",25,95,5)
defense.row=row(pages.Combat,"DefenseStatus","Defense status","Disabled. No damage reduction or invulnerability is granted.",140)
defense.row.RowTitle.Size=UDim2.new(1,-32,0,22);defense.row.Detail.Size=UDim2.new(1,-32,1,-48)
on(Run.Heartbeat,function(dt)
local ok,err=pcall(defense.tick,dt)
if not ok and alive then C.DefenseAssist=false;refresh();defense.status("Defense assist stopped: "..tostring(err):sub(1,100))end
end)
local studio={job=0,running=false,thread=nil,lines={},layoutKey="",drag=nil}
C.EditorOpen=false
function studio.log(message)
if not alive then return end
table.insert(studio.lines,tostring(message):sub(1,1200))
while #studio.lines>40 do table.remove(studio.lines,1)end
studio.output.Text=table.concat(studio.lines,"\n")
gui:SetAttribute("ExecutorOutput",studio.lines[#studio.lines])
end
function studio.layout(viewport)
local key=tostring(viewport)
if studio.layoutKey==key then return end;studio.layoutKey=key
local width=math.max(280,math.min(880,viewport.X-24))
local height=math.max(320,math.min(670,viewport.Y-36))
studio.window.Size=UDim2.fromOffset(width,height)
end
function studio.show(value)
if value then
showMenu(false);C.EditorOpen=true;setFree(true);studio.window.Visible=true
studio.window.Position=UDim2.fromScale(.5,.5)
studio.layout(workspace.CurrentCamera.ViewportSize)
else
C.EditorOpen=false;studio.window.Visible=false;studio.code:ReleaseFocus(false);showMenu(true)
end
gui:SetAttribute("EditorOpen",C.EditorOpen)
end
function studio.run()
if studio.running then studio.log("An editor task is already running. Stop it before running another.");return end
if studio.code.Text:match("^%s*$")then studio.log("Paste your Luau code first.");return end
if type(loadstring)~="function"then studio.log("This executor does not provide loadstring.");return end
local fn,err=loadstring(studio.code.Text,"=Nova Script Studio")
if not fn then studio.log("Compile error: "..tostring(err));return end
studio.job+=1;local job=studio.job;studio.running=true
studio.state.Text="RUNNING";gui:SetAttribute("ExecutorRunning",true)
studio.log("Running script...")
if type(setfenv)=="function"and type(getfenv)=="function"then
local base=getfenv(fn)
local function capture(prefix,...)
local args=table.pack(...);local out={}
for i=1,args.n do out[i]=tostring(args[i])end
if studio.job==job then studio.log(prefix..table.concat(out,"\t"))end
end
local environment=setmetatable({print=function(...)capture("",...)end,warn=function(...)capture("WARN: ",...)end},{__index=base,__newindex=base})
setfenv(fn,environment)
end
studio.thread=task.spawn(function()
local result=table.pack(xpcall(fn,traceError))
if job~=studio.job or not alive then return end
studio.running=false;studio.thread=nil;studio.state.Text=result[1]and "FINISHED"or "ERROR"
gui:SetAttribute("ExecutorRunning",false)
if not result[1]then studio.log("Runtime error: "..tostring(result[2]))
else
local returned={};for i=2,result.n do returned[#returned+1]=tostring(result[i])end
studio.log(#returned>0 and "Returned: "..table.concat(returned,"\t")or "Script finished.")
end
end)
end
function studio.stop()
studio.job+=1
if studio.thread and coroutine.status(studio.thread)~="dead"then pcall(task.cancel,studio.thread)end
studio.thread=nil;studio.running=false;gui:SetAttribute("ExecutorRunning",false)
if alive then studio.state.Text="STOPPED";studio.log("Editor task stopped. Existing script changes or spawned tasks can remain.")end
end
function studio.destroy()
studio.job+=1
if studio.thread and coroutine.status(studio.thread)~="dead"then pcall(task.cancel,studio.thread)end
studio.thread=nil;studio.running=false
end
function studio.file(action)
local ok,err=pcall(function()
if action=="save"then
assert(type(writefile)=="function","File saving is unavailable")
if type(makefolder)=="function"then pcall(makefolder,"NOVA")end
writefile("NOVA/editor.luau",studio.code.Text);studio.log("Saved: NOVA/editor.luau")
else
assert(type(readfile)=="function","File loading is unavailable")
studio.code.Text=readfile("NOVA/editor.luau");studio.log("Loaded: NOVA/editor.luau")
end
end)
if not ok then studio.log("File error: "..tostring(err))end
end
studio.window=make("Frame",{Name="ScriptStudio",AnchorPoint=Vector2.new(.5,.5),Position=UDim2.fromScale(.5,.5),Size=UDim2.fromOffset(860,650),BackgroundColor3=Color3.fromRGB(13,17,25),BorderSizePixel=0,Visible=false,ZIndex=50},gui)
round(studio.window,14);outline(studio.window,.35)
studio.header=make("Frame",{Name="StudioHeader",Size=UDim2.new(1,0,0,48),BackgroundColor3=Color3.fromRGB(22,29,42),BorderSizePixel=0,Active=true},studio.window);round(studio.header,14)
text(studio.header,"NOVA / SCRIPT STUDIO",15,Color3.fromRGB(225,235,250),UDim2.fromOffset(16,0),UDim2.new(1,-65,1,0))
studio.close=button(studio.header,"CloseStudio","×",UDim2.new(1,-44,0,8),UDim2.fromOffset(32,32))
on(studio.close.Activated,function()studio.show(false)end)
text(studio.window,"Paste Luau and run locally in Madium. Ctrl + Enter runs your script.",11,muted,UDim2.fromOffset(16,55),UDim2.new(1,-32,0,28))
studio.editor=make("ScrollingFrame",{Name="CodeScroll",BackgroundColor3=Color3.fromRGB(8,11,17),BorderSizePixel=0,Position=UDim2.fromOffset(16,90),Size=UDim2.new(1,-32,1,-315),AutomaticCanvasSize=Enum.AutomaticSize.XY,CanvasSize=UDim2.new(),ScrollBarThickness=5,ScrollingDirection=Enum.ScrollingDirection.XY},studio.window);round(studio.editor,8)
studio.code=make("TextBox",{Name="ScriptCode",Position=UDim2.fromOffset(10,8),Size=UDim2.new(1,-20,1,-16),AutomaticSize=Enum.AutomaticSize.XY,BackgroundTransparency=1,
Text='print("Hello from Nova")\nreturn "Ready"',PlaceholderText="Paste your script here...",ClearTextOnFocus=false,MultiLine=true,TextEditable=true,RichText=false,TextWrapped=false,
Font=Enum.Font.Code,TextSize=14,TextColor3=Color3.fromRGB(207,222,246),TextXAlignment=Enum.TextXAlignment.Left,TextYAlignment=Enum.TextYAlignment.Top},studio.editor)
studio.toolbar=make("ScrollingFrame",{Name="StudioToolbar",Position=UDim2.new(0,16,1,-214),Size=UDim2.new(1,-32,0,44),AutomaticCanvasSize=Enum.AutomaticSize.X,CanvasSize=UDim2.new(),BackgroundTransparency=1,BorderSizePixel=0,ScrollBarThickness=2,ScrollingDirection=Enum.ScrollingDirection.X},studio.window)
make("UIListLayout",{FillDirection=Enum.FillDirection.Horizontal,Padding=UDim.new(0,7),SortOrder=Enum.SortOrder.LayoutOrder},studio.toolbar)
studio.actions={{"RunScript","RUN",studio.run},{"StopScript","STOP TASK",studio.stop},{"ClearScript","CLEAR",function()studio.code.Text=""end},{"CopyScript","COPY",function()
local copy=setclipboard or toclipboard
if type(copy)=="function"then copy(studio.code.Text);studio.log("Code copied.")else studio.log("Clipboard API unavailable.")end
end},{"SaveScript","SAVE",function()studio.file("save")end},{"LoadScript","LOAD",function()studio.file("load")end},{"ClearOutput","CLEAR LOG",function()table.clear(studio.lines);studio.output.Text=""end}}
for index,entry in ipairs(studio.actions)do
local control=button(studio.toolbar,entry[1],entry[2],UDim2.new(),UDim2.fromOffset(entry[2]=="STOP TASK"and 108 or 96,36));control.LayoutOrder=index
on(control.Activated,function()local ok,err=pcall(entry[3]);if not ok then studio.log(tostring(err))end end)
end
studio.state=text(studio.window,"READY",10,muted,UDim2.new(0,16,1,-166),UDim2.new(1,-32,0,20));studio.state.Name="ExecutorState"
studio.outputScroll=make("ScrollingFrame",{Name="OutputScroll",Position=UDim2.new(0,16,1,-140),Size=UDim2.new(1,-32,0,122),BackgroundColor3=Color3.fromRGB(8,11,17),BorderSizePixel=0,AutomaticCanvasSize=Enum.AutomaticSize.Y,CanvasSize=UDim2.new(),ScrollBarThickness=4,ScrollingDirection=Enum.ScrollingDirection.Y},studio.window);round(studio.outputScroll,8)
studio.output=text(studio.outputScroll,"Output and errors appear here.",12,Color3.fromRGB(171,198,228),UDim2.fromOffset(10,8),UDim2.new(1,-24,0,100))
studio.output.Font=Enum.Font.Code;studio.output.TextWrapped=true;studio.output.TextYAlignment=Enum.TextYAlignment.Top;studio.output.AutomaticSize=Enum.AutomaticSize.Y
studio.quick=button(gui,"OpenScriptStudioQuick","SCRIPT STUDIO",UDim2.new(1,-16,.5,178),UDim2.fromOffset(174,44));studio.quick.AnchorPoint=Vector2.new(1,0);studio.quick.ZIndex=25
on(studio.quick.Activated,function()studio.show(not C.EditorOpen)end)
on(studio.header.InputBegan,function(input)
if input.UserInputType==Enum.UserInputType.MouseButton1 or input.UserInputType==Enum.UserInputType.Touch then studio.drag={input=input,origin=input.Position,position=studio.window.Position}end
end)
on(UIS.InputChanged,function(input)
if studio.drag and (input.UserInputType==Enum.UserInputType.MouseMovement or input==studio.drag.input)then
local delta=input.Position-studio.drag.origin
local viewport=workspace.CurrentCamera.ViewportSize;local size=studio.window.AbsoluteSize
local origin=studio.drag.position
local x=origin.X.Scale*viewport.X+origin.X.Offset+delta.X
local y=origin.Y.Scale*viewport.Y+origin.Y.Offset+delta.Y
studio.window.Position=UDim2.fromOffset(math.clamp(x,size.X/2,math.max(size.X/2,viewport.X-size.X/2)),math.clamp(y,size.Y/2,math.max(size.Y/2,viewport.Y-size.Y/2)))
end
end)
on(UIS.InputEnded,function(input)if studio.drag and (input==studio.drag.input or input.UserInputType==Enum.UserInputType.MouseButton1)then studio.drag=nil end end)
on(UIS.InputBegan,function(input)
if C.EditorOpen and input.KeyCode==Enum.KeyCode.Return and (UIS:IsKeyDown(Enum.KeyCode.LeftControl)or UIS:IsKeyDown(Enum.KeyCode.RightControl))then studio.code:ReleaseFocus(false);studio.run()end
end)
studio.layout(workspace.CurrentCamera.ViewportSize)
-- Useful session tools.
studio.toolCount=0
function studio.tool(name,label,callback)
studio.toolCount+=1
local control=button(pages.Tools,name,label,UDim2.new(),UDim2.new(1,0,0,44))
on(control.Activated,function()
local ok,result=pcall(callback)
studio.toolStatus.Detail.Text=ok and (result or "Done.")or "Failed: "..tostring(result):sub(1,160)
end)
end
function studio.copy(textValue)
local copy=setclipboard or toclipboard;assert(type(copy)=="function","Clipboard API unavailable")
copy(textValue);return "Copied to clipboard."
end
heading(pages.Tools,"Session tools","Script editor, local profiles, camera recovery, weapon switching, and quick diagnostics.")
studio.tool("OpenScriptStudio","OPEN SCRIPT STUDIO",function()studio.show(true);return "Script Studio opened."end)
studio.tool("SaveNovaProfile","SAVE GAME SETTINGS",function()
assert(type(writefile)=="function","File saving unavailable")
if type(makefolder)=="function"then pcall(makefolder,"NOVA")end
writefile("NOVA/settings-"..game.PlaceId..".json",Http:JSONEncode({place=game.PlaceId,settings=C}));return "Settings saved for this game."
end)
studio.tool("LoadNovaProfile","LOAD GAME SETTINGS",function()
local data=Http:JSONDecode(readfile("NOVA/settings-"..game.PlaceId..".json"))
assert(data.place==game.PlaceId and type(data.settings)=="table","Invalid profile for this game")
for key,value in pairs(data.settings)do
if typeof(value)==typeof(C[key])and (type(value)~="number"or value==value and math.abs(value)<=1000000)then C[key]=value end
end
for _,key in ipairs({"Bot","AutoShoot","TriggerBot","AutoClicker","Healing","DefenseAssist","EditorOpen"})do C[key]=false end
refresh();return "Settings loaded. Automatic actions are paused; enable them when ready."
end)
studio.tool("CopyCoordinates","COPY COORDINATES",function()local _,_,r=extras.characterParts();assert(r,"No character");return studio.copy(string.format("%.2f, %.2f, %.2f",r.Position.X,r.Position.Y,r.Position.Z))end)
studio.tool("CopyGameDetails","COPY GAME DETAILS",function()return studio.copy("Place: "..game.PlaceId.."\nServer: "..game.JobId.."\nPlayers: "..#Players:GetPlayers())end)
studio.tool("CycleWeapon","NEXT COMPATIBLE GUN",function()
local ch,h=extras.characterParts();assert(h,"No living character")
local reg=autofire.registryForGame();assert(reg,"No compatible gun adapter")
local list={};for tool,gun in pairs(reg.Tools)do if typeof(tool)=="Instance"and (tool.Parent==LP.Backpack or tool.Parent==ch)and type(gun)=="table"and type(gun.DoFire)=="function"then table.insert(list,tool)end end
table.sort(list,function(a,b)return a.Name<b.Name end);assert(#list>0,"No compatible guns owned")
local index=table.find(list,ch:FindFirstChildOfClass("Tool"))or 0;local tool=list[index%#list+1];h:EquipTool(tool);return "Equipped "..tool.Name
end)
studio.tool("UnequipTools","UNEQUIP TOOL",function()local _,h=extras.characterParts();assert(h,"No living character");h:UnequipTools();return "Tool unequipped."end)
studio.tool("RepairCamera","RESTORE CAMERA FOLLOW",function()
local _,h=extras.characterParts();assert(h,"No living character")
C.CameraOverride=false;C.CameraOffsetOverride=false;C.ZoomOverride=false;C.ViewMode="Game default"
workspace.CurrentCamera.CameraType=Enum.CameraType.Custom;workspace.CurrentCamera.CameraSubject=h;refresh();return "Camera follow restored."
end)
studio.tool("LowClutterPreset","LOW CLUTTER VIEW",function()C.Circle=false;C.Opacity=100;C.Distance=false;C.Health=false;C.Names=true;C.NoBlur=true;C.NoDOF=true;C.Motion=false;refresh();return "Low clutter view applied."end)
studio.tool("NightVisionPreset","BRIGHT CLEAR VIEW",function()C.FullBright=true;C.NoFog=true;C.NoShadows=true;refresh();return "Local bright, clear view applied."end)
studio.tool("ShowPerformance","SHOW PERFORMANCE HUD",function()C.ShowFPS=true;C.FPSDetails=true;C.FPSGraph=true;refresh();return "Performance HUD enabled."end)
studio.tool("WeaponDiagnostics","CHECK CURRENT WEAPON",function()utility.inspect();return gui:GetAttribute("AmmoStatus")end)
studio.tool("StopCombatTools","STOP COMBAT FEATURES",function()
for _,key in ipairs({"Bot","Aim","AutoShoot","TriggerBot","AutoClicker","InfiniteAmmo","NoCooldown","NoRecoil","NoSpread","NoAimKick","Hitboxes","WallShots"})do C[key]=false end
bot.stop("Stopped from session tools");autofire.reset("Stopped");refresh();return "Combat features stopped."
end)
studio.toolStatus=row(pages.Tools,"ToolsStatus","Tools status","Ready. Script Studio also has a shortcut on the right.",120)
studio.toolStatus.RowTitle.Size=UDim2.new(1,-32,0,22);studio.toolStatus.Detail.Size=UDim2.new(1,-32,1,-48)
gui:SetAttribute("SessionToolCount",studio.toolCount)
C.BotObstacleJump=true;C.BotShortcut=true;C.BotJumpLookAhead=6;C.BotMaxObstacle=4
function bot.checkObstacle(hum,root,direction)
local now=os.clock()
if not C.BotObstacleJump or bot.jumpPlan or hum.FloorMaterial==Enum.Material.Air or now<(bot.nextObstacleJump or 0)or now<(bot.nextObstacleScan or 0)then return false end
bot.nextObstacleScan=now+.15
direction=Vector3.new(direction.X,0,direction.Z)
if direction.Magnitude<.01 then return false end;direction=direction.Unit
local params=RaycastParams.new();params.FilterType=Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances={LP.Character,world,bot.target and bot.target.Character}
if typeof(root)=="Instance"and root.Parent then local exclude=params.FilterDescendantsInstances;table.insert(exclude,root.Parent);params.FilterDescendantsInstances=exclude end
pcall(function()params.RespectCanCollide=true end)
local floor=workspace:Raycast(root.Position,Vector3.new(0,-12,0),params)
if not floor then return false end
local gravity=math.max(1,workspace.Gravity)
local jumpHeight=hum.UseJumpPower and hum.JumpPower*hum.JumpPower/(2*gravity)or hum.JumpHeight
local velocity=math.sqrt(2*gravity*jumpHeight)
local speed=math.max(1,hum.WalkSpeed)
local reach=speed*(2*velocity/gravity)*.82
local scan=math.min(C.BotJumpLookAhead,math.max(2,reach-2))
local hit
for _,height in ipairs({.7,1.6,2.5})do
local origin=Vector3.new(root.Position.X,floor.Position.Y+height,root.Position.Z)
local candidate=workspace:Raycast(origin,direction*scan,params)
if candidate and (not hit or candidate.Distance<hit.Distance)then hit=candidate end
end
if not hit then return false end
bot.failedBarriers=bot.failedBarriers or setmetatable({},{__mode="k"})
if now<(bot.failedBarriers[hit.Instance]or 0)then gui:SetAttribute("BotObstacleStatus","Recent failed jump: using a route around this barrier");return false end
local maximum=math.min(C.BotMaxObstacle,jumpHeight*.75)
local probe=hit.Position+direction*.4
local top=workspace:Raycast(Vector3.new(probe.X,floor.Position.Y+maximum+1,probe.Z),Vector3.new(0,-maximum-2,0),params)
if not top or top.Instance~=hit.Instance or top.Position.Y-floor.Position.Y>maximum then gui:SetAttribute("BotObstacleStatus","Barrier exceeds jump clearance: routing around it");return false end
local barrierHeight=top.Position.Y-floor.Position.Y
if barrierHeight<.9 then return false end
local landing
local side=Vector3.new(-direction.Z,0,direction.X)
for extra=3,math.max(3,reach-hit.Distance),.5 do
local point=hit.Position+direction*extra
local ground=workspace:Raycast(Vector3.new(point.X,floor.Position.Y+maximum+1,point.Z),Vector3.new(0,-maximum-8,0),params)
if ground and ground.Instance~=hit.Instance and ground.Position.Y-floor.Position.Y<=maximum and ground.Position.Y-floor.Position.Y>=-4 then
local clear=true
for _,offset in ipairs({Vector3.zero,side,-side,direction,-direction})do
local supported=workspace:Raycast(ground.Position+offset+Vector3.new(0,1.2,0),Vector3.new(0,-2.4,0),params)
if not supported or math.abs(supported.Position.Y-ground.Position.Y)>.8 or workspace:Raycast(ground.Position+offset+Vector3.new(0,.2,0),Vector3.new(0,4.8,0),params)then clear=false;break end
end
if clear then landing=ground.Position;break end
end
end
if not landing then gui:SetAttribute("BotObstacleStatus","No supported landing within jump range: routing around");return false end
local rootOffset=root.Position.Y-floor.Position.Y
local deltaY=landing.Y+rootOffset-root.Position.Y
local discriminant=velocity*velocity-2*gravity*deltaY
if discriminant<=0 then return false end
local flight=(velocity+math.sqrt(discriminant))/gravity
local horizontal=Vector3.new(landing.X-root.Position.X,0,landing.Z-root.Position.Z)
local distance=horizontal.Magnitude
if distance>speed*flight*.9 then gui:SetAttribute("BotObstacleStatus","Landing beyond current jump range");return false end
local travel=horizontal.Unit
local offsets={Vector3.new(0,-math.max(.5,rootOffset-.35),0),Vector3.zero,Vector3.new(0,1.8,0),side*.75,-side*.75}
local previous=root.Position
for index=1,12 do
local t=flight*index/12
local point=root.Position+travel*math.min(distance,speed*t)+Vector3.new(0,velocity*t-.5*gravity*t*t,0)
for _,offset in ipairs(offsets)do
local blocked=workspace:Raycast(previous+offset,point-previous,params)
if blocked then gui:SetAttribute("BotJumpBlockedBy",blocked.Instance:GetFullName());gui:SetAttribute("BotObstacleStatus","Jump arc intersects cover or ceiling: routing around");return false end
end
previous=point
end
if not bot.requestJump(hum,"Planned barrier jump")then return false end
bot.jumpPlan={goal=Vector3.new(landing.X,landing.Y+rootOffset,landing.Z),started=now,flight=flight,obstacle=hit.Instance,wasAir=false,start=root.Position}
bot.goal=bot.jumpPlan.goal;bot.smoothed=travel;hum:Move(travel,false)
bot.nextObstacleJump=now+flight+.3
gui:SetAttribute("BotObstacleStatus",string.format("Committed jump: %.1f high / %.1f forward",barrierHeight,distance))
return true,bot.jumpPlan.goal
end
function bot.updateJump(hum,root)
local plan=bot.jumpPlan;if not plan then return end
local now=os.clock()
if hum.FloorMaterial==Enum.Material.Air or root.Position.Y-plan.start.Y>.5 then plan.wasAir=true end
local landed=plan.wasAir and hum.FloorMaterial~=Enum.Material.Air and root.AssemblyLinearVelocity.Y<2 and now-plan.started>.18
if landed or now-plan.started>plan.flight+1 then
local gap=Vector3.new(root.Position.X-plan.goal.X,0,root.Position.Z-plan.goal.Z).Magnitude
if not landed or gap>2 or math.abs(root.Position.Y-plan.goal.Y)>1.2 then
bot.failedBarriers[plan.obstacle]=now+8;bot.waypoints=nil;bot.pathAt=0
gui:SetAttribute("BotObstacleStatus","Jump did not reach landing: avoiding this barrier for 8 seconds")
else gui:SetAttribute("BotObstacleStatus","Jump landed successfully")end
bot.jumpPlan=nil;bot.shortcutUntil=0
else bot.goal=plan.goal end
end
heading(pages.Bot,"Obstacle navigation","Plan jumps using the character's jump height, a supported landing, and body clearance along the full jump arc.")
toggle(pages.Bot,"BotObstacleJump","Obstacle jump","Jump checked low barriers. Movement stays committed to the landing while airborne.")
toggle(pages.Bot,"BotShortcut","Jump shortcuts","Try a short checked jump before taking a longer path around an obstacle.")
slider(pages.Bot,"BotJumpLookAhead","Obstacle detection distance","Scan ahead; actual movement speed and jump range limit the planner.",3,8,.5)
slider(pages.Bot,"BotMaxObstacle","Maximum barrier height","Actual jump height and ceiling clearance may impose a lower limit.",1,6,.5)
bot.obstacleRow=row(pages.Bot,"ObstacleNavigation","Obstacle status","Ready. Failed barriers are temporarily avoided rather than repeatedly jumped into.",130)
bot.obstacleRow.RowTitle.Size=UDim2.new(1,-32,0,22);bot.obstacleRow.Detail.Size=UDim2.new(1,-32,1,-48)
C.BotFollowCamera=true;C.BotCameraSpeed=8;C.BotJumpAssist=true
function bot.requestJump(hum,reason)
local now=os.clock()
if hum.FloorMaterial==Enum.Material.Air or now<(bot.nextNativeJump or 0)then return false end
local ok,enabled=pcall(hum.GetStateEnabled,hum,Enum.HumanoidStateType.Jumping)
if not ok or not enabled then gui:SetAttribute("BotObstacleStatus","The game currently disables jumping; computing a route around it.");return false end
bot.nextNativeJump=now+.65;bot.jumpUntil=now+.25
hum.Jump=true
if C.BotJumpAssist then pcall(hum.ChangeState,hum,Enum.HumanoidStateType.Jumping)end
gui:SetAttribute("BotJumpReason",reason or "Navigation")
return true
end
function bot.routeCamera(cam,root,dt,fallback)
if not C.BotFollowCamera then return end
local direction=bot.smoothed
if direction.Magnitude<.1 and bot.goal then direction=bot.goal-root.Position end
if direction.Magnitude<.1 and fallback then direction=fallback-root.Position end
direction=Vector3.new(direction.X,0,direction.Z)
if direction.Magnitude<.1 then return end
local desired=CFrame.lookAt(cam.CFrame.Position,cam.CFrame.Position+direction.Unit*30)
cam.CFrame=cam.CFrame:Lerp(desired,1-math.exp(-C.BotCameraSpeed*math.min(dt,.1)))
gui:SetAttribute("BotCameraStatus","Following travel direction")
end
heading(pages.Bot,"Camera and jump control","The camera follows travel direction and switches to visible targets during a fight.")
toggle(pages.Bot,"BotFollowCamera","Follow bot view","Turn your screen smoothly toward the route while the bot walks.")
slider(pages.Bot,"BotCameraSpeed","Route camera turn speed","Smooth camera response while navigating.",3,20,1)
toggle(pages.Bot,"BotJumpAssist","Jump input assist","Use the native jump state and briefly hold the jump request to avoid canceled inputs.")
C.BotADS=true
function bot.setADS(gun,enabled)
enabled=enabled and C.BotADS
if not enabled or gun~=bot.adsGun then
if bot.adsGun and bot.adsOriginal then
if bot.adsGun.DoAim==bot.adsWrapper then pcall(function()bot.adsGun.DoAim=bot.adsOriginal end)end
pcall(bot.adsOriginal,bot.adsGun,false)
end
bot.adsGun=nil;bot.adsActive=false;bot.adsOriginal=nil;bot.adsWrapper=nil
end
if not enabled or not C.BotADS then gui:SetAttribute("BotADSStatus","Hip fire / traveling");return end
if type(gun)~="table"or type(gun.DoAim)~="function"then gui:SetAttribute("BotADSStatus","Weapon does not expose native aim-down-sights");return end
local hum=LP.Character and LP.Character:FindFirstChildOfClass("Humanoid")
if not bot.adsWrapper then
local original=gun.DoAim
local wrapper=function(self,requested,...)
local character=LP.Character
local h=character and character:FindFirstChildOfClass("Humanoid")
local held=alive and C.Bot and C.BotADS and bot.adsActive and bot.adsGun==self and extras.active()and not C.Healing and not C.EditorOpen and h and not h:GetAttribute("Reloading")
return original(self,held and true or requested,...)
end
local ok=pcall(function()gun.DoAim=wrapper end)
if not ok then gui:SetAttribute("BotADSStatus","Weapon aim controller is read-only");return end
bot.adsOriginal=original;bot.adsWrapper=wrapper;bot.adsGun=gun;bot.adsActive=true
end
if gun==bot.adsGun and hum and hum:GetAttribute("Aiming")then return end
if os.clock()<(bot.adsRetry or 0)then return end;bot.adsRetry=os.clock()+.3
local ok,err=pcall(gun.DoAim,gun,true)
if ok then bot.adsGun=gun;bot.adsActive=true;gui:SetAttribute("BotADSStatus","Native aim-down-sights requested")
else gui:SetAttribute("BotADSStatus","Native aim unavailable: "..tostring(err):sub(1,90))end
end
toggle(pages.Bot,"BotADS","Aim down sights","Use the gun's native aim/scope action on visible targets. Release it during travel, reload, pause, or stop.")
bot.adsRow=row(pages.Bot,"BotADSStatus","Aim-down-sights status","Ready. Requires a compatible gun with a native DoAim action.",110)
bot.adsRow.RowTitle.Size=UDim2.new(1,-32,0,22);bot.adsRow.Detail.Size=UDim2.new(1,-32,1,-48)
-- TTK uses a controller-owned weapon model, not a Backpack Tool.
do
local ttk={name="TTK Testing",registry={Tools={}},controller=nil,weapon=nil,tool=nil,gun=nil}
function ttk.connect()
if (game.PlaceId~=120189115846709 and game.GameId~=10090256806) then return nil end
if ttk.controller then return ttk.controller end
local rs=game:GetService("ReplicatedStorage")
local modules=rs:FindFirstChild("Modules")
local client=modules and modules:FindFirstChild("Client")
local controllers=client and client:FindFirstChild("Controllers")
local module=controllers and controllers:FindFirstChild("GunController")
if not module or not module:IsA("ModuleScript") then return nil end
local ok,value=pcall(require,module)
if ok and type(value)=="table" and type(value.FireWeapon)=="function" and type(value.Reload)=="function" and type(value.StartAiming)=="function" and type(value.StopAiming)=="function" then ttk.controller=value;return value end
end
function ttk.current()
local c=ttk.connect()
local w=c and c.Weapon
if type(w)~="table" or not c.Enabled or not w.IsEquipped or c._isGenericItem then
ttk.weapon=nil;ttk.tool=nil;ttk.gun=nil;table.clear(ttk.registry.Tools)
gui:SetAttribute("AdapterWeapon",nil)
return nil
end
if ttk.weapon~=w then
ttk.weapon=w
local tool={Name=w.Name or "TTK weapon",Enabled=true,Parent=LP.Character}
function tool:GetAttribute(key)
if key=="Ammo" then return w.MagAmmo end
if key=="Mags" then return type(w.GetReserve)=="function" and w:GetReserve() or 0 end
end
local gun={Settings={Modes={w.FireMode=="auto" and "Automatic" or "Semi"}}}
function gun:DoFire()
if not alive or c.Weapon~=w or not c.Enabled or w.IsReloading then return false end
if type(c.ShouldBlockWeaponInput)=="function" and c:ShouldBlockWeaponInput() then return false end
local fired=c:FireWeapon()
-- A discrete native shot, including semi-auto trigger release.
if fired and not UIS:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) and type(w.ReleaseTrigger)=="function" then w:ReleaseTrigger() end
return fired
end
function gun:DoReload()
if alive and c.Weapon==w and c.Enabled and not w.IsReloading then return c:Reload() end
end
function gun:DoAim(enabled)
if c.Weapon~=w then return end
if enabled and alive and c.Enabled and not w.IsReloading then c:StartAiming() else c:StopAiming() end
end
ttk.tool=tool;ttk.gun=gun;table.clear(ttk.registry.Tools);ttk.registry.Tools[tool]=gun
end
ttk.tool.Parent=LP.Character
ttk.tool.Enabled=c.Enabled and not w.IsReloading
gui:SetAttribute("WeaponAdapter",ttk.name)
gui:SetAttribute("AdapterWeapon",ttk.tool.Name)
return ttk.tool,ttk.gun
end
if (game.PlaceId==120189115846709 or game.GameId==10090256806) then
gui:SetAttribute("WeaponAdapter",ttk.name)
gui:SetAttribute("AdapterSupport","Native firing, aiming, reload, bot weapon selection. Ammo, wall shots, recoil overrides, healing and defense are unavailable.")
autofire.registryForGame=function()ttk.current();return ttk.registry end
autofire.currentTool=function()return ttk.current()end
utility.current=function()return ttk.current()end
utility.watch=function()end -- No Tool attribute signals exist in this game.
utility.capacity=function(tool)
local current,gun=ttk.current()
if current and current==tool then return tonumber(ttk.weapon.MaxMagSize),gun end
end
utility.refill=function()utility.status("TTK Testing: infinite ammo is unsupported; native ammo rules remain active.")end
utility.inspect=function()
local tool=ttk.current()
gui:SetAttribute("AmmoServerVerified",false)
if not tool then gui:SetAttribute("AmmoWeapon",nil);gui:SetAttribute("AmmoCapacity",0);utility.status("TTK Testing: equip a firearm to use native fire, aim and reload.");return end
local capacity=tonumber(ttk.weapon.MaxMagSize) or 0
gui:SetAttribute("AmmoWeapon",tool.Name);gui:SetAttribute("AmmoCapacity",capacity)
utility.status(C.InfiniteAmmo and "TTK Testing: infinite ammo is unsupported; native ammo rules remain active." or (tool.Name.." | "..tostring(tool:GetAttribute("Ammo")).."/"..capacity.." | reserve "..tostring(tool:GetAttribute("Mags"))..". Native firing / aiming / reload supported."))
end
bot.weapon=function()
local tool,gun=ttk.current()
if tool then return tool,gun end
return nil,nil,"TTK Testing: equip a firearm; automatic loadout selection is unavailable."
end
combat.checkWeapons=function()local tool=ttk.current();return "TTK Testing - native fire / aim / reload; "..(tool and tool.Name or "equip a gun"),true end
combat.checkWallFilter=function()return "UNSUPPORTED - TTK native ballistic rules apply"end
local support=row(pages.Settings,"TTKSupport","TTK Testing compatibility",gui:GetAttribute("AdapterSupport"),130)
support.RowTitle.Size=UDim2.new(1,-32,0,22);support.Detail.Size=UDim2.new(1,-32,1,-48)
if bot.adsRow then bot.adsRow.Detail.Text="TTK Testing uses native StartAiming / StopAiming."end
utility.inspect()
end
end
C.BotAvoid=true
function bot.steer(hum,root,wanted)
if not C.BotAvoid or wanted.Magnitude<.1 or bot.jumpPlan or hum.FloorMaterial==Enum.Material.Air then return wanted,false end
wanted=Vector3.new(wanted.X,0,wanted.Z).Unit
local now=os.clock()
local params=RaycastParams.new();params.FilterType=Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances={LP.Character,world,root.Parent,bot.target and bot.target.Character}
pcall(function()params.RespectCanCollide=true end)
local floor=workspace:Raycast(root.Position,Vector3.new(0,-12,0),params)
if not floor then return Vector3.zero,true end
local rootHeight=root.Position.Y-floor.Position.Y
local look=math.clamp(hum.WalkSpeed*.35,4,8)
local radius=math.clamp(root.Size.X*.5,.8,1.5)
local function clear(direction)
local side=Vector3.new(-direction.Z,0,direction.X)*radius
for _,offset in {Vector3.zero,Vector3.new(0,1.5,0),Vector3.new(0,-math.min(1.2,rootHeight-.4),0),side,-side} do
if workspace:Raycast(root.Position+offset,direction*look,params) then return false end
end
for _,offset in {Vector3.zero,side*.7,-side*.7} do
local ahead=root.Position+direction*math.min(look,4)+offset
local support=workspace:Raycast(ahead+Vector3.new(0,2,0),Vector3.new(0,-rootHeight-5,0),params)
if not support or support.Normal.Y<.55 or support.Position.Y-floor.Position.Y>1.5 or support.Position.Y-floor.Position.Y< -3 then return false end
end
return true
end
if clear(wanted) then
gui:SetAttribute("BotAvoidance","Route clear")
return wanted,false
end
local best,score,chosenSign=nil,-math.huge,0
for _,angle in {35,-35,70,-70,105,-105,145,-145,180} do
local direction=CFrame.fromAxisAngle(Vector3.yAxis,math.rad(angle)):VectorToWorldSpace(wanted)
if clear(direction) then
local sign=angle>0 and 1 or -1
local value=direction:Dot(wanted)*2
if now<(bot.avoidUntil or 0) and sign==bot.avoidSign then value+=.65 end
if value>score then best=direction;score=value;chosenSign=sign end
end
end
if best then
bot.avoidSign=chosenSign;bot.avoidUntil=now+.8
gui:SetAttribute("BotAvoidance","Steering around obstacle / checking ground clearance")
gui:SetAttribute("BotObstacleStatus","Steering around blocked route")
return best,true
end
if now>=(bot.avoidRepathAt or 0) then bot.avoidRepathAt=now+.8;bot.pathAt=0;bot.waypoints=nil end
gui:SetAttribute("BotAvoidance","No safe side route: stopped for path replanning")
gui:SetAttribute("BotObstacleStatus","Blocked on all sides: requesting a new path")
return Vector3.zero,true
end
toggle(pages.Bot,"BotAvoid","Avoid walls and ledges","Scan body clearance and ground support, steer around obstacles, and stop for a new path when no safe direction is available. Start Bot enables this.")
-- Shared capability layer: explicit native adapters first, ordinary Tool input second.
do
local compat={name="NOVA Shooter",mode="Standard tools",registry={Tools={}},cache=setmetatable({},{__mode="k"}),held=nil}
local nativeRegistry=autofire.registryForGame
local nativeBotWeapon=bot.weapon
local nativeInspect=utility.inspect
C.GenericToolInput=false
function compat.detect()
if (game.PlaceId==120189115846709 or game.GameId==10090256806) then compat.mode="TTK Testing";return end
local reg=nativeRegistry()
compat.mode=reg and "Native gun adapter" or "Standard tools"
end
function compat.reason(key)
if compat.mode=="TTK Testing" then
if table.find({"InfiniteAmmo","WallShots","NoCooldown","NoRecoil","NoSpread","NoAimKick","DefenseAssist","BotEquip","GenericToolInput"},key) then return "Unavailable in TTK Testing. Native firing, ADS and reload are supported." end
elseif compat.mode=="Standard tools" then
if table.find({"InfiniteAmmo","WallShots","NoCooldown","NoRecoil","NoSpread","NoAimKick","AutoReload","BotReload","BotADS","BotEquip","DefenseAssist"},key) then return "This game has no adapter for this feature. Standard Tool input supports activation only." end
end
if key=="DefenseAssist" and game.PlaceId~=126210570846701 then return "This game has no verified healing adapter." end
end
function compat.release()
local held=compat.held;compat.held=nil;compat.serial=(compat.serial or 0)+1
if held then pcall(held.Deactivate,held) end
end
function compat.armStandardInput()
if compat.mode~="Standard tools" then return true end
local ch=LP.Character
local tool=ch and ch:FindFirstChildOfClass("Tool")
if not tool then
local hum=ch and ch:FindFirstChildOfClass("Humanoid")
local backpack=LP:FindFirstChildOfClass("Backpack")
if hum and backpack then for _,candidate in backpack:GetChildren() do
if candidate:IsA("Tool") and candidate.Enabled and candidate:GetAttribute("Gun")==true then hum:EquipTool(candidate);tool=candidate;break end
end end
end
if not tool then return false end
C.GenericToolInput=true
return true
end
ui.prepareBot=compat.armStandardInput
C.ToolFireMode="Auto"
function compat.inputMethod(tool)
if C.ToolFireMode~="Auto" then return C.ToolFireMode end
if mobile then return "Tool activation" end
if type(getconnections)=="function" then
local ok,connections=pcall(getconnections,tool.Activated)
if ok and #connections>0 then return "Tool activation" end
if ok and type(mouse1click)=="function" then return "Mouse click" end
end
if game.GameId==9741874508 and type(mouse1click)=="function" then return "Mouse click" end
return "Tool activation"
end
function compat.current()
local ch=LP.Character
local hum=ch and ch:FindFirstChildOfClass("Humanoid")
local tool=ch and ch:FindFirstChildOfClass("Tool")
if not C.GenericToolInput or not hum or hum.Health<=0 or not tool or not tool.Enabled then table.clear(compat.registry.Tools);return nil end
local gun=compat.cache[tool]
if not gun then
gun={Settings={}}
function gun:DoFire()
if not alive or not C.GenericToolInput or tool.Parent~=LP.Character or not tool.Enabled then return false end
if menuOpen or not focus or UIS:GetFocusedTextBox() then return false end
if type(iswindowactive)=="function" then local ok,active=pcall(iswindowactive);if not ok or not active then return false end end
local method=compat.inputMethod(tool)
gui:SetAttribute("SharedFireMethod",method)
if method=="Mouse click" then
if type(mouse1click)~="function" or type(iswindowactive)~="function" then return false end
local position=UIS:GetMouseLocation()
if ui.pointerBlocked(position) then gui:SetAttribute("SharedFireStatus","Paused: pointer is over a Nova control");return false end
mouse1click();gui:SetAttribute("SharedFireStatus","Mouse click dispatched; native cooldown and game rules apply");return true
end
compat.release()
tool:Activate();compat.held=tool;gui:SetAttribute("SharedFireStatus","Tool activated; native game rules apply")
local serial=compat.serial
task.delay(.05,function()
if compat.held==tool and compat.serial==serial then compat.release() end
end)
return true
end
compat.cache[tool]=gun
end
table.clear(compat.registry.Tools);compat.registry.Tools[tool]=gun
return tool,gun
end
compat.detect()
local applyNativePreset=preset.apply
preset.apply=function()
if not compat.armStandardInput() then notify("Equip a weapon","Equip a Tool before applying a shooting preset in this game.");return end
applyNativePreset()
end
if compat.mode=="Standard tools" then
autofire.registryForGame=function()
local reg=nativeRegistry()
if reg then compat.mode="Native gun adapter";return reg end
compat.current();return compat.registry
end
bot.weapon=function(hum,ch)
if compat.mode~="Standard tools" then return nativeBotWeapon(hum,ch) end
local tool,gun=compat.current()
if tool then return tool,gun end
return nil,nil,"Equip a gun represented by a Tool. This game may need a custom weapon adapter."
end
utility.inspect=function()
if compat.mode~="Standard tools" then return nativeInspect() end
local ch=LP.Character;local tool=ch and ch:FindFirstChildOfClass("Tool")
utility.status("Standard Tool input: "..(tool and tool.Name or "equip a weapon")..". "..(C.GenericToolInput and "Activation enabled; firing depends on the game." or "Enable auto shoot or Start Bot with an equipped Tool to use standard activation.").." Ammo and reload overrides are unavailable.")
end
end
ui.enforceCapabilities=function()
for key,value in pairs(C) do if value==true and compat.reason(key) then C[key]=false end end
end
ui.canToggle=function(key)
if not C[key] and (key=="Bot" or key=="AutoShoot" or key=="TriggerBot") and not compat.armStandardInput() then
if notify then notify("Equip a weapon","This game uses Standard Tool input. Equip the gun you want to activate, then try again.") end
return false
end
local reason=compat.reason(key)
if reason then if notify then notify("Game compatibility",reason) end;return false end
return true
end
heading(pages.Game,"NOVA / Shooter compatibility","Detect a native weapon adapter or use ordinary equipped-Tool input. Custom weapons and character rigs may require more support.")
compat.game=row(pages.Game,"DetectedGame","Detected game","",120)
compat.features=row(pages.Game,"SupportedFeatures","Feature compatibility","",215)
compat.botStatus=row(pages.Game,"LiveBotStatus","Bot status","Stopped. START BOT configures movement and supported weapon controls. Roblox must be focused.",125)
for _,box in {compat.game,compat.features,compat.botStatus} do box.RowTitle.Size=UDim2.new(1,-32,0,22);box.Detail.Size=UDim2.new(1,-32,1,-48) end
local start=button(pages.Game,"StartBot","START BOT / F7",UDim2.new(),UDim2.new(1,0,0,48))
on(start.Activated,function()C.Bot=true;refresh();showMenu(false);notify("Bot enabled","Movement and supported ADS/reload are configured automatically. Focus Roblox; F10 stops.")end)
toggle(pages.Game,"GenericToolInput","Standard Tool input","Normal equipped-Tool activation for other games. Enabling auto shoot, Start Bot, or the game preset arms this input mode. It cannot add an unsupported firing system.")
cycle(pages.Game,"ToolFireMode","Shared weapon input","Auto uses Tool activation when handlers exist, otherwise native mouse clicks when available. Choose a method manually if this game needs it.",{"Auto","Tool activation","Mouse click"})
local check=button(pages.Game,"CheckSupport","CHECK GAME SUPPORT",UDim2.new(),UDim2.new(1,0,0,44))
local combatPage=button(pages.Game,"OpenCombat","OPEN SHOOTING CONTROLS",UDim2.new(),UDim2.new(1,0,0,44))
on(combatPage.Activated,function()selectTab("Combat")end)
local botPage=button(pages.Game,"OpenBot","OPEN BOT AND MOVEMENT",UDim2.new(),UDim2.new(1,0,0,44))
on(botPage.Activated,function()selectTab("Bot")end)
for i,entry in {{"Aim","AIM"},{"AutoShoot","AUTO FIRE"},{"Bot","BOT PLAY"}} do
local key,title=entry[1],entry[2]
local quick=button(gui,"TTKQuick"..key,"",UDim2.new(1,-16,.5,-122+(i-1)*50),UDim2.fromOffset(174,44))
quick.AnchorPoint=Vector2.new(1,0);quick.ZIndex=25
on(quick.Activated,function()
if not C[key] and ui.canToggle and not ui.canToggle(key) then return end
if key=="Bot" then C.Bot=not C.Bot;if not C.Bot then bot.stop("Stopped")end else C[key]=not C[key]end
refresh();notify(title,C[key] and "Enabled; close the menu to engage." or "Disabled")
end)
table.insert(paints,function()quick.Text=title..": "..(C[key] and "ON" or "OFF");quick.BackgroundColor3=C[key] and Color3.fromRGB(28,133,94)or Color3.fromRGB(31,34,43)end)
end
local botBadge=make("Frame",{Name="BotLiveBadge",AnchorPoint=Vector2.new(1,0),Position=UDim2.new(1,-16,.5,-194),Size=UDim2.fromOffset(174,66),BackgroundColor3=Color3.fromRGB(23,26,34),BorderSizePixel=0,ZIndex=25,Visible=false},gui)
round(botBadge,8)
local botBadgeText=text(botBadge,"",10,ink,UDim2.fromOffset(8,5),UDim2.new(1,-16,1,-10));botBadgeText.TextWrapped=true;botBadgeText.ZIndex=26
function compat.update()
if not alive then return end
botBadge.Visible=C.Bot
botBadgeText.Text=gui:GetAttribute("BotStatus") or "Bot starting"
local native=compat.mode=="TTK Testing" or compat.mode=="Native gun adapter"
local tool=utility.current()
local weapon=tool and tool.Name or "No equipped weapon"
if compat.mode=="Standard tools" and tool then gui:SetAttribute("SharedFireMethod",compat.inputMethod(tool))end
compat.game.Detail.Text=compat.mode.." / Place "..game.PlaceId.."\n"..weapon..(compat.mode=="Standard tools" and tool and (" / "..compat.inputMethod(tool)) or "").."\nBoot settings: every switch OFF."
compat.botStatus.Detail.Text=(gui:GetAttribute("BotStatus") or "Stopped").."\nF7 toggles / F10 stops / F8 emergency stop. Reopening the menu pauses the bot."
compat.features.Detail.Text=compat.mode=="TTK Testing" and "Native: firing, aim down sights, reload, bot weapon detection.\nShared: aim camera, player overlays, crosshair, navigation, clicker and interface tools.\nUnavailable: infinite ammo, wall shots, recoil overrides, healing and defense."
or native and "Native gun adapter detected. Use Combat's compatibility check for weapon details.\nShared: camera, overlays, crosshair, navigation, clicker and interface tools.\nServer-controlled effects depend on this game's support."
or "Shared: standard Humanoid player detection, aim camera, overlays, crosshair, navigation and clicker.\nOpt in: equipped Tool activation or mouse input for auto shoot / bot.\nUnavailable: native ADS, ammo, reload, wall shots, recoil, healing and defense. Custom characters and weapons require a game adapter."
gui:SetAttribute("Edition","NOVA Shooter");gui:SetAttribute("CompatibilityMode",compat.mode)
gui:SetAttribute("CompatibilityWeapon",weapon)
for _,key in {"InfiniteAmmo","WallShots","NoCooldown","NoRecoil","NoSpread","NoAimKick","AutoReload","BotReload","BotADS","BotEquip","DefenseAssist","GenericToolInput"} do
local b=gui:FindFirstChild(key,true)
if b and b:IsA("GuiButton") then
local reason=compat.reason(key);b:SetAttribute("UnavailableReason",reason)
b.AutoButtonColor=reason==nil
local label=b.Parent:FindFirstChild("ToggleState")
if label and reason then label.Text="N/A";label.TextColor3=muted end
if label and not reason and label.Text=="N/A" then label.Text=C[key] and "ON" or "OFF" end
end
end
extras.ammo.Visible=compat.reason("InfiniteAmmo")==nil
if compat.mode~="Native gun adapter" then extras.ammo.Visible=false end
preset.quick.Position=UDim2.new(1,-16,.5,28)
studio.quick.Position=UDim2.new(1,-16,.5,78)
extras.ammo.Position=UDim2.new(1,-16,.5,128)
healing.quick.Position=UDim2.new(1,-16,.5,178)
defense.quick.Position=UDim2.new(1,-16,.5,228)
healing.quick.Visible=game.PlaceId==126210570846701
defense.quick.Visible=compat.reason("DefenseAssist")==nil
healing.button.Visible=game.PlaceId==126210570846701
end
on(check.Activated,function()compat.detect();ui.enforceCapabilities();refresh();compat.update();notify("Game support",compat.mode.." / capabilities refreshed")end)
local elapsed=0
on(Run.Heartbeat,function(dt)
elapsed+=dt;if elapsed<.5 then return end;elapsed=0
if compat.held and (not C.GenericToolInput or not C.Bot and not C.AutoShoot and not C.TriggerBot or menuOpen or not focus) then compat.release() end
compat.update()
end)
on(gui.Destroying,function()if compat.held then compat.release() end end)
compat.update()
end
heading(pages.Settings,"Session controls","Reset settings or unload. World changes restore automatically.")
local help=row(pages.Settings,"Help",mobile and "Touch controls" or "Cursor release",mobile and "MENU opens settings. Use the AIM pad during play." or "U unlocks your cursor. Right Shift toggles the menu.",124)
text(help,mobile and "Aim pauses while the menu is open.\nClose it to reveal the AIM control." or "Aim pauses while your cursor is free.\nMinimize the panel or press U to resume.",11,muted,
UDim2.fromOffset(16,mobile and 85 or 65),UDim2.new(1,-32,0,32))
local reset=button(pages.Settings,"Reset","↺ RESET ALL SETTINGS",UDim2.new(),UDim2.new(1,0,0,40))
for key,value in pairs(C)do if type(value)=="boolean"then C[key]=false end end
C.ViewMode="Game default"
local defaults=table.clone(C)
defaults.Color="Background";defaults.Motion=true;defaults.Backdrop=68
on(reset.Activated,function() C=table.clone(defaults);C.Aim=false;selected=nil;latch=false;refresh() end)
local stop=button(pages.Settings,"Stop","× UNLOAD NOVA",UDim2.new(),UDim2.new(1,0,0,40))
on(stop.Activated,function() gui:Destroy() end)
on(unload.Activated,function() gui:Destroy() end)
on(header.InputBegan,function(i)
if i.UserInputType==Enum.UserInputType.MouseButton1 or i.UserInputType==Enum.UserInputType.Touch then drag={mouse=i.Position,pos=root.AbsolutePosition-overlay.AbsolutePosition,input=i} end
end)
on(UIS.InputChanged,function(i)
if i.UserInputType~=Enum.UserInputType.MouseMovement and i.UserInputType~=Enum.UserInputType.Touch then return end
if sliding and (i==sliding.input or i.UserInputType==Enum.UserInputType.MouseMovement and sliding.input.UserInputType==Enum.UserInputType.MouseButton1) then sliding.update(i.Position.X) end
if drag and (i==drag.input or i.UserInputType==Enum.UserInputType.MouseMovement and drag.input.UserInputType==Enum.UserInputType.MouseButton1) then
local camera=workspace.CurrentCamera;if not camera then return end
local d=i.Position-drag.mouse;local size=root.AbsoluteSize;local v=overlay.AbsoluteSize
root.Position=UDim2.fromOffset(math.clamp(drag.pos.X+d.X,0,math.max(0,v.X-size.X))+size.X/2,
math.clamp(drag.pos.Y+d.Y,0,math.max(0,v.Y-size.Y))+size.Y/2)
end
end)
on(UIS.InputEnded,function(i)
if drag and (i==drag.input or i.UserInputType==Enum.UserInputType.MouseButton1 and drag.input.UserInputType==Enum.UserInputType.MouseButton1) then drag=nil end
if sliding and (i==sliding.input or i.UserInputType==Enum.UserInputType.MouseButton1 and sliding.input.UserInputType==Enum.UserInputType.MouseButton1) then
sliding=nil;for _,p in pairs(pages) do p.ScrollingEnabled=true end
end
if aimTouch==i then aimTouch=nil;touchHolding=false;gui:SetAttribute("TouchHolding",false);updateAimPad() end
end)
on(UIS.InputBegan,function(i)
if UIS:GetFocusedTextBox() then return end
if i.KeyCode==Enum.KeyCode.RightShift then showMenu(not menuOpen)
elseif i.KeyCode==Enum.KeyCode.U and not mobile then setFree(not free)
elseif not mobile and i.UserInputType==Enum.UserInputType.MouseButton2 and not free then latch=not latch end
end)
on(UIS.WindowFocusReleased,function() focus=false;releaseTouch();drag=nil;sliding=nil;for _,p in pairs(pages) do p.ScrollingEnabled=true end;updateAimPad() end)
on(UIS.WindowFocused,function() focus=true end)
local ring=make("Frame",{BackgroundTransparency=1,AnchorPoint=Vector2.new(.5,.5)},overlay)
make("UICorner",{CornerRadius=UDim.new(1,0)},ring)
local ringStroke=make("UIStroke",{Color=palettes[C.Color],Transparency=.5,Thickness=1},ring)
local motionTime=0
local parallax=Vector2.new()
local function animateChrome(dt)
halo.Visible=root.Visible
if root.Visible then
if C.Motion then motionTime+=dt*C.AnimationSpeed/100 end
local t=motionTime
local target=Vector2.new()
if C.Motion and C.Parallax and not mobile and free and focus then
local mouse=UIS:GetMouseLocation()
local center=root.AbsolutePosition+root.AbsoluteSize/2
target=Vector2.new(math.clamp((mouse.X-center.X)/math.max(1,root.AbsoluteSize.X),-.5,.5),
math.clamp((mouse.Y-center.Y)/math.max(1,root.AbsoluteSize.Y),-.5,.5))
end
if C.Motion then parallax=parallax:Lerp(target,1-math.exp(-dt*5)) else parallax=Vector2.new() end
surfaceLight.Offset=Vector2.new((t*.13)%2.8-1.4,0)
local edgeGradient=border:FindFirstChildOfClass("UIGradient")
if edgeGradient then edgeGradient.Rotation=25+math.sin(t*.2)*35 end
halo.Visible=root.Visible
halo.Position=UDim2.fromOffset(root.AbsolutePosition.X-overlay.AbsolutePosition.X+root.AbsoluteSize.X/2,
root.AbsolutePosition.Y-overlay.AbsolutePosition.Y+root.AbsoluteSize.Y/2)
halo.Size=UDim2.fromOffset(root.AbsoluteSize.X+8,root.AbsoluteSize.Y+8)
haloEdge.Transparency=.95+root.GroupTransparency*.05
liquid.Position=UDim2.fromScale(-.04+math.sin(t*.14)*.018+parallax.X*.025,-.035+math.cos(t*.12)*.007+parallax.Y*.012)
liquidSwap.Position=liquid.Position
local mix=backgroundMix.Value
liquid.ImageTransparency=1-C.Backdrop/100*(1-mix)
liquidSwap.ImageTransparency=1-C.Backdrop/100*mix
gui:SetAttribute("BackgroundLoaded",liquidSwap.IsLoaded)
mist.Position=UDim2.fromScale(-.03+math.sin(t*.09)*.018,.26)
mist.ImageTransparency=1-C.Backdrop/100*.15
chrome.Offset=Vector2.new(math.sin(t*.25)*.3,0)
shine.Offset=Vector2.new(math.sin(t*.3)*.65,0)
liveDot.BackgroundTransparency=.15+(math.sin(t*1.7)+1)*.2
end
end
local lastLayout=""
local function adaptiveLayout(view)
if mobile then
local w=math.max(260,math.min(600,view.X-24))
local h=math.max(240,math.min(740,view.Y-24))
local key=tostring(w).."x"..tostring(h)
scale.Scale=reveal.Value
if lastLayout==key then return end
lastLayout=key;compact=true
root.Size=UDim2.fromOffset(w,h);root.Position=UDim2.fromScale(.5,.5)
brand.TextSize=24;brand.Position=UDim2.fromOffset(16,7);brand.Size=UDim2.fromOffset(180,34)
heroTag.Visible=false;cursor.Visible=false
liveDot.Position=UDim2.fromOffset(18,55)
deviceBadge.Position=UDim2.fromOffset(30,47);deviceBadge.Size=UDim2.fromOffset(170,18)
header.Size=UDim2.new(1,-112,0,76)
minimize.Position=UDim2.new(1,-104,0,12);minimize.Size=UDim2.fromOffset(44,44)
unload.Position=UDim2.new(1,-54,0,12);unload.Size=UDim2.fromOffset(44,44)
for _,o in ipairs(root:GetChildren()) do
if o:IsA("TextLabel") and o.Text:find("L I Q U I D",1,true) then o.Visible=false end
if o:IsA("Frame") and o.Position.Y.Offset==143 then o.Position=UDim2.fromOffset(14,78);o.Size=UDim2.new(1,-28,0,1) end
end
side.Position=UDim2.fromOffset(12,88);side.Size=UDim2.new(1,-24,0,46)
keybox.Visible=false;rail.Visible=false
side.ScrollingEnabled=true;side.ScrollingDirection=Enum.ScrollingDirection.X;side.CanvasSize=UDim2.fromOffset(#tabNames*112,0)
for _,o in ipairs(side:GetChildren()) do if o:IsA("TextLabel") then o.Visible=false end end
for name,tab in pairs(tabs) do
tab.Position=UDim2.fromOffset((tabIndex[name]-1)*112+4,0);tab.Size=UDim2.fromOffset(104,44)
for _,o in ipairs(tab:GetChildren()) do
if o:IsA("TextLabel") and o.Position.X.Offset==44 then o.Position=UDim2.fromOffset(36,0);o.Size=UDim2.new(1,-40,1,0) end
end
end
indicator.Position=UDim2.fromOffset((tabIndex[activeTab]-1)*112+6,43);indicator.Size=UDim2.fromOffset(100,2)
uiPagePosition=UDim2.fromOffset(14,187)
for _,p in pairs(pages) do
p.Position=uiPagePosition;p.Size=UDim2.new(1,-28,1,-233)
if p:FindFirstChild("Heading") then p.Heading.Visible=view.Y>460 end
end
status.Position=UDim2.new(0,24,1,-34);status.Size=UDim2.new(1,-100,0,21);status.TextSize=9
mini.Position=UDim2.new(1,-160,0,8);mini.Size=UDim2.fromOffset(148,44)
touchAim.Position=UDim2.new(1,-100,1,-190)
if view.Y<460 then touchAim.Position=UDim2.new(1,-104,1,-156) end
gui:SetAttribute("LayoutWidth",w);gui:SetAttribute("LayoutHeight",h)
gui:SetAttribute("LayoutOrientation",view.X>view.Y and "Landscape" or "Portrait")
else
scale.Scale=math.clamp(math.min((view.X-32)/880,(view.Y-90)/680,C.UISize/100),.3,1.25)*reveal.Value
end
end
local function showDeviceWelcome()
gui:SetAttribute("StartupMessage",deviceName.." / controls ready")
local welcome=make("CanvasGroup",{Name="DeviceWelcome",AnchorPoint=Vector2.new(.5,.5),
Position=UDim2.fromScale(.5,.5),Size=UDim2.fromOffset(270,160),GroupTransparency=1,
BackgroundColor3=bg,BorderSizePixel=0,ZIndex=20},gui);round(welcome,16);outline(welcome,.35)
local introScale=make("UIScale",{Scale=.92},welcome)
animate(introScale,{Scale=1},.5,Enum.EasingStyle.Back)
make("ImageLabel",{Image=image,BackgroundTransparency=1,ImageTransparency=.7,
Size=UDim2.fromScale(1,1),ScaleType=Enum.ScaleType.Crop},welcome)
text(welcome,"N O V A",11,ink,UDim2.fromOffset(22,17),UDim2.fromOffset(226,20))
text(welcome,deviceName,36,ink,UDim2.fromOffset(22,46),UDim2.fromOffset(226,48)).Font=Enum.Font.GothamBold
text(welcome,mobile and "Touch controls ready" or "Keyboard + mouse ready",12,ink,
UDim2.fromOffset(22,109),UDim2.fromOffset(226,25))
local progress=make("Frame",{Name="LoadingLine",BackgroundColor3=ink,BorderSizePixel=0,
Position=UDim2.new(0,22,1,-12),Size=UDim2.new(0,0,0,2)},welcome)
animate(progress,{Size=UDim2.new(1,-44,0,2)},.8)
animate(welcome,{GroupTransparency=0},.28)
task.delay(math.max(.7,motionDuration(1.05)),function()
if not alive or not welcome.Parent then return end
animate(welcome,{GroupTransparency=1},.25)
task.delay(motionDuration(.3),function() if welcome.Parent then welcome:Destroy() end end)
end)
end
-- Property ownership restores only changes still owned by this script.
local Lighting=game:GetService("Lighting")
local owned={}
local function own(instance,property,value)
local ok,err=pcall(function()
local state=owned[instance]
if not state then state={};owned[instance]=state end
local current=instance[property]
local r=state[property]
if not r then r={original=current};state[property]=r
elseif r.last~=nil and current~=r.last then r.original=current end
if current~=value then instance[property]=value end
r.last=instance[property];r.used=true
end)
if not ok then gui:SetAttribute("WorldError",tostring(err)) end
end
local function releaseUnused(all)
for instance,state in pairs(owned) do
for property,r in pairs(state) do
if all or not r.used then
pcall(function() if instance[property]==r.last then instance[property]=r.original end end)
state[property]=nil
end
end
if next(state)==nil then owned[instance]=nil end
end
end
restoreWorld=function() releaseUnused(true) end
applyWorld=function()
for _,state in pairs(owned) do for _,r in pairs(state) do r.used=false end end
if C.FullBright then
own(Lighting,"Brightness",3)
own(Lighting,"Ambient",Color3.new(1,1,1))
own(Lighting,"OutdoorAmbient",Color3.new(1,1,1))
own(Lighting,"ExposureCompensation",.25)
elseif C.CustomLight then
own(Lighting,"Brightness",C.LightBrightness)
own(Lighting,"ExposureCompensation",C.LightExposure)
local level=C.AmbientLevel/100
own(Lighting,"Ambient",Color3.new(level,level,level))
own(Lighting,"OutdoorAmbient",Color3.new(level,level,level))
end
if C.FullBright or C.NoShadows then own(Lighting,"GlobalShadows",false) end
if C.TimeLock then own(Lighting,"ClockTime",C.DayTime%24) end
if C.NoFog then own(Lighting,"FogStart",0);own(Lighting,"FogEnd",1000000) end
local camera=workspace.CurrentCamera
if C.CameraOverride and camera then own(camera,"FieldOfView",C.CameraFOV) end
local effects={BloomEffect=C.NoBloom,BlurEffect=C.NoBlur,DepthOfFieldEffect=C.NoDOF,
SunRaysEffect=C.NoSunRays,ColorCorrectionEffect=C.NoColor}
if C.NoFog or C.NoBloom or C.NoBlur or C.NoDOF or C.NoSunRays or C.NoColor then
local containers={Lighting};if camera then table.insert(containers,camera) end
for _,container in ipairs(containers) do
for _,effect in ipairs(container:GetChildren()) do
if effect:IsA("Atmosphere") and C.NoFog then
own(effect,"Density",0);own(effect,"Haze",0);own(effect,"Glare",0)
elseif effects[effect.ClassName] then own(effect,"Enabled",false) end
end
end
end
travel.update(own)
extras.apply(own)
shooter.apply(own)
combat.update(own)
releaseUnused(false)
end
local hud={frames=0,elapsed=0,started=os.clock(),history={},layoutKey="",ping=nil}
hud.fps=button(gui,"FPS","",UDim2.new(),UDim2.fromOffset(224,108))
hud.mark=button(gui,"Watermark","",UDim2.new(),UDim2.fromOffset(254,72))
for _,panel in ipairs({hud.fps,hud.mark}) do
panel.BackgroundColor3=Color3.fromRGB(15,17,23);panel.ZIndex=8
make("UIScale",{Name="HUDScale",Scale=1},panel)
make("Frame",{Name="Accent",BackgroundColor3=ink,BorderSizePixel=0,
Position=UDim2.fromOffset(0,12),Size=UDim2.new(0,3,1,-24),ZIndex=9},panel)
end
hud.fpsTitle=text(hud.fps,"PERFORMANCE",9,muted,UDim2.fromOffset(14,8),UDim2.fromOffset(150,16))
hud.fpsValue=text(hud.fps,"--",26,ink,UDim2.fromOffset(14,24),UDim2.fromOffset(100,30));hud.fpsValue.Name="Value";hud.fpsValue.Font=Enum.Font.GothamBold
hud.fpsUnit=text(hud.fps,"FPS",10,muted,UDim2.new(1,-50,0,33),UDim2.fromOffset(35,18))
hud.fpsDetail=text(hud.fps,"-- ms/frame / -- ms ping",10,muted,UDim2.fromOffset(14,57),UDim2.new(1,-28,0,18));hud.fpsDetail.Name="Details"
hud.graph=make("Frame",{Name="Graph",BackgroundTransparency=1,Position=UDim2.fromOffset(14,80),Size=UDim2.new(1,-28,0,20)},hud.fps)
hud.bars={}
for i=1,24 do
hud.bars[i]=make("Frame",{Name="Sample"..i,BackgroundColor3=ink,BackgroundTransparency=.45,BorderSizePixel=0,
AnchorPoint=Vector2.new(0,1),Position=UDim2.new((i-1)/24,0,1,0),Size=UDim2.new(1/24,-2,0,2)},hud.graph)
round(hud.bars[i],2)
end
hud.logo=make("TextLabel",{Name="Logo",Text="N",Font=Enum.Font.GothamBold,TextSize=22,
TextColor3=ink,BackgroundColor3=Color3.fromRGB(35,39,49),BorderSizePixel=0,
Position=UDim2.fromOffset(13,12),Size=UDim2.fromOffset(34,34)},hud.mark);round(hud.logo,9)
hud.brand=text(hud.mark,"N O V A",14,ink,UDim2.fromOffset(58,10),UDim2.fromOffset(112,23));hud.brand.Name="Brand";hud.brand.Font=Enum.Font.GothamBold
hud.version=text(hud.mark,"v3.38",10,muted,UDim2.new(1,-60,0,13),UDim2.fromOffset(47,20));hud.version.Name="Version"
hud.markDetail=text(hud.mark,"",10,muted,UDim2.fromOffset(58,34),UDim2.new(1,-71,0,18));hud.markDetail.Name="Details"
for _,panel in ipairs({hud.fps,hud.mark}) do for _,child in ipairs(panel:GetDescendants()) do if child:IsA("GuiObject") then child.ZIndex=9 end end end
on(hud.fps.Activated,function() C.FPSDetails=not C.FPSDetails;refresh() end)
on(hud.mark.Activated,function() C.WatermarkDetails=not C.WatermarkDetails;refresh() end)
function hud.position(panel,corner,width,height,scaleValue,offset,view)
local right=corner:find("right",1,true)~=nil
local bottom=corner:find("Bottom",1,true)~=nil
local reserve=not bottom and (not right or mobile) and 60 or 0
panel.AnchorPoint=Vector2.new(right and 1 or 0,bottom and 1 or 0)
panel.Position=UDim2.new(right and 1 or 0,right and -16 or 16,bottom and 1 or 0,bottom and -16-offset or 16+reserve+offset)
panel.Size=UDim2.fromOffset(width,height);panel.HUDScale.Scale=scaleValue
end
function hud.layout(view)
local key=table.concat({view.X,view.Y,C.HUDScale,C.HUDOpacity,tostring(C.ShowFPS),tostring(C.Watermark),tostring(C.FPSDetails),tostring(C.FPSGraph),tostring(C.WatermarkDetails),C.FPSCorner,C.WatermarkCorner},"|")
if key==hud.layoutKey then return end;hud.layoutKey=key
local scaleValue=math.min(C.HUDScale/100,math.max(.5,(view.X-32)/254))
local fpsHeight=C.FPSDetails and (C.FPSGraph and 108 or 82) or 60
local markHeight=C.WatermarkDetails and 64 or 48
local stack=C.ShowFPS and C.Watermark and C.FPSCorner==C.WatermarkCorner
local fpsOffset=stack and markHeight*scaleValue+10 or 0
hud.position(hud.mark,C.WatermarkCorner,254,markHeight,scaleValue,0,view)
hud.position(hud.fps,C.FPSCorner,224,fpsHeight,scaleValue,fpsOffset,view)
hud.fps.Visible=C.ShowFPS;hud.mark.Visible=C.Watermark
hud.fpsDetail.Visible=C.FPSDetails;hud.graph.Visible=C.FPSDetails and C.FPSGraph
hud.markDetail.Visible=C.WatermarkDetails
hud.logo.Size=UDim2.fromOffset(C.WatermarkDetails and 34 or 28,C.WatermarkDetails and 34 or 28)
hud.logo.Position=UDim2.fromOffset(13,C.WatermarkDetails and 12 or 10)
for _,panel in ipairs({hud.fps,hud.mark}) do
panel:SetAttribute("RestAlpha",1-C.HUDOpacity/100);panel.BackgroundTransparency=1-C.HUDOpacity/100
end
end
function hud.sample(dt,view)
hud.layout(view)
hud.frames+=1;hud.elapsed+=dt
if hud.elapsed<.25 then return end
local value=math.floor(hud.frames/math.max(.001,hud.elapsed)+.5)
local ms=hud.elapsed/math.max(1,hud.frames)*1000
hud.frames=0;hud.elapsed=0
gui:SetAttribute("FPS",value);gui:SetAttribute("FrameTimeMs",ms)
hud.fpsValue.Text=tostring(value)
local color=value>=55 and Color3.fromRGB(105,231,177) or value>=30 and Color3.fromRGB(255,205,113) or Color3.fromRGB(255,119,137)
hud.fpsValue.TextColor3=color
table.insert(hud.history,value);if #hud.history>24 then table.remove(hud.history,1) end
local maximum=60
for _,n in ipairs(hud.history) do maximum=math.max(maximum,n) end
for i,bar in ipairs(hud.bars) do
local sample=hud.history[i-(24-#hud.history)]
bar.Size=UDim2.new(1/24,-2,0,sample and math.max(2,sample/maximum*20) or 2)
bar.BackgroundTransparency=sample and .2 or .8;bar.BackgroundColor3=color
end
hud.ping=nil
pcall(function()
local ping=game:GetService("Stats").Network.ServerStatsItem["Data Ping"]:GetValue()
if type(ping)=="number" and ping>=0 then hud.ping=ping end
end)
if hud.ping then gui:SetAttribute("HUDPingMs",hud.ping) else gui:SetAttribute("HUDPingMs",nil) end
hud.fpsDetail.Text=string.format("%.1f ms/frame / %s ms ping",ms,hud.ping and tostring(math.floor(hud.ping+.5)) or "--")
local elapsed=math.max(0,math.floor(os.clock()-hud.started))
hud.markDetail.Text=string.format("%s / %d players / %02d:%02d",deviceName,#Players:GetPlayers(),math.floor(elapsed/60),elapsed%60)
hud.logo.TextColor3=ink;hud.brand.TextColor3=ink;hud.version.TextColor3=muted
hud.fpsTitle.TextColor3=muted;hud.fpsUnit.TextColor3=muted;hud.fpsDetail.TextColor3=muted;hud.markDetail.TextColor3=muted
hud.fps.Accent.BackgroundColor3=color;hud.mark.Accent.BackgroundColor3=ink
end
local cross=make("Frame",{Name="Crosshair",BackgroundTransparency=1,Size=UDim2.fromOffset(0,0)},overlay)
local arms={}
for i=1,4 do arms[i]=make("Frame",{BorderSizePixel=0,BackgroundColor3=ink},cross) end
local centerDot=make("Frame",{BorderSizePixel=0,BackgroundColor3=ink,AnchorPoint=Vector2.new(.5,.5),
Size=UDim2.fromOffset(4,4)},cross);round(centerDot,2)
local worldTime=0
local function displayExtras(dt,camera)
worldTime+=dt
hud.sample(dt,camera.ViewportSize)
if worldTime>=.12 then worldTime=0;applyWorld() end
cross.Visible=C.Crosshair and focus and not menuOpen
local p=camera.ViewportSize/2-overlay.AbsolutePosition
cross.Position=UDim2.fromOffset(p.X,p.Y)
cross.Rotation=C.CrosshairStyle=="Cross" and 45 or 0
local length,gap=C.CrosshairSize,C.CrosshairGap
local col=palettes[C.Color]
for i,arm in ipairs(arms) do
arm.Visible=C.CrosshairStyle~="Dot";arm.BackgroundColor3=col
if i==1 then arm.Position=UDim2.fromOffset(-gap-length,-1);arm.Size=UDim2.fromOffset(length,2)
elseif i==2 then arm.Position=UDim2.fromOffset(gap,-1);arm.Size=UDim2.fromOffset(length,2)
elseif i==3 then arm.Position=UDim2.fromOffset(-1,-gap-length);arm.Size=UDim2.fromOffset(2,length)
else arm.Position=UDim2.fromOffset(-1,gap);arm.Size=UDim2.fromOffset(2,length) end
end
centerDot.Visible=C.CrosshairStyle=="Dot";centerDot.BackgroundColor3=col
end
local ray=RaycastParams.new(); ray.FilterType=Enum.RaycastFilterType.Exclude
local function remove(p)
local r=records[p]
if r then r.highlight:Destroy(); r.billboard:Destroy(); records[p]=nil end
end
local elapsed=math.huge
local roster=Players:GetPlayers()
local function trackPlayer(p)
on(p.CharacterAdded,function() remove(p);elapsed=math.huge end)
on(p.CharacterRemoving,function() remove(p);elapsed=math.huge end)
end
for _,p in ipairs(roster) do trackPlayer(p) end
on(Players.PlayerAdded,function(p) table.insert(roster,p);trackPlayer(p);elapsed=math.huge end)
on(Players.PlayerRemoving,function(p)
remove(p);local i=table.find(roster,p);if i then table.remove(roster,i) end
elapsed=math.huge
end)
local function setESP(instance,key,value)
if instance[key]~=value then instance[key]=value end
end
local function character(p)
local ch=p.Character
if not ch or not ch:IsDescendantOf(workspace) then return end
local h=ch:FindFirstChildOfClass("Humanoid")
local part=ch:FindFirstChild(C.Part) or ch:FindFirstChild("HumanoidRootPart") or ch:FindFirstChild("Head") or ch.PrimaryPart
if h and h.Health>0 and part and part:IsA("BasePart") then return ch,h,part end
end
local function eligible(p)
return p~=LP and (not C.Teams or LP.Neutral or p.Neutral or LP.Team==nil or p.Team~=LP.Team)
end
local function record(p,ch)
local r=records[p]; if r and r.character~=ch then remove(p); r=nil end
if r then return r end
r={character=ch}
r.highlight=make("Highlight",{Name="Player_"..p.UserId,Adornee=ch},world)
r.billboard=make("BillboardGui",{Name="Label_"..p.UserId,Size=UDim2.fromOffset(220,66),
StudsOffsetWorldSpace=Vector3.new(0,3,0),AlwaysOnTop=true,MaxDistance=C.Range},pg)
r.label=text(r.billboard,"",12,ink,UDim2.new(),UDim2.new(1,0,0,48))
r.label.TextXAlignment=Enum.TextXAlignment.Center; r.label.TextStrokeTransparency=.35
r.bar=make("Frame",{BackgroundColor3=Color3.fromRGB(43,48,62),BorderSizePixel=0,
Position=UDim2.fromOffset(50,54),Size=UDim2.fromOffset(120,4)},r.billboard); round(r.bar,2)
r.fill=make("Frame",{BorderSizePixel=0,BackgroundColor3=Color3.fromRGB(103,230,160),Size=UDim2.fromScale(1,1)},r.bar); round(r.fill,2)
records[p]=r; return r
end
local function cleanup()
if not alive then return end
alive=false;Run:UnbindFromRenderStep(binding);studio.destroy()
for _,connection in ipairs(cons)do pcall(function()connection:Disconnect()end)end
table.clear(cons)
C.Healing=false;healing.epoch+=1;healing.release()
C.Bot=false;bot.stop("Unloaded")
extras.destroy()
C.AutoClicker=false;C.InfiniteAmmo=false;C.AutoReload=false;utility.alive=false
alive=false; Run:UnbindFromRenderStep(binding)
C.Fly=false;C.WallShots=false;C.TriggerBot=false;C.AutoShoot=false;autofire.reset("Unloaded");cooldown.restore();flight.stop();combat.restore()
combat.clearBoxes();combat.displayFolder:Destroy()
for _,c in ipairs(cons) do c:Disconnect() end
for _,state in pairs(anims) do for _,tw in pairs(state) do tw:Cancel() end end
for p in pairs(records) do remove(p) end
world:Destroy()
if travel.marker then travel.marker:Destroy();travel.marker=nil end
if restoreWorld then restoreWorld() end
if not mobile then UIS.MouseBehavior=lastMouse; UIS.MouseIconEnabled=lastIcon end
end
on(gui.Destroying,cleanup)
local espVisible,espAvailable,lastCount,lastTotal=0,0,0,0
local aim={}
function aim.point(part)
local point=part.Position
if C.AimPrediction then
local velocity=part.AssemblyLinearVelocity
if velocity.Magnitude<200 then point+=velocity*(C.AimLead/1000) end
end
return point
end
function aim.candidate(ch,primary,cam,origin,ray)
local candidates={primary}
if C.AimFallback then
for _,name in ipairs({"Head","UpperTorso","Torso","LowerTorso"}) do
local part=ch:FindFirstChild(name)
if part and part:IsA("BasePart") and part~=primary then table.insert(candidates,part) end
end
end
for _,part in ipairs(candidates) do
local point=aim.point(part)
local projected,onScreen=cam:WorldToViewportPoint(point)
local pixels=(Vector2.new(projected.X,projected.Y)-origin).Magnitude
if onScreen and projected.Z>0 and pixels<C.FOV then
local hit=C.Visibility and not C.AimThroughWalls and workspace:Raycast(cam.CFrame.Position,point-cam.CFrame.Position,ray)
if not hit or hit.Instance:IsDescendantOf(ch) then return part,point,pixels end
end
end
end
function aim.score(p,h,distance,pixels)
local score=pixels/math.max(1,C.FOV)
if C.AimPriority=="Nearest" then score=distance/math.max(1,C.Range)
elseif C.AimPriority=="Lowest health" then score=h.Health/math.max(1,h.MaxHealth)+pixels/math.max(1,C.FOV)*.01 end
if C.Sticky and selected==p then score*=1-C.AimRetention/100 end
return score
end
function aim.follow(current,point,dt)
if (point-current.Position).Magnitude<.001 then return current end
local goal=CFrame.lookAt(current.Position,point)
local alpha=C.AimResponse=="Instant" and 1 or 1-math.exp(-C.Speed*math.clamp(dt,0,.1))
return current:Lerp(goal,alpha)
end
local function frame(dt)
local cam=workspace.CurrentCamera; if not cam then return end
adaptiveLayout(TEST_VIEWPORT or (mobile and overlay.AbsoluteSize or cam.ViewportSize))
studio.layout(cam.ViewportSize)
if C.EditorOpen and not mobile and not free then setFree(true)end
ui.layoutSearch()
animateChrome(dt)
displayExtras(dt,cam)
flight.step(dt,cam)
extras.step(dt,cam)
if not mobile then
if free then UIS.MouseBehavior=Enum.MouseBehavior.Default;UIS.MouseIconEnabled=true
else UIS.MouseBehavior=Enum.MouseBehavior.LockCenter end
end
local origin=not mobile and C.Origin=="Mouse" and UIS:GetMouseLocation() or cam.ViewportSize/2
ring.Position=UDim2.fromOffset(origin.X-overlay.AbsolutePosition.X,origin.Y-overlay.AbsolutePosition.Y); ring.Size=UDim2.fromOffset(C.FOV*2,C.FOV*2)
ring.Visible=C.Circle and focus and (not C.HideRingMenu or not menuOpen); ringStroke.Color=palettes[C.Color]
ray.FilterDescendantsInstances=LP.Character and {LP.Character,world} or {world}
local localCh=LP.Character; local ownHum=localCh and localCh:FindFirstChildOfClass("Humanoid")
local ownRoot=localCh and localCh:FindFirstChild("HumanoidRootPart")
local localPosition=ownRoot and ownRoot.Position or cam.CFrame.Position
local active=C.Aim and not C.EditorOpen and not C.Healing and not C.Bot and (mobile and not menuOpen or not mobile and not free) and focus and not UIS:GetFocusedTextBox() and ownHum and ownHum.Health>0
and (C.Mode=="Always" or ((C.Mode=="Toggle RMB" or C.Mode=="Toggle AIM") and latch)
or (mobile and C.Mode=="Hold AIM" and touchHolding)
or (not mobile and C.Mode=="Hold RMB" and UIS:IsMouseButtonPressed(Enum.UserInputType.MouseButton2)))
elapsed+=dt
local update=elapsed>=C.ESPInterval/1000; if update then elapsed=0;espVisible=0;espAvailable=0 end
local best,chosen,chosenPart,chosenPoint=math.huge,nil,nil,nil
local count,total=lastCount,lastTotal
if update or active then
count,total=0,0
for _,p in ipairs(roster) do
if p~=LP then total+=1 end
local ch,h,part=character(p)
local valid=eligible(p) and ch~=nil
local distance=valid and (part.Position-localPosition).Magnitude or math.huge
valid=valid and distance<=C.Range
if valid then count+=1 end
if update then
local espValid=p~=LP and ch~=nil and (C.ESPAll or eligible(p))
local espDistance=ch and (part.Position-localPosition).Magnitude or math.huge
if p~=LP and ch then espAvailable+=1 end
espValid=espValid and (C.ESPUnlimited or espDistance<=C.Range)
if espValid and C.ESP then
espVisible+=1
local r=record(p,ch); local col=palettes[C.Color]
setESP(r.highlight,"Enabled",true)
setESP(r.highlight,"FillColor",col);setESP(r.highlight,"OutlineColor",col)
setESP(r.highlight,"FillTransparency",C.Opacity/100);setESP(r.highlight,"OutlineTransparency",C.OutlineFade/100)
setESP(r.highlight,"DepthMode",C.Through and Enum.HighlightDepthMode.AlwaysOnTop or Enum.HighlightDepthMode.Occluded)
setESP(r.billboard,"Adornee",ch:FindFirstChild("Head") or part)
setESP(r.billboard,"AlwaysOnTop",C.Through)
setESP(r.billboard,"MaxDistance",C.ESPUnlimited and 0 or math.min(C.Range,C.LabelRange))
setESP(r.billboard,"StudsOffsetWorldSpace",Vector3.new(0,C.LabelHeight,0));setESP(r.label,"TextSize",C.LabelSize)
setESP(r.billboard,"Enabled",C.Names or C.Health or C.Distance)
local lines={}
if C.Names then table.insert(lines,p.DisplayName==p.Name and p.Name or p.DisplayName.." (@"..p.Name..")") end
if C.Distance then table.insert(lines,math.floor(espDistance).." studs") end
if C.Health then table.insert(lines,math.ceil(h.Health).." / "..math.ceil(h.MaxHealth).." HP") end
setESP(r.label,"Text",table.concat(lines,"\n"));setESP(r.label,"TextColor3",ink);setESP(r.bar,"Visible",C.Health)
local ratio=math.clamp(h.Health/math.max(1,h.MaxHealth),0,1)
setESP(r.fill,"Size",UDim2.fromScale(ratio,1))
setESP(r.fill,"BackgroundColor3",Color3.fromRGB(255,100,120):Lerp(Color3.fromRGB(103,230,160),ratio))
else remove(p) end
end
if active and valid then
local target,point,pixels=aim.candidate(ch,part,cam,origin,ray)
if target then
local score=aim.score(p,h,distance,pixels)
if score<best then best=score;chosen=p;chosenPart=target;chosenPoint=point end
end
end
end
lastCount,lastTotal=count,total
end
if update then
gui:SetAttribute("ESPVisiblePlayers",espVisible);gui:SetAttribute("ESPAvailablePlayers",espAvailable)
gui:SetAttribute("ESPRefreshMs",C.ESPInterval)
end
selected=chosen
if chosenPoint then
cam.CFrame=aim.follow(cam.CFrame,chosenPoint,dt)
ringStroke.Color=Color3.fromRGB(103,230,160)
end
local utilityOk,utilityErr=pcall(utility.step)
if not utilityOk then gui:SetAttribute("UtilityError",tostring(utilityErr));utility.status("Utility error; see diagnostic attribute.") end
if not C.Bot then autofire.step(cam,chosen,chosenPoint) else autofire.reset("Bot owns firing") end
local botOk,botErr=xpcall(function()bot.step(dt,cam)end,traceError)
if not botOk then gui:SetAttribute("LastBotError",tostring(botErr));C.Bot=false;bot.stop("Bot error: "..tostring(botErr):sub(1,240));refresh() end
gui:SetAttribute("LastFrame",os.clock())
gui:SetAttribute("EligiblePlayers",count); gui:SetAttribute("OtherPlayers",total)
gui:SetAttribute("Tracking",chosen and chosen.Name or "")
gui:SetAttribute("TrackingPart",chosenPart and chosenPart.Name or "")
if update then
local mode=mobile and (menuOpen and "Menu open / aim paused" or not C.Aim and "Aim disabled / open MENU" or chosen and "Tracking "..chosen.DisplayName or "Ready / "..C.Mode) or (free and "Cursor free - press U or minimize to aim" or not C.Aim and "Aim disabled" or chosen and ("Tracking "..chosen.DisplayName) or ("Aim ready - "..C.Mode))
status.Text=mode.." / "..count.." eligible of "..total.." players"
end
end
for key,value in pairs(C)do if type(value)=="boolean"then C[key]=false end end
C.ViewMode="Game default"
setFree(true)
gui:SetAttribute("Version","3.38")
gui:SetAttribute("CompatibilityProfile","Portable filesystem and custom-image fallbacks")
if type(NOVA_ASSET_STATUS)=="table" then
gui:SetAttribute("AssetFilesReady",NOVA_ASSET_STATUS.ready)
gui:SetAttribute("AssetFilesFailed",NOVA_ASSET_STATUS.failed)
end
if type(identifyexecutor)=="function" then
pcall(function()gui:SetAttribute("Executor",tostring(identifyexecutor()))end)
end
gui:SetAttribute("DeviceMode",deviceName)
gui:SetAttribute("TouchHolding",false)
gui:SetAttribute("Theme","Liquid Chrome")
selectTab("Game")
showMenu(true)
showDeviceWelcome()
Run:BindToRenderStep(binding,Enum.RenderPriority.Last.Value+100,function(dt)
if not alive then return end
local ok,err=xpcall(function() frame(dt) end,traceError)
if not ok then
gui:SetAttribute("LastError",tostring(err)); status.Text="Runtime error - see console"
warn("NOVA: "..tostring(err)); Run:UnbindFromRenderStep(binding)
end
end)
return "NOVA SHOOTER / "..deviceName.." loaded."