Blocage
Leçon 10 sur 20 du cours Jeu Roblox : Arènes de combat de Coddy.
Blocs de F : pendant Settings.BlockTime secondes, chaque coup que tu reçois n'inflige qu'une partie de ses dégâts, Settings.BlockMultiplier. Le fait qu'un personnage bloque est stocké dans un attribut de son personnage, Blocking, donc tout peut le lire.
Comme chaque coup passe par hurt, la règle est écrite une seule fois :
if character:GetAttribute("Blocking") then
amount *= Settings.BlockMultiplier
endLes bots t'attaqueront au chapitre 4, et ces mêmes lignes te protégeront alors.
Défi
Moyen- Ajoute
abilities.Block: définis l’attributBlockingdu personnage et supprime-le aprèsSettings.BlockTime(si le personnage est toujours là). - Dans
hurt, multiplie la quantité parSettings.BlockMultiplierlorsque le personnage bloque. - Dans
BattleClient, associe"Block"à F et affiche-le à l’écran.
Appuie sur Play, puis sur 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")
-- Tous les coups portés dans le jeu passent par ici
local function hurt(humanoid, amount)
if humanoid.Health <= 0 then
return
end
local character = humanoid.Parent
humanoid:TakeDamage(amount)
end
-- Un coup d'épée : l'animation se joue, puis tous ceux qui se trouvent dans la zone devant vous sont touchés
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 humanoid 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
hurt(humanoid, 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
-- tous ceux qui vous entourent sont touchés et projetés loin de vous
function abilities.Slam(player, character, root)
local params = OverlapParams.new()
params.FilterDescendantsInstances = { character }
local hit = {}
for _, part in workspace:GetPartBoundsInRadius(root.Position, Settings.SlamRadius, params) do
local humanoid = part.Parent:FindFirstChildOfClass("Humanoid")
local theirRoot = part.Parent:FindFirstChild("HumanoidRootPart")
if humanoid and theirRoot and not hit[humanoid] then
hit[humanoid] = true
hurt(humanoid, Settings.SlamDamage)
local away = (theirRoot.Position - root.Position) * Vector3.new(1, 0, 1)
if away.Magnitude > 0 then
away = away.Unit
end
theirRoot:ApplyImpulse((away * Settings.SlamKnockback + Vector3.new(0, 40, 0)) * theirRoot.AssemblyMass)
end
end
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 en vie et que son temps de recharge est terminé. Le moment où elle sera de nouveau disponible
-- est un attribut du joueur, afin 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 nouvelle 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 sa santé, et un mannequin vaincu
-- réapparaît peu après, sous la 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.