How does TSB do it?

So, TSB (The Strongest Battlegrounds) has a badge that players can obtain around every 15 minutes in a private or public server. This being an orb that when touched by a player, awards a badge. The orb only spawns every 15 minutes and in a different location each time. My guess is that they use parts in Workspace that the orb randomly can fall and crash near. If you would like to see this in action, you can click here to create a private server and spawn the orb after waiting.

Screenshot 2025-03-18 202439
(A picture of the chained key orb when it falls from the sky and crashes.)

Screenshot 2025-03-18 201806
(This is my orb. I know it looks awful, but this is just a placeholder lol. I made this in 5 seconds.)

How would I replicate this? I’m still a beginner and this is pretty hard.

I would really appreciate your suggestions and scripts, as I think this would be a really cool addition for my game.

1 Like

TSB uses TweenService to make the orb drop from the sky in a smoother manner. I suggest you to read the documentation on that before continuing!

Considering that you have created a folder with possible spawn point for this orb, I’ll just help write the skeleton of this system:

local spawnLocations = workspace.SpawnLocations -- Replace with your own folder
local previousSpawnPoint
local orb = game.ServerStorage.Orb -- I'm assuming you keep the orb part in ServerStorage. Feel free to change this!
local tweenService = game:GetService("TweenService")
local tweenInfo = TweenInfo.new() -- You can customise this, but I'll leave this blank for now

while true do

   task.wait(15 * 60) -- Waits 15 minutes
   local chosenSpawn = spawnLocations:GetChildren[math.random(1, #spawnLocations:GetChildren())] -- :GetChildren returns a table, so what we're doing is selecting a random index from the returned table, using math.random
   -- #spawnLocations:GetChildren() simply gets the number of values in the table spawnLocations:GetChildren()

   if previousSpawn ~= nil and previousSpawn == chosenSpawn then -- This checks if the selected spawn has been previously selected before, and selects a new spawn if so
       repeat
           chosenSpawn = spawnLocations:GetChildren[math.random(1, #spawnLocations:GetChildren())] 
       until chosenSpawn ~= previousSpawn
    end
       previousSpawn = chosenSpawn

       local orbClone = orb:Clone
       orbClone.Parent = workspace
       orbClone.Position = chosenSpawn.Position + Vector3.new(0, chosenSpawn.Position.Y + 20, 0) -- Simply sets the cloned orb to the position of the chosenSpawn, but 20 studs offsetted from the ground.
       tweenService:Create(orbClone, tweenInfo, {
         Position = chosenSpawn.Position}):Play() -- Tweens the orb up from the sky to its spawn point.
end
4 Likes

Well, if you want to keep the 15 minute intervals, then you would have something like this:

local badgeId = --your badge id here

while true do
   wait(15*60)
   local NewMeteor = game.ServerStorage.YourMetorHere:Clone() --have your meteor in server storage
   --code to tween it
   NewMeteor.Touched:Connect(function(otherpart)
      plr = game.Players:FindFirstChild(otherpart:FindFirstAncestorOfClass("Model").Name)
      if not plr then return end
      game:GetService("BadgeService"):AwardBadge(plr.UserId, badgeId)
   end)
   
end

You can use @HelpSupport01 's code for the tweening!

1 Like

Hey @HelpSupport01, sorry for the super late reply. I kinda fell asleep. But if I wanted to award the player a badge when they touch it, would I just include that badge award script that @The_DuckDeveloper made, and include that script inside the one you made? Or would I make a “badge award on touch” script that will go inside the orb in ServerStorage.

Arguably you could probably separate the code for spawning a meteor and the actual loop itself for readability.

-- Services
local Players = game:GetService("Players")
local BadgeService = game:GetService("BadgeService")
local ServerStorage = game:GetService("ServerStorage")

-- Instances
local CrashSpots = workspace:FindFirstChild("CrashSpots") -- Folder containing parts
local Meteor = ServerStorage:FindFirstChild("Meteor") -- Your original meteor is here.

-- Variables
local badgeId = 0000000 -- Your Badge ID goes here.

-- Functions
local lastSpot = nil
local function GetRandomCrashSpot() : Part
   local Spots = CrashSpots:GetChildren() -- Returns a list of the parts underneath the "CrashSpots" folder.

   -- Check for a potential spot to spawn the meteor.
   while true do
      local PotentialSpot = Spots[math.random(1,#Spots)]
      if PotentialSpot == lastSpot then continue end -- Do not pick the same spot twice in a row.
      lastSpot = PotentialSpot
      return PotentialSpot
   end
end

local function SpawnMeteor() : never
   -- Clones the original meteor.
   local NewMeteor = Meteor:Clone()

   -- Connects a function to the "Touched" signal of the Meteor. Awards the player a badge upon contact with the meteor.
   NewMeteor.Touched:Connect(function(Part : Part)
      local Player = Players:FindFirstChild(Part:FindFirstAncestorOfClass("Model").Name)
      if not Player then return end
      BadgeService:AwardBadge(Player.UserId, badgeId)
   end)

   -- Moves the Meteor to the workspace so it can be seen.
   NewMeteor.Parent = workspace

   local RandomSpot = GetRandomCrashSpot()
   -- TODO: Insert the tween animation code here.
   
end

-- Code Execution
while true do
   wait(15*60)
   SpawnMeteor()
end
1 Like

Thank you for that. I will try your guy’s suggestions soon. However, I would like it so only one player could get the badge, so it’s kind of a race to see who can get it.