Fighter Bot
Key Required

Fighter Bot

Ragdoll Testingdacoder123dacoder123 726 views 305 executesUpdated Jan 4, 2026
2.5/ 5(2 votes)
1150% Positive
Lua Script•772 lines (31489 chars)
-- LocalScript: Multi-Target Click Lock + Smarter SelfYeet-Behind
-- ***Both leans enabled***:
--   (A) OLD horizontal ~70° lean (MoveTo side-entry shove)
--   (B) BodyGyro lean with dynamic ±60° yaw offset (continuous)
-- Smarter Humanoid:MoveTo striker: closes in more as you get closer to the target’s back.
-- Click-to-multi-target, safer selfyeet (auto side-switch), robust cleanup (X), hand-map toggle (H).
-- Place in StarterPlayerScripts

--==============================================================
-- SERVICES
--==============================================================
local Players            = game:GetService("Players")
local RunService         = game:GetService("RunService")
local UserInputService   = game:GetService("UserInputService")
local Workspace          = game:GetService("Workspace")
local Debris             = game:GetService("Debris")

local LocalPlayer        = Players.LocalPlayer
local Mouse              = LocalPlayer:GetMouse()

local character          = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
local hrp                = character:WaitForChild("HumanoidRootPart")
local humanoid           = character:WaitForChild("Humanoid")
local camera             = Workspace.CurrentCamera

--==============================================================
-- ANIMATION IDS (detect which hand)
--==============================================================
local leftSwingAnimId  = "rbxassetid://7218622714"
local rightSwingAnimId = "rbxassetid://7218624486"

--==============================================================
-- OPTIONAL REMOTE (get-up toggle)
--==============================================================
local ok, toggleRemote = pcall(function()
	return LocalPlayer:WaitForChild("PlayerGui")
		:WaitForChild("RTGui")
		:WaitForChild("codebase")
		:WaitForChild("ragdoll")
		:WaitForChild("Events")
		:WaitForChild("Toggle")
end)
if not ok then toggleRemote = nil end
local toggleArgs = { "R", false }

--==============================================================
-- CONFIG
--==============================================================
local SIDE_DISTANCE              = 44
local SAFE_DISTANCE              = 30
local GETUP_FIRE_DISTANCE        = 100

local SELFYEET_MIN_INTERVAL      = 0.01
local YEET_MIN_INTERVAL          = 0.25
local YEET_TRIGGER_DISTANCE      = 140
local MOVE_INTERVAL              = 0.005
local BACKSTEP_DISTANCE          = 30
local GETUP_SPAM_INTERVAL        = 0.05
local SWING_PRIORITY_THRESHOLD   = 0.50
local COMBO_INTERVAL             = 0.50

-- Predictive tuning
local SELFYEET_DASH_SPEED        = 120
local MAX_YEET_LEAD_TIME         = 0.50
local PREDICT_MIN_DIST           = 30
local LATERAL_LEAD_BIAS          = 1.0

-- Vulnerability windows
local VULN_DOT_THRESHOLD         = 0.55
local VULN_DIST_MIN              = 25
local VULN_DIST_MAX              = 60
local PREEMPT_SELFYEET_COOLDOWN  = 0.01
local SELFYEET_MIN_RANGE         = 60 -- don't selfyeet if this close

--==================== CAMERA (LOW + ALWAYS DOWN) ====================
local CAM_STICK_DISTANCE         = 70
local CAM_HEIGHT                 = 2
local CAM_SMOOTH_ALPHA           = 0.14
local BASE_DOWN_TILT             = 12
local AIR_DOWNWARD_AIM_OFFSET    = 60
local AIR_DOWNWARD_SELFYEET_BOOST= 25
--===================================================================

-- Safer-yeet anti-collision
local ENEMY_RECENT_SWING_TIME    = 0.45
local SAFETY_LATERAL_EVASION     = 10
local SAFETY_FORWARD_PULLBACK    = 6

--==================== SIDEWAYS FOOTWORK (ORBIT) =====================
local ORBIT_MIN_STEP             = 10
local ORBIT_MAX_STEP             = 24
local STRIKE_ARC_DEG             = 45
local STRIKE_CORRIDOR_WIDTH      = 12
local LATERAL_DRIVE_BIAS         = 1.25
local STUCK_TIME                 = 0.35
local STUCK_DIST_EPS             = 2.0
local REPULSE_WHEN_TOOCLOSE      = 18
local MOVE_TO_TIMEOUT            = 1.2
--====================================================================

--==================== ***GYRO LEAN + YAW OFFSET*** ==================
local HAND_INVERT                = true
local YAW_OFFSET_DEG             = 50      -- ±60° while striking (right hand -> +60°, left -> -60°)
local ROLL_LEAN_DEG              = 8       -- small roll so it's obvious; 0 to disable
local HAND_LEAN_TIME             = 0.60    -- lean window
--====================================================================

--==================== OLD HORIZONTAL ~70° LEAN (side shove) =========
local LEAN_ANGLE_DEG             = 50      -- horizontal movement angle versus forward
local LEAN_DIST_BASE             = 18
local LEAN_DIST_NEAR             = 30
local LEAN_FORWARD_PUSH          = 6
--====================================================================

--==================== SMART SELFYEET-BEHIND =========================
local BEHIND_RADIUS              = 36
local BEHIND_SIDE_OFFSET         = 18
local BEHIND_EXTRA_LEAD_TIME     = 0.20
local SWITCH_SIDE_COOLDOWN       = 0.15
local BEHIND_SCORE_FRONT_PENALTY = 1.6
local BEHIND_SCORE_SIDE_BONUS    = 0.25
--====================================================================

--==================== SMART CLOSE-IN WHEN BEHIND =====================
-- As "behindness" -> 1, shrink desired orbit radius to hit range.
local BEHIND_CLOSE_RADIUS_MIN    = 10      -- how close we want when fully behind
local BEHIND_CLOSE_RADIUS_MAX    = SAFE_DISTANCE + 12  -- normal orbit when not behind
local BACK_ENTRY_BOOST           = 8       -- extra pull forward when behind to secure hit
--====================================================================

--==============================================================
-- STATE / CONNECTIONS
--==============================================================
local RUNNING = true
local CONNS = {}
local function track(conn) if conn then table.insert(CONNS, conn) end; return conn end

--==============================================================
-- UI
--==============================================================
local gui = Instance.new("ScreenGui")
gui.Name = "WalkFlankGui"
gui.ResetOnSpawn = false
gui.Parent = LocalPlayer:WaitForChild("PlayerGui")

local statusLabel = Instance.new("TextLabel")
statusLabel.Size = UDim2.new(0, 1100, 0, 48)
statusLabel.Position = UDim2.new(0.5, -550, 0.86, 0)
statusLabel.BackgroundTransparency = 0.25
statusLabel.BackgroundColor3 = Color3.fromRGB(0, 0, 0)
statusLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
statusLabel.TextScaled = true
statusLabel.Font = Enum.Font.GothamMedium
statusLabel.Text = "Initializing..."
statusLabel.Parent = gui

--==============================================================
-- BodyGyro (full torque for roll/yaw) & Camera
--==============================================================
local gyro = Instance.new("BodyGyro")
gyro.MaxTorque = Vector3.new(1e7, 1e7, 1e7)
gyro.P = 6000
gyro.D = 300
gyro.CFrame = hrp.CFrame
gyro.Parent = hrp

local previousCameraType = camera.CameraType
camera.CameraType = Enum.CameraType.Scriptable
local currentCamCFrame = camera.CFrame

--==============================================================
-- TARGETING
--==============================================================
local selectedTargets, highlights, targetLastSwing = {}, {}, {}

local function makeHighlight(plr)
	if not plr.Character then return end
	local h = highlights[plr]
	if h and h.Parent then return end
	h = Instance.new("Highlight")
	h.Name = "TargetHighlight_" .. plr.Name
	h.FillTransparency = 1
	h.OutlineTransparency = 0.08
	h.OutlineColor = Color3.fromRGB(255, 240, 150)
	h.DepthMode = Enum.HighlightDepthMode.Occluded
	h.Parent = plr.Character
	highlights[plr] = h
end
local function removeHighlight(plr) local h = highlights[plr]; if h then h:Destroy() end; highlights[plr] = nil end
local function toggleTarget(plr)
	if not plr or plr == LocalPlayer then return end
	if not plr.Character or not plr.Character:FindFirstChild("HumanoidRootPart") then return end
	if selectedTargets[plr] then selectedTargets[plr] = nil; removeHighlight(plr)
	else selectedTargets[plr] = true; makeHighlight(plr) end
end
local function getPlayerFromInstance(inst)
	if not inst then return nil end
	local model = inst:FindFirstAncestorOfClass("Model")
	if not model then return nil end
	return Players:GetPlayerFromCharacter(model)
end
track(Mouse.Button1Down:Connect(function()
	if not RUNNING then return end
	if UserInputService:GetFocusedTextBox() then return end
	local plr = getPlayerFromInstance(Mouse.Target)
	if plr then toggleTarget(plr) end
end))
track(Players.PlayerAdded:Connect(function(plr)
	track(plr.CharacterAdded:Connect(function()
		if selectedTargets[plr] then task.wait(0.1); makeHighlight(plr) end
	end))
end))

--==============================================================
-- HELPERS
--==============================================================
local function safestChar()
	character = LocalPlayer.Character
	if not character then return end
	hrp = character:FindFirstChild("HumanoidRootPart")
	humanoid = character:FindFirstChildOfClass("Humanoid")
	return character and hrp and humanoid
end
local function getTargetsList()
	local list = {}
	for plr, v in pairs(selectedTargets) do
		if v and plr.Character and plr.Character:FindFirstChild("HumanoidRootPart") then
			table.insert(list, plr)
		end
	end
	return list
end
local function getClosestOfTargets()
	local best, bestDist
	local pos = hrp.Position
	for plr, v in pairs(selectedTargets) do
		if v and plr.Character and plr.Character:FindFirstChild("HumanoidRootPart") then
			local d = (plr.Character.HumanoidRootPart.Position - pos).Magnitude
			if not bestDist or d < bestDist then best, bestDist = plr, d end
		end
	end
	return best, bestDist
end
local function equipToolByName(name)
	local backpack = LocalPlayer:FindFirstChildOfClass("Backpack")
	if not backpack or not LocalPlayer.Character then return nil end
	local tool = LocalPlayer.Character:FindFirstChild(name) or backpack:FindFirstChild(name)
	if not tool then return nil end
	if tool.Parent ~= LocalPlayer.Character then tool.Parent = LocalPlayer.Character end
	return tool
end
local function activateToolLocal(tool) if tool and typeof(tool.Activate) == "function" then pcall(function() tool:Activate() end) end end

local function getHRPVelocity(part)
	if part and part:IsA("BasePart") then
		local okVel, vel = pcall(function() return part.AssemblyLinearVelocity end)
		if okVel and typeof(vel) == "Vector3" then return vel end
		return part.Velocity
	end
	return Vector3.zero
end

--==============================================================
-- PREDICTION & SAFETY
--==============================================================
local function predictTargetPosition(myPos, targetHRP, dashSpeed, extraLead)
	local targetPos = targetHRP.Position
	local toTarget = targetPos - myPos
	local dist = toTarget.Magnitude
	if dist < PREDICT_MIN_DIST then return targetPos end
	local toTargetUnit = toTarget.Unit
	local targetVel = getHRPVelocity(targetHRP)
	local radial = targetVel:Dot(toTargetUnit)
	local lateral = targetVel - toTargetUnit * radial
	local approxTime = math.clamp(dist / math.max(dashSpeed, 1), 0, MAX_YEET_LEAD_TIME + (extraLead or 0))
	return targetPos + lateral * approxTime * LATERAL_LEAD_BIAS + toTargetUnit * (radial * 0.25 * approxTime)
end

local function saferAdjust(predicted, targetHRP, enemyLastSwingTime)
	if not targetHRP then return predicted end
	local now = tick()
	local enemyMidSwing = enemyLastSwingTime and (now - enemyLastSwingTime) <= ENEMY_RECENT_SWING_TIME
	if not enemyMidSwing then return predicted end
	local enemyLook  = targetHRP.CFrame.LookVector
	local enemyRight = targetHRP.CFrame.RightVector
	local toPredUnit = (predicted - targetHRP.Position).Unit
	if math.abs(enemyLook:Dot(toPredUnit)) > 0.5 then
		predicted = predicted - enemyLook * SAFETY_FORWARD_PULLBACK
		predicted = predicted + enemyRight * ((math.random() < 0.5) and -SAFETY_LATERAL_EVASION or SAFETY_LATERAL_EVASION)
	end
	return predicted
end

--==============================================================
-- CAMERA (low + always down)
--==============================================================
local function smoothCameraTo(desired)
	currentCamCFrame = currentCamCFrame:Lerp(desired, CAM_SMOOTH_ALPHA)
	camera.CFrame = currentCamCFrame
end
local function aimCameraAtPoint(lookPoint, isSelfYeet)
	local myPos   = hrp.Position
	local state   = humanoid:GetState()
	local inAir   = (state == Enum.HumanoidStateType.Freefall) or (state == Enum.HumanoidStateType.Jumping)
	local extraDown = BASE_DOWN_TILT
	if inAir then extraDown = extraDown + AIR_DOWNWARD_AIM_OFFSET + (isSelfYeet and AIR_DOWNWARD_SELFYEET_BOOST or 0) end
	local flatDir = Vector3.new(lookPoint.X, myPos.Y, lookPoint.Z) - myPos
	if flatDir.Magnitude < 1e-3 then flatDir = hrp.CFrame.LookVector end
	local dirUnit = flatDir.Unit
	local camPos  = myPos - dirUnit * CAM_STICK_DISTANCE + Vector3.new(0, CAM_HEIGHT, 0)
	local desired = CFrame.new(camPos, lookPoint - Vector3.new(0, extraDown, 0))
	smoothCameraTo(desired)
end

--==============================================================
-- GYRO ORIENTATION (continuous; always face target with optional ±60° yaw + roll)
--==============================================================
local function yawRotate2D(v, rad)
	local c, s = math.cos(rad), math.sin(rad)
	return Vector3.new(v.X * c - v.Z * s, 0, v.X * s + v.Z * c)
end
local function cframeFacingWithYawAndRoll(pos, forwardFlatUnit, yawOffsetRad, rollRad)
	local f = yawRotate2D(forwardFlatUnit, yawOffsetRad)
	if f.Magnitude < 1e-3 then f = Vector3.new(0,0,-1) end
	f = f.Unit
	local upWorld = Vector3.new(0,1,0)
	local right = upWorld:Cross(f).Unit
	local up    = f:Cross(right).Unit
	if rollRad ~= 0 then
		local cr, sr = math.cos(rollRad), math.sin(rollRad)
		local r2 = right*cr + up*sr
		local u2 = f:Cross(r2).Unit
		right, up = r2, u2
	end
	return CFrame.fromMatrix(pos, right, up, -f)
end

--==============================================================
-- VULNERABILITY
--==============================================================
local function isSelfVulnerable(targetHRP)
	local toTarget = targetHRP.Position - hrp.Position
	local dist = toTarget.Magnitude
	if dist < VULN_DIST_MIN or dist > VULN_DIST_MAX then return false, dist end
	local toTargetUnit = toTarget.Unit
	local myRight = hrp.CFrame.RightVector
	local sideExposure = math.abs(myRight:Dot(toTargetUnit))
	return sideExposure >= VULN_DOT_THRESHOLD, dist
end

--==============================================================
-- SWING TRACKING
--==============================================================
local myLastSwingTime, mySwingActiveUntil = 0, 0
local myCurrentHandBias, myHandBiasUntil  = 0, 0 -- -1 left, +1 right

track(humanoid.AnimationPlayed:Connect(function(trackObj)
	if not RUNNING then return end
	if not trackObj or not trackObj.Animation or not trackObj.Animation.AnimationId then return end
	local animId = trackObj.Animation.AnimationId
	if animId == leftSwingAnimId or animId == rightSwingAnimId then
		myLastSwingTime    = tick()
		mySwingActiveUntil = myLastSwingTime + SWING_PRIORITY_THRESHOLD
		local handSign = (animId == rightSwingAnimId) and 1 or -1
		if HAND_INVERT then handSign = -handSign end
		myCurrentHandBias = handSign
		myHandBiasUntil   = myLastSwingTime + HAND_LEAN_TIME
	end
end))

local function hookEnemySwing(plr)
	if not plr or plr == LocalPlayer then return end
	if not plr.Character then return end
	local thum = plr.Character:FindFirstChildOfClass("Humanoid"); if not thum then return end
	if thum:FindFirstChild("_SwingHook") then return end
	local tag = Instance.new("BoolValue"); tag.Name = "_SwingHook"; tag.Parent = thum
	track(thum.AnimationPlayed:Connect(function(trackObj)
		if not RUNNING then return end
		if not trackObj or not trackObj.Animation or not trackObj.Animation.AnimationId then return end
		local animId = trackObj.Animation.AnimationId
		if animId == leftSwingAnimId or animId == rightSwingAnimId then
			targetLastSwing[plr] = tick()
		end
	end))
end
for _, plr in ipairs(Players:GetPlayers()) do
	if plr ~= LocalPlayer then
		if plr.Character then hookEnemySwing(plr) end
		track(plr.CharacterAdded:Connect(function() task.wait(0.05); if RUNNING then hookEnemySwing(plr) end end))
	end
end
track(Players.PlayerAdded:Connect(function(plr)
	if plr ~= LocalPlayer then
		track(plr.CharacterAdded:Connect(function() task.wait(0.05); if RUNNING then hookEnemySwing(plr) end end))
	end
end))

--==============================================================
-- SMART SELFYEET-BEHIND CHOOSER
--==============================================================
local lastSideChoice, lastSideTick = 0, 0 -- -1 left, +1 right

local function chooseSelfYeetBehindPoint(myPos, targetHRP)
	local basePred = predictTargetPosition(myPos, targetHRP, SELFYEET_DASH_SPEED, BEHIND_EXTRA_LEAD_TIME)
	local tCF = targetHRP.CFrame
	local tLook = tCF.LookVector
	local tRight = tCF.RightVector
	local tVel = getHRPVelocity(targetHRP)
	local lateralVel = tVel - tLook * tVel:Dot(tLook)

	local driftSign = (lateralVel:Dot(tRight) >= 0) and 1 or -1
	if tick() - lastSideTick > SWITCH_SIDE_COOLDOWN then
		lastSideChoice, lastSideTick = driftSign, tick()
	end

	local behind = basePred - tLook * BEHIND_RADIUS
	local candRight = behind + tRight * BEHIND_SIDE_OFFSET
	local candLeft  = behind - tRight * BEHIND_SIDE_OFFSET

	local function score(pt, sideSign)
		local toPt = (pt - basePred)
		local flatToPt = Vector3.new(toPt.X, 0, toPt.Z)
		if flatToPt.Magnitude < 1e-3 then return -math.huge end
		local unit = flatToPt.Unit
		local behindness = (-tLook):Dot(unit)
		local frontPenalty = math.max(0, tLook:Dot(unit)) * BEHIND_SCORE_FRONT_PENALTY
		local sideBonus = (sideSign == lastSideChoice) and BEHIND_SCORE_SIDE_BONUS or 0
		local myFwd = (pt - myPos); myFwd = Vector3.new(myFwd.X, 0, myFwd.Z)
		local approach = (myFwd.Magnitude > 0) and (myFwd.Unit:Dot(unit)) or 0
		return behindness - frontPenalty + sideBonus + 0.1*approach
	end

	local sRight = score(candRight,  1)
	local sLeft  = score(candLeft,  -1)
	local best = sRight >= sLeft and candRight or candLeft
	lastSideChoice = (sRight >= sLeft) and 1 or -1
	return best
end

--==============================================================
-- SELFYEET
--==============================================================
local lastSelfYeetTime, lastPreemptSelfYeet = 0, 0
local function canSelfYeet() return (tick() - lastSelfYeetTime) >= SELFYEET_MIN_INTERVAL end
local function trySelfYeetTo(point, isSelfYeet)
	if not canSelfYeet() then return false end
	aimCameraAtPoint(point, isSelfYeet)
	local tool = equipToolByName("SelfYeet")
	if tool then activateToolLocal(tool); lastSelfYeetTime = tick(); return true end
	return false
end
local function trySelfYeetPredictiveBehind(targetPlr)
	if not targetPlr or not targetPlr.Character or not targetPlr.Character:FindFirstChild("HumanoidRootPart") then return false end
	local targetHRP = targetPlr.Character.HumanoidRootPart
	local targetPoint = chooseSelfYeetBehindPoint(hrp.Position, targetHRP)
	targetPoint = saferAdjust(targetPoint, targetHRP, targetLastSwing[targetPlr])
	return trySelfYeetTo(targetPoint, true)
end

--==============================================================
-- COUNTER
--==============================================================
local function quickCounter()
	local tool = equipToolByName("Punch") or equipToolByName("Yeet")
	if tool then
		activateToolLocal(tool)
		myLastSwingTime = tick()
		mySwingActiveUntil = myLastSwingTime + SWING_PRIORITY_THRESHOLD
	end
end

--==============================================================
-- DIRECTION UTILITIES
--==============================================================
local function dirAtAngle(forwardFlatUnit, rightFlatUnit, sign, degrees)
	local rad = math.rad(math.clamp(degrees or 70, 0, 89.9))
	local d = forwardFlatUnit * math.cos(rad) + rightFlatUnit * (sign) * math.sin(rad)
	if d.Magnitude < 1e-3 then return forwardFlatUnit end
	return d.Unit
end

--==============================================================
-- SIDEWAYS FOOTWORK ENGINE (MoveTo orbits) + BACK-CLOSER LOGIC
--==============================================================
local activeWaypoint = nil
local lastProgressTime, lastProgressDist = 0, math.huge
local moving = false
local moveStartTick = 0

local function desiredOrbitRadiusFromBehindness(behindness)
	-- behindness in [0,1]: 0 = front, 1 = fully behind
	return BEHIND_CLOSE_RADIUS_MAX - (BEHIND_CLOSE_RADIUS_MAX - BEHIND_CLOSE_RADIUS_MIN) * math.clamp(behindness, 0, 1)
end

local function chooseOrbitWaypointSmart(myPos, targetHRP, preferSign)
	local tPos = targetHRP.Position
	local tCF  = targetHRP.CFrame
	local tLook = tCF.LookVector
	-- behindness: 1 when we're directly behind the target
	local vecTM = (myPos - tPos); vecTM = Vector3.new(vecTM.X, 0, vecTM.Z)
	local unitTM = (vecTM.Magnitude > 0) and vecTM.Unit or -tLook
	local behindness = math.max(0, (-tLook):Dot(unitTM)) -- [0..1]

	local desiredR = desiredOrbitRadiusFromBehindness(behindness)
	local f = (tPos - myPos); f = Vector3.new(f.X, 0, f.Z); if f.Magnitude < 1e-3 then f = Vector3.new(0,0,-1) end; f=f.Unit
	local r = Vector3.new(0,1,0):Cross(f).Unit

	local sign = preferSign
	if sign == 0 then
		local dotFacing = targetHRP.CFrame.RightVector:Dot(-(tPos - myPos).Unit)
		sign = (dotFacing > 0) and 1 or -1
	end

	-- lateral-biased drive, plus forward boost if we are behind (so we glide into the back more)
	local forwardBoost = BACK_ENTRY_BOOST * behindness
	local drive = (r * sign * LATERAL_DRIVE_BIAS + f + f * (forwardBoost / math.max(desiredR,1))).Unit

	-- step length adapts to distance; reduce step when we are nearly at desired radius
	local curR = (tPos - myPos).Magnitude
	local closenessToRing = math.abs(curR - desiredR)
	local stepBase = math.clamp(curR * 0.35, ORBIT_MIN_STEP, ORBIT_MAX_STEP)
	local step = stepBase * (closenessToRing > 6 and 1 or 0.6)

	local candidate = myPos + drive * step

	-- clamp to ring radius = desiredR (the "smart" ring)
	local v = candidate - tPos
	v = Vector3.new(v.X, 0, v.Z)
	if v.Magnitude > 1e-3 then
		candidate = tPos + v.Unit * desiredR
	end

	-- nudge toward strike corridor (hand-side 45° arc)
	local entryDir = (f + r * sign).Unit
	local angleToEntry = math.deg(math.acos(math.clamp(entryDir:Dot((candidate - tPos).Unit), -1, 1)))
	if angleToEntry > STRIKE_ARC_DEG then
		local toward = (entryDir + ((candidate - tPos).Unit))*0.5
		if toward.Magnitude > 0 then
			candidate = tPos + toward.Unit * (desiredR - STRIKE_CORRIDOR_WIDTH*0.25)
		end
	else
		candidate = candidate + entryDir * (STRIKE_CORRIDOR_WIDTH * 0.25)
	end

	return Vector3.new(candidate.X, myPos.Y, candidate.Z), behindness, desiredR
end

local function beginMoveTo(point)
	activeWaypoint = point
	moveStartTick = tick()
	lastProgressTime = moveStartTick
	lastProgressDist = (activeWaypoint - hrp.Position).Magnitude
	moving = true
	humanoid:MoveTo(activeWaypoint)
end
track(humanoid.MoveToFinished:Connect(function() moving = false end))

local function updateSidewaysController(targetHRP, preferSign)
	local now = tick()
	local myPos = hrp.Position
	if not activeWaypoint or not moving then
		local wp = chooseOrbitWaypointSmart(myPos, targetHRP, preferSign)
		beginMoveTo(wp)
		return
	end
	local distNow = (activeWaypoint - myPos).Magnitude
	if distNow + STUCK_DIST_EPS < lastProgressDist then
		lastProgressDist = distNow
		lastProgressTime = now
	end
	local tDist = (targetHRP.Position - myPos).Magnitude
	if tDist < SAFE_DISTANCE * 0.8 then
		local f = Vector3.new(targetHRP.Position.X - myPos.X, 0, targetHRP.Position.Z - myPos.Z).Unit
		beginMoveTo(myPos - f * REPULSE_WHEN_TOOCLOSE)
		return
	end
	if (now - moveStartTick) > MOVE_TO_TIMEOUT or (now - lastProgressTime) > STUCK_TIME then
		local wp = chooseOrbitWaypointSmart(myPos, targetHRP, preferSign)
		beginMoveTo(wp)
		return
	end
	if (now - moveStartTick) > 0.15 then
		local steer = chooseOrbitWaypointSmart(myPos, targetHRP, preferSign)
		activeWaypoint = activeWaypoint:Lerp(steer, 0.4)
		humanoid:MoveTo(activeWaypoint)
	end
end

--==============================================================
-- LOOP STATE
--==============================================================
local currentAction = "Yeet"
local lastActionTime = 0
local lastGetupTime = 0

--==============================================================
-- MAIN LOOP
--==============================================================
track(RunService.RenderStepped:Connect(function()
	if not RUNNING then return end
	if not safestChar() then return end

	local closestTarget, _ = getClosestOfTargets()
	if not closestTarget then
		statusLabel.Text = "No target selected. Click players to toggle targets."
		return
	end
	local tHRP = closestTarget.Character and closestTarget.Character:FindFirstChild("HumanoidRootPart")
	if not tHRP then statusLabel.Text = "Target invalid."; return end

	local myPos = hrp.Position
	local tPos  = tHRP.Position
	local toTarget = tPos - myPos
	local distanceToTarget = toTarget.Magnitude
	local toTargetUnit = (distanceToTarget > 0) and toTarget.Unit or hrp.CFrame.LookVector

	-- prefer side (hand) during swing window for orbiting & old lean
	local preferSign = 0
	if tick() <= myHandBiasUntil and myCurrentHandBias ~= 0 then
		preferSign = (myCurrentHandBias > 0) and 1 or -1
	end
	updateSidewaysController(tHRP, preferSign)

	-- ***OLD HORIZONTAL ~70° LEAN***: extra shove along ±70° when striking
	if tick() <= myHandBiasUntil and myCurrentHandBias ~= 0 then
		local fwdFlat = Vector3.new(toTargetUnit.X, 0, toTargetUnit.Z).Unit
		local rightFlat = Vector3.new(0,1,0):Cross(fwdFlat).Unit
		local leanDir = dirAtAngle(fwdFlat, rightFlat, (myCurrentHandBias>0) and 1 or -1, LEAN_ANGLE_DEG)
		local closeness = math.clamp((SAFE_DISTANCE + 20 - distanceToTarget) / 20, 0, 1)
		local leanDist = LEAN_DIST_BASE + (LEAN_DIST_NEAR - LEAN_DIST_BASE) * closeness
		local forcePoint = myPos + leanDir * leanDist + fwdFlat * LEAN_FORWARD_PUSH
		humanoid:MoveTo(forcePoint)
	end

	-- far -> predictive selfyeet ***behind*** (respect ≤90 rule)
	if distanceToTarget > math.max(SAFE_DISTANCE + 40, SELFYEET_MIN_RANGE + 1) then
		trySelfYeetPredictiveBehind(closestTarget)
	end

	-- camera (low + down)
	local fwdFlat = Vector3.new(toTargetUnit.X, 0, toTargetUnit.Z).Unit
	local camLook = myPos + fwdFlat * 5
	local camFrom = myPos - fwdFlat * CAM_STICK_DISTANCE + Vector3.new(0, CAM_HEIGHT, 0)
	local desiredCFrame = CFrame.new(camFrom, camLook - Vector3.new(0, BASE_DOWN_TILT, 0))
	currentCamCFrame = currentCamCFrame:Lerp(desiredCFrame, CAM_SMOOTH_ALPHA)
	camera.CFrame = currentCamCFrame

	-- ================== CONTINUOUS GYRO LEAN & FACING ==================
	-- Always face target; in strike window: apply ±60° yaw + small roll
	local yawOffset = 0
	local rollLean  = 0
	if tick() <= myHandBiasUntil and myCurrentHandBias ~= 0 then
		local sign = (myCurrentHandBias > 0) and 1 or -1
		yawOffset = math.rad(sign * YAW_OFFSET_DEG)
		rollLean  = math.rad(sign * ROLL_LEAN_DEG)
	end
	gyro.CFrame = cframeFacingWithYawAndRoll(hrp.Position, fwdFlat, yawOffset, rollLean)
	-- ===================================================================

	-- preempt selfyeet on exposure -> slip behind
	local selfVuln, _ = isSelfVulnerable(tHRP)
	if selfVuln and distanceToTarget > SELFYEET_MIN_RANGE and (tick() - lastPreemptSelfYeet) >= PREEMPT_SELFYEET_COOLDOWN then
		local behindPoint = chooseSelfYeetBehindPoint(myPos, tHRP)
		behindPoint = saferAdjust(behindPoint, tHRP, targetLastSwing[closestTarget])
		if trySelfYeetTo(behindPoint, true) then lastPreemptSelfYeet = tick() end
	end

	-- combo loop
	if distanceToTarget <= YEET_TRIGGER_DISTANCE then
		if tick() - lastActionTime >= COMBO_INTERVAL then
			local tool = equipToolByName(currentAction)
			if tool then
				activateToolLocal(tool)
				myLastSwingTime    = tick()
				mySwingActiveUntil = myLastSwingTime + SWING_PRIORITY_THRESHOLD
				myHandBiasUntil    = myLastSwingTime + HAND_LEAN_TIME
			end
			currentAction = (currentAction == "Yeet") and "Punch" or "Yeet"
			lastActionTime = tick()
		end
	end

	-- HUD
	local tLook = tHRP.CFrame.LookVector
	local behindnessVec = (myPos - tPos); behindnessVec = Vector3.new(behindnessVec.X,0,behindnessVec.Z)
	local behindness = 0
	if behindnessVec.Magnitude > 0 then
		behindness = math.max(0, (-tLook):Dot(behindnessVec.Unit))
	end
	statusLabel.Text = string.format(
		"Targets: %d | Focus: %s | Dist: %.1f | Behindness: %.2f | SelfYeet side: %s | Yaw±%d°",
		#(getTargetsList()), closestTarget.Name, distanceToTarget,
		behindness,
		(lastSideChoice==0 and "n/a" or (lastSideChoice>0 and "RIGHT" or "LEFT")),
		YAW_OFFSET_DEG
	)

	-- get-up spam
	if toggleRemote and distanceToTarget <= GETUP_FIRE_DISTANCE then
		if (tick() - lastGetupTime) >= GETUP_SPAM_INTERVAL then
			pcall(function() toggleRemote:FireServer(unpack(toggleArgs)) end)
			lastGetupTime = tick()
		end
	end
end))

--==============================================================
-- ENEMY-SWING REACTIVE
--==============================================================
local lastCheckedSwing = {}
track(RunService.RenderStepped:Connect(function()
	if not RUNNING then return end
	local now = tick()
	for plr, _ in pairs(selectedTargets) do
		repeat
			if not plr.Character then break end
			local root = plr.Character:FindFirstChild("HumanoidRootPart"); if not root then break end
			local t = targetLastSwing[plr]
			if not t or (lastCheckedSwing[plr] and t <= lastCheckedSwing[plr]) then break end
			lastCheckedSwing[plr] = t

			local dist = (root.Position - hrp.Position).Magnitude
			local iAmMidSwing = now <= mySwingActiveUntil
			local theyHitBeforeMe = not iAmMidSwing

			if theyHitBeforeMe then
				if dist > SELFYEET_MIN_RANGE then
					local pt = chooseSelfYeetBehindPoint(hrp.Position, root)
					pt = saferAdjust(pt, root, t)
					trySelfYeetTo(pt, true)
				else
					-- juke & counter
					local toward = (root.Position - hrp.Position); toward = Vector3.new(toward.X,0,toward.Z).Unit
					local rightFlat = Vector3.new(0,1,0):Cross(toward).Unit
					local sign = (math.random() < 0.5) and 1 or -1
					local juke = (toward + rightFlat * sign).Unit
					humanoid:MoveTo(hrp.Position + juke * 14)
					quickCounter()
				end
			else
				if dist <= SELFYEET_MIN_RANGE then quickCounter() end
			end
		until true
	end
end))

--==============================================================
-- CLEANUP (press X) & HAND MAP TOGGLE (H)
--==============================================================
local function cleanupAndDestroy()
	if not RUNNING then return end
	RUNNING = false
	for _, c in ipairs(CONNS) do pcall(function() c:Disconnect() end) end
	table.clear(CONNS)
	for plr,_ in pairs(highlights) do removeHighlight(plr) end
	table.clear(highlights); table.clear(selectedTargets); table.clear(targetLastSwing); table.clear(lastCheckedSwing)
	pcall(function() camera.CameraType = previousCameraType or Enum.CameraType.Custom end)
	pcall(function() if gui then gui:Destroy() end end)
	pcall(function() if gyro and gyro.Parent then gyro:Destroy() end end)
	pcall(function() script.Parent = nil end)
	pcall(function() Debris:AddItem(script, 0) end)
	pcall(function() script:Destroy() end)
end

track(UserInputService.InputBegan:Connect(function(input, processed)
	if processed then return end
	if input.KeyCode == Enum.KeyCode.X then
		cleanupAndDestroy()
	elseif input.KeyCode == Enum.KeyCode.H then
		HAND_INVERT = not HAND_INVERT
	end
end))

Features & Information

fighter bot, REQUIRES TITAN AND SELFYEET

Community Comments (1)

dacoder123dacoder123Jan 4, 2026

more scripts https://discord.gg/3mkMnE6N

More Scripts for Ragdoll Testing