I’ve been working on a medieval type game and one function I introduced into the combat style is parrying. Whenever you hit someone who is hitting you, the both of you perform a parry. There’s other conditions that can also produce this but I’ll use that example in this case.
The reason why I find it important to ask how I can set up my code here is because I’m trying to reduce latency with server-to-client events so I don’t put more pressure on the server to act. At the same time, I’m worried that having a client listen to simple things that the server may change will allow exploiters to abuse the parrying effect so that they never suffer from a parry.
Here’s the example: Option #1
elseif Hum:GetAttribute("isHitting") == true then
if Type == "Blockbash" then
Hum:TakeDamage((Dmg * 75)/100)
elseif Type == "Special" or Type == "ChargeAttack" then
Hum:TakeDamage((Dmg * 90)/100)
elseif Type == "JumpAttack" then
Hum:TakeDamage(Dmg)
else
Hum:TakeDamage((Dmg * 60)/100)
end
Detector:FindFirstChild("Parry"..math.random(1,3)):Play()
Detector:FindFirstChild("Slice"..math.random(1,4)):Play()
breakHit:FireClient(Player, "Parry", Char) --sending message to client #1
breakHit:FireClient(Plyr, "Parry", Player.Character) --sending message to client #2
In this case I am having the server send a message to the client for an answer. Alternatively, what if I just had the client listen for a change in value instead?
Option #2
elseif Hum:GetAttribute("isHitting") == true then
if Type == "Blockbash" then
Hum:TakeDamage((Dmg * 75)/100)
elseif Type == "Special" or Type == "ChargeAttack" then
Hum:TakeDamage((Dmg * 90)/100)
elseif Type == "JumpAttack" then
Hum:TakeDamage(Dmg)
else
Hum:TakeDamage((Dmg * 60)/100)
end
Detector:FindFirstChild("Parry"..math.random(1,3)):Play()
Detector:FindFirstChild("Slice"..math.random(1,4)):Play()
Player:SetAttribute("Parry", true) --The client listens to this to produce the parry
Plyr:SetAttribute("Parry", true) --The client listens to this to produce the parry
Which option do you prefer? I feel like Option #2 is easier for exploiters to abuse but Option #1 can cause more latency.
You still have to send the data from a client, to the server, and to another client. This sometimes has to occur under high latency. A player might parry on one end but due to latency issues one of them might see it parry but one of them might see it as a normal attack
There aren’t really many exploiters that can exploit. I would strive for a better user experience than cheating reduction. I would use server validation for more important things. For instance, user data such as player cash, bought items, etc.
I’d imagine I’m gonna hybrid between server and client validation. There’s still quite a few remote events that fire commands between both participants in battle, but I’ve been trying to reduce it lately.
Assuming that I’m sticking to a hybrid, do you think there will still be lagging issues with clients catching up with changes the server makes, that makes it useless to utilize client validation? My biggest problem is going down this road to reduce lag and seeing that it doesn’t really solve much for me
What does the client do in all of this? From the looks of it, the server is correctly dealing damage and just tells the client there’s a parry and…? How would the client be able to prevent the parry if you’ve dealt damage before even telling the client anything?
use Player1 and Player2, it looks kinda confusing
I’m not sure you can listen to an event of attributes changing.
Games like Arsenal use client sided validation. This gives the user a more seamless playing experience. But, when you’re lagging, players stay in one place. This causes you to be able to kill everyone because it’s client validated and it’s super easy to hit stationary units.
Either way, both still have latency issues. Hybrid or not.
Because scripts work from up to down (and I wouldn’t like to add more stress to the handler) I have the client produce a LineVelocity that forces them to go backwards while client-sided. This line velocity is enabled for a certain duration as well. They also need to play a little animation and a client-sided boolean turns on to lock them up, so it’s necessary to tell the client that a parry is occurring.
I know it’s only a certain portion of code you’re seeing right now but a parry occurs in game when two players successfully hit each other at once, thus producing a parry. In this case you’ll see both of them fly backwards while producing the parry animation. The parry forces both of them to take damage – but this damage is limited because the attack was not “successfully completed”. This is why you see only a certain percentage of the damage is dealt. I’m happy to explain more conditions that help make a parry more sufficient for the player if you’d like.
This is also a good reason as to why I wanted there to be client validation because I don’t want the server to fire the same event twice in this script, but I also want to make sure that both of them are experiencing this “double-edged sword” by the parry. Luckily I discovered that .Changed events or attribute changing events will not fire a command again given that the changes are identical to the original.
The server is perfectly capable of handling all of this.
If you want your game to be near lag free, then maybe you should consider Arsenal’s approach and let the client tell the server when they’ve hit something. Otherwise, you could try and implement something to hide the lag, for example when the client thinks there’s a parry maybe it could play an animation where the player moves the sword to their side behind their head, looking like they’re preparing to swing it. I suggest you look at this: Lag Compensation