Chặn đòn
Bài học 12 trên 25 trong khóa học Trò chơi Roblox: Đấu trường của Coddy.
Khi đỡ đòn, trong Settings.BlockTime giây, mỗi đòn đánh trúng bạn chỉ gây một phần sát thương, Settings.BlockMultiplier. Việc một nhân vật có đang đỡ đòn hay không được lưu trong thuộc tính Blocking của nhân vật đó, nên mọi thứ đều có thể đọc thuộc tính này.
Vì mọi đòn đánh đều đi qua hurt, quy tắc này chỉ cần viết một lần:
if character:GetAttribute("Blocking") then
amount *= Settings.BlockMultiplier
endBot sẽ đánh bạn ở chương 4, và những dòng code này cũng sẽ bảo vệ bạn khi đó.
Thử thách
Trung bìnhChặn bằng phím F: trong chốc lát, mỗi đòn đánh chỉ gây một phần năm sát thương.
- Thêm
abilities.Block(player, character): đặt thuộc tínhBlockingcủa nhân vật thành true, rồi xóa thuộc tính này sauSettings.BlockTimenếu nhân vật vẫn còn ở đó. - Trong
hurt, khi nhân vật đangBlocking, nhânamountvớiSettings.BlockMultiplier. - Trong
BattleClient, gán"Block"cho phím F và thêm nó vàoshown.
Nhấn Chơi rồi nhấn F: nhãn Block đếm ngược. Sau đó nhấn Kiểm tra.
Tự làm thử
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Settings = require(game.ReplicatedStorage.Settings)
local remotes = game.ReplicatedStorage.Remotes
local lastSwing = {} -- player -> thời điểm vung kiếm gần nhất
-- Hoạt ảnh vung kiếm có sẵn của Roblox
local slash = Instance.new("Animation")
slash.AnimationId = "rbxassetid://522635514"
print("Swords deal " .. Settings.SwordDamage .. " damage")
-- Mọi đòn đánh trong trò chơi đều đi qua đây
local function hurt(humanoid, amount)
if humanoid.Health <= 0 then
return
end
local character = humanoid.Parent
humanoid:TakeDamage(amount)
end
-- Một lần vung kiếm: phát hoạt ảnh, rồi đánh trúng mọi người trong vùng hình hộp phía trước bạn
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()
-- Vùng hình hộp phía trước bạn, không bao gồm cơ thể bạn
local params = OverlapParams.new()
params.FilterDescendantsInstances = { character }
local box = root.CFrame * CFrame.new(0, 0, -3)
local hit = {} -- Mỗi humanoid chỉ trúng đòn một lần trong mỗi lần vung kiếm
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
-- Các kỹ năng theo tên và tác dụng của từng kỹ năng
local abilities = {}
-- Thiết bị của người chơi điều khiển nhân vật, nên thao tác lướt diễn ra trên thiết bị đó
function abilities.Dash(player)
remotes.Ability:FireClient(player, "Dash")
end
-- Mọi người xung quanh đều trúng đòn và bị hất ra xa bạn
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
-- Bài học 12: thêm Block vào đây
-- Máy khách yêu cầu một kỹ năng theo tên. Máy chủ kiểm tra: kỹ năng có thật,
-- người chơi còn sống và thời gian hồi chiêu đã hết. Khi kỹ năng sẵn sàng trở lại
-- là thuộc tính của người chơi để màn hình của họ hiển thị thời điểm đó.
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)
-- Mỗi lần hồi sinh, người chơi nhận một thanh kiếm.
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function()
local sword = ServerStorage.Sword:Clone()
sword.Parent = player.Backpack
sword.Activated:Connect(function()
swing(player)
end)
end)
end)
-- Hình nộm tập luyện: thanh máu thay đổi theo lượng máu; khi bị đánh bại,
-- hình nộm sẽ xuất hiện lại sau chốc lát dưới dạng bản sao mới ở vị trí cũ.
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)
Tất cả bài học trong Trò chơi Roblox: Đấu trường
Tự luyện tập: Playground Roblox