
Key Required

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local LocalPlayer = Players.LocalPlayer
local CONFIG = {
FireDelay = 0.37,
RetryDelay = 0.04,
RetryFire = true,
FacingDotThreshold = -0.6,
LowHPThreshold = 15,
ChainResetTime = 2,
FaceCheckMaxDist = 8,
BehindOffset = 5,
DashSideRadius = 4.5,
-- Dash humanizado: duração base por stud percorrido + jitter
DashSpeedPerStud = 0.026, -- segundos por stud (ligeiramente mais lento = mais peso, mais intencional)
DashMinDuration = 0.14, -- mínimo absoluto aumentado (elimina flash em alvo próximo)
DashMaxDuration = 0.32, -- máximo levemente maior pra dar espaço pro Cubic InOut respirar
DashTimeJitter = 0.04, -- ±0.04s variação aleatória de tempo por dash
DashRadiusJitter = 1.2, -- ±1.2 stud no raio lateral (variação mais perceptível entre dashes)
DashArcHeight = 0.3, -- offset Y no midpoint do arco (curvatura 3D sutil, não fica flat)
FireDelayJitter = 0.015, -- pequena margem de tolerância pro golden delay não falhar com variação de ping
-- Lock On câmera
LockOnSmoothness = 0.12, -- 0 = instantâneo, 1 = nunca chega. 0.12 = suave mas responsivo
LockOnHeightOffset = 2.0, -- mira um pouco acima do HRP (mais pro tronco/cabeça)
}
if _G.retryfire ~= nil then
CONFIG.RetryFire = _G.retryfire
end
local function getRemote(...)
local path = { ... }
local ok, remote = pcall(function()
local node = ReplicatedStorage
for _, child in ipairs(path) do
node = node:WaitForChild(child, 5)
end
return node
end)
return ok and remote or nil
end
local targetRemote = getRemote("Knit","Knit","Services","DivergentFistService","RE","Activated")
if not targetRemote then
warn("[DivergentFist] Remote not found!")
return
end
local returnSkillRemote = getRemote("Knit","Knit","Services","ItadoriService","RE","RightActivated")
local function getHRP()
local char = LocalPlayer.Character
return char and char:FindFirstChild("HumanoidRootPart")
end
local function isAliveModel(model)
local myChar = LocalPlayer.Character
if model == myChar then return false end
local root = model:FindFirstChild("HumanoidRootPart")
local humanoid = model:FindFirstChild("Humanoid")
return root and humanoid and humanoid.Health > 0
end
local function findNearestTarget()
local hrp = getHRP()
if not hrp then return nil end
local nearest = nil
local bestDist = math.huge
local function checkModel(model)
if not isAliveModel(model) then return end
local root = model:FindFirstChild("HumanoidRootPart")
local dist = (hrp.Position - root.Position).Magnitude
if dist < bestDist then
bestDist = dist
nearest = model
end
end
for _, player in ipairs(Players:GetPlayers()) do
if player ~= LocalPlayer and player.Character then
checkModel(player.Character)
end
end
for _, obj in ipairs(workspace:GetDescendants()) do
if obj:IsA("Model") then checkModel(obj) end
end
return nearest
end
-- checa se EU estou atrás do alvo (dot bem negativo = eu tô na direção
-- oposta ao LookVector dele, ou seja, atrás das costas dele).
-- é a única situação que deveria pular o dash de reposição.
local function isBehindTarget(targetRoot)
local hrp = getHRP()
if not hrp or not targetRoot or not targetRoot.Parent then return false end
local toPlayer = (hrp.Position - targetRoot.Position)
if toPlayer.Magnitude < 0.01 then return false end
local dot = targetRoot.CFrame.LookVector:Dot(toPlayer.Unit)
return dot < CONFIG.FacingDotThreshold
end
local function isClose(targetRoot)
local hrp = getHRP()
if not hrp or not targetRoot or not targetRoot.Parent then return false end
return (hrp.Position - targetRoot.Position).Magnitude <= CONFIG.FaceCheckMaxDist
end
local function isTargetInFrontClose(targetRoot)
if not isClose(targetRoot) then return false end
return not isBehindTarget(targetRoot)
end
local function getTargetHP(target)
if not target then return math.huge end
local humanoid = target:FindFirstChild("Humanoid")
if not humanoid then return math.huge end
return humanoid.Health
end
-- ──────────────────────────────────────────────
-- LOCK ON – câmera olha suavemente pro alvo
-- NÃO muda CameraType pra Scriptable (quebra input do BF!)
-- Funciona via CFrame.lookAt + Lerp no RenderStepped
-- Auto-desativa após 1 segundo
-- ──────────────────────────────────────────────
local camera = workspace.CurrentCamera
local lockOnConn = nil -- conexão RenderStepped do lock on
local lockOnTimer = nil -- task.delay de 1s pra desativar
local function stopLockOn()
if lockOnConn then
lockOnConn:Disconnect()
lockOnConn = nil
end
if lockOnTimer then
task.cancel(lockOnTimer)
lockOnTimer = nil
end
end
local function startLockOn(targetRoot)
-- Desconecta qualquer lock anterior
stopLockOn()
lockOnConn = RunService.RenderStepped:Connect(function()
-- Para se o alvo sumiu ou morreu
if not targetRoot or not targetRoot.Parent then
stopLockOn()
return
end
local hrp = getHRP()
if not hrp then return end
-- Ponto que a câmera vai olhar: HRP do alvo + offset de altura
local aimPoint = targetRoot.Position + Vector3.new(0, CONFIG.LockOnHeightOffset, 0)
-- CFrame atual da câmera (posição mantida, só muda a direção)
local camPos = camera.CFrame.Position
local wantedCF = CFrame.lookAt(camPos, aimPoint)
-- Lerp suave: câmera gira em direção ao alvo sem travar o input
camera.CFrame = camera.CFrame:Lerp(wantedCF, CONFIG.LockOnSmoothness)
end)
-- Auto-desativa após 1 segundo
lockOnTimer = task.delay(1, function()
stopLockOn()
lockOnTimer = nil
end)
end
-- ──────────────────────────────────────────────
-- DASH 180: arco horizontal lateral, alterna L/R
-- ──────────────────────────────────────────────
local dashSide = "Left"
local function dashBehindTarget(targetRoot)
local hrp = getHRP()
if not hrp or not targetRoot or not targetRoot.Parent then return end
local side = dashSide
dashSide = (side == "Left") and "Right" or "Left"
local y = hrp.Position.Y
local startPos = hrp.Position
local rightVec = targetRoot.CFrame.RightVector
local sideVec = (side == "Right") and rightVec or -rightVec
-- raio lateral com jitter: evita arco perfeito e idêntico toda vez
local radiusJitter = (math.random() * 2 - 1) * CONFIG.DashRadiusJitter
local sideRadius = CONFIG.DashSideRadius + radiusJitter
local midPos = targetRoot.Position + sideVec * sideRadius
-- leve elevação no midpoint: arco tem curvatura 3D sutil ao invés de ser completamente flat
midPos = Vector3.new(midPos.X, y + CONFIG.DashArcHeight, midPos.Z)
-- duração proporcional à distância real a percorrer + jitter de tempo
local lookDir = targetRoot.CFrame.LookVector
local behindDest = targetRoot.Position - lookDir * CONFIG.BehindOffset
behindDest = Vector3.new(behindDest.X, y, behindDest.Z)
local totalDist = (startPos - midPos).Magnitude + (midPos - behindDest).Magnitude
local baseDur = math.clamp(totalDist * CONFIG.DashSpeedPerStud, CONFIG.DashMinDuration, CONFIG.DashMaxDuration)
local timeJitter = (math.random() * 2 - 1) * CONFIG.DashTimeJitter
local duration = math.max(CONFIG.DashMinDuration, baseDur + timeJitter)
local startTime = os.clock()
while true do
if not targetRoot.Parent then return end
local alpha = (os.clock() - startTime) / duration
if alpha >= 1 then break end
-- Cubic InOut: arranca devagar, acelera no meio, desacelera no final
-- parece movimento de corpo humano de verdade (wind-up → burst → brake)
-- muito mais orgânico que Sine.Out que começa imediato demais
local easedAlpha = TweenService:GetValue(alpha, Enum.EasingStyle.Cubic, Enum.EasingDirection.InOut)
-- recalcula behindPos em tempo real (alvo pode se mover durante o dash)
local curLookDir = targetRoot.CFrame.LookVector
local behindPos = targetRoot.Position - curLookDir * CONFIG.BehindOffset
behindPos = Vector3.new(behindPos.X, y, behindPos.Z)
local p1 = startPos:Lerp(midPos, easedAlpha)
local p2 = midPos:Lerp(behindPos, easedAlpha)
local pos = p1:Lerp(p2, easedAlpha)
hrp.CFrame = CFrame.new(pos, Vector3.new(targetRoot.Position.X, y, targetRoot.Position.Z))
RunService.Heartbeat:Wait()
end
if not targetRoot.Parent then return end
local curLookDir = targetRoot.CFrame.LookVector
local behindPos = targetRoot.Position - curLookDir * CONFIG.BehindOffset
behindPos = Vector3.new(behindPos.X, y, behindPos.Z)
hrp.CFrame = CFrame.new(behindPos, Vector3.new(targetRoot.Position.X, y, targetRoot.Position.Z))
print("[DivergentFist] Dash 180 → " .. side .. string.format(" (%.2fs, r=%.1f)", duration, sideRadius))
end
-- ──────────────────────────────────────────────
-- HOOK
-- ──────────────────────────────────────────────
local isCooling = false
local isRetrying = false
local chainCount = 0
local lastFireTime = 0
local lockedTarget = nil -- trava no alvo assim que a chain começa
local oldNamecall
oldNamecall = hookmetamethod(game, "__namecall", function(self, ...)
if getnamecallmethod() ~= "FireServer" or self ~= targetRemote then
return oldNamecall(self, ...)
end
if isRetrying then return oldNamecall(self, ...) end
if isCooling then return oldNamecall(self, ...) end
isCooling = true
local now = tick()
if (now - lastFireTime) > CONFIG.ChainResetTime then
chainCount = 0
lockedTarget = nil -- chain nova: solta o lock antigo
stopLockOn() -- reseta o lock on também quando a chain reinicia
end
lastFireTime = now
chainCount = chainCount + 1
print(string.format("[DivergentFist] Black Flash #%d", chainCount))
local result = oldNamecall(self, ...)
local args = { ... }
-- lock: só busca alvo novo se ainda não tem lock ou se o lock morreu/sumiu
if not lockedTarget or not lockedTarget.Parent or not isAliveModel(lockedTarget) then
lockedTarget = findNearestTarget()
end
local target = lockedTarget
local targetRoot = target and target:FindFirstChild("HumanoidRootPart")
-- Lock On: reativa a cada disparo enquanto a chain estiver rolando,
-- em vez de só quando o alvo muda. Isso mantém a câmera travada
-- do começo ao fim da chain, não só nos primeiros 1s depois de travar.
if targetRoot and targetRoot.Parent then
startLockOn(targetRoot)
end
-- perto (qualquer ângulo: frente, lado, costas) → dash 180 pras costas
if targetRoot and targetRoot.Parent and isClose(targetRoot) then
task.spawn(function()
dashBehindTarget(targetRoot)
end)
end
task.delay(CONFIG.FireDelay, function()
if chainCount == 4 then
local hp = getTargetHP(target)
if hp > CONFIG.LowHPThreshold then
print(string.format("[DivergentFist] 4º BF – inimigo com %.0f HP > %d → cancelando", hp, CONFIG.LowHPThreshold))
if returnSkillRemote then
pcall(function() returnSkillRemote:FireServer() end)
end
chainCount = 0
lockedTarget = nil
stopLockOn() -- solta câmera quando cancela
task.defer(function() isCooling = false end)
return
else
print(string.format("[DivergentFist] 4º BF – inimigo com %.0f HP <= %d → deixa passar!", hp, CONFIG.LowHPThreshold))
end
end
if chainCount >= 4 then
chainCount = 0
lockedTarget = nil
stopLockOn() -- solta câmera quando chain completa
end
if targetRoot and targetRoot.Parent and not isBehindTarget(targetRoot) then
-- ainda não tô nas costas dele: faz dash pras costas e continua a chain
if isClose(targetRoot) then
task.spawn(function() dashBehindTarget(targetRoot) end)
end
task.spawn(function()
task.wait(CONFIG.RetryDelay)
if not targetRoot.Parent or not isAliveModel(targetRoot.Parent) then
stopLockOn()
task.defer(function() isCooling = false end)
return
end
local shouldRetryFire = (_G.retryfire ~= nil) and _G.retryfire or CONFIG.RetryFire
local perto = isClose(targetRoot)
local stillNotBehind = perto and not isBehindTarget(targetRoot)
-- reposicionamento (dash) só acontece perto do alvo
if stillNotBehind then
print("[DivergentFist] Ainda nao tô atras - dash 180 de novo")
dashBehindTarget(targetRoot)
if targetRoot.Parent and isAliveModel(targetRoot.Parent) then
stillNotBehind = not isBehindTarget(targetRoot)
end
end
if stillNotBehind then
print("[DivergentFist] Nao deu pra reposicionar - desistindo")
elseif not shouldRetryFire then
print("[DivergentFist] RetryFire OFF")
elseif not isAliveModel(targetRoot.Parent) then
-- alvo morreu durante o delay: não dispara fire perdido
print("[DivergentFist] Alvo morreu - cancelando retry")
stopLockOn()
else
-- dispara o Black Flash independente da distância (perto ou longe)
isRetrying = true
pcall(function() targetRemote:FireServer(table.unpack(args)) end)
task.wait(CONFIG.FireDelay + CONFIG.FireDelayJitter)
pcall(function() targetRemote:FireServer(table.unpack(args)) end)
isRetrying = false
end
task.defer(function() isCooling = false end)
end)
else
-- já confirmado atrás do alvo: deixa o BF sair direto, sem dash
if targetRoot and targetRoot.Parent then
pcall(function() targetRemote:FireServer(table.unpack(args)) end)
end
task.defer(function() isCooling = false end)
end
end)
return result
end)
print("[DivergentFist] Pronto! | LowHP: " .. CONFIG.LowHPThreshold .. " | ChainReset: " .. CONFIG.ChainResetTime .. "s | LockOn: ON")
-- ──────────────────────────────────────────────
-- LOOP: apaga DisableChase e FlashChain do Info
-- ──────────────────────────────────────────────
task.spawn(function()
while task.wait(0.1) do
local char = LocalPlayer.Character
if char then
local info = char:FindFirstChild("Info")
if info then
local disableChase = info:FindFirstChild("DisableChase")
if disableChase then
pcall(function() disableChase:Destroy() end)
end
local flashChain = info:FindFirstChild("FlashChain")
if flashChain then
pcall(function() flashChain:Destroy() end)
end
end
end
end
end)No comments yet for this script.



