Hello all,
I’ve done a verification system for my basic combat system but sometimes it goes out of sync, which I don’t know why happens.
SERVER SCRIPT →
local playerRandoms = {}
PlayerManager.PlayerAdded:Connect(function(player)
local seed = math.random() * 3264
playerRandoms[player] = Random.new(seed)
print(playerRandoms[player], player)
SeedRemoteEvent:FireClient(player, seed, itemsWithoutSpaces)
end)
local total = 0
for i, data in animations do total += data.Chance end
local function SelectAnimation(player)
local value = playerRandoms[player]:NextInteger(1, total)
for i, data in animations do
value -= data.Chance
if value > 0 then continue end
return animations[i]
end
end
local function SelectDamage(player, animation)
return playerRandoms[player]:NextInteger(animation.Damage.Min, animation.Damage.Max)
end
PlayerAttackRemoteEvent.OnServerEvent:Connect(function(player, anim, playerHit)
local animation = SelectAnimation(player)
local animationDamage = SelectDamage(player, animation)
local tool = player.Character:FindFirstChildWhichIsA("Tool")
local toolDamage = itemsWithoutSpaces[tool.Name].Damage
if animation.Chance == anim.Chance then --Safety check
local damage = toolDamage + animationDamage
if damage > 0 then
playerHit.Character.Humanoid:TakeDamage(damage)
end
end
end)
AnimationStoppedRemoteEvent.OnServerEvent:Connect(function(player)
SelectAnimation(player)
playerRandoms[player]:NextNumber()
end)
LOCALSCRIPT →
local canAttack = true
tool.Activated:Connect(function()
if tool:GetAttribute("Type") == "Sword" or tool:GetAttribute("Type") == "Axe" then
if canAttack and LocalPlayer.PlayerGui.Inventory.InventoryFrame.Items.Visible == false then
local anim = SelectAnimation()
local animation = animator:LoadAnimation(anim.Animation)
tool.Main.Trail.Enabled = true
animation:Play()
if tool:FindFirstChildWhichIsA("Sound") == nil then
local sound = game.ReplicatedStorage.SoundEffects.WeaponSound:Clone()
sound.Parent = tool
end
tool:FindFirstChildWhichIsA("Sound"):Play()
canAttack = false
local players = {}
local connection = tool.Main.Touched:Connect(function(hit)
local player = Players:GetPlayerFromCharacter(hit.Parent)
if player and players[player] == nil then
players[player] = true
local animationDamage = SelectDamage(anim)
local toolDamage = items[tool.Name].Damage
local damage = animationDamage + toolDamage
local healthDamage = damage
if healthDamage then
local toolDamageText = ToolDamageText:Clone()
toolDamageText.Text = healthDamage
toolDamageText.TextColor3 = Color3.fromRGB(170, 0, 0)
toolDamageText.Position = UDim2.new((0.3 + math.random() * (0.7 - 0.3)), 0, (0.3 + math.random() * (0.7 - 0.3)), 0)
toolDamageText.Parent = LocalPlayer.PlayerGui.UI
toolDamageText:TweenSize(UDim2.new(0, 75, 0, 75), Enum.EasingDirection.InOut, Enum.EasingStyle.Linear, 1, true, function()
local transparencyTween = TweenService:Create(toolDamageText, toolDamageTextTweenInfo, { TextTransparency = 1 })
transparencyTween:Play()
transparencyTween.Completed:Connect(function()
toolDamageText:Destroy()
end)
end)
end
PlayerAttackRemoteEvent:FireServer(anim, player)
end
end)
animation.Stopped:Connect(function()
tool.Main.Trail.Enabled = false
connection:Disconnect()
localRandom:NextNumber()
AnimationStoppedRemoteEvent:FireServer()
wait(1)
canAttack = true
end)
end
end
end)
The way it works is that the server sends a certain seed to a client so they both can get the same NextInteger() values for it. This works very well until the player misses hitting somebody (eg. just hits the air), after that it will no longer be synced and many will not go thru the safety check which is commented in the server script. Help is appreciated, if you have any questions, please leave them below