בוט מופיע
שיעור 16 מתוך 25 בקורס משחק Roblox: זירות קרב של Coddy.
עכשיו יריב. בוט הוא מודל ב־ServerStorage.Bot עם Humanoid, שמשוכפל אל המשטח האדום, עם הערכים שלו מתוך Settings ועם סרגל בריאות כמו של בובת האימון.
Roblox מאפשר ללקוח של שחקן שנמצא בקרבת מקום לחשב את הפיזיקה של מודל לא מעוגן, ואז קריאה מהשרת כמו ApplyImpulse עליו לא עושה דבר. המכה שלך מעיפה בוטים לאחור מהשרת, לכן השאר את הפיזיקה של כל בוט בשרת, מרגע שהבוט נמצא בסביבת העבודה:
crate.Parent = workspace
crate:SetNetworkOwner(nil)אתגר
קשההוסף בוט לזירה.
- הוסף
local bots = workspace.Bots. כתוב אתspawnBot(): שכפל אתServerStorage.Botבגובה 3 studs מעלworkspace.BotSpawn; הגדר את MaxHealth ואת Health ל-Settings.BotHealth, ואת WalkSpeed ל-Settings.BotSpeed. - הגדר את ההורה שלו ל-
bots, ואז הפעל אתbot.HumanoidRootPart:SetNetworkOwner(nil). - עדכן את הגודל של
bot.HealthBar.Back.Fillבעת HealthChanged, כמו אצל בובת האימון. קרא ל-spawnBot().
לחץ על "שחק": בוט אדום עומד על המשטח האדום. לאחר מכן לחץ על "בדיקה".
נסו בעצמכם
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Debris = game:GetService("Debris")
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 damageNumber(character, amount)
local root = character:FindFirstChild("HumanoidRootPart")
if not root then
return
end
local tag = Instance.new("BillboardGui")
tag.Name = "Damage"
tag.Size = UDim2.fromOffset(60, 30)
tag.StudsOffset = Vector3.new(0, 4.5, 0)
tag.Adornee = root
local text = Instance.new("TextLabel")
text.Size = UDim2.fromScale(1, 1)
text.BackgroundTransparency = 1
text.TextColor3 = Color3.fromRGB(255, 220, 80)
text.TextScaled = true
text.Text = "-" .. math.round(amount)
text.Parent = tag
tag.Parent = character
Debris:AddItem(tag, 0.8)
end
-- כל פגיעה במשחק עוברת כאן
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)
damageNumber(character, amount)
end
-- הלם משתק מישהו לרגע
local function stun(humanoid)
local character = humanoid.Parent
if character:GetAttribute("Stunned") then
return
end
character:SetAttribute("Stunned", true)
print(character.Name .. " is stunned")
local speed = humanoid.WalkSpeed
humanoid.WalkSpeed = 0
task.delay(Settings.StunTime, function()
if character.Parent then
humanoid.WalkSpeed = speed
character:SetAttribute("Stunned", nil)
end
end)
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])
if finisher then
stun(humanoid)
end
end
end
end
-- היכולות, לפי שם: מה כל אחת עושה
local abilities = {}
-- המכשיר של השחקן מזיז את הדמות שלו, ולכן ההסתערות מתבצעת בו
function abilities.Dash(player)
remotes.Ability:FireClient(player, "Dash")
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)
-- כל שחקן מקבל חרב בכל פעם שהדמות שלו מופיעה מחדש
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)
-- בובת האימון: מד הבריאות שלה מתעדכן לפי מצב הבריאות שלה, ובובה שהובסה
-- חוזרת כעבור רגע כעותק חדש באותו מקום
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)
-- שיעור 16: בוט מופיע כאן
כל השיעורים ביחידה משחק Roblox: זירות קרב
תרגלו בעצמכם: Roblox אונליין