A room is a single encounter within a dungeon. Rooms can contain combat encounters, loot drops, or both. Dungeons string rooms together β€” players move through them in order.

Files live in: <pack_root>/data/enemies/rooms/<group_folder>/<room_name>.json

Rooms are stored under data/enemies/ because a room is fundamentally a combat encounter unit β€” it holds the enemies the player fights and what they earn for clearing it.

JSON Shape

{
  "group": "pirate",
  "displayName": "dungeons.mypack.pirate.ambush_zone",
  "description": "dungeons.mypack.pirate.ambush_zone.desc",
  "gainXp": 200,
  "credits": 500,
  "bossRoom": false,
  "hostiles": [
    "enemies.mypack.pirate.raider_frigate",
    "enemies.mypack.pirate.raider_frigate"
  ],
  "loot": [
    {
      "id": "mypack:ore_iron",
      "chance": 0.5,
      "min": 2,
      "max": 5
    }
  ]
}

Field Reference

FieldTypeRequiredDescription
groupstringβœ…Faction slug. Should match the dungeon(s) that reference this room.
displayNamestring (lang key)βœ…Registry key for the room name.
descriptionstring (lang key)βœ…Registry key for the room description.
gainXpintegerβœ…XP awarded to the player on room completion.
creditsintegerβœ…Credits awarded on room completion.
bossRoombooleanβœ…Whether this room is a boss room. Boss rooms trigger special UI and reward behavior.
hostilesarray of stringsβœ…Ordered list of enemy registry keys. Duplicate entries spawn multiple copies of the same enemy. Use [] for a loot-only room.
lootarrayNoItems granted when the room is entered or cleared. Same schema as enemy loot: id, chance, min, max.
metaobjectNoArbitrary key-value extension pairs.

Example β€” Combat Room

{
  "group": "pirate",
  "displayName": "dungeons.mypack.pirate.patrol_room",
  "description": "dungeons.mypack.pirate.patrol_room.desc",
  "gainXp": 150,
  "credits": 300,
  "bossRoom": false,
  "hostiles": [
    "enemies.mypack.pirate.raider_frigate",
    "enemies.mypack.pirate.raider_frigate"
  ]
}

Example β€” Loot Room (No Combat)

{
  "group": "pirate",
  "displayName": "dungeons.mypack.pirate.cargo_bay",
  "description": "dungeons.mypack.pirate.cargo_bay.desc",
  "gainXp": 20,
  "credits": 500,
  "bossRoom": false,
  "hostiles": [],
  "loot": [
    { "id": "mypack:ore_iron",    "chance": 1.0, "min": 3, "max": 5 },
    { "id": "mypack:ingot_iron",  "chance": 0.4, "min": 1, "max": 2 }
  ]
}

Example β€” Boss Room

{
  "group": "pirate",
  "displayName": "dungeons.mypack.pirate.warlord_bridge",
  "description": "dungeons.mypack.pirate.warlord_bridge.desc",
  "gainXp": 1000,
  "credits": 5000,
  "bossRoom": true,
  "hostiles": [
    "enemies.mypack.pirate.warlord_dreadnought"
  ]
}

Design Tips

  • Start easy, end hard. Early rooms should be lighter than late rooms.
  • Use loot rooms as breathing room. A loot-only room mid-dungeon gives players a break before the final boss.
  • Scale rewards to difficulty. Boss rooms should pay out significantly more than patrol rooms.
  • Repeat room IDs. A dungeon can reference the same room ID multiple times β€” valid and useful for wave encounters.