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

فترات انتظار الخادم

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

يتحكم المخترق بجهازه، لذا يمكنه استدعاء Remotes.Ability مئة مرة في الثانية، وبأي اسم. إن وضع فترة انتظار في LocalScript لن يوقف سوى اللاعبين النزيهين: على الخادم فرضها.

يحتفظ الخادم، لكل لاعب ولكل قدرة، بموعد جاهزيتها مجددًا كسمة للاعب (يوضح الدرس التالي ذلك على الشاشة). workspace:GetServerTimeNow() ساعة يتفق عليها الخادم وكل عميل:

local now = workspace:GetServerTimeNow()
if now < (player:GetAttribute(name .. "ReadyAt") or 0) then
	return
end
player:SetAttribute(name .. "ReadyAt", now + Settings.Cooldowns[name])

ويتحقق مما أُرسل إليه: سلسلة نصية تسمّي قدرة حقيقية، من لاعب على قيد الحياة.

challenge icon

التحدي

متوسط

في معالج Ability، قبل تشغيل القدرة، أعد عند تحقق ما يلي:

  1. الاسم ليس سلسلة نصية تُسمّي قدرة،
  2. اللاعب ليس لديه جذر للشخصية، أو أن صحة Humanoid لديه تساوي 0،
  3. يكون GetServerTimeNow() قبل وقت جاهزية اللاعب لتلك القدرة، وهو السمة name .. "ReadyAt".

وإلا، فعيّن تلك السمة إلى الوقت الحالي مضافًا إليه Settings.Cooldowns[name]، ثم شغّلها. اضغط 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 -> وقت آخر تلويحة له

-- حركات السيف الخاصة بـRoblox
local slash = Instance.new("Animation")
slash.AnimationId = "rbxassetid://522635514"

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

-- تلويحة بالسيف: تبدأ الحركة، ثم يُصاب كل من في المنطقة أمامك
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
	character.Humanoid.Animator:LoadAnimation(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
			humanoid:TakeDamage(Settings.SwordDamage)
		end
	end
end

-- القدرات بحسب أسمائها: وظيفة كل منها
local abilities = {}

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

-- يطلب العميل قدرةً باسمها؛ وينفّذها الخادم
remotes.Ability.OnServerEvent:Connect(function(player, name)
	local character = player.Character
	local root = character and character:FindFirstChild("HumanoidRootPart")
	if abilities[name] and root then
		abilities[name](player, character, root)
	end
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: ساحات القتال