Mini Boss 1: Cerberus - UQcsse3200/2026-studio-4 GitHub Wiki
Current implementation: checked against
mainat 77e0b9b2 on 21 October 2026. Values below are defaults before room difficulty scaling unless stated otherwise.
Overview
Cerberus is a three-headed mini boss with independent head health, tethered movement and phase-based attacks.
The middle head also acts as the main body. The left and right heads are separate entities attached to it. Each head owns a different attack, which becomes unavailable when that head dies.
When the combined health of all three heads reaches 50% or below, Cerberus enters Phase 2. Living heads display a pulsing red aura, and attacks can run concurrently while retaining their individual cooldowns.
Head Types and Default Statistics
| Head | Health | Ability | Behaviour |
|---|---|---|---|
| Left | 125 | Dark Mist | Creates a temporary mist area at the player’s position when cast. |
| Middle / Body | 250 | Lunge and Bite | Winds up, lunges towards a locked destination and can damage the player once per attack. |
| Right | 125 | Homing Projectile | Fires projectiles that continuously adjust their direction towards the player. |
The default combined health is 500.
The middle head’s health and base attack are read from the cerberus configuration in NPCs.json. Each side head receives half the configured middle-head health.
The default middle-head attack damage is 20. The right head supplies 10 as projectile damage.
The left head’s mist applies the shared Slow and Vulnerable status effects through the player component. The current slow is configured with a -1.5 movement-speed change and a 5,000 ms duration; it is no longer implemented by CerberusMistSlowEffect. CerberusMistComponent handles mist placement, duration, visuals, and entry/exit events. PlayerCerberusMistDebuffComponent connects those events to the player’s status effects.
The effects are removed when the player leaves the mist or when the mist is cleared. Re-entering the same mist does not stack its effects.
Main Classes
| Class | Responsibility |
|---|---|
| CerberusFactory | Creates the three heads and connects their components to a shared attack coordinator. |
| CerberusDeathComponent | Preserves the main body until all heads have died. |
| CerberusMovementComponent | Controls normal pursuit within the tethered area and gives bite movement priority. |
| ChainRestrictionComponent | Restricts the main body to a fixed radius around its anchor. |
| HeadAttachmentComponent | Positions each side head relative to the main body. |
| CerberusBiteComponent | Controls windup, lunge, damage and cooldown. |
| CerberusMistComponent | Controls mist duration, area detection, rendering and entry/exit events. |
| CerberusProjectileComponent | Controls projectile cooldown, deferred creation and cancellation. |
| HomingProjectileMovementComponent | Moves projectiles towards the target with a travel-distance limit. |
| CerberusPhaseComponent | Detects the combined-health threshold and starts Phase 2. |
| CerberusAttackCoordinator | Controls sequential attacks in Phase 1 and concurrent attacks in Phase 2. |
| CerberusEnrageVisualComponent | Renders a red aura around each living, enraged head. |
| PlayerCerberusMistDebuffComponent | Listens for mist entry/exit events and adds or removes the player's mist effects. |
| CerberusLayeredRenderComponent | Renders the body and three head layers, controls their animations and hides dead heads independently. |
| CerberusProjectileFactory | Creates animated homing fireballs with the existing movement, lifetime and contact-damage behaviour. |
| CerberusChainComponent | Stores the fixed wall anchor and calculates the attachment point on the moving body. |
| CerberusChainRenderComponent | Draws repeated chain links along a sagging path between the wall and body. Unregisters when the main entity is disposed. |
Cerberus-specific components are grouped in the com.csse3200.game.components.miniboss.cerberus package.
Independent Head Death
Each head has its own CombatStatsComponent.
- Left-head death: clears the active mist and prevents further mist casts.
- Middle-head death: disables bite attacks and stops body movement. The main body remains available as the attachment parent for surviving side heads.
- Right-head death: prevents further firing and cancels queued projectile creation.
- All three heads dead:
CerberusDeathComponentemitscerberusDefeatedand schedules disposal of the main body. The dedicated completion event reports oneCERBERUSkill for Three Heads, One Victory; killing only the middle head must not unlock it.
Side heads use EnemyDeathComponent(false) for their own disposal. A dying head also releases its attack opportunity so it does not block the remaining heads.
Movement and Attachment
The main body follows the player within a circular area centred on a fixed movement anchor. The current movement radius is 3 world units.
CerberusMovementComponent limits the pursuit destination, while ChainRestrictionComponent corrects positions outside the boundary and removes outward velocity.
The visible chain uses a separate wall anchor. This anchor controls where the chain is drawn; it does not replace the existing movement anchor or change the movement boundary.
The main body uses a 2×2 world-unit scale. Side-head entities retain independent health and hitboxes, while their images are drawn by the main body's layered renderer.
Current side-head position offsets relative to the main entity's bottom-left position are:
| Head | Offset |
|---|---|
| Left | (0.2825f, 0.95f) |
| right | (1.1575f, 0.95f) |
| -- | -- |
The chain attaches to the body at 50% of its width and 40% of its height. Its wall endpoint remains fixed while its body endpoint follows movement.
The chain remains after the middle head dies if either side head is still alive. It disappears when all three heads have died and the main entity is disposed.
Attacks
Left Head: Dark Mist
The mist is created at the player’s centre position when cast. Its position remains fixed for that cast.
| Parameter | Value |
|---|---|
| Cooldown | 5 seconds |
| Duration | 3 seconds |
| Cast range | 7 world units |
| Area radius | 2 world units |
The component checks whether the player’s centre is inside the mist. Entering and leaving trigger events on the player, with the left-head entity supplied as the source.
The cooldown restarts when the mist expires. Head death, player death or component disposal clears an active mist and releases any current occupancy.
While the player remains inside the mist, PlayerCerberusMistDebuffComponent applies two shared status effects:
Slowis constructed with a -1.5 movement-speed change (clamped at zero on application) and a 5,000 ms duration.StatusEffectsFactory.createVulnerable()creates the incoming-damage effect.
These are shared status-effect implementations; their current removal and timing behaviour should be checked together with mist entry/exit during playtesting.
The player component removes its effect references from the status controller when the player leaves the mist, the mist expires, the left head dies, the player dies, or the player debuff component is disposed. Re-entering the same mist does not stack the effects.
Middle Head: Lunge and Bite
The attack follows these states:
READY → WINDUP → LUNGE → COOLDOWN → READY
| Parameter | Value |
|---|---|
| Trigger range | 2 world units |
| Hit range | 1.2 world units |
| Windup | 0.5 seconds |
| Lunge duration | 0.35 seconds |
| Cooldown | 2 seconds |
| Lunge movement speed setting | 6 |
| Default damage | 20 |
The destination is locked when windup begins and is constrained to the tethered area. During the lunge, damage can be applied once if the player is within hit range.
The attack is cancelled if the middle head or target dies.
Right Head: Homing Projectile
| Parameter | Value |
|---|---|
| Cooldown | 2.5 seconds |
| Attack range | 7 world units |
| Projectile speed | 5 world units per second |
| Maximum travel distance | 7 world units |
| Projectile lifetime | 1.8 seconds |
| Default projectile damage | 10 |
The right head creates fireballs through CerberusProjectileFactory.createHomingProjectile(). The factory uses images/cerberus/cerberus-fireball.atlas and retains HomingProjectileMovementComponent for tracking.
The projectile animation loops during flight. Reaching the travel-distance limit triggers projectileHit; this event is not a collision callback.
Fireballs retain the existing hitbox contact-damage behaviour. They do not automatically disappear on their first successful hit.
Phase Behaviour
Phase 1: Sequential Attacks
The coordinator prioritises heads in this order:
Left → Middle → Right → Left
Heads that are dead, cooling down or outside their attack range are skipped. Consequently, the visible attack order can vary, and the opening attack is not guaranteed to come from the left head.
An attack occupies its turn until:
- The mist expires or is cancelled.
- The bite finishes its lunge or is cancelled.
- The projectile creation task finishes or is cancelled.
An already-fired projectile can remain in flight during the next attack. Normal pursuit movement is not blocked solely because another head owns the attack turn.
Phase 2: Concurrent Attacks
The threshold uses all three heads:
Combined current health / Combined maximum health ≤ 0.5
Dead heads still contribute their maximum health to the denominator. With the default values, Phase 2 begins at 250 combined HP or below, provided some health remains.
The transition occurs only once. Healing does not return Cerberus to Phase 1.
During Phase 2:
- Different heads may attack concurrently.
- Individual cooldowns and range checks still apply.
- An attack already in progress is not restarted by the coordinator.
- Living heads display a pulsing red aura.
Animation and Visuals
Cerberus uses images/cerberus/cerberus-modular.atlas and cerberus-modular.png.
CerberusLayeredRenderComponent draws four layers: body, left head, middle head and right head. Each layer has its own animation state. The factory connects the body's attackStart and default events to the body and middle-head lunge and idle animations.
Each head layer is connected to its corresponding CombatStatsComponent. A dead head becomes invisible independently, while the body remains visible until the complete boss is disposed.
Fireballs use a dedicated atlas containing flight and impact animations. The wall chain uses images/cerberus/cerberus-chain.atlas and repeated textured links.
The mist remains a purple area, and living enraged heads display pulsing red auras. Mist and aura textures are generated procedurally. The visual changes do not require modifications to the shared AnimationRenderComponent.
Usage and Main Methods
Factory
Entity main = CerberusFactory.createCerberus(
target, anchorPoint, wallAnchor, sideHeadSpawner);
anchorPoint is the centre of the existing movement restriction. wallAnchor is the fixed attachment point used by the visible chain.
The factory returns the main body and passes both side heads to sideHeadSpawner. The caller must spawn and track all three entities.
The current factory has the four-argument signature above. Pass null as wallAnchor to omit the visible chain. The modular atlas is selected inside the factory; it is not a caller argument. All three parts reuse NPCFactory.createBaseNPC() for shared physics and status-effect support.
The room must load the modular, fireball and chain atlases before spawning the boss.
Attack Coordinator
CerberusAttackCoordinator is a plain Java class shared by all three skills.
| Method | Purpose |
|---|---|
| register(Entity, BooleanSupplier) | Registers a head’s attack-readiness check. |
| tryStart(Entity) | Requests permission to begin an attack. |
| finish(Entity) | Releases an attack when it completes or is cancelled. |
Each skill connects to the coordinator through setAttackCoordinator(...), after it has been attached to its entity.
State Queries
| Method | Purpose |
|---|---|
| CerberusPhaseComponent.getCurrentPhase() | Returns the current phase. |
| CerberusMistComponent.isMistActive() | Reports whether mist is active. |
| CerberusMistComponent.getMistCentre() | Returns a copy of the mist centre. |
| CerberusEnrageVisualComponent.isAuraActive() | Reports whether the head’s aura is active. |
Events
| Event | Source | Purpose |
|---|---|---|
| updateHealth / updateMaxHealth | Each head’s combat stats | Re-evaluates the combined-health phase threshold. |
| entityDied | Each head | Cancels abilities and handles head lifecycle. |
| enragePhaseStarted | Phase component, on living heads | Announces entry into Phase 2. |
| biteWindup | Middle head | Announces bite windup. |
| attackStart | Middle head | Starts the bite attack animation. |
| default | Middle head | Returns to the default animation after lunge. |
| cerberusMistEntered / cerberusMistExited | Player event handler | Reports mist occupancy, with the left head as the source argument. |
| cerberusProjectileSpawned | Main body | Requests projectile spawning through the room manager. |
| projectileRangeReached | Projectile | Signals that its travel-distance limit has been reached. |
Room Integration
Cerberus currently spawns in dungeonOneEnd, the Greek dungeon's end room. EnemyManagerComponent.createCerberus(...) sets the visible chain anchor to tile (26, 50), adding half a tile to the world-space x coordinate. The movement anchor remains the boss's configured spawn point.
This coordinate belongs to the current room layout. If the room layout changes, review the wall attachment alongside the spawn position in EnemyManagerComponent.java.
The chain is a render component on the main body, not a separate enemy, and does not affect the room's enemy count.
EnemyManagerComponent tracks all three heads as enemies. Each head is removed from enemy tracking when it dies.
Projectiles are spawned through a separate event callback and are not added to the active-enemy count. They therefore do not need to be defeated to clear the room.
The room clears only when all tracked enemies have died, including any surviving Cerberus heads.
Testing
Automated Tests
| Test class | Main coverage |
|---|---|
| CerberusPhaseComponentTest | Combined-health threshold and one-way phase transition. |
| CerberusAttackCoordinatorTest | Turn order, readiness, death and concurrent attacks. |
| CerberusAttackCoordinationTest | Interaction between the three real skills and phase changes. |
| CerberusBiteComponentTest | Windup, damage, cooldown, cancellation and turn release. |
| CerberusMistComponentTest | Duration, occupancy, cleanup and attack coordination. |
| CerberusProjectileComponentTest | Deferred firing, cooldown, cancellation and coordination. |
| HomingProjectileMovementComponentTest | Homing movement and travel limits. |
| CerberusEnrageVisualComponentTest | Aura activation, independent death and disposal. |
| CerberusLayeredRenderComponentTest | Layered animation state and independent head visibility. |
| CerberusProjectileFactoryTest | Dedicated fireball construction and component setup. |
| CerberusChainComponentTest | Fixed wall anchor, defensive copying, body attachment and endpoint distance. |
| CerberusChainRenderComponentTest | Chain endpoints, approximate length, straight-path fallback and renderer disposal. |
| CerberusStatusEffectsTest | Shared enemy status-effect support on Cerberus parts. |
| ChainRestrictionComponentTest | Tether boundary behaviour. |
| HeadAttachmentComponentTest | Relative head positioning. |
| CerberusTest | Factory setup, animation events, head positioning and optional chain attachment. |
From the source directory on Windows PowerShell:
.\gradlew.bat :core:test --tests "com.csse3200.game.components.miniboss.cerberus.*" --tests "com.csse3200.game.entities.enemy.CerberusTest" --tests "com.csse3200.game.entities.factories.CerberusProjectileFactoryTest" --tests "com.csse3200.game.entities.factories.CerberusStatusEffectsTest" --tests "com.csse3200.game.components.ChainRestrictionComponentTest" --tests "com.csse3200.game.components.HeadAttachmentComponentTest"
Run the complete core test suite with:
.\gradlew.bat :core:test
Manual Verification
Launch Desktop and enter a room configured to spawn Cerberus.
- Confirm that three heads appear close together and use the default idle animation.
- Move away and verify that the body remains within its anchor radius.
- During Phase 1, verify that active mist prevents new bite and projectile attacks.
- Verify that other attacks resume after the mist expires.
- Reduce combined health to 50% or below and verify that living heads display red auras.
- Confirm that attacks can overlap in Phase 2 while still respecting cooldowns and range.
- Kill individual heads and verify that their abilities stop while surviving heads continue.
- Confirm that the room does not clear while tracked enemies remain alive.
UML Overview
Creation and Visuals
Attack And Phases
ECS, Death And Movement
Design Decisions and Changes
The previous separate wolf sprites were replaced with a layered Cerberus appearance while retaining the independent three-head combat system. Side heads remain separate gameplay entities, and the main renderer combines their visuals into one boss.
A dedicated projectile factory separates Cerberus's fireball appearance from the ordinary ranged-enemy projectile factory.
The visible wall chain communicates the existing movement restriction. Its wall attachment and the movement-boundary centre remain separate so that adding the visual does not alter the established combat movement.
Current integration notes
Independent heads and attacks: #143, #153, #188; layered art, chain and cleanup: #255; complete-boss achievement: #291; shared NPC factory integration: #332. Sources: CerberusFactory.java, CerberusDeathComponent.java, PlayerCerberusMistDebuffComponent.java.
The diagrams above record the earlier architecture; the current factory signature and shared status-effect classes are described in the text. CerberusMistSlowEffectTest and PlayerCerberusMistDebuffComponentTest are not present at the documented revision. Mist restoration and achievement timing remain explicit manual checks in the Team 1 Test Plan.