On line 5 you wrote:
local anims = {"Uppercut"}
But as I commented, you don’t need to do that, all you need to do is create a folder in ReplicatedStorage, put your uppercut animation in there and name it ‘uppercut’ or change all references of ‘uppercut’ in the script to the name of the uppercut animation (case sensitive!).
On line 12, you wrote:
local remotes = {"ClickHitbox", "Remotes"}
But again, you don’t need to do that because as I commented, you need to add the table indexes in the format:
local remotes = {
uppercut = game:GetService('ReplicatedStorage'):WaitForChild('Remotes'):WaitForChild('ClickHitbox');
someDifferentAction = game:GetService('ReplicatedStorage'):WaitForChild('Remotes'):WaitForChild('SomeDifferentAnimationRemote');
}
This looks for a folder called ‘Remotes’ in ReplicatedStorage, which has the child ‘ClickHitbox’ as a RemoteEvent.
Since you wanted to use the uppercase ‘Uppercut’, I have changed the script accordingly:
local player = game.Players.LocalPlayer
local character
local animationFolder = game:GetService('ReplicatedStorage'):WaitForChild('AnimationFolder'):GetChildren() --> Change 'AnimationFolder' to a folder with all of your animations in it
local anims = { }
--> This will create an easy to access dict for our anims, for this, we need an animation in there called the name of the action, in this case:
--> 'Uppercut' will need to be in the animation folder
for i, v in next, animationFolder do
anims[v.Name] = v
end
local remotes = {
--> Create a table of remotes, so that you can access them at will for each command
Uppercut = game:GetService('ReplicatedStorage'):WaitForChild('Remotes'):WaitForChild('ClickHitbox');
--[?] To add another, you would write: otherAnimation = game:GetService('ReplicatedStorage'):WaitForChild('Remotes'):WaitForChild('otherRemote')';
}
local states = { --> This is used to keep track of what our player is currently doing
playing = nil; --> This determines whether or not we're performing an action currently so that we can't perform another
last = {
--> This is where we'll store the last performed action times
};
}
local cooldowns = { --[!] You could put this in a module for both the server + the client to access
Uppercut = 6; --> How long you should wait before someone can perform another Uppercut (in seconds)
}
local actions = { --[!] This could also be put in a module as above
Uppercut = Enum.KeyCode.F; --> What input are we looking for when we want to perform this action
}
local function isAlive()
local char = character or player.Character
if not char or not char:IsDescendantOf(game.Workspace) or not char:FindFirstChild "Humanoid" or char.Humanoid:GetState() == Enum.HumanoidStateType.Dead then
return
end
return char
end
local function checkCooldown(class)
if cooldowns[class] then --> Do we have a cooldown value to compare to for this class of action?
if (time() - (states.last[class] or 0)) > cooldowns[class] then --> Returns true if the last time we performed this action has passed the length of the cooldown
return true
end
end
return false
end
local function performAction(class, args)
local anim = anims[class]
local remote = remotes[class]
if anim and remote then
local track = character.Humanoid:LoadAnimation(anim)
track.Priority = Enum.AnimationPriority.Action
track:GetMarkerReachedSignal("ActionFrame"):Connect(function ()
--> Tell the server we're at the action frame of the animation, so it needs to look to do any damage
remote:FireServer(args)
--> Update our states so we can perform other actions again + add our last time to the list
states.last[class] = time()
states.playing = false
end)
track:Play()
end
end
game:GetService("UserInputService").InputBegan:Connect(function(Input, gameProcessed)
character = isAlive()
if not character or gameProcessed then
return
end
if Input.UserInputType == Enum.UserInputType.Keyboard then
if Input.KeyCode == actions.Uppercut then
if not states.playing and checkCooldown('Uppercut') then
states.playing = true
performAction('Uppercut', 'Right')
end
end
end
end)
However, don’t forget to have the folder ‘Remotes’ in ReplicatedStorage with all your remotes inside, and another folder called ‘AnimationFolder’ with the animation ‘Uppercut’ (Case sensitive!) with that animation as a child.