Advertisement
alexhernandezroblox

Untitled

Apr 22nd, 2025
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 17.13 KB | None | 0 0
  1. local attackHandler = {}
  2. type table = {[any]: any} -- defines the table type since roblox doesnt have a build in type for it
  3.  
  4. local RepStorage = game.ReplicatedStorage
  5. local ServerStorage = game:GetService("ServerStorage")
  6. local Keybinds = require(RepStorage.Keybinds)
  7. local Moves = Keybinds.Moves
  8. local SFXFolder
  9. if ServerStorage and ServerStorage:FindFirstChild("SFX") then
  10.     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
  11. end
  12. local Players = game.Players
  13.  
  14. --Remotes
  15. local Remotes = RepStorage.Remotes
  16.  
  17. -- Move Classes
  18. local BoxerMoves = Moves.Boxer
  19.  
  20. attackHandler.ActivateIFrames = function(character: Model, length: number)
  21.     character:SetAttribute("IFrames", os.clock() + length)
  22. end
  23.  
  24. attackHandler.DoKnockback = function(selfCharacter: Model, hitCharacter: Model, move: table, combo: number, val: number) -- knockback for moves and stuff
  25.     local linearVelocity = Instance.new("LinearVelocity")
  26.     local attachment = Instance.new("Attachment")
  27.     attachment.Name = "VelocityAttachment"
  28.  
  29.     linearVelocity.Attachment0 = attachment
  30.     attachment.Parent = hitCharacter.HumanoidRootPart
  31.     linearVelocity.Parent = hitCharacter.HumanoidRootPart
  32.  
  33.     local direction = selfCharacter.HumanoidRootPart.CFrame.LookVector
  34.     linearVelocity.MaxForce = 100000
  35.     linearVelocity.VectorVelocity = direction * move.Knockback[combo] * val
  36.  
  37.     task.defer(function()
  38.         task.wait(move.KnockbackTime[combo])
  39.         linearVelocity:Destroy()
  40.         attachment:Destroy()
  41.     end)
  42. end
  43.  
  44. 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
  45.     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
  46.     if isBlocked then
  47.         VFX = BoxerMoves.Jab.VFX.Small:Clone()
  48.     else
  49.         VFX = BoxerMoves.Jab.VFX:Clone()
  50.     end -- determines whether to use the small vfx or big one
  51.     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
  52.     local hrp = character:WaitForChild("HumanoidRootPart"):: BasePart
  53.     for i, v in VFX:GetChildren() do
  54.         if not v:IsA("BasePart") then continue end
  55.         v.CFrame = hrp.CFrame * offset -- the attachments are obviously in a basepart and stuff light lighting blocks and stuff shouldnt be :emit()
  56.     end
  57.     VFX.Parent = workspace
  58.     local darkEmitter = VFX.Dark.Attachment.ParticleEmitter:: ParticleEmitter
  59.     for i, v in VFX.Dust.Punch:GetChildren() do
  60.         v:Emit(2)
  61.     end
  62.     for i, v in VFX.Hit.Attachment:GetChildren() do
  63.         if v:IsA("ParticleEmitter") then v:Emit(1) else v.Enabled = true end
  64.     end
  65.     darkEmitter:Emit(2)
  66.    
  67.     game.Debris:AddItem(VFX, 0.7)
  68. end
  69.  
  70. attackHandler.BoxerBlockFX = function(character: Model)
  71.     local VFX = BoxerMoves.Block.VFX.Block:Clone()
  72.     local offset = BoxerMoves.Block.VFXOffset[1]
  73.     local hrp = character.HumanoidRootPart:: BasePart
  74.     VFX.CFrame = hrp.CFrame * offset
  75.     VFX.Parent = workspace
  76.     for i, v in VFX.Main:GetChildren() do
  77.         v:Emit(1)
  78.     end
  79.     game.Debris:AddItem(VFX, 2)
  80. end
  81.  
  82. attackHandler.BoxerBlockBreakFX = function(character: Model)
  83.     local VFX = BoxerMoves.Block.VFX.BlockBreak:Clone()
  84.     local Attachment = VFX.Main
  85.     local offset = BoxerMoves.Block.VFXOffset[2]
  86.     local hrp = character.HumanoidRootPart:: BasePart
  87.     VFX.CFrame = hrp.CFrame * offset
  88.     VFX.Parent = workspace
  89.     Attachment.Specs:Emit(70)
  90.     Attachment.Shockwave:Emit(1)
  91.     Attachment.Sharp:Emit(50)
  92.     task.wait(0.15)
  93.     Attachment.Shockwave:Emit(1)
  94.     game.Debris:AddItem(VFX, 2)
  95. end
  96.  
  97. local JabDebounce = {}
  98. attackHandler.Jab = function(entity: Player | Model, combo: number, moveLength: number, ...: any) -- actual jab move for the boxer class
  99.     local character
  100.     if entity:IsA("Player") then -- using entity since both NPCs and players can use moves, i couldnt think of a better name
  101.         character = entity.Character
  102.     else
  103.         character = entity
  104.     end -- if its a player it does player.character and if its an NPC itll just set character to the actual entity itself
  105.    
  106.     local move = BoxerMoves.Jab
  107.     if table.find(JabDebounce, character.Name) then
  108.         return -- makes sure there isnt a debounce. i put a debounce both locally and server sides because exploiters prevention
  109.     else
  110.         table.insert(JabDebounce, character.Name)
  111.         task.delay(move.SelfCooldown[combo], function()
  112.             if JabDebounce[table.find(JabDebounce, character.Name)] then JabDebounce[table.find(JabDebounce, character.Name)] = nil end
  113.         end)
  114.     end
  115.     local attackEnds = os.clock() + moveLength -- when does the attack end
  116.     --local hitboxSize = Vector3.new(3.5, 4.5, 3)
  117.     local hitboxSize = move.HitboxSize[combo] -- hitbox size is in keybinds module
  118.     character:SetAttribute("LastCombat", os.clock()) -- for blockbar regeneration, this attribute is for when the player was last in combat
  119.     local HRP = character.HumanoidRootPart:: BasePart
  120.     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
  121.     Params.FilterType = Enum.RaycastFilterType.Exclude
  122.     Params.FilterDescendantsInstances = {character}
  123.  
  124.     --SFX below
  125.     local MovesFXFolder = SFXFolder[move.Class][move.Name]
  126.     local currentSFX = MovesFXFolder:FindFirstChild(math.random(1, #MovesFXFolder:GetChildren())):Clone()
  127.     currentSFX.Parent = character.HumanoidRootPart
  128.     currentSFX:Destroy() -- plays when removed
  129.     --SFX end
  130.  
  131.     local HitboxOffset = move.HitboxOffset[combo]
  132.     --HitboxOffset = CFrame.new(0,0,0)
  133.     ----[[
  134.     local hitboxVisualizer -- there is a !hitbox command in chat, if you put it the hitboxvisualizer.transparency will be 0
  135.     if character:GetAttribute("Hitbox") then
  136.         hitboxVisualizer = Instance.new("Part")
  137.         hitboxVisualizer.Size = hitboxSize
  138.         hitboxVisualizer.Transparency = 0.7
  139.         hitboxVisualizer.Color = Color3.new(1, 0, 0)
  140.         hitboxVisualizer.Anchored = true
  141.         hitboxVisualizer.CanCollide = false
  142.         hitboxVisualizer.Parent = workspace
  143.         hitboxVisualizer.CFrame = HRP.CFrame * HitboxOffset
  144.         game.Debris:AddItem(hitboxVisualizer, move.Length[combo])
  145.     end
  146.     --]]
  147.  
  148.     local parts
  149.     local MaxHits = 0
  150.     local CharactersHit = {}
  151.  
  152.     local AnimReactions = ServerStorage.AnimationReactions
  153.     local ClassReactions = AnimReactions:FindFirstChild(move.Class)
  154.  
  155.     local isBlocking = false
  156.     task.spawn(function()
  157.         repeat
  158.             parts = workspace:GetPartBoundsInBox(HRP.CFrame * HitboxOffset, hitboxSize, Params) -- all the parts that was
  159.             if hitboxVisualizer then hitboxVisualizer.CFrame = HRP.CFrame * HitboxOffset end
  160.             for i, v in parts do
  161.                 if not v.Parent:FindFirstChildWhichIsA("Humanoid") then continue end
  162.                 if table.find(CharactersHit, v.Parent) then continue end
  163.                 if MaxHits == move.MaxHits then continue end
  164.  
  165.                 MaxHits += 1
  166.                 table.insert(CharactersHit, v.Parent)
  167.                 if v.Parent:GetAttribute("IFrames") and v.Parent:GetAttribute("IFrames") > os.clock() then continue end
  168.                 local humanoid = v.Parent:FindFirstChildWhichIsA("Humanoid"):: Humanoid
  169.                 local animator = humanoid.Animator:: Animator
  170.  
  171.                 local reaction
  172.                 v.Parent:SetAttribute("LastCombat", os.clock())
  173.                 if v.Parent:GetAttribute("Blocking") then
  174.                     isBlocking = true
  175.                     attackHandler.DoKnockback(character, v.Parent, move, combo, 0.2)
  176.                     humanoid:TakeDamage(move.Damage[combo]*0.1)
  177.                     local CurrentBlockBar = v.Parent:GetAttribute("BlockBar")
  178.                     local BlockBarDMG = move.BlockBarDamage[combo]
  179.                     v.Parent:SetAttribute("BlockBar", CurrentBlockBar + BlockBarDMG)
  180.                     warn("BLOCKBAR IS:",v.Parent:GetAttribute("BlockBar"))
  181.                     local blockBroken = false
  182.                     if v.Parent:GetAttribute("BlockBar") >= 100 then
  183.                         v.Parent:SetAttribute("BlockBar", 100)
  184.                         v.Parent:SetAttribute("Cooldown", os.clock() + 5)
  185.                         v.Parent:SetAttribute("BlockBroken", true)
  186.                         local enemyPlayer = game.Players:GetPlayerFromCharacter(v.Parent)
  187.                         if enemyPlayer then
  188.                             Remotes.BlockBroken:FireClient(enemyPlayer)
  189.                         end
  190.                         Remotes.VFX:FireAllClients(v.Parent, "BoxerBlockBroken")
  191.                         task.spawn(function()
  192.                             blockBroken = true
  193.                             v.Parent:SetAttribute("BlockBar", 0)
  194.                             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
  195.                             local BlockBarTransition = animator:LoadAnimation(BlockBarTransitionAnim)
  196.                             local StunAnim = AnimReactions:FindFirstChild(move.Class).BlockStun:: Animation
  197.                             local Stun = animator:LoadAnimation(StunAnim)
  198.                             BlockBarTransition.Priority = Enum.AnimationPriority.Action4
  199.                             Stun.Priority = Enum.AnimationPriority.Action4
  200.                             BlockBarTransition:Play()
  201.                             BlockBarTransition.Stopped:Wait()
  202.                             Stun:Play()
  203.                             v.Parent:SetAttribute("Blocking", false)
  204.                             repeat
  205.                                 v.Parent.Humanoid.WalkSpeed = 0
  206.                             until v.Parent.Humanoid.WalkSpeed == 0
  207.                             task.wait(5)
  208.                             v.Parent.Humanoid.WalkSpeed = 16
  209.                             v.Parent:SetAttribute("BlockBroken", false)
  210.                             print("walkspeed set")
  211.                             Stun:Stop()
  212.                         end)
  213.                     end
  214.                     task.wait()
  215.                     if blockBroken then return end
  216.                     Remotes.VFX:FireAllClients(v.Parent, "BoxerBlock") -- server client replication for vfx
  217.                     reaction = animator:LoadAnimation(ClassReactions:FindFirstChild("BlockHit"))
  218.                     reaction.Priority = Enum.AnimationPriority.Action2
  219.                 else
  220.                     attackHandler.DoKnockback(character, v.Parent, move, combo, 1)
  221.                     humanoid:TakeDamage(move.Damage[combo])
  222.                     reaction = animator:LoadAnimation(ClassReactions:FindFirstChild(move.Name..tostring(combo)))
  223.                     reaction.Priority = Enum.AnimationPriority.Action2
  224.                 end
  225.                 reaction:Play()
  226.                 v.Parent:SetAttribute("Stun", os.clock() + move.Stun[combo])
  227.             end
  228.             task.wait()
  229.         until os.clock() >= attackEnds
  230.     end)
  231.     if isBlocking then
  232.         local OGWalkspeed = character.Humanoid.WalkSpeed
  233.         character.Humanoid.WalkSpeed = 8
  234.         task.delay(moveLength, function()
  235.             Remotes.VFX:FireAllClients(character, move.Name.."Small", combo, moveLength)
  236.             task.wait(0.3)
  237.             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
  238.         end)
  239.     else
  240.         local OGWalkspeed = character.Humanoid.WalkSpeed
  241.         character.Humanoid.WalkSpeed = 8
  242.         task.delay(moveLength, function()
  243.             Remotes.VFX:FireAllClients(character, move.Name, combo, moveLength)
  244.             task.wait(0.3)
  245.             character.Humanoid.WalkSpeed = OGWalkspeed
  246.         end)
  247.     end
  248. end
  249.  
  250. local UppercutDebounce = {}
  251. attackHandler.Uppercut = function(entity: Player | Model, combo: number, moveLength: number, ...: any)
  252.     local character
  253.     if entity:IsA("Player") then
  254.         character = entity.Character
  255.     else
  256.         character = entity
  257.     end
  258.    
  259.     local move = BoxerMoves.Jab
  260.     if table.find(UppercutDebounce, character.Name) then
  261.         return
  262.     else
  263.         table.insert(UppercutDebounce, character.Name)
  264.         task.delay(move.SelfCooldown[combo], function()
  265.             if UppercutDebounce[table.find(UppercutDebounce, character.Name)] then UppercutDebounce[table.find(UppercutDebounce, character.Name)] = nil end
  266.         end)
  267.     end
  268.     local attackEnds = os.clock() + moveLength
  269.     --local hitboxSize = Vector3.new(3.5, 4.5, 3)
  270.     local hitboxSize = move.HitboxSize[combo]
  271.     character:SetAttribute("LastCombat", os.clock())
  272.     local HRP = character.HumanoidRootPart:: BasePart
  273.     local Params = OverlapParams.new()
  274.     Params.FilterType = Enum.RaycastFilterType.Exclude
  275.     Params.FilterDescendantsInstances = {character}
  276.  
  277.     --SFX below
  278.     local MovesFXFolder = SFXFolder[move.Class][move.Name]
  279.     local currentSFX = MovesFXFolder:FindFirstChild(math.random(1, #MovesFXFolder:GetChildren())):Clone()
  280.     currentSFX.Parent = character.HumanoidRootPart
  281.     currentSFX:Destroy() -- plays when removed
  282.     --SFX end
  283.  
  284.     local HitboxOffset = move.HitboxOffset[combo]
  285.     --HitboxOffset = CFrame.new(0,0,0)
  286.     ----[[
  287.     local hitboxVisualizer
  288.     if character:GetAttribute("Hitbox") then
  289.         hitboxVisualizer = Instance.new("Part")
  290.         hitboxVisualizer.Size = hitboxSize
  291.         hitboxVisualizer.Transparency = 0.7
  292.         hitboxVisualizer.Color = Color3.new(1, 0, 0)
  293.         hitboxVisualizer.Anchored = true
  294.         hitboxVisualizer.CanCollide = false
  295.         hitboxVisualizer.Parent = workspace
  296.         hitboxVisualizer.CFrame = HRP.CFrame * HitboxOffset
  297.         game.Debris:AddItem(hitboxVisualizer, move.Length[combo])
  298.     end
  299.     --]]
  300.  
  301.     local parts
  302.     local MaxHits = 0
  303.     local CharactersHit = {}
  304.  
  305.     local AnimReactions = ServerStorage.AnimationReactions
  306.     local ClassReactions = AnimReactions:FindFirstChild(move.Class)
  307.  
  308.     local isBlocking = false
  309.     task.spawn(function()
  310.         repeat
  311.             parts = workspace:GetPartBoundsInBox(HRP.CFrame * HitboxOffset, hitboxSize, Params)
  312.             if hitboxVisualizer then hitboxVisualizer.CFrame = HRP.CFrame * HitboxOffset end
  313.             for i, v in parts do
  314.                 if not v.Parent:FindFirstChildWhichIsA("Humanoid") then continue end
  315.                 if table.find(CharactersHit, v.Parent) then continue end
  316.                 if MaxHits == move.MaxHits then continue end
  317.  
  318.                 MaxHits += 1
  319.                 table.insert(CharactersHit, v.Parent)
  320.                 if v.Parent:GetAttribute("IFrames") and v.Parent:GetAttribute("IFrames") > os.clock() then continue end
  321.                 local humanoid = v.Parent:FindFirstChildWhichIsA("Humanoid"):: Humanoid
  322.                 local animator = humanoid.Animator:: Animator
  323.  
  324.                 local reaction
  325.                 v.Parent:SetAttribute("LastCombat", os.clock())
  326.                 if v.Parent:GetAttribute("Blocking") then
  327.                     isBlocking = true
  328.                     attackHandler.DoKnockback(character, v.Parent, move, combo, 0.2)
  329.                     humanoid:TakeDamage(move.Damage[combo]*0.1)
  330.                     local CurrentBlockBar = v.Parent:GetAttribute("BlockBar")
  331.                     local BlockBarDMG = move.BlockBarDamage[combo]
  332.                     v.Parent:SetAttribute("BlockBar", CurrentBlockBar + BlockBarDMG)
  333.                     warn("BLOCKBAR IS:",v.Parent:GetAttribute("BlockBar"))
  334.                     local blockBroken = false
  335.                     if v.Parent:GetAttribute("BlockBar") >= 100 then
  336.                         v.Parent:SetAttribute("BlockBar", 100)
  337.                         v.Parent:SetAttribute("Cooldown", os.clock() + 5)
  338.                         v.Parent:SetAttribute("BlockBroken", true)
  339.                         local enemyPlayer = game.Players:GetPlayerFromCharacter(v.Parent)
  340.                         if enemyPlayer then
  341.                             Remotes.BlockBroken:FireClient(enemyPlayer)
  342.                         end
  343.                         Remotes.VFX:FireAllClients(v.Parent, "BoxerBlockBroken")
  344.                         task.spawn(function()
  345.                             blockBroken = true
  346.                             v.Parent:SetAttribute("BlockBar", 0)
  347.                             local BlockBarTransitionAnim = AnimReactions:FindFirstChild(move.Class).BlockBreak:: Animation
  348.                             local BlockBarTransition = animator:LoadAnimation(BlockBarTransitionAnim)
  349.                             local StunAnim = AnimReactions:FindFirstChild(move.Class).BlockStun:: Animation
  350.                             local Stun = animator:LoadAnimation(StunAnim)
  351.                             BlockBarTransition.Priority = Enum.AnimationPriority.Action4
  352.                             Stun.Priority = Enum.AnimationPriority.Action4
  353.                             BlockBarTransition:Play()
  354.                             BlockBarTransition.Stopped:Wait()
  355.                             Stun:Play()
  356.                             v.Parent:SetAttribute("Blocking", false)
  357.                             repeat
  358.                                 v.Parent.Humanoid.WalkSpeed = 0
  359.                             until v.Parent.Humanoid.WalkSpeed == 0
  360.                             task.wait(5)
  361.                             v.Parent.Humanoid.WalkSpeed = 16
  362.                             v.Parent:SetAttribute("BlockBroken", false)
  363.                             print("walkspeed set")
  364.                             Stun:Stop()
  365.                         end)
  366.                     end
  367.                     task.wait()
  368.                     if blockBroken then return end
  369.                     Remotes.VFX:FireAllClients(v.Parent, "BoxerBlock")
  370.                     reaction = animator:LoadAnimation(ClassReactions:FindFirstChild("BlockHit"))
  371.                     reaction.Priority = Enum.AnimationPriority.Action2
  372.                 else
  373.                     attackHandler.DoKnockback(character, v.Parent, move, combo, 1)
  374.                     humanoid:TakeDamage(move.Damage[combo])
  375.                     reaction = animator:LoadAnimation(ClassReactions:FindFirstChild(move.Name..tostring(combo)))
  376.                     reaction.Priority = Enum.AnimationPriority.Action2
  377.                 end
  378.                 reaction:Play()
  379.                 v.Parent:SetAttribute("Stun", os.clock() + move.Stun[combo])
  380.             end
  381.             task.wait()
  382.         until os.clock() >= attackEnds
  383.     end)
  384.     if isBlocking then
  385.         local OGWalkspeed = character.Humanoid.WalkSpeed
  386.         character.Humanoid.WalkSpeed = 8
  387.         task.delay(moveLength, function()
  388.             Remotes.VFX:FireAllClients(character, move.Name.."Small", combo, moveLength)
  389.             task.wait(0.3)
  390.             character.Humanoid.WalkSpeed = OGWalkspeed
  391.         end)
  392.     else
  393.         local OGWalkspeed = character.Humanoid.WalkSpeed
  394.         character.Humanoid.WalkSpeed = 8
  395.         task.delay(moveLength, function()
  396.             Remotes.VFX:FireAllClients(character, move.Name, combo, moveLength)
  397.             task.wait(0.3)
  398.             character.Humanoid.WalkSpeed = OGWalkspeed
  399.         end)
  400.     end
  401. end
  402.  
  403. return attackHandler
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement