[SOLVED] How to go about making a flag capture system?

  1. I want to make a flag capture system so whenever you stand in an area, it starts to capture it. I have done this so when a player touches a invisible part it captures the flag. Also, I want it to add a booster and take it away if that player isn’t still the one who has the flag captured.

  2. The Issue is I cant get it to stop when the player leaves the zone or when someone if contesting the other player. How would I do this?

  3. I have tried using .Magnitude by subtracting the flags base by the players HumanoidRootPart and I put this in a loop to check if they leave the zone but it didn’t work.

I am using a Tween to make the flag go up and down. I already have the booster being added to the player their is nothing in place to remove the booster from them if someone else captures the flag.

Code so far:

--//Services
local TS = game:GetService("TweenService")

--//Variables
local thumbType = Enum.ThumbnailType.AvatarBust
local thumbSize = Enum.ThumbnailSize.Size420x420

local touchPart = script.Parent.TouchPart

local flagMiddle = script.Parent.FlagMiddle
local flagSettings = flagMiddle.FlagSettings
local playerName = flagMiddle.Post.FlagDisplay.Frame.PlayerName
local raised = flagMiddle.Raised
local lowered = flagMiddle.Lowered

local playerImg1 = flagMiddle.FlagPart.Front.PlayerImg1
local playerImg2 = flagMiddle.FlagPart.Back.PlayerImg2

local claiming = false

local Info = TweenInfo.new(
	10,
	Enum.EasingStyle.Linear,
	Enum.EasingDirection.In,
	0,
	true
)

touchPart.Touched:Connect(function(hit)
	local char = hit.Parent
	if char then
		local plr = game.Players:GetPlayerFromCharacter(char)
		local playerBoosts = plr:FindFirstChild("PlayerBoosts")
		local activeBoosts = playerBoosts:FindFirstChild("ActiveBoosts")
		local flagBoost = playerBoosts:FindFirstChild("FlagBoost")
		if flagSettings.PlayerID.Value ~= plr.UserId then
			if claiming == false then
				claiming = true
				local userId = plr.UserId
				local content, isReady = game.Players:GetUserThumbnailAsync(userId, thumbType, thumbSize)

				local LRtween = TS:Create(flagMiddle.FlagPart, Info, {Position = lowered.Position})
				LRtween:Play()
				
				playerName.Text = "Claiming..."

				LRtween.Completed:Connect(function()
					playerName.UnClaimed.Enabled = false
					playerName.Claimed.Enabled = true
					playerName.Text = plr.Name

					playerImg1.Image = content
					playerImg2.Image = content

					flagSettings.PlayerName.Value = plr.Name
					flagSettings.PlayerID.Value = plr.UserId
					
					activeBoosts.Value += flagBoost.Value
					
					claiming = false
				end)
			end
		end
	end
end)

Using mangitude is the correct option, can you show the code that uses magnitude?

I put this right after playerName.Text = “Claiming…”

				while true and wait(.1) do
					if (flagMiddle.Base.Position - char.HumanoidRootPart.Position).Magnitude <= 20 then
						LRtween:Pause()
					end
				end

It might actually be working but not pausing the Tween so its not showing any signs of working.

Magntiude is being used correctly at the wrong place. Change the first .touched event into a while loop and check the distance of every player/entity capable of capturing. Adjust the capture progress according to who’s within distance of the capture point.

This is what I had originally getting everyone in the game and checking it based on that. I started out with having a local script that every render stepped it would fire the server and pass the player and char and on the server it would check if they are close enough based on that but I didn’t think firing the server that many times with the players would be good. I got this idea from the video attached but the problem with the scripts in that one is that their is no claim time or anyway to contest the flag. Changing the .Touched event wouldn’t allow me to get the character or the player unless I use the idea that I was talking about before. Is their maybe an alternative to get the players character or is the idea mentioned above the only way?

Capture Flag System Video

There are several ways to get the player’s character, the easiest is by going through the Players object.

local Characters = {}

for i,vPlayer in ipairs(game.Players:GetChildren())
	if vPlayer.Character then
		table.insert(Characters, vPlayer.Character)
	end
end

This can be done on the server, preventing the need to use a local script at all.

I tried implementing what you said and it worked but I made a loop to check if the player leaves the zone and to pause the tween according to that. I can get it to pause but I cant figure out a way to break the loop whenever the Tween is done. I tried using Tween.Completed:Wait() but that would require another spawn function and would take it outside the while loop. How would I go about pausing the tween or maybe not even using a tween at all?

while true and wait(.2) do
	for _, plr in ipairs(game.Players:GetChildren()) do
		if plr.Character then
			local char = plr.Character
			local plr = game.Players:GetPlayerFromCharacter(char)
			local playerBoosts = plr:FindFirstChild("PlayerBoosts")
			local activeBoosts = playerBoosts:FindFirstChild("ActiveBoosts")
			local flagBoost = playerBoosts:FindFirstChild("FlagBoost")
			local LRtween = TS:Create(flagMiddle.FlagPart, Info, {Position = lowered.Position})
			if (flagMiddle.Base.Position - char.HumanoidRootPart.Position).Magnitude <= 65 then
				if flagSettings.PlayerID.Value ~= plr.UserId then
					if claiming == false then
						claiming = true
						local userId = plr.UserId
						local content, isReady = game.Players:GetUserThumbnailAsync(userId, thumbType, thumbSize)

						LRtween:Play()
						
						spawn(function()
							while true and wait(.2) do
								if not ((flagMiddle.Base.Position - char.HumanoidRootPart.Position).Magnitude <= 65) then
									LRtween:Pause()
								else
									LRtween:Play()
								end
							end
						end)

						playerName.Text = "Claiming..."

						LRtween.Completed:Connect(function()
							playerName.Text = plr.Name

							playerImg1.Image = content
							playerImg2.Image = content

							flagSettings.PlayerName.Value = plr.Name
							flagSettings.PlayerID.Value = plr.UserId

							activeBoosts.Value += flagBoost.Value

							claiming = false
						end)
					end
				end
			end
		end
	end
end

You don’t need a loop within the loop to find out when a player leaves the capture radius. Just store all the players who were within capture distance last interval, and if they’re not within the capture distance in the current interval, cancel their capture progress.

You should also switch out tween.completed and instead check for a number value. Add to the capture number if the flag is being captured, subtract it if it isn’t. If the number goes over 100, that’ll count as fully captured.

I get what your saying and implemented the capture progress but I still cant find a way for the Tween to cancel. It says I’m canceling the tween but it doesn’t do anything because Im playing the tween inside of another if statement.

while true and wait(.2) do
	for _, plr in ipairs(game.Players:GetChildren()) do
		if plr.Character then
			local char = plr.Character
			local plr = game.Players:GetPlayerFromCharacter(char)
			local playerBoosts = plr:FindFirstChild("PlayerBoosts")
			local activeBoosts = playerBoosts:FindFirstChild("ActiveBoosts")
			local flagBoost = playerBoosts:FindFirstChild("FlagBoost")
			local LRtween = TS:Create(flagMiddle.FlagPart, Info, {Position = lowered.Position})
			if (flagMiddle.Base.Position - char.HumanoidRootPart.Position).Magnitude <= 65 then
				if not table.find(charsInRange, char) then
					table.insert(charsInRange, char)
				end
				if flagSettings.PlayerID.Value ~= plr.UserId then
					if not claiming then
						LRtween:Play()
					end
					
					if table.find(charsInRange, char) then
						claiming = true
					end
					
					local userId = plr.UserId
					local content, isReady = game.Players:GetUserThumbnailAsync(userId, thumbType, thumbSize)

					playerName.Text = "Claiming..."
					
					captureProgress += 1

					if captureProgress == 100 then
						playerName.Text = plr.Name

						playerImg1.Image = content
						playerImg2.Image = content

						flagSettings.PlayerName.Value = plr.Name
						flagSettings.PlayerID.Value = plr.UserId

						activeBoosts.Value += flagBoost.Value

						claiming = false
					end
				end
			else
				claiming = false
				captureProgress = 0
				LRtween:Cancel()
				if table.find(charsInRange, char) then
					table.remove(charsInRange, table.find(charsInRange, char))
				end
			end
		end
	end
end

LRtween needs to be declared outside of the function. Make sure there is also only one LRtween as well.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.