Making Boss Battles Correctly

Hello, I’m DankDinoDragon.
Today I’ll be teaching you how to approach making Boss Battles in your game for beginners. There are definitely better ways to do this but this method is easy to follow for beginners. Making a boss battle may seem daunting at first. But with this guide your boss script won’t be way too long.
So there are two types of boss fights, survival boss fights, and health bar fights.
So the script layouts for the boss fights are:
Survival Bosses:

-- Variables
-- Attack Functions
-- Loop containing those attacks that repeat a few times
for i = 1, 3, 1 do -- Repeats all attacks inside here 3 times
-- Attacks
end
-- Ending cutscene or if you want to, add a phase 2 starting cutscene or whatever you want and then do another loop that repeats some new and preferably challenging attacks

Health Bar Bosses:
These bosses are a bit more difficult to make in my opinion but are still not too hard.

-- Variables
-- Attack Functions
local function Attack()
end
-- Loop of all the attacks 
while true do -- Repeats all the attacks
       for i = 1, 3, 1 do -- This makes players survive 3 rounds of all your attacks
            -- Put your attacks here.
       end
       -- Make boss vulnerable to take damage from players
      wait(CertainVulnerabilityTime) -- Give players time to attack the boss.
       If BossHealth <= Phase2HealthRequirement then
             break -- You don't have to make a phase 2. You can just check if the bosses health is 0 then end the boss here or if it isn't then repeat these attacks and make them go on until the bosses health is 0
       end
 -- If the boss didn't lose enough health to start phase 2 or if you don't want phase 2 and they just didn't die yet then make the boss invincible again until the attacks end again.
end

-- Phase 2 attacks 
while true do -- Repeats all the attacks
       for i = 1, 3, 1 do -- This makes players survive 3 rounds of all your attacks
            -- Put your attacks here.
       end
       -- Make boss vulnerable to take damage from players
       wait(CertainVulnerabilityTime) -- Give players time to attack the boss.
       If BossHealth <= 0 then -- Checks if boss is dead
             break
       end
       -- If the boss didn't die then make the boss invincible again until the attacks end.
end
-- Ending Cutscene

After making a boss fight, you should feel proud of yourself. They are difficult to make in games but are very rewarding since good bosses can enhance gameplay experience a lot.
Results of me making a Survival Boss Battle
Video: https://youtu.be/TvGAvNiO660
Note: The boss was made in less than 2 hours (I wanted to jump on the halloween event trend but jumped very late so I didn’t have much time before halloween), I know it’s repetitive and dull though this is still pretty good according to ratings from around 50 people who played it.
Game: Wishing Well Boss - City Hangout - Roblox
(For the game you have to click 3 green pumpkins around the map. One is near the pool, one is at the park, one is behind the waterfall. There is also another boss fight in a portal behind the waterfall if you want an extra challenge.)
The boss isn’t good but shows the nice results you can achieve using this method.

It’s a repetitive boss fight but it’s challenging and the second phase introduces 2 new attacks along with a more powerful ground slam attack.
Elements of a good boss battle:
Good design in a boss battle is key. Make sure that the boss battle is challenging and has good replayability. I recommend having 2 phases in a survival boss fight and just 2 phases in a health bar boss fight. Attacks in a boss battle need to make the player think it’s their fault that they got hit by the attack and not the game. If a boss battle attack is too hard or impossible to dodge the players will call the boss unfair. Good bosses in my opinion use cutscenes. Cutscenes hype up the incoming boss battle and establish some context to the fight. Imagine a player walking through a mysterious portal just to be teleported to some random person that wants to kill you. But then, think about the same boss but with a cutscene to explain why that person wants to kill you. Music brings a boss to the next level. In the example I showed of a survival boss fight. Try listening to it with music and then without music. The music version is so much better in my opinion. Also add some ending cutscenes if the boss in your game is important enough such as a final boss or first boss or boss guarding something important.

Anyways, these are all my tips for making a boss fight. I hope this tutorial takes your games to the next level!

PS: Script example I’ve provided will make a boss fight that is kinda repetitive though it’s designed to be as easy and possible for beginners (I know I could use module scripts to shorten my script though this is for beginners). For me the boss I’ve provided isn’t good for anyone that isn’t a beginner since you can start making better and more complex boss systems. The script I’ve provided isn’t for copy and pasting since I don’t have access to roblox studio currently and can’t test the script. Also sorry about the clickbaity title.

Note for advanced devs: This tutorial wasn’t directed towards you since a lot of you look down upon techniques used here. The code is messy, the boss isn’t random enough, I didn’t use modules. This was for beginners but if you’re here too you can utilize the techniques I said above. Modules, storing functions in a table which is someting I do to make random attacks and something someone has talked about in a reply to this post. If your comment to this post is about any of these topics I’ve acknowledged that this is for beginners.

Credits:

omgcchheeesseee - Provided amazing feedback (I’m bad at handling criticism though I try my best to take it in a good way.)

kingerman88 - Suggested I add a note to advanced devs to talk about some techniques that they could use when making bosses + helped me realized I accidently captitalized my while true do loop (I made this at 10:00 PM at night but that’s no excuse for me to not have checked my code that I used as an example for you guys.).

Why I’m credible to make this post:
I’ve done commisions for multiple games and have a lot of experience scripting. I created a messy but easy to understand boss tutorial that utilizes only very basic things in lua that beginners would understand since so many people asked in comment sections of scripting youtube channels. Of course I’ve got a ton of learn and am by no means a pro scripter. Anyways this last section was just to adress some advanced devs who may be looking at this tutorial and see how messy my code is.

I hope anyone reading this has an amazing day!

30 Likes

I watched the video and im going to be honest that boss fight looks dull and repetitive. It looks interesting at first but instead of making new attacks that build on the previous you just repeat them over and over.

4 Likes

There are definitely better ways to do this but it’s good for a beginner

4 Likes

The new slam is more powerful in the second phase which is building on the one in the first phase which was less powerful. The second phase one poses a larger threat since if it hits you then you get stunned and the meteor attack can hurt you. Also the meteor and laser attacks are in the second phase so there were 2 new attacks. The attack cycle for the first phase is Slam, Slam, Slam, AOE fire move, then chunks of the place you are surviving on lower into lava. This repeats 3 times to make the player constantly under stress from the attacks. The slam when the boss first starts catches people off guard and gives little time to react. Then the second and third slam also catch the player off guard since they don’t expect the attack to be repeated. The second and third attack also can deal a lot of damage to the player if they are lying on the ground stunned and if you got hit by the first, the second and third will deal and extra 60 damage leaving the player at 10 health for the rest of the fight until they heal. The second attack then makes the player run away from the center where the slam starts off small and easier to dodge. Then the lava plates force the player to run to another plate and the long pause after that attack keeps the player on edge and then they won’t expect the slam again. The transition from first to second phase surprises players when they see the platform of stone rise from the ground and they don’t get much time to react and jump on it. While I agree that repeating the first phase attacks 3 times was a bit too much since then the boss just gets repetitive, the second phase is too easy without it being repeated 3 times and it is pretty challenging with the slam and the laser at the end catches players off guard again since the meteor attack goes on for a while and just as they get used to running from the meteors the laser attack plays and the players don’t know what to do. The second and third time are just to add some challenge since the player has to survive the second phase attacks all over again and it increases the chance of getting hit by the ground slam which knocks you down to the ground and then you die from the meteors falling on you.

I meant visual changes. Even if the attack values are the same to keep the player engaged you need to have more than 2-4 different attacks per phase.

1 Like

Errors within the code

If is capitalized in a couple of lines. While is capitalized in a couple of lines

If the boss dies, it still goes through the attack sequence before breaking


I mean I agree with @omgcchheeessee

The tutorial right now is more of a loop tutorial, not really how to make boss battles correctly.
A boss fight is supposed to be engaging. Repetition is not a bad thing! However not having any variability in a boss fight will make it boring fast. Take legend of zelda breath of the wild, or minecraft even. There are key boss attacks, which generally are indicated by sounds, but the bosses do roam around and can attack in random orders

In order to replicate this you should probably utilize an array, which I will dive into a bit.


Something to note is that you can store functions in arrays which is key, this means that we can index a function in 2 different ways.

First way you can store functions directly (It is more messy but works)

local bossAttacks = 
{
   function attack1(bossObject)
       Sound:Play()
       -- Do stuff here
   end,
   function attack2(bossObject)
      Sound2:Play()
      -- More stuff here
   end
}

-- Calling a random boss attack
while bossAlive == true do
    bossAttacks[math.random(1,#bossAttacks)](boss) -- Choose a random boss attack function and fire it
   wait(math.random(30,60)) -- Wait 30-60 seconds 
end

Now you can do it like this, however utilizing modules or creating a secondary array for storing attacks is just more clean in my opinion. Additionally using this method allows us to create stages for the boss where we can easily add new attacks

local bossPhase = 1
local attacks = {}

attacks.NormalAttack = function(bossObject)
   Sound:Play()
   -- More Stuff Here
end
attacks.SpecialAttack = function(bossObject)
   Sound:Play()
   -- More Stuff Here
end

-- Store the attacks into an array
local phaseOneAttacks = {attacks.NormalAttack}
local phaseTwoAttacks = {attacks.NormalAttack, attacks.SpecialAttack}

while bossPhase == 1 do
    phaseOneAttacks [math.random(1,#phaseOneAttacks )](boss) -- Choose a random boss attack function and fire it
   wait(math.random(30,60)) -- Wait 30-60 seconds 
end

while bossPhase == 2 do
    phaseTwoAttacks[math.random(1,#phaseTwoAttacks)](boss) 
   wait(math.random(15,30))
end

Just with this minor additions we have created some randomness and have a lot of freedom to easily add more boss attacks! Additionally I would suggest utilizing coroutines or spawn() in order to be able to play multiple attacks at the same time.

9 Likes

Yeah, sorry about that I just was pretty proud of my boss. This is meant for beginners since normally in a lot of scripting channel comment sections I see requests for this. I want beginners to have an easy to use system even if it is a bit repetitive and thats the purpose the boss tutorial serves. The code I’ve provided isn’t meant to be a copy and paste for players but just something to look at and see how it’s formatted. The boss won’t be vulnerable during the attack phase then will become vulnerable for a few seconds for players to attack. Then the script checks if the health is low enough to end the boss or just start the next phase. The “While” in the code has become lowercase though I think the health script works fine when checking if the boss is ok. I can’t test the code I’ve written until friday or the weekends though. Also in my script I acknowledged that it was repetitive and the boss I’ve done utilizes coroutines to play a slam attack at the same time as the meteor attacks and I’ll add your suggestions to the tutorial. The reasons this code is not as efficient as your code is because I’m not sure beginners would understand module scripts though they do save tons of space in your code and sorry the title is a bit clickbaity.

3 Likes

Yeah I understand what you mean, the amount of attacks and difference in visuals between the first and second ground slam should be changed thanks for the criticism.