CCCPaste

Battlegrounds - Dash (35)

local ContextActionService = game:GetService("ContextActionService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local UserInputService = game:GetService("UserInputService")
local Workspace = game:GetService("Workspace")
local RunService = game:GetService("RunService")

local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local HitboxModule = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("HitboxModule"))

local OnCooldown = false
local CooldownDuration = 1.5

local DashSpeed = 60
local DashDuration = 0.3
local DashRange = 8

local CurrentCharName = nil
local CurrentCharInfo = nil

Remotes.ChangeCharacter.OnClientEvent:Connect(function(CharInfo)
	CurrentCharName = CharInfo.Name
	CurrentCharInfo = CharInfo
end)

local DashKeys = { Enum.KeyCode.E }

local HeldKeys = { W = false, A = false, S = false, D = false }

local DashMobileButton
local MobileButtonImage = `rbxassetid://16086340003`
local MobileButtonPosition = UDim2.new(1, -125, 1, -125)
local NormalImageColor = Color3.fromRGB(0, 0, 0)
local CooldownImageColor = Color3.fromRGB(51, 51, 51)

local DashFOVIncrease = 15
local DefaultFOV

local DashActionName = "DASH_ACTION"

local Camera = Workspace.CurrentCamera
DefaultFOV = Camera.FieldOfView

local Character = script.Parent
local RootPart: BasePart = Character:WaitForChild("HumanoidRootPart")
local Humanoid: Humanoid = Character:WaitForChild("Humanoid")
local Animator: Animator = Humanoid:WaitForChild("Animator")

local Attachment = Instance.new("Attachment")
Attachment.Name = "DashAttachment0"
Attachment.Parent = RootPart

local LinearVelocity = Instance.new("LinearVelocity")
LinearVelocity.Attachment0 = Attachment
LinearVelocity.VelocityConstraintMode = Enum.VelocityConstraintMode.Plane
LinearVelocity.PrimaryTangentAxis = Vector3.new(1, 0, 0)
LinearVelocity.SecondaryTangentAxis = Vector3.new(0, 0, 1)
LinearVelocity.MaxForce = math.huge
LinearVelocity.Enabled = false
LinearVelocity.Parent = RootPart

local DashSound = script:WaitForChild("DashSound")
DashSound.Parent = RootPart

local DashForwardAnim = Animator:LoadAnimation(script:WaitForChild("DashForward"))
local DashLeftAnim = Animator:LoadAnimation(script:WaitForChild("DashLeft"))
local DashBackAnim = Animator:LoadAnimation(script:WaitForChild("DashBack"))
local DashRightAnim = Animator:LoadAnimation(script:WaitForChild("DashRight"))

local RaycastParameters = RaycastParams.new()
RaycastParameters.FilterDescendantsInstances = { Character }
RaycastParameters.FilterType = Enum.RaycastFilterType.Exclude

function Lerp(A: number, B: number, T: number)
	return A + (B - A) * T
end

function IsDashAllowed(ActionName: string, InputState: Enum.UserInputState)
	if OnCooldown then return false end
	if ActionName ~= DashActionName then return false end
	if InputState ~= Enum.UserInputState.Begin then return false end
	if Character:GetAttribute("CanDash") == false then return false end

	return true
end

function GetDashVelocity()
	local VectorMask = Vector3.new(1, 0, 1)
	local Direction = RootPart.AssemblyLinearVelocity * VectorMask

	if Direction.Magnitude <= 0.1 then
		Direction = Camera.CFrame.LookVector * VectorMask
	end

	Direction = Direction.Unit
	local PlaneDirection = Vector2.new(Direction.X, Direction.Z)

	local DashVelocity = PlaneDirection * DashSpeed

	return DashVelocity
end

function PlayDashAnimation()
	DashForwardAnim:Stop()
	DashLeftAnim:Stop()
	DashRightAnim:Stop()
	DashBackAnim:Stop()

	if UserInputService.MouseBehavior ~= Enum.MouseBehavior.LockCenter then
		DashForwardAnim:Play()
		return
	end

	if HeldKeys.W then
		DashForwardAnim:Play()
		return

	elseif HeldKeys.A then
		DashLeftAnim:Play()
		return

	elseif HeldKeys.S then
		DashRightAnim:Play()
		return

	elseif HeldKeys.D then
		DashBackAnim:Play()
		return
	end

	DashForwardAnim:Play()
end

function HandleCooldown()
	if DashMobileButton then
		DashMobileButton.ImageColor3 = CooldownImageColor
	end

	local CooldownStarted = tick()
	local LastTick = tick()

	while tick() - CooldownStarted < CooldownDuration do
		RunService.PostSimulation:Wait()

		local DeltaTime = tick() - LastTick
		LastTick = tick()

		local StartFOV
		if LinearVelocity.Enabled == false then
			if Camera.FieldOfView > DefaultFOV then
				if not StartFOV then
					StartFOV = Camera.FieldOfView
				end

				local LerpAmount = DeltaTime * 10
				local NewFOV = Lerp(StartFOV, DefaultFOV, LerpAmount)

				Camera.FieldOfView = NewFOV
			end
		end
	end

	Camera.FieldOfView = DefaultFOV

	if DashMobileButton then
		DashMobileButton.ImageColor3 = NormalImageColor
	end

	OnCooldown = false
end

function HandleDashDuration()
	local DashStarted = tick()
	local StartFOV = Camera.FieldOfView
	local GoalFOV = DefaultFOV + DashFOVIncrease
	local LastTick = tick()

	while tick() - DashStarted < DashDuration do
		RunService.PostSimulation:Wait()

		if Camera.FieldOfView < GoalFOV then
			local DeltaTime = tick() - LastTick
			LastTick = tick()

			local LerpAmount = DeltaTime * 20
			local NewFOV = Lerp(Camera.FieldOfView, GoalFOV, LerpAmount)

			Camera.FieldOfView = NewFOV
		end

		if IsDashBlocked() then
			break
		end
	end
end

function IsDashBlocked()
	local RayOrigin = RootPart.Position
	local RayDirection = RootPart.CFrame.LookVector
	local RayDepth = DashRange

	local Raycast = Workspace:Raycast(RayOrigin, RayDirection * RayDepth, RaycastParameters)

	if Raycast and Raycast.Instance.CanCollide and Raycast.Instance.Anchored then
		return true
	end
end

function DashEffects()
	DashSound:Play()
end

function EnableLinearVelocity(DashVelocity: Vector2)
	LinearVelocity.PlaneVelocity = DashVelocity
	LinearVelocity.Enabled = true

	RootPart.CFrame = CFrame.new(RootPart.Position, Vector3.new(DashVelocity.X, 0, DashVelocity.Y * 1000))
end

function DisableLinearVelocity()
	LinearVelocity.Enabled = false
end

task.delay(0, function()
	if not CurrentCharInfo then
		local SelectedChar, CharDataTable = Remotes.GetCharacterInfo:InvokeServer()

		if SelectedChar and CharDataTable then
			CurrentCharName = SelectedChar
			CurrentCharInfo = CharDataTable
		end
	end
end)

function Dash(ActionName: string, InputState: Enum.UserInputState)
	if DashMobileButton then
		DashMobileButton.Image = MobileButtonImage
	end

	if IsDashAllowed(ActionName, InputState) then
		if CurrentCharInfo == nil then
			return
		end

		if Humanoid and Humanoid.Health <= 0 then
			return
		end
		
		OnCooldown = true
		task.spawn(HandleCooldown)

		PlayDashAnimation()

		local DashVelocity = GetDashVelocity()
		EnableLinearVelocity(DashVelocity)
		DashEffects()
		HandleDashDuration()
		DisableLinearVelocity()
		
		task.wait(0.3)

		Remotes.Attack:FireServer(1, "Normal")
	end
end

ContextActionService:BindAction(DashActionName, Dash, true, unpack(DashKeys))

DashMobileButton = ContextActionService:GetButton(DashActionName)

if DashMobileButton then
	DashMobileButton.Image = MobileButtonImage
	DashMobileButton.ImageColor3 = NormalImageColor
	DashMobileButton.Position = MobileButtonPosition
end

UserInputService.InputBegan:Connect(function(Input: InputObject, GameProcessedEvent: boolean)
	if not GameProcessedEvent then
		if Input.KeyCode == Enum.KeyCode.W then
			HeldKeys.W = true
		elseif Input.KeyCode == Enum.KeyCode.S then
			HeldKeys.S = true
		elseif Input.KeyCode == Enum.KeyCode.A then
			HeldKeys.A = true
		elseif Input.KeyCode == Enum.KeyCode.D then
			HeldKeys.D = true
		end
	end
end)

UserInputService.InputEnded:Connect(function(Input: InputObject, GameProcessedEvent: boolean)
	if not GameProcessedEvent then
		if Input.KeyCode == Enum.KeyCode.W then
			HeldKeys.W = false
		elseif Input.KeyCode == Enum.KeyCode.S then
			HeldKeys.S = false
		elseif Input.KeyCode == Enum.KeyCode.A then
			HeldKeys.A = false
		elseif Input.KeyCode == Enum.KeyCode.D then
			HeldKeys.D = false
		end
	end
end)