How To Make A Boss Fight
☆⸻●⸻☆
The title summed up pretty much everything so maybe scroll down to see specific features in details.
[Reminder for me to put a video here]
Introduction 
Introduction ![]()
Hi everyone! This post was made in order to help you guys with designing interesting boss fights
It took me over 3 years of learning and about 2 years of developing my own game to finally make this possible, so hopefully you find it helpful!
New attacks will be added overtime so come back every once in a while!
I’ll occasionally provide updates to fix bugs or improve the system (Any help would be appreciated!)
During special occasions like Halloween or Christmas, you can expect to see even more premade bosses and attacks themed around those events, which are free for use (Basically similar to game events)
How this system works:
- All bosses are controlled from a main ModuleScript (BossController), which can be activated by requiring it from a Script and providing additional settings/configurations.
- In there, most of the basic functions and logic will run to make the bosses move, wander, find target, attack, regenerate their health, run animations, run death effects, etc...
- Bosses have Defense, Immunities like 🔥 Fire, 🧊 Ice, ⚡ Stun, 💀Poison. These are set as attributes. Without them, a boss can be stunned, frozen, slowed down or weakened, so make sure you balance the stats well.
- Bosses can use abilities/attacks. Each boss has their own global attack cooldown + local cooldown for each type of attack
- Attacks are activated through a RemoteEvent, so it's fine if the boss model gets destroyed while an attack is still happening
Free Ability/Attack Examples (? Presets/Templates) 
Free Ability/Attack Examples (? Presets/Templates) ![]()
Please read the notice in Credits section below. Thanks! More attacks will be added overtime
All of them can be found in the Attack folder in ServerScriptService of the test place
You can find newly added and undocumented attacks by checking the test place!
Basic - The foundation of all other attacks
Explosions
Create an explosion to deal damage to all targets caught within its blast radius. Damage falloff scales with the distance. There are 10+ explosion effects for you to choose from, including making it invisible
FunctionBank.CreateExplosion(
Creator,
Position,
Radius,
1.5, --Ratio between the outer and inner sphere, might be removed later once I can
Color3.fromRGB(255, 0, 0), --Color of the outer explosion sphere (Not all effects have the sphere so this will be the main color of their ParticleEmitters)
Color3.fromRGB(85, 0, 0), --Color of the inner explosion sphere
Damage,
Force,
false, --ForceScaleWithMass?
true, --DamagePlayer?
"Realistic"
)
Status Effects
Call this function and provide a target with an effect name as well as other settings. Check explanation to see all the effects and their behaviors
local Effect = "Stun"
local Duration = 5
FunctionBank.AddEffect(Target, Effect, Duration, {
Creator = Caster.Character
})
Melee - Close-ranged attacks
- Method 1: Create an explosion using FunctionBank.CreateExplosion(…) right at the boss’s location, set the effect to invisible if you only need the animation, otherwise pick any fitting effect
- Method 2: Loop through all the descendants of the workspace, then check their distance from the boss and deal damage
- Method 3: Call FunctionBank.GetPartsInPart(…) and provide the arguments needed, then check their distance and deal damage. You can also provide a custom hitbox part in this function if you have a sword or something
- [WIP]
Swing
Play an animation before dealing damage to targets caught within the range
["Swing"] = function(Caster, AttackSettings)
task.spawn(function()
if AttackSettings then
FunctionBank.PlaySound(FunctionBank.Roll(HitSounds), Caster.Root, nil, 3, 1, false, false, nil, true)
FunctionBank.PlayAnimation(Caster.Character, Caster.Animator, ClientFunctionBank.CheckRigType(Caster.Character) == "R15" and FunctionBank.Roll(R15SwingAnims) or FunctionBank.Roll(R6SwingAnims), nil, "Action", false, true, false, nil, nil, 1.75)
if string.find(Caster.Character.Name, "Headless Horseman") then
local Start = Caster.Root.Position
FunctionBank.CreateExplosion(
Caster.Character,
Start,
AttackSettings.Range or 10,
1.25,
Color3.fromRGB(255, 85, 0),
Color3.fromRGB(255, 170, 0),
AttackSettings.Damage or 25,
10,
false,
true,
"Slash",
AttackSettings.Effect or nil
)
task.wait(0.15)
for i = 1, 2 do
local RingRadius = 25 + (i - 1) * 50
for e = 1, 6 do
local Angle = (e / 6) * (math.pi * 2)
local Offset = Vector3.new(
math.cos(Angle) * RingRadius,
0,
math.sin(Angle) * RingRadius
)
FunctionBank.CreateExplosion(
Caster.Character,
Start + Offset,
AttackSettings.Range / 3,
1.25,
Color3.fromRGB(255, 85, 0),
Color3.fromRGB(255, 170, 0),
AttackSettings.Damage / 2,
10,
false,
true,
"Slash",
AttackSettings.Effect or nil
)
task.wait(0.05)
end
end
else
FunctionBank.CreateExplosion(
Caster.Character,
Caster.Root.Position,
AttackSettings.Range or 10,
1.25,
Color3.fromRGB(255, 255, 255),
Color3.fromRGB(255, 255, 255),
AttackSettings.Damage or 25,
10,
false,
true,
"Invisible",
AttackSettings.Effect or nil
)
end
end
end)
return AttackSettings.Cooldown
end,
Shockwaves/Slam/Smash
Create a ring-shaped shockwave that gradually grows bigger. Can easily be avoided by jumping over the ring at the right moment
Ranged - Far-ranged attacks
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
Throw Projectiles
Fire Projectiles
Shards
Beam
Shoot a beam straight at the goal position. This beam will deal damage to all targets inside it every tick until each target reach the limit for how many hits they can take
Flamethrower/Fire Breath,/Blazing Breath
Laser Projectiles
Spinning Lasers
Lightning Strike
Lava Rise/The Floor Is Lava
Missiles/Rockets
Cluster Bombs
Mini Nuke Launcher
Movement - Bosses perform physical actions and move to somewhere
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
Rush/Charge
Leap/Jump & Slam
Leap Shockwaves
Teleport/Warp
Dash
Reality Altering - You can't do this in real life, so why not break it online?
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
Stop Time
Rewind Time
Skip Time
Accelerate/Decelerate Time
Curruption
Defense - The strongest defense is the strongest offense
- [WIP]
- [WIP]
- [WIP]
- [WIP]
Heal
Hidden/Camoflag/Stealth/Void Cloak
Energy Shield/Block Hits
Thorn/Damage Reflect
Others - Attacks that do not need a range or even a target
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
- [WIP]
Body Control + Disable Gears
Self Destruct
Spawn Minions
Jumpscare
Send Friend Request
Chat/Send Messages
Dance
Clones
Deploy Decoys
Shapeshift
Explanation:
Status effects, I tried making them as unique as possible. They can be applied to bosses or players with customizable settings
-
Stun: Stuns and stops the target from moving with a strong force. For heavy targets or those with Stun Immunity, the target is not stunned but rather slowed down along with their animation speed. Can set tick, can set stun type (Zap/Shock/Paralyze) or color with variant. Effect emits once every tick. Tick, Force and AnimationSpeed factor are affected by Stun Immunity -
Fire: Burns to deal DoT and melt defense -
Acid: Corrodes to deal DoT and melt defense -
Radiation: Deals DoT, also melts and ignores defense -
Poison: Deals DoT while bypassing defense, damage (%) depends on the MaxHealth of the target -
Bleed: Deals DoT, damage grows after each tick until the limit is reached, also reduces the WalkSpeed and JumpPower of the target based on the % of Health remaining -
Heal: Heals target -
Ice: Freezes the target to reduces defense, stops any movements or animations while retaining physics, creates a thin ice layer on the character. Utilizes my FreezeModule. If the target is 100% immune to this then
Chill will be applied instead -
Chill: Slows down chilled targets, freeze amount depends on FreezeAmount setting and the IceImmunity of the target -
Confusion: If the target is a Player, their control is inverted (all devices), otherwise, the movement of the target is reversed/heavily altered -
Void: Halves the damage that the target can deal when applied -
Lifesteal: Takes HP from the target to heal the attacker. Lifesteal amount is affected by Defense, Void immunity and is multiplied by LifestealBoost stat. Must provide Creator in the settings -
Love-Link: (Will be added one day): Electrocuts targets near the main target who is being affected by this effect, lightning strikes will link the affected targets together -
Explosion: (Will be added on New Year Eve): Instantly kills the target and then creates an explosion afterwards -
Teleportation: (Will be added on ??? event): Randomly teleports the target to a random location at random time
Examples of status effects being applied
- You apply
Fire with 100 damage per tick for 5 seconds to a Noob who has Defense = 50(%), FireImmunity = 50, he will only take 25 damage every tick for 2.5 seconds. - You apply
Ice for 2 seconds to a Snowman that has IceImmunity = 100, it will not be frozen at all. - You apply
Poison with 1% MaxHealth as damage per tick for 10 seconds to a Zombie who has Defense = 90, PoisonImmunity = 150, it will not take any damage, but heal up by 1.5% of its MaxHealth per tick for 10 seconds. Poison ignores Defense - You apply
Acid with 100 damage per tick for 5 seconds to a Robot that has Defense = 50, AcidImmunity = -50, it will take 75 damage every tick for 7.5 seconds. - You apply
Radiation with 100 damage per tick for 5 seconds to a Golem that has Defense = 100, no RadiationImmunity, it will take 100 damage every tick for 5 seconds. Radiation ignores Defense - You apply
Confusion for 5 seconds to a Player without ConfusionImmunity, their control will be inverted during that time (WASD → SDWA on PC, opposite movement direction on all devices) - You apply
Failure with infinite emotional damage per tick to a Player forever, they will not be happy and will most likely dislike your game
And now other things
-
DoT: Damage over time. Damage is applied every Tick
-
Defense: How many % of damage that a character can block. The effective damage dealt towards a character is decreased if its defense amount is higher than 0. However, Poison & Radiation can both bypass/ignore defense
-
Immunity:: How many % of damage that a character can block from the same type of effect they are immune to, can stack with Defense (Full Damage → Reduced by Defense → Reduced by Immunity)
-
Defense-melting: Reduce defense, each type of elemental status effect can only drop up to a certain amount of defense and does not stack with the same type of status effect
-
Tick: The rate at which the effect deals damage or activates. Basically firerate
-
Duration: How long the effect will be applied for. This timespan can be shorten by an immunity (0%-100%). If the immunity is higher than 100%, then the duration is not changed. Else if the immunity is lower than 0%, then the duration is increased. Duration is also stackable if an effect allows it
-
Creator: The Player instance or the character of a player (Module auto checks), is used to tag targets and recognize total damage contributed and the final hit dealer. Does not tag if the Creator is not a player
-
Variant: Customize an effect or give it a different mechanic. This is because you can’t send info to the CollectionService
-
AoE/CC: Refering to area of effect or crowd control. Basically the ability to hit multiple targets at once with or without a limit in a specific range. Usually seen in explosive attacks
Free Bosses 
Free Bosses ![]()
🎃 Headless Horseman
Go through this portal in the test place
You can skip all other steps if you have already defeated the same boss in MBB
Find this statue and activate the proximity prompt
Defeat the boss to claim the model
Source Code/Main Scripts 
Source Code/Main Scripts ![]()
BossController (The main ModuleScript you require):
local BossTemplateController = {}
BossTemplateController.__index = BossTemplateController
local RS = game:GetService("ReplicatedStorage")
local SS = game:GetService("ServerStorage")
local SSS = game:GetService("ServerScriptService")
local TS = game:GetService("TweenService")
local Debris = require(SSS.DebrisGobbler.DebrisGobbler)
local Players = game:GetService("Players")
local Lighting = game:GetService("Lighting")
local Running = game:GetService("RunService")
local DebrisHolder = workspace:FindFirstChild("DebrisHolder")
local Attacks = SS:FindFirstChild("Attacks")
local Animations = RS:FindFirstChild("Animations")
local AttackServer = RS:FindFirstChild("RemoteEvents"):FindFirstChild("AttackServer")
local GameConfig = require(RS.GameConfig)
local FunctionBank = require(SS.ServerFunctionBank:FindFirstChild("FunctionBank"))
local ClientFunctionBank = require(RS:FindFirstChild("ClientFunctionBank"))
local StatsHandler = require(SSS.Main.StatsHandler)
local DefaultStats = GameConfig.DefaultStats
function BossTemplateController.New(Boss, Settings)
local self = setmetatable({}, BossTemplateController)
self.Character = Boss
self.Settings = Settings or {}
self.Humanoid = Boss:FindFirstChildOfClass("Humanoid")
self.Animator = self.Humanoid and self.Humanoid:FindFirstChildOfClass("Animator")
self.Root = self.Humanoid and self.Humanoid.RootPart or Boss:FindFirstChild("HumanoidRootPart")
self.Head = Boss:FindFirstChild("Head")
self.CanMove = true
self.Attacking = false
self.Walking = false
self.Phase2 = false
self.Cooldown = false
self.OriginalPosition = self.Root and self.Root.Position
self.PreviousState = Enum.HumanoidStateType.Physics
self.Settings.Anims = self.Settings.Anims or {}
self.WalkAnim = self.Settings.WalkAnim or self.Settings.Anims.Walk or Animations:FindFirstChild(Boss.Name .. " Walk")
self.Settings.Anims.Idle = self.Settings.Anims.Idle or Animations:FindFirstChild(Boss.Name .. " Idle")
if Boss.Name == "Fallen Emperor" then
self.WalkAnim = Animations["Fallen Emperor Walk"]
self.Settings.Anims.Idle = Animations["Fallen Emperor Idle"]
self.Settings.Anims.RageWalk = Animations["Fallen Emperor Rage Walk"]
end
self:InitializeAttacks()
self:InitializeBoss()
self:StepRegenerate()
return self
end
function BossTemplateController:InitializeAttacks()
AttackServer.Event:Connect(function(Status, Boss)
if Status == "Finished" and Boss == self.Character then
self.CanMove = true
self.Attacking = false
end
end)
end
function BossTemplateController:InitializeBoss()
local Boss = self.Character
local Humanoid = self.Humanoid
local Animator = self.Animator
local Root = self.Root
Boss:SetAttribute("State", "Normal")
if not Humanoid then return end
if Boss.Name == "Fallen Emperor" then
local Anim = FunctionBank:PlayAnimation(Boss, Animator, Animations["Fallen Emperor Spawn"], nil, "Action", false, false, true)
Anim:GetMarkerReachedSignal("Landed"):Connect(function()
FunctionBank:CreateExplosion(Boss, Root.Position, 150, 1.25, Color3.fromRGB(61, 95, 120), Color3.fromRGB(0, 85, 127), 250, 400, false, true, "Blue Fallen", "Stun 5 0", "JointBreak")
FunctionBank:CreateShockwave(Boss, "Boss", 200, "Ground", 1, 300, 600, Root.Position, Color3.fromRGB(0, 0, 0), false, nil, "JointBreak")
end)
task.wait(2)
end
if self.Settings.MovementAnimation then
FunctionBank:PlayAnimation(Boss, Animator, self.Settings.Anims.Idle, nil, "Idle", true, false, true)
end
local AnimationConnection
AnimationConnection = Humanoid.Running:Connect(function(Speed)
if not self.Settings.MovementAnimation or self.Attacking then return end
local State = Humanoid:GetState()
if State == Enum.HumanoidStateType.Running and Speed > 5 and self.CanMove then
if not self.Walking then
FunctionBank:PlayAnimation(Boss, Animator, self.WalkAnim, nil, "Movement", true, false, true, nil, nil, self.Phase2 and 2 or 1)
self.Walking = true
end
elseif State == Enum.HumanoidStateType.Seated then
Humanoid.PlatformStand = false
Humanoid.Jump = true
if self.Walking then
FunctionBank:PlayAnimation(Boss, Animator, self.Settings.Anims.Idle, nil, "Idle", true, false, true)
self.Walking = false
end
else
if self.Walking and State ~= self.PreviousState then
FunctionBank:PlayAnimation(Boss, Animator, self.Settings.Anims.Idle, nil, "Idle", true, false, true)
self.Walking = false
end
end
self.PreviousState = State
end)
local HealthConnection
HealthConnection = Humanoid.HealthChanged:Connect(function()
if Humanoid.Health <= Humanoid.MaxHealth * 0.8 then
for i, v in ipairs(Boss:GetDescendants()) do
if v:GetAttribute("Destroyable") then
local Destroyable = v:GetAttribute("Destroyable")
if Humanoid.Health <= Humanoid.MaxHealth * Destroyable then
FunctionBank:CreateExplosion(Boss, v.Position, 5, 1.5, v.Color, v.Color, 0, 1, false, true, "VFX")
v:Destroy()
end
end
end
end
if Humanoid.Health <= Humanoid.MaxHealth * 0.5 then
if self.Settings.Phase2 then
if self.Settings.Anims.RageWalk then
self.WalkAnim = self.Settings.Anims.RageWalk
end
if not self.Phase2 then
self.Phase2 = true
StatsHandler.AddModifier(Boss, "DamageBoost", "Phase2", self.Settings.DamageBoost)
StatsHandler.AddModifier(Boss, "WalkSpeed", "Phase2", self.Settings.WalkSpeedBoost)
if Boss.Name == "Fallen Emperor" then
local Anim = FunctionBank:PlayAnimation(Boss, Animator, Animations["Fallen Emperor Rage"], nil, "Action", false, false, true)
Anim:GetMarkerReachedSignal("Stomped"):Connect(function()
FunctionBank:CreateExplosion(Boss, Root.Position, 150, 1.25, Color3.fromRGB(61, 95, 120), Color3.fromRGB(0, 85, 127), 250, 400, false, true, "Blue Fallen", "Stun 5 0", "JointBreak")
FunctionBank:CreateShockwave(Boss, "Boss", 200, "Ground", 1, 300, 600, Root.Position, Color3.fromRGB(0, 0, 0), false, nil, "JointBreak")
task.wait(0.25)
Humanoid:ChangeState(Enum.HumanoidStateType.Landed)
end)
end
end
if Humanoid.Health <= 0 then
if HealthConnection then
HealthConnection:Disconnect()
HealthConnection = nil
end
if AnimationConnection then
AnimationConnection:Disconnect()
AnimationConnection = nil
end
if self.Walking then
self.Walking = false
end
if self.Attacking then
self.Attacking = false
end
end
end
end
end)
end
function BossTemplateController:MoveTo(TargetRoot)
if not self:IsAlive() then return end
local Hit, EndPosition = workspace:FindPartOnRayWithIgnoreList(Ray.new(self.Root.Position, self.Root.CFrame.LookVector.Unit * (self.Root.Size.Z * 2.5)), {self.Character})
if Hit and Hit.Parent and Hit.Parent ~= self.Character then
self.Humanoid.Jump = true
end
if typeof(TargetRoot) == "Vector3" then
self.Humanoid:MoveTo(TargetRoot)
self.Character:SetAttribute("CurrentCursorPosition", TargetRoot)
self.CurrentCursorPosition = TargetRoot
else
self.Humanoid:MoveTo(TargetRoot.Position, TargetRoot)
self.Character:SetAttribute("CurrentCursorPosition", TargetRoot.Position)
self.CurrentCursorPosition = TargetRoot.Position
end
end
function BossTemplateController:Wander()
if not self:IsAlive() or not self.Settings.Wander then return end
local WanderOffset = Vector3.new(math.random(-self.Settings.WalkRadius, self.Settings.WalkRadius), 0, math.random(-self.Settings.WalkRadius, self.Settings.WalkRadius))
local TargetPosition = self.Root.Position + WanderOffset
self:MoveTo(TargetPosition)
end
function BossTemplateController:StopMoving()
if not self:IsAlive() then return end
self:MoveTo(self.Root)
self.CanMove = false
end
function BossTemplateController:IsAlive()
if self.Settings.Object then return true end
return self.Character and self.Character.Parent and self.Humanoid and self.Root and self.Humanoid.Health > 0
end
function BossTemplateController:StartAttackCycle()
if not self:IsAlive() then return end
local AttackCycle = self.Settings.AttackCycle
local Boss = self.Character
local TargetChar, TargetHum, TargetRoot = FunctionBank:FindTarget(Boss, self.Root, self.Settings.MaxFollowDistance, "All", "Closest")
if TargetChar and TargetChar.Parent and TargetHum and TargetHum.Parent and TargetRoot and TargetRoot.Parent then
local State = Boss:GetAttribute("State")
local Distance = (self.Root.Position - TargetRoot.Position).Magnitude
if State == "Normal" then
if self.CanMove and self.Settings.Move then
self:MoveTo(TargetRoot)
end
if not self.Cooldown then
local SelectedAttack
local AttackType = nil
local AttackOrderKey = nil
if Distance <= self.Settings.MeleeDistance and AttackCycle.Melee and next(AttackCycle.Melee) then
AttackType = "Melee"
AttackOrderKey = "MeleeAttackOrder"
elseif Distance <= self.Settings.RangedDistance and AttackCycle.Ranged and next(AttackCycle.Ranged) then
AttackType = "Ranged"
AttackOrderKey = "RangedAttackOrder"
end
if AttackType then
local AttackInfo = AttackCycle[AttackType]
local AttackPattern = AttackInfo.AttackPattern or "Ordered"
local Cooldown = AttackType == "Melee" and self.Settings.MeleeCD or self.Settings.RangedCD
self[AttackOrderKey] = self[AttackOrderKey] or 1
if AttackPattern == "Structured" and AttackInfo.Structured and #AttackInfo.Structured > 0 then
local Entry = AttackInfo.Structured[self[AttackOrderKey]]
if Entry and typeof(Entry) == "string" and string.sub(Entry, 1, 4):lower() == "wait" then
local DelayTime = tonumber(string.match(Entry, "%d+")) or 1
self.Cooldown = true
task.delay(DelayTime, function()
self.Cooldown = false
self.CanMove = true
self.Attacking = false
end)
else
SelectedAttack = {Attack = Entry, Settings = {}}
end
self[AttackOrderKey] = (self[AttackOrderKey] % #AttackInfo.Structured) + 1
elseif AttackPattern == "Random" then
SelectedAttack = AttackInfo[math.random(1, #AttackInfo)]
else
SelectedAttack = AttackInfo[self[AttackOrderKey]]
self[AttackOrderKey] = (self[AttackOrderKey] % #AttackInfo) + 1
end
if SelectedAttack then
self.Cooldown = true
task.delay(Cooldown, function()
self.Cooldown = false
self.CanMove = true
self.Attacking = false
end)
if SelectedAttack.Settings then
if SelectedAttack.Settings.StayStill then
self:StopMoving()
end
SelectedAttack.Settings.CurrentCursorPosition = TargetRoot.Position
end
self.Attacking = true
AttackServer:Fire(self, SelectedAttack.Attack, SelectedAttack.Settings or {})
end
end
end
elseif State == "Stunned" then
task.wait(self.Settings.ResponseRate)
end
else
self:Wander()
task.wait(self.Settings.WanderDuration)
end
end
function BossTemplateController:StepRegenerate()
task.spawn(function()
local RegenerateRate = DefaultStats.RegenerateRate
local RegeneratePercent = DefaultStats.RegeneratePercent
if not self.Settings.Regenerate then return end
while self:IsAlive() do
while self.Humanoid.Health < self.Humanoid.MaxHealth do
local DeltaTime = task.wait(RegenerateRate)
if self.Character:GetAttribute("RegeneratePercent") then
RegeneratePercent = self.Character:GetAttribute("RegeneratePercent")
else
RegeneratePercent = DefaultStats.RegeneratePercent
end
if self.Character:GetAttribute("RegenerateRate") then
RegenerateRate = self.Character:GetAttribute("RegenerateRate")
else
RegenerateRate = DefaultStats.RegenerateRate
end
local DeltaHealth = DeltaTime * (RegeneratePercent / 100) * self.Humanoid.MaxHealth
if self.Humanoid.Health > 0 then
self.Humanoid.Health = math.min(self.Humanoid.Health + DeltaHealth, self.Humanoid.MaxHealth)
end
if not self or not self.Humanoid.Parent or self.Humanoid.Health <= 0 then break end
end
self.Humanoid.HealthChanged:Wait()
end
end)
end
return BossTemplateController
Script (You have 1 in each boss model):
local Boss = script.Parent
local BossController = require(game:GetService("ServerScriptService").Main.BossController)
local ClientFunctionBank = require(game:GetService("ReplicatedStorage"):FindFirstChild("ClientFunctionBank"))
local BossSettings = {
ResponseRate = 1/60,
WanderDuration = 2,
MaxFollowDistance = 2000,
MeleeDistance = 80,
RangedDistance = 1000,
MeleeCD = 3,
RangedCD = 10,
WalkRadius = 150,
DamageBoost = 50,
WalkSpeedBoost = 4,
Phase2 = true,
MovementAnimation = true,
Move = true,
Wander = true,
Anims = {},
AttackCycle = {
Melee = {
[1] = {
Attack = "Swing",
Settings = {
Damage = 45,
Range = 80,
Effect = "Burn 5 5",
StayStill = true
}
},
},
Ranged = {
AttackPattern = "Ordered",
[1] = {
Attack = "Axe Throw",
Settings = {
Cooldown = 1,
Damage = 5,
ExplosionDamage = 300,
Radius = 45,
Range = 300,
Force = 30,
TravelTime = 1,
ReturnTime = 1.5,
Curve = true,
CurveFactor = 0.15,
StayStill = false
}
},
[3] = {
Attack = "Slices",
Settings = {
Damage = 100,
Cooldown = 3,
Radius = 30,
Force = 1.5,
Delay = 0.05,
Amount = 8,
Duration = 2,
Color1 = Color3.fromRGB(255, 85, 0),
Color2 = Color3.fromRGB(255, 170, 0),
StayStill = true
}
},
[4] = {
Attack = "Leap Shockwave",
Settings = {
Damage = 45,
Cooldown = 5,
Radius = 30,
MaxRange = 200,
Speed = 200,
Force = 40,
Amount = 3,
Randomness = 100,
StayStill = true
}
},
[2] = {
Attack = "E",
Settings = {
Damage = 25,
Cooldown = 1,
Radius = 30,
Force = 1.5,
Amount = 4,
OuterColor = Color3.fromRGB(255, 85, 0),
InnerColor = Color3.fromRGB(255, 170, 0),
StayStill = true
}
},
},
}
}
local BossController = BossController.New(Boss, BossSettings)
ClientFunctionBank:BindToInstanceDestroyed(Boss, function()
BossController = nil
end)
local ResponseRate = BossSettings.ResponseRate
while true do
BossController:StartAttackCycle()
task.wait(ResponseRate)
end
All other scripts:
Bruh you thought I can put the amount of text equivalent to 2 years of typing here huh?
Absolutely not! Go edit the uncopylocked place to see the rest as there are too much stuff for a single post with low character limit
Features 
Features ![]()
-
Pro OOP in the BossController module
-
Attacks shown are already made so you can just copy paste them into your game. They are also good for learning I suppose
-
Bosses have Defense (Take less damage), Immunities (Less vulnerable to damage or debuffs from status effects)
-
Most visual effects are handled on the client side → You can add easily add settings to reduce the quality or hide them, less stress on the server
-
Useful functions I’ve gathered over the years
-
Stats Handler - Manage layers of stats like WalkSpeed, JumpPower, Defense, etc… so that they don’t overlap/override each other. Useful for status effects and changing phases of bosses
-
Status Effect System - Deal damage over time, restrict movement, alter behavior, reduce defense or apply other unique mechanics depending on the effect type
-
Revamped Roblox’s TagHumanoid function - Know how much damage each player/boss have dealt in total + Final hit dealer
Limitations 
Limitations ![]()
-
I’m a bad modeler, so my coding skill is limited. HOWEVER, the models I make are also not really good (Jack of all trades, master of none moment)
-
I cannot animate or make visual effects
-
There might be pretty outdated stuff or change of coding style from time to time as I’m still learning how to code, most of the more advanced scripts were only made a few months before this post
-
The optimization isn’t that great. You should not have more than 10 bosses spamming insane amount of attacks too fast (Though I don’t see any reason to have >1~3 bosses at once)
Story 
Story ![]()
One day in 2022, I stumbed upon this tutorial by HowToRoblox, which was the beginning of everything
However, the biggest inspiration was a game called MEGA Boss Survival by Dinpey. As I was developing my fanmade game, Mega Boss Battles, I made this open-sourced FreezeModule for everyone to use with my little scripting knowledge
From then on, I kept learning more and more, making more public resources and improving until this boss fight system became somewhat acceptable
Update Logs 
Update Logs ![]()
Credits 
Credits ![]()
I feel like the mentions would be annoying so I removed @
- Dinpey - The legend, unfortunately terminated for a false reason - Big motivation
- Sub2HTR - Original boss fight tutorial - Big inspiration
- Lightlimn - Original StatsHandler module - The StatsHandler system being used
- Xan_TheDragon - FastCast module - Some attack projectiles use this
- verret001 - DebrisGobbler module - Replacement for Roblox’s outdated Debris service which stops working at 1k objects limit
- Mythamanx - Explosion damage calculation made easy - Realistic damage falloff for explosions
- ketrab2004 - Damage equation graph demonstration in Desmos (#6 from the damage falloff post above) - Helpful
- ThunderDaNub - Creator, made basically everything else - Please credit me if possible or let me know about your game when using this so I can try it out :D
Honorable mention:
- Toolbox - Effects and animations
- Roblox gears - Some attacks were heavily based on them
Notice about usage: If you plan to use any free premade attacks, make sure you have permission to use the animations, visual effect designs (ParticleEmitter, Trail, Beam), audio sound effects or boss models (UGC Accessory, Roblox Accessory). Some of them were taken from the Roblox Toolbox which might not always be safe for commercial use
Support Me - Check the game below to see this system in effect!
(Uncopylocked) Boss Fight System | Mega Boss Battles (Showcase) | Clothing Store |
Youtube Channel
Support Me - Check the game below to see this system in effect!












