Hey everyone, sorry for the long post. I am in need of help because this is actually my first time scripting and I could use some guidance. If you have any knowledge of the solution to these following questions, please let me know in the comment section!
1. I was writing a punching script and I came across an issue where if I pressed the Keybind “f” more than once it would cancel the animation if it had not finished from the first time I pressed the button and I would start the animation over. Basically, I am trying to figure out how I can implement an interval or a “reload time” in between each punch to prevent spamming and other issues.**
2. I want to change the Keybind to the Left Mouse Button but I am not sure how.
3. How can I make it so the animation can vary? I have two animations, a right hand punch and a left hand punch. I want to know how I can make it so that the animations will alternate for each punch.
For example: First click would be a right hand punch and then the second click would be a right hand punch.
CanDoDmg = true
Keybind = "RightMouseButton"
dmg = 10
local plr = game.Players.LocalPlayer
local mouse = plr:GetMouse()
mouse.KeyDown:Connect(function(key)
if key == Keybind then
local anim = script.Parent.Humanoid:LoadAnimation(script.Animation)
anim:Play()
script.Parent.RightArm.Touched:connect(function(hit)
if hit.Parent.Humanoid and CanDoDmg == true then
hit.Parent.Humanoid:TakeDamage(dmg)
CanDoDmg = false
wait(1)
CanDoDmg = true
end
end)
end
end)
For number 1, add a variable named something like “punching” to act as a flag to tell if you are already punching. If the player inputs a punch, check if “punching” is true, and if it isn’t, set it to true and let the player punch. Then, use the AnimationTrack’s stopped event to reset that flag once the animation ends.
For number 3, you can use another variable to keep track of the last hand used to punch, let’s call it “rightHandPunched”. It’ll default to false, and every time you punch, it flips from false to true or vise versa. If it’s false when the player punches, play the right hand punch animation and flip it to true. If it’s true when the player punches, do the left hand punch animation instead.
Put all these together and we might get something like this:
CanDoDmg = true
dmg = 10
local userInput = game:GetService("UserInputService")
local plr = game.Players.LocalPlayer
local punching = false
local rightHandPunched = false
userInput.InputBegan:Connect(function(key)
if key ==Enum.UserInputType.MouseButton1 and not punching then
punching = true
local anim;
local touchEvent;
if not rightHandPunched then
anim = script.Parent.Humanoid:LoadAnimation(script.RightHandPunch) --there must be an animation named RightHandPunch under the script for this to work.
touchEvent = script.Parent.RightArm.Touched:connect(function(hit)
if hit.Parent.Humanoid and CanDoDmg == true then
hit.Parent.Humanoid:TakeDamage(dmg)
CanDoDmg = false
wait(1)
CanDoDmg = true
end
end)
else
local anim = script.Parent.Humanoid:LoadAnimation(script.LeftHandPunch) --there must be an animation named LeftHandPunch under the script for this to work.
touchEvent = script.Parent.LeftArm.Touched:connect(function(hit)
if hit.Parent.Humanoid and CanDoDmg == true then
hit.Parent.Humanoid:TakeDamage(dmg)
CanDoDmg = false
wait(1)
CanDoDmg = true
end
end)
end
anim:Play()
animationTrack.Stopped:wait()
touchEvent:Disconnect();
punching = false;
rightHandPunched = not rightHandPunched;
end
end)
A quick note: I also stored the Touched event in a variable so we can disconnect from the event once the animation ends. The reason why we do this is because if we don’t disconnect a function we connect to an event, it will continuously listen to the event and run the code inside whenever the event fires. In this case, if we don’t disconnect from the Touched event the player could potentially still hurt other players with their arm even if they aren’t in the punching animation.
Thanks man, I appreciate it. However, I don’t fully understand all of this because this is legit the first time I have coded in Lua so I have no clue. Although, I have the anims but the script itself did not work and I can’t figure out why.
--// LocalScript
local Keybind = "RightMouseButton";
local Debounce = false; --// For animation
local Remote = game:GetService("ReplicatedStorage"):WaitForChild("PunchEvent");
local plr = game:GetService("Players").LocalPlayer;
local mouse = plr:GetMouse();
--// For right click change the 1 to a 2
mouse.Button1Down:Connect(function()
if not Debounce then
Debounce = true;
local anim = script.Parent.Humanoid:LoadAnimation(script.Animation);
anim:Play();
Remote:FireServer();
wait(1) --// Time before you can use punch again.
Debounce = false;
end
end)
--// Server Script
local Remote = Instance.new("RemoteEvent", game:GetService("ReplicatedStorage"));
Remote.Name = "PunchEvent";
local serverDebounce = {};
local dmg = 10;
Remote.OnServerEvent:connect(function(player)
local Character = player.Character;
if Character and Character:FindFirstChild("Humanoid") and not serverDebounce[player] then
local Humanoid = Character.Humanoid;
local PeopleGettingHit = Character.RightArm:GetTouchedParts();
for _,v in pairs(PeopleGettingHit) do
if v.Parent:FindFirstChild("Humanoid") then
v.Parent.Humanoid:TakeDamage(dmg);
break;
end
end
serverDebounce[player] = true;
wait(1) --// Time to wait before calling it again (preventing exploiters)
serverDebounce[player] = nil;
end
end)
Is it the script giving any errors or is it just not working?
If it’s just not working, I realized when looking at it again that
hit.Parent.Humanoid:TakeDamage(dmg)
will not work in a LocalScript. If a player wants to do damage to another player, it has to ask the server to do so using a RemoteEvent.
You can replace that line with something like
game:GetService("ReplicatedStorage"):FindFirstChild("DamagePlayer"):FireServer(hit.Parent.Humanoid);
--create a RemoteEvent in the root of ReplicatedStorage named DamagePlayer for this to work
and then in a Script located inside of ServerScriptService have something like this inside:
local function DamagePlayer(requestingPlayer,targetHumanoid)--remote events fired from a client always provide the player that fired it as the first argument.
local dmg = 10;
targetHumanoid:TakeDamage(dmg)
end
game:GetService("ReplicatedStorage"):FindFirstChild("DamagePlayer").OnServerEvent:Connect(DamagePlayer)
Keep in mind that this is a very simple example, and would be very easy for exploiters to use to cheat. You could guard against this by doing some checks in the DamagePlayer function in the Script such as checking that the requestingPlayer’s character is close enough to the targetHumanoid’s parent in order to do damage. Here is a short article with some basic info on this.
Yes it is, which is why I mentioned as much at the end of my post. It’s not meant to be a permanent solution, just something simple to get the script to work for now.