Enemies - UQcsse3200/2026-studio-4 GitHub Wiki
Enemies
Current implementation: checked against
mainat 77e0b9b2 on 21 October 2026. Values below are defaults before room difficulty scaling unless stated otherwise.
Team 1 implements five regular-enemy archetypes with four dungeon themes, plus the minibosses and Final Boss linked below. Sprite thumbnails and original art credits are retained in the table.
Related: Enemy AI and Navigation ยท EnemyStatDisplay ยท Team 1 Test Plan.
Types and default statistics
| Enemy Name | Default Sprite | Attack Damage | Attack Style | Health | Main Classes Used |
|---|---|---|---|---|---|
| Bomb Enemy: Beetle {Egyptian}, Golem {Greek}, Knight {Norse}, Zombie {Chinese} | 11 nominal (config 7 + factory 4) | Visible player contact starts a 2-second fuse. Damage is attempted only if the player still overlaps when it expires; the enemy then dies. | 10 | ExplodeComponent, BombEnemyConfig, NPCFactory, WanderTask, ChaseTask, EnemyAnimationController |
|
| Split Enemy: Crab {Egyptian}, Medusa {Greek}, Dark Elves {Norse}, Bug {Chinese} | 2 parent / 1 child | Pursues and lunges. On death, the parent is replaced by two weaker children; children cannot split again. Medusa also has hit recovery. | 40 parent / 30 child | SplitComponent, GroundChaseTask, LungeAttackTask, TouchAttackComponent, MedusaHitRecoveryComponent, NPCFactory |
|
| Chase Enemy: Minotaur {Greek}, Sandeye {Egyptian}, Wolf {Norse}, Longwei {Chinese} | 2 base; attack behaviour varies by skin | Pursues using ground navigation and performs a telegraphed lunge. These variants do not split. Minotaur uses timed axe attacks and dedicated animations. | 40 | GroundChaseTask, LungeAttackTask, TouchAttackComponent, MinotaurAnimationController, MinotaurAttackRenderComponent, MinotaurDashTrailComponent, NPCFactory |
|
| Flying Enemy: Wasp {Egyptian}, Harpy {Greek}, Crow {Norse}, Jingwei {Chinese} | 7 per projectile | Patrols a triangle relative to its spawn position and fires three spread projectiles. Projectiles stop at solid obstacles. | 77 | FlyingEnemyPatrolComponent, FloatingDemonProjectileFactory, RangedAttackTask, PatrolTask, ProjectileMovementComponent, NPCFactory |
|
| Giant Enemy: Mummy {Egyptian}, Cyclops{Greek}, Jotunn {Norse}, Wukong {Chinese} | 3 | Wanders and chases the player when nearby. | 30 | GiantEnemyConfig, NPCFactory, WanderTask, ChaseTask, EnemyAnimationController |
Damage, splitting and scaling
Bombs do not explode immediately on first contact. ExplodeComponent starts the configured fuse on eligible contact, checks overlap again at expiry, and removes the bomb even if the player has escaped. Concealment suppresses detection/damage, and disposal cancels pending fuse work.
Only the split variants receive SplitComponent. It listens to hit reactions but creates children only once the parent is dead. Each child receives 75% of the parent's maximum health and half its base attack (at least 1), so the unscaled defaults are 30 HP and 1 attack. Children do not receive another SplitComponent. The room registers them through spawnChildren before considering the encounter complete.
Room difficulty calls CombatStatsComponent.scale(completedDungeons) on tracked enemies. It adds int(originalMaxHealth ร 0.5 ร completedDungeons) to maximum health and an equivalent increment to base attack, then starts the enemy at full health. Health and maximum health are updated together before updateMaxHealth and updateHealth are emitted. Thus health bars and half-health boss transitions see consistent values. Skill-specific fixed damage is not automatically derived from base attack.
Medusa uses a 1.5-second contact-damage interval and a 3-second lunge cooldown. A surviving, effective player hit starts or refreshes a 350 ms recovery period: movement, contact damage and knockback are suppressed and the pending/current lunge is cancelled. This also applies to Medusa children. Minotaur instead uses its axe attack window and one-hit-per-attack tracking, with a red dash trail and speed-line feedback. See Enemy AI and Navigation.
Flying enemies and projectiles
FlyingEnemyPatrolComponent establishes a spawn-relative triangular patrol after placement. RangedAttackTask requests a three-shot spread. The room receives enemyProjectileSpawned and owns projectile spawning/disposal; projectiles are not additional enemies to defeat.
Themed atlases can supply projectile and projectileHit regions. Wasp, Harpy, Crow and Jingwei all contain both region sets at the documented revision. If the selected atlas lacks the projectile region, FloatingDemonProjectileFactory uses images/flying-enemy/floating-demon-projectile.atlas. Flight defaults are speed 5, maximum distance 7 and lifetime 1.8 seconds. Swept obstacle checks prevent shots passing through walls between frames.
Factories and assets
NPCFactory.createBaseNPC() provides PhysicsComponent, PhysicsMovementComponent, ColliderComponent, an NPC HitboxComponent and StatusEffectsControllerComponent. Concrete factories add combat stats, AI, rendering, health bars and the appropriate death lifecycle; the base helper does not add death handling itself.
| Resource directory | Regular-enemy skins |
|---|---|
images/bomb-enemy/ |
Beetle, Golem, Knight, Zombie |
images/split-enemy/ |
Crab, Medusa, Dark Elves, Bug |
images/chase-enemy/ |
Sandeye, Minotaur, Wolf, Longwei |
images/flying-enemy/ |
Wasp, Harpy, Crow, Jingwei and fallback projectile atlas |
images/giant-enemy/ |
Mummy, Cyclops, Jotunn, Wukong |
Load required textures/atlases through the room resource lifecycle before creating enemies. New room-spawnable types also need the matching EnemySpawnConfig type and EnemyManagerComponent factory mapping. Theme-specific methods in NPCFactory reuse the common archetype builders. The room supplies spawn positions for flying patrols and Sleipnir, and bounds/camera context for the Snake. Flying enemies and Dragon publish NPCFactory.PROJECTILE_SPAWNED (enemyProjectileSpawned); the room connects that event before registration and owns the resulting projectiles. Before creating or tracking an enemy, the room rejects configured positions on wall or empty tiles. Chasing and burrowing additionally require their movement-specific obstacle checks.
Room placement and final balance
Enemy type, count and placement are configured in the enemySpawns arrays in rooms.json. PR #341 reduced Medusa crowding in the Greek entrance; its current starting group is five Medusas and three Minotaurs. The Medusa recovery and cooldown changes are described above.
PR #388 increased enemy density across the four regular Egyptian rooms and adjusted Norse and Chinese entrance groups. Current configured groups are:
| Room | Initial enemy group |
|---|---|
dungeonTwoEntrance |
8 Crab + 6 Sandeye |
dungeonTwoSide |
8 Sandeye + 8 Mummy |
dungeonTwoMiddle |
8 Beetle + 8 Wasp |
dungeonTwoAntechamber |
9 Crab + 9 Mummy |
dungeonThreeEntrance |
6 Dark Elves + 8 Wolf |
dungeonFourEntrance |
6 Bug + 5 Longwei |
These counts describe the initially configured entities; split children are created later during combat. The same update sets the Snake's base maximum health to 250 and enlarges its sprite and burrow dust. See Snake Miniboss Remake for its collider and effect behaviour.
Death and room integration
Regular enemies use EnemyDeathComponent with EnemyAnimationController. The entityDied event stops combat/movement and starts the appropriate death animation. Removal is deferred through EntityService.scheduleDisposal(...), avoiding disposal while the physics world is locked.
Bosses have additional lifecycle rules. Cerberus retains its body while side heads survive and emits cerberusDefeated only after all three heads die. The Final Boss completes through finalBossEncounterCompleted after Grandpa's return transformation; completion does not require killing the peaceful Grandpa. Refer to each boss page before reusing generic death handling.
The Team 1 magnetic-pickup contribution works with ordinary room drops: holding E for one second attracts the current eligible drops; releasing E does not cancel drops already travelling. Later drops need a new hold. Short E interaction is resolved on release, while a completed hold suppresses that interaction. Final Boss ice pickups and Snake shield gems retain their own encounter-specific collection rules. See the shared Item Pickup page and the Team 1 regression plan.
Boss encounters
| Dungeon | Boss | Documentation |
|---|---|---|
| Dungeon 1 โ Greek | Cerberus | Three-head combat, chain and mist |
| Dungeon 2 โ Egyptian | Snake | Current burrow/poison/shield encounter |
| Dungeon 3 โ Norse | Sleipnir | Patrol, earthquake and stampede |
| Dungeon 4 โ Chinese | Dragon | Thunder Orb, Cloud Dash and Storm Zone |
| Final Boss room | Grandpa | All three stages and achievements |
Verification and merged work
The Team 1 Test Plan maps current test classes to manual gameplay checks and distinguishes historical coverage reports from current source inspection.
Core implementation: NPCFactory.java, SplitComponent.java, ExplodeComponent.java, CombatStatsComponent.java, FloatingDemonProjectileFactory.java.
Merged development: enemy foundations #35, #63, #77, #113, themed/chase variants #229, #249, contact and wall fixes #225, #226, spawn bounds #286, Minotaur integration #312, ground navigation #325, shared factory/patrol/projectile fixes #332, magnetic pickup #339, Medusa recovery #341, and asset/projectile integration #371, #380. Minotaur attack visuals in #312 were contributed by Team 5 and integrated into Team 1 enemy behaviour.