Few indie games have left as deep a mark on game design as Undertale (2015). Its boss battles aren't just fights — they are conversations, emotional crescendos, and puzzles wrapped in a bullet-hell shell. For modders, fangame developers, and coding enthusiasts, recreating that magic starts with one thing: the script.
An "Undertale boss battles script" refers to the code (often in GameMaker Language (GML) or Unity/C# for fangames) that controls the flow of a boss encounter, from dialogue to attacks to sparing mechanics.
ACT commands:
const actCommands =
"Check": () => showBossStats(),
"Flirt": () =>
if (boss.name === "Papyrus") boss.spareProgress += 30;
showText("* You flirt. Papyrus blushes.");
,
"Threaten": () =>
boss.dialog = "* ...?";
boss.spareProgress -= 10;
;
Spare condition:
function checkSpare()
if (boss.spareProgress >= 100 && boss.spareEnabled)
endBattle("SPARED");
Before we write a single line of code, we must understand that an Undertale boss fight is a state machine. A static enemy that repeats one attack is boring. A great boss script cycles through phases.
let dialogQueue = [];function showText(text) dialogQueue.push(text); typewriterEffect(text);
function typewriterEffect(text) let i = 0; let interval = setInterval(() => if (i < text.length) dialogBox.innerHTML += text[i]; i++; else clearInterval(interval); setTimeout(() => dialogBox.innerHTML = "", 1500); , 30);Undertale Boss Battles Script
START Battle Load BossData (HP, Attack, Defense, Name, Dialog) PlayerTurn = TRUELOOP while (Boss.HP > 0 AND Player.HP > 0): IF PlayerTurn: Display "ACT", "FIGHT", "ITEM", "MERCY" HandlePlayerChoice() ApplyEffects() PlayerTurn = FALSE ELSE: ChooseBossAttack() StartBulletPattern() ApplyDamageToPlayer() PlayerTurn = TRUE END LOOP
IF Player.HP <= 0: GameOver() ELSE: SpareOrKillCheck() ENDFew indie games have left as deep a
player_hp = 20 papyrus_hp = 150 mercy = 0 state = "PLAYER_TURN" selected_option = 0 menu_options = ["FIGHT", "ACT", "ITEM", "MERCY"]
Now, let’s script actual boss behaviors. Below are templates for three famous encounters. Spare condition: function checkSpare() if (boss