Ai Slop Sonic
Key RequiredUniversal

Ai Slop Sonic

Universal ScriptKinjidamaKinjidama 3.6K views 2.9K executesUpdated Sep 28, 2025
5.0/ 5(1 votes)
10100% Positive
Lua Script•302 lines (9609 chars)
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local ContextActionService = game:GetService("ContextActionService")
local UserInputService = game:GetService("UserInputService")

local player = Players.LocalPlayer

-- === NERFED CONFIG ===
local baseMaxSpeed = 70
local topMaxSpeed = 120
local accel = 3
local speedBuildRate = 3
local speedDecayRate = 15
local boostMultiplier = 1.3
local boostKey = Enum.KeyCode.LeftShift
local jumpPower = 50
local tauntDuration = 1
local tauntCooldownTime = 1
local maxJumps = 2

local runAnimId   = "rbxassetid://85752365414182"
local jumpAnimId  = "rbxassetid://119889021060156"
local tauntAnimId = "rbxassetid://131991078572593"
local idleAnimId  = "rbxassetid://75752382380063"
local fakeDeathAnimId = "rbxassetid://82378425345026"  -- Updated fake death anim

local speed = 0
local currentMaxSpeed = baseMaxSpeed
local boostActive = false
local tauntCooldown = false
local jumpCount = 0

local humanoid, rootPart, character
local runTrack, jumpTrack, tauntTrack, idleTrack
local leftFootSmoke, rightFootSmoke, leftFootTrail, rightFootTrail

local fakeDeathTrack = nil
local isFakingDeath = false

local function createTrailAttachment(part, name, position)
	local a = Instance.new("Attachment")
	a.Name = name
	a.Position = position
	a.Parent = part
	return a
end

local function loadAnimations()
	local runAnim = Instance.new("Animation")
	runAnim.AnimationId = runAnimId
	runTrack = humanoid:LoadAnimation(runAnim)

	local jumpAnim = Instance.new("Animation")
	jumpAnim.AnimationId = jumpAnimId
	jumpTrack = humanoid:LoadAnimation(jumpAnim)
	jumpTrack.Looped = true

	local tauntAnim = Instance.new("Animation")
	tauntAnim.AnimationId = tauntAnimId
	tauntTrack = humanoid:LoadAnimation(tauntAnim)

	local idleAnim = Instance.new("Animation")
	idleAnim.AnimationId = idleAnimId
	idleTrack = humanoid:LoadAnimation(idleAnim)
end

local function doTaunt()
	if tauntCooldown then return end
	tauntCooldown = true
	if runTrack.IsPlaying then runTrack:Stop() end
	if idleTrack.IsPlaying then idleTrack:Stop() end
	if jumpTrack.IsPlaying then jumpTrack:Stop() end
	tauntTrack:Play()

	task.delay(tauntDuration, function()
		tauntTrack:Stop()
		if speed <= 0 then idleTrack:Play() else runTrack:Play() end
	end)

	task.delay(tauntCooldownTime, function()
		tauntCooldown = false
	end)
end

local function getSlopeNormal()
	local params = RaycastParams.new()
	params.FilterDescendantsInstances = {character}
	params.FilterType = Enum.RaycastFilterType.Blacklist
	local result = workspace:Raycast(rootPart.Position, Vector3.new(0, -5, 0), params)
	return result and result.Normal or Vector3.new(0, 1, 0)
end

local function setupVFX()
	local leftFoot = character:FindFirstChild("LeftFoot") or character:FindFirstChild("Left Leg")
	local rightFoot = character:FindFirstChild("RightFoot") or character:FindFirstChild("Right Leg")
	if not (leftFoot and rightFoot) then return end

	local function makeSmoke(parent)
		local e = Instance.new("ParticleEmitter")
		e.Enabled = false
		e.Texture = "rbxassetid://7712212245"
		e.Lifetime = NumberRange.new(0.5, 1)
		e.Speed = NumberRange.new(0.5, 1)
		e.Size = NumberSequence.new({NumberSequenceKeypoint.new(0, 2), NumberSequenceKeypoint.new(1, 0)})
		e.Transparency = NumberSequence.new(0.1, 1)
		e.RotSpeed = NumberRange.new(-50, 50)
		e.SpreadAngle = Vector2.new(45, 45)
		e.Rate = 20
		e.Parent = parent
		return e
	end

	leftFootSmoke = makeSmoke(leftFoot)
	rightFootSmoke = makeSmoke(rightFoot)

	local leftStart  = createTrailAttachment(leftFoot, "TrailStart", Vector3.new(0, 0.3, 0))
	local leftEnd    = createTrailAttachment(leftFoot, "TrailEnd",   Vector3.new(0, -0.3, -0.5))
	local rightStart = createTrailAttachment(rightFoot, "TrailStart",Vector3.new(0, 0.3, 0))
	local rightEnd   = createTrailAttachment(rightFoot, "TrailEnd",  Vector3.new(0, -0.3, -0.5))

	leftFootTrail = Instance.new("Trail")
	leftFootTrail.Attachment0 = leftStart
	leftFootTrail.Attachment1 = leftEnd
	leftFootTrail.Enabled = false
	leftFootTrail.Texture = "rbxassetid://13211689684"
	leftFootTrail.TextureLength = 5
	leftFootTrail.Lifetime = 0.2
	leftFootTrail.LightEmission = 1
	leftFootTrail.Transparency = NumberSequence.new(0.3, 1)
	leftFootTrail.Parent = leftFoot

	rightFootTrail = Instance.new("Trail")
	rightFootTrail.Attachment0 = rightStart
	rightFootTrail.Attachment1 = rightEnd
	rightFootTrail.Enabled = false
	rightFootTrail.Texture = "rbxassetid://13211689684"
	rightFootTrail.TextureLength = 5
	rightFootTrail.Lifetime = 0.2
	rightFootTrail.LightEmission = 1
	rightFootTrail.Transparency = NumberSequence.new(0.3, 1)
	rightFootTrail.Parent = rightFoot
end

local function doAirJump()
	local vel = rootPart.Velocity
	rootPart.Velocity = Vector3.new(vel.X, jumpPower, vel.Z)
	jumpTrack:Stop()
	jumpTrack:Play()
end

local function toggleFakeDeath(actionName, inputState, inputObject)
	if inputState == Enum.UserInputState.Begin then
		if not isFakingDeath then
			fakeDeathTrack:Play()
			isFakingDeath = true
		else
			fakeDeathTrack:Stop()
			isFakingDeath = false
		end
	end
end

local function setupCharacter(char)
	character = char
	humanoid  = char:WaitForChild("Humanoid")
	rootPart  = char:WaitForChild("HumanoidRootPart")

	speed = 0
	currentMaxSpeed = baseMaxSpeed
	boostActive = false
	tauntCooldown = false
	jumpCount = 0

	loadAnimations()
	idleTrack:Play()
	setupVFX()

	local fakeDeathAnim = Instance.new("Animation")
	fakeDeathAnim.AnimationId = fakeDeathAnimId
	fakeDeathTrack = humanoid:LoadAnimation(fakeDeathAnim)
	isFakingDeath = false

	humanoid.Jumping:Connect(function(active)
		if active and not tauntCooldown then
			jumpCount += 1
			if runTrack.IsPlaying then runTrack:Stop() end
			if idleTrack.IsPlaying then idleTrack:Stop() end
			if not jumpTrack.IsPlaying then jumpTrack:Play() end
		end
	end)

	humanoid.StateChanged:Connect(function(_, newState)
		local onGround = (
			newState == Enum.HumanoidStateType.Landed or
			newState == Enum.HumanoidStateType.Running or
			newState == Enum.HumanoidStateType.RunningNoPhysics
		)
		if onGround then
			jumpCount = 0
			if jumpTrack.IsPlaying then jumpTrack:Stop() end
			if speed > 0 then runTrack:Play() else idleTrack:Play() end
		end
	end)

	ContextActionService:BindAction("FakeDeathToggle", toggleFakeDeath, true, Enum.KeyCode.F)
	ContextActionService:SetTitle("FakeDeathToggle", "Fake Death")
	ContextActionService:SetPosition("FakeDeathToggle", UDim2.new(0.75, 0, 0.85, 0))
	ContextActionService:SetImage("FakeDeathToggle", fakeDeathAnimId) -- Use the animation for button icon
end

UserInputService.JumpRequest:Connect(function()
	if not humanoid then return end
	local state = humanoid:GetState()
	local onGround = (
		state == Enum.HumanoidStateType.Running or
		state == Enum.HumanoidStateType.RunningNoPhysics or
		state == Enum.HumanoidStateType.Landed
	)
	if not onGround and jumpCount < maxJumps then
		jumpCount += 1
		doAirJump()
	end
end)

RunService.Heartbeat:Connect(function(dt)
	if not humanoid or not rootPart then return end

	local moveDir = humanoid.MoveDirection
	local state = humanoid:GetState()
	local onGround = (
		state == Enum.HumanoidStateType.Running or
		state == Enum.HumanoidStateType.RunningNoPhysics or
		state == Enum.HumanoidStateType.Landed
	)

	if moveDir.Magnitude > 0 then
		if boostActive then
			if leftFootSmoke then leftFootSmoke.Enabled = true end
			if rightFootSmoke then rightFootSmoke.Enabled = true end
			if leftFootTrail then leftFootTrail.Enabled = true end
			if rightFootTrail then rightFootTrail.Enabled = true end
		else
			if leftFootSmoke then leftFootSmoke.Enabled = false end
			if rightFootSmoke then rightFootSmoke.Enabled = false end
			if leftFootTrail then leftFootTrail.Enabled = false end
			if rightFootTrail then rightFootTrail.Enabled = false end
		end

		if boostActive then
			currentMaxSpeed = math.min(currentMaxSpeed + speedBuildRate * dt, topMaxSpeed)
			currentMaxSpeed = math.max(currentMaxSpeed, baseMaxSpeed)
		else
			currentMaxSpeed = math.min(currentMaxSpeed + speedBuildRate * dt, baseMaxSpeed)
		end

		local targetMax = boostActive and topMaxSpeed or baseMaxSpeed

		local slopeNormal = getSlopeNormal()
		local slopeMoveDir = (moveDir - slopeNormal * moveDir:Dot(slopeNormal)).Unit
		speed = math.min(speed + accel * dt * 60, targetMax)

		if onGround and not runTrack.IsPlaying and not tauntCooldown then
			idleTrack:Stop()
			runTrack:Play()
		end

		humanoid.WalkSpeed = speed
		rootPart.Velocity = slopeMoveDir * speed + Vector3.new(0, rootPart.Velocity.Y, 0)

	else
		speed = 0
		currentMaxSpeed = math.max(currentMaxSpeed - speedDecayRate * dt, baseMaxSpeed)

		if runTrack.IsPlaying then runTrack:Stop() end
		if leftFootSmoke then leftFootSmoke.Enabled = false end
		if rightFootSmoke then rightFootSmoke.Enabled = false end
		if leftFootTrail then leftFootTrail.Enabled = false end
		if rightFootTrail then rightFootTrail.Enabled = false end

		if onGround and not idleTrack.IsPlaying and not tauntCooldown then
			idleTrack:Play()
		end

		humanoid.WalkSpeed = 0
		rootPart.Velocity = Vector3.new(0, rootPart.Velocity.Y, 0)
	end
end)

ContextActionService:BindAction("Taunt", function(_, state)
	if state == Enum.UserInputState.Begin then doTaunt() end
end, true, Enum.KeyCode.T)

ContextActionService:BindAction("Boost", function(_, state)
	if state == Enum.UserInputState.Begin then
		boostActive = true
	elseif state == Enum.UserInputState.End then
		boostActive = false
	end
end, true, boostKey)

player.CharacterAdded:Connect(setupCharacter)
if player.Character then setupCharacter(player.Character) end

Features & Information

Like that slop retro flinger script I made but for sonic fans
#Sonic#I love gooning

Community Comments (0)

No comments yet for this script.

More Scripts for Universal Scripts