CaptureFlagService - Simplified CTF Module

Introduction to CaptureFlagService

What is CaptureFlagService?

CaptureFlagService is a simple yet flexible module that helps developers with Capture The Flag. This module aims to replace Roblox’s old CTF system and help cut development time significantly for developers in need of a CTF system.

Why should I use this?

If you’re creating a game that includes a capture the flag gamemode (or its entirely based around capture the flag) but you don’t want to spend a lot of time on creating a system or you’re just not so sure where to begin, this module will provide you the necessary components to help with these issues. It essentially acts as the middleman for these dilemmas. And if you feel like there’s something missing with the module (or you want to add something that’s specifically for your game), you can easily modify the source code.

Getting Started

All you need to do is get the module here and place it into a desired location. Within the module is a script containing the full documentation of the system’s functions and some example code. This post also contains full documentation. To demonstrate how simple it is to set up, here’s a snippet of code I made while working on this post!

-- Example Code
local CaptureFlagService = require(game.ReplicatedStorage.CaptureFlagService)
local RedTeam = game.Teams:WaitForChild("Red")
local BlueTeam = game.Teams:WaitForChild("Blue")

local RedFlag = CaptureFlagService.new(RedTeam, workspace.RedTeamStand)
local BlueFlag = CaptureFlagService.new(BlueTeam, workspace.BlueTeamStand)

As for the flag model, all you need to do is set one part to the PrimaryPart (or call it “Flag”) and another part called “MainPad” (or “Pad”).


And there you go! Now you’re ready to start using the system!

Documentation

Exclusive Module Variables

CaptureFlagService.SystemEnabled
Determines if all flags can be captured or not. It also affects if the player can score or not.

CaptureFlagService.TeamScoreActive
Determines if scores are all added up or not.

CaptureFlagService.SoundEnabled
Determines if the sound is plays after the flag is captured or not.

CaptureFlagService.SpectateColors
A table containing teams that the system will ignore all interactions with.

CaptureFlagService.DropParent
The location of where the flag will be dropped. This goes in conjunction with Droppable.

CaptureFlagService.ScoreName
The name of the corresponding leaderstats score.

Module & Logic Variables

CaptureFlagService.FlagType or Logic.FlagType
Determines the type of flag the player will receive when capturing a flag. Types include Accessory and Tool.

Accessory - Gives the player an accessory of the flag.
Tool - Gives the player a tool of the flag.

CaptureFlagService.ShowPlayerLocation or Logic.ShowPlayerLocation
Determines if the location of the person holding the flag is shown or not.

CaptureFlagService.LocationImage or Logic.LocationImage
The image ID for the “LocationImage” class. Goes in conjunction with ShowPlayerLocation.

CaptureFlagService.LocationImageSize or Logic.LocationImageSize
Determines the size of the “LocationImage” class. Goes in conjunction with ShowPlayerLocation.

CaptureFlagService.ChangeLocationImageColor or Logic.ChangeLocationColor
Determines if the color of the “LocationImage” class corresponds with the team’s color or not. Goes in conjunction with ShowPlayerLocation.

CaptureFlagService.ScoreSound or Logic.ScoreSound
The Sound instance that goes in conjunction with SoundEnabled.

CaptureFlagService.Droppable or Logic.Droppable
Determines if the flag is droppable or not after the player dies.

CaptureFlagService.DropType or Logic.DropType
Determines the dropped flag’s type. Types include Stay, TeamGrab, and TouchReturn. Goes in conjunction with Droppable.

Stay - Flag stays in the location where the player died until the ReturnTime is up.
TeamGrab - Flag stays in location where the player died until the ReturnTime is up or a teammate grabs and returns the flag to the pad.
TouchReturn - Flag stays in location where the player died until ReturnTime is up or a teammate touches the dropped flag.

CaptureFlagService.ReturnTime or Logic.ReturnTime
The amount of time it takes for a flag to return to its stand. Goes in conjunction with Droppable.

CaptureFlagService.DropOffset or Logic.DropOffset
Determines the offset of the flag’s drop. It is highly suggested to keep the Y axis above 0. Goes in conjunction with Droppable.

CaptureFlagService.PadBehaviorType or Logic.PadBehaviorType
Determines the behavior of the team’s FlagPad. Types include Touch and Radius.

Touch - A physical touch requires for the flag to be captured.
Radius - Player needs to be in a certain radius below PadRadial in order for the flag to be captured.

CaptureFlagService.PadRadial or Logic.PadRadial
The maximum amount of distance of the FlagPad. PadBehaviorType must be set to Radius in order to work.

Logic Variables

Logic.Team
The team associated with the data.

Logic.FlagModel
The flag’s model.

Logic.FlagOwner
The owner of the captured flag.

Logic.FlagHandle
The FlagModel’s handle.

Logic.FlagPad
The FlagModel’s pad.

Logic.Enabled
Determines if the flag is enabled or not.

Logic.Captured
Determines if the flag is captured or not.

Logic.Dropped
Determines if the flag is dropped or not.

Module Functions / Methods

CaptureFlagService.new(Team teamObject, Model flagModel)
returns Instance Logic

Creates new team data for the system.

CaptureFlagService:FindTeam(Team teamObject)
returns Instance Data, Integer tableOrder
Finds data relating to the team.

CaptureFlagService:RemoveTeam(Team teamObject)
Removes the team’s data.

CaptureFlagService:IncreaseScore(Player player, Team teamObject)
Increases the player’s corresponding score.

CaptureFlagService:ResetScore(Team teamObject)
Resets the scores of the player and the team.

CaptureFlagService:SyncData()
Syncs all team data with the System’s data.

Logic Functions / Methods

Logic:AddModel(Model newModel)
Sets the data’s FlagModel, FlagHandle, and FlagPad to the newModel.

Logic:RemoveModel()
Removes the FlagModel associated with the data. This includes FlagHandle and FlagPad.

Logic:Reset()
Resets the data’s capture state.

Logic:OnGrabbed()
Fires when someone grabs the flag.

Logic:OnDropped(BasePart handle)
Fires when the flag is dropped.

Update Logs

v1.1.0
  • Added new functionality: PadBehaviorType, PadRadial, and DropType! See documentation above for more details. Thanks to @TecmagDiams for the suggestions.
  • Slight internal reworks to compensate for the new variables.
  • Added new Module functions: ResetScore() and SyncData().
  • Logic variables can now work independently from the system’s variables!
  • Logic:AddModel() will now search for the PrimaryPart of newModel (if the variable is a Model)!
v1.0.0
  • Official release!
  • Entire rescript of beta’s code (because it was unnecessarily complex and felt ugly).
  • Added all the basic functionality into the module.

Additional Information

If you find any bugs and issues, please report them to me. Suggestions are also appreciated.

If you wish to test out this system in a live setting, I’ve also created an example place that has 4 teams! https://www.roblox.com/games/4275533970/Capture-The-Flag-System-Example

21 Likes

Didn’t get to look at this in-game or anything since I’m not at home and can’t access Studio or anything, but I wanted to call out a few things not mentioned in the thread and that might be more useful for a more versatile system.

  1. Flags should be models with the handle as their PrimaryPart. This is better aligned with the purpose of a model. The flag can then be made of as many parts as a developer wants, with constraints holding it together in the DataModel.
  2. There should be a quick variable as part of initializing things (maybe per-flag? maybe a game internalize?) in which controls flag behavior from a set of options: eg. does killing the flag holder immediately return the flag or drop it? Do dropped flags get picked up and carried (meaning you need to return it yourself) or do they teleport back when recaptured, or do they just need to be defended for a short time and teleport themselves back?
  3. Same but for pad behavior. Do pads need their flag at them in-order for a flag to be brought to them for capture or no?
1 Like

Currently, the flag system searches for objects that are named FlagHandle, Flag, and Handle rather than the PrimaryPart. This is actually an extremely good suggestion that I should’ve done in the beginning and I will get to working on it right now.

Some of these variables already exist within the module (both per-flag and the system) such as the flag being dropped after death and determining if the flag returns on death or stays in the location where the player died. But I have yet to add some of these such as binding for dropping the flag, determining if a teammate has to carry the flag to their base, defend it, simply touching it, etc.

Same thing applies to the behavior of the pad but to a lesser extent. Which I never really thought about up until this point. I sincerely appreciate this feedback.

3 Likes

Awesome, sounds like we’re on the same page already, haha. I have no doubt you can get the model implementation of the flag working in no time honestly.

As far as the variable options for configuring how things work, awesome that it already was designed with these kinda things in mind. Once you’ve added those I think you could have a really solid system by adding documentation that beginner game makers that want to focus on making a cool game for them and their friends to play rather than learning scripting itself could use to bring their ideas to life.

I think a lot of people forget that one of the most powerful ways people get into programming is by simply being able to make things for them and their friends to enjoy, haha.

1 Like

Yeah haha. I already added a script containing documentation but I was thinking of also adding the documentation here as well.

1 Like

Updates have been implemented and I also decided to add the full documentation to the post. Thanks @TecmagDiams for the suggestions!

1 Like

Hey man, i really like your flag set here, but i was trying to put a billboard gui marker over the flag so all players can see where the flag is in the world. problem is, is that the gui duplicates and it stays hovering over the flag when you pick it up, and one just stays over the flagstand where the flag used to be.

is there any way i can destroy the marker so this will stop happening?