Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local attackHandler = {}
- type table = {[any]: any} -- defines the table type since roblox doesnt have a build in type for it
- local RepStorage = game.ReplicatedStorage
- local ServerStorage = game:GetService("ServerStorage")
- local Keybinds = require(RepStorage.Keybinds)
- local Moves = Keybinds.Moves
- local SFXFolder
- if ServerStorage and ServerStorage:FindFirstChild("SFX") then
- SFXFolder = ServerStorage.SFX -- since this script can be used both locally and by the server, if you are accessing this locally it will error if you do serverstorage:findfirstchild so i make an if statement to prevent erroring
- end
- local Players = game.Players
- --Remotes
- local Remotes = RepStorage.Remotes
- -- Move Classes
- local BoxerMoves = Moves.Boxer
- attackHandler.ActivateIFrames = function(character: Model, length: number)
- character:SetAttribute("IFrames", os.clock() + length)
- end
- attackHandler.DoKnockback = function(selfCharacter: Model, hitCharacter: Model, move: table, combo: number, val: number) -- knockback for moves and stuff
- local linearVelocity = Instance.new("LinearVelocity")
- local attachment = Instance.new("Attachment")
- attachment.Name = "VelocityAttachment"
- linearVelocity.Attachment0 = attachment
- attachment.Parent = hitCharacter.HumanoidRootPart
- linearVelocity.Parent = hitCharacter.HumanoidRootPart
- local direction = selfCharacter.HumanoidRootPart.CFrame.LookVector
- linearVelocity.MaxForce = 100000
- linearVelocity.VectorVelocity = direction * move.Knockback[combo] * val
- task.defer(function()
- task.wait(move.KnockbackTime[combo])
- linearVelocity:Destroy()
- attachment:Destroy()
- end)
- end
- attackHandler.JabVFX = function(character: Model, combo: number, moveLength: number, isBlocked: boolean) -- you need the character that is commencing the move, combo like move 1 or 2, movelength, and checking for whether the move has been blocked or not already provided
- local VFX -- so basically for the moves i go into the keybinds module which has the vfx saved like for example ReplicatedStorage.VFXFolder.JabVFX and there are big and small versions. if the move is blocked i make the move's VFX smaller cuz the moves VFX are too big and it'll hide the VFX for the block. the block has VFX and you cant see it if a giant jab VFX is showing
- if isBlocked then
- VFX = BoxerMoves.Jab.VFX.Small:Clone()
- else
- VFX = BoxerMoves.Jab.VFX:Clone()
- end -- determines whether to use the small vfx or big one
- local offset = BoxerMoves.Jab.VFXOffset[combo] -- you cant just put the VFX at the humanoidRootPart's position and you have to put it at the arm so you do HRP.CFrame * offset to find the arm's position and there are two offsets since you use two different arms for the jab
- local hrp = character:WaitForChild("HumanoidRootPart"):: BasePart
- for i, v in VFX:GetChildren() do
- if not v:IsA("BasePart") then continue end
- v.CFrame = hrp.CFrame * offset -- the attachments are obviously in a basepart and stuff light lighting blocks and stuff shouldnt be :emit()
- end
- VFX.Parent = workspace
- local darkEmitter = VFX.Dark.Attachment.ParticleEmitter:: ParticleEmitter
- for i, v in VFX.Dust.Punch:GetChildren() do
- v:Emit(2)
- end
- for i, v in VFX.Hit.Attachment:GetChildren() do
- if v:IsA("ParticleEmitter") then v:Emit(1) else v.Enabled = true end
- end
- darkEmitter:Emit(2)
- game.Debris:AddItem(VFX, 0.7)
- end
- attackHandler.BoxerBlockFX = function(character: Model)
- local VFX = BoxerMoves.Block.VFX.Block:Clone()
- local offset = BoxerMoves.Block.VFXOffset[1]
- local hrp = character.HumanoidRootPart:: BasePart
- VFX.CFrame = hrp.CFrame * offset
- VFX.Parent = workspace
- for i, v in VFX.Main:GetChildren() do
- v:Emit(1)
- end
- game.Debris:AddItem(VFX, 2)
- end
- attackHandler.BoxerBlockBreakFX = function(character: Model)
- local VFX = BoxerMoves.Block.VFX.BlockBreak:Clone()
- local Attachment = VFX.Main
- local offset = BoxerMoves.Block.VFXOffset[2]
- local hrp = character.HumanoidRootPart:: BasePart
- VFX.CFrame = hrp.CFrame * offset
- VFX.Parent = workspace
- Attachment.Specs:Emit(70)
- Attachment.Shockwave:Emit(1)
- Attachment.Sharp:Emit(50)
- task.wait(0.15)
- Attachment.Shockwave:Emit(1)
- game.Debris:AddItem(VFX, 2)
- end
- local JabDebounce = {}
- attackHandler.Jab = function(entity: Player | Model, combo: number, moveLength: number, ...: any) -- actual jab move for the boxer class
- local character
- if entity:IsA("Player") then -- using entity since both NPCs and players can use moves, i couldnt think of a better name
- character = entity.Character
- else
- character = entity
- end -- if its a player it does player.character and if its an NPC itll just set character to the actual entity itself
- local move = BoxerMoves.Jab
- if table.find(JabDebounce, character.Name) then
- return -- makes sure there isnt a debounce. i put a debounce both locally and server sides because exploiters prevention
- else
- table.insert(JabDebounce, character.Name)
- task.delay(move.SelfCooldown[combo], function()
- if JabDebounce[table.find(JabDebounce, character.Name)] then JabDebounce[table.find(JabDebounce, character.Name)] = nil end
- end)
- end
- local attackEnds = os.clock() + moveLength -- when does the attack end
- --local hitboxSize = Vector3.new(3.5, 4.5, 3)
- local hitboxSize = move.HitboxSize[combo] -- hitbox size is in keybinds module
- character:SetAttribute("LastCombat", os.clock()) -- for blockbar regeneration, this attribute is for when the player was last in combat
- local HRP = character.HumanoidRootPart:: BasePart
- local Params = OverlapParams.new() -- so i use spatial query instead of direct query since its a jab and no sword and stuff is used so i dont need to be precise and i can just throw out a hitbox and everything will be fine
- Params.FilterType = Enum.RaycastFilterType.Exclude
- Params.FilterDescendantsInstances = {character}
- --SFX below
- local MovesFXFolder = SFXFolder[move.Class][move.Name]
- local currentSFX = MovesFXFolder:FindFirstChild(math.random(1, #MovesFXFolder:GetChildren())):Clone()
- currentSFX.Parent = character.HumanoidRootPart
- currentSFX:Destroy() -- plays when removed
- --SFX end
- local HitboxOffset = move.HitboxOffset[combo]
- --HitboxOffset = CFrame.new(0,0,0)
- ----[[
- local hitboxVisualizer -- there is a !hitbox command in chat, if you put it the hitboxvisualizer.transparency will be 0
- if character:GetAttribute("Hitbox") then
- hitboxVisualizer = Instance.new("Part")
- hitboxVisualizer.Size = hitboxSize
- hitboxVisualizer.Transparency = 0.7
- hitboxVisualizer.Color = Color3.new(1, 0, 0)
- hitboxVisualizer.Anchored = true
- hitboxVisualizer.CanCollide = false
- hitboxVisualizer.Parent = workspace
- hitboxVisualizer.CFrame = HRP.CFrame * HitboxOffset
- game.Debris:AddItem(hitboxVisualizer, move.Length[combo])
- end
- --]]
- local parts
- local MaxHits = 0
- local CharactersHit = {}
- local AnimReactions = ServerStorage.AnimationReactions
- local ClassReactions = AnimReactions:FindFirstChild(move.Class)
- local isBlocking = false
- task.spawn(function()
- repeat
- parts = workspace:GetPartBoundsInBox(HRP.CFrame * HitboxOffset, hitboxSize, Params) -- all the parts that was
- if hitboxVisualizer then hitboxVisualizer.CFrame = HRP.CFrame * HitboxOffset end
- for i, v in parts do
- if not v.Parent:FindFirstChildWhichIsA("Humanoid") then continue end
- if table.find(CharactersHit, v.Parent) then continue end
- if MaxHits == move.MaxHits then continue end
- MaxHits += 1
- table.insert(CharactersHit, v.Parent)
- if v.Parent:GetAttribute("IFrames") and v.Parent:GetAttribute("IFrames") > os.clock() then continue end
- local humanoid = v.Parent:FindFirstChildWhichIsA("Humanoid"):: Humanoid
- local animator = humanoid.Animator:: Animator
- local reaction
- v.Parent:SetAttribute("LastCombat", os.clock())
- if v.Parent:GetAttribute("Blocking") then
- isBlocking = true
- attackHandler.DoKnockback(character, v.Parent, move, combo, 0.2)
- humanoid:TakeDamage(move.Damage[combo]*0.1)
- local CurrentBlockBar = v.Parent:GetAttribute("BlockBar")
- local BlockBarDMG = move.BlockBarDamage[combo]
- v.Parent:SetAttribute("BlockBar", CurrentBlockBar + BlockBarDMG)
- warn("BLOCKBAR IS:",v.Parent:GetAttribute("BlockBar"))
- local blockBroken = false
- if v.Parent:GetAttribute("BlockBar") >= 100 then
- v.Parent:SetAttribute("BlockBar", 100)
- v.Parent:SetAttribute("Cooldown", os.clock() + 5)
- v.Parent:SetAttribute("BlockBroken", true)
- local enemyPlayer = game.Players:GetPlayerFromCharacter(v.Parent)
- if enemyPlayer then
- Remotes.BlockBroken:FireClient(enemyPlayer)
- end
- Remotes.VFX:FireAllClients(v.Parent, "BoxerBlockBroken")
- task.spawn(function()
- blockBroken = true
- v.Parent:SetAttribute("BlockBar", 0)
- local BlockBarTransitionAnim = AnimReactions:FindFirstChild(move.Class).BlockBreak:: Animation -- so this is basically the animations for it. first when your block breaks you do a little beginning animation then you do another animation which is set to looped and you stay there for 5 seconds
- local BlockBarTransition = animator:LoadAnimation(BlockBarTransitionAnim)
- local StunAnim = AnimReactions:FindFirstChild(move.Class).BlockStun:: Animation
- local Stun = animator:LoadAnimation(StunAnim)
- BlockBarTransition.Priority = Enum.AnimationPriority.Action4
- Stun.Priority = Enum.AnimationPriority.Action4
- BlockBarTransition:Play()
- BlockBarTransition.Stopped:Wait()
- Stun:Play()
- v.Parent:SetAttribute("Blocking", false)
- repeat
- v.Parent.Humanoid.WalkSpeed = 0
- until v.Parent.Humanoid.WalkSpeed == 0
- task.wait(5)
- v.Parent.Humanoid.WalkSpeed = 16
- v.Parent:SetAttribute("BlockBroken", false)
- print("walkspeed set")
- Stun:Stop()
- end)
- end
- task.wait()
- if blockBroken then return end
- Remotes.VFX:FireAllClients(v.Parent, "BoxerBlock") -- server client replication for vfx
- reaction = animator:LoadAnimation(ClassReactions:FindFirstChild("BlockHit"))
- reaction.Priority = Enum.AnimationPriority.Action2
- else
- attackHandler.DoKnockback(character, v.Parent, move, combo, 1)
- humanoid:TakeDamage(move.Damage[combo])
- reaction = animator:LoadAnimation(ClassReactions:FindFirstChild(move.Name..tostring(combo)))
- reaction.Priority = Enum.AnimationPriority.Action2
- end
- reaction:Play()
- v.Parent:SetAttribute("Stun", os.clock() + move.Stun[combo])
- end
- task.wait()
- until os.clock() >= attackEnds
- end)
- if isBlocking then
- local OGWalkspeed = character.Humanoid.WalkSpeed
- character.Humanoid.WalkSpeed = 8
- task.delay(moveLength, function()
- Remotes.VFX:FireAllClients(character, move.Name.."Small", combo, moveLength)
- task.wait(0.3)
- character.Humanoid.WalkSpeed = OGWalkspeed -- ignore this i added it because of "powerups" but then i found it was useless for a battlegrounds game, it still works normally so i didnt bother to remove it
- end)
- else
- local OGWalkspeed = character.Humanoid.WalkSpeed
- character.Humanoid.WalkSpeed = 8
- task.delay(moveLength, function()
- Remotes.VFX:FireAllClients(character, move.Name, combo, moveLength)
- task.wait(0.3)
- character.Humanoid.WalkSpeed = OGWalkspeed
- end)
- end
- end
- local UppercutDebounce = {}
- attackHandler.Uppercut = function(entity: Player | Model, combo: number, moveLength: number, ...: any)
- local character
- if entity:IsA("Player") then
- character = entity.Character
- else
- character = entity
- end
- local move = BoxerMoves.Jab
- if table.find(UppercutDebounce, character.Name) then
- return
- else
- table.insert(UppercutDebounce, character.Name)
- task.delay(move.SelfCooldown[combo], function()
- if UppercutDebounce[table.find(UppercutDebounce, character.Name)] then UppercutDebounce[table.find(UppercutDebounce, character.Name)] = nil end
- end)
- end
- local attackEnds = os.clock() + moveLength
- --local hitboxSize = Vector3.new(3.5, 4.5, 3)
- local hitboxSize = move.HitboxSize[combo]
- character:SetAttribute("LastCombat", os.clock())
- local HRP = character.HumanoidRootPart:: BasePart
- local Params = OverlapParams.new()
- Params.FilterType = Enum.RaycastFilterType.Exclude
- Params.FilterDescendantsInstances = {character}
- --SFX below
- local MovesFXFolder = SFXFolder[move.Class][move.Name]
- local currentSFX = MovesFXFolder:FindFirstChild(math.random(1, #MovesFXFolder:GetChildren())):Clone()
- currentSFX.Parent = character.HumanoidRootPart
- currentSFX:Destroy() -- plays when removed
- --SFX end
- local HitboxOffset = move.HitboxOffset[combo]
- --HitboxOffset = CFrame.new(0,0,0)
- ----[[
- local hitboxVisualizer
- if character:GetAttribute("Hitbox") then
- hitboxVisualizer = Instance.new("Part")
- hitboxVisualizer.Size = hitboxSize
- hitboxVisualizer.Transparency = 0.7
- hitboxVisualizer.Color = Color3.new(1, 0, 0)
- hitboxVisualizer.Anchored = true
- hitboxVisualizer.CanCollide = false
- hitboxVisualizer.Parent = workspace
- hitboxVisualizer.CFrame = HRP.CFrame * HitboxOffset
- game.Debris:AddItem(hitboxVisualizer, move.Length[combo])
- end
- --]]
- local parts
- local MaxHits = 0
- local CharactersHit = {}
- local AnimReactions = ServerStorage.AnimationReactions
- local ClassReactions = AnimReactions:FindFirstChild(move.Class)
- local isBlocking = false
- task.spawn(function()
- repeat
- parts = workspace:GetPartBoundsInBox(HRP.CFrame * HitboxOffset, hitboxSize, Params)
- if hitboxVisualizer then hitboxVisualizer.CFrame = HRP.CFrame * HitboxOffset end
- for i, v in parts do
- if not v.Parent:FindFirstChildWhichIsA("Humanoid") then continue end
- if table.find(CharactersHit, v.Parent) then continue end
- if MaxHits == move.MaxHits then continue end
- MaxHits += 1
- table.insert(CharactersHit, v.Parent)
- if v.Parent:GetAttribute("IFrames") and v.Parent:GetAttribute("IFrames") > os.clock() then continue end
- local humanoid = v.Parent:FindFirstChildWhichIsA("Humanoid"):: Humanoid
- local animator = humanoid.Animator:: Animator
- local reaction
- v.Parent:SetAttribute("LastCombat", os.clock())
- if v.Parent:GetAttribute("Blocking") then
- isBlocking = true
- attackHandler.DoKnockback(character, v.Parent, move, combo, 0.2)
- humanoid:TakeDamage(move.Damage[combo]*0.1)
- local CurrentBlockBar = v.Parent:GetAttribute("BlockBar")
- local BlockBarDMG = move.BlockBarDamage[combo]
- v.Parent:SetAttribute("BlockBar", CurrentBlockBar + BlockBarDMG)
- warn("BLOCKBAR IS:",v.Parent:GetAttribute("BlockBar"))
- local blockBroken = false
- if v.Parent:GetAttribute("BlockBar") >= 100 then
- v.Parent:SetAttribute("BlockBar", 100)
- v.Parent:SetAttribute("Cooldown", os.clock() + 5)
- v.Parent:SetAttribute("BlockBroken", true)
- local enemyPlayer = game.Players:GetPlayerFromCharacter(v.Parent)
- if enemyPlayer then
- Remotes.BlockBroken:FireClient(enemyPlayer)
- end
- Remotes.VFX:FireAllClients(v.Parent, "BoxerBlockBroken")
- task.spawn(function()
- blockBroken = true
- v.Parent:SetAttribute("BlockBar", 0)
- local BlockBarTransitionAnim = AnimReactions:FindFirstChild(move.Class).BlockBreak:: Animation
- local BlockBarTransition = animator:LoadAnimation(BlockBarTransitionAnim)
- local StunAnim = AnimReactions:FindFirstChild(move.Class).BlockStun:: Animation
- local Stun = animator:LoadAnimation(StunAnim)
- BlockBarTransition.Priority = Enum.AnimationPriority.Action4
- Stun.Priority = Enum.AnimationPriority.Action4
- BlockBarTransition:Play()
- BlockBarTransition.Stopped:Wait()
- Stun:Play()
- v.Parent:SetAttribute("Blocking", false)
- repeat
- v.Parent.Humanoid.WalkSpeed = 0
- until v.Parent.Humanoid.WalkSpeed == 0
- task.wait(5)
- v.Parent.Humanoid.WalkSpeed = 16
- v.Parent:SetAttribute("BlockBroken", false)
- print("walkspeed set")
- Stun:Stop()
- end)
- end
- task.wait()
- if blockBroken then return end
- Remotes.VFX:FireAllClients(v.Parent, "BoxerBlock")
- reaction = animator:LoadAnimation(ClassReactions:FindFirstChild("BlockHit"))
- reaction.Priority = Enum.AnimationPriority.Action2
- else
- attackHandler.DoKnockback(character, v.Parent, move, combo, 1)
- humanoid:TakeDamage(move.Damage[combo])
- reaction = animator:LoadAnimation(ClassReactions:FindFirstChild(move.Name..tostring(combo)))
- reaction.Priority = Enum.AnimationPriority.Action2
- end
- reaction:Play()
- v.Parent:SetAttribute("Stun", os.clock() + move.Stun[combo])
- end
- task.wait()
- until os.clock() >= attackEnds
- end)
- if isBlocking then
- local OGWalkspeed = character.Humanoid.WalkSpeed
- character.Humanoid.WalkSpeed = 8
- task.delay(moveLength, function()
- Remotes.VFX:FireAllClients(character, move.Name.."Small", combo, moveLength)
- task.wait(0.3)
- character.Humanoid.WalkSpeed = OGWalkspeed
- end)
- else
- local OGWalkspeed = character.Humanoid.WalkSpeed
- character.Humanoid.WalkSpeed = 8
- task.delay(moveLength, function()
- Remotes.VFX:FireAllClients(character, move.Name, combo, moveLength)
- task.wait(0.3)
- character.Humanoid.WalkSpeed = OGWalkspeed
- end)
- end
- end
- return attackHandler
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement