Menu
CoddyTech

Betäubung

Lektion 12 von 20 im Kurs Roblox-Spiel: Schlachtfelder von Coddy.

Der Ausfallschritt eines Combos betäubt: Sein Ziel bleibt für Settings.StunTime bewegungsunfähig. Ein Humanoid mit einer WalkSpeed von 0 kann nicht laufen; die Betäubung merkt sich die vorherige Geschwindigkeit und stellt sie wieder her.

Ein Stunned-Attribut kennzeichnet die betäubte Figur. Die Bots in Kapitel 4 lesen es, um ihre Angriffe einzustellen. Außerdem verhindert es, dass eine zweite Betäubung 0 als Geschwindigkeit speichert, zu der zurückgekehrt werden soll:

if character:GetAttribute("Stunned") then
	return
end
challenge icon

Aufgabe

Mittel

Schreibe stun(humanoid) oberhalb von swing: Kehre zurück, wenn der Charakter bereits Stunned ist; markiere ihn andernfalls, merke dir seine WalkSpeed, setze sie auf 0 und gib ihm nach Settings.StunTime seine Geschwindigkeit zurück und entferne die Markierung (falls der Charakter noch vorhanden ist). Betäube das Ziel des dritten Treffers der Kombo.

Drücke Play und dann Check.

Probier es selbst

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Settings = require(game.ReplicatedStorage.Settings)

local remotes = game.ReplicatedStorage.Remotes
local lastSwing = {} -- player -> Zeitpunkt des letzten Schwertschwungs
local combo = {} -- player -> { Treffer in Folge, Zeitpunkt des letzten Treffers }

-- Roblox' eigene Schwertanimationen
local slash = Instance.new("Animation")
slash.AnimationId = "rbxassetid://522635514"
local lunge = Instance.new("Animation")
lunge.AnimationId = "rbxassetid://522638767"

print("Swords deal " .. Settings.SwordDamage .. " damage")

-- Jeder Treffer im Spiel läuft hierüber
local function hurt(humanoid, amount)
	if humanoid.Health <= 0 then
		return
	end
	local character = humanoid.Parent
	-- Blocken fängt den Großteil des Treffers ab
	if character:GetAttribute("Blocking") then
		amount *= Settings.BlockMultiplier
	end
	humanoid:TakeDamage(amount)
end

-- Ein Schwertschwung: erst die Animation, dann werden alle im Bereich vor dir getroffen
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
	-- Drei Schwertschwünge in Folge ergeben eine Kombo; der dritte ist ein Ausfallschritt
	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()
	-- Der Bereich vor dir, niemals dein eigener Körper
	local params = OverlapParams.new()
	params.FilterDescendantsInstances = { character }
	local box = root.CFrame * CFrame.new(0, 0, -3)
	local hit = {} -- Jeder humanoid nur einmal pro Schwertschwung
	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

-- Die Fähigkeiten, nach Namen geordnet: Was jede einzelne bewirkt
local abilities = {}

function abilities.Dash(player, character, root)
	root.AssemblyLinearVelocity = root.CFrame.LookVector * Settings.DashSpeed + Vector3.new(0, 15, 0)
end

-- Alle um dich herum werden getroffen und von dir weggeschleudert
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

-- Der Client fordert eine Fähigkeit anhand ihres Namens an. Der Server prüft: Ist es eine gültige
-- Fähigkeit, ein lebender Spieler und eine abgelaufene Abklingzeit. Wann sie wieder bereit ist,
-- ist als Attribut des Spielers gespeichert, damit es auf seinem Bildschirm angezeigt werden kann.
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)

-- Jeder Spieler erhält Kills auf der Bestenliste und bei jedem neuen Leben ein Schwert
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)

-- Die Trainingspuppe: Ihre Gesundheitsanzeige passt sich ihrer Gesundheit an, und eine besiegte
-- Puppe kehrt nach kurzer Zeit als neue Kopie an derselben Stelle zurück
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)
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Roblox-Spiel: Schlachtfelder