הלם
שיעור 12 מתוך 20 בקורס משחק Roblox: זירות קרב של Coddy.
הסתערות של קומבו מדהימה: המטרה שלה קופאת למשך Settings.StunTime. Humanoid עם WalkSpeed בערך 0 לא יכול ללכת; ההלם זוכר את מהירות ההליכה שהייתה לו ומשיב אותה.
מאפיין Stunned מסמן את הדמות ההמומה. הבוטים בפרק 4 קוראים אותו כדי להפסיק לתקוף, והוא מונע מהלם שני לשמור את 0 בתור המהירות שאליה צריך לחזור:
if character:GetAttribute("Stunned") then
return
endאתגר
בינוניכתבו את stun(humanoid) מעל swing: חזרו אם הדמות שלו כבר 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)
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.