Bloqueo
Lección 10 de 20 del curso Juego de Roblox: Combates en la arena de Coddy.
Bloqueo con F: durante Settings.BlockTime segundos, cada golpe que recibas solo inflige una parte de su daño, Settings.BlockMultiplier. Si alguien está bloqueando es un atributo de su personaje, Blocking, así que cualquier cosa puede leerlo.
Como cada golpe pasa por hurt, la regla se escribe una sola vez:
if character:GetAttribute("Blocking") then
amount *= Settings.BlockMultiplier
endLos bots te atacarán en el capítulo 4, y esas mismas líneas te protegerán entonces.
Desafío
Intermedio- Añade
abilities.Block: establece el atributoBlockingdel personaje y elimínalo después deSettings.BlockTime(si el personaje sigue ahí). - En
hurt, multiplica la cantidad porSettings.BlockMultipliercuando el personaje esté bloqueando. - En
BattleClient, vincula"Block"a F y muéstralo en la pantalla.
Pulsa Jugar y, después, Comprobar.
Pruébalo tú mismo
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Settings = require(game.ReplicatedStorage.Settings)
local remotes = game.ReplicatedStorage.Remotes
local lastSwing = {} -- player -> cuándo dio su último espadazo
-- Las animaciones de espada propias de Roblox
local slash = Instance.new("Animation")
slash.AnimationId = "rbxassetid://522635514"
print("Swords deal " .. Settings.SwordDamage .. " damage")
-- Todos los golpes del juego pasan por aquí
local function hurt(humanoid, amount)
if humanoid.Health <= 0 then
return
end
local character = humanoid.Parent
humanoid:TakeDamage(amount)
end
-- Un espadazo: se reproduce la animación y luego reciben un golpe todos los que estén en el área frente a ti
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()
-- el área frente a ti, nunca tu propio cuerpo
local params = OverlapParams.new()
params.FilterDescendantsInstances = { character }
local box = root.CFrame * CFrame.new(0, 0, -3)
local hit = {} -- cada humanoide una sola vez por espadazo
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
-- Las habilidades, por nombre: qué hace cada una
local abilities = {}
function abilities.Dash(player, character, root)
root.AssemblyLinearVelocity = root.CFrame.LookVector * Settings.DashSpeed + Vector3.new(0, 15, 0)
end
-- todos los que están a tu alrededor reciben un golpe y salen despedidos
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
-- El cliente solicita una habilidad por su nombre. El servidor comprueba que sea una
-- habilidad real, que el jugador siga con vida y que haya terminado su tiempo de recarga. El momento en que vuelve a estar lista
-- es un atributo del jugador, para que pueda mostrarse en su pantalla.
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)
-- Cada jugador recibe Kills en la tabla de clasificación y una espada en cada vida
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)
-- El muñeco de entrenamiento: su barra de salud refleja su salud y, cuando es derrotado,
-- el muñeco reaparece al cabo de un momento como una copia nueva en el mismo lugar
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)
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.