Menu
CoddyTech
flag Ar iconالعربيةdown icon

الإغماء

الدرس 12 من 20 في دورة لعبة Roblox: ساحات القتال على Coddy.

تُسبّب ضربة الاندفاع في الكومبو الذهول: يبقى هدفها متجمّدًا لمدة Settings.StunTime. لا يستطيع كائن Humanoid ذو قيمة WalkSpeed تساوي 0 المشي؛ لذا يحتفظ الذهول بالسرعة التي كانت لديه ويعيدها إليه.

تُشير السمة Stunned إلى الشخصية المصابة بالذهول. تقرؤها الروبوتات في الفصل 4 لتتوقف عن الهجوم، كما تمنع حدوث ذهول ثانٍ من حفظ القيمة 0 بوصفها السرعة التي ينبغي الرجوع إليها:

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

التحدي

متوسط

اكتب 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)
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس لعبة Roblox: ساحات القتال