기절
Coddy의 Roblox 게임: 배틀그라운드 코스 레슨. 20개 중 12번째.
콤보의 돌진은 대상을 기절시킵니다: 대상은 Settings.StunTime 동안 꼼짝 못 합니다. WalkSpeed가 0인 Humanoid는 걸을 수 없습니다. 기절 효과는 기존 속도를 기억했다가 되돌려 줍니다.
Stunned 속성은 기절한 대상을 표시합니다. 4장의 봇은 이 속성을 읽어 공격을 멈추며, 두 번째 기절 효과가 되돌릴 속도로 0을 저장하는 것도 방지합니다:
if character:GetAttribute("Stunned") then
return
end챌린지
중급swing 위에 stun(humanoid)를 작성하세요. 캐릭터가 이미 Stunned 상태라면 반환하고, 그렇지 않으면 표시를 설정하고 WalkSpeed를 저장한 다음 0으로 설정하세요. 그런 다음 Settings.StunTime이 지나면 캐릭터가 여전히 존재하는 경우 속도를 복원하고 표시를 해제하세요. 콤보의 세 번째 타격 대상에게 기절 효과를 적용하세요.
Play를 누른 다음 Check를 누르세요.
직접 해보기
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Settings = require(game.ReplicatedStorage.Settings)
local remotes = game.ReplicatedStorage.Remotes
local lastSwing = {} -- player -> 마지막으로 검을 휘두른 시각
local combo = {} -- player -> { 연속 명중 횟수, 마지막 공격이 적중한 시각 }
-- Roblox 자체 검 애니메이션
local slash = Instance.new("Animation")
slash.AnimationId = "rbxassetid://522635514"
local lunge = Instance.new("Animation")
lunge.AnimationId = "rbxassetid://522638767"
print("Swords deal " .. Settings.SwordDamage .. " damage")
-- 게임의 모든 타격은 여기를 거친다
local function hurt(humanoid, amount)
if humanoid.Health <= 0 then
return
end
local character = humanoid.Parent
-- 막으면 피해의 대부분을 줄인다
if character:GetAttribute("Blocking") then
amount *= Settings.BlockMultiplier
end
humanoid:TakeDamage(amount)
end
-- 검 휘두르기: 애니메이션이 재생된 뒤 앞쪽 상자 범위 안의 모두를 공격한다
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
-- 검을 세 번 연속 휘두르면 콤보가 되고, 세 번째는 찌르기 공격이다
local c = combo[player]
if c and now - c.last <= Settings.ComboWindow then
c.count = c.count % 3 + 1
else
c = { count = 1 }
combo[player] = c
end
c.last = now
local finisher = c.count == 3
character.Humanoid.Animator:LoadAnimation(finisher and lunge or slash):Play()
-- 앞쪽의 상자 범위이며, 자신의 몸은 포함하지 않는다
local params = OverlapParams.new()
params.FilterDescendantsInstances = { character }
local box = root.CFrame * CFrame.new(0, 0, -3)
local hit = {} -- 한 번 휘두를 때 각 humanoid는 한 번만 공격한다
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.ComboDamage[c.count])
end
end
end
-- 이름별 능력과 각 능력의 효과
local abilities = {}
function abilities.Dash(player, character, root)
root.AssemblyLinearVelocity = root.CFrame.LookVector * Settings.DashSpeed + Vector3.new(0, 15, 0)
end
-- 주변의 모두를 공격하고 자신에게서 멀리 밀어낸다
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
function abilities.Block(player, character)
character:SetAttribute("Blocking", true)
task.delay(Settings.BlockTime, function()
if character.Parent then
character:SetAttribute("Blocking", nil)
end
end)
end
-- 클라이언트가 이름으로 능력 사용을 요청한다. 서버는 실제로 존재하는
-- 능력이 실제로 존재하고, 플레이어가 살아 있으며, 재사용 대기시간이 끝났는지 확인합니다. 다시 사용할 수 있는 시각은
-- 플레이어의 속성으로 저장되어 화면에 표시할 수 있습니다.
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)
-- 모든 플레이어는 리더보드에 Kills를 부여받고, 부활할 때마다 검을 받습니다.
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)
-- 훈련용 더미: 체력 바는 더미의 체력에 따라 변하고, 쓰러진
-- 더미는 잠시 후 같은 자리에 새 복제본으로 다시 나타납니다.
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)
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.