Menu
CoddyTech

Golpe contra el suelo

Lección 9 de 20 del curso Juego de Roblox: Combates en la arena de Coddy.

Una segunda habilidad, con E: un golpe contra el suelo que alcanza a todos los que te rodean y los lanza lejos. workspace:GetPartBoundsInRadius(position, radius, params) encuentra las partes que están dentro de una distancia, y ApplyImpulse en una raíz da un empujón a todo su cuerpo. Un impulso es un cambio de velocidad multiplicado por la masa, así que multiplicar por AssemblyMass lanza los rigs ligeros y pesados de la misma manera:

theirRoot:ApplyImpulse((away * Settings.SlamKnockback + Vector3.new(0, 40, 0)) * theirRoot.AssemblyMass)

Ahora el juego tiene dos maneras de hacer daño, y habrá más. Cada golpe pasa por una función, hurt(humanoid, amount), así que una regla sobre el daño (bloquear, en la próxima lección) se escribe una sola vez.

challenge icon

Desafío

Intermedio
  1. Escribe hurt(humanoid, amount) antes de swing: retorna si el Humanoid ya ha sido derrotado; de lo contrario, TakeDamage(amount). Haz que swing la llame.
  2. Añade abilities.Slam: todos (una vez cada uno, menos tú) que tengan una raíz dentro de Settings.SlamRadius reciben Settings.SlamDamage mediante hurt y son empujados lejos de ti con Settings.SlamKnockback y 40 hacia arriba.
  3. En BattleClient, asigna "Slam" a E y añádelo a la visualización del tiempo de recuperación.

Pulsa Play y después Check.

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 atacó por última vez

-- Las animaciones de espada propias de Roblox
local slash = Instance.new("Animation")
slash.AnimationId = "rbxassetid://522635514"

print("Swords deal " .. Settings.SwordDamage .. " damage")

-- Un ataque: se reproduce la animación y luego todos los que estén en la zona frente a ti reciben un golpe
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 zona 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 solo una vez por ataque
	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

-- 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

-- El cliente solicita una habilidad por su nombre. El servidor comprueba que sea una
-- habilidad real, que el jugador esté vivo y que haya terminado su tiempo de reutilización. El momento en que vuelve a estar disponible
-- 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 obtiene 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)
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Juego de Roblox: Combates en la arena