Nihai Yetenek
Coddy'nin Roblox Oyunu: Savaş Arenası kursunda ders 20 / 20.
Son yetenek: R tuşundaki bir özel saldırı. İsabet ettirdiğin her vuruş, oyuncunun bir özniteliği olan göstergeye Settings.UltimatePerHit ekler; gösterge Settings.UltimateMax değerine kadar dolar. Gösterge tamamen dolduğunda R, Settings.UltimateRadius içindeki herkese Settings.UltimateDamage hasar verir ve göstergeyi boşaltır.
Gösterge boşken özel saldırı hiçbir şey yapmamalı ve hiçbir maliyeti olmamalı. Bu yüzden bir yetenek artık false döndürerek kullanılamayacağını belirtebilir; işleyici de bekleme süresini yalnızca false döndürülmediğinde ayarlar:
if abilities[name](player, character, root) ~= false then
player:SetAttribute(name .. "ReadyAt", now + Settings.Cooldowns[name])
endHUD'daki Ultimate çubuğu göstergeyi gösterir. Oyunun tamamı bundan ibaret: savaş, kombo yap, blok yap ve göstergeyi doldur.
Görev
Zor- Her oyuncunun
Ultimateözelliğini 0 olarak başlat. hurtiçinde, saldıranı olan bir vuruş saldıranın göstergesineSettings.UltimatePerHitekler; en fazlaSettings.UltimateMaxdeğerine kadar.abilities.Ultimateekle: gösterge dolu değilse false döndür;Settings.UltimateRadiusiçindeki herkese (her birine bir kez, sana değil)Settings.UltimateDamagekadar hasar ver; ardından göstergeyi boşalt (vuruşlardan sonra, çünkü onlar da göstergeyi doldurur). Bekleme süresini yalnızca bir yetenek false döndürmediyse ayarla.BattleClientiçinde"Ultimate"özelliğini R tuşuna bağla vehud.Ultimate.Fillboyutunu göstergeye göre ayarla.
Play'e bas ve savaş. Ardından Check'e bas.
Kendin dene
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Debris = game:GetService("Debris")
local PathfindingService = game:GetService("PathfindingService")
local Settings = require(game.ReplicatedStorage.Settings)
local remotes = game.ReplicatedStorage.Remotes
local bots = workspace.Bots
local lastSwing = {} -- player -> en son ne zaman kılıç savurduğu
local combo = {} -- player -> { art arda isabet sayısı, son isabetin gerçekleştiği zaman }
local lastHit = {} -- humanoid -> ona en son vuran oyuncu
-- Roblox'un kendi kılıç animasyonları
local slash = Instance.new("Animation")
slash.AnimationId = "rbxassetid://522635514"
local lunge = Instance.new("Animation")
lunge.AnimationId = "rbxassetid://522638767"
print("Swords deal " .. Settings.SwordDamage .. " damage")
-- Vurulan kişinin üzerinde kısa süre beliren bir sayı
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
-- Oyundaki her vuruş buradan geçer (attacker: vuran oyuncu veya nil)
local function hurt(humanoid, amount, attacker)
if humanoid.Health <= 0 then
return
end
local character = humanoid.Parent
-- bloklama, hasarın büyük kısmını engeller
if character:GetAttribute("Blocking") then
amount *= Settings.BlockMultiplier
end
humanoid:TakeDamage(amount)
damageNumber(character, amount)
if attacker then
lastHit[humanoid] = attacker
end
end
-- Sersemletme, birini kısa süreliğine hareketsiz bırakır
local function stun(humanoid)
local character = humanoid.Parent
if character:GetAttribute("Stunned") then
return
end
character:SetAttribute("Stunned", true)
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
-- Bir kılıç savuruşu: önce animasyon oynar, ardından önündeki kutunun içindeki herkes vurulur
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
-- art arda üç kılıç savuruşu bir kombo oluşturur; üçüncüsü ileri atılarak yapılan bir saldırıdır
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()
-- önündeki kutu; kendi vücudun asla dahil değildir
local params = OverlapParams.new()
params.FilterDescendantsInstances = { character }
local box = root.CFrame * CFrame.new(0, 0, -3)
local hit = {} -- her humanoid, savuruş başına bir kez
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], player)
if finisher then
stun(humanoid)
end
end
end
end
-- Yetenekler, adlarına göre: her birinin ne yaptığı
local abilities = {}
function abilities.Dash(player, character, root)
root.AssemblyLinearVelocity = root.CFrame.LookVector * Settings.DashSpeed + Vector3.new(0, 15, 0)
end
-- Etrafındaki herkes darbe alır ve senden uzağa savrulur
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, player)
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
-- İstemci, bir yeteneği adıyla kullanmak ister. Sunucu şunları kontrol eder: geçerli bir
-- yetenek olması, oyuncunun hayatta olması ve bekleme süresinin dolmuş olması. Yeteneğin yeniden ne zaman hazır olacağı
-- oyuncunun bir niteliğinde tutulur; böylece ekranda gösterilebilir.
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)
-- Her oyuncu, liderlik tablosunda Kills değeri ve her yeniden doğuşunda bir kılıç alır
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()
player:SetAttribute("Streak", 0)
local sword = ServerStorage.Sword:Clone()
sword.Parent = player.Backpack
sword.Activated:Connect(function()
swing(player)
end)
end)
end)
-- Antrenman kuklası: can çubuğu can durumunu yansıtır ve yenilen
-- kukla kısa bir süre sonra aynı yerde yeni bir kopya olarak geri gelir
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)
-- Bir botun görebildiği, hayatta olan en yakın oyuncunun karakteri ve ona uzaklığı
local function nearestCharacter(position)
local best, bestDistance = nil, Settings.BotSight
for _, player in Players:GetPlayers() do
local character = player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
if root and character.Humanoid.Health > 0 then
local distance = (root.Position - position).Magnitude
if distance < bestDistance then
best, bestDistance = character, distance
end
end
end
return best, bestDistance
end
-- Bir karaktere doğru yürü: önünde engel yoksa doğrudan ona, varsa
-- engelin etrafından geçen yolun bir sonraki noktasına
local function walkToward(bot, target, path)
local root = bot.HumanoidRootPart
local goal = target.HumanoidRootPart.Position
local params = RaycastParams.new()
params.FilterDescendantsInstances = { bot }
local hit = workspace:Raycast(root.Position, goal - root.Position, params)
if not hit or hit.Instance:IsDescendantOf(target) then
bot.Humanoid:MoveTo(goal)
return
end
path:ComputeAsync(root.Position, goal)
local points = path:GetWaypoints()
if path.Status == Enum.PathStatus.Success and points[2] then
bot.Humanoid:MoveTo(points[2].Position)
end
end
-- Bir botun zihni: her çeyrek saniyede bir etrafına bakıp karar verir
local function runBot(bot)
local humanoid = bot.Humanoid
local root = bot.HumanoidRootPart
local lastAttack = 0
local path = PathfindingService:CreatePath()
while bot.Parent and humanoid.Health > 0 do
local target, distance = nearestCharacter(root.Position)
local state
if bot:GetAttribute("Stunned") then
state = "Stunned"
elseif humanoid.Health < humanoid.MaxHealth * Settings.RetreatAt then
state = "Retreat"
elseif not target then
state = "Idle"
elseif distance <= Settings.BotRange then
state = "Attack"
else
state = "Chase"
end
bot:SetAttribute("State", state)
if state == "Chase" then
walkToward(bot, target, path)
elseif state == "Attack" then
humanoid:MoveTo(root.Position)
if time() - lastAttack >= Settings.BotAttackCooldown then
lastAttack = time()
humanoid.Animator:LoadAnimation(slash):Play()
hurt(target.Humanoid, Settings.BotDamage)
end
elseif state == "Retreat" and target then
local away = (root.Position - target.HumanoidRootPart.Position) * Vector3.new(1, 0, 1)
if away.Magnitude > 0 then
humanoid:MoveTo(root.Position + away.Unit * 12)
end
else
humanoid:MoveTo(root.Position)
end
task.wait(0.25)
end
end
-- Kırmızı platformda, özellik değerleri ve sağlık çubuğuyla yeni bir bot
local function spawnBot()
local bot = ServerStorage.Bot:Clone()
bot:PivotTo(workspace.BotSpawn.CFrame + Vector3.new(0, 3, 0))
bot.Humanoid.MaxHealth = Settings.BotHealth
bot.Humanoid.Health = Settings.BotHealth
bot.Humanoid.WalkSpeed = Settings.BotSpeed
bot.Parent = bots
-- slam yeteneğinin savurması botu hareket ettirebilsin diye botun fizik hesaplamalarını sunucuda tut
bot.HumanoidRootPart:SetNetworkOwner(nil)
bot.Humanoid.HealthChanged:Connect(function(health)
bot.HealthBar.Back.Fill.Size = UDim2.fromScale(health / bot.Humanoid.MaxHealth, 1)
end)
bot.Humanoid.Died:Connect(function()
-- Öldürme puanını bota son vuran oyuncu alır
local killer = lastHit[bot.Humanoid]
lastHit[bot.Humanoid] = nil
if killer and killer.Parent then
killer.leaderstats.Kills.Value += 1
killer:SetAttribute("Streak", (killer:GetAttribute("Streak") or 0) + 1)
end
task.wait(1)
bot:Destroy()
task.wait(Settings.BotRespawn)
spawnBot()
end)
task.spawn(runBot, bot)
end
for _ = 1, Settings.Bots do
spawnBot()
end
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.