Menu
CoddyTech

الارتداد

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

ينبغي للضربة القوية أن تقذف ما تصيبه. تطبيق ApplyImpulse على جذر يمنح الجسم كله دفعة. الدفع هو التغير في السرعة مضروبًا في الكتلة، لذا فإن الضرب في AssemblyMass يقذف الهياكل الخفيفة والثقيلة بالطريقة نفسها:

theirRoot:ApplyImpulse((away * 30 + Vector3.new(0, 20, 0)) * theirRoot.AssemblyMass)

يشير away من موقعك إلى موقعهم، بمحاذاة سطح الأرض: موقعهم مطروحًا منه موقعك، مع جعل Y صفرًا، ثم .Unit ليكون طوله 1.

challenge icon

التحدي

متوسط

اجعل الضربة المقذوفة ترمي كل من تصيبه.

  1. في abilities.Slam، بعد hurt: local away = (theirRoot.Position - root.Position) * Vector3.new(1, 0, 1)، ثم away = away.Unit إذا كان مقدارها أكبر من 0.
  2. ثم theirRoot:ApplyImpulse((away * Settings.SlamKnockback + Vector3.new(0, 40, 0)) * theirRoot.AssemblyMass).

اضغط «العب»، وامشِ بين المجسمين الأحمرين واضغط E: سيندفعان مبتعدين. ثم اضغط «تحقق».

جرّب بنفسك

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 hurt(humanoid, amount)
	if humanoid.Health <= 0 then
		return
	end
	local character = humanoid.Parent
	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
	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
			hurt(humanoid, Settings.SwordDamage)
		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)
			-- الدرس 11: يُضاف تأثير الدفع إلى الخلف هنا
		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)

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

تدرّب بنفسك: Playground لـ Roblox