Affichage du délai de récupération
Leçon 8 sur 20 du cours Jeu Roblox : Arènes de combat de Coddy.
Un joueur doit voir quand une capacité est prête. Le HUD comporte un cadre Cooldowns avec une étiquette par capacité, et le serveur conserve déjà DashReadyAt sur le joueur, où son client peut le lire.
Un compte à rebours change à chaque image, donc le client le redessine sur RunService.Heartbeat, qui se déclenche une fois par image. string.format conserve une décimale :
string.format("%s %.1f", "Dash", 2.345) --> "Dash 2.3"Le client affiche uniquement le temps de recharge. La vérification du serveur de la leçon précédente reste déterminante.
Défi
MoyenDans BattleClient, récupère RunService, local me = Players.LocalPlayer et local hud = script.Parent. À chaque Heartbeat, pour chaque nom dans local shown = { "Dash" }, définis hud.Cooldowns[name].Text sur Dash 2.3 pendant le temps de recharge, et sur Dash ready lorsqu’il est prêt.
Appuie sur Play, appuie sur Q et observe l’étiquette. Puis Check.
Essayez vous-même
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Settings = require(game.ReplicatedStorage.Settings)
local remotes = game.ReplicatedStorage.Remotes
local lastSwing = {} -- player -> moment de son dernier coup d'épée
-- Les animations d'épée de Roblox
local slash = Instance.new("Animation")
slash.AnimationId = "rbxassetid://522635514"
print("Swords deal " .. Settings.SwordDamage .. " damage")
-- Un coup d'épée : l'animation se joue, puis toutes les personnes dans la zone devant vous sont touchées
local function swing(player)
local character = player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
if not root or character.Humanoid.Health <= 0 then
return
end
local now = time()
if lastSwing[player] and now - lastSwing[player] < Settings.SwingCooldown then
return
end
lastSwing[player] = now
character.Humanoid.Animator:LoadAnimation(slash):Play()
-- la zone devant vous, jamais votre propre corps
local params = OverlapParams.new()
params.FilterDescendantsInstances = { character }
local box = root.CFrame * CFrame.new(0, 0, -3)
local hit = {} -- chaque humanoïde une seule fois par coup d'épée
for _, part in workspace:GetPartBoundsInBox(box, Settings.HitboxSize, params) do
local humanoid = part.Parent:FindFirstChildOfClass("Humanoid")
if humanoid and not hit[humanoid] then
hit[humanoid] = true
humanoid:TakeDamage(Settings.SwordDamage)
end
end
end
-- Les capacités, par nom : ce que fait chacune
local abilities = {}
function abilities.Dash(player, character, root)
root.AssemblyLinearVelocity = root.CFrame.LookVector * Settings.DashSpeed + Vector3.new(0, 15, 0)
end
-- Le client demande une capacité par son nom. Le serveur vérifie qu'il s'agit d'une véritable
-- capacité, que le joueur est vivant et que son délai de récupération est écoulé. Le moment où elle sera de nouveau disponible
-- est un attribut du joueur, pour que son écran puisse l'afficher.
remotes.Ability.OnServerEvent:Connect(function(player, name)
if typeof(name) ~= "string" or not abilities[name] then
return
end
local character = player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
if not root or character.Humanoid.Health <= 0 then
return
end
local now = workspace:GetServerTimeNow()
if now < (player:GetAttribute(name .. "ReadyAt") or 0) then
return
end
player:SetAttribute(name .. "ReadyAt", now + Settings.Cooldowns[name])
abilities[name](player, character, root)
end)
-- Chaque joueur reçoit Kills dans le classement et une épée à chaque vie
Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local kills = Instance.new("IntValue")
kills.Name = "Kills"
kills.Parent = leaderstats
player.CharacterAdded:Connect(function()
local sword = ServerStorage.Sword:Clone()
sword.Parent = player.Backpack
sword.Activated:Connect(function()
swing(player)
end)
end)
end)
-- Le mannequin d'entraînement : sa barre de vie suit son état de santé et, une fois vaincu, le
-- mannequin réapparaît après un instant, sous forme d'une nouvelle copie au même endroit
local function setupDummy(dummy)
local humanoid = dummy.Humanoid
humanoid.HealthChanged:Connect(function(health)
dummy.HealthBar.Back.Fill.Size = UDim2.fromScale(health / humanoid.MaxHealth, 1)
end)
humanoid.Died:Connect(function()
local spot = dummy:GetPivot()
task.wait(0.5)
dummy:Destroy()
task.wait(Settings.DummyRespawn)
local fresh = ServerStorage.Dummy:Clone()
fresh:PivotTo(spot)
fresh.Parent = workspace
setupDummy(fresh)
end)
end
setupDummy(workspace.Dummy)
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.