more improvements (2)
This commit is contained in:
1 parent
591196a61d
commit
d6eed813d5
12 files changed
+2896
-355
No files matched your search
@@ -1,6 +1,10 @@
|
||||
# Kitty Hub
|
||||
<p align="center">
|
||||
<img src="logo.png" alt="Kitty Hub" width="170">
|
||||
</p>
|
||||
|
||||
Messy MM2 script. Many features are broken, so see what works for you.
|
||||
<h1 align="center">Kitty Hub</h1>
|
||||
|
||||
<p align="center">Messy MM2 script. Many features are broken, so see what works for you.</p>
|
||||
|
||||
|
||||
## Loadstring
|
||||
|
||||
@@ -20,13 +20,14 @@ do
|
||||
Key = "C",
|
||||
Method = "Mouse", -- Remote | Mouse
|
||||
CameraSnap = true, -- Mouse method: face the target first
|
||||
MouseSpeed = 0.4, -- 1 snaps, lower eases the turn and walk
|
||||
MouseSpeed = 0.6, -- camera turn only; the cursor always snaps
|
||||
Prediction = 2.8, -- studs of lead per unit of velocity
|
||||
PingComp = true, -- scale lead by measured ping
|
||||
FireRate = 0.10, -- seconds between shots
|
||||
KeepEquipped = true, -- re-draw the gun if it gets stowed
|
||||
SilentAim = false, -- redirect your own manual shots
|
||||
SilentMode = "Auto", -- Auto | Hook | Takeover | Click
|
||||
DryRun = false, -- aim and report, never shoot
|
||||
AimAtHead = false, -- Head instead of HumanoidRootPart
|
||||
NotifyShot = false,
|
||||
},
|
||||
|
||||
+107
-18
@@ -55,12 +55,28 @@ do
|
||||
end
|
||||
|
||||
-- --------------------------------------------------------- role tracking
|
||||
local function applyData(data)
|
||||
if typeof(data) ~= "table" then return end
|
||||
Game.Data = data
|
||||
-- Our own role is latched for the round. MM2 empties our hands the moment
|
||||
-- the knife is thrown and the role table can arrive late, in pieces, or
|
||||
-- still holding last round's answer — one unlucky read must never turn the
|
||||
-- murderer back into an innocent.
|
||||
local myLatch = nil
|
||||
|
||||
local function latch(role)
|
||||
if role == "Murderer" or role == "Sheriff" or role == "Hero" then
|
||||
myLatch = role
|
||||
end
|
||||
end
|
||||
|
||||
local function clearRoles()
|
||||
Game.Data = {}
|
||||
Game.Murderer, Game.Sheriff, Game.Hero = nil, nil, nil
|
||||
myLatch = nil
|
||||
end
|
||||
Game.clearRoles = clearRoles
|
||||
|
||||
local function recompute()
|
||||
local murderer, sheriff, hero
|
||||
for name, entry in pairs(data) do
|
||||
for name, entry in pairs(Game.Data) do
|
||||
if typeof(entry) == "table" then
|
||||
local role = entry.Role
|
||||
if role == "Murderer" then murderer = name
|
||||
@@ -74,10 +90,44 @@ do
|
||||
or (hero ~= Game.Hero)
|
||||
|
||||
Game.Murderer, Game.Sheriff, Game.Hero = murderer, sheriff, hero
|
||||
|
||||
local me = LocalPlayer.Name
|
||||
if murderer == me then latch("Murderer")
|
||||
elseif sheriff == me then latch("Sheriff")
|
||||
elseif hero == me then latch("Hero") end
|
||||
|
||||
if changed then emit("RoleChange", murderer, sheriff, hero) end
|
||||
end
|
||||
|
||||
-- Only a payload that actually carries roles may replace what we have; a
|
||||
-- partial push used to wipe the table and leave us knowing nothing.
|
||||
local function applyData(data)
|
||||
if typeof(data) ~= "table" then return end
|
||||
|
||||
local fresh, roles = {}, 0
|
||||
for name, entry in pairs(data) do
|
||||
if typeof(name) == "string" and typeof(entry) == "table" then
|
||||
fresh[name] = entry
|
||||
if typeof(entry.Role) == "string" then roles = roles + 1 end
|
||||
end
|
||||
end
|
||||
if roles == 0 then return end
|
||||
|
||||
Game.Data = fresh
|
||||
recompute()
|
||||
end
|
||||
Game.applyData = applyData
|
||||
|
||||
-- Some builds push one player's entry instead of the whole table.
|
||||
local function applyOne(who, entry)
|
||||
local name = who
|
||||
if typeof(who) == "Instance" and who:IsA("Player") then name = who.Name end
|
||||
if typeof(name) ~= "string" or typeof(entry) ~= "table" then return end
|
||||
if typeof(entry.Role) ~= "string" then return end
|
||||
Game.Data[name] = entry
|
||||
recompute()
|
||||
end
|
||||
|
||||
function Game.refreshRoles()
|
||||
local remote = findRemote("GetPlayerData")
|
||||
if not remote then return false end
|
||||
@@ -94,17 +144,13 @@ do
|
||||
KH.spawn(function()
|
||||
local gameplay = findRemote("PlayerDataChanged")
|
||||
if gameplay and gameplay:IsA("RemoteEvent") then
|
||||
KH.track(gameplay.OnClientEvent:Connect(applyData))
|
||||
KH.track(gameplay.OnClientEvent:Connect(function(first, second)
|
||||
if typeof(first) == "table" then applyData(first) else applyOne(first, second) end
|
||||
end))
|
||||
end
|
||||
Game.refreshRoles()
|
||||
end)
|
||||
|
||||
-- Poll as a safety net: the push event is the fast path, but if it is ever
|
||||
-- renamed we still recover roles within a couple of seconds.
|
||||
KH.loop(2, function()
|
||||
if not Game.Murderer then Game.refreshRoles() end
|
||||
end)
|
||||
|
||||
-- ------------------------------------------------- tool-based fallback
|
||||
-- No remote needed, and the only way to spot a Hero the moment they pick
|
||||
-- the gun up. Cached briefly: ESP asks for every role every frame.
|
||||
@@ -143,10 +189,12 @@ do
|
||||
local role = entry and entry.Role or nil
|
||||
local held = cachedToolRole(player)
|
||||
|
||||
-- Only the murderer ever holds a knife, so that outranks the table —
|
||||
-- including a table left standing from the round before.
|
||||
if held == "Murderer" then return "Murderer" end
|
||||
|
||||
if role == nil or role == "Innocent" then
|
||||
if held == "Murderer" then
|
||||
role = "Murderer"
|
||||
elseif held == "Sheriff" then
|
||||
if held == "Sheriff" then
|
||||
-- An innocent holding a gun picked it up off a dead sheriff.
|
||||
role = (role == "Innocent") and "Hero" or "Sheriff"
|
||||
end
|
||||
@@ -169,12 +217,52 @@ do
|
||||
return U.isAliveChar(player)
|
||||
end
|
||||
|
||||
function Game.myRole() return Game.roleOf(LocalPlayer) end
|
||||
function Game.myRole()
|
||||
local role = Game.roleOf(LocalPlayer)
|
||||
latch(role)
|
||||
if role == "Innocent" and myLatch then return myLatch end
|
||||
return role
|
||||
end
|
||||
|
||||
function Game.amSheriff()
|
||||
local role = Game.myRole()
|
||||
return role == "Sheriff" or role == "Hero"
|
||||
end
|
||||
function Game.amMurderer() return Game.myRole() == "Murderer" end
|
||||
|
||||
-- Asked from every angle: a wrong "no" walks the murderer onto the gun.
|
||||
function Game.amMurderer()
|
||||
if myLatch == "Murderer" then return true end
|
||||
if Game.Murderer == LocalPlayer.Name then return true end
|
||||
if Game.knifeTool() then return true end
|
||||
return Game.myRole() == "Murderer"
|
||||
end
|
||||
|
||||
-- Lets callers tell "innocent" apart from "no idea yet".
|
||||
function Game.selfKnown()
|
||||
if myLatch then return true end
|
||||
local entry = Game.Data[LocalPlayer.Name]
|
||||
return typeof(entry) == "table" and typeof(entry.Role) == "string"
|
||||
end
|
||||
|
||||
-- Latch our role even when nothing asks: the knife is only ours briefly.
|
||||
KH.loop(0.5, function() Game.myRole() end)
|
||||
|
||||
-- Poll until we know who the murderer is *and* what we are, then keep
|
||||
-- re-asking slowly: a missed round boundary would otherwise leave last
|
||||
-- round's roles standing for the whole of this one.
|
||||
local polledAt = 0
|
||||
KH.loop(2, function()
|
||||
if Game.Murderer and Game.selfKnown() and os.clock() - polledAt < 10 then return end
|
||||
polledAt = os.clock()
|
||||
Game.refreshRoles()
|
||||
end)
|
||||
|
||||
-- A fresh body means a fresh round; stale roles are worse than none.
|
||||
KH.track(LocalPlayer.CharacterAdded:Connect(function()
|
||||
clearRoles()
|
||||
task.wait(1)
|
||||
Game.refreshRoles()
|
||||
end))
|
||||
|
||||
-- Resolve names to live Player objects, skipping the dead.
|
||||
local function playerByName(name, requireAlive)
|
||||
@@ -326,14 +414,15 @@ do
|
||||
if obj.Parent == workspace and obj.Name ~= "Lobby" and isMapModel(obj) then
|
||||
Game.Traps = {}
|
||||
Game.GunDrop = nil
|
||||
clearRoles()
|
||||
emit("RoundStart", obj)
|
||||
KH.detach(Game.refreshRoles)
|
||||
end
|
||||
end))
|
||||
|
||||
KH.track(workspace.ChildRemoved:Connect(function(obj)
|
||||
if obj.Name ~= "Lobby" and obj:FindFirstChild("CoinContainer") then
|
||||
Game.Data = {}
|
||||
Game.Murderer, Game.Sheriff, Game.Hero = nil, nil, nil
|
||||
clearRoles()
|
||||
Game.Traps = {}
|
||||
Game.GunDrop = nil
|
||||
emit("RoundEnd")
|
||||
|
||||
+4
-16
@@ -453,7 +453,6 @@ do
|
||||
entry.page.Visible = on
|
||||
tween(entry.button, 0.14, {BackgroundTransparency = on and 0.86 or 1})
|
||||
tween(entry.label, 0.14, {TextColor3 = on and C.Text or C.TextDim})
|
||||
tween(entry.icon, 0.14, {TextTransparency = on and 0 or 0.35})
|
||||
end
|
||||
indicator.Visible = true
|
||||
tween(indicator, 0.2, {
|
||||
@@ -462,7 +461,7 @@ do
|
||||
}, Enum.EasingStyle.Back)
|
||||
end
|
||||
|
||||
function UI.addTab(name, icon)
|
||||
function UI.addTab(name)
|
||||
tabOrder = tabOrder + 1
|
||||
local button = make("TextButton", {
|
||||
Name = name,
|
||||
@@ -478,25 +477,14 @@ do
|
||||
UI.corner(button, 7)
|
||||
UI.accented(button, "BackgroundColor3")
|
||||
|
||||
local iconLabel = make("TextLabel", {
|
||||
Text = icon or "•",
|
||||
Font = Enum.Font.GothamBold,
|
||||
TextSize = 13,
|
||||
TextColor3 = C.Text,
|
||||
TextTransparency = 0.35,
|
||||
BackgroundTransparency = 1,
|
||||
Position = UDim2.fromOffset(9, 0),
|
||||
Size = UDim2.fromOffset(20, 34),
|
||||
Parent = button,
|
||||
})
|
||||
local textLabel = make("TextLabel", {
|
||||
Text = name,
|
||||
Font = Enum.Font.GothamMedium,
|
||||
TextSize = 13,
|
||||
TextColor3 = C.TextDim,
|
||||
BackgroundTransparency = 1,
|
||||
Position = UDim2.fromOffset(32, 0),
|
||||
Size = UDim2.new(1, -38, 1, 0),
|
||||
Position = UDim2.fromOffset(15, 0),
|
||||
Size = UDim2.new(1, -21, 1, 0),
|
||||
TextXAlignment = Enum.TextXAlignment.Left,
|
||||
Parent = button,
|
||||
})
|
||||
@@ -518,7 +506,7 @@ do
|
||||
UI.list(page, 10)
|
||||
UI.pad(page, 0, 2, 16, 14, 14)
|
||||
|
||||
local tab = {name = name, button = button, page = page, label = textLabel, icon = iconLabel, sections = {}}
|
||||
local tab = {name = name, button = button, page = page, label = textLabel, sections = {}}
|
||||
tabs[name] = tab
|
||||
|
||||
button.MouseEnter:Connect(function()
|
||||
|
||||
+305
-105
@@ -46,8 +46,8 @@ do
|
||||
return (pos - centre).Magnitude
|
||||
end
|
||||
|
||||
function Combat.pickTarget()
|
||||
local mode = S.Aim.Target
|
||||
function Combat.pickTarget(mode)
|
||||
mode = mode or S.Aim.Target
|
||||
|
||||
if mode == "Murderer" then
|
||||
local murderer = Game.murdererPlayer()
|
||||
@@ -135,6 +135,7 @@ do
|
||||
do
|
||||
local GuiService = game:GetService("GuiService")
|
||||
local Players = KH.Services.Players
|
||||
local UIS = KH.Services.UserInputService
|
||||
|
||||
-- Plain globals; one the executor lacks reads back nil.
|
||||
local moveRel = type(mousemoverel) == "function" and mousemoverel or nil
|
||||
@@ -155,6 +156,12 @@ do
|
||||
|
||||
Mouse.CanMove = (moveRel ~= nil) or (moveAbs ~= nil) or (VIM ~= nil)
|
||||
|
||||
-- What a viewport pixel is worth to the cursor, and how long a frame of
|
||||
-- the walk really takes. Both are measured rather than assumed, and both
|
||||
-- are reported in the menu — a wrong one shows up there first.
|
||||
local gain, samples = 1, 0
|
||||
local stepTime = 1 / 60
|
||||
|
||||
function Mouse.support()
|
||||
if not Mouse.CanMove then return "none — this executor cannot move the cursor" end
|
||||
local mover = moveRel and "mousemoverel"
|
||||
@@ -164,7 +171,7 @@ do
|
||||
or click and "mouse1click"
|
||||
or VIM and "VirtualInputManager"
|
||||
or "Tool:Activate"
|
||||
return mover .. " + " .. clicker
|
||||
return ("%s + %s · gain %.2f · %d ms"):format(mover, clicker, gain, stepTime * 1000)
|
||||
end
|
||||
|
||||
local mouseObj
|
||||
@@ -199,11 +206,9 @@ do
|
||||
return raw + offset, mouseObj
|
||||
end
|
||||
|
||||
-- What a viewport pixel is worth to the cursor. A relative move is in OS
|
||||
-- pixels and the projection is in viewport pixels, and on a scaled
|
||||
-- display those are not the same unit — so rather than assume, watch
|
||||
-- A relative move is in OS pixels and the projection is in viewport
|
||||
-- pixels, and on a scaled display those are not the same unit — so watch
|
||||
-- what the last move actually achieved and correct the next one.
|
||||
local gain = 1
|
||||
local function learn(want, got)
|
||||
if not moveRel then return end
|
||||
if want.Magnitude < 8 or got.Magnitude < 2 then return end
|
||||
@@ -212,7 +217,23 @@ do
|
||||
-- that into the gain is how the aim runs away.
|
||||
local ratio = want.Magnitude / got.Magnitude
|
||||
if ratio < 0.4 or ratio > 2.5 then return end
|
||||
gain = U.clamp(gain * ratio, 0.5, 2)
|
||||
-- Take the first couple of samples whole, since the first press of
|
||||
-- a session has nothing better to go on, then ease: one noisy frame
|
||||
-- swinging the next move is the cursor wandering instead of walking.
|
||||
samples = samples + 1
|
||||
gain = U.clamp(gain * (1 + (ratio - 1) * (samples <= 2 and 1 or 0.25)), 0.5, 2)
|
||||
end
|
||||
|
||||
local function recalibrate()
|
||||
gain, samples = 1, 0
|
||||
end
|
||||
|
||||
-- The cursor's reported position only stops responding once it has left
|
||||
-- the Roblox window, and it can only leave through an edge.
|
||||
local function atBorder(point)
|
||||
local view = KH.camera().ViewportSize
|
||||
return point.X <= 8 or point.Y <= 8
|
||||
or point.X >= view.X - 8 or point.Y >= view.Y - 8
|
||||
end
|
||||
|
||||
-- Drag the cursor back inside the window. Once it is out there — put
|
||||
@@ -293,18 +314,37 @@ do
|
||||
end
|
||||
|
||||
local TOLERANCE = 4 -- pixel floor for "close enough"
|
||||
local MAX_STEPS = 16
|
||||
local LEAD = 0.7 -- share of a frame's drift to aim ahead by
|
||||
local NEAR_STUDS = 4.5 -- how far off them a landed ray may stop
|
||||
local MAX_STEPS = 40
|
||||
|
||||
-- Where to point. Not Combat.aimPoint: prediction leads the target for
|
||||
-- the remote route's flight and ping, and a client raycast has neither,
|
||||
-- so the lead only walks the ray off the body — hardest on a falling
|
||||
-- target, whose damped -Y velocity drags the aim metres underneath them.
|
||||
local function livePoint(part)
|
||||
return part.Position
|
||||
-- Every lead below is counted in frames of the walk, so a 30 fps client
|
||||
-- leads twice as far as a 144 fps one.
|
||||
local function noteStep(dt)
|
||||
if dt > 0 and dt < 0.2 then stepTime = stepTime + (dt - stepTime) * 0.2 end
|
||||
end
|
||||
|
||||
-- Where the target will be in `lead` seconds. Nothing here has a
|
||||
-- projectile to lead, but the cursor lags a frame behind the move that
|
||||
-- put it there, the click lags a frame behind that, and the server
|
||||
-- resolves the shot a ping later still — a running target crosses most
|
||||
-- of their own body in that. Straight-line is enough: over a couple of
|
||||
-- frames gravity moves a jumping target a fraction of a stud.
|
||||
local function livePoint(part, lead)
|
||||
if not lead or lead <= 0 then return part.Position end
|
||||
local ok, velocity = pcall(function() return part.AssemblyLinearVelocity end)
|
||||
if not ok or typeof(velocity) ~= "Vector3" then return part.Position end
|
||||
return part.Position + velocity * lead
|
||||
end
|
||||
Mouse.livePoint = livePoint
|
||||
|
||||
-- Where the camera should be pointing for the shot to land. The lock
|
||||
-- reads this too, so the turn and the shot never disagree about where
|
||||
-- the target is going to be.
|
||||
Mouse.Lead = 0
|
||||
function Mouse.aimPoint(part)
|
||||
return livePoint(part, Mouse.Lead)
|
||||
end
|
||||
|
||||
-- Where the target sits on screen right now, for the camera lock.
|
||||
function Mouse.screenOf(part)
|
||||
return project(livePoint(part))
|
||||
@@ -323,108 +363,197 @@ do
|
||||
|
||||
-- A press projects before the camera lock has had a frame to run, so a
|
||||
-- target who is off screen this instant may simply not have been turned
|
||||
-- to yet. Give the lock a few frames before writing them off.
|
||||
-- to yet. Give the lock time to bring them in, and no more than that:
|
||||
-- the walk below is happy to chase a view that is still moving.
|
||||
local function waitVisible(part)
|
||||
local speed = U.clamp(S.Aim.MouseSpeed or 1, 0.1, 1)
|
||||
for _ = 1, math.clamp(math.ceil(6 / speed), 6, 30) do
|
||||
local _, onScreen = project(livePoint(part))
|
||||
local deadline = os.clock() + U.clamp(0.2 / speed, 0.2, 0.7)
|
||||
repeat
|
||||
local _, onScreen = project(part.Position)
|
||||
if onScreen then return true end
|
||||
if not S.Aim.CameraSnap then return false end
|
||||
task.wait()
|
||||
end
|
||||
until os.clock() >= deadline
|
||||
return false
|
||||
end
|
||||
|
||||
-- Walks the cursor onto the target and says whether it got there. Not
|
||||
-- one jump: a relative move only lands next frame, and the target keeps
|
||||
-- moving while we close on it.
|
||||
local function pointAt(char, part)
|
||||
if not waitVisible(part) then return false, "off screen" end
|
||||
local speed = U.clamp(S.Aim.MouseSpeed or 1, 0.1, 1)
|
||||
local steps = math.clamp(math.ceil(1 / speed), 1, MAX_STEPS)
|
||||
local lastFrom, lastWant, lastPoint
|
||||
local lastGap, worse, stuck = nil, 0, 0
|
||||
-- First person and shift lock pin the cursor to the middle of the
|
||||
-- screen, so there is no cursor to walk: the crosshair *is* the camera
|
||||
-- and aiming is turning. This is the more exact of the two paths — no
|
||||
-- display scale to learn, no readback to wait for, one rotation — but it
|
||||
-- is only available when the lock is allowed to take the camera.
|
||||
local function pointCamera(char, part)
|
||||
if not S.Aim.CameraSnap then
|
||||
return false, "cursor is locked — switch on Turn Camera to aim in first person"
|
||||
end
|
||||
|
||||
for step = 1, MAX_STEPS do
|
||||
Mouse.Lead = stepTime + (S.Aim.PingComp and U.clamp(U.ping() / 3000, 0, 0.06) or 0)
|
||||
Mouse.Precise = true
|
||||
|
||||
local budget = os.clock() + 0.3
|
||||
local reached, why = false, "could not turn onto them"
|
||||
|
||||
while true do
|
||||
if not (char.Parent and part.Parent) then
|
||||
why = "target gone"
|
||||
break
|
||||
end
|
||||
|
||||
-- The lock does the turning, on its own bind after Roblox's
|
||||
-- camera module. Writing the camera from here as well would put
|
||||
-- two authors on it in the same frame.
|
||||
task.wait()
|
||||
|
||||
local point, onScreen = project(Mouse.aimPoint(part))
|
||||
if onScreen then
|
||||
local view = KH.camera().ViewportSize
|
||||
local centre = Vector2.new(view.X / 2, view.Y / 2)
|
||||
local hit = select(2, cursor()).Target
|
||||
local onBody = hit and hit:IsDescendantOf(char)
|
||||
|
||||
-- The cursor sits dead centre, so the distance from the
|
||||
-- centre to them is the whole aiming error.
|
||||
if onBody or (point - centre).Magnitude <= bodyRadius(part, point) * 0.75 then
|
||||
local blocker = not onBody and hit and hit:FindFirstAncestorOfClass("Model")
|
||||
local owner = blocker and Players:GetPlayerFromCharacter(blocker)
|
||||
if owner and owner ~= LocalPlayer then
|
||||
why = "holding fire — " .. owner.DisplayName .. " is in the line"
|
||||
else
|
||||
reached, why = true, hit and ("through " .. hit.Name) or "on target"
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if os.clock() > budget then break end
|
||||
end
|
||||
|
||||
Mouse.Precise = false
|
||||
Mouse.Lead = 0
|
||||
return reached, why
|
||||
end
|
||||
|
||||
-- Puts the cursor on the target and says whether it got there.
|
||||
--
|
||||
-- Nobody else can see your cursor — the camera turn is the only part of
|
||||
-- this anyone else witnesses — so there is nothing to be gained by
|
||||
-- easing it across the screen. It goes the whole way in one move, then
|
||||
-- spends the frames after that correcting for what the move actually
|
||||
-- achieved. That is both the fastest way there and the most exact.
|
||||
local function pointAt(char, part)
|
||||
-- No cursor to place: turn instead.
|
||||
if UIS.MouseBehavior ~= Enum.MouseBehavior.Default then
|
||||
return pointCamera(char, part)
|
||||
end
|
||||
if not Mouse.CanMove then return false, "no mouse control" end
|
||||
if not waitVisible(part) then return false, "off screen" end
|
||||
|
||||
local budget = os.clock() + 0.3
|
||||
-- The click lands a frame after the cursor does, and MM2 casts its
|
||||
-- own ray then rather than now.
|
||||
local pingLead = S.Aim.PingComp and U.clamp(U.ping() / 3000, 0, 0.06) or 0
|
||||
local lastFrom, lastWant, stuck = nil, nil, 0
|
||||
local tick = os.clock()
|
||||
local grazed = false
|
||||
|
||||
for _ = 1, MAX_STEPS do
|
||||
if not (char.Parent and part.Parent) then return false, "target gone" end
|
||||
|
||||
local mark = os.clock()
|
||||
if lastWant then noteStep(mark - tick) end
|
||||
tick = mark
|
||||
|
||||
local here, m = cursor()
|
||||
|
||||
-- Asked it to move and it did not. That means the cursor is
|
||||
-- outside the Roblox window, where its reported position stops
|
||||
-- changing — so every later move would be computed from a
|
||||
-- position that is no longer real. Sweep it back in, throw away
|
||||
-- the calibration that put it there, and start the walk over.
|
||||
local recovering = false
|
||||
if lastWant and lastWant.Magnitude >= 8 and (here - lastFrom).Magnitude < 1 then
|
||||
stuck = stuck + 1
|
||||
if stuck >= 2 then
|
||||
stuck, gain = 0, 1
|
||||
lastFrom, lastWant, lastPoint, lastGap = nil, nil, nil, nil
|
||||
if not sweepHome(here) then return false, "cursor is off the window" end
|
||||
recovering = true
|
||||
-- The last move has not shown up yet. Issuing another on top of
|
||||
-- it is how the cursor overshoots and has to come back — wait
|
||||
-- for it to land instead. Against an edge it means something
|
||||
-- else: the cursor is outside the window, where its reported
|
||||
-- position stops changing at all, and only a sweep inwards gets
|
||||
-- it back.
|
||||
if lastWant and lastWant.Magnitude >= 4 and (here - lastFrom).Magnitude < 1 then
|
||||
if atBorder(here) then
|
||||
stuck = stuck + 1
|
||||
if stuck >= 2 then
|
||||
stuck = 0
|
||||
recalibrate()
|
||||
lastFrom, lastWant = nil, nil
|
||||
if not sweepHome(here) then return false, "cursor is off the window" end
|
||||
end
|
||||
end
|
||||
else
|
||||
stuck = 0
|
||||
end
|
||||
|
||||
if recovering then
|
||||
task.wait()
|
||||
else
|
||||
-- The camera belongs to the lock below; two writers a frame
|
||||
-- is how the cursor ends up chasing a point that moves.
|
||||
local point, onScreen = project(livePoint(part))
|
||||
stuck = 0
|
||||
|
||||
local now, onScreen = project(part.Position)
|
||||
if not onScreen then return false, "off screen" end
|
||||
|
||||
if lastWant then learn(lastWant, here - lastFrom) end
|
||||
|
||||
-- Walking away from the target three steps running means
|
||||
-- the calibration is wrong rather than the aim. Drop it and
|
||||
-- start over instead of chasing the cursor round the screen.
|
||||
local gap = (point - here).Magnitude
|
||||
if lastGap and gap > lastGap + 2 then
|
||||
worse = worse + 1
|
||||
if worse >= 3 then
|
||||
gain = 1
|
||||
return false, "cursor ran away — recalibrated"
|
||||
end
|
||||
else
|
||||
worse = 0
|
||||
-- Two questions, and for anyone moving they have different
|
||||
-- answers. Where must the ray land? Where they will be when
|
||||
-- the click is processed, a frame from now. Where must the
|
||||
-- cursor be sent? Where they will be once *this* move has
|
||||
-- landed, a frame later again. Never past their body edge
|
||||
-- either way: MM2 shoots wherever the cursor's ray stops, so
|
||||
-- a lead that overshoots them sends the wall behind instead.
|
||||
local radius = bodyRadius(part, now)
|
||||
local function ahead(seconds)
|
||||
local point, ok = project(livePoint(part, seconds))
|
||||
if not ok then return now end
|
||||
local drift = point - now
|
||||
local cap = radius * 0.8
|
||||
if drift.Magnitude > cap then drift = drift.Unit * cap end
|
||||
return now + drift
|
||||
end
|
||||
lastGap = gap
|
||||
|
||||
-- Being on their body is the test that matters. The pixel
|
||||
-- distance is the fallback for when something in front of
|
||||
-- them owns the cursor's ray.
|
||||
local hitPoint = ahead(stepTime + pingLead)
|
||||
local sendTo = ahead(stepTime * 2 + pingLead)
|
||||
-- Against where the shot has to land, not where the next
|
||||
-- move is going: the cursor is already a frame ahead, and
|
||||
-- measuring it against the frame after that left a running
|
||||
-- target permanently one step out of reach.
|
||||
local gap = (hitPoint - here).Magnitude
|
||||
local spent = os.clock() >= budget
|
||||
|
||||
-- The ray hitting them proves where they were a frame ago,
|
||||
-- which is the whole answer for someone standing still and
|
||||
-- worth nothing against someone crossing.
|
||||
local hit = m.Target
|
||||
if hit and hit:IsDescendantOf(char) then return true, "on target" end
|
||||
if gap <= bodyRadius(part, point) then
|
||||
local onBody = hit and hit:IsDescendantOf(char)
|
||||
local settled = (hitPoint - now).Magnitude <= radius * 0.3
|
||||
local close = gap <= math.max(TOLERANCE, radius * 0.7)
|
||||
or (spent and gap <= radius)
|
||||
|
||||
-- Pixels lie. A cursor within a body width of their centre
|
||||
-- can still be a ray that slips past them into the scenery
|
||||
-- twenty studs behind, and MM2 sends wherever the ray
|
||||
-- stops, so that is what has to be near them -- in studs.
|
||||
local lands = onBody and settled
|
||||
if not lands and close then
|
||||
local reach, at = pcall(function() return m.Hit.Position end)
|
||||
lands = reach
|
||||
and (at - livePoint(part, stepTime)).Magnitude <= NEAR_STUDS
|
||||
if not lands then grazed = true end
|
||||
end
|
||||
|
||||
if lands then
|
||||
-- MM2 shoots where the cursor's ray stops. A wall costs
|
||||
-- a wasted shot, but another player standing in the line
|
||||
-- costs the round: a sheriff who shoots an innocent dies
|
||||
-- for it. Hold fire and let the next press try again.
|
||||
local blocker = hit and hit:FindFirstAncestorOfClass("Model")
|
||||
local blocker = not onBody and hit and hit:FindFirstAncestorOfClass("Model")
|
||||
local owner = blocker and Players:GetPlayerFromCharacter(blocker)
|
||||
if owner and owner ~= LocalPlayer then
|
||||
return false, "holding fire — " .. owner.DisplayName .. " is in the line"
|
||||
end
|
||||
return true, hit and ("through " .. hit.Name) or "on target"
|
||||
end
|
||||
if spent then break end
|
||||
|
||||
-- Aim where they will be once this move lands, not where
|
||||
-- they were when it was projected: without this the cursor
|
||||
-- trails a running target forever. Short of a full frame,
|
||||
-- though — while the camera is easing the drift is slowing
|
||||
-- down, and leading it in full overshoots and comes back.
|
||||
local aim = lastPoint and (point + (point - lastPoint) * LEAD) or point
|
||||
lastPoint = point
|
||||
|
||||
-- A fixed fraction of the gap never arrives; a share of the
|
||||
-- steps left arrives exactly on the last one.
|
||||
local left = math.max(1, steps - step + 1)
|
||||
local dest = clampToView(here + (aim - here) / left)
|
||||
-- Learn against what was actually asked for, which is the
|
||||
-- clamped move, not the one we would have liked to make.
|
||||
-- The whole way, every time. What the move does not achieve
|
||||
-- is measured next frame and taken off the one after.
|
||||
local dest = clampToView(sendTo)
|
||||
lastFrom, lastWant = here, dest - here
|
||||
if not moveTo(here, dest) then
|
||||
return false, "no mouse control"
|
||||
@@ -432,7 +561,13 @@ do
|
||||
task.wait()
|
||||
end
|
||||
end
|
||||
gain = 1
|
||||
-- On them by the pixels every time and never by the ray: they are
|
||||
-- behind something, and the shot would go into whatever that is.
|
||||
if grazed then return false, "the shot would land behind them" end
|
||||
|
||||
-- Never got there: the scale it is moving by is the thing most
|
||||
-- likely wrong, so the next press starts from a clean one.
|
||||
recalibrate()
|
||||
return false, "could not reach"
|
||||
end
|
||||
|
||||
@@ -446,7 +581,11 @@ do
|
||||
-- would otherwise have a dozen of them fighting over the cursor.
|
||||
function Mouse.fire(player, char, part, force)
|
||||
if busy then return false, "aiming" end
|
||||
if not Mouse.CanMove then return false, "no mouse control" end
|
||||
-- A locked cursor is aimed by turning, which needs no mouse mover
|
||||
-- at all — only something to click with.
|
||||
if UIS.MouseBehavior == Enum.MouseBehavior.Default and not Mouse.CanMove then
|
||||
return false, "no mouse control"
|
||||
end
|
||||
|
||||
local now = os.clock()
|
||||
if not force and now - lastShot < S.Aim.FireRate then return false, "cooldown" end
|
||||
@@ -455,30 +594,60 @@ do
|
||||
activePart = part
|
||||
|
||||
local function sequence()
|
||||
local dry = S.Aim.DryRun
|
||||
|
||||
-- Draw the gun and walk at the same time rather than one after
|
||||
-- the other: EquipTool takes a frame or two, and so does the
|
||||
-- walk, so waiting for the first before starting the second
|
||||
-- doubled the time from the key press to the shot.
|
||||
local gun, equipped = Game.gunTool()
|
||||
if gun and not equipped then
|
||||
-- The click needs a gun that is actually out, and EquipTool
|
||||
-- does not land in the same frame.
|
||||
Game.equip(gun)
|
||||
local began = os.clock()
|
||||
while not select(2, Game.gunTool()) and os.clock() - began < 0.35 do
|
||||
task.wait()
|
||||
end
|
||||
end
|
||||
if gun and not equipped and not dry then Game.equip(gun) end
|
||||
|
||||
local reached, why = pointAt(char, part)
|
||||
if not reached then
|
||||
Combat.LastResult = "mouse aim — " .. why
|
||||
Combat.LastResult = (dry and "aim test — " or "mouse aim — ") .. why
|
||||
-- No shot went out; do not charge the next one a cooldown.
|
||||
lastShot = 0
|
||||
-- A press that quietly does nothing looks like a dead key.
|
||||
if force then
|
||||
UI.notify({title = dry and "Aim Test" or "Aimbot", text = why, kind = "warn", duration = 2})
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- Aim test: say where the cursor actually ended up. The point
|
||||
-- under it is the one MM2 would have sent, so its distance to
|
||||
-- them is the whole truth about whether the shot would land.
|
||||
if dry then
|
||||
local _, m = cursor()
|
||||
local ok, at = pcall(function() return m.Hit.Position end)
|
||||
local speed = 0
|
||||
pcall(function() speed = part.AssemblyLinearVelocity.Magnitude end)
|
||||
local text = ok
|
||||
and ("%.1f studs off %s, who was doing %.0f studs/s (%s)"):format(
|
||||
(at - part.Position).Magnitude, player.DisplayName, speed, why)
|
||||
or "could not read where the cursor landed"
|
||||
Combat.LastResult = "aim test — " .. text
|
||||
if force then
|
||||
UI.notify({title = "Aim Test", text = text, duration = 4})
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- The click still needs the gun actually out.
|
||||
local began = os.clock()
|
||||
while not select(2, Game.gunTool()) and os.clock() - began < 0.25 do
|
||||
task.wait()
|
||||
end
|
||||
|
||||
Mouse.Firing = true
|
||||
local sent = shootHere()
|
||||
Combat.LastResult = sent
|
||||
and ("mouse shot at " .. player.DisplayName .. " — " .. why)
|
||||
or "cursor on target but the click went nowhere"
|
||||
if force and not sent then
|
||||
UI.notify({title = "Aimbot", text = "the click went nowhere", kind = "bad", duration = 2})
|
||||
end
|
||||
end
|
||||
|
||||
KH.detach(function()
|
||||
@@ -487,6 +656,8 @@ do
|
||||
-- silent-aim handler ignore every real click.
|
||||
local ok, err = pcall(sequence)
|
||||
Mouse.Firing = false
|
||||
Mouse.Precise = false
|
||||
Mouse.Lead = 0
|
||||
activePart = nil
|
||||
busy = false
|
||||
if not ok then Combat.LastResult = "mouse aim error: " .. tostring(err) end
|
||||
@@ -497,16 +668,33 @@ do
|
||||
|
||||
-- Fires once at the current best target. Returns true when a shot went out.
|
||||
function Combat.fireOnce(force)
|
||||
-- A key press that does nothing at all is the most confusing thing this
|
||||
-- can do, so say why. Only for a real press: the render loop calls this
|
||||
-- every frame and would notify every frame with it.
|
||||
local function refuse(reason)
|
||||
Combat.LastResult = reason
|
||||
if force then
|
||||
UI.notify({title = "Aimbot", text = reason, kind = "warn", duration = 2})
|
||||
end
|
||||
return false, reason
|
||||
end
|
||||
|
||||
-- An aim test needs no gun: it is checking where the cursor lands, and
|
||||
-- waiting to roll sheriff to find that out is most of a round each try.
|
||||
local gun = Game.gunTool()
|
||||
if not gun then
|
||||
Combat.LastResult = "no gun — you are not holding one"
|
||||
return false, "no gun"
|
||||
if not gun and not S.Aim.DryRun then
|
||||
return refuse("no gun — you are not holding one")
|
||||
end
|
||||
|
||||
local player, char, part = Combat.pickTarget()
|
||||
if not player and S.Aim.DryRun then
|
||||
-- Anyone will do when nothing is going to be fired at them.
|
||||
player, char, part = Combat.pickTarget("Nearest")
|
||||
end
|
||||
if not player then
|
||||
Combat.LastResult = "no target"
|
||||
return false, "no target"
|
||||
return refuse(S.Aim.Target == "Murderer"
|
||||
and "no target — the murderer is not known yet"
|
||||
or "no target")
|
||||
end
|
||||
Combat.LastTarget = player
|
||||
|
||||
@@ -523,7 +711,12 @@ do
|
||||
Combat.LastResult = tostring(err)
|
||||
end
|
||||
end
|
||||
if not ok then return false, err end
|
||||
-- A cooldown is the fire rate doing its job, not a failure worth saying
|
||||
-- out loud; everything else here means the press went nowhere.
|
||||
if not ok then
|
||||
if err == "cooldown" then return false, err end
|
||||
return refuse(tostring(err))
|
||||
end
|
||||
|
||||
if S.Aim.NotifyShot then
|
||||
UI.notify({title = "Shot", text = "Fired at " .. player.DisplayName, duration = 1.5})
|
||||
@@ -590,13 +783,19 @@ do
|
||||
part = picked
|
||||
end
|
||||
-- Last, because it is the only test that walks the character.
|
||||
if part and Game.gunTool() then return part end
|
||||
if part and (Game.gunTool() or S.Aim.DryRun) then return part end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function lockCamera(dt)
|
||||
local part = lockTarget()
|
||||
if part then
|
||||
-- A shot with a locked cursor is aimed entirely by this: it has to
|
||||
-- land exactly on the target rather than ease towards it, and it
|
||||
-- cannot stop early for being comfortably inside the view.
|
||||
local precise = part ~= nil and Combat.Mouse.Precise
|
||||
if precise then
|
||||
turning = true
|
||||
elseif part then
|
||||
-- Turn only when there is something to turn for: a target
|
||||
-- already well inside the view needs no camera work at all,
|
||||
-- and a view that stays still is both smoother and far less
|
||||
@@ -625,7 +824,8 @@ do
|
||||
held = CFrame.new(cam.CFrame.Position) * (held or cam.CFrame).Rotation
|
||||
|
||||
if turning then
|
||||
held = held:Lerp(CFrame.new(cam.CFrame.Position, Combat.Mouse.livePoint(part)), alpha)
|
||||
local want = CFrame.new(cam.CFrame.Position, Combat.Mouse.aimPoint(part))
|
||||
held = precise and want or held:Lerp(want, alpha)
|
||||
cam.CFrame = held
|
||||
return
|
||||
end
|
||||
|
||||
+63
-26
@@ -18,8 +18,12 @@ do
|
||||
-- Coins that were touched but whose model has not despawned yet. Without
|
||||
-- this the farm re-targets the same coin forever.
|
||||
local claimed = {}
|
||||
Game.on("RoundStart", function() claimed = {} end)
|
||||
Game.on("RoundEnd", function() claimed = {} end)
|
||||
|
||||
-- The drop we already reacted to, so we never run at it twice.
|
||||
local triedDrop = nil
|
||||
|
||||
Game.on("RoundStart", function() claimed = {} triedDrop = nil end)
|
||||
Game.on("RoundEnd", function() claimed = {} triedDrop = nil end)
|
||||
|
||||
-- ------------------------------------------------------------- collect
|
||||
local function touch(part)
|
||||
@@ -128,7 +132,19 @@ do
|
||||
-- ========================================================= GUN GRABBING
|
||||
local grabbing = false
|
||||
|
||||
function Farm.grabGun(announce)
|
||||
-- The murderer cannot pick the gun up, so anything short of a confident
|
||||
-- "not the murderer" counts as a no.
|
||||
local function blockedReason(strict)
|
||||
if Game.amMurderer() then return "You are the murderer — that gun is not yours to take." end
|
||||
if Game.gunTool() then return "You already have a gun." end
|
||||
if not U.isAliveChar(LocalPlayer) then return "You are not alive." end
|
||||
-- Automatic grabs only: a button press is the user's call, but nothing
|
||||
-- moves on its own while we cannot prove what we are.
|
||||
if strict and not Game.selfKnown() then return "Roles are not known yet — staying put." end
|
||||
return nil
|
||||
end
|
||||
|
||||
function Farm.grabGun(announce, strict)
|
||||
local drop = Game.GunDrop
|
||||
if not drop or not drop.Parent then
|
||||
if announce then
|
||||
@@ -137,52 +153,73 @@ do
|
||||
return false
|
||||
end
|
||||
if grabbing then return false end
|
||||
if Game.gunTool() then return false end -- already armed
|
||||
|
||||
-- The murderer cannot pick the gun up. Going anyway means teleporting
|
||||
-- onto the sheriff's body seconds after killing them, standing there
|
||||
-- while the pickup that will never happen times out, and teleporting
|
||||
-- back — in front of whoever is watching.
|
||||
if Game.amMurderer() then
|
||||
local blocked = blockedReason(strict)
|
||||
if blocked then
|
||||
if announce then
|
||||
UI.notify({title = "Gun Drop", text = "You are the murderer — that gun is not yours to take.", kind = "warn"})
|
||||
UI.notify({title = "Gun Drop", text = blocked, kind = "warn"})
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
grabbing = true
|
||||
KH.detach(function()
|
||||
local root = U.myRoot()
|
||||
if root then
|
||||
-- pcall, or one error leaves the flag stuck on forever.
|
||||
pcall(function()
|
||||
local root = U.myRoot()
|
||||
if not root then return end
|
||||
|
||||
local origin = root.CFrame
|
||||
root.CFrame = CFrame.new(drop.Position + Vector3.new(0, 2.5, 0))
|
||||
|
||||
-- Wait for the pickup to actually register before hopping back.
|
||||
local began = os.clock()
|
||||
repeat
|
||||
-- Wait for the pickup, rechecking we may stand here at all.
|
||||
local began, bailed = os.clock(), false
|
||||
while true do
|
||||
task.wait(0.08)
|
||||
until Game.gunTool() or not drop.Parent or os.clock() - began > 2.5
|
||||
|
||||
if S.Farm.GrabReturn then
|
||||
local current = U.myRoot()
|
||||
if current then current.CFrame = origin end
|
||||
if Game.gunTool() or not drop.Parent then break end
|
||||
if os.clock() - began > 2.5 then break end
|
||||
if U.myRoot() ~= root or blockedReason(false) then
|
||||
bailed = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if Game.gunTool() then
|
||||
-- Same body only: never drag a fresh spawn to the old spot.
|
||||
if U.myRoot() == root and (bailed or S.Farm.GrabReturn) then
|
||||
root.CFrame = origin
|
||||
end
|
||||
|
||||
if not bailed and Game.gunTool() then
|
||||
UI.notify({title = "Gun Drop", text = "Picked up the dropped gun.", kind = "good"})
|
||||
end
|
||||
end
|
||||
end)
|
||||
grabbing = false
|
||||
end)
|
||||
return true
|
||||
end
|
||||
|
||||
Game.on("GunDropped", function()
|
||||
Game.on("GunDropped", function(drop)
|
||||
UI.notify({title = "Gun Dropped", text = "The sheriff went down — gun is on the floor.", kind = "warn", duration = 5})
|
||||
if S.Farm.AutoGrabGun then
|
||||
if not S.Farm.AutoGrabGun then return end
|
||||
if drop == triedDrop then return end
|
||||
triedDrop = drop
|
||||
|
||||
-- Off the signal thread: a listener that yields stalls the rest.
|
||||
KH.detach(function()
|
||||
task.wait(0.6) -- let the part settle where it lands
|
||||
Farm.grabGun(false)
|
||||
end
|
||||
|
||||
-- The murderer's thrown knife is in flight right now, so empty
|
||||
-- hands are not proof of innocence — wait for the real roles.
|
||||
local deadline = os.clock() + 4
|
||||
while not Game.selfKnown() and os.clock() < deadline do
|
||||
if Game.amMurderer() then return end
|
||||
task.wait(0.2)
|
||||
end
|
||||
|
||||
if not S.Farm.AutoGrabGun then return end
|
||||
if not drop.Parent or Game.GunDrop ~= drop then return end
|
||||
Farm.grabGun(false, true)
|
||||
end)
|
||||
end)
|
||||
|
||||
Game.on("GunTaken", function()
|
||||
|
||||
+18
-10
@@ -33,7 +33,7 @@ do
|
||||
|
||||
-- ========================================================== AIMBOT TAB
|
||||
do
|
||||
local tab = UI.addTab("Aimbot", "🎯")
|
||||
local tab = UI.addTab("Aimbot")
|
||||
|
||||
local targeting = UI.section(tab, "Targeting")
|
||||
UI.label(targeting, "Draws your gun, then shoots the murderer wherever they are — through walls, across the map, no mouse movement. MM2's shot is a world position the server resolves, so nothing needs to be on screen.")
|
||||
@@ -88,13 +88,21 @@ do
|
||||
}))
|
||||
UI.slider(mouseAim, opt("Aim", "MouseSpeed", {
|
||||
text = "Aim Speed",
|
||||
desc = "Governs the turn and the cursor together. 1 is an instant snap; lower eases both, which looks far smoother for a few frames' delay. 0.4 lands in about a tenth of a second.",
|
||||
desc = "How fast the camera turns onto the target. 1 snaps in one frame; lower eases the turn, which looks far smoother and is the only part of this anyone else can see. The cursor itself always goes straight there.",
|
||||
min = 0.1, max = 1, step = 0.05,
|
||||
}))
|
||||
UI.readout(mouseAim, {
|
||||
text = "Mouse Control",
|
||||
get = function() return Combat.Mouse.support() end,
|
||||
})
|
||||
UI.toggle(mouseAim, opt("Aim", "DryRun", {
|
||||
text = "Aim Test (no shooting)",
|
||||
desc = "Aims at the nearest player and reports how many studs the cursor landed from them, without firing and without needing a gun. For checking the aim without waiting to roll sheriff.",
|
||||
}))
|
||||
UI.readout(mouseAim, {
|
||||
text = "Last Result",
|
||||
get = function() return Combat.LastResult or "nothing yet" end,
|
||||
})
|
||||
|
||||
local extras = UI.section(tab, "Extras")
|
||||
UI.toggle(extras, opt("Aim", "SilentAim", {
|
||||
@@ -133,7 +141,7 @@ do
|
||||
|
||||
-- =========================================================== KNIFE TAB
|
||||
do
|
||||
local tab = UI.addTab("Knife", "🔪")
|
||||
local tab = UI.addTab("Knife")
|
||||
UI.label(UI.section(tab, "Murderer Only"),
|
||||
"These do nothing unless you are holding the knife.")
|
||||
|
||||
@@ -193,7 +201,7 @@ do
|
||||
|
||||
-- ============================================================= ESP TAB
|
||||
do
|
||||
local tab = UI.addTab("ESP", "👁")
|
||||
local tab = UI.addTab("ESP")
|
||||
|
||||
local players = UI.section(tab, "Players")
|
||||
UI.toggle(players, opt("ESP", "Enabled", {text = "ESP Enabled"}))
|
||||
@@ -248,7 +256,7 @@ do
|
||||
|
||||
-- ============================================================ FARM TAB
|
||||
do
|
||||
local tab = UI.addTab("Farm", "💰")
|
||||
local tab = UI.addTab("Farm")
|
||||
|
||||
local coins = UI.section(tab, "Coins")
|
||||
UI.toggle(coins, opt("Farm", "CoinFarm", {
|
||||
@@ -299,7 +307,7 @@ do
|
||||
|
||||
-- ========================================================== SAFETY TAB
|
||||
do
|
||||
local tab = UI.addTab("Safety", "🛡")
|
||||
local tab = UI.addTab("Safety")
|
||||
|
||||
local warning = UI.section(tab, "Murderer Warning")
|
||||
UI.label(warning, "The half of an MM2 script that keeps you alive when you are just an innocent.")
|
||||
@@ -347,7 +355,7 @@ do
|
||||
|
||||
-- ======================================================== MOVEMENT TAB
|
||||
do
|
||||
local tab = UI.addTab("Movement", "🏃")
|
||||
local tab = UI.addTab("Movement")
|
||||
|
||||
local speed = UI.section(tab, "Speed & Jump")
|
||||
UI.toggle(speed, opt("Move", "SpeedEnabled", {
|
||||
@@ -449,7 +457,7 @@ do
|
||||
|
||||
-- ========================================================= VISUALS TAB
|
||||
do
|
||||
local tab = UI.addTab("Visuals", "✨")
|
||||
local tab = UI.addTab("Visuals")
|
||||
|
||||
local lighting = UI.section(tab, "Lighting")
|
||||
UI.toggle(lighting, opt("Visual", "Fullbright", {
|
||||
@@ -482,7 +490,7 @@ do
|
||||
|
||||
-- ========================================================= PLAYERS TAB
|
||||
do
|
||||
local tab = UI.addTab("Players", "👥")
|
||||
local tab = UI.addTab("Players")
|
||||
local section = UI.section(tab, "In This Server")
|
||||
UI.label(section, "Live roster with roles. Click a name to spectate, or use the arrow to teleport.")
|
||||
|
||||
@@ -630,7 +638,7 @@ do
|
||||
|
||||
-- ======================================================== SETTINGS TAB
|
||||
do
|
||||
local tab = UI.addTab("Settings", "⚙")
|
||||
local tab = UI.addTab("Settings")
|
||||
|
||||
local interface = UI.section(tab, "Interface")
|
||||
UI.keybind(interface, opt("UI", "MenuKey", {text = "Menu Key"}))
|
||||
|
||||
@@ -0,0 +1,274 @@
|
||||
-- ============================================================================
|
||||
-- PROBE — the diagnostics tab. Everything the mouse aim rests on but cannot
|
||||
-- see for itself: whether the cursor answers a synthetic move, what a pixel is
|
||||
-- worth to it, how fast a target really crosses the screen, and where the last
|
||||
-- few shots actually landed.
|
||||
-- ============================================================================
|
||||
|
||||
do
|
||||
local UI = KH.UI
|
||||
local U = KH.U
|
||||
local Combat = KH.Combat
|
||||
local UIS = KH.Services.UserInputService
|
||||
local LocalPlayer = KH.LocalPlayer
|
||||
|
||||
local Probe = {}
|
||||
KH.Probe = Probe
|
||||
|
||||
Probe.Cursor = "not run yet"
|
||||
local live = {} -- the target's numbers, while the tab is open
|
||||
local history = {} -- the last few aim results, newest first
|
||||
local lines = {} -- the labels those are printed into
|
||||
local lastResult
|
||||
|
||||
-- --------------------------------------------------------- cursor test
|
||||
-- Ask for a move of a known size and watch what mouse.X/Y makes of it. Two
|
||||
-- answers matter: whether it answers at all, which is what the whole aim
|
||||
-- loop is built on, and by how much, which is the display scale it has to
|
||||
-- learn rather than assume.
|
||||
local testing = false
|
||||
function Probe.testCursor()
|
||||
if testing then return end
|
||||
if type(mousemoverel) ~= "function" then
|
||||
Probe.Cursor = "no mousemoverel on this executor"
|
||||
return
|
||||
end
|
||||
testing = true
|
||||
Probe.Cursor = "running…"
|
||||
|
||||
KH.detach(function()
|
||||
pcall(function()
|
||||
local mouse = LocalPlayer:GetMouse()
|
||||
local home = Vector2.new(mouse.X, mouse.Y)
|
||||
local lag, scale, lost = {}, {}, 0
|
||||
|
||||
-- Start from the middle of the screen. A move that runs into
|
||||
-- the edge of the window is clamped, and a clamped sample looks
|
||||
-- exactly like a wildly wrong display scale.
|
||||
local view = KH.camera().ViewportSize
|
||||
pcall(mousemoverel,
|
||||
math.floor(view.X / 2 - mouse.X + 0.5),
|
||||
math.floor(view.Y / 2 - mouse.Y + 0.5))
|
||||
task.wait()
|
||||
task.wait()
|
||||
|
||||
local moves = {
|
||||
Vector2.new(120, 0), Vector2.new(-120, 0),
|
||||
Vector2.new(0, 90), Vector2.new(0, -90),
|
||||
}
|
||||
for _, delta in ipairs(moves) do
|
||||
local from = Vector2.new(mouse.X, mouse.Y)
|
||||
pcall(mousemoverel, delta.X, delta.Y)
|
||||
|
||||
local landed, waited = nil, 0
|
||||
for frame = 1, 10 do
|
||||
task.wait()
|
||||
waited = frame
|
||||
if (Vector2.new(mouse.X, mouse.Y) - from).Magnitude >= 1 then
|
||||
task.wait() -- one more, in case it arrives in pieces
|
||||
landed = Vector2.new(mouse.X, mouse.Y)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if landed then
|
||||
lag[#lag + 1] = waited
|
||||
scale[#scale + 1] = delta.Magnitude
|
||||
/ math.max((landed - from).Magnitude, 0.001)
|
||||
else
|
||||
lost = lost + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Put it back roughly where it was found.
|
||||
pcall(mousemoverel,
|
||||
math.floor(home.X - mouse.X + 0.5),
|
||||
math.floor(home.Y - mouse.Y + 0.5))
|
||||
|
||||
if lost >= 3 then
|
||||
Probe.Cursor = "never moved — mouse aim cannot work on this setup"
|
||||
elseif #scale == 0 then
|
||||
Probe.Cursor = "no usable samples"
|
||||
else
|
||||
local frames = 0
|
||||
for i = 1, #lag do frames = frames + lag[i] end
|
||||
|
||||
-- Median, and every sample printed beside it. One clamped
|
||||
-- or half-landed move used to drag the mean into nonsense
|
||||
-- and make a healthy setup look broken.
|
||||
local sorted, each = {}, {}
|
||||
for i = 1, #scale do
|
||||
sorted[i] = scale[i]
|
||||
each[i] = ("%.2f"):format(scale[i])
|
||||
end
|
||||
table.sort(sorted)
|
||||
|
||||
Probe.Cursor = ("%d frame lag · scale %.2f (%s)%s"):format(
|
||||
math.floor(frames / #lag + 0.5),
|
||||
sorted[math.ceil(#sorted / 2)],
|
||||
table.concat(each, " "),
|
||||
lost > 0 and (" · " .. lost .. " lost") or "")
|
||||
end
|
||||
end)
|
||||
testing = false
|
||||
end)
|
||||
end
|
||||
|
||||
-- ----------------------------------------------------------------- tab
|
||||
local tab = UI.addTab("Probe")
|
||||
|
||||
local env = UI.section(tab, "This Executor")
|
||||
UI.label(env, "What the mouse aim has to work with. If something here is wrong, no amount of tuning on the Aimbot tab will land a shot.")
|
||||
UI.readout(env, {text = "Mouse Control", get = function() return Combat.Mouse.support() end})
|
||||
UI.readout(env, {
|
||||
text = "Mouse Behaviour",
|
||||
get = function()
|
||||
local mode = tostring(UIS.MouseBehavior):gsub("Enum%.MouseBehavior%.", "")
|
||||
if mode == "Default" then return mode end
|
||||
return mode .. " — cursor is locked"
|
||||
end,
|
||||
})
|
||||
UI.button(env, {text = "Run Cursor Test", callback = function() Probe.testCursor() end})
|
||||
UI.readout(env, {text = "Cursor Test", get = function() return Probe.Cursor end})
|
||||
|
||||
local target = UI.section(tab, "Target Right Now")
|
||||
UI.label(target, "Live while this tab is open. The last line is the one that matters: a shot takes roughly 30 ms from the key press to the server, so anything near that is a target the aim has to lead rather than follow.")
|
||||
UI.readout(target, {text = "Target", get = function() return live.name or "none" end})
|
||||
UI.readout(target, {
|
||||
text = "Distance",
|
||||
get = function() return live.distance and ("%.0f studs"):format(live.distance) or "—" end,
|
||||
})
|
||||
UI.readout(target, {
|
||||
text = "Speed",
|
||||
get = function() return live.speed and ("%.0f studs/s"):format(live.speed) or "—" end,
|
||||
})
|
||||
UI.readout(target, {
|
||||
text = "On Screen",
|
||||
get = function()
|
||||
if not live.name then return "—" end
|
||||
return live.onScreen and "yes" or "no"
|
||||
end,
|
||||
})
|
||||
UI.readout(target, {
|
||||
text = "Body Width",
|
||||
get = function() return live.radius and ("%.0f px"):format(live.radius * 2) or "—" end,
|
||||
})
|
||||
UI.readout(target, {
|
||||
text = "Screen Speed",
|
||||
get = function() return live.pxPerSec and ("%.0f px/s"):format(live.pxPerSec) or "—" end,
|
||||
})
|
||||
UI.readout(target, {
|
||||
text = "Crosses Own Width",
|
||||
get = function() return live.crossMs and ("%.0f ms"):format(live.crossMs) or "—" end,
|
||||
})
|
||||
|
||||
local results = UI.section(tab, "Last Aim Results")
|
||||
UI.label(results, "Switch on Aim Test on the Aimbot tab, then press your aim key at someone who is moving. Under a stud means the cursor was on them; twenty means the ray went past them into the scenery.")
|
||||
for i = 1, 6 do
|
||||
lines[i] = UI.label(results, "—")
|
||||
end
|
||||
|
||||
-- -------------------------------------------------------- the report
|
||||
-- One button, one paste. Reading numbers off a screen and retyping them is
|
||||
-- how the important digit gets lost.
|
||||
local function report()
|
||||
local out = {
|
||||
"kitty hub probe · v" .. tostring(KH.Version),
|
||||
"executor: " .. tostring(KH.X.name),
|
||||
"mouse control: " .. tostring(Combat.Mouse.support()),
|
||||
"mouse behaviour: " .. tostring(UIS.MouseBehavior),
|
||||
"cursor test: " .. tostring(Probe.Cursor),
|
||||
}
|
||||
if live.name then
|
||||
out[#out + 1] = ("target: %s · %.0f studs · %.0f studs/s · body %.0f px · %.0f px/s · own width in %s")
|
||||
:format(live.name, live.distance or 0, live.speed or 0,
|
||||
(live.radius or 0) * 2, live.pxPerSec or 0,
|
||||
live.crossMs and ("%.0f ms"):format(live.crossMs) or "n/a")
|
||||
else
|
||||
out[#out + 1] = "target: none in view"
|
||||
end
|
||||
out[#out + 1] = "aim results:"
|
||||
for i = 1, #history do out[#out + 1] = " " .. tostring(history[i]) end
|
||||
if #history == 0 then out[#out + 1] = " (none yet)" end
|
||||
return table.concat(out, "\n")
|
||||
end
|
||||
|
||||
local share = UI.section(tab, "Report")
|
||||
UI.label(share, "Copies everything on this tab as text. Open the tab, take a few shots at someone moving with Aim Test on, then copy.")
|
||||
UI.button(share, {
|
||||
text = "Copy Report",
|
||||
callback = function()
|
||||
local ok, text = pcall(report)
|
||||
if not ok then
|
||||
UI.notify({title = "Probe", text = "Could not build the report.", kind = "bad", duration = 3})
|
||||
return
|
||||
end
|
||||
if KH.X.setclipboard and pcall(setclipboard, text) then
|
||||
UI.notify({title = "Probe", text = "Copied. Paste it wherever you need it.", kind = "good", duration = 3})
|
||||
else
|
||||
print(text)
|
||||
UI.notify({
|
||||
title = "Probe",
|
||||
text = "No clipboard here — printed to the console (F9) instead.",
|
||||
kind = "warn",
|
||||
duration = 5,
|
||||
})
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- ------------------------------------------------------- aim history
|
||||
-- Polled rather than pushed: the aim already writes its own outcome, and
|
||||
-- nothing here has to reach into it to find out.
|
||||
KH.loop(0.2, function()
|
||||
local result = Combat.LastResult
|
||||
if not result or result == lastResult then return end
|
||||
lastResult = result
|
||||
table.insert(history, 1, result)
|
||||
for i = #history, 7, -1 do history[i] = nil end
|
||||
for i = 1, #lines do lines[i].Text = history[i] or "—" end
|
||||
end)
|
||||
|
||||
-- ------------------------------------------------------- live target
|
||||
local lastPoint, lastAt
|
||||
KH.loop(0.1, function()
|
||||
if not (UI.IsOpen and UI.ActiveTab == "Probe") then
|
||||
lastPoint = nil
|
||||
return
|
||||
end
|
||||
|
||||
local player, _, part = Combat.pickTarget()
|
||||
if not player then player, _, part = Combat.pickTarget("Nearest") end
|
||||
if not part then
|
||||
live, lastPoint = {}, nil
|
||||
return
|
||||
end
|
||||
|
||||
local cam = KH.camera()
|
||||
local point, onScreen = cam:WorldToViewportPoint(part.Position)
|
||||
local here = Vector2.new(point.X, point.Y)
|
||||
local now = os.clock()
|
||||
|
||||
local pxPerSec = 0
|
||||
if lastPoint and now > lastAt then
|
||||
pxPerSec = (here - lastPoint).Magnitude / (now - lastAt)
|
||||
end
|
||||
lastPoint, lastAt = here, now
|
||||
|
||||
local edge = cam:WorldToViewportPoint(part.Position + Vector3.new(0, part.Size.Y * 0.5, 0))
|
||||
local radius = (Vector2.new(edge.X, edge.Y) - here).Magnitude
|
||||
|
||||
local speed = 0
|
||||
pcall(function() speed = part.AssemblyLinearVelocity.Magnitude end)
|
||||
|
||||
live = {
|
||||
name = player.DisplayName,
|
||||
onScreen = onScreen,
|
||||
distance = U.distanceTo(part.Position),
|
||||
speed = speed,
|
||||
pxPerSec = pxPerSec,
|
||||
radius = radius,
|
||||
crossMs = pxPerSec > 1 and (radius * 2 / pxPerSec) * 1000 or nil,
|
||||
}
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,454 @@
|
||||
-- ============================================================================
|
||||
-- LOGO — the Kitty Hub mark, carried in the script rather than fetched.
|
||||
--
|
||||
-- Roblox only draws an image it can resolve as an asset, and this one was
|
||||
-- never uploaded to Roblox. getcustomasset turns a file in the executor's own
|
||||
-- folder into an asset, so the mark travels here as base64, is written out
|
||||
-- once on the first run, and is read straight off disk every run after.
|
||||
--
|
||||
-- The name carries a version because the file is cached: change the image and
|
||||
-- the old one has to stop being found, or it is the one that keeps drawing.
|
||||
--
|
||||
-- An executor with no file API gets nothing back. Nothing may assume this
|
||||
-- returns an asset — the splash draws the wordmark as text when it does not.
|
||||
-- ============================================================================
|
||||
|
||||
do
|
||||
local FILE = "kittyhub_logo_v2.png"
|
||||
local STALE = {"kittyhub_logo.png"}
|
||||
|
||||
local ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
||||
local VALUE = {}
|
||||
for i = 1, #ALPHABET do VALUE[ALPHABET:byte(i)] = i - 1 end
|
||||
|
||||
-- Whitespace and padding read back as nil and are skipped, so the blob
|
||||
-- below can be wrapped to a sane width.
|
||||
local function decode(text)
|
||||
local out, bits, held = {}, 0, 0
|
||||
for i = 1, #text do
|
||||
local value = VALUE[text:byte(i)]
|
||||
if value then
|
||||
bits = bits * 64 + value
|
||||
held = held + 6
|
||||
if held >= 8 then
|
||||
held = held - 8
|
||||
local scale = 2 ^ held
|
||||
out[#out + 1] = string.char(math.floor(bits / scale) % 256)
|
||||
bits = bits % scale
|
||||
end
|
||||
end
|
||||
end
|
||||
return table.concat(out)
|
||||
end
|
||||
|
||||
local DATA = [[
|
||||
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]]
|
||||
|
||||
local asset, resolved = nil, false
|
||||
|
||||
function KH.logoAsset()
|
||||
if resolved then return asset end
|
||||
resolved = true
|
||||
if type(getcustomasset) ~= "function" then return nil end
|
||||
|
||||
local ok, result = pcall(function()
|
||||
-- A truncated file from a half-finished write would resolve to an
|
||||
-- asset that draws nothing, so check it looks like the image before
|
||||
-- trusting it.
|
||||
if type(isfile) == "function" and isfile(FILE) then
|
||||
local read, existing = pcall(readfile, FILE)
|
||||
if read and type(existing) == "string" and #existing > 1000 then
|
||||
return getcustomasset(FILE)
|
||||
end
|
||||
end
|
||||
if not KH.X.writefile then return nil end
|
||||
writefile(FILE, decode(DATA))
|
||||
|
||||
-- Best effort: an earlier version of the mark is dead weight now.
|
||||
if type(delfile) == "function" and type(isfile) == "function" then
|
||||
for _, old in ipairs(STALE) do
|
||||
if isfile(old) then pcall(delfile, old) end
|
||||
end
|
||||
end
|
||||
|
||||
return getcustomasset(FILE)
|
||||
end)
|
||||
|
||||
asset = ok and result or nil
|
||||
return asset
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,213 @@
|
||||
-- ============================================================================
|
||||
-- SPLASH — the load-in screen.
|
||||
--
|
||||
-- Cosmetic, and honest about it: the script is a single chunk and has already
|
||||
-- finished running by the time this draws, so nothing here is waiting on
|
||||
-- anything. It sits over the menu for a moment and fades off.
|
||||
--
|
||||
-- Everything it makes is owned by KH and has a hard timer behind it, so there
|
||||
-- is no path where it stays on screen — including the blur, which would be the
|
||||
-- worst thing to leave behind.
|
||||
-- ============================================================================
|
||||
|
||||
do
|
||||
local UI = KH.UI
|
||||
local C = UI.C
|
||||
local make = UI.make
|
||||
local Lighting = KH.Services.Lighting
|
||||
|
||||
if UI.Overlay then
|
||||
local fades = {}
|
||||
local function fading(obj, prop)
|
||||
fades[#fades + 1] = {obj = obj, prop = prop or "BackgroundTransparency"}
|
||||
return obj
|
||||
end
|
||||
|
||||
-- Blurring what is behind it is what makes a transparent cover read as
|
||||
-- glass rather than as a screen that failed to draw.
|
||||
local blur = make("BlurEffect", {Name = "khSplash", Size = 0, Parent = Lighting})
|
||||
KH.own(blur)
|
||||
|
||||
-- Active = false: even in the worst case this can never swallow a click.
|
||||
local root = fading(make("Frame", {
|
||||
Name = "Splash",
|
||||
BackgroundColor3 = C.Bg,
|
||||
BorderSizePixel = 0,
|
||||
Size = UDim2.fromScale(1, 1),
|
||||
Active = false,
|
||||
ZIndex = 500,
|
||||
Parent = UI.Overlay,
|
||||
}))
|
||||
KH.own(root)
|
||||
|
||||
-- Darkest at the edges, thinnest across the middle, so the game stays
|
||||
-- readable behind the card instead of being painted out.
|
||||
make("UIGradient", {
|
||||
Rotation = 90,
|
||||
Color = ColorSequence.new(C.Bg, C.Panel),
|
||||
Transparency = NumberSequence.new({
|
||||
NumberSequenceKeypoint.new(0, 0.12),
|
||||
NumberSequenceKeypoint.new(0.5, 0.46),
|
||||
NumberSequenceKeypoint.new(1, 0.12),
|
||||
}),
|
||||
Parent = root,
|
||||
})
|
||||
|
||||
local card = fading(make("Frame", {
|
||||
AnchorPoint = Vector2.new(0.5, 0.5),
|
||||
Position = UDim2.fromScale(0.5, 0.5),
|
||||
Size = UDim2.fromOffset(330, 224),
|
||||
BackgroundColor3 = C.Panel,
|
||||
BackgroundTransparency = 0.1,
|
||||
BorderSizePixel = 0,
|
||||
ZIndex = 502,
|
||||
Parent = root,
|
||||
}))
|
||||
UI.corner(card, 16)
|
||||
UI.gradient(card, C.Card, C.Panel, 90)
|
||||
fading(UI.stroke(card, C.Accent, 1, 0.55), "Transparency")
|
||||
|
||||
local shadow = UI.shadow(card, 30, 0.45)
|
||||
shadow.ZIndex = 501
|
||||
fading(shadow, "ImageTransparency")
|
||||
|
||||
-- A hairline of accent along the top edge, faded out at both ends.
|
||||
local edge = fading(make("Frame", {
|
||||
AnchorPoint = Vector2.new(0.5, 0),
|
||||
Position = UDim2.new(0.5, 0, 0, 0),
|
||||
Size = UDim2.new(1, -70, 0, 1),
|
||||
BackgroundColor3 = C.Accent,
|
||||
BorderSizePixel = 0,
|
||||
ZIndex = 503,
|
||||
Parent = card,
|
||||
}))
|
||||
make("UIGradient", {
|
||||
Transparency = NumberSequence.new({
|
||||
NumberSequenceKeypoint.new(0, 1),
|
||||
NumberSequenceKeypoint.new(0.5, 0.05),
|
||||
NumberSequenceKeypoint.new(1, 1),
|
||||
}),
|
||||
Parent = edge,
|
||||
})
|
||||
|
||||
-- The mark carries the name, so there is no title line to draw with it.
|
||||
-- Without it, the name has to be set instead.
|
||||
local asset = KH.logoAsset()
|
||||
if asset then
|
||||
fading(make("ImageLabel", {
|
||||
Image = asset,
|
||||
BackgroundTransparency = 1,
|
||||
AnchorPoint = Vector2.new(0.5, 0),
|
||||
Position = UDim2.new(0.5, 0, 0, 24),
|
||||
Size = UDim2.fromOffset(96, 96),
|
||||
ZIndex = 503,
|
||||
Parent = card,
|
||||
}), "ImageTransparency")
|
||||
else
|
||||
fading(make("TextLabel", {
|
||||
Text = "KITTY HUB",
|
||||
Font = Enum.Font.GothamBold,
|
||||
TextSize = 24,
|
||||
TextColor3 = C.Text,
|
||||
BackgroundTransparency = 1,
|
||||
Position = UDim2.fromOffset(0, 56),
|
||||
Size = UDim2.new(1, 0, 0, 30),
|
||||
ZIndex = 503,
|
||||
Parent = card,
|
||||
}), "TextTransparency")
|
||||
end
|
||||
|
||||
fading(make("TextLabel", {
|
||||
Text = "Murder Mystery 2",
|
||||
Font = Enum.Font.Gotham,
|
||||
TextSize = 12,
|
||||
TextColor3 = C.TextDim,
|
||||
BackgroundTransparency = 1,
|
||||
Position = UDim2.fromOffset(0, 128),
|
||||
Size = UDim2.new(1, 0, 0, 16),
|
||||
ZIndex = 503,
|
||||
Parent = card,
|
||||
}), "TextTransparency")
|
||||
|
||||
local track = fading(make("Frame", {
|
||||
AnchorPoint = Vector2.new(0.5, 0),
|
||||
Position = UDim2.new(0.5, 0, 0, 156),
|
||||
Size = UDim2.fromOffset(236, 3),
|
||||
BackgroundColor3 = C.Row,
|
||||
BackgroundTransparency = 0.35,
|
||||
BorderSizePixel = 0,
|
||||
ZIndex = 503,
|
||||
Parent = card,
|
||||
}))
|
||||
UI.corner(track, 2)
|
||||
|
||||
local fill = fading(make("Frame", {
|
||||
Size = UDim2.fromScale(0, 1),
|
||||
BackgroundColor3 = C.Accent,
|
||||
BorderSizePixel = 0,
|
||||
ZIndex = 504,
|
||||
Parent = track,
|
||||
}))
|
||||
UI.corner(fill, 2)
|
||||
|
||||
local status = fading(make("TextLabel", {
|
||||
Text = "starting up",
|
||||
Font = Enum.Font.Gotham,
|
||||
TextSize = 11,
|
||||
TextColor3 = C.TextDim,
|
||||
BackgroundTransparency = 1,
|
||||
Position = UDim2.fromOffset(0, 170),
|
||||
Size = UDim2.new(1, 0, 0, 14),
|
||||
ZIndex = 503,
|
||||
Parent = card,
|
||||
}), "TextTransparency")
|
||||
|
||||
fading(make("TextLabel", {
|
||||
Text = ("v%s · %s"):format(KH.Version, KH.X.name),
|
||||
Font = Enum.Font.Gotham,
|
||||
TextSize = 10,
|
||||
TextColor3 = C.TextFaint,
|
||||
BackgroundTransparency = 1,
|
||||
Position = UDim2.fromOffset(0, 194),
|
||||
Size = UDim2.new(1, 0, 0, 14),
|
||||
ZIndex = 503,
|
||||
Parent = card,
|
||||
}), "TextTransparency")
|
||||
|
||||
-- Nothing is loading, so the bar walks a fixed path rather than
|
||||
-- pretending to measure one.
|
||||
local stages = {
|
||||
{0.3, "checking the executor"},
|
||||
{0.6, "building the interface"},
|
||||
{0.85, "arming features"},
|
||||
{1, "ready"},
|
||||
}
|
||||
|
||||
KH.spawn(function()
|
||||
UI.tween(blur, 0.25, {Size = 14})
|
||||
for _, stage in ipairs(stages) do
|
||||
if not (KH.Alive and root.Parent) then return end
|
||||
status.Text = stage[2]
|
||||
UI.tween(fill, 0.2, {Size = UDim2.fromScale(stage[1], 1)})
|
||||
task.wait(0.2)
|
||||
end
|
||||
|
||||
task.wait(0.1)
|
||||
if not (KH.Alive and root.Parent) then return end
|
||||
for _, item in ipairs(fades) do
|
||||
pcall(function() UI.tween(item.obj, 0.35, {[item.prop] = 1}) end)
|
||||
end
|
||||
UI.tween(blur, 0.35, {Size = 0})
|
||||
task.wait(0.4)
|
||||
root:Destroy()
|
||||
blur:Destroy()
|
||||
end)
|
||||
|
||||
-- Whatever happens above — an error, an unload mid-fade — both come
|
||||
-- off. Reading Parent on a destroyed instance is safe.
|
||||
task.delay(4, function()
|
||||
if root.Parent then root:Destroy() end
|
||||
if blur.Parent then blur:Destroy() end
|
||||
end)
|
||||
end
|
||||
end
|
||||
Reference in new issue
Block a user