aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--building_guide/behaviors.md45
-rw-r--r--building_guide/mobs.md377
-rw-r--r--data/.admin_history.json2
-rw-r--r--data/mobs/examples/ancient_construct.yaml51
-rw-r--r--data/mobs/examples/bandit.yaml49
-rw-r--r--data/mobs/examples/bioengineer.yaml58
-rw-r--r--data/mobs/examples/client.yaml14
-rw-r--r--data/mobs/examples/corrupted_scientist.yaml53
-rw-r--r--data/mobs/examples/cow.yaml39
-rw-r--r--data/mobs/examples/crawler.yaml45
-rw-r--r--data/mobs/examples/drone.yaml45
-rw-r--r--data/mobs/examples/elite_synth.yaml53
-rw-r--r--data/mobs/examples/enforcer_bot.yaml51
-rw-r--r--data/mobs/examples/estate_broker.yaml5
-rw-r--r--data/mobs/examples/farmer.yaml58
-rw-r--r--data/mobs/examples/feral_cyborg.yaml49
-rw-r--r--data/mobs/examples/general_store_clerk.yaml20
-rw-r--r--data/mobs/examples/ghoul.yaml51
-rw-r--r--data/mobs/examples/goblin.yaml41
-rw-r--r--data/mobs/examples/greater_drone.yaml44
-rw-r--r--data/mobs/examples/guard.yaml22
-rw-r--r--data/mobs/examples/heavy_mech.yaml51
-rw-r--r--data/mobs/examples/iron_sentinel.yaml41
-rw-r--r--data/mobs/examples/lesser_drone.yaml44
-rw-r--r--data/mobs/examples/man.yaml60
-rw-r--r--data/mobs/examples/molten_elemental.yaml51
-rw-r--r--data/mobs/examples/moss_giant.yaml41
-rw-r--r--data/mobs/examples/mutant_rat.yaml51
-rw-r--r--data/mobs/examples/newbie_trainer.yaml14
-rw-r--r--data/mobs/examples/phantom.yaml45
-rw-r--r--data/mobs/examples/plasma_wraith.yaml53
-rw-r--r--data/mobs/examples/psionic_entity.yaml51
-rw-r--r--data/mobs/examples/rat.yaml39
-rw-r--r--data/mobs/examples/sawmill_operator.yaml7
-rw-r--r--data/mobs/examples/scrap_bot.yaml49
-rw-r--r--data/mobs/examples/security_turret.yaml53
-rw-r--r--data/mobs/examples/skeleton.yaml41
-rw-r--r--data/mobs/examples/slug.yaml45
-rw-r--r--data/mobs/examples/solar_panel_frame.yaml43
-rw-r--r--data/mobs/examples/tanner.yaml20
-rw-r--r--data/mobs/examples/titan_sentinel.yaml51
-rw-r--r--data/mobs/examples/veteran_merc.yaml51
-rw-r--r--data/mobs/examples/void_reaper.yaml55
-rw-r--r--data/mobs/examples/war_drone.yaml51
-rw-r--r--data/mobs/examples/weapons_smith.yaml20
-rw-r--r--data/mobs/examples/zombie.yaml43
-rw-r--r--data/mobs/flight_attendant_copy.yaml29
-rw-r--r--data/rooms/intro/1001.yaml1
-rw-r--r--internal/admin/static/mobeditor.js261
-rw-r--r--internal/admin/static/objecteditor.js6
-rw-r--r--internal/game/look_entities.go5
-rw-r--r--internal/game/sys_construction.go74
-rw-r--r--internal/validate/checks.go22
-rw-r--r--internal/world/mob.go263
54 files changed, 1651 insertions, 1252 deletions
diff --git a/building_guide/behaviors.md b/building_guide/behaviors.md
index c7b091d..ce266c1 100644
--- a/building_guide/behaviors.md
+++ b/building_guide/behaviors.md
@@ -185,7 +185,8 @@ name: Guard
talk:
nodes:
start:
- message: "\"Halt! This area is restricted.\" The guard eyes you suspiciously."
+ messages:
+ - "\"Halt! This area is restricted.\" The guard eyes you suspiciously."
options:
- text: "\"What's behind that gate?\""
goto: about_gate
@@ -202,7 +203,8 @@ talk:
# no goto = end conversation
about_gate:
- message: "\"Supplies. Weapons.\" He shifts his weight. \"Bring me some copper ore and I'll stamp you a pass.\""
+ messages:
+ - "\"Supplies. Weapons.\" He shifts his weight. \"Bring me some copper ore and I'll stamp you a pass.\""
action:
set_player_flags:
talked_to_guard: true
@@ -214,7 +216,8 @@ talk:
has_item: copper_ore
trade_ore:
- message: "\"Good quality ore.\" He stamps a pass and hands it to you."
+ messages:
+ - "\"Good quality ore.\" He stamps a pass and hands it to you."
action:
take_item: copper_ore
give_item: pass_stub
@@ -224,7 +227,8 @@ talk:
- text: "\"Thanks.\""
has_pass:
- message: "\"Alright, I'll open the gate.\""
+ messages:
+ - "\"Alright, I'll open the gate.\""
action:
set_flags:
gate_open: true
@@ -236,9 +240,8 @@ talk:
| Field | Type | Description |
|---|---|---|
-| `message` | string or list | NPC dialogue. May be a single string or a list of strings (pick one at random). |
-| `sequence` | []string | NPC monologue — each message shown one at a time, player presses enter to advance. Options appear after the last message. Takes priority over `message` if both present. |
-| `condition` | Condition | Optional. If the condition fails, the node is skipped entirely — its message, action, and options are not shown. Use with `goto` to auto-advance to a different node. |
+| `messages` | []string | NPC dialogue, shown one at a time. The player presses enter to advance through each message. Options appear after the last message. A single-element list works like a simple one-shot line. |
+| `condition` | Condition | Optional. If the condition fails, the node is skipped entirely — its messages, action, and options are not shown. Use with `goto` to auto-advance to a different node. |
| `action` | NodeAction | Fires when the node is entered (give items, set flags, etc). |
| `options` | []TalkOption | Player choices. If empty and `goto` is set, auto-advances. |
| `goto` | string | Node ID to auto-advance to when there are no visible options OR when the node condition fails. |
@@ -262,14 +265,12 @@ talk:
| `take_item` | Removes an item from the player's inventory. |
| `teleport` | Moves the player to a room ID. |
| `heal` | Restores that many hitpoints. |
-| `cost` | Credits charged for the action. |
-| `assign_task` | Assigns a random assassin task based on assassin level. |
-| `skip_task` | Cancels current assassin task, costs 30 reputation, resets streak. |
-| `extend_task` | Adds 50% more kills to current task, costs 30 reputation. |
+| `credits` | Credits charged (negative) or awarded (positive). |
| `reputation_cost` | Deducts reputation from `assassin_reputation` flag before other actions. |
-| `sawmill` | Opens sawmill plank conversion interface. |
| `aps_node` | Marks this room's APS node as unlocked. |
+> **Planned (not yet implemented):** `assign_task`, `skip_task`, `extend_task`, and `sawmill` are under design and will be added in a future update.
+
All fields in a single action are processed together — give an item, take an item, set flags,
and heal in one node.
@@ -294,11 +295,12 @@ simple transactions:
```yaml
nodes:
start:
- message: "Welcome! Houses are 10 credits. Interested?"
+ messages:
+ - "Welcome! Houses are 10 credits. Interested?"
options:
- text: "Yes, I'll buy one."
action:
- cost: 10
+ credits: -10
set_player_flags:
owns_house: true
goto: purchased
@@ -307,7 +309,8 @@ nodes:
not: true
- text: "No thanks."
purchased:
- message: "Excellent! The plot is yours."
+ messages:
+ - "Excellent! The plot is yours."
options:
- text: "Thanks!"
goto: start
@@ -316,9 +319,9 @@ nodes:
If an option has both an `action` and a `goto`, the action runs first, then the player
navigates to the target node (which may also have its own action, fired on entry).
-#### Sequences
+#### Multi-message nodes
-`sequence` is a flat list of NPC messages shown one at a time. The player presses
+`messages` is a list of NPC lines shown one at a time. The player presses
enter to advance through each message. After the last message, the node's options
(if any) are displayed. This is the preferred way to deliver NPC monologues — no
named nodes or `goto` chains needed:
@@ -326,7 +329,7 @@ named nodes or `goto` chains needed:
```yaml
nodes:
sign_reminder:
- sequence:
+ messages:
- "\"Yeah, just us two! Not a lot of people heading into the belt these days.\""
- "\"But we'll be landing shortly! Please look at the information sign.\""
options:
@@ -335,11 +338,11 @@ nodes:
```
Each `[enter to continue]` prompt is automatic. The node's action fires once on
-entry, before the first sequence message. Node conditions still work normally —
+entry, before the first message. Node conditions still work normally —
if the condition fails, the entire sequence is skipped via `goto`.
-If a sequence node has no options after the last message and `goto` is set, it
-auto-advances to the target node. Non-empty input during a sequence cancels the
+If a multi-message node has no options after the last message and `goto` is set, it
+auto-advances to the target node. Non-empty input during messages cancels the
conversation (just like invalid input does during option selection).
#### Randomized messages
diff --git a/building_guide/mobs.md b/building_guide/mobs.md
index 745fb49..31ff109 100644
--- a/building_guide/mobs.md
+++ b/building_guide/mobs.md
@@ -4,91 +4,143 @@
`goblin`), and the loader derives `MobDef.ID` from it. Do not put an `id:` field in the file
— it is ignored. Rooms reference mobs by that filename.
-Basic combat mob with per-type defense bonuses:
+All combat and stat fields are nested under a `combat:` block. Protected mobs (NPCs, shopkeepers,
+quest givers) do not have a `combat:` block at all — they cannot be attacked.
+
+Basic combat mob:
```yaml
name: "man"
description: "A shabby-looking man."
-attack: 1
-strength: 1
-defense: 1
-hp: 7
-speed: 5
-aggressive: false
-respawn_ticks: 30
-attack_type: crush # stab/slash/crush/ranged/science (default: crush)
-stab_defense: 0 # per-type defense bonuses
-slash_defense: 0
-crush_defense: 0
-science_defense: 0
-ranged_defense: 0
+idle_descriptions:
+ - "scribbles something in a small notebook"
+ - "gazes skyward at the clouds"
drops:
- remains: "bones" # always dropped on death
+ remains: "bones"
loot:
- item_id: "credits"
weight: 98
quantity: 10
- - item_id: "credits"
- weight: 2
- quantity: 150
-idle_descriptions:
- - "scribbles something in a small notebook"
- - "gazes skyward at the clouds"
-combat_descriptions:
- - "is engaged in a fight to the death with %s"
+combat:
+ kind: combat
+ stats:
+ hp: 7
+ attack: 1
+ strength: 1
+ defense: 1
+ attack_type: crush # stab/slash/crush/ranged/science (default: crush)
+ speed: 5
+ aggressive: false
+ respawn_ticks: 30
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 0 # per-type defense bonuses
+ slash_defense: 0
+ crush_defense: 0
+ science_defense: 0
+ ranged_defense: 0
+ size: small
+ combat_descriptions:
+ - "is engaged in a fight to the death with %s"
```
### Aggressive Mobs
-Mobs with `aggressive: true` auto-attack players entering their room (1-tick delay). Only aggros if the player's combat level is at most double the mob's combat level. Checked on room enter and login.
+Mobs with `combat.stats.aggressive: true` auto-attack players entering their room (1-tick delay). Only aggros if the player's combat level is at most double the mob's combat level. Checked on room enter and login.
```yaml
name: goblin
-aggressive: true # attacks players on sight
-attack: 1
-strength: 3
-defense: 3
-hp: 12
-attack_type: slash
-attack_bonus: 3 # equipment-equivalent attack bonus for mob's attack roll
-strength_bonus: 2 # equipment-equivalent strength bonus for mob's max hit
-stab_defense: 4
-slash_defense: 3
-crush_defense: -2 # weak to crush — negative defense is valid
-science_defense: 0
-ranged_defense: 3
+combat:
+ kind: combat
+ stats:
+ aggressive: true # attacks players on sight
+ hp: 12
+ attack: 1
+ strength: 3
+ defense: 3
+ attack_type: slash
+ speed: 5
+ respawn_ticks: 25
+ bonuses:
+ attack_bonus: 3 # equipment-equivalent attack bonus for mob's attack roll
+ strength_bonus: 2 # equipment-equivalent strength bonus for mob's max hit
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 4
+ slash_defense: 3
+ crush_defense: -2 # weak to crush — negative defense is valid
+ science_defense: 0
+ ranged_defense: 3
+ size: small
```
-### Mob Attack/Defense Fields
+### Combat Stats Fields
+
+All combat stats live under `combat.stats:`
| Field | Description |
|---|---|
+| `hp` | Hit points |
| `attack` | Attack level (base accuracy) |
| `strength` | Strength level (base max hit) |
| `defense` | Defense level (base defense) |
-| `hp` | Hit points |
| `ranged` | Ranged level (for ranged/science mobs) |
| `science` | Science level |
+| `attack_type` | Determines which player defense is used against this mob (stab/slash/crush/ranged/science) |
+| `speed` | Attack speed in ticks (default 5) |
+| `aggressive` | Auto-attacks players on sight (false if omitted) |
+| `respawn_ticks` | Ticks until respawn after death |
+
+#### Bonuses (`combat.stats.bonuses:`)
+
+| Field | Description |
+|---|---|
| `attack_bonus` | Equipment-equivalent attack bonus (added to attack roll) |
| `strength_bonus` | Equipment-equivalent strength bonus (added to max hit) |
-| `attack_type` | Determines which player defense is used against this mob |
-| `stab_defense` through `ranged_defense` | Per-type defense bonuses |
-| `weakness` | Elemental weakness (solar/hydro/eco/bio) — for future Science combat |
+| `science_bonus` | Equipment-equivalent science attack bonus |
+| `science_percent_bonus` | Percent boost to science damage |
+| `ranged_bonus` | Equipment-equivalent ranged attack bonus |
+| `ranged_strength_bonus` | Equipment-equivalent ranged strength bonus |
+
+#### Defenses (`combat.stats.defenses:`)
+
+| Field | Description |
+|---|---|
+| `stab_defense` | Stab defense bonus |
+| `slash_defense` | Slash defense bonus |
+| `crush_defense` | Crush defense bonus |
+| `science_defense` | Science defense bonus |
+| `ranged_defense` | Ranged defense bonus |
+| `weakness` | Elemental weakness (solar/hydro/eco/bio/chaos) — for future Science combat |
+
+#### Combat-level fields (under `combat:`)
+
+| Field | Description |
+|---|---|
+| `kind` | `combat` (default) or `task` — task mobs are worksites |
| `size` | Mob size for safespot blocking: small/medium/large/massive (default: medium) |
+| `assassin_level` | Required assassin skill level to attack this mob |
+| `finishing_blow` | Item ID required to kill (mob stays at 1 HP until used via `use <item> on <target>`) |
+| `damage_without` | Item ID for protection — mob deals 1.5x damage if player lacks it equipped |
+| `combat_descriptions` | List of strings shown when the mob is in combat. Use `%s` for the opponent's name |
### Protected/Unique Mobs
-Protected mobs cannot be attacked. All combat and stat fields (`attack`, `strength`,
-`defense`, `hp`, `speed`, `attack_type`, `attack_bonus`, `strength_bonus`,
-`*_defense`, `weakness`, `size`, `drops`, `aggressive`, `respawn_ticks`) are
-**optional for protected mobs** — omit them entirely. Protected mobs don't show
-a combat level in room listings or when examined.
+Protected mobs cannot be attacked. They have **no `combat:` block** at all. They don't show a combat level in room listings or when examined.
-Minimal protected mob (shopkeeper, quest giver, NPC):
```yaml
name: flight attendant
description: A smiling flight attendant in a crisp uniform.
unique: true # displays as "Flight attendant" not "a flight attendant"
-protected: true # cannot be attacked, combat stats are optional
+protected: true # cannot be attacked, no combat section
idle_descriptions:
- adjusts her name badge
- smiles politely at passengers
@@ -98,18 +150,20 @@ talk: # inline talk config
condition: # only show this node when flag is NOT set
player_flag: 1001_look_sign
not: true
- message: "\"How can I help you?\""
+ messages:
+ - "\"How can I help you?\""
goto: thanks # auto-advance here if condition fails
options:
- text: "\"Oh, nothing...\""
goto: sign_reminder
- text: "\"Goodbye.\""
thanks:
- message: "\"Thank you for flying with us. Be careful on the stairs.\""
+ messages:
+ - "\"Thank you for flying with us. Be careful on the stairs.\""
options:
- text: "\"Thanks!\""
sign_reminder:
- sequence:
+ messages:
- "\"Yeah, just us two! Not a lot of people heading into the belt these days.\""
- "\"But we'll be landing shortly! Look at the information sign so you'll know what to do.\""
options:
@@ -119,16 +173,16 @@ talk: # inline talk config
When the player has `1001_look_sign` set, the `start` node's condition fails, so
it skips directly to `thanks` ("Thank you for flying..."). When the flag is unset,
the player sees "How can I help you?" and can choose to be reminded about the sign
-or say goodbye. The `sign_reminder` node uses a `sequence` so the flight attendant
-delivers two lines, pausing for the player to press enter between them, before
-showing the "Okay" option.
+or say goodbye. The `sign_reminder` node uses a multi-message `messages` list so the
+flight attendant delivers two lines, pausing for the player to press enter between
+them, before showing the "Okay" option.
See the [Talk section of behaviors](behaviors.md#talk-dialog-trees) for the full
-dialog tree format, including sequences and conditional nodes.
+dialog tree format, including multi-message nodes and conditional nodes.
### Shops
-Give a mob a root-level `shop:` block to make it a shopkeeper. Players trade with
+Give a protected mob a root-level `shop:` block to make it a shopkeeper. Players trade with
it using the ordinary `list`, `buy`, and `sell` commands from the game prompt.
Prices derive from each item's `value:` field. See the
[Shops section of behaviors](behaviors.md#shops) for the full format, pricing
@@ -137,7 +191,6 @@ formula, and stock/restock rules.
```yaml
name: Shopkeeper
protected: true
-hp: 50
shop:
items:
- item_id: fishing_rod
@@ -146,57 +199,55 @@ shop:
stock: 10
```
-Protected mob with combat stats (for internal testing or debug purposes):
-```yaml
-name: "Guard"
-unique: true
-protected: true
-talk:
- nodes:
- start:
- message: "\"Halt! Who goes there?\""
- options:
- - text: "\"Just passing through.\""
-attack: 5
-strength: 5
-defense: 5
-hp: 30
-speed: 5
-aggressive: false
-respawn_ticks: 60
-attack_type: slash
-attack_bonus: 8
-strength_bonus: 6
-stab_defense: 12
-slash_defense: 15
-crush_defense: 10
-science_defense: -5
-ranged_defense: 12
-idle_descriptions:
- - "scans the area with a watchful eye"
-```
-
Note: `wander_rooms` and `wander_interval` are NOT set on the mob definition. Wander config
is per-instance in the room YAML (see Rooms > Mobs section above).
### Stealable Mobs
-Mobs can be stealable via the `steal` command. On failure, the mob turns hostile and attacks.
+Stealable mobs have a root-level `steal:` block. On failed steal, the mob turns hostile and attacks.
```yaml
name: Farmer
-steal_table: farmer_steal # Drop table for steal loot
-steal_level: 10 # Required thieving level
-steal_xp: 15 # XP per successful steal
-steal_speed: 4 # Ticks per steal attempt
+steal:
+ table: farmer_steal # Drop table for steal loot
+ level: 10 # Required thieving level
+ xp: 15 # XP per successful steal
+ speed: 4 # Ticks per steal attempt
+combat:
+ kind: combat
+ stats:
+ hp: 15
+ attack: 3
+ strength: 3
+ defense: 3
+ attack_type: crush
+ speed: 5
+ aggressive: false
+ respawn_ticks: 40
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 0
+ slash_defense: 0
+ crush_defense: 0
+ science_defense: 0
+ ranged_defense: 0
+ size: small
+ combat_descriptions:
+ - "swings a shovel at %s"
```
| Field | Description |
|---|---|
-| `steal_table` | Drop table ID for loot when stealing |
-| `steal_level` | Required thieving level |
-| `steal_xp` | XP awarded per successful steal |
-| `steal_speed` | Ticks per steal attempt (base wait) |
+| `steal.table` | Drop table ID for loot when stealing |
+| `steal.level` | Required thieving level |
+| `steal.xp` | XP awarded per successful steal |
+| `steal.speed` | Ticks per steal attempt (base wait) |
### Assassin Mobs
@@ -204,13 +255,35 @@ Assassin (Slayer) mobs restrict combat by assassin level and introduce finishing
```yaml
name: slug
-assassin_level: 1 # required assassin level to attack
-finishing_blow: salt # item required to kill (mob stays at 1 HP otherwise)
-attack: 3
-strength: 3
-defense: 1
-hp: 15
-speed: 6
+combat:
+ kind: combat
+ stats:
+ hp: 15
+ attack: 3
+ strength: 3
+ defense: 1
+ attack_type: crush
+ speed: 6
+ aggressive: false
+ respawn_ticks: 25
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 0
+ slash_defense: 0
+ crush_defense: 0
+ science_defense: 0
+ ranged_defense: 0
+ assassin_level: 1 # required assassin level to attack
+ finishing_blow: salt # item required to kill (mob stays at 1 HP otherwise)
+ size: small
+ combat_descriptions:
+ - "lunges slimily at %s"
drops:
remains: slug_mucus
loot:
@@ -222,47 +295,83 @@ drops:
Damage-without mobs deal 1.5x damage unless the player has the specified item equipped:
```yaml
name: drone
-assassin_level: 15
-damage_without: insulated_gloves # 1.5x damage without this item equipped
-attack: 15
-strength: 14
-defense: 12
-hp: 45
-speed: 4
-aggressive: true
+combat:
+ kind: combat
+ stats:
+ hp: 45
+ attack: 15
+ strength: 14
+ defense: 12
+ attack_type: crush
+ speed: 4
+ aggressive: true
+ respawn_ticks: 35
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 0
+ slash_defense: 0
+ crush_defense: 0
+ science_defense: 0
+ ranged_defense: 0
+ assassin_level: 15
+ damage_without: insulated_gloves # 1.5x damage without this item equipped
+ size: small
```
| Field | Description |
|---|---|
-| `assassin_level` | Required assassin skill level to attack this mob |
-| `finishing_blow` | Item ID required to kill this mob (mob stays at 1 HP until used via `use <item> on <target>`) |
-| `damage_without` | Item ID for protection — mob deals 1.5x damage if player doesn't have it equipped |
+| `combat.assassin_level` | Required assassin skill level to attack this mob |
+| `combat.finishing_blow` | Item ID required to kill this mob (mob stays at 1 HP until used via `use <item> on <target>`) |
+| `combat.damage_without` | Item ID for protection — mob deals 1.5x damage if player doesn't have it equipped |
Mobs without these fields work normally (assassin_level defaults to 0, finishing_blow and damage_without default to empty).
### Task Mobs (Worksites)
-A task mob is a non-violent "worksite" — build a solar panel, survey flora, prospect a rock — that reuses the entire combat engine. Set `kind: task`. Mechanically its `hp` is a hidden work pool that drains to 0 to **complete** the work; the player sees a progress bar filling toward 100%. A task mob **never attacks back** — the danger (if any) comes from a room `hazard:` (see `hazards.md`). Use the `work` command (or `attack`) on it.
+A task mob is a non-violent "worksite" — build a solar panel, survey flora, prospect a rock — that reuses the entire combat engine. Set `combat.kind: task`. Mechanically `combat.stats.hp` is the work pool that drains to 0 to **complete** the work; the player sees a progress bar filling toward 100%. A task mob **never attacks back** — the danger (if any) comes from a room `hazard:` (see `hazards.md`). Use the `work` command (or `attack`) on it.
+
+Task-specific fields live in the root-level `task:` block:
```yaml
name: solar panel frame
-kind: task # "" / "combat" (default) or "task"
-verb: assemble # flavor verb shown in messages (default: "work on")
-progress_noun: assembly # flavor noun in the progress line (default: "work")
-complete_message: "You bolt the final panel into place and the array hums to life!"
-hp: 40 # units of work to complete (NOT a health bar)
-defense: 10 # base difficulty
-speed: 5
-aggressive: false # task mobs do not fight; this is ignored
-respawn_ticks: 40 # the worksite replenishes after this many ticks
-attack_type: crush
-# Per-type defenses become METHOD EFFICIENCY: low = that approach works well.
-crush_defense: 0 # hammering panels in: efficient
-stab_defense: 40 # stabbing a frame: useless
-slash_defense: 40
-ranged_defense: 10 # a rivet gun / scanner (ranged weapon): works
-science_defense: 10 # an analysis deck (science weapon): works
-drops: # the "payment" for the labour — same drop system as combat
+description: "A half-assembled photovoltaic array."
+task:
+ verb: assemble # flavor verb shown in messages (default: "work on")
+ progress_noun: assembly # flavor noun in the progress line (default: "work")
+ complete_message: "You bolt the final panel into place and the solar array hums to life!"
+idle_descriptions:
+ - "stands half-assembled, panels waiting to be fitted"
+combat:
+ kind: task # "task" triggers the work-engine mode
+ stats:
+ hp: 40 # units of work to complete (NOT a health bar)
+ defense: 10 # base difficulty
+ attack_type: crush
+ speed: 5
+ aggressive: false # task mobs do not fight; this is ignored
+ respawn_ticks: 40 # the worksite replenishes after this many ticks
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ # Per-type defenses become METHOD EFFICIENCY: low = that approach works well.
+ defenses:
+ stab_defense: 40 # stabbing a frame: useless
+ slash_defense: 40
+ crush_defense: 0 # hammering panels in: efficient
+ science_defense: 10 # an analysis deck (science weapon): works
+ ranged_defense: 10 # a rivet gun / scanner (ranged weapon): works
+ size: medium
+drops: # the "payment" for the labour — same drop system as combat
loot:
- item_id: credits
weight: 95
@@ -281,5 +390,3 @@ Key points:
- **One worker at a time**, the same 1-v-1 lock as combat.
---
-
-
diff --git a/data/.admin_history.json b/data/.admin_history.json
index 60de6c3..90d278b 100644
--- a/data/.admin_history.json
+++ b/data/.admin_history.json
@@ -1 +1 @@
-{"history":[{"time":"2026-06-30T14:29:37-04:00","description":"delete room 1016 (cleaned 0 exits)","file_path":"data/rooms/intro/1016.yaml","old_content":"id: 1016\nname: New Room\ncolor: \"97\"\ndescription:\n - text: A featureless room.\nexits:\n down:\n room: 1017\n south:\n room: 1009\n southwest:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:29:38-04:00","description":"delete room 1015 (cleaned 0 exits)","file_path":"data/rooms/intro/1015.yaml","old_content":"id: 1015\nname: 'Room #1015'\ncolor: 0C\ndescription: []\nexits:\n northwest:\n room: 1018\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:29:39-04:00","description":"delete room 1017 (cleaned 0 exits)","file_path":"data/rooms/intro/1017.yaml","old_content":"id: 1017\nname: New Room\ncolor: \"\"\ndescription:\n - text: A featureless room.\nexits: {}\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:29:40-04:00","description":"delete room 1018 (cleaned 0 exits)","file_path":"data/rooms/intro/1018.yaml","old_content":"id: 1018\nname: 'Room #1018'\ncolor: D0\ndescription: []\nexits: {}\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:29:40-04:00","description":"delete room 1019 (cleaned 0 exits)","file_path":"data/rooms/intro/1019.yaml","old_content":"id: 1019\nname: 'Room #1019'\ncolor: \"\"\ndescription: []\nexits: {}\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:29:41-04:00","description":"delete room 1020 (cleaned 0 exits)","file_path":"data/rooms/intro/1020.yaml","old_content":"id: 1020\nname: 'Room #1020'\ncolor: \"\"\ndescription: []\nexits: {}\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:30:45-04:00","description":"delete room 1013 (cleaned 1 exits)","file_path":"data/rooms/intro/1013.yaml","old_content":"id: 1013\nname: 'Room #1013'\ncolor: \"72\"\ndescription: []\nexits:\n west:\n room: 1007\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:30:49-04:00","description":"delete room 1009 (cleaned 0 exits)","file_path":"data/rooms/intro/1009.yaml","old_content":"id: 1009\nname: New Room\ncolor: \"27\"\ndescription:\n - text: A featureless room.\nexits:\n northwest:\n room: 8\n southwest:\n room: 1006\n west:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs:\n - id: man\n - id: man\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:30:51-04:00","description":"delete room 1007 (cleaned 1 exits)","file_path":"data/rooms/intro/1007.yaml","old_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n west:\n room: 2004\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:30:53-04:00","description":"delete room 1006 (cleaned 4 exits)","file_path":"data/rooms/intro/1006.yaml","old_content":"id: 1006\nname: New Room\ncolor: E2\ndescription:\n - text: A featureless room.\nexits:\n north:\n room: 1005\n northwest:\n room: 1008\n up:\n room: 1010\n west:\n room: 2003\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:30:59-04:00","description":"delete room 1010 (cleaned 1 exits)","file_path":"data/rooms/intro/1010.yaml","old_content":"id: 1010\nname: New Room\ncolor: \"\"\ndescription:\n - text: A featureless room.\nexits:\n north:\n room: 1011\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:31:00-04:00","description":"delete room 1011 (cleaned 0 exits)","file_path":"data/rooms/intro/1011.yaml","old_content":"id: 1011\nname: New Room\ncolor: \"\"\ndescription:\n - text: A featureless room.\nexits:\n east:\n room: 1012\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:31:01-04:00","description":"delete room 1012 (cleaned 0 exits)","file_path":"data/rooms/intro/1012.yaml","old_content":"id: 1012\nname: New Room\ncolor: \"\"\ndescription:\n - text: A featureless room.\nexits: {}\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:31:02-04:00","description":"delete room 1005 (cleaned 2 exits)","file_path":"data/rooms/intro/1005.yaml","old_content":"id: 1005\nname: New Room\ncolor: CC\ndescription:\n - text: A featureless room.\nexits:\n southwest:\n room: 2003\n west:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:31:03-04:00","description":"delete room 1008 (cleaned 1 exits)","file_path":"data/rooms/intro/1008.yaml","old_content":"id: 1008\nname: New Room\ncolor: A9\ndescription:\n - text: A featureless room.\nexits:\n north:\n room: 7\n south:\n room: 2003\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:29-04:00","description":"update room 2003 (add exit north to 1005)","file_path":"data/rooms/intro/2003.yaml","old_content":"id: 2003\nname: Test Room\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 2003\nname: Test Room\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 1005\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:29-04:00","description":"create room 1005","file_path":"data/rooms/intro/1005.yaml","old_content":"","new_content":"exits:\n south: 2003\nid: 1005\nname: 'Room #1005'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:30-04:00","description":"update room 1005 (add exit east to 1006)","file_path":"data/rooms/intro/1005.yaml","old_content":"exits:\n south: 2003\nid: 1005\nname: 'Room #1005'\n","new_content":"id: 1005\nname: 'Room #1005'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1006\n south:\n room: 2003\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:30-04:00","description":"create room 1006","file_path":"data/rooms/intro/1006.yaml","old_content":"","new_content":"exits:\n west: 1005\nid: 1006\nname: 'Room #1006'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:31-04:00","description":"update room 1006 (add exit south to 1007)","file_path":"data/rooms/intro/1006.yaml","old_content":"exits:\n west: 1005\nid: 1006\nname: 'Room #1006'\n","new_content":"id: 1006\nname: 'Room #1006'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1007\n west:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:31-04:00","description":"create room 1007","file_path":"data/rooms/intro/1007.yaml","old_content":"","new_content":"exits:\n north: 1006\nid: 1007\nname: 'Room #1007'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:32-04:00","description":"update room 1007 (add exit east to 1008)","file_path":"data/rooms/intro/1007.yaml","old_content":"exits:\n north: 1006\nid: 1007\nname: 'Room #1007'\n","new_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1008\n north:\n room: 1006\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:32-04:00","description":"create room 1008","file_path":"data/rooms/intro/1008.yaml","old_content":"","new_content":"exits:\n west: 1007\nid: 1008\nname: 'Room #1008'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:32-04:00","description":"update room 1008 (add exit north to 1009)","file_path":"data/rooms/intro/1008.yaml","old_content":"exits:\n west: 1007\nid: 1008\nname: 'Room #1008'\n","new_content":"id: 1008\nname: 'Room #1008'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1009\n west:\n room: 1007\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:32-04:00","description":"create room 1009","file_path":"data/rooms/intro/1009.yaml","old_content":"","new_content":"exits:\n south: 1008\nid: 1009\nname: 'Room #1009'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:33-04:00","description":"update room 1009 (add exit north to 1010)","file_path":"data/rooms/intro/1009.yaml","old_content":"exits:\n south: 1008\nid: 1009\nname: 'Room #1009'\n","new_content":"id: 1009\nname: 'Room #1009'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1010\n south:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:33-04:00","description":"create room 1010","file_path":"data/rooms/intro/1010.yaml","old_content":"","new_content":"exits:\n south: 1009\nid: 1010\nname: 'Room #1010'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:33-04:00","description":"update room 1010 (add exit east to 1011)","file_path":"data/rooms/intro/1010.yaml","old_content":"exits:\n south: 1009\nid: 1010\nname: 'Room #1010'\n","new_content":"id: 1010\nname: 'Room #1010'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1011\n south:\n room: 1009\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:33-04:00","description":"create room 1011","file_path":"data/rooms/intro/1011.yaml","old_content":"","new_content":"exits:\n west: 1010\nid: 1011\nname: 'Room #1011'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:34-04:00","description":"update room 1011 (add exit south to 1012)","file_path":"data/rooms/intro/1011.yaml","old_content":"exits:\n west: 1010\nid: 1011\nname: 'Room #1011'\n","new_content":"id: 1011\nname: 'Room #1011'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1012\n west:\n room: 1010\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:34-04:00","description":"create room 1012","file_path":"data/rooms/intro/1012.yaml","old_content":"","new_content":"exits:\n north: 1011\nid: 1012\nname: 'Room #1012'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:34-04:00","description":"update room 1012 (add exit south to 1013)","file_path":"data/rooms/intro/1012.yaml","old_content":"exits:\n north: 1011\nid: 1012\nname: 'Room #1012'\n","new_content":"id: 1012\nname: 'Room #1012'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1011\n south:\n room: 1013\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:34-04:00","description":"create room 1013","file_path":"data/rooms/intro/1013.yaml","old_content":"","new_content":"exits:\n north: 1012\nid: 1013\nname: 'Room #1013'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:35-04:00","description":"delete room 1013 (cleaned 1 exits)","file_path":"data/rooms/intro/1013.yaml","old_content":"exits:\n north: 1012\nid: 1013\nname: 'Room #1013'\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:36-04:00","description":"delete room 1012 (cleaned 1 exits)","file_path":"data/rooms/intro/1012.yaml","old_content":"id: 1012\nname: 'Room #1012'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1011\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:37-04:00","description":"delete room 1011 (cleaned 1 exits)","file_path":"data/rooms/intro/1011.yaml","old_content":"id: 1011\nname: 'Room #1011'\ncolor: \"\"\ndescription: []\nexits:\n west:\n room: 1010\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:37-04:00","description":"delete room 1010 (cleaned 1 exits)","file_path":"data/rooms/intro/1010.yaml","old_content":"id: 1010\nname: 'Room #1010'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1009\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:38-04:00","description":"delete room 1009 (cleaned 1 exits)","file_path":"data/rooms/intro/1009.yaml","old_content":"id: 1009\nname: 'Room #1009'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:39-04:00","description":"delete room 1008 (cleaned 1 exits)","file_path":"data/rooms/intro/1008.yaml","old_content":"id: 1008\nname: 'Room #1008'\ncolor: \"\"\ndescription: []\nexits:\n west:\n room: 1007\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:40-04:00","description":"delete room 1007 (cleaned 1 exits)","file_path":"data/rooms/intro/1007.yaml","old_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1006\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:40-04:00","description":"delete room 1006 (cleaned 1 exits)","file_path":"data/rooms/intro/1006.yaml","old_content":"id: 1006\nname: 'Room #1006'\ncolor: \"\"\ndescription: []\nexits:\n west:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:41-04:00","description":"delete room 1005 (cleaned 1 exits)","file_path":"data/rooms/intro/1005.yaml","old_content":"id: 1005\nname: 'Room #1005'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 2003\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T15:05:42-04:00","description":"update room 1001","file_path":"data/rooms/intro/1001.yaml","old_content":"id: 1001\nname: Inside Transport Shuttle\ncolor: \"\"\ndescription:\n - text: |-\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large framed sign hangs next to the closed cockpit door. The piston-powered staircase is firmly closed at the rear of the craft.\n\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large {11}framed sign{/} hangs next to the closed cockpit door. A piston-powered staircase leads down out the back of the small craft with a smiling attendant ready to help disembark.\nexits:\n down:\n room: 1002\n condition:\n flag: \"\"\n value: null\n not: false\n player_flag: 1001_touchdown\n has_item: \"\"\n min_credits: 0\n all_of: []\n any_of: []\n blocked_message: The piston-powered staircase is firmly closed.\n east:\n room: 2001\nobjects:\n - name: framed sign\n hidden: true\n description:\n - text: \"We hope you enjoy your trip on our shuttle! Your pilot is [TYLER].\\n\\nWhen you arrive at your final destination, please be aware of the following basic commands:\\n\\n{0B bold}Movement:{/} {0A}north{/}, {0A}south{/}, {0A}east{/}, {0A}west{/}, {0A}up{/}, {0A}down{/}\\n{0B bold}Look:{/} {0A}look{/}, {0A}look \u003citem/object/mob\u003e{/}, and {0A}map{/}\\n{0B bold}Items:{/} {0A}inv{/} to see your 28-slot inventory\\n {0A}get \u003citem\u003e{/}, {0A}drop \u003citem\u003e{/}, {0A}wear \u003citem\u003e{/}, {0A}remove \u003citem\u003e{/}\\n {0A}use \u003citem\u003e on \u003citem/object\u003e{/}\\n {0A}eq{/} for equiped gear\\n{0B bold}Comms:{/} {0A}talk \u003cmob\u003e{/} for NPC chat\\n {0A}say \u003cmsg\u003e{/} and {0A}global \u003cmsg\u003e{/} for human chat\\n{0B bold}Character:{/} {0A}score{/} and {0A}skills{/} for stats. \\n{0B bold}Combat{/} {0A}attack \u003cmob\u003e{/}\\n{0B bold}Skills{/} Many skills have shortcuts like {0A}mine{/}, {0A}fish{/}, or {0A}chop{/}\\n{0B bold}Options{/} {0A}options{/} for a list of account options\\n {0A}options \u003copt\u003e \u003cvalue\u003e{/} to change an option\\n\\nType {0C bold}what{/} for a list of possible common actions\\n\\nMake sure to check the {0A}help{/} pages, especially {0A}help newplayer{/}!\"\n on_look:\n set_flags: {}\n set_player_flags:\n 1001_look_sign: true\n give_item: \"\"\n take_item: \"\"\n teleport: 0\n heal: 0\n cost: 0\n shop: null\n assign_task: false\n skip_task: false\n extend_task: false\n reputation_cost: 0\n sawmill: false\n aps_node: false\n - name: door\n hidden: true\n description:\n - text: A sturdy, locked steel door that keeps passengers out of the cockpit. There is a tiny, thin window at eye level.\n - name: window\n hidden: true\n description:\n - text: A thick trim with rounded bolt heads frames the tiny window. It looks like it was cut into the door at some point, potentially as a simple replacement to computerized security systems. Inside the cockpit there's a pilot finishing up landing procedures on a large panel of analog instruments.\n - name: instrument panel\n aliases:\n - cockpit\n hidden: true\n description:\n - text: The cramped cockpit is surrounded by buttons, swiches, dials, and analog gauges. The parts are a mix of technologies from the last century. Part of the panel is obscured by a draped cloth as if to hide it from view. Odd.\n - name: pilot\n hidden: true\n description:\n - text: That's the guy who took you from the Passenger Barge Denali down here to Vesta. A middle-aged man in a neat white jumpsuit with a matching white sort of conductor's hat. He's following a written procedure checklist and seems to take his job seriously.\nitem_spawns: []\nmobs:\n - id: flight_attendant\non_enter:\n - message: '{0B bold}Welcome to The House of Icarus{/}'\n condition:\n flag: \"\"\n value: null\n not: true\n player_flag: 1001_welcome\n has_item: \"\"\n min_credits: 0\n all_of: []\n any_of: []\n delay: 5\n set_flags: {}\n set_player_flags: {}\n broadcast: \"\"\n broadcast_global: \"\"\n spawn_mob: null\n despawn_mob: \"\"\n give_item: \"\"\n take_item: \"\"\n teleport: 0\n heal: 0\n - message: '{0B}Type{/} {0A}look sign{/} {0B}or{/} {0A}talk attendant{/} {0B}to get started{/}'\n condition:\n flag: \"\"\n value: null\n not: true\n player_flag: 1001_welcome\n has_item: \"\"\n min_credits: 0\n all_of: []\n any_of: []\n delay: 7\n set_flags: {}\n set_player_flags:\n 1001_welcome: true\n broadcast: \"\"\n broadcast_global: \"\"\n spawn_mob: null\n despawn_mob: \"\"\n give_item: \"\"\n take_item: \"\"\n teleport: 0\n heal: 0\n - message: '{0B}Type{/} {0A}help newplayer{/} {0B}for the new player''s guide. That''s it. Explore and have fun.{/}'\n condition:\n flag: \"\"\n value: null\n not: true\n player_flag: 1001_welcome\n has_item: \"\"\n min_credits: 0\n all_of: []\n any_of: []\n delay: 7\n set_flags: {}\n set_player_flags: {}\n broadcast: \"\"\n broadcast_global: \"\"\n spawn_mob: null\n despawn_mob: \"\"\n give_item: \"\"\n take_item: \"\"\n teleport: 0\n heal: 0\nhazard: \"\"\nblock_transport: true\ntriggers:\n - id: \"\"\n on_player_flag: 1001_look_sign\n on_flag: \"\"\n value: null\n room: 0\n steps:\n - delay: 5\n message: The cabin shakes as the small craft touches down\n broadcast: \"\"\n broadcast_global: \"\"\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n give_item: \"\"\n take_item: \"\"\n teleport: 0\n heal: 0\n despawn_mob: \"\"\n - delay: 5\n message: The pistons hiss as the rear staircase opens\n broadcast: \"\"\n broadcast_global: \"\"\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n give_item: \"\"\n take_item: \"\"\n teleport: 0\n heal: 0\n despawn_mob: \"\"\n - delay: 0\n message: \"\"\n broadcast: \"\"\n broadcast_global: \"\"\n set_flags: {}\n set_player_flags:\n 1001_touchdown: true\n spawn_mob: null\n give_item: \"\"\n take_item: \"\"\n teleport: 0\n heal: 0\n despawn_mob: \"\"\n","new_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: |-\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large framed sign hangs next to the closed cockpit door. The piston-powered staircase is firmly closed at the rear of the craft.\n\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large {11}framed sign{/} hangs next to the closed cockpit door. A piston-powered staircase leads down out the back of the small craft with a smiling attendant ready to help disembark.\nexits:\n down:\n blocked_message: The piston-powered staircase is firmly closed.\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: false\n player_flag: 1001_touchdown\n value: null\n room: 1002\n east:\n room: 2001\nhazard: \"\"\nid: 1001\nitem_spawns: []\nmobs:\n - id: flight_attendant\nname: Inside Transport Shuttle\nobjects:\n - description:\n - text: \"We hope you enjoy your trip on our shuttle! Your pilot is [TYLER].\\n\\nWhen you arrive at your final destination, please be aware of the following basic commands:\\n\\n{0B bold}Movement:{/} {0A}north{/}, {0A}south{/}, {0A}east{/}, {0A}west{/}, {0A}up{/}, {0A}down{/}\\n{0B bold}Look:{/} {0A}look{/}, {0A}look \u003citem/object/mob\u003e{/}, and {0A}map{/}\\n{0B bold}Items:{/} {0A}inv{/} to see your 28-slot inventory\\n {0A}get \u003citem\u003e{/}, {0A}drop \u003citem\u003e{/}, {0A}wear \u003citem\u003e{/}, {0A}remove \u003citem\u003e{/}\\n {0A}use \u003citem\u003e on \u003citem/object\u003e{/}\\n {0A}eq{/} for equiped gear\\n{0B bold}Comms:{/} {0A}talk \u003cmob\u003e{/} for NPC chat\\n {0A}say \u003cmsg\u003e{/} and {0A}global \u003cmsg\u003e{/} for human chat\\n{0B bold}Character:{/} {0A}score{/} and {0A}skills{/} for stats. \\n{0B bold}Combat{/} {0A}attack \u003cmob\u003e{/}\\n{0B bold}Skills{/} Many skills have shortcuts like {0A}mine{/}, {0A}fish{/}, or {0A}chop{/}\\n{0B bold}Options{/} {0A}options{/} for a list of account options\\n {0A}options \u003copt\u003e \u003cvalue\u003e{/} to change an option\\n\\nType {0C bold}what{/} for a list of possible common actions\\n\\nMake sure to check the {0A}help{/} pages, especially {0A}help newplayer{/}!\"\n hidden: true\n name: framed sign\n on_look:\n aps_node: false\n assign_task: false\n cost: 0\n extend_task: false\n give_item: \"\"\n heal: 0\n reputation_cost: 0\n sawmill: false\n set_flags: {}\n set_player_flags:\n 1001_look_sign: true\n shop: null\n skip_task: false\n take_item: \"\"\n teleport: 0\n - description:\n - text: A sturdy, locked steel door that keeps passengers out of the cockpit. There is a tiny, thin window at eye level.\n hidden: true\n name: door\n - description:\n - text: A thick trim with rounded bolt heads frames the tiny window. It looks like it was cut into the door at some point, potentially as a simple replacement to computerized security systems. Inside the cockpit there's a pilot finishing up landing procedures on a large panel of analog instruments.\n hidden: true\n name: window\n - aliases:\n - cockpit\n description:\n - text: The cramped cockpit is surrounded by buttons, swiches, dials, and analog gauges. The parts are a mix of technologies from the last century. Part of the panel is obscured by a draped cloth as if to hide it from view. Odd.\n hidden: true\n name: instrument panel\n - aliases: []\n description:\n - text: That's the guy who took you from the Passenger Barge Denali down here to Vesta. A middle-aged man in a neat white jumpsuit with a matching white sort of conductor's hat. He's following a written procedure checklist and seems to take his job seriously.\n hidden: false\n name: pilot\non_enter:\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B bold}Welcome to The House of Icarus{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}look sign{/} {0B}or{/} {0A}talk attendant{/} {0B}to get started{/}'\n set_flags: {}\n set_player_flags:\n 1001_welcome: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}help newplayer{/} {0B}for the new player''s guide. That''s it. Explore and have fun.{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\ntriggers:\n - id: \"\"\n on_flag: \"\"\n on_player_flag: 1001_look_sign\n room: 0\n steps:\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The cabin shakes as the small craft touches down\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The pistons hiss as the rear staircase opens\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 0\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: \"\"\n set_flags: {}\n set_player_flags:\n 1001_touchdown: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n value: null\n","is_delete":false,"is_create":false},{"time":"2026-06-30T15:05:43-04:00","description":"update room 1001","file_path":"data/rooms/intro/1001.yaml","old_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: |-\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large framed sign hangs next to the closed cockpit door. The piston-powered staircase is firmly closed at the rear of the craft.\n\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large {11}framed sign{/} hangs next to the closed cockpit door. A piston-powered staircase leads down out the back of the small craft with a smiling attendant ready to help disembark.\nexits:\n down:\n blocked_message: The piston-powered staircase is firmly closed.\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: false\n player_flag: 1001_touchdown\n value: null\n room: 1002\n east:\n room: 2001\nhazard: \"\"\nid: 1001\nitem_spawns: []\nmobs:\n - id: flight_attendant\nname: Inside Transport Shuttle\nobjects:\n - description:\n - text: \"We hope you enjoy your trip on our shuttle! Your pilot is [TYLER].\\n\\nWhen you arrive at your final destination, please be aware of the following basic commands:\\n\\n{0B bold}Movement:{/} {0A}north{/}, {0A}south{/}, {0A}east{/}, {0A}west{/}, {0A}up{/}, {0A}down{/}\\n{0B bold}Look:{/} {0A}look{/}, {0A}look \u003citem/object/mob\u003e{/}, and {0A}map{/}\\n{0B bold}Items:{/} {0A}inv{/} to see your 28-slot inventory\\n {0A}get \u003citem\u003e{/}, {0A}drop \u003citem\u003e{/}, {0A}wear \u003citem\u003e{/}, {0A}remove \u003citem\u003e{/}\\n {0A}use \u003citem\u003e on \u003citem/object\u003e{/}\\n {0A}eq{/} for equiped gear\\n{0B bold}Comms:{/} {0A}talk \u003cmob\u003e{/} for NPC chat\\n {0A}say \u003cmsg\u003e{/} and {0A}global \u003cmsg\u003e{/} for human chat\\n{0B bold}Character:{/} {0A}score{/} and {0A}skills{/} for stats. \\n{0B bold}Combat{/} {0A}attack \u003cmob\u003e{/}\\n{0B bold}Skills{/} Many skills have shortcuts like {0A}mine{/}, {0A}fish{/}, or {0A}chop{/}\\n{0B bold}Options{/} {0A}options{/} for a list of account options\\n {0A}options \u003copt\u003e \u003cvalue\u003e{/} to change an option\\n\\nType {0C bold}what{/} for a list of possible common actions\\n\\nMake sure to check the {0A}help{/} pages, especially {0A}help newplayer{/}!\"\n hidden: true\n name: framed sign\n on_look:\n aps_node: false\n assign_task: false\n cost: 0\n extend_task: false\n give_item: \"\"\n heal: 0\n reputation_cost: 0\n sawmill: false\n set_flags: {}\n set_player_flags:\n 1001_look_sign: true\n shop: null\n skip_task: false\n take_item: \"\"\n teleport: 0\n - description:\n - text: A sturdy, locked steel door that keeps passengers out of the cockpit. There is a tiny, thin window at eye level.\n hidden: true\n name: door\n - description:\n - text: A thick trim with rounded bolt heads frames the tiny window. It looks like it was cut into the door at some point, potentially as a simple replacement to computerized security systems. Inside the cockpit there's a pilot finishing up landing procedures on a large panel of analog instruments.\n hidden: true\n name: window\n - aliases:\n - cockpit\n description:\n - text: The cramped cockpit is surrounded by buttons, swiches, dials, and analog gauges. The parts are a mix of technologies from the last century. Part of the panel is obscured by a draped cloth as if to hide it from view. Odd.\n hidden: true\n name: instrument panel\n - aliases: []\n description:\n - text: That's the guy who took you from the Passenger Barge Denali down here to Vesta. A middle-aged man in a neat white jumpsuit with a matching white sort of conductor's hat. He's following a written procedure checklist and seems to take his job seriously.\n hidden: false\n name: pilot\non_enter:\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B bold}Welcome to The House of Icarus{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}look sign{/} {0B}or{/} {0A}talk attendant{/} {0B}to get started{/}'\n set_flags: {}\n set_player_flags:\n 1001_welcome: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}help newplayer{/} {0B}for the new player''s guide. That''s it. Explore and have fun.{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\ntriggers:\n - id: \"\"\n on_flag: \"\"\n on_player_flag: 1001_look_sign\n room: 0\n steps:\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The cabin shakes as the small craft touches down\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The pistons hiss as the rear staircase opens\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 0\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: \"\"\n set_flags: {}\n set_player_flags:\n 1001_touchdown: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n value: null\n","new_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: |-\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large framed sign hangs next to the closed cockpit door. The piston-powered staircase is firmly closed at the rear of the craft.\n\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large {11}framed sign{/} hangs next to the closed cockpit door. A piston-powered staircase leads down out the back of the small craft with a smiling attendant ready to help disembark.\nexits:\n down:\n blocked_message: The piston-powered staircase is firmly closed.\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: false\n player_flag: 1001_touchdown\n value: null\n room: 1002\n east:\n room: 2001\nhazard: \"\"\nid: 1001\nitem_spawns: []\nmobs:\n - id: flight_attendant\nname: Inside Transport Shuttle\nobjects:\n - description:\n - text: \"We hope you enjoy your trip on our shuttle! Your pilot is [TYLER].\\n\\nWhen you arrive at your final destination, please be aware of the following basic commands:\\n\\n{0B bold}Movement:{/} {0A}north{/}, {0A}south{/}, {0A}east{/}, {0A}west{/}, {0A}up{/}, {0A}down{/}\\n{0B bold}Look:{/} {0A}look{/}, {0A}look \u003citem/object/mob\u003e{/}, and {0A}map{/}\\n{0B bold}Items:{/} {0A}inv{/} to see your 28-slot inventory\\n {0A}get \u003citem\u003e{/}, {0A}drop \u003citem\u003e{/}, {0A}wear \u003citem\u003e{/}, {0A}remove \u003citem\u003e{/}\\n {0A}use \u003citem\u003e on \u003citem/object\u003e{/}\\n {0A}eq{/} for equiped gear\\n{0B bold}Comms:{/} {0A}talk \u003cmob\u003e{/} for NPC chat\\n {0A}say \u003cmsg\u003e{/} and {0A}global \u003cmsg\u003e{/} for human chat\\n{0B bold}Character:{/} {0A}score{/} and {0A}skills{/} for stats. \\n{0B bold}Combat{/} {0A}attack \u003cmob\u003e{/}\\n{0B bold}Skills{/} Many skills have shortcuts like {0A}mine{/}, {0A}fish{/}, or {0A}chop{/}\\n{0B bold}Options{/} {0A}options{/} for a list of account options\\n {0A}options \u003copt\u003e \u003cvalue\u003e{/} to change an option\\n\\nType {0C bold}what{/} for a list of possible common actions\\n\\nMake sure to check the {0A}help{/} pages, especially {0A}help newplayer{/}!\"\n hidden: true\n name: framed sign\n on_look:\n aps_node: false\n assign_task: false\n cost: 0\n extend_task: false\n give_item: \"\"\n heal: 0\n reputation_cost: 0\n sawmill: false\n set_flags: {}\n set_player_flags:\n 1001_look_sign: true\n shop: null\n skip_task: false\n take_item: \"\"\n teleport: 0\n - description:\n - text: A sturdy, locked steel door that keeps passengers out of the cockpit. There is a tiny, thin window at eye level.\n hidden: true\n name: door\n - description:\n - text: A thick trim with rounded bolt heads frames the tiny window. It looks like it was cut into the door at some point, potentially as a simple replacement to computerized security systems. Inside the cockpit there's a pilot finishing up landing procedures on a large panel of analog instruments.\n hidden: true\n name: window\n - aliases:\n - cockpit\n description:\n - text: The cramped cockpit is surrounded by buttons, swiches, dials, and analog gauges. The parts are a mix of technologies from the last century. Part of the panel is obscured by a draped cloth as if to hide it from view. Odd.\n hidden: true\n name: instrument panel\n - aliases: []\n description:\n - text: That's the guy who took you from the Passenger Barge Denali down here to Vesta. A middle-aged man in a neat white jumpsuit with a matching white sort of conductor's hat. He's following a written procedure checklist and seems to take his job seriously.\n hidden: true\n name: pilot\non_enter:\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B bold}Welcome to The House of Icarus{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}look sign{/} {0B}or{/} {0A}talk attendant{/} {0B}to get started{/}'\n set_flags: {}\n set_player_flags:\n 1001_welcome: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}help newplayer{/} {0B}for the new player''s guide. That''s it. Explore and have fun.{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\ntriggers:\n - id: \"\"\n on_flag: \"\"\n on_player_flag: 1001_look_sign\n room: 0\n steps:\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The cabin shakes as the small craft touches down\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The pistons hiss as the rear staircase opens\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 0\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: \"\"\n set_flags: {}\n set_player_flags:\n 1001_touchdown: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n value: null\n","is_delete":false,"is_create":false},{"time":"2026-06-30T16:34:21-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T16:35:02-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T16:35:15-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T17:43:28-04:00","description":"Update object copper_rock","file_path":"data/objects/copper_rock.yaml","old_content":"color: \"B2\"\ngather:\n depleted_message: You don't see any ore in this rock.\n drops:\n - depletes: true\n item_id: copper_ore\n level: 1\n message: You manage to mine some {B2}copper ore{/}.\n weight: 90\n xp: 17\n - depletes: false\n message: You spot a glint of something valuable!\n table: gem_table\n weight: 10\n fail_message: You chip away but get nothing useful.\n gather_message: You swing your pickaxe at the rock...\n respawn_broadcast: A glint of copper catches your eye from some {name}.\n respawn_timer: 50\n skill: mining\n success:\n base: 0.5\n cap: 0.95\n per_level: 0.01\n tools:\n - pickaxe\nname: copper rock\n","new_content":"aliases: []\ncolor: B2\ndescription: \"\"\ngather:\n bait: \"\"\n deplete_timer: 0\n depleted_message: You don't see any ore in this rock.\n drops:\n - depletes: true\n item_id: copper_ore\n level: 1\n message: You manage to mine some {B2}copper ore{/}.\n quantity: 0\n table: \"\"\n weight: 90\n xp: 17\n - depletes: false\n item_id: \"\"\n level: 0\n message: You spot a glint of something valuable!\n quantity: 0\n table: gem_table\n weight: 10\n xp: 0\n exhausted_message: \"\"\n fail_message: You chip away but get nothing useful.\n gather_message: You swing your pickaxe at the rock...\n nest_chance: 0\n respawn_broadcast: A glint of copper catches your eye from some {name}.\n respawn_timer: 50\n skill: mining\n success:\n base: 0.5\n cap: 0.95\n per_level: 0.01\n tools:\n - pickaxe\nhidden: false\nid: copper_rock\ninroom_description: \"\"\nname: copper rock\nremoval_item: \"\"\n","is_delete":false,"is_create":false},{"time":"2026-06-30T23:48:18-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T23:48:23-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 0\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T23:53:08-04:00","description":"Update item bread_dough","file_path":"data/items/consumables/bread_dough.yaml","old_content":"color: \"DE\"\ncraft:\n type: combine\n consume:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n wait: 2\ndescription: A ball of uncooked bread dough. It needs to be baked.\nname: bread dough\nstackable: false\nvalue: 3\n","new_content":"color: DE\ncraft:\n - consume:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n end_message: testend\n fail: \"\"\n level: 0\n message: testmsg\n output_qty: 0\n start_message: teststart\n station: []\n subtype: \"\"\n tool: \"\"\n type: combine\n wait: 2\n xp: 0\ndescription: A ball of uncooked bread dough. It needs to be baked.\nid: bread_dough\nmax_quality: 0\nname: bread dough\nquality: 0\nstackable: false\nvalue: 3\n","is_delete":false,"is_create":false},{"time":"2026-07-01T00:23:04-04:00","description":"Update item bread_dough","file_path":"data/items/consumables/bread_dough.yaml","old_content":"color: DE\ncraft:\n - consume:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n end_message: testend\n fail: \"\"\n level: 0\n message: testmsg\n output_qty: 0\n start_message: teststart\n station: []\n subtype: \"\"\n tool: \"\"\n type: combine\n wait: 2\n xp: 0\ndescription: A ball of uncooked bread dough. It needs to be baked.\nid: bread_dough\nmax_quality: 0\nname: bread dough\nquality: 0\nstackable: false\nvalue: 3\n","new_content":"color: DE\ncraft:\n - consume:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n end_message: testend\n fail: \"\"\n level: 0\n message: testmsg\n output_qty: 0\n start_message: teststart\n station: []\n subtype: \"\"\n tool: \"\"\n type: combine\n wait: 2\n xp: 0\ndescription: A ball of uncooked bread dough. It needs to be baked.\nid: bread_dough\nmax_quality: 0\nname: bread dough\nquality: 0\nstackable: false\nvalue: 3\n","is_delete":false,"is_create":false},{"time":"2026-07-01T01:22:55-04:00","description":"update room 1001","file_path":"data/rooms/intro/1001.yaml","old_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: |-\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large framed sign hangs next to the closed cockpit door. The piston-powered staircase is firmly closed at the rear of the craft.\n\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large {11}framed sign{/} hangs next to the closed cockpit door. A piston-powered staircase leads down out the back of the small craft with a smiling attendant ready to help disembark.\nexits:\n down:\n blocked_message: The piston-powered staircase is firmly closed.\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: false\n player_flag: 1001_touchdown\n value: null\n room: 1002\n east:\n room: 2001\nhazard: \"\"\nid: 1001\nitem_spawns: []\nmobs:\n - id: flight_attendant\nname: Inside Transport Shuttle\nobjects:\n - description:\n - text: \"We hope you enjoy your trip on our shuttle! Your pilot is [TYLER].\\n\\nWhen you arrive at your final destination, please be aware of the following basic commands:\\n\\n{0B bold}Movement:{/} {0A}north{/}, {0A}south{/}, {0A}east{/}, {0A}west{/}, {0A}up{/}, {0A}down{/}\\n{0B bold}Look:{/} {0A}look{/}, {0A}look \u003citem/object/mob\u003e{/}, and {0A}map{/}\\n{0B bold}Items:{/} {0A}inv{/} to see your 28-slot inventory\\n {0A}get \u003citem\u003e{/}, {0A}drop \u003citem\u003e{/}, {0A}wear \u003citem\u003e{/}, {0A}remove \u003citem\u003e{/}\\n {0A}use \u003citem\u003e on \u003citem/object\u003e{/}\\n {0A}eq{/} for equiped gear\\n{0B bold}Comms:{/} {0A}talk \u003cmob\u003e{/} for NPC chat\\n {0A}say \u003cmsg\u003e{/} and {0A}global \u003cmsg\u003e{/} for human chat\\n{0B bold}Character:{/} {0A}score{/} and {0A}skills{/} for stats. \\n{0B bold}Combat{/} {0A}attack \u003cmob\u003e{/}\\n{0B bold}Skills{/} Many skills have shortcuts like {0A}mine{/}, {0A}fish{/}, or {0A}chop{/}\\n{0B bold}Options{/} {0A}options{/} for a list of account options\\n {0A}options \u003copt\u003e \u003cvalue\u003e{/} to change an option\\n\\nType {0C bold}what{/} for a list of possible common actions\\n\\nMake sure to check the {0A}help{/} pages, especially {0A}help newplayer{/}!\"\n hidden: true\n name: framed sign\n on_look:\n aps_node: false\n assign_task: false\n cost: 0\n extend_task: false\n give_item: \"\"\n heal: 0\n reputation_cost: 0\n sawmill: false\n set_flags: {}\n set_player_flags:\n 1001_look_sign: true\n shop: null\n skip_task: false\n take_item: \"\"\n teleport: 0\n - description:\n - text: A sturdy, locked steel door that keeps passengers out of the cockpit. There is a tiny, thin window at eye level.\n hidden: true\n name: door\n - description:\n - text: A thick trim with rounded bolt heads frames the tiny window. It looks like it was cut into the door at some point, potentially as a simple replacement to computerized security systems. Inside the cockpit there's a pilot finishing up landing procedures on a large panel of analog instruments.\n hidden: true\n name: window\n - aliases:\n - cockpit\n description:\n - text: The cramped cockpit is surrounded by buttons, swiches, dials, and analog gauges. The parts are a mix of technologies from the last century. Part of the panel is obscured by a draped cloth as if to hide it from view. Odd.\n hidden: true\n name: instrument panel\n - aliases: []\n description:\n - text: That's the guy who took you from the Passenger Barge Denali down here to Vesta. A middle-aged man in a neat white jumpsuit with a matching white sort of conductor's hat. He's following a written procedure checklist and seems to take his job seriously.\n hidden: true\n name: pilot\non_enter:\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B bold}Welcome to The House of Icarus{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}look sign{/} {0B}or{/} {0A}talk attendant{/} {0B}to get started{/}'\n set_flags: {}\n set_player_flags:\n 1001_welcome: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}help newplayer{/} {0B}for the new player''s guide. That''s it. Explore and have fun.{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\ntriggers:\n - id: \"\"\n on_flag: \"\"\n on_player_flag: 1001_look_sign\n room: 0\n steps:\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The cabin shakes as the small craft touches down\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The pistons hiss as the rear staircase opens\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 0\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: \"\"\n set_flags: {}\n set_player_flags:\n 1001_touchdown: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n value: null\n","new_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: |-\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large framed sign hangs next to the closed cockpit door. The piston-powered staircase is firmly closed at the rear of the craft.\n\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large {11}framed sign{/} hangs next to the closed cockpit door. A piston-powered staircase leads down out the back of the small craft with a smiling attendant ready to help disembark.\nexits:\n down:\n blocked_message: The piston-powered staircase is firmly closed.\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: false\n player_flag: 1001_touchdown\n value: null\n room: 1002\n east:\n room: 2001\nhazard: \"\"\nid: 1001\nitem_spawns: []\nmobs:\n - id: flight_attendant\nname: Inside Transport Shuttle\nobjects:\n - description:\n - text: \"We hope you enjoy your trip on our shuttle! Your pilot is [TYLER].\\n\\nWhen you arrive at your final destination, please be aware of the following basic commands:\\n\\n{0B bold}Movement:{/} {0A}north{/}, {0A}south{/}, {0A}east{/}, {0A}west{/}, {0A}up{/}, {0A}down{/}\\n{0B bold}Look:{/} {0A}look{/}, {0A}look \u003citem/object/mob\u003e{/}, and {0A}map{/}\\n{0B bold}Items:{/} {0A}inv{/} to see your 28-slot inventory\\n {0A}get \u003citem\u003e{/}, {0A}drop \u003citem\u003e{/}, {0A}wear \u003citem\u003e{/}, {0A}remove \u003citem\u003e{/}\\n {0A}use \u003citem\u003e on \u003citem/object\u003e{/}\\n {0A}eq{/} for equiped gear\\n{0B bold}Comms:{/} {0A}talk \u003cmob\u003e{/} for NPC chat\\n {0A}say \u003cmsg\u003e{/} and {0A}global \u003cmsg\u003e{/} for human chat\\n{0B bold}Character:{/} {0A}score{/} and {0A}skills{/} for stats. \\n{0B bold}Combat{/} {0A}attack \u003cmob\u003e{/}\\n{0B bold}Skills{/} Many skills have shortcuts like {0A}mine{/}, {0A}fish{/}, or {0A}chop{/}\\n{0B bold}Options{/} {0A}options{/} for a list of account options\\n {0A}options \u003copt\u003e \u003cvalue\u003e{/} to change an option\\n\\nType {0C bold}what{/} for a list of possible common actions\\n\\nMake sure to check the {0A}help{/} pages, especially {0A}help newplayer{/}!\"\n hidden: true\n name: framed sign\n on_look:\n aps_node: false\n assign_task: false\n cost: 0\n extend_task: false\n give_item: \"\"\n heal: 0\n reputation_cost: 0\n sawmill: false\n set_flags: {}\n set_player_flags:\n 1001_look_sign: true\n shop: null\n skip_task: false\n take_item: \"\"\n teleport: 0\n - description:\n - text: A sturdy, locked steel door that keeps passengers out of the cockpit. There is a tiny, thin window at eye level.\n hidden: true\n name: door\n - description:\n - text: A thick trim with rounded bolt heads frames the tiny window. It looks like it was cut into the door at some point, potentially as a simple replacement to computerized security systems. Inside the cockpit there's a pilot finishing up landing procedures on a large panel of analog instruments.\n hidden: true\n name: window\n - aliases:\n - cockpit\n description:\n - text: The cramped cockpit is surrounded by buttons, swiches, dials, and analog gauges. The parts are a mix of technologies from the last century. Part of the panel is obscured by a draped cloth as if to hide it from view. Odd.\n hidden: true\n name: instrument panel\n - aliases: []\n description:\n - text: That's the guy who took you from the Passenger Barge Denali down here to Vesta. A middle-aged man in a neat white jumpsuit with a matching white sort of conductor's hat. He's following a written procedure checklist and seems to take his job seriously.\n hidden: true\n name: pilot\non_enter:\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B bold}Welcome to The House of Icarus{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}look sign{/} {0B}or{/} {0A}talk attendant{/} {0B}to get started{/}'\n set_flags: {}\n set_player_flags:\n 1001_welcome: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}help newplayer{/} {0B}for the new player''s guide. That''s it. Explore and have fun.{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\ntriggers:\n - id: \"\"\n on_flag: \"\"\n on_player_flag: 1001_look_sign\n room: 0\n steps:\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The cabin shakes as the small craft touches down\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The pistons hiss as the rear staircase opens\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 0\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: \"\"\n set_flags: {}\n set_player_flags:\n 1001_touchdown: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n value: null\n","is_delete":false,"is_create":false},{"time":"2026-07-01T03:00:10-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 0\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T03:00:11-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T03:52:58-04:00","description":"Update item bread_dough","file_path":"data/items/consumables/bread_dough.yaml","old_content":"color: DE\ncraft:\n - ingredients:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n end_message: testend\n fail: \"\"\n level: 0\n success_message: testmsg\n output_qty: 0\n start_message: teststart\n station: []\n subtype: \"\"\n tool: \"\"\n type: combine\n ticks_per_cycle: 2\n xp: 0\ndescription: A ball of uncooked bread dough. It needs to be baked.\nid: bread_dough\nmax_quality: 0\nname: bread dough\nquality: 0\nstackable: false\nvalue: 3\n","new_content":"color: DE\ncraft:\n - end_message: \"\"\n fail: \"\"\n ingredients:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n level: 0\n output_qty: 0\n start_message: \"\"\n station: []\n subtype: \"\"\n success_message: \"\"\n ticks_per_cycle: 2\n tool: \"\"\n type: smithing\n xp: 0\ndescription: A ball of uncooked bread dough. It needs to be baked.\nid: bread_dough\nmax_quality: 0\nname: bread dough\nquality: 0\nstackable: false\nvalue: 3\n","is_delete":false,"is_create":false},{"time":"2026-07-01T03:53:08-04:00","description":"Update item bread_dough","file_path":"data/items/consumables/bread_dough.yaml","old_content":"color: DE\ncraft:\n - end_message: \"\"\n fail: \"\"\n ingredients:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n level: 0\n output_qty: 0\n start_message: \"\"\n station: []\n subtype: \"\"\n success_message: \"\"\n ticks_per_cycle: 2\n tool: \"\"\n type: smithing\n xp: 0\ndescription: A ball of uncooked bread dough. It needs to be baked.\nid: bread_dough\nmax_quality: 0\nname: bread dough\nquality: 0\nstackable: false\nvalue: 3\n","new_content":"color: DE\ncraft:\n - end_message: \"\"\n fail: \"\"\n ingredients:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n level: 0\n output_qty: 0\n start_message: \"\"\n station: []\n subtype: \"\"\n success_message: \"\"\n ticks_per_cycle: 2\n tool: \"\"\n type: combine\n xp: 0\ndescription: A ball of uncooked bread dough. It needs to be baked.\nid: bread_dough\nmax_quality: 0\nname: bread dough\nquality: 0\nstackable: false\nvalue: 3\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:08:15-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: solar_radiation\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:08:19-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: solar_radiation\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:08:26-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:08:32-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - id: tree\n - aliases: []\n description:\n - text: \"\"\n hidden: false\n name: \"\"\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:08:37-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - id: tree\n - aliases: []\n description:\n - text: \"\"\n hidden: false\n name: \"\"\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - aliases: []\n description: []\n hidden: false\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:08:43-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - aliases: []\n description: []\n hidden: false\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - aliases: []\n description:\n - text: YOU FOUND HIM\n hidden: false\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:08:44-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - aliases: []\n description:\n - text: YOU FOUND HIM\n hidden: false\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - aliases: []\n description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:41-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"id: 2003\nname: Test Room\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:41-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:44-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:44-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:47-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:47-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:49-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:49-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:51-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:53-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:55-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:56-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:58-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:58-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:10:01-04:00","description":"update room 2003 (add exit northeast to 1005)","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"id: 2003\nname: Test Room\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n northeast:\n room: 1005\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:10:01-04:00","description":"create room 1005","file_path":"data/rooms/intro/1005.yaml","old_content":"","new_content":"color: A5\nexits:\n southwest: 2003\nid: 1005\nname: 'Room #1005'\n","is_delete":false,"is_create":true},{"time":"2026-07-01T04:10:03-04:00","description":"delete room 1005 (cleaned 1 exits)","file_path":"data/rooms/intro/1005.yaml","old_content":"color: A5\nexits:\n southwest: 2003\nid: 1005\nname: 'Room #1005'\n","new_content":"","is_delete":true,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2003.yaml","old_content":"id: 2003\nname: Test Room\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n northeast:\n room: 1005\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 2003\nname: Test Room\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-01T04:11:43-04:00","description":"update room 2003 (add exit north to 1005)","file_path":"data/rooms/intro/2003.yaml","old_content":"id: 2003\nname: Test Room\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 2003\nname: Test Room\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 1005\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:22:38-04:00","description":"Update drop credit_stick_drop","file_path":"data/drops/credit_stick_drop.yaml","old_content":"drops:\n - item_id: credits\n weight: 40\n quantity: 15\n - item_id: credits\n weight: 30\n quantity: 30\n - item_id: credits\n weight: 20\n quantity: 50\n - item_id: credits\n weight: 8\n quantity: 100\n - item_id: credits\n weight: 2\n quantity: 250","new_content":"drops:\n - item_id: credits\n quantity: 14\n weight: 40\n - item_id: credits\n quantity: 30\n weight: 30\n - item_id: credits\n quantity: 50\n weight: 20\n - item_id: credits\n quantity: 100\n weight: 8\n - item_id: credits\n quantity: 250\n weight: 2\nid: credit_stick_drop\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:22:42-04:00","description":"Update drop credit_stick_drop","file_path":"data/drops/credit_stick_drop.yaml","old_content":"drops:\n - item_id: credits\n quantity: 14\n weight: 40\n - item_id: credits\n quantity: 30\n weight: 30\n - item_id: credits\n quantity: 50\n weight: 20\n - item_id: credits\n quantity: 100\n weight: 8\n - item_id: credits\n quantity: 250\n weight: 2\nid: credit_stick_drop\n","new_content":"drops:\n - item_id: credits\n quantity: 15\n weight: 40\n - item_id: credits\n quantity: 30\n weight: 30\n - item_id: credits\n quantity: 50\n weight: 20\n - item_id: credits\n quantity: 100\n weight: 8\n - item_id: credits\n quantity: 250\n weight: 2\nid: credit_stick_drop\n","is_delete":false,"is_create":false},{"time":"2026-07-01T13:06:32-04:00","description":"Create mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"","new_content":"id: flight_attendant_copy\n","is_delete":false,"is_create":true},{"time":"2026-07-01T13:06:32-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"id: flight_attendant_copy\n","new_content":"description: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nname: flight attendant\nprotected: true\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - text: '\"Thank you.\"'\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T13:07:46-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"description: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nname: flight attendant\nprotected: true\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - text: '\"Thank you.\"'\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n sequence:\n - Test\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - text: '\"Thank you.\"'\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T13:08:04-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n sequence:\n - Test\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - text: '\"Thank you.\"'\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n sequence:\n - Test\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - text: '\"Thank you.\"'\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T13:09:12-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n sequence:\n - Test\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - text: '\"Thank you.\"'\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - goto: Test\n text: '\"Thank you.\"'\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T13:16:15-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - goto: Test\n text: '\"Thank you.\"'\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - goto: Test\n text: '\"Thank you.\"'\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T13:16:46-04:00","description":"Update item adamant_arrow","file_path":"data/items/ammo/adamant_arrow.yaml","old_content":"color: \"78\"\ncraft:\n ingredients:\n - items:\n - headless_arrow\n quantity: 15\n - items:\n - adamant_arrowtips\n quantity: 15\n level: 60\n output_qty: 15\n type: fletching\n ticks_per_cycle: 2\n xp: 10\ndescription: An adamant-tipped arrow.\nequipment:\n other:\n ranged: 31\n slot: ammo\n type: ammo\nname: adamant arrow\nrecoverable: true\nstackable: true\nvalue: 20\n","new_content":"color: \"78\"\ncraft:\n - end_message: \"\"\n fail: \"\"\n ingredients:\n - items:\n - headless_arrow\n quantity: 15\n - items:\n - adamant_arrowtips\n quantity: 15\n level: 60\n output_qty: 15\n start_message: \"\"\n station: []\n subtype: \"\"\n success_message: \"\"\n ticks_per_cycle: 2\n tool: \"\"\n type: fletching\n xp: 10\ndescription: An adamant-tipped arrow.2\nequipment:\n other:\n ranged: 31\n slot: ammo\n type: ammo\nid: adamant_arrow\nmax_quality: 0\nname: adamant arrow\nquality: 0\nrecoverable: true\nstackable: true\nvalue: 20\n","is_delete":false,"is_create":false},{"time":"2026-07-01T13:16:50-04:00","description":"Update item adamant_arrow","file_path":"data/items/ammo/adamant_arrow.yaml","old_content":"color: \"78\"\ncraft:\n - end_message: \"\"\n fail: \"\"\n ingredients:\n - items:\n - headless_arrow\n quantity: 15\n - items:\n - adamant_arrowtips\n quantity: 15\n level: 60\n output_qty: 15\n start_message: \"\"\n station: []\n subtype: \"\"\n success_message: \"\"\n ticks_per_cycle: 2\n tool: \"\"\n type: fletching\n xp: 10\ndescription: An adamant-tipped arrow.2\nequipment:\n other:\n ranged: 31\n slot: ammo\n type: ammo\nid: adamant_arrow\nmax_quality: 0\nname: adamant arrow\nquality: 0\nrecoverable: true\nstackable: true\nvalue: 20\n","new_content":"color: \"78\"\ncraft:\n - end_message: \"\"\n fail: \"\"\n ingredients:\n - items:\n - headless_arrow\n quantity: 15\n - items:\n - adamant_arrowtips\n quantity: 15\n level: 60\n output_qty: 15\n start_message: \"\"\n station: []\n subtype: \"\"\n success_message: \"\"\n ticks_per_cycle: 2\n tool: \"\"\n type: fletching\n xp: 10\ndescription: An adamant-tipped arrow.\nequipment:\n other:\n ranged: 31\n slot: ammo\n type: ammo\nid: adamant_arrow\nmax_quality: 0\nname: adamant arrow\nquality: 0\nrecoverable: true\nstackable: true\nvalue: 20\n","is_delete":false,"is_create":false},{"time":"2026-07-01T15:41:47-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n messages:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n messages: ['\"Hi there, how can I help?\"']\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n thanks:\n messages: ['\"Thank for flying with Denali. Watch your step on the way out please.\"']\n options:\n - goto: Test\n text: '\"Thank you.\"'\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\n - condition:\n min_credits: 500000\n goto: \"\"\n text: 500000!!\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T15:41:55-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\n - condition:\n min_credits: 500000\n goto: \"\"\n text: 500000!!\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\n - condition:\n min_credits: 500000\n goto: \"\"\n text: 500000!!\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T15:42:56-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - aliases: []\n description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\n - id: flight_attendant_copy\nname: Test Room\nobjects:\n - aliases: []\n description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T15:47:02-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\n - condition:\n min_credits: 500000\n goto: \"\"\n text: 500000!!\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\n - action:\n shop:\n items:\n - buy_price: 1\n item_id: bronze_pickaxe\n sell_price: 1\n message: SHOP SHOP\n goto: \"\"\n text: 500000!!\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T15:47:37-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\n - action:\n shop:\n items:\n - buy_price: 1\n item_id: bronze_pickaxe\n sell_price: 1\n message: SHOP SHOP\n goto: \"\"\n text: 500000!!\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\n - action:\n shop:\n items:\n - buy_price: 1\n item_id: bronze_pickaxe\n sell_price: 1\n message: SHOP SHOP\n goto: \"\"\n text: 500000!!\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T17:16:00-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\nshop:\n message: SHOP SHOP\n items:\n - item_id: bronze_pickaxe\n stock: 5\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\nshop:\n buy_percentage: 0\n buys_anything: false\n change_percentage: 0\n items:\n - item_id: bronze_pickaxe\n restock_ticks: 0\n stock: 5\n message: SHOP SHOP\n restock_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T17:16:36-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\nshop:\n buy_percentage: 0\n buys_anything: false\n change_percentage: 0\n items:\n - item_id: bronze_pickaxe\n restock_ticks: 0\n stock: 5\n message: SHOP SHOP\n restock_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\nshop:\n buy_percentage: 0\n buys_anything: true\n change_percentage: 0\n items:\n - item_id: bronze_pickaxe\n restock_ticks: 0\n stock: 5\n message: SHOP SHOP\n restock_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T18:04:00-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\nshop:\n message: SHOP SHOP\n items:\n - item_id: bronze_pickaxe\n stock: 5\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\nunique: false\n","new_content":"aggressive: false\nattack: 0\nbonuses:\n attack_bonus: 0\n attack_type: stab\n strength_bonus: 0\ndefense: 0\ndefenses:\n crush_defense: 0\n ranged_defense: 0\n science_defense: 0\n slash_defense: 0\n stab_defense: 0\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nhp: 0\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nranged: 0\nrespawn_ticks: 0\nscience: 0\nshop:\n buy_percentage: 0\n buys_anything: true\n change_percentage: 0\n items:\n - item_id: bronze_pickaxe\n restock_ticks: 0\n stock: 5\n message: SHOP SHOP\nspeed: 0\nstrength: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\nunique: false\n","is_delete":false,"is_create":false}],"redo":null} \ No newline at end of file
+{"history":[{"time":"2026-06-30T14:29:39-04:00","description":"delete room 1017 (cleaned 0 exits)","file_path":"data/rooms/intro/1017.yaml","old_content":"id: 1017\nname: New Room\ncolor: \"\"\ndescription:\n - text: A featureless room.\nexits: {}\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:29:40-04:00","description":"delete room 1018 (cleaned 0 exits)","file_path":"data/rooms/intro/1018.yaml","old_content":"id: 1018\nname: 'Room #1018'\ncolor: D0\ndescription: []\nexits: {}\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:29:40-04:00","description":"delete room 1019 (cleaned 0 exits)","file_path":"data/rooms/intro/1019.yaml","old_content":"id: 1019\nname: 'Room #1019'\ncolor: \"\"\ndescription: []\nexits: {}\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:29:41-04:00","description":"delete room 1020 (cleaned 0 exits)","file_path":"data/rooms/intro/1020.yaml","old_content":"id: 1020\nname: 'Room #1020'\ncolor: \"\"\ndescription: []\nexits: {}\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:30:45-04:00","description":"delete room 1013 (cleaned 1 exits)","file_path":"data/rooms/intro/1013.yaml","old_content":"id: 1013\nname: 'Room #1013'\ncolor: \"72\"\ndescription: []\nexits:\n west:\n room: 1007\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:30:49-04:00","description":"delete room 1009 (cleaned 0 exits)","file_path":"data/rooms/intro/1009.yaml","old_content":"id: 1009\nname: New Room\ncolor: \"27\"\ndescription:\n - text: A featureless room.\nexits:\n northwest:\n room: 8\n southwest:\n room: 1006\n west:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs:\n - id: man\n - id: man\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:30:51-04:00","description":"delete room 1007 (cleaned 1 exits)","file_path":"data/rooms/intro/1007.yaml","old_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n west:\n room: 2004\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:30:53-04:00","description":"delete room 1006 (cleaned 4 exits)","file_path":"data/rooms/intro/1006.yaml","old_content":"id: 1006\nname: New Room\ncolor: E2\ndescription:\n - text: A featureless room.\nexits:\n north:\n room: 1005\n northwest:\n room: 1008\n up:\n room: 1010\n west:\n room: 2003\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:30:59-04:00","description":"delete room 1010 (cleaned 1 exits)","file_path":"data/rooms/intro/1010.yaml","old_content":"id: 1010\nname: New Room\ncolor: \"\"\ndescription:\n - text: A featureless room.\nexits:\n north:\n room: 1011\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:31:00-04:00","description":"delete room 1011 (cleaned 0 exits)","file_path":"data/rooms/intro/1011.yaml","old_content":"id: 1011\nname: New Room\ncolor: \"\"\ndescription:\n - text: A featureless room.\nexits:\n east:\n room: 1012\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:31:01-04:00","description":"delete room 1012 (cleaned 0 exits)","file_path":"data/rooms/intro/1012.yaml","old_content":"id: 1012\nname: New Room\ncolor: \"\"\ndescription:\n - text: A featureless room.\nexits: {}\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:31:02-04:00","description":"delete room 1005 (cleaned 2 exits)","file_path":"data/rooms/intro/1005.yaml","old_content":"id: 1005\nname: New Room\ncolor: CC\ndescription:\n - text: A featureless room.\nexits:\n southwest:\n room: 2003\n west:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:31:03-04:00","description":"delete room 1008 (cleaned 1 exits)","file_path":"data/rooms/intro/1008.yaml","old_content":"id: 1008\nname: New Room\ncolor: A9\ndescription:\n - text: A featureless room.\nexits:\n north:\n room: 7\n south:\n room: 2003\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:29-04:00","description":"update room 2003 (add exit north to 1005)","file_path":"data/rooms/intro/2003.yaml","old_content":"id: 2003\nname: Test Room\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 2003\nname: Test Room\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 1005\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:29-04:00","description":"create room 1005","file_path":"data/rooms/intro/1005.yaml","old_content":"","new_content":"exits:\n south: 2003\nid: 1005\nname: 'Room #1005'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:30-04:00","description":"update room 1005 (add exit east to 1006)","file_path":"data/rooms/intro/1005.yaml","old_content":"exits:\n south: 2003\nid: 1005\nname: 'Room #1005'\n","new_content":"id: 1005\nname: 'Room #1005'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1006\n south:\n room: 2003\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:30-04:00","description":"create room 1006","file_path":"data/rooms/intro/1006.yaml","old_content":"","new_content":"exits:\n west: 1005\nid: 1006\nname: 'Room #1006'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:31-04:00","description":"update room 1006 (add exit south to 1007)","file_path":"data/rooms/intro/1006.yaml","old_content":"exits:\n west: 1005\nid: 1006\nname: 'Room #1006'\n","new_content":"id: 1006\nname: 'Room #1006'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1007\n west:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:31-04:00","description":"create room 1007","file_path":"data/rooms/intro/1007.yaml","old_content":"","new_content":"exits:\n north: 1006\nid: 1007\nname: 'Room #1007'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:32-04:00","description":"update room 1007 (add exit east to 1008)","file_path":"data/rooms/intro/1007.yaml","old_content":"exits:\n north: 1006\nid: 1007\nname: 'Room #1007'\n","new_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1008\n north:\n room: 1006\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:32-04:00","description":"create room 1008","file_path":"data/rooms/intro/1008.yaml","old_content":"","new_content":"exits:\n west: 1007\nid: 1008\nname: 'Room #1008'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:32-04:00","description":"update room 1008 (add exit north to 1009)","file_path":"data/rooms/intro/1008.yaml","old_content":"exits:\n west: 1007\nid: 1008\nname: 'Room #1008'\n","new_content":"id: 1008\nname: 'Room #1008'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1009\n west:\n room: 1007\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:32-04:00","description":"create room 1009","file_path":"data/rooms/intro/1009.yaml","old_content":"","new_content":"exits:\n south: 1008\nid: 1009\nname: 'Room #1009'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:33-04:00","description":"update room 1009 (add exit north to 1010)","file_path":"data/rooms/intro/1009.yaml","old_content":"exits:\n south: 1008\nid: 1009\nname: 'Room #1009'\n","new_content":"id: 1009\nname: 'Room #1009'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1010\n south:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:33-04:00","description":"create room 1010","file_path":"data/rooms/intro/1010.yaml","old_content":"","new_content":"exits:\n south: 1009\nid: 1010\nname: 'Room #1010'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:33-04:00","description":"update room 1010 (add exit east to 1011)","file_path":"data/rooms/intro/1010.yaml","old_content":"exits:\n south: 1009\nid: 1010\nname: 'Room #1010'\n","new_content":"id: 1010\nname: 'Room #1010'\ncolor: \"\"\ndescription: []\nexits:\n east:\n room: 1011\n south:\n room: 1009\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:33-04:00","description":"create room 1011","file_path":"data/rooms/intro/1011.yaml","old_content":"","new_content":"exits:\n west: 1010\nid: 1011\nname: 'Room #1011'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:34-04:00","description":"update room 1011 (add exit south to 1012)","file_path":"data/rooms/intro/1011.yaml","old_content":"exits:\n west: 1010\nid: 1011\nname: 'Room #1011'\n","new_content":"id: 1011\nname: 'Room #1011'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1012\n west:\n room: 1010\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:34-04:00","description":"create room 1012","file_path":"data/rooms/intro/1012.yaml","old_content":"","new_content":"exits:\n north: 1011\nid: 1012\nname: 'Room #1012'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:34-04:00","description":"update room 1012 (add exit south to 1013)","file_path":"data/rooms/intro/1012.yaml","old_content":"exits:\n north: 1011\nid: 1012\nname: 'Room #1012'\n","new_content":"id: 1012\nname: 'Room #1012'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1011\n south:\n room: 1013\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T14:32:34-04:00","description":"create room 1013","file_path":"data/rooms/intro/1013.yaml","old_content":"","new_content":"exits:\n north: 1012\nid: 1013\nname: 'Room #1013'\n","is_delete":false,"is_create":true},{"time":"2026-06-30T14:32:35-04:00","description":"delete room 1013 (cleaned 1 exits)","file_path":"data/rooms/intro/1013.yaml","old_content":"exits:\n north: 1012\nid: 1013\nname: 'Room #1013'\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:36-04:00","description":"delete room 1012 (cleaned 1 exits)","file_path":"data/rooms/intro/1012.yaml","old_content":"id: 1012\nname: 'Room #1012'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1011\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:37-04:00","description":"delete room 1011 (cleaned 1 exits)","file_path":"data/rooms/intro/1011.yaml","old_content":"id: 1011\nname: 'Room #1011'\ncolor: \"\"\ndescription: []\nexits:\n west:\n room: 1010\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:37-04:00","description":"delete room 1010 (cleaned 1 exits)","file_path":"data/rooms/intro/1010.yaml","old_content":"id: 1010\nname: 'Room #1010'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1009\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:38-04:00","description":"delete room 1009 (cleaned 1 exits)","file_path":"data/rooms/intro/1009.yaml","old_content":"id: 1009\nname: 'Room #1009'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 1008\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:39-04:00","description":"delete room 1008 (cleaned 1 exits)","file_path":"data/rooms/intro/1008.yaml","old_content":"id: 1008\nname: 'Room #1008'\ncolor: \"\"\ndescription: []\nexits:\n west:\n room: 1007\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:40-04:00","description":"delete room 1007 (cleaned 1 exits)","file_path":"data/rooms/intro/1007.yaml","old_content":"id: 1007\nname: 'Room #1007'\ncolor: \"\"\ndescription: []\nexits:\n north:\n room: 1006\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:40-04:00","description":"delete room 1006 (cleaned 1 exits)","file_path":"data/rooms/intro/1006.yaml","old_content":"id: 1006\nname: 'Room #1006'\ncolor: \"\"\ndescription: []\nexits:\n west:\n room: 1005\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T14:32:41-04:00","description":"delete room 1005 (cleaned 1 exits)","file_path":"data/rooms/intro/1005.yaml","old_content":"id: 1005\nname: 'Room #1005'\ncolor: \"\"\ndescription: []\nexits:\n south:\n room: 2003\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"","is_delete":true,"is_create":false},{"time":"2026-06-30T15:05:42-04:00","description":"update room 1001","file_path":"data/rooms/intro/1001.yaml","old_content":"id: 1001\nname: Inside Transport Shuttle\ncolor: \"\"\ndescription:\n - text: |-\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large framed sign hangs next to the closed cockpit door. The piston-powered staircase is firmly closed at the rear of the craft.\n\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large {11}framed sign{/} hangs next to the closed cockpit door. A piston-powered staircase leads down out the back of the small craft with a smiling attendant ready to help disembark.\nexits:\n down:\n room: 1002\n condition:\n flag: \"\"\n value: null\n not: false\n player_flag: 1001_touchdown\n has_item: \"\"\n min_credits: 0\n all_of: []\n any_of: []\n blocked_message: The piston-powered staircase is firmly closed.\n east:\n room: 2001\nobjects:\n - name: framed sign\n hidden: true\n description:\n - text: \"We hope you enjoy your trip on our shuttle! Your pilot is [TYLER].\\n\\nWhen you arrive at your final destination, please be aware of the following basic commands:\\n\\n{0B bold}Movement:{/} {0A}north{/}, {0A}south{/}, {0A}east{/}, {0A}west{/}, {0A}up{/}, {0A}down{/}\\n{0B bold}Look:{/} {0A}look{/}, {0A}look \u003citem/object/mob\u003e{/}, and {0A}map{/}\\n{0B bold}Items:{/} {0A}inv{/} to see your 28-slot inventory\\n {0A}get \u003citem\u003e{/}, {0A}drop \u003citem\u003e{/}, {0A}wear \u003citem\u003e{/}, {0A}remove \u003citem\u003e{/}\\n {0A}use \u003citem\u003e on \u003citem/object\u003e{/}\\n {0A}eq{/} for equiped gear\\n{0B bold}Comms:{/} {0A}talk \u003cmob\u003e{/} for NPC chat\\n {0A}say \u003cmsg\u003e{/} and {0A}global \u003cmsg\u003e{/} for human chat\\n{0B bold}Character:{/} {0A}score{/} and {0A}skills{/} for stats. \\n{0B bold}Combat{/} {0A}attack \u003cmob\u003e{/}\\n{0B bold}Skills{/} Many skills have shortcuts like {0A}mine{/}, {0A}fish{/}, or {0A}chop{/}\\n{0B bold}Options{/} {0A}options{/} for a list of account options\\n {0A}options \u003copt\u003e \u003cvalue\u003e{/} to change an option\\n\\nType {0C bold}what{/} for a list of possible common actions\\n\\nMake sure to check the {0A}help{/} pages, especially {0A}help newplayer{/}!\"\n on_look:\n set_flags: {}\n set_player_flags:\n 1001_look_sign: true\n give_item: \"\"\n take_item: \"\"\n teleport: 0\n heal: 0\n cost: 0\n shop: null\n assign_task: false\n skip_task: false\n extend_task: false\n reputation_cost: 0\n sawmill: false\n aps_node: false\n - name: door\n hidden: true\n description:\n - text: A sturdy, locked steel door that keeps passengers out of the cockpit. There is a tiny, thin window at eye level.\n - name: window\n hidden: true\n description:\n - text: A thick trim with rounded bolt heads frames the tiny window. It looks like it was cut into the door at some point, potentially as a simple replacement to computerized security systems. Inside the cockpit there's a pilot finishing up landing procedures on a large panel of analog instruments.\n - name: instrument panel\n aliases:\n - cockpit\n hidden: true\n description:\n - text: The cramped cockpit is surrounded by buttons, swiches, dials, and analog gauges. The parts are a mix of technologies from the last century. Part of the panel is obscured by a draped cloth as if to hide it from view. Odd.\n - name: pilot\n hidden: true\n description:\n - text: That's the guy who took you from the Passenger Barge Denali down here to Vesta. A middle-aged man in a neat white jumpsuit with a matching white sort of conductor's hat. He's following a written procedure checklist and seems to take his job seriously.\nitem_spawns: []\nmobs:\n - id: flight_attendant\non_enter:\n - message: '{0B bold}Welcome to The House of Icarus{/}'\n condition:\n flag: \"\"\n value: null\n not: true\n player_flag: 1001_welcome\n has_item: \"\"\n min_credits: 0\n all_of: []\n any_of: []\n delay: 5\n set_flags: {}\n set_player_flags: {}\n broadcast: \"\"\n broadcast_global: \"\"\n spawn_mob: null\n despawn_mob: \"\"\n give_item: \"\"\n take_item: \"\"\n teleport: 0\n heal: 0\n - message: '{0B}Type{/} {0A}look sign{/} {0B}or{/} {0A}talk attendant{/} {0B}to get started{/}'\n condition:\n flag: \"\"\n value: null\n not: true\n player_flag: 1001_welcome\n has_item: \"\"\n min_credits: 0\n all_of: []\n any_of: []\n delay: 7\n set_flags: {}\n set_player_flags:\n 1001_welcome: true\n broadcast: \"\"\n broadcast_global: \"\"\n spawn_mob: null\n despawn_mob: \"\"\n give_item: \"\"\n take_item: \"\"\n teleport: 0\n heal: 0\n - message: '{0B}Type{/} {0A}help newplayer{/} {0B}for the new player''s guide. That''s it. Explore and have fun.{/}'\n condition:\n flag: \"\"\n value: null\n not: true\n player_flag: 1001_welcome\n has_item: \"\"\n min_credits: 0\n all_of: []\n any_of: []\n delay: 7\n set_flags: {}\n set_player_flags: {}\n broadcast: \"\"\n broadcast_global: \"\"\n spawn_mob: null\n despawn_mob: \"\"\n give_item: \"\"\n take_item: \"\"\n teleport: 0\n heal: 0\nhazard: \"\"\nblock_transport: true\ntriggers:\n - id: \"\"\n on_player_flag: 1001_look_sign\n on_flag: \"\"\n value: null\n room: 0\n steps:\n - delay: 5\n message: The cabin shakes as the small craft touches down\n broadcast: \"\"\n broadcast_global: \"\"\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n give_item: \"\"\n take_item: \"\"\n teleport: 0\n heal: 0\n despawn_mob: \"\"\n - delay: 5\n message: The pistons hiss as the rear staircase opens\n broadcast: \"\"\n broadcast_global: \"\"\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n give_item: \"\"\n take_item: \"\"\n teleport: 0\n heal: 0\n despawn_mob: \"\"\n - delay: 0\n message: \"\"\n broadcast: \"\"\n broadcast_global: \"\"\n set_flags: {}\n set_player_flags:\n 1001_touchdown: true\n spawn_mob: null\n give_item: \"\"\n take_item: \"\"\n teleport: 0\n heal: 0\n despawn_mob: \"\"\n","new_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: |-\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large framed sign hangs next to the closed cockpit door. The piston-powered staircase is firmly closed at the rear of the craft.\n\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large {11}framed sign{/} hangs next to the closed cockpit door. A piston-powered staircase leads down out the back of the small craft with a smiling attendant ready to help disembark.\nexits:\n down:\n blocked_message: The piston-powered staircase is firmly closed.\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: false\n player_flag: 1001_touchdown\n value: null\n room: 1002\n east:\n room: 2001\nhazard: \"\"\nid: 1001\nitem_spawns: []\nmobs:\n - id: flight_attendant\nname: Inside Transport Shuttle\nobjects:\n - description:\n - text: \"We hope you enjoy your trip on our shuttle! Your pilot is [TYLER].\\n\\nWhen you arrive at your final destination, please be aware of the following basic commands:\\n\\n{0B bold}Movement:{/} {0A}north{/}, {0A}south{/}, {0A}east{/}, {0A}west{/}, {0A}up{/}, {0A}down{/}\\n{0B bold}Look:{/} {0A}look{/}, {0A}look \u003citem/object/mob\u003e{/}, and {0A}map{/}\\n{0B bold}Items:{/} {0A}inv{/} to see your 28-slot inventory\\n {0A}get \u003citem\u003e{/}, {0A}drop \u003citem\u003e{/}, {0A}wear \u003citem\u003e{/}, {0A}remove \u003citem\u003e{/}\\n {0A}use \u003citem\u003e on \u003citem/object\u003e{/}\\n {0A}eq{/} for equiped gear\\n{0B bold}Comms:{/} {0A}talk \u003cmob\u003e{/} for NPC chat\\n {0A}say \u003cmsg\u003e{/} and {0A}global \u003cmsg\u003e{/} for human chat\\n{0B bold}Character:{/} {0A}score{/} and {0A}skills{/} for stats. \\n{0B bold}Combat{/} {0A}attack \u003cmob\u003e{/}\\n{0B bold}Skills{/} Many skills have shortcuts like {0A}mine{/}, {0A}fish{/}, or {0A}chop{/}\\n{0B bold}Options{/} {0A}options{/} for a list of account options\\n {0A}options \u003copt\u003e \u003cvalue\u003e{/} to change an option\\n\\nType {0C bold}what{/} for a list of possible common actions\\n\\nMake sure to check the {0A}help{/} pages, especially {0A}help newplayer{/}!\"\n hidden: true\n name: framed sign\n on_look:\n aps_node: false\n assign_task: false\n cost: 0\n extend_task: false\n give_item: \"\"\n heal: 0\n reputation_cost: 0\n sawmill: false\n set_flags: {}\n set_player_flags:\n 1001_look_sign: true\n shop: null\n skip_task: false\n take_item: \"\"\n teleport: 0\n - description:\n - text: A sturdy, locked steel door that keeps passengers out of the cockpit. There is a tiny, thin window at eye level.\n hidden: true\n name: door\n - description:\n - text: A thick trim with rounded bolt heads frames the tiny window. It looks like it was cut into the door at some point, potentially as a simple replacement to computerized security systems. Inside the cockpit there's a pilot finishing up landing procedures on a large panel of analog instruments.\n hidden: true\n name: window\n - aliases:\n - cockpit\n description:\n - text: The cramped cockpit is surrounded by buttons, swiches, dials, and analog gauges. The parts are a mix of technologies from the last century. Part of the panel is obscured by a draped cloth as if to hide it from view. Odd.\n hidden: true\n name: instrument panel\n - aliases: []\n description:\n - text: That's the guy who took you from the Passenger Barge Denali down here to Vesta. A middle-aged man in a neat white jumpsuit with a matching white sort of conductor's hat. He's following a written procedure checklist and seems to take his job seriously.\n hidden: false\n name: pilot\non_enter:\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B bold}Welcome to The House of Icarus{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}look sign{/} {0B}or{/} {0A}talk attendant{/} {0B}to get started{/}'\n set_flags: {}\n set_player_flags:\n 1001_welcome: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}help newplayer{/} {0B}for the new player''s guide. That''s it. Explore and have fun.{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\ntriggers:\n - id: \"\"\n on_flag: \"\"\n on_player_flag: 1001_look_sign\n room: 0\n steps:\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The cabin shakes as the small craft touches down\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The pistons hiss as the rear staircase opens\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 0\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: \"\"\n set_flags: {}\n set_player_flags:\n 1001_touchdown: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n value: null\n","is_delete":false,"is_create":false},{"time":"2026-06-30T15:05:43-04:00","description":"update room 1001","file_path":"data/rooms/intro/1001.yaml","old_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: |-\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large framed sign hangs next to the closed cockpit door. The piston-powered staircase is firmly closed at the rear of the craft.\n\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large {11}framed sign{/} hangs next to the closed cockpit door. A piston-powered staircase leads down out the back of the small craft with a smiling attendant ready to help disembark.\nexits:\n down:\n blocked_message: The piston-powered staircase is firmly closed.\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: false\n player_flag: 1001_touchdown\n value: null\n room: 1002\n east:\n room: 2001\nhazard: \"\"\nid: 1001\nitem_spawns: []\nmobs:\n - id: flight_attendant\nname: Inside Transport Shuttle\nobjects:\n - description:\n - text: \"We hope you enjoy your trip on our shuttle! Your pilot is [TYLER].\\n\\nWhen you arrive at your final destination, please be aware of the following basic commands:\\n\\n{0B bold}Movement:{/} {0A}north{/}, {0A}south{/}, {0A}east{/}, {0A}west{/}, {0A}up{/}, {0A}down{/}\\n{0B bold}Look:{/} {0A}look{/}, {0A}look \u003citem/object/mob\u003e{/}, and {0A}map{/}\\n{0B bold}Items:{/} {0A}inv{/} to see your 28-slot inventory\\n {0A}get \u003citem\u003e{/}, {0A}drop \u003citem\u003e{/}, {0A}wear \u003citem\u003e{/}, {0A}remove \u003citem\u003e{/}\\n {0A}use \u003citem\u003e on \u003citem/object\u003e{/}\\n {0A}eq{/} for equiped gear\\n{0B bold}Comms:{/} {0A}talk \u003cmob\u003e{/} for NPC chat\\n {0A}say \u003cmsg\u003e{/} and {0A}global \u003cmsg\u003e{/} for human chat\\n{0B bold}Character:{/} {0A}score{/} and {0A}skills{/} for stats. \\n{0B bold}Combat{/} {0A}attack \u003cmob\u003e{/}\\n{0B bold}Skills{/} Many skills have shortcuts like {0A}mine{/}, {0A}fish{/}, or {0A}chop{/}\\n{0B bold}Options{/} {0A}options{/} for a list of account options\\n {0A}options \u003copt\u003e \u003cvalue\u003e{/} to change an option\\n\\nType {0C bold}what{/} for a list of possible common actions\\n\\nMake sure to check the {0A}help{/} pages, especially {0A}help newplayer{/}!\"\n hidden: true\n name: framed sign\n on_look:\n aps_node: false\n assign_task: false\n cost: 0\n extend_task: false\n give_item: \"\"\n heal: 0\n reputation_cost: 0\n sawmill: false\n set_flags: {}\n set_player_flags:\n 1001_look_sign: true\n shop: null\n skip_task: false\n take_item: \"\"\n teleport: 0\n - description:\n - text: A sturdy, locked steel door that keeps passengers out of the cockpit. There is a tiny, thin window at eye level.\n hidden: true\n name: door\n - description:\n - text: A thick trim with rounded bolt heads frames the tiny window. It looks like it was cut into the door at some point, potentially as a simple replacement to computerized security systems. Inside the cockpit there's a pilot finishing up landing procedures on a large panel of analog instruments.\n hidden: true\n name: window\n - aliases:\n - cockpit\n description:\n - text: The cramped cockpit is surrounded by buttons, swiches, dials, and analog gauges. The parts are a mix of technologies from the last century. Part of the panel is obscured by a draped cloth as if to hide it from view. Odd.\n hidden: true\n name: instrument panel\n - aliases: []\n description:\n - text: That's the guy who took you from the Passenger Barge Denali down here to Vesta. A middle-aged man in a neat white jumpsuit with a matching white sort of conductor's hat. He's following a written procedure checklist and seems to take his job seriously.\n hidden: false\n name: pilot\non_enter:\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B bold}Welcome to The House of Icarus{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}look sign{/} {0B}or{/} {0A}talk attendant{/} {0B}to get started{/}'\n set_flags: {}\n set_player_flags:\n 1001_welcome: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}help newplayer{/} {0B}for the new player''s guide. That''s it. Explore and have fun.{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\ntriggers:\n - id: \"\"\n on_flag: \"\"\n on_player_flag: 1001_look_sign\n room: 0\n steps:\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The cabin shakes as the small craft touches down\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The pistons hiss as the rear staircase opens\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 0\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: \"\"\n set_flags: {}\n set_player_flags:\n 1001_touchdown: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n value: null\n","new_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: |-\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large framed sign hangs next to the closed cockpit door. The piston-powered staircase is firmly closed at the rear of the craft.\n\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large {11}framed sign{/} hangs next to the closed cockpit door. A piston-powered staircase leads down out the back of the small craft with a smiling attendant ready to help disembark.\nexits:\n down:\n blocked_message: The piston-powered staircase is firmly closed.\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: false\n player_flag: 1001_touchdown\n value: null\n room: 1002\n east:\n room: 2001\nhazard: \"\"\nid: 1001\nitem_spawns: []\nmobs:\n - id: flight_attendant\nname: Inside Transport Shuttle\nobjects:\n - description:\n - text: \"We hope you enjoy your trip on our shuttle! Your pilot is [TYLER].\\n\\nWhen you arrive at your final destination, please be aware of the following basic commands:\\n\\n{0B bold}Movement:{/} {0A}north{/}, {0A}south{/}, {0A}east{/}, {0A}west{/}, {0A}up{/}, {0A}down{/}\\n{0B bold}Look:{/} {0A}look{/}, {0A}look \u003citem/object/mob\u003e{/}, and {0A}map{/}\\n{0B bold}Items:{/} {0A}inv{/} to see your 28-slot inventory\\n {0A}get \u003citem\u003e{/}, {0A}drop \u003citem\u003e{/}, {0A}wear \u003citem\u003e{/}, {0A}remove \u003citem\u003e{/}\\n {0A}use \u003citem\u003e on \u003citem/object\u003e{/}\\n {0A}eq{/} for equiped gear\\n{0B bold}Comms:{/} {0A}talk \u003cmob\u003e{/} for NPC chat\\n {0A}say \u003cmsg\u003e{/} and {0A}global \u003cmsg\u003e{/} for human chat\\n{0B bold}Character:{/} {0A}score{/} and {0A}skills{/} for stats. \\n{0B bold}Combat{/} {0A}attack \u003cmob\u003e{/}\\n{0B bold}Skills{/} Many skills have shortcuts like {0A}mine{/}, {0A}fish{/}, or {0A}chop{/}\\n{0B bold}Options{/} {0A}options{/} for a list of account options\\n {0A}options \u003copt\u003e \u003cvalue\u003e{/} to change an option\\n\\nType {0C bold}what{/} for a list of possible common actions\\n\\nMake sure to check the {0A}help{/} pages, especially {0A}help newplayer{/}!\"\n hidden: true\n name: framed sign\n on_look:\n aps_node: false\n assign_task: false\n cost: 0\n extend_task: false\n give_item: \"\"\n heal: 0\n reputation_cost: 0\n sawmill: false\n set_flags: {}\n set_player_flags:\n 1001_look_sign: true\n shop: null\n skip_task: false\n take_item: \"\"\n teleport: 0\n - description:\n - text: A sturdy, locked steel door that keeps passengers out of the cockpit. There is a tiny, thin window at eye level.\n hidden: true\n name: door\n - description:\n - text: A thick trim with rounded bolt heads frames the tiny window. It looks like it was cut into the door at some point, potentially as a simple replacement to computerized security systems. Inside the cockpit there's a pilot finishing up landing procedures on a large panel of analog instruments.\n hidden: true\n name: window\n - aliases:\n - cockpit\n description:\n - text: The cramped cockpit is surrounded by buttons, swiches, dials, and analog gauges. The parts are a mix of technologies from the last century. Part of the panel is obscured by a draped cloth as if to hide it from view. Odd.\n hidden: true\n name: instrument panel\n - aliases: []\n description:\n - text: That's the guy who took you from the Passenger Barge Denali down here to Vesta. A middle-aged man in a neat white jumpsuit with a matching white sort of conductor's hat. He's following a written procedure checklist and seems to take his job seriously.\n hidden: true\n name: pilot\non_enter:\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B bold}Welcome to The House of Icarus{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}look sign{/} {0B}or{/} {0A}talk attendant{/} {0B}to get started{/}'\n set_flags: {}\n set_player_flags:\n 1001_welcome: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}help newplayer{/} {0B}for the new player''s guide. That''s it. Explore and have fun.{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\ntriggers:\n - id: \"\"\n on_flag: \"\"\n on_player_flag: 1001_look_sign\n room: 0\n steps:\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The cabin shakes as the small craft touches down\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The pistons hiss as the rear staircase opens\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 0\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: \"\"\n set_flags: {}\n set_player_flags:\n 1001_touchdown: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n value: null\n","is_delete":false,"is_create":false},{"time":"2026-06-30T16:34:21-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T16:35:02-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T16:35:15-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T17:43:28-04:00","description":"Update object copper_rock","file_path":"data/objects/copper_rock.yaml","old_content":"color: \"B2\"\ngather:\n depleted_message: You don't see any ore in this rock.\n drops:\n - depletes: true\n item_id: copper_ore\n level: 1\n message: You manage to mine some {B2}copper ore{/}.\n weight: 90\n xp: 17\n - depletes: false\n message: You spot a glint of something valuable!\n table: gem_table\n weight: 10\n fail_message: You chip away but get nothing useful.\n gather_message: You swing your pickaxe at the rock...\n respawn_broadcast: A glint of copper catches your eye from some {name}.\n respawn_timer: 50\n skill: mining\n success:\n base: 0.5\n cap: 0.95\n per_level: 0.01\n tools:\n - pickaxe\nname: copper rock\n","new_content":"aliases: []\ncolor: B2\ndescription: \"\"\ngather:\n bait: \"\"\n deplete_timer: 0\n depleted_message: You don't see any ore in this rock.\n drops:\n - depletes: true\n item_id: copper_ore\n level: 1\n message: You manage to mine some {B2}copper ore{/}.\n quantity: 0\n table: \"\"\n weight: 90\n xp: 17\n - depletes: false\n item_id: \"\"\n level: 0\n message: You spot a glint of something valuable!\n quantity: 0\n table: gem_table\n weight: 10\n xp: 0\n exhausted_message: \"\"\n fail_message: You chip away but get nothing useful.\n gather_message: You swing your pickaxe at the rock...\n nest_chance: 0\n respawn_broadcast: A glint of copper catches your eye from some {name}.\n respawn_timer: 50\n skill: mining\n success:\n base: 0.5\n cap: 0.95\n per_level: 0.01\n tools:\n - pickaxe\nhidden: false\nid: copper_rock\ninroom_description: \"\"\nname: copper rock\nremoval_item: \"\"\n","is_delete":false,"is_create":false},{"time":"2026-06-30T23:48:18-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T23:48:23-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 0\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-06-30T23:53:08-04:00","description":"Update item bread_dough","file_path":"data/items/consumables/bread_dough.yaml","old_content":"color: \"DE\"\ncraft:\n type: combine\n consume:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n wait: 2\ndescription: A ball of uncooked bread dough. It needs to be baked.\nname: bread dough\nstackable: false\nvalue: 3\n","new_content":"color: DE\ncraft:\n - consume:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n end_message: testend\n fail: \"\"\n level: 0\n message: testmsg\n output_qty: 0\n start_message: teststart\n station: []\n subtype: \"\"\n tool: \"\"\n type: combine\n wait: 2\n xp: 0\ndescription: A ball of uncooked bread dough. It needs to be baked.\nid: bread_dough\nmax_quality: 0\nname: bread dough\nquality: 0\nstackable: false\nvalue: 3\n","is_delete":false,"is_create":false},{"time":"2026-07-01T00:23:04-04:00","description":"Update item bread_dough","file_path":"data/items/consumables/bread_dough.yaml","old_content":"color: DE\ncraft:\n - consume:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n end_message: testend\n fail: \"\"\n level: 0\n message: testmsg\n output_qty: 0\n start_message: teststart\n station: []\n subtype: \"\"\n tool: \"\"\n type: combine\n wait: 2\n xp: 0\ndescription: A ball of uncooked bread dough. It needs to be baked.\nid: bread_dough\nmax_quality: 0\nname: bread dough\nquality: 0\nstackable: false\nvalue: 3\n","new_content":"color: DE\ncraft:\n - consume:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n end_message: testend\n fail: \"\"\n level: 0\n message: testmsg\n output_qty: 0\n start_message: teststart\n station: []\n subtype: \"\"\n tool: \"\"\n type: combine\n wait: 2\n xp: 0\ndescription: A ball of uncooked bread dough. It needs to be baked.\nid: bread_dough\nmax_quality: 0\nname: bread dough\nquality: 0\nstackable: false\nvalue: 3\n","is_delete":false,"is_create":false},{"time":"2026-07-01T01:22:55-04:00","description":"update room 1001","file_path":"data/rooms/intro/1001.yaml","old_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: |-\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large framed sign hangs next to the closed cockpit door. The piston-powered staircase is firmly closed at the rear of the craft.\n\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large {11}framed sign{/} hangs next to the closed cockpit door. A piston-powered staircase leads down out the back of the small craft with a smiling attendant ready to help disembark.\nexits:\n down:\n blocked_message: The piston-powered staircase is firmly closed.\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: false\n player_flag: 1001_touchdown\n value: null\n room: 1002\n east:\n room: 2001\nhazard: \"\"\nid: 1001\nitem_spawns: []\nmobs:\n - id: flight_attendant\nname: Inside Transport Shuttle\nobjects:\n - description:\n - text: \"We hope you enjoy your trip on our shuttle! Your pilot is [TYLER].\\n\\nWhen you arrive at your final destination, please be aware of the following basic commands:\\n\\n{0B bold}Movement:{/} {0A}north{/}, {0A}south{/}, {0A}east{/}, {0A}west{/}, {0A}up{/}, {0A}down{/}\\n{0B bold}Look:{/} {0A}look{/}, {0A}look \u003citem/object/mob\u003e{/}, and {0A}map{/}\\n{0B bold}Items:{/} {0A}inv{/} to see your 28-slot inventory\\n {0A}get \u003citem\u003e{/}, {0A}drop \u003citem\u003e{/}, {0A}wear \u003citem\u003e{/}, {0A}remove \u003citem\u003e{/}\\n {0A}use \u003citem\u003e on \u003citem/object\u003e{/}\\n {0A}eq{/} for equiped gear\\n{0B bold}Comms:{/} {0A}talk \u003cmob\u003e{/} for NPC chat\\n {0A}say \u003cmsg\u003e{/} and {0A}global \u003cmsg\u003e{/} for human chat\\n{0B bold}Character:{/} {0A}score{/} and {0A}skills{/} for stats. \\n{0B bold}Combat{/} {0A}attack \u003cmob\u003e{/}\\n{0B bold}Skills{/} Many skills have shortcuts like {0A}mine{/}, {0A}fish{/}, or {0A}chop{/}\\n{0B bold}Options{/} {0A}options{/} for a list of account options\\n {0A}options \u003copt\u003e \u003cvalue\u003e{/} to change an option\\n\\nType {0C bold}what{/} for a list of possible common actions\\n\\nMake sure to check the {0A}help{/} pages, especially {0A}help newplayer{/}!\"\n hidden: true\n name: framed sign\n on_look:\n aps_node: false\n assign_task: false\n cost: 0\n extend_task: false\n give_item: \"\"\n heal: 0\n reputation_cost: 0\n sawmill: false\n set_flags: {}\n set_player_flags:\n 1001_look_sign: true\n shop: null\n skip_task: false\n take_item: \"\"\n teleport: 0\n - description:\n - text: A sturdy, locked steel door that keeps passengers out of the cockpit. There is a tiny, thin window at eye level.\n hidden: true\n name: door\n - description:\n - text: A thick trim with rounded bolt heads frames the tiny window. It looks like it was cut into the door at some point, potentially as a simple replacement to computerized security systems. Inside the cockpit there's a pilot finishing up landing procedures on a large panel of analog instruments.\n hidden: true\n name: window\n - aliases:\n - cockpit\n description:\n - text: The cramped cockpit is surrounded by buttons, swiches, dials, and analog gauges. The parts are a mix of technologies from the last century. Part of the panel is obscured by a draped cloth as if to hide it from view. Odd.\n hidden: true\n name: instrument panel\n - aliases: []\n description:\n - text: That's the guy who took you from the Passenger Barge Denali down here to Vesta. A middle-aged man in a neat white jumpsuit with a matching white sort of conductor's hat. He's following a written procedure checklist and seems to take his job seriously.\n hidden: true\n name: pilot\non_enter:\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B bold}Welcome to The House of Icarus{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}look sign{/} {0B}or{/} {0A}talk attendant{/} {0B}to get started{/}'\n set_flags: {}\n set_player_flags:\n 1001_welcome: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}help newplayer{/} {0B}for the new player''s guide. That''s it. Explore and have fun.{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\ntriggers:\n - id: \"\"\n on_flag: \"\"\n on_player_flag: 1001_look_sign\n room: 0\n steps:\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The cabin shakes as the small craft touches down\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The pistons hiss as the rear staircase opens\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 0\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: \"\"\n set_flags: {}\n set_player_flags:\n 1001_touchdown: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n value: null\n","new_content":"block_transport: true\ncolor: \"\"\ndescription:\n - text: |-\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large framed sign hangs next to the closed cockpit door. The piston-powered staircase is firmly closed at the rear of the craft.\n\n A dim, windowless shuttle interior with a few uncomfortable rows of steel seats facing forward. A large {11}framed sign{/} hangs next to the closed cockpit door. A piston-powered staircase leads down out the back of the small craft with a smiling attendant ready to help disembark.\nexits:\n down:\n blocked_message: The piston-powered staircase is firmly closed.\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: false\n player_flag: 1001_touchdown\n value: null\n room: 1002\n east:\n room: 2001\nhazard: \"\"\nid: 1001\nitem_spawns: []\nmobs:\n - id: flight_attendant\nname: Inside Transport Shuttle\nobjects:\n - description:\n - text: \"We hope you enjoy your trip on our shuttle! Your pilot is [TYLER].\\n\\nWhen you arrive at your final destination, please be aware of the following basic commands:\\n\\n{0B bold}Movement:{/} {0A}north{/}, {0A}south{/}, {0A}east{/}, {0A}west{/}, {0A}up{/}, {0A}down{/}\\n{0B bold}Look:{/} {0A}look{/}, {0A}look \u003citem/object/mob\u003e{/}, and {0A}map{/}\\n{0B bold}Items:{/} {0A}inv{/} to see your 28-slot inventory\\n {0A}get \u003citem\u003e{/}, {0A}drop \u003citem\u003e{/}, {0A}wear \u003citem\u003e{/}, {0A}remove \u003citem\u003e{/}\\n {0A}use \u003citem\u003e on \u003citem/object\u003e{/}\\n {0A}eq{/} for equiped gear\\n{0B bold}Comms:{/} {0A}talk \u003cmob\u003e{/} for NPC chat\\n {0A}say \u003cmsg\u003e{/} and {0A}global \u003cmsg\u003e{/} for human chat\\n{0B bold}Character:{/} {0A}score{/} and {0A}skills{/} for stats. \\n{0B bold}Combat{/} {0A}attack \u003cmob\u003e{/}\\n{0B bold}Skills{/} Many skills have shortcuts like {0A}mine{/}, {0A}fish{/}, or {0A}chop{/}\\n{0B bold}Options{/} {0A}options{/} for a list of account options\\n {0A}options \u003copt\u003e \u003cvalue\u003e{/} to change an option\\n\\nType {0C bold}what{/} for a list of possible common actions\\n\\nMake sure to check the {0A}help{/} pages, especially {0A}help newplayer{/}!\"\n hidden: true\n name: framed sign\n on_look:\n aps_node: false\n assign_task: false\n cost: 0\n extend_task: false\n give_item: \"\"\n heal: 0\n reputation_cost: 0\n sawmill: false\n set_flags: {}\n set_player_flags:\n 1001_look_sign: true\n shop: null\n skip_task: false\n take_item: \"\"\n teleport: 0\n - description:\n - text: A sturdy, locked steel door that keeps passengers out of the cockpit. There is a tiny, thin window at eye level.\n hidden: true\n name: door\n - description:\n - text: A thick trim with rounded bolt heads frames the tiny window. It looks like it was cut into the door at some point, potentially as a simple replacement to computerized security systems. Inside the cockpit there's a pilot finishing up landing procedures on a large panel of analog instruments.\n hidden: true\n name: window\n - aliases:\n - cockpit\n description:\n - text: The cramped cockpit is surrounded by buttons, swiches, dials, and analog gauges. The parts are a mix of technologies from the last century. Part of the panel is obscured by a draped cloth as if to hide it from view. Odd.\n hidden: true\n name: instrument panel\n - aliases: []\n description:\n - text: That's the guy who took you from the Passenger Barge Denali down here to Vesta. A middle-aged man in a neat white jumpsuit with a matching white sort of conductor's hat. He's following a written procedure checklist and seems to take his job seriously.\n hidden: true\n name: pilot\non_enter:\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B bold}Welcome to The House of Icarus{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}look sign{/} {0B}or{/} {0A}talk attendant{/} {0B}to get started{/}'\n set_flags: {}\n set_player_flags:\n 1001_welcome: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n condition:\n all_of: []\n any_of: []\n flag: \"\"\n has_item: \"\"\n min_credits: 0\n not: true\n player_flag: 1001_welcome\n value: null\n delay: 7\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: '{0B}Type{/} {0A}help newplayer{/} {0B}for the new player''s guide. That''s it. Explore and have fun.{/}'\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\ntriggers:\n - id: \"\"\n on_flag: \"\"\n on_player_flag: 1001_look_sign\n room: 0\n steps:\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The cabin shakes as the small craft touches down\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 5\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: The pistons hiss as the rear staircase opens\n set_flags: {}\n set_player_flags: {}\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n - broadcast: \"\"\n broadcast_global: \"\"\n delay: 0\n despawn_mob: \"\"\n give_item: \"\"\n heal: 0\n message: \"\"\n set_flags: {}\n set_player_flags:\n 1001_touchdown: true\n spawn_mob: null\n take_item: \"\"\n teleport: 0\n value: null\n","is_delete":false,"is_create":false},{"time":"2026-07-01T03:00:10-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 0\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T03:00:11-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 0\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T03:52:58-04:00","description":"Update item bread_dough","file_path":"data/items/consumables/bread_dough.yaml","old_content":"color: DE\ncraft:\n - ingredients:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n end_message: testend\n fail: \"\"\n level: 0\n success_message: testmsg\n output_qty: 0\n start_message: teststart\n station: []\n subtype: \"\"\n tool: \"\"\n type: combine\n ticks_per_cycle: 2\n xp: 0\ndescription: A ball of uncooked bread dough. It needs to be baked.\nid: bread_dough\nmax_quality: 0\nname: bread dough\nquality: 0\nstackable: false\nvalue: 3\n","new_content":"color: DE\ncraft:\n - end_message: \"\"\n fail: \"\"\n ingredients:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n level: 0\n output_qty: 0\n start_message: \"\"\n station: []\n subtype: \"\"\n success_message: \"\"\n ticks_per_cycle: 2\n tool: \"\"\n type: smithing\n xp: 0\ndescription: A ball of uncooked bread dough. It needs to be baked.\nid: bread_dough\nmax_quality: 0\nname: bread dough\nquality: 0\nstackable: false\nvalue: 3\n","is_delete":false,"is_create":false},{"time":"2026-07-01T03:53:08-04:00","description":"Update item bread_dough","file_path":"data/items/consumables/bread_dough.yaml","old_content":"color: DE\ncraft:\n - end_message: \"\"\n fail: \"\"\n ingredients:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n level: 0\n output_qty: 0\n start_message: \"\"\n station: []\n subtype: \"\"\n success_message: \"\"\n ticks_per_cycle: 2\n tool: \"\"\n type: smithing\n xp: 0\ndescription: A ball of uncooked bread dough. It needs to be baked.\nid: bread_dough\nmax_quality: 0\nname: bread dough\nquality: 0\nstackable: false\nvalue: 3\n","new_content":"color: DE\ncraft:\n - end_message: \"\"\n fail: \"\"\n ingredients:\n - byproducts:\n - empty_pot\n items:\n - pot_of_flour\n quantity: 1\n - byproducts:\n - empty_bucket\n - empty_jug\n items:\n - bucket_of_water\n - jug_of_water\n quantity: 1\n level: 0\n output_qty: 0\n start_message: \"\"\n station: []\n subtype: \"\"\n success_message: \"\"\n ticks_per_cycle: 2\n tool: \"\"\n type: combine\n xp: 0\ndescription: A ball of uncooked bread dough. It needs to be baked.\nid: bread_dough\nmax_quality: 0\nname: bread dough\nquality: 0\nstackable: false\nvalue: 3\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:08:15-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: solar_radiation\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:08:19-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: solar_radiation\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:08:26-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs: []\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:08:32-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - id: tree\n - aliases: []\n description:\n - text: \"\"\n hidden: false\n name: \"\"\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:08:37-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - id: tree\n - aliases: []\n description:\n - text: \"\"\n hidden: false\n name: \"\"\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - aliases: []\n description: []\n hidden: false\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:08:43-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - aliases: []\n description: []\n hidden: false\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - aliases: []\n description:\n - text: YOU FOUND HIM\n hidden: false\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:08:44-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - aliases: []\n description:\n - text: YOU FOUND HIM\n hidden: false\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - aliases: []\n description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:41-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"id: 2003\nname: Test Room\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:41-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:44-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:44-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:47-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:47-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:49-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:49-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:51-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: \"00\"\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:53-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:55-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:56-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:58-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:09:58-04:00","description":"update room 2003","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:10:01-04:00","description":"update room 2003 (add exit northeast to 1005)","file_path":"data/rooms/intro/2003.yaml","old_content":"block_transport: false\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nhazard: \"\"\nid: 2003\nitem_spawns: []\nmobs: []\nname: Test Room\nobjects: []\non_enter: []\ntriggers: []\n","new_content":"id: 2003\nname: Test Room\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n northeast:\n room: 1005\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:10:01-04:00","description":"create room 1005","file_path":"data/rooms/intro/1005.yaml","old_content":"","new_content":"color: A5\nexits:\n southwest: 2003\nid: 1005\nname: 'Room #1005'\n","is_delete":false,"is_create":true},{"time":"2026-07-01T04:10:03-04:00","description":"delete room 1005 (cleaned 1 exits)","file_path":"data/rooms/intro/1005.yaml","old_content":"color: A5\nexits:\n southwest: 2003\nid: 1005\nname: 'Room #1005'\n","new_content":"","is_delete":true,"is_create":false,"extra_files":[{"file_path":"data/rooms/intro/2003.yaml","old_content":"id: 2003\nname: Test Room\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n northeast:\n room: 1005\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 2003\nname: Test Room\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n"}]},{"time":"2026-07-01T04:11:43-04:00","description":"update room 2003 (add exit north to 1005)","file_path":"data/rooms/intro/2003.yaml","old_content":"id: 2003\nname: Test Room\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","new_content":"id: 2003\nname: Test Room\ncolor: A5\ndescription:\n - text: It's a test room\nexits:\n north:\n room: 1005\n south:\n room: 2004\n southwest:\n room: 2005\n west:\n room: 2002\nobjects: []\nitem_spawns: []\nmobs: []\non_enter: []\nhazard: \"\"\nblock_transport: false\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:22:38-04:00","description":"Update drop credit_stick_drop","file_path":"data/drops/credit_stick_drop.yaml","old_content":"drops:\n - item_id: credits\n weight: 40\n quantity: 15\n - item_id: credits\n weight: 30\n quantity: 30\n - item_id: credits\n weight: 20\n quantity: 50\n - item_id: credits\n weight: 8\n quantity: 100\n - item_id: credits\n weight: 2\n quantity: 250","new_content":"drops:\n - item_id: credits\n quantity: 14\n weight: 40\n - item_id: credits\n quantity: 30\n weight: 30\n - item_id: credits\n quantity: 50\n weight: 20\n - item_id: credits\n quantity: 100\n weight: 8\n - item_id: credits\n quantity: 250\n weight: 2\nid: credit_stick_drop\n","is_delete":false,"is_create":false},{"time":"2026-07-01T04:22:42-04:00","description":"Update drop credit_stick_drop","file_path":"data/drops/credit_stick_drop.yaml","old_content":"drops:\n - item_id: credits\n quantity: 14\n weight: 40\n - item_id: credits\n quantity: 30\n weight: 30\n - item_id: credits\n quantity: 50\n weight: 20\n - item_id: credits\n quantity: 100\n weight: 8\n - item_id: credits\n quantity: 250\n weight: 2\nid: credit_stick_drop\n","new_content":"drops:\n - item_id: credits\n quantity: 15\n weight: 40\n - item_id: credits\n quantity: 30\n weight: 30\n - item_id: credits\n quantity: 50\n weight: 20\n - item_id: credits\n quantity: 100\n weight: 8\n - item_id: credits\n quantity: 250\n weight: 2\nid: credit_stick_drop\n","is_delete":false,"is_create":false},{"time":"2026-07-01T13:06:32-04:00","description":"Create mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"","new_content":"id: flight_attendant_copy\n","is_delete":false,"is_create":true},{"time":"2026-07-01T13:06:32-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"id: flight_attendant_copy\n","new_content":"description: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nname: flight attendant\nprotected: true\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - text: '\"Thank you.\"'\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T13:07:46-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"description: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nname: flight attendant\nprotected: true\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - text: '\"Thank you.\"'\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n sequence:\n - Test\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - text: '\"Thank you.\"'\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T13:08:04-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n sequence:\n - Test\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - text: '\"Thank you.\"'\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n sequence:\n - Test\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - text: '\"Thank you.\"'\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T13:09:12-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n sequence:\n - Test\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - text: '\"Thank you.\"'\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - goto: Test\n text: '\"Thank you.\"'\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T13:16:15-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - goto: Test\n text: '\"Thank you.\"'\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n sequence:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n message: '\"Hi there, how can I help?\"'\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n thanks:\n message: '\"Thank for flying with Denali. Watch your step on the way out please.\"'\n options:\n - goto: Test\n text: '\"Thank you.\"'\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T13:16:46-04:00","description":"Update item adamant_arrow","file_path":"data/items/ammo/adamant_arrow.yaml","old_content":"color: \"78\"\ncraft:\n ingredients:\n - items:\n - headless_arrow\n quantity: 15\n - items:\n - adamant_arrowtips\n quantity: 15\n level: 60\n output_qty: 15\n type: fletching\n ticks_per_cycle: 2\n xp: 10\ndescription: An adamant-tipped arrow.\nequipment:\n other:\n ranged: 31\n slot: ammo\n type: ammo\nname: adamant arrow\nrecoverable: true\nstackable: true\nvalue: 20\n","new_content":"color: \"78\"\ncraft:\n - end_message: \"\"\n fail: \"\"\n ingredients:\n - items:\n - headless_arrow\n quantity: 15\n - items:\n - adamant_arrowtips\n quantity: 15\n level: 60\n output_qty: 15\n start_message: \"\"\n station: []\n subtype: \"\"\n success_message: \"\"\n ticks_per_cycle: 2\n tool: \"\"\n type: fletching\n xp: 10\ndescription: An adamant-tipped arrow.2\nequipment:\n other:\n ranged: 31\n slot: ammo\n type: ammo\nid: adamant_arrow\nmax_quality: 0\nname: adamant arrow\nquality: 0\nrecoverable: true\nstackable: true\nvalue: 20\n","is_delete":false,"is_create":false},{"time":"2026-07-01T13:16:50-04:00","description":"Update item adamant_arrow","file_path":"data/items/ammo/adamant_arrow.yaml","old_content":"color: \"78\"\ncraft:\n - end_message: \"\"\n fail: \"\"\n ingredients:\n - items:\n - headless_arrow\n quantity: 15\n - items:\n - adamant_arrowtips\n quantity: 15\n level: 60\n output_qty: 15\n start_message: \"\"\n station: []\n subtype: \"\"\n success_message: \"\"\n ticks_per_cycle: 2\n tool: \"\"\n type: fletching\n xp: 10\ndescription: An adamant-tipped arrow.2\nequipment:\n other:\n ranged: 31\n slot: ammo\n type: ammo\nid: adamant_arrow\nmax_quality: 0\nname: adamant arrow\nquality: 0\nrecoverable: true\nstackable: true\nvalue: 20\n","new_content":"color: \"78\"\ncraft:\n - end_message: \"\"\n fail: \"\"\n ingredients:\n - items:\n - headless_arrow\n quantity: 15\n - items:\n - adamant_arrowtips\n quantity: 15\n level: 60\n output_qty: 15\n start_message: \"\"\n station: []\n subtype: \"\"\n success_message: \"\"\n ticks_per_cycle: 2\n tool: \"\"\n type: fletching\n xp: 10\ndescription: An adamant-tipped arrow.\nequipment:\n other:\n ranged: 31\n slot: ammo\n type: ammo\nid: adamant_arrow\nmax_quality: 0\nname: adamant arrow\nquality: 0\nrecoverable: true\nstackable: true\nvalue: 20\n","is_delete":false,"is_create":false},{"time":"2026-07-01T15:41:47-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n sign_reminder:\n messages:\n - '\"Yeah, just us two! Not a lot of people heading into the belt these days.\"'\n - '\"But we''ll be landing shortly! Please be sure {0B bold}look{/} at the information {0B bold}sign{/} so you''ll be all set for your final destination.\"'\n start:\n condition:\n not: true\n player_flag: 1001_look_sign\n goto: thanks\n messages: ['\"Hi there, how can I help?\"']\n options:\n - goto: sign_reminder\n text: '\"Oh, nothing... Small crowd on this ship. Just looking for conversation.\"'\n - text: '\"Goodbye.\"'\n thanks:\n messages: ['\"Thank for flying with Denali. Watch your step on the way out please.\"']\n options:\n - goto: Test\n text: '\"Thank you.\"'\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\n - condition:\n min_credits: 500000\n goto: \"\"\n text: 500000!!\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T15:41:55-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: flight attendant\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\n - condition:\n min_credits: 500000\n goto: \"\"\n text: 500000!!\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\n - condition:\n min_credits: 500000\n goto: \"\"\n text: 500000!!\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T15:42:56-04:00","description":"update room 2001","file_path":"data/rooms/intro/2001.yaml","old_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\nname: Test Room\nobjects:\n - aliases: []\n description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","new_content":"block_transport: false\ncolor: \"\"\ndescription:\n - text: It's a test room\nexits:\n east:\n room: 2002\n south:\n room: 2006\n southeast:\n room: 2005\n west:\n room: 1001\nhazard: \"\"\nid: 2001\nitem_spawns:\n - id: bronze_axe\n quantity: 1\n respawn_ticks: 1\n - id: pot_of_flour\n quantity: 1\n respawn_ticks: 1\n - id: bucket_of_water\n quantity: 1\n respawn_ticks: 1\nmobs:\n - id: man\n - id: flight_attendant_copy\nname: Test Room\nobjects:\n - aliases: []\n description:\n - text: YOU FOUND HIM\n hidden: true\n name: hidden guy\n - id: tree\non_enter: []\ntriggers: []\n","is_delete":false,"is_create":false},{"time":"2026-07-01T15:47:02-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\n - condition:\n min_credits: 500000\n goto: \"\"\n text: 500000!!\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\n - action:\n shop:\n items:\n - buy_price: 1\n item_id: bronze_pickaxe\n sell_price: 1\n message: SHOP SHOP\n goto: \"\"\n text: 500000!!\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T15:47:37-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\n - action:\n shop:\n items:\n - buy_price: 1\n item_id: bronze_pickaxe\n sell_price: 1\n message: SHOP SHOP\n goto: \"\"\n text: 500000!!\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\n - action:\n shop:\n items:\n - buy_price: 1\n item_id: bronze_pickaxe\n sell_price: 1\n message: SHOP SHOP\n goto: \"\"\n text: 500000!!\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T17:16:00-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\nshop:\n message: SHOP SHOP\n items:\n - item_id: bronze_pickaxe\n stock: 5\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\nshop:\n buy_percentage: 0\n buys_anything: false\n change_percentage: 0\n items:\n - item_id: bronze_pickaxe\n restock_ticks: 0\n stock: 5\n message: SHOP SHOP\n restock_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T17:16:36-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\nshop:\n buy_percentage: 0\n buys_anything: false\n change_percentage: 0\n items:\n - item_id: bronze_pickaxe\n restock_ticks: 0\n stock: 5\n message: SHOP SHOP\n restock_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\nunique: false\n","new_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\nshop:\n buy_percentage: 0\n buys_anything: true\n change_percentage: 0\n items:\n - item_id: bronze_pickaxe\n restock_ticks: 0\n stock: 5\n message: SHOP SHOP\n restock_ticks: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T18:04:00-04:00","description":"Update mob flight_attendant_copy","file_path":"data/mobs/flight_attendant_copy.yaml","old_content":"aggressive: false\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nrespawn_ticks: 0\nshop:\n message: SHOP SHOP\n items:\n - item_id: bronze_pickaxe\n stock: 5\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\nunique: false\n","new_content":"aggressive: false\nattack: 0\nbonuses:\n attack_bonus: 0\n attack_type: stab\n strength_bonus: 0\ndefense: 0\ndefenses:\n crush_defense: 0\n ranged_defense: 0\n science_defense: 0\n slash_defense: 0\n stab_defense: 0\ndescription: A smiling flight attendant in a crisp uniform, ready to assist passengers.\nhp: 0\nid: flight_attendant_copy\nidle_descriptions:\n - adjusts her name badge\n - smiles politely at you\nkind: combat\nname: Credit Checker!\nprotected: true\nranged: 0\nrespawn_ticks: 0\nscience: 0\nshop:\n buy_percentage: 0\n buys_anything: true\n change_percentage: 0\n items:\n - item_id: bronze_pickaxe\n restock_ticks: 0\n stock: 5\n message: SHOP SHOP\nspeed: 0\nstrength: 0\ntalk:\n nodes:\n start:\n options:\n - goto: \"\"\n text: None!\n - text: None\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T18:37:34-04:00","description":"Update mob bandit","file_path":"data/mobs/examples/bandit.yaml","old_content":"name: bandit\ndescription: \"A scrappy outlaw with a cybernetic arm and patched armor. He eyes you with predatory intent.\"\nattack: 10\nstrength: 12\ndefense: 12\nhp: 28\nspeed: 5\naggressive: true\nrespawn_ticks: 30\nattack_type: slash\nattack_bonus: 5\nstrength_bonus: 5\nstab_defense: 10\nslash_defense: 15\ncrush_defense: 8\nscience_defense: -5\nranged_defense: 12\nidle_descriptions:\n - \"scans the horizon for targets\"\n - \"wipes a blade on his sleeve\"\n - \"spits on the ground\"\n - \"adjusts a cybernetic knuckle\"\ncombat_descriptions:\n - \"slashes at %s with a serrated blade\"\n - \"delivers a crushing punch with a cybernetic fist\"\n - \"lunges at %s with a battle cry\"\nsize: medium\ndrops:\n remains: bones\n loot:\n - item_id: credits\n weight: 70\n quantity: 30\n - item_id: credits\n weight: 20\n quantity: 80\n - table: herb_table_low\n weight: 10\n","new_content":"aggressive: true\nassassin_level: 0\nattack: 10\nbonuses:\n attack_bonus: 0\n attack_type: stab\n strength_bonus: 0\ncombat_descriptions:\n - slashes at %s with a serrated blade\n - delivers a crushing punch with a cybernetic fist\n - lunges at %s with a battle cry\ndefense: 12\ndefenses:\n crush_defense: 0\n ranged_defense: 0\n science_defense: 0\n slash_defense: 0\n stab_defense: 0\ndescription: A scrappy outlaw with a cybernetic arm and patched armor. He eyes you with predatory intent.\ndrops:\n loot:\n - item_id: credits\n quantity: 30\n weight: 70\n - item_id: credits\n quantity: 80\n weight: 20\n - quantity: 0\n table: herb_table_low\n weight: 10\n remains: bones\nhp: 28\nid: bandit\nidle_descriptions:\n - scans the horizon for targets\n - wipes a blade on his sleeve\n - spits on the ground\n - adjusts a cybernetic knuckle\nkind: combat\nname: bandit\nprotected: false\nranged: 0\nrespawn_ticks: 30\nscience: 0\nsize: medium\nspeed: 5\nstrength: 12\nunique: false\n","is_delete":false,"is_create":false},{"time":"2026-07-01T18:39:27-04:00","description":"Update mob bandit","file_path":"data/mobs/examples/bandit.yaml","old_content":"aggressive: true\nassassin_level: 0\nattack: 10\nbonuses:\n attack_bonus: 0\n attack_type: stab\n strength_bonus: 0\ncombat_descriptions:\n - slashes at %s with a serrated blade\n - delivers a crushing punch with a cybernetic fist\n - lunges at %s with a battle cry\ndefense: 12\ndefenses:\n crush_defense: 0\n ranged_defense: 0\n science_defense: 0\n slash_defense: 0\n stab_defense: 0\ndescription: A scrappy outlaw with a cybernetic arm and patched armor. He eyes you with predatory intent.\ndrops:\n loot:\n - item_id: credits\n quantity: 30\n weight: 70\n - item_id: credits\n quantity: 80\n weight: 20\n - quantity: 0\n table: herb_table_low\n weight: 10\n remains: bones\nhp: 28\nid: bandit\nidle_descriptions:\n - scans the horizon for targets\n - wipes a blade on his sleeve\n - spits on the ground\n - adjusts a cybernetic knuckle\nkind: combat\nname: bandit\nprotected: false\nranged: 0\nrespawn_ticks: 30\nscience: 0\nsize: medium\nspeed: 5\nstrength: 12\nunique: false\n","new_content":"aggressive: true\nassassin_level: 0\nattack: 10\nbonuses:\n attack_bonus: 0\n attack_type: stab\n strength_bonus: 0\ncombat_descriptions:\n - slashes at %s with a serrated blade\n - delivers a crushing punch with a cybernetic fist\n - lunges at %s with a battle cry\ndefense: 12\ndefenses:\n crush_defense: 0\n ranged_defense: 0\n science_defense: 0\n slash_defense: 0\n stab_defense: 0\ndescription: A scrappy outlaw with a cybernetic arm and patched armor. He eyes you with predatory intent.\ndrops:\n loot:\n - item_id: credits\n quantity: 30\n weight: 70\n - item_id: credits\n quantity: 80\n weight: 20\n - quantity: 0\n table: herb_table_low\n weight: 10\n remains: bones\nhp: 28\nid: bandit\nidle_descriptions:\n - scans the horizon for targets\n - wipes a blade on his sleeve\n - spits on the ground\n - adjusts a cybernetic knuckle\nkind: task\nname: bandit\nprotected: false\nranged: 0\nrespawn_ticks: 30\nscience: 0\nsize: medium\nspeed: 5\nstrength: 12\nunique: false\n","is_delete":false,"is_create":false}],"redo":null} \ No newline at end of file
diff --git a/data/mobs/examples/ancient_construct.yaml b/data/mobs/examples/ancient_construct.yaml
index 190e8c2..ab878cd 100644
--- a/data/mobs/examples/ancient_construct.yaml
+++ b/data/mobs/examples/ancient_construct.yaml
@@ -1,31 +1,10 @@
name: ancient construct
description: "An impossibly old machine from before the regression, still operational. Its design is alien even by modern standards, covered in glowing runes that predate recorded history."
-attack: 58
-strength: 62
-defense: 66
-hp: 152
-speed: 4
-aggressive: true
-respawn_ticks: 150
-attack_type: slash
-attack_bonus: 55
-strength_bonus: 55
-stab_defense: 95
-slash_defense: 100
-crush_defense: 85
-science_defense: -40
-ranged_defense: 70
-weakness: chaos
idle_descriptions:
- "etches glowing symbols into the air"
- "reconfigures its form with clicking sounds"
- "projects a holographic star map"
- "emits a resonant chime that shakes the walls"
-combat_descriptions:
- - "slices at %s with a blade of pure light"
- - "unleashes a cascade of ancient energy at %s"
- - "teleports behind %s and strikes"
-size: massive
drops:
remains: scrap
loot:
@@ -45,3 +24,33 @@ drops:
quantity: 3
- table: herb_table_high
weight: 10
+combat:
+ kind: combat
+ stats:
+ hp: 152
+ attack: 58
+ strength: 62
+ defense: 66
+ attack_type: slash
+ speed: 4
+ aggressive: true
+ respawn_ticks: 150
+ bonuses:
+ attack_bonus: 55
+ strength_bonus: 55
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 95
+ slash_defense: 100
+ crush_defense: 85
+ science_defense: -40
+ ranged_defense: 70
+ weakness: chaos
+ size: massive
+ combat_descriptions:
+ - "slices at %s with a blade of pure light"
+ - "unleashes a cascade of ancient energy at %s"
+ - "teleports behind %s and strikes"
diff --git a/data/mobs/examples/bandit.yaml b/data/mobs/examples/bandit.yaml
index 51e4b8e..a3fd3e7 100644
--- a/data/mobs/examples/bandit.yaml
+++ b/data/mobs/examples/bandit.yaml
@@ -1,30 +1,10 @@
name: bandit
description: "A scrappy outlaw with a cybernetic arm and patched armor. He eyes you with predatory intent."
-attack: 10
-strength: 12
-defense: 12
-hp: 28
-speed: 5
-aggressive: true
-respawn_ticks: 30
-attack_type: slash
-attack_bonus: 5
-strength_bonus: 5
-stab_defense: 10
-slash_defense: 15
-crush_defense: 8
-science_defense: -5
-ranged_defense: 12
idle_descriptions:
- "scans the horizon for targets"
- "wipes a blade on his sleeve"
- "spits on the ground"
- "adjusts a cybernetic knuckle"
-combat_descriptions:
- - "slashes at %s with a serrated blade"
- - "delivers a crushing punch with a cybernetic fist"
- - "lunges at %s with a battle cry"
-size: medium
drops:
remains: bones
loot:
@@ -36,3 +16,32 @@ drops:
quantity: 80
- table: herb_table_low
weight: 10
+combat:
+ kind: combat
+ stats:
+ hp: 28
+ attack: 10
+ strength: 12
+ defense: 12
+ attack_type: stab
+ speed: 5
+ aggressive: true
+ respawn_ticks: 30
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 0
+ slash_defense: 0
+ crush_defense: 0
+ science_defense: 0
+ ranged_defense: 0
+ size: medium
+ combat_descriptions:
+ - "slashes at %s with a serrated blade"
+ - "delivers a crushing punch with a cybernetic fist"
+ - "lunges at %s with a battle cry"
diff --git a/data/mobs/examples/bioengineer.yaml b/data/mobs/examples/bioengineer.yaml
index 4761991..d6c9193 100644
--- a/data/mobs/examples/bioengineer.yaml
+++ b/data/mobs/examples/bioengineer.yaml
@@ -1,32 +1,15 @@
name: Bioengineer
description: "A lab-coated scientist carrying a satchel of genetically modified seeds. Her pockets are stuffed with rare specimens."
-combat_descriptions:
- - "jabs a syringe at %s"
- - "is being overpowered by %s"
- - "fights desperately against %s"
idle_descriptions:
- "scribbles notes on a clipboard"
- "carefully inspects a vial of green liquid"
- "adjusts her safety goggles"
- "mutters about gene splicing yields"
-attack: 6
-strength: 4
-defense: 5
-hp: 25
-speed: 5
-aggressive: false
-respawn_ticks: 50
-attack_type: crush
-stab_defense: 0
-slash_defense: 0
-crush_defense: 0
-science_defense: 0
-ranged_defense: 0
-steal_table: bioengineer_steal
-steal_level: 38
-steal_xp: 45
-steal_speed: 4
-size: small
+steal:
+ table: bioengineer_steal
+ level: 38
+ xp: 45
+ speed: 4
drops:
remains: "bones"
loot:
@@ -41,4 +24,33 @@ drops:
quantity: 1
- item_id: "ranarr_seed"
weight: 5
- quantity: 1 \ No newline at end of file
+ quantity: 1
+combat:
+ kind: combat
+ stats:
+ hp: 25
+ attack: 6
+ strength: 4
+ defense: 5
+ attack_type: crush
+ speed: 5
+ aggressive: false
+ respawn_ticks: 50
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 0
+ slash_defense: 0
+ crush_defense: 0
+ science_defense: 0
+ ranged_defense: 0
+ size: small
+ combat_descriptions:
+ - "jabs a syringe at %s"
+ - "is being overpowered by %s"
+ - "fights desperately against %s"
diff --git a/data/mobs/examples/client.yaml b/data/mobs/examples/client.yaml
index 0d5f27d..2442a8a 100644
--- a/data/mobs/examples/client.yaml
+++ b/data/mobs/examples/client.yaml
@@ -1,8 +1,7 @@
-aggressive: false
-attack: 1
-defense: 1
+name: The Client
description: A shadowy figure in a dark coat. They speak in clipped, measured tones and seem to know everything about every creature in the sector.
-hp: 100
+protected: true
+unique: true
idle_descriptions:
- reviews a holographic dossier
- marks a location on a worn star chart
@@ -10,11 +9,6 @@ idle_descriptions:
- mutters coordinates under their breath
- glances at you appraisingly
- taps a data pad with a stylus
-name: The Client
-protected: true
-respawn_ticks: 30
-speed: 5
-strength: 1
talk:
nodes:
assign_task:
@@ -224,5 +218,3 @@ talk:
text: '"Buy spectral visor (75 credits)."'
- goto: start
text: '"Back."'
-unique: true
-size: small
diff --git a/data/mobs/examples/corrupted_scientist.yaml b/data/mobs/examples/corrupted_scientist.yaml
index 2083c03..aeda04d 100644
--- a/data/mobs/examples/corrupted_scientist.yaml
+++ b/data/mobs/examples/corrupted_scientist.yaml
@@ -1,32 +1,10 @@
name: corrupted scientist
description: "A researcher whose mind was consumed by their own experiments. Energy crackles around their fingertips and their lab coat is singed and tattered."
-attack: 1
-strength: 1
-defense: 18
-hp: 40
-science: 50
-speed: 5
-aggressive: true
-respawn_ticks: 45
-attack_type: science
-attack_bonus: 0
-strength_bonus: 0
-stab_defense: 25
-slash_defense: 25
-crush_defense: 20
-science_defense: 35
-ranged_defense: -5
-weakness: eco
idle_descriptions:
- "mutters incomprehensible formulas"
- "energy arcs between their fingers"
- "scribbles equations on the wall in soot"
- "stares at their own hands in horror"
-combat_descriptions:
- - "blasts %s with a burst of unstable energy"
- - "unleashes a wave of chaotic force at %s"
- - "channels raw power through their hands at %s"
-size: medium
drops:
remains: bones
loot:
@@ -41,3 +19,34 @@ drops:
quantity: 2
- table: herb_table_mid
weight: 15
+combat:
+ kind: combat
+ stats:
+ hp: 40
+ attack: 1
+ strength: 1
+ defense: 18
+ science: 50
+ attack_type: science
+ speed: 5
+ aggressive: true
+ respawn_ticks: 45
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 25
+ slash_defense: 25
+ crush_defense: 20
+ science_defense: 35
+ ranged_defense: -5
+ weakness: eco
+ size: medium
+ combat_descriptions:
+ - "blasts %s with a burst of unstable energy"
+ - "unleashes a wave of chaotic force at %s"
+ - "channels raw power through their hands at %s"
diff --git a/data/mobs/examples/cow.yaml b/data/mobs/examples/cow.yaml
index 7f1ee3c..2171d12 100644
--- a/data/mobs/examples/cow.yaml
+++ b/data/mobs/examples/cow.yaml
@@ -1,24 +1,10 @@
name: cow
description: "A placid dairy cow, chewing cud."
-attack: 1
-strength: 1
-defense: 1
-hp: 8
-speed: 5
-aggressive: false
-respawn_ticks: 30
-attack_type: crush
-stab_defense: 1
-slash_defense: 1
-crush_defense: 1
-science_defense: 0
-ranged_defense: 0
idle_descriptions:
- "moos softly"
- "chews on some grass"
- "swishes its tail lazily"
- "stares at you with big brown eyes"
-size: large
drops:
remains: bones
loot:
@@ -26,3 +12,28 @@ drops:
weight: 100
- item_id: raw_beef
weight: 100
+combat:
+ kind: combat
+ stats:
+ hp: 8
+ attack: 1
+ strength: 1
+ defense: 1
+ attack_type: crush
+ speed: 5
+ aggressive: false
+ respawn_ticks: 30
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 1
+ slash_defense: 1
+ crush_defense: 1
+ science_defense: 0
+ ranged_defense: 0
+ size: large
diff --git a/data/mobs/examples/crawler.yaml b/data/mobs/examples/crawler.yaml
index 9021c51..55d8f6f 100644
--- a/data/mobs/examples/crawler.yaml
+++ b/data/mobs/examples/crawler.yaml
@@ -1,24 +1,10 @@
name: crawler
description: "A heavily armored bio-mechanical creature with a chitinous exoskeleton. Its regenerative biology prevents death unless dissolved with acid."
-assassin_level: 30
-finishing_blow: acid_vial
-attack: 25
-strength: 22
-defense: 30
-hp: 80
-speed: 5
-aggressive: false
-respawn_ticks: 45
idle_descriptions:
- "scrapes its mandibles together menacingly"
- "clicks and chitters in an alien rhythm"
- "tests the air with feathered antennae"
- "coils its segmented body defensively"
-combat_descriptions:
- - "snaps its mandibles at %s"
- - "lashes out with a barbed tail at %s"
- - "charges headlong into %s"
-size: large
drops:
remains: chitin_plate
loot:
@@ -30,3 +16,34 @@ drops:
- item_id: credits
weight: 20
quantity: 500
+combat:
+ kind: combat
+ stats:
+ hp: 80
+ attack: 25
+ strength: 22
+ defense: 30
+ attack_type: crush
+ speed: 5
+ aggressive: false
+ respawn_ticks: 45
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 0
+ slash_defense: 0
+ crush_defense: 0
+ science_defense: 0
+ ranged_defense: 0
+ assassin_level: 30
+ finishing_blow: acid_vial
+ size: large
+ combat_descriptions:
+ - "snaps its mandibles at %s"
+ - "lashes out with a barbed tail at %s"
+ - "charges headlong into %s"
diff --git a/data/mobs/examples/drone.yaml b/data/mobs/examples/drone.yaml
index 5ac6552..08091f5 100644
--- a/data/mobs/examples/drone.yaml
+++ b/data/mobs/examples/drone.yaml
@@ -1,24 +1,10 @@
name: drone
description: "A malfunctioning security drone crackling with electrical discharge. Its attacks are especially dangerous to anyone not wearing insulated gloves."
-assassin_level: 15
-damage_without: insulated_gloves
-attack: 15
-strength: 14
-defense: 12
-hp: 45
-speed: 4
-aggressive: true
-respawn_ticks: 35
idle_descriptions:
- "hovers erratically, sparking"
- "emits a high-pitched whine"
- "scans the area with a flickering red beam"
- "rotates its weapon array with a mechanical click"
-combat_descriptions:
- - "fires an electrical bolt at %s"
- - "charges its capacitors and zaps %s"
- - "swoops down on %s with crackling energy"
-size: small
drops:
remains: circuit_board
loot:
@@ -30,3 +16,34 @@ drops:
- item_id: credits
weight: 15
quantity: 200
+combat:
+ kind: combat
+ stats:
+ hp: 45
+ attack: 15
+ strength: 14
+ defense: 12
+ attack_type: crush
+ speed: 4
+ aggressive: true
+ respawn_ticks: 35
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 0
+ slash_defense: 0
+ crush_defense: 0
+ science_defense: 0
+ ranged_defense: 0
+ assassin_level: 15
+ damage_without: insulated_gloves
+ size: small
+ combat_descriptions:
+ - "fires an electrical bolt at %s"
+ - "charges its capacitors and zaps %s"
+ - "swoops down on %s with crackling energy"
diff --git a/data/mobs/examples/elite_synth.yaml b/data/mobs/examples/elite_synth.yaml
index b095716..9628572 100644
--- a/data/mobs/examples/elite_synth.yaml
+++ b/data/mobs/examples/elite_synth.yaml
@@ -1,32 +1,10 @@
name: elite synth
description: "A sleek combat android with glowing blue optics and a compact energy weapon. Its chassis is polished alloy and its movements are disturbingly fluid."
-attack: 1
-strength: 1
-defense: 38
-hp: 104
-science: 65
-speed: 4
-aggressive: true
-respawn_ticks: 75
-attack_type: science
-attack_bonus: 0
-strength_bonus: 0
-stab_defense: 45
-slash_defense: 45
-crush_defense: 40
-science_defense: 55
-ranged_defense: -15
-weakness: chaos
idle_descriptions:
- "calibrates targeting sensors with a soft chime"
- "projects a holographic tactical display"
- "emits a binary chirp"
- "reconfigures its weapon array silently"
-combat_descriptions:
- - "unleashes a coherent energy beam at %s"
- - "fires a pulse of disruptor energy at %s"
- - "overloads its emitters and blasts %s"
-size: medium
drops:
remains: circuit_board
loot:
@@ -41,3 +19,34 @@ drops:
quantity: 3
- table: gem_table
weight: 15
+combat:
+ kind: combat
+ stats:
+ hp: 104
+ attack: 1
+ strength: 1
+ defense: 38
+ science: 65
+ attack_type: science
+ speed: 4
+ aggressive: true
+ respawn_ticks: 75
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 45
+ slash_defense: 45
+ crush_defense: 40
+ science_defense: 55
+ ranged_defense: -15
+ weakness: chaos
+ size: medium
+ combat_descriptions:
+ - "unleashes a coherent energy beam at %s"
+ - "fires a pulse of disruptor energy at %s"
+ - "overloads its emitters and blasts %s"
diff --git a/data/mobs/examples/enforcer_bot.yaml b/data/mobs/examples/enforcer_bot.yaml
index 78150c3..efdd698 100644
--- a/data/mobs/examples/enforcer_bot.yaml
+++ b/data/mobs/examples/enforcer_bot.yaml
@@ -1,31 +1,10 @@
name: enforcer bot
description: "A heavy riot control automaton with impact shields and a shock baton. It moves with deliberate, crushing steps."
-attack: 30
-strength: 35
-defense: 32
-hp: 70
-speed: 5
-aggressive: true
-respawn_ticks: 55
-attack_type: crush
-attack_bonus: 25
-strength_bonus: 25
-stab_defense: 40
-slash_defense: 40
-crush_defense: 50
-science_defense: -15
-ranged_defense: 30
-weakness: solar
idle_descriptions:
- "patrols the area with heavy footsteps"
- "deploys its riot shield with a hiss"
- "announces a warning in garbled speech"
- "tests its shock baton against a wall"
-combat_descriptions:
- - "smashes %s with a shock baton"
- - "slams its riot shield into %s"
- - "delivers a stunning blow to %s"
-size: large
drops:
remains: scrap
loot:
@@ -40,3 +19,33 @@ drops:
quantity: 800
- table: gem_table
weight: 5
+combat:
+ kind: combat
+ stats:
+ hp: 70
+ attack: 30
+ strength: 35
+ defense: 32
+ attack_type: crush
+ speed: 5
+ aggressive: true
+ respawn_ticks: 55
+ bonuses:
+ attack_bonus: 25
+ strength_bonus: 25
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 40
+ slash_defense: 40
+ crush_defense: 50
+ science_defense: -15
+ ranged_defense: 30
+ weakness: solar
+ size: large
+ combat_descriptions:
+ - "smashes %s with a shock baton"
+ - "slams its riot shield into %s"
+ - "delivers a stunning blow to %s"
diff --git a/data/mobs/examples/estate_broker.yaml b/data/mobs/examples/estate_broker.yaml
index b095214..e95c3a7 100644
--- a/data/mobs/examples/estate_broker.yaml
+++ b/data/mobs/examples/estate_broker.yaml
@@ -1,6 +1,6 @@
-color: "E3"
description: A sharply-dressed real estate agent with a datapad and a practiced smile.
-idle: The estate broker flashes a professional smile.
+idle_descriptions:
+ - flashes a professional smile
name: estate broker
protected: true
talk:
@@ -57,4 +57,3 @@ talk:
- goto: info
text: What do I get with a house?
unique: true
-size: small
diff --git a/data/mobs/examples/farmer.yaml b/data/mobs/examples/farmer.yaml
index 591f1a3..8e72ac2 100644
--- a/data/mobs/examples/farmer.yaml
+++ b/data/mobs/examples/farmer.yaml
@@ -1,32 +1,15 @@
name: Farmer
description: "A weathered farmer in muddy overalls, pockets bulging with seeds."
-combat_descriptions:
- - "swings a shovel at %s"
- - "is getting beaten by %s"
- - "grapples with %s"
idle_descriptions:
- "examines a handful of seeds"
- "wipes dirt from his hands"
- "mutters about the growing season"
- "adjusts his wide-brimmed hat"
-attack: 3
-strength: 3
-defense: 3
-hp: 15
-speed: 5
-aggressive: false
-respawn_ticks: 40
-attack_type: crush
-stab_defense: 0
-slash_defense: 0
-crush_defense: 0
-science_defense: 0
-ranged_defense: 0
-steal_table: farmer_steal
-steal_level: 10
-steal_xp: 15
-steal_speed: 4
-size: small
+steal:
+ table: farmer_steal
+ level: 10
+ xp: 15
+ speed: 4
drops:
remains: "bones"
loot:
@@ -41,4 +24,33 @@ drops:
quantity: 2
- item_id: "tomato_seed"
weight: 10
- quantity: 1 \ No newline at end of file
+ quantity: 1
+combat:
+ kind: combat
+ stats:
+ hp: 15
+ attack: 3
+ strength: 3
+ defense: 3
+ attack_type: crush
+ speed: 5
+ aggressive: false
+ respawn_ticks: 40
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 0
+ slash_defense: 0
+ crush_defense: 0
+ science_defense: 0
+ ranged_defense: 0
+ size: small
+ combat_descriptions:
+ - "swings a shovel at %s"
+ - "is getting beaten by %s"
+ - "grapples with %s"
diff --git a/data/mobs/examples/feral_cyborg.yaml b/data/mobs/examples/feral_cyborg.yaml
index 8b30cc3..e5edf3d 100644
--- a/data/mobs/examples/feral_cyborg.yaml
+++ b/data/mobs/examples/feral_cyborg.yaml
@@ -1,30 +1,10 @@
name: feral cyborg
description: "A heavily augmented human whose implants have driven them to madness. Razor-sharp blades extend from their forearms and their optical implant glows red."
-attack: 34
-strength: 36
-defense: 32
-hp: 82
-speed: 4
-aggressive: true
-respawn_ticks: 50
-attack_type: slash
-attack_bonus: 30
-strength_bonus: 28
-stab_defense: 35
-slash_defense: 45
-crush_defense: 30
-science_defense: -10
-ranged_defense: 35
idle_descriptions:
- "paces back and forth, muttering"
- "retracts and extends forearm blades"
- "emits a distorted laugh"
- "scratches at their own cybernetics"
-combat_descriptions:
- - "slashes %s with forearm blades"
- - "delivers a powered kick to %s"
- - "grapples %s with augmented strength"
-size: medium
drops:
remains: bones
loot:
@@ -36,3 +16,32 @@ drops:
quantity: 3
- table: herb_table_mid
weight: 15
+combat:
+ kind: combat
+ stats:
+ hp: 82
+ attack: 34
+ strength: 36
+ defense: 32
+ attack_type: slash
+ speed: 4
+ aggressive: true
+ respawn_ticks: 50
+ bonuses:
+ attack_bonus: 30
+ strength_bonus: 28
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 35
+ slash_defense: 45
+ crush_defense: 30
+ science_defense: -10
+ ranged_defense: 35
+ size: medium
+ combat_descriptions:
+ - "slashes %s with forearm blades"
+ - "delivers a powered kick to %s"
+ - "grapples %s with augmented strength"
diff --git a/data/mobs/examples/general_store_clerk.yaml b/data/mobs/examples/general_store_clerk.yaml
index bee395d..489ed28 100644
--- a/data/mobs/examples/general_store_clerk.yaml
+++ b/data/mobs/examples/general_store_clerk.yaml
@@ -1,24 +1,12 @@
-aggressive: false
-attack: 1
-attack_type: crush
-crush_defense: 0
-defense: 1
+name: Shopkeeper
description: A friendly merchant with a tidy apron, standing behind a well-stocked counter.
-hp: 50
+protected: true
+unique: true
idle_descriptions:
- arranges items on the shelves
- polishes the counter
- counts credits in the register
- greets a passerby with a nod
-name: Shopkeeper
-protected: true
-ranged_defense: 0
-respawn_ticks: 30
-science_defense: 0
-slash_defense: 0
-speed: 5
-stab_defense: 0
-strength: 1
shop:
message: '"Welcome to the General Store! Have a look around."'
items:
@@ -49,5 +37,3 @@ talk:
- '"Welcome to the General Store! Type ''list'' to see my wares."'
options:
- text: '"Goodbye."'
-unique: true
-size: small
diff --git a/data/mobs/examples/ghoul.yaml b/data/mobs/examples/ghoul.yaml
index ae8fed6..070d6f1 100644
--- a/data/mobs/examples/ghoul.yaml
+++ b/data/mobs/examples/ghoul.yaml
@@ -1,31 +1,10 @@
name: ghoul
description: "A radiation-scarred crew member, barely recognizable as human. Its flesh glows faintly and its eyes are hollow sockets."
-attack: 22
-strength: 22
-defense: 20
-hp: 54
-speed: 4
-aggressive: true
-respawn_ticks: 35
-attack_type: crush
-attack_bonus: 15
-strength_bonus: 12
-stab_defense: 20
-slash_defense: 25
-crush_defense: 15
-science_defense: -5
-ranged_defense: 20
-weakness: hydro
idle_descriptions:
- "shambles aimlessly and moans"
- "scratches at the walls leaving glowing marks"
- "stares blankly into the darkness"
- "emits a low, rattling groan"
-combat_descriptions:
- - "claws at %s with irradiated hands"
- - "lunges at %s with a gurgling shriek"
- - "bites %s with decaying teeth"
-size: medium
drops:
remains: bones
loot:
@@ -36,3 +15,33 @@ drops:
weight: 25
- table: herb_table_low
weight: 15
+combat:
+ kind: combat
+ stats:
+ hp: 54
+ attack: 22
+ strength: 22
+ defense: 20
+ attack_type: crush
+ speed: 4
+ aggressive: true
+ respawn_ticks: 35
+ bonuses:
+ attack_bonus: 15
+ strength_bonus: 12
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 20
+ slash_defense: 25
+ crush_defense: 15
+ science_defense: -5
+ ranged_defense: 20
+ weakness: hydro
+ size: medium
+ combat_descriptions:
+ - "claws at %s with irradiated hands"
+ - "lunges at %s with a gurgling shriek"
+ - "bites %s with decaying teeth"
diff --git a/data/mobs/examples/goblin.yaml b/data/mobs/examples/goblin.yaml
index a02c112..23a5f77 100644
--- a/data/mobs/examples/goblin.yaml
+++ b/data/mobs/examples/goblin.yaml
@@ -1,26 +1,10 @@
name: goblin
description: "A small green-skinned goblin with a rusty blade."
-attack: 1
-strength: 3
-defense: 3
-hp: 12
-speed: 5
-aggressive: true
-respawn_ticks: 25
-attack_type: slash
-attack_bonus: 3
-strength_bonus: 2
-stab_defense: 4
-slash_defense: 3
-crush_defense: -2
-science_defense: 0
-ranged_defense: 3
idle_descriptions:
- "mutters something unintelligible"
- "waves a rusty blade around"
- "picks its nose"
- "kicks a pebble"
-size: small
drops:
remains: bones
loot:
@@ -30,3 +14,28 @@ drops:
- item_id: credits
weight: 20
quantity: 25
+combat:
+ kind: combat
+ stats:
+ hp: 12
+ attack: 1
+ strength: 3
+ defense: 3
+ attack_type: slash
+ speed: 5
+ aggressive: true
+ respawn_ticks: 25
+ bonuses:
+ attack_bonus: 3
+ strength_bonus: 2
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 4
+ slash_defense: 3
+ crush_defense: -2
+ science_defense: 0
+ ranged_defense: 3
+ size: small
diff --git a/data/mobs/examples/greater_drone.yaml b/data/mobs/examples/greater_drone.yaml
index 11cf8e2..93993ea 100644
--- a/data/mobs/examples/greater_drone.yaml
+++ b/data/mobs/examples/greater_drone.yaml
@@ -1,28 +1,10 @@
name: greater drone
description: "A large, heavily armored drone with multiple energy emitters. Red warning lights pulse along its hull."
-attack: 1
-strength: 1
-defense: 30
-hp: 120
-ranged: 0
-science: 40
-speed: 4
-aggressive: true
-respawn_ticks: 80
-attack_type: science
-attack_bonus: 0
-strength_bonus: 0
-stab_defense: 55
-slash_defense: 55
-crush_defense: 50
-science_defense: 40
-ranged_defense: -20
idle_descriptions:
- "projects a defensive energy shield"
- "recalibrates its targeting array"
- "emits a warning klaxon"
- "deploys sensor probes"
-size: medium
drops:
loot:
- item_id: scrap
@@ -31,3 +13,29 @@ drops:
- item_id: credits
weight: 60
quantity: 1500
+combat:
+ kind: combat
+ stats:
+ hp: 120
+ attack: 1
+ strength: 1
+ defense: 30
+ science: 40
+ attack_type: science
+ speed: 4
+ aggressive: true
+ respawn_ticks: 80
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 55
+ slash_defense: 55
+ crush_defense: 50
+ science_defense: 40
+ ranged_defense: -20
+ size: medium
diff --git a/data/mobs/examples/guard.yaml b/data/mobs/examples/guard.yaml
index cba448b..bd20f24 100644
--- a/data/mobs/examples/guard.yaml
+++ b/data/mobs/examples/guard.yaml
@@ -1,26 +1,12 @@
-aggressive: false
-attack: 5
-attack_bonus: 8
-attack_type: slash
-crush_defense: 10
-defense: 5
+name: Guard
description: A stern-looking guard in weathered armor.
-hp: 30
+unique: true
+protected: true
idle_descriptions:
- scans the area with a watchful eye
- adjusts the grip on his weapon
- nods curtly at passersby
- leans against the gate, arms folded
-name: Guard
-protected: true
-ranged_defense: 12
-respawn_ticks: 60
-science_defense: -5
-slash_defense: 15
-speed: 5
-stab_defense: 12
-strength: 5
-strength_bonus: 6
talk:
nodes:
about_gate:
@@ -71,5 +57,3 @@ talk:
- '"Good quality ore. This''ll do." He stamps a slip of paper and hands it to you. "That''s your pass. Don''t lose it."'
options:
- text: '"Thanks."'
-unique: true
-size: medium
diff --git a/data/mobs/examples/heavy_mech.yaml b/data/mobs/examples/heavy_mech.yaml
index e2f5f5a..669c444 100644
--- a/data/mobs/examples/heavy_mech.yaml
+++ b/data/mobs/examples/heavy_mech.yaml
@@ -1,31 +1,10 @@
name: heavy mech
description: "A lumbering assault mech with layered armor plating and a rotary cannon arm. Steam vents from its exhaust ports with each step."
-attack: 40
-strength: 44
-defense: 44
-hp: 94
-speed: 5
-aggressive: true
-respawn_ticks: 70
-attack_type: crush
-attack_bonus: 35
-strength_bonus: 35
-stab_defense: 55
-slash_defense: 55
-crush_defense: 65
-science_defense: -25
-ranged_defense: 40
-weakness: solar
idle_descriptions:
- "scans the room with a blue optical beam"
- "vents a cloud of steam"
- "rotates its cannon with a mechanical whine"
- "announces a threat level assessment"
-combat_descriptions:
- - "fires its rotary cannon at %s"
- - "smashes %s with a hydraulic fist"
- - "unleashes a missile salvo at %s"
-size: massive
drops:
remains: scrap
loot:
@@ -40,3 +19,33 @@ drops:
- item_id: lawjunk
weight: 10
quantity: 2
+combat:
+ kind: combat
+ stats:
+ hp: 94
+ attack: 40
+ strength: 44
+ defense: 44
+ attack_type: crush
+ speed: 5
+ aggressive: true
+ respawn_ticks: 70
+ bonuses:
+ attack_bonus: 35
+ strength_bonus: 35
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 55
+ slash_defense: 55
+ crush_defense: 65
+ science_defense: -25
+ ranged_defense: 40
+ weakness: solar
+ size: massive
+ combat_descriptions:
+ - "fires its rotary cannon at %s"
+ - "smashes %s with a hydraulic fist"
+ - "unleashes a missile salvo at %s"
diff --git a/data/mobs/examples/iron_sentinel.yaml b/data/mobs/examples/iron_sentinel.yaml
index bf8b9b5..48b2dbe 100644
--- a/data/mobs/examples/iron_sentinel.yaml
+++ b/data/mobs/examples/iron_sentinel.yaml
@@ -1,26 +1,10 @@
name: iron sentinel
description: "A massive bipedal automaton forged from pre-regression alloys. Its joints grind with each deliberate step."
-attack: 25
-strength: 30
-defense: 45
-hp: 180
-speed: 6
-aggressive: true
-respawn_ticks: 100
-attack_type: crush
-attack_bonus: 40
-strength_bonus: 35
-stab_defense: 80
-slash_defense: 80
-crush_defense: 70
-science_defense: -30
-ranged_defense: 50
idle_descriptions:
- "stands motionless, servos whining softly"
- "turns its armored head with a mechanical grind"
- "vents steam from exhaust ports"
- "scans the area with a red optical sensor"
-size: large
drops:
loot:
- item_id: scrap
@@ -29,3 +13,28 @@ drops:
- item_id: credits
weight: 60
quantity: 5000
+combat:
+ kind: combat
+ stats:
+ hp: 180
+ attack: 25
+ strength: 30
+ defense: 45
+ attack_type: crush
+ speed: 6
+ aggressive: true
+ respawn_ticks: 100
+ bonuses:
+ attack_bonus: 40
+ strength_bonus: 35
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 80
+ slash_defense: 80
+ crush_defense: 70
+ science_defense: -30
+ ranged_defense: 50
+ size: large
diff --git a/data/mobs/examples/lesser_drone.yaml b/data/mobs/examples/lesser_drone.yaml
index c9e50a5..d9c452d 100644
--- a/data/mobs/examples/lesser_drone.yaml
+++ b/data/mobs/examples/lesser_drone.yaml
@@ -1,28 +1,10 @@
name: lesser drone
description: "A floating metallic drone with a pulsing energy core. Its surface crackles with electric discharge."
-attack: 1
-strength: 1
-defense: 18
-hp: 55
-ranged: 0
-science: 20
-speed: 4
-aggressive: true
-respawn_ticks: 50
-attack_type: science
-attack_bonus: 0
-strength_bonus: 0
-stab_defense: 35
-slash_defense: 35
-crush_defense: 30
-science_defense: 20
-ranged_defense: -10
idle_descriptions:
- "hovers silently, scanning the area"
- "emits a low electronic hum"
- "projects a thin beam of light across the floor"
- "rotates slowly in place"
-size: small
drops:
loot:
- item_id: scrap
@@ -30,3 +12,29 @@ drops:
- item_id: credits
weight: 40
quantity: 300
+combat:
+ kind: combat
+ stats:
+ hp: 55
+ attack: 1
+ strength: 1
+ defense: 18
+ science: 20
+ attack_type: science
+ speed: 4
+ aggressive: true
+ respawn_ticks: 50
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 35
+ slash_defense: 35
+ crush_defense: 30
+ science_defense: 20
+ ranged_defense: -10
+ size: small
diff --git a/data/mobs/examples/man.yaml b/data/mobs/examples/man.yaml
index 8478f41..ec3624c 100644
--- a/data/mobs/examples/man.yaml
+++ b/data/mobs/examples/man.yaml
@@ -1,11 +1,5 @@
name: man
description: "A shabby-looking man loitering in the town square."
-combat_descriptions:
- - "is engaged in a fight to the death with %s"
- - "is getting pummelled by %s"
- - "is locked in combat with %s"
- - "trades blows with %s"
- - "circles warily around %s"
idle_descriptions:
- "scribbles something in a small notebook"
- "gazes skyward at the clouds"
@@ -13,24 +7,11 @@ idle_descriptions:
- "scratches his head thoughtfully"
- "stares off into the distance"
- "adjusts his tunic and stretches"
-attack: 1
-strength: 1
-defense: 1
-hp: 7
-speed: 5
-aggressive: false
-respawn_ticks: 30
-steal_table: man_steal
-steal_level: 1
-steal_xp: 8
-steal_speed: 4
-attack_type: crush
-stab_defense: 0
-slash_defense: 0
-crush_defense: 0
-science_defense: 0
-ranged_defense: 0
-size: small
+steal:
+ table: man_steal
+ level: 1
+ xp: 8
+ speed: 4
drops:
remains: "bones"
loot:
@@ -46,3 +27,34 @@ drops:
weight: 4
- item_id: "grimy_tarromin"
weight: 2
+combat:
+ kind: combat
+ stats:
+ hp: 7
+ attack: 1
+ strength: 1
+ defense: 1
+ attack_type: crush
+ speed: 5
+ aggressive: false
+ respawn_ticks: 30
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ crush_defense: 0
+ ranged_defense: 0
+ science_defense: 0
+ slash_defense: 0
+ stab_defense: 0
+ size: small
+ combat_descriptions:
+ - "is engaged in a fight to the death with %s"
+ - "is getting pummelled by %s"
+ - "is locked in combat with %s"
+ - "trades blows with %s"
+ - "circles warily around %s"
diff --git a/data/mobs/examples/molten_elemental.yaml b/data/mobs/examples/molten_elemental.yaml
index 9c46ccb..3c9b023 100644
--- a/data/mobs/examples/molten_elemental.yaml
+++ b/data/mobs/examples/molten_elemental.yaml
@@ -1,31 +1,10 @@
name: molten elemental
description: "A flowing mass of liquid metal and superheated slag, roughly humanoid. The air around it shimmers with heat and droplets of molten alloy drip to the floor."
-attack: 48
-strength: 52
-defense: 52
-hp: 115
-speed: 5
-aggressive: true
-respawn_ticks: 80
-attack_type: crush
-attack_bonus: 40
-strength_bonus: 42
-stab_defense: 60
-slash_defense: 60
-crush_defense: 70
-science_defense: -30
-ranged_defense: 45
-weakness: hydro
idle_descriptions:
- "bubbles and churns, throwing off sparks"
- "melts a nearby chunk of metal absent-mindedly"
- "pulses with an inner orange glow"
- "drips glowing droplets onto the floor"
-combat_descriptions:
- - "hurls a glob of molten metal at %s"
- - "engulfs %s in a wave of liquid fire"
- - "smashes %s with a superheated limb"
-size: large
drops:
remains: scrap
loot:
@@ -40,3 +19,33 @@ drops:
quantity: 2
- table: herb_table_high
weight: 15
+combat:
+ kind: combat
+ stats:
+ hp: 115
+ attack: 48
+ strength: 52
+ defense: 52
+ attack_type: crush
+ speed: 5
+ aggressive: true
+ respawn_ticks: 80
+ bonuses:
+ attack_bonus: 40
+ strength_bonus: 42
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 60
+ slash_defense: 60
+ crush_defense: 70
+ science_defense: -30
+ ranged_defense: 45
+ weakness: hydro
+ size: large
+ combat_descriptions:
+ - "hurls a glob of molten metal at %s"
+ - "engulfs %s in a wave of liquid fire"
+ - "smashes %s with a superheated limb"
diff --git a/data/mobs/examples/moss_giant.yaml b/data/mobs/examples/moss_giant.yaml
index f19f0a3..9b07a37 100644
--- a/data/mobs/examples/moss_giant.yaml
+++ b/data/mobs/examples/moss_giant.yaml
@@ -1,26 +1,10 @@
name: moss giant
description: "A towering creature covered in moss and vines, its rocky skin dripping with moisture."
-attack: 12
-strength: 14
-defense: 10
-hp: 60
-speed: 7
-aggressive: true
-respawn_ticks: 45
-attack_type: crush
-attack_bonus: 10
-strength_bonus: 12
-stab_defense: 15
-slash_defense: 12
-crush_defense: 18
-science_defense: -5
-ranged_defense: 15
idle_descriptions:
- "surveys its territory with dull eyes"
- "pulls a vine from its shoulder"
- "stamps the ground, sending tremors"
- "scratches its mossy hide"
-size: massive
drops:
remains: bones
loot:
@@ -30,3 +14,28 @@ drops:
- item_id: credits
weight: 50
quantity: 500
+combat:
+ kind: combat
+ stats:
+ hp: 60
+ attack: 12
+ strength: 14
+ defense: 10
+ attack_type: crush
+ speed: 7
+ aggressive: true
+ respawn_ticks: 45
+ bonuses:
+ attack_bonus: 10
+ strength_bonus: 12
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 15
+ slash_defense: 12
+ crush_defense: 18
+ science_defense: -5
+ ranged_defense: 15
+ size: massive
diff --git a/data/mobs/examples/mutant_rat.yaml b/data/mobs/examples/mutant_rat.yaml
index 7836ef9..676b510 100644
--- a/data/mobs/examples/mutant_rat.yaml
+++ b/data/mobs/examples/mutant_rat.yaml
@@ -1,31 +1,10 @@
name: mutant rat
description: "A bloated rodent with glowing green eyes and exposed muscle tissue. Bio-engineering runoff has made it unnaturally aggressive."
-attack: 13
-strength: 13
-defense: 12
-hp: 32
-speed: 4
-aggressive: true
-respawn_ticks: 25
-attack_type: crush
-attack_bonus: 8
-strength_bonus: 6
-stab_defense: 15
-slash_defense: 15
-crush_defense: 10
-science_defense: -10
-ranged_defense: 5
-weakness: bio
idle_descriptions:
- "scurries frantically in circles"
- "gnaws on a rusted pipe"
- "emits a gurgling screech"
- "twitches unnaturally"
-combat_descriptions:
- - "bites %s with glowing teeth"
- - "slashes %s with mutated claws"
- - "lunges at %s with unnatural speed"
-size: small
drops:
remains: bones
loot:
@@ -37,3 +16,33 @@ drops:
- item_id: credits
weight: 10
quantity: 60
+combat:
+ kind: combat
+ stats:
+ hp: 32
+ attack: 13
+ strength: 13
+ defense: 12
+ attack_type: crush
+ speed: 4
+ aggressive: true
+ respawn_ticks: 25
+ bonuses:
+ attack_bonus: 8
+ strength_bonus: 6
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 15
+ slash_defense: 15
+ crush_defense: 10
+ science_defense: -10
+ ranged_defense: 5
+ weakness: bio
+ size: small
+ combat_descriptions:
+ - "bites %s with glowing teeth"
+ - "slashes %s with mutated claws"
+ - "lunges at %s with unnatural speed"
diff --git a/data/mobs/examples/newbie_trainer.yaml b/data/mobs/examples/newbie_trainer.yaml
index 3897dba..eddb0e9 100644
--- a/data/mobs/examples/newbie_trainer.yaml
+++ b/data/mobs/examples/newbie_trainer.yaml
@@ -2,19 +2,6 @@ name: Newbie Trainer
description: "A friendly-looking instructor ready to help new adventurers."
unique: true
protected: true
-attack: 1
-strength: 1
-defense: 1
-hp: 50
-speed: 5
-aggressive: false
-respawn_ticks: 30
-attack_type: crush
-stab_defense: 0
-slash_defense: 0
-crush_defense: 0
-science_defense: 0
-ranged_defense: 0
idle_descriptions:
- "reviews a training manual"
- "adjusts a practice dummy"
@@ -22,4 +9,3 @@ idle_descriptions:
- "offers a friendly nod to passersby"
- "polishes a wooden shield"
- "checks a stopwatch and jots something down"
-size: small
diff --git a/data/mobs/examples/phantom.yaml b/data/mobs/examples/phantom.yaml
index d871b76..fad8167 100644
--- a/data/mobs/examples/phantom.yaml
+++ b/data/mobs/examples/phantom.yaml
@@ -1,24 +1,10 @@
name: phantom
description: "A semi-transparent entity that phases in and out of visible light. Its psychic attacks are devastating to anyone without a spectral visor."
-assassin_level: 45
-damage_without: spectral_visor
-attack: 35
-strength: 30
-defense: 25
-hp: 100
-speed: 3
-aggressive: true
-respawn_ticks: 50
idle_descriptions:
- "flickers between visible and invisible"
- "emits a low, resonant hum"
- "drifts through a wall and back again"
- "stares at you with hollow, glowing eyes"
-combat_descriptions:
- - "blasts %s with a psychic wave"
- - "phases through %s's defenses"
- - "unleashes a spectral shriek at %s"
-size: medium
drops:
remains: ectoplasm
loot:
@@ -30,3 +16,34 @@ drops:
- item_id: credits
weight: 37
quantity: 1000
+combat:
+ kind: combat
+ stats:
+ hp: 100
+ attack: 35
+ strength: 30
+ defense: 25
+ attack_type: crush
+ speed: 3
+ aggressive: true
+ respawn_ticks: 50
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 0
+ slash_defense: 0
+ crush_defense: 0
+ science_defense: 0
+ ranged_defense: 0
+ assassin_level: 45
+ damage_without: spectral_visor
+ size: medium
+ combat_descriptions:
+ - "blasts %s with a psychic wave"
+ - "phases through %s's defenses"
+ - "unleashes a spectral shriek at %s"
diff --git a/data/mobs/examples/plasma_wraith.yaml b/data/mobs/examples/plasma_wraith.yaml
index c4ced2b..7241d9a 100644
--- a/data/mobs/examples/plasma_wraith.yaml
+++ b/data/mobs/examples/plasma_wraith.yaml
@@ -1,32 +1,10 @@
name: plasma wraith
description: "A shimmering entity of contained plasma, vaguely humanoid in shape. It radiates intense heat and hums with barely contained energy."
-attack: 1
-strength: 1
-defense: 22
-hp: 56
-science: 65
-speed: 4
-aggressive: true
-respawn_ticks: 60
-attack_type: science
-attack_bonus: 0
-strength_bonus: 0
-stab_defense: 30
-slash_defense: 30
-crush_defense: 25
-science_defense: 45
-ranged_defense: -10
-weakness: hydro
idle_descriptions:
- "drifts silently, leaving heat shimmer in its wake"
- "pulses with internal light"
- "phases partially through a wall"
- "emits a low frequency hum"
-combat_descriptions:
- - "lashes %s with a whip of plasma"
- - "engulfs %s in a superheated cloud"
- - "discharges a concentrated beam at %s"
-size: medium
drops:
remains: ectoplasm
loot:
@@ -41,3 +19,34 @@ drops:
quantity: 2
- table: gem_table
weight: 15
+combat:
+ kind: combat
+ stats:
+ hp: 56
+ attack: 1
+ strength: 1
+ defense: 22
+ science: 65
+ attack_type: science
+ speed: 4
+ aggressive: true
+ respawn_ticks: 60
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 30
+ slash_defense: 30
+ crush_defense: 25
+ science_defense: 45
+ ranged_defense: -10
+ weakness: hydro
+ size: medium
+ combat_descriptions:
+ - "lashes %s with a whip of plasma"
+ - "engulfs %s in a superheated cloud"
+ - "discharges a concentrated beam at %s"
diff --git a/data/mobs/examples/psionic_entity.yaml b/data/mobs/examples/psionic_entity.yaml
index 1c518bf..1f270e6 100644
--- a/data/mobs/examples/psionic_entity.yaml
+++ b/data/mobs/examples/psionic_entity.yaml
@@ -1,31 +1,10 @@
name: psionic entity
description: "A barely visible distortion in the air, only detectable by the pressure it exerts on your mind. When it focuses, you see a shimmering outline of something vast and ancient."
-attack: 1
-strength: 1
-defense: 42
-hp: 128
-science: 97
-speed: 4
-aggressive: true
-respawn_ticks: 100
-attack_type: science
-attack_bonus: 0
-strength_bonus: 0
-stab_defense: 50
-slash_defense: 50
-crush_defense: 45
-science_defense: 70
-ranged_defense: -20
idle_descriptions:
- "probes the edges of your consciousness"
- "flickers between visible and invisible states"
- "emits a subsonic pulse you feel in your teeth"
- "momentarily shows you visions of another dimension"
-combat_descriptions:
- - "assaults %s's mind with psionic force"
- - "tears at %s's perception of reality"
- - "unleashes a devastating mental blast at %s"
-size: large
drops:
remains: ectoplasm
loot:
@@ -44,3 +23,33 @@ drops:
weight: 5
- table: herb_table_high
weight: 5
+combat:
+ kind: combat
+ stats:
+ hp: 128
+ attack: 1
+ strength: 1
+ defense: 42
+ science: 97
+ attack_type: science
+ speed: 4
+ aggressive: true
+ respawn_ticks: 100
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 50
+ slash_defense: 50
+ crush_defense: 45
+ science_defense: 70
+ ranged_defense: -20
+ size: large
+ combat_descriptions:
+ - "assaults %s's mind with psionic force"
+ - "tears at %s's perception of reality"
+ - "unleashes a devastating mental blast at %s"
diff --git a/data/mobs/examples/rat.yaml b/data/mobs/examples/rat.yaml
index 4265674..7a92026 100644
--- a/data/mobs/examples/rat.yaml
+++ b/data/mobs/examples/rat.yaml
@@ -1,22 +1,33 @@
name: rat
description: "A large, mangy rat with beady red eyes."
-attack: 1
-strength: 1
-defense: 1
-hp: 2
-speed: 4
-aggressive: false
-respawn_ticks: 20
-attack_type: crush
-stab_defense: 0
-slash_defense: 0
-crush_defense: 0
-science_defense: 0
-ranged_defense: 0
idle_descriptions:
- "sniffs around the ground"
- "nibbles on something"
- "scurries in circles"
-size: small
drops:
remains: bones
+combat:
+ kind: combat
+ stats:
+ hp: 2
+ attack: 1
+ strength: 1
+ defense: 1
+ attack_type: crush
+ speed: 4
+ aggressive: false
+ respawn_ticks: 20
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ crush_defense: 0
+ ranged_defense: 0
+ science_defense: 0
+ slash_defense: 0
+ stab_defense: 0
+ size: small
diff --git a/data/mobs/examples/sawmill_operator.yaml b/data/mobs/examples/sawmill_operator.yaml
index 366cfe3..0fc423d 100644
--- a/data/mobs/examples/sawmill_operator.yaml
+++ b/data/mobs/examples/sawmill_operator.yaml
@@ -1,6 +1,6 @@
-color: "BA"
description: A burly worker in a thick apron, covered in sawdust. He operates the industrial sawmill.
-idle: The sawmill operator wipes sawdust from his goggles.
+idle_descriptions:
+ - wipes sawdust from his goggles
name: sawmill operator
protected: true
talk:
@@ -30,8 +30,6 @@ talk:
- goto: goodbye
text: No thanks.
process:
- action:
- sawmill: true
messages:
- ""
start:
@@ -51,4 +49,3 @@ talk:
- goto: goodbye
text: Nothing for now.
unique: true
-size: small
diff --git a/data/mobs/examples/scrap_bot.yaml b/data/mobs/examples/scrap_bot.yaml
index a8b34d8..44d92aa 100644
--- a/data/mobs/examples/scrap_bot.yaml
+++ b/data/mobs/examples/scrap_bot.yaml
@@ -1,30 +1,10 @@
name: scrap bot
description: "A malfunctioning maintenance robot that has gone rogue. Its chassis is covered in dents and rust, and one optical sensor flickers erratically."
-attack: 15
-strength: 15
-defense: 14
-hp: 30
-speed: 5
-aggressive: true
-respawn_ticks: 30
-attack_type: crush
-attack_bonus: 10
-strength_bonus: 8
-stab_defense: 20
-slash_defense: 15
-crush_defense: 25
-science_defense: -5
-ranged_defense: 10
idle_descriptions:
- "beeps erratically and twitches"
- "bumps into a wall and reverses"
- "emits a burst of static"
- "scans the floor with a flickering beam"
-combat_descriptions:
- - "rams %s with its chassis"
- - "swings a broken manipulator arm at %s"
- - "discharges a spark at %s"
-size: medium
drops:
remains: scrap
loot:
@@ -37,3 +17,32 @@ drops:
- item_id: credits
weight: 10
quantity: 100
+combat:
+ kind: combat
+ stats:
+ hp: 30
+ attack: 15
+ strength: 15
+ defense: 14
+ attack_type: crush
+ speed: 5
+ aggressive: true
+ respawn_ticks: 30
+ bonuses:
+ attack_bonus: 10
+ strength_bonus: 8
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 20
+ slash_defense: 15
+ crush_defense: 25
+ science_defense: -5
+ ranged_defense: 10
+ size: medium
+ combat_descriptions:
+ - "rams %s with its chassis"
+ - "swings a broken manipulator arm at %s"
+ - "discharges a spark at %s"
diff --git a/data/mobs/examples/security_turret.yaml b/data/mobs/examples/security_turret.yaml
index 9929106..05fce67 100644
--- a/data/mobs/examples/security_turret.yaml
+++ b/data/mobs/examples/security_turret.yaml
@@ -1,32 +1,10 @@
name: security turret
description: "A ceiling-mounted auto-turret with twin barrels and a red targeting laser. It tracks you with mechanical precision."
-attack: 1
-strength: 1
-defense: 16
-hp: 44
-ranged: 34
-speed: 5
-aggressive: true
-respawn_ticks: 40
-attack_type: ranged
-attack_bonus: 0
-strength_bonus: 0
-stab_defense: 30
-slash_defense: 20
-crush_defense: 40
-science_defense: -20
-ranged_defense: 15
-weakness: solar
idle_descriptions:
- "pans the room with a targeting laser"
- "emits a rhythmic clicking sound"
- "calibrates its targeting sensors"
- "beeps a warning tone"
-combat_descriptions:
- - "fires twin bolts at %s"
- - "unleashes a burst of rounds at %s"
- - "locks onto %s and opens fire"
-size: small
drops:
remains: scrap
loot:
@@ -39,3 +17,34 @@ drops:
- item_id: credits
weight: 10
quantity: 250
+combat:
+ kind: combat
+ stats:
+ hp: 44
+ attack: 1
+ strength: 1
+ defense: 16
+ ranged: 34
+ attack_type: ranged
+ speed: 5
+ aggressive: true
+ respawn_ticks: 40
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 30
+ slash_defense: 20
+ crush_defense: 40
+ science_defense: -20
+ ranged_defense: 15
+ weakness: solar
+ size: small
+ combat_descriptions:
+ - "fires twin bolts at %s"
+ - "unleashes a burst of rounds at %s"
+ - "locks onto %s and opens fire"
diff --git a/data/mobs/examples/skeleton.yaml b/data/mobs/examples/skeleton.yaml
index ba82afc..2431215 100644
--- a/data/mobs/examples/skeleton.yaml
+++ b/data/mobs/examples/skeleton.yaml
@@ -1,25 +1,9 @@
name: skeleton
description: "An animated pile of bones, held together by dark energy."
-attack: 8
-strength: 6
-defense: 8
-hp: 22
-speed: 5
-aggressive: true
-respawn_ticks: 30
-attack_type: stab
-attack_bonus: 6
-strength_bonus: 4
-stab_defense: 10
-slash_defense: 18
-crush_defense: -5
-science_defense: -8
-ranged_defense: 10
idle_descriptions:
- "rattles ominously"
- "clicks its jaw open and shut"
- "stares with empty eye sockets"
-size: medium
drops:
remains: bones
loot:
@@ -29,3 +13,28 @@ drops:
- item_id: credits
weight: 30
quantity: 100
+combat:
+ kind: combat
+ stats:
+ hp: 22
+ attack: 8
+ strength: 6
+ defense: 8
+ attack_type: stab
+ speed: 5
+ aggressive: true
+ respawn_ticks: 30
+ bonuses:
+ attack_bonus: 6
+ strength_bonus: 4
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 10
+ slash_defense: 18
+ crush_defense: -5
+ science_defense: -8
+ ranged_defense: 10
+ size: medium
diff --git a/data/mobs/examples/slug.yaml b/data/mobs/examples/slug.yaml
index 64082ec..0429ee1 100644
--- a/data/mobs/examples/slug.yaml
+++ b/data/mobs/examples/slug.yaml
@@ -1,27 +1,44 @@
name: slug
description: "A bloated, translucent slug the size of a dog. Its skin glistens with toxic mucus. It cannot be killed by conventional means — only salt can destroy it."
-assassin_level: 1
-finishing_blow: salt
-attack: 3
-strength: 3
-defense: 1
-hp: 15
-speed: 6
-aggressive: false
-respawn_ticks: 25
idle_descriptions:
- "oozes along the floor leaving a slimy trail"
- "contracts and expands rhythmically"
- "extends its eyestalks toward you"
- "secretes a glob of toxic mucus"
-combat_descriptions:
- - "lunges slimily at %s"
- - "sprays mucus toward %s"
- - "writhes in combat with %s"
-size: small
drops:
remains: slug_mucus
loot:
- item_id: credits
weight: 100
quantity: 15
+combat:
+ kind: combat
+ stats:
+ hp: 15
+ attack: 3
+ strength: 3
+ defense: 1
+ attack_type: crush
+ speed: 6
+ aggressive: false
+ respawn_ticks: 25
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 0
+ slash_defense: 0
+ crush_defense: 0
+ science_defense: 0
+ ranged_defense: 0
+ assassin_level: 1
+ finishing_blow: salt
+ size: small
+ combat_descriptions:
+ - "lunges slimily at %s"
+ - "sprays mucus toward %s"
+ - "writhes in combat with %s"
diff --git a/data/mobs/examples/solar_panel_frame.yaml b/data/mobs/examples/solar_panel_frame.yaml
index 90269f2..2685db0 100644
--- a/data/mobs/examples/solar_panel_frame.yaml
+++ b/data/mobs/examples/solar_panel_frame.yaml
@@ -1,25 +1,13 @@
name: solar panel frame
description: "A half-assembled photovoltaic array on a steel frame. Panels, brackets and cabling are laid out, waiting to be fitted. This is work, not a fight — fix the panels into place to complete the array."
-kind: task
-verb: assemble
-progress_noun: assembly
-complete_message: "You bolt the final panel into place and the solar array hums to life!"
-hp: 40
-defense: 10
-speed: 5
-aggressive: false
-respawn_ticks: 40
-attack_type: crush
-crush_defense: 0
-stab_defense: 40
-slash_defense: 40
-ranged_defense: 10
-science_defense: 10
+task:
+ verb: assemble
+ progress_noun: assembly
+ complete_message: "You bolt the final panel into place and the solar array hums to life!"
idle_descriptions:
- "stands half-assembled, panels waiting to be fitted"
- "has loose cabling dangling from an open junction box"
- "catches the light on its few mounted panels"
-size: medium
drops:
loot:
- item_id: credits
@@ -31,3 +19,26 @@ drops:
- item_id: coal
weight: 5
quantity: 1
+combat:
+ kind: task
+ stats:
+ hp: 40
+ defense: 10
+ attack_type: crush
+ speed: 5
+ aggressive: false
+ respawn_ticks: 40
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 40
+ slash_defense: 40
+ crush_defense: 0
+ science_defense: 10
+ ranged_defense: 10
+ size: medium
diff --git a/data/mobs/examples/tanner.yaml b/data/mobs/examples/tanner.yaml
index 4c1f38b..99d64f1 100644
--- a/data/mobs/examples/tanner.yaml
+++ b/data/mobs/examples/tanner.yaml
@@ -1,24 +1,12 @@
-aggressive: false
-attack: 1
-attack_type: crush
-crush_defense: 0
-defense: 1
+name: Tanner
description: A weathered craftsman with stained hands and a leather apron.
-hp: 50
+protected: true
+unique: true
idle_descriptions:
- scrapes at a piece of hide
- examines a stack of leathers
- sharpens a tanning knife
- wipes sweat from his brow
-name: Tanner
-protected: true
-ranged_defense: 0
-respawn_ticks: 30
-science_defense: 0
-slash_defense: 0
-speed: 5
-stab_defense: 0
-strength: 1
talk:
nodes:
start:
@@ -64,5 +52,3 @@ talk:
goto: start
text: '"Tan another."'
- text: '"Thanks."'
-unique: true
-size: small
diff --git a/data/mobs/examples/titan_sentinel.yaml b/data/mobs/examples/titan_sentinel.yaml
index 32ddcc2..6fb36d3 100644
--- a/data/mobs/examples/titan_sentinel.yaml
+++ b/data/mobs/examples/titan_sentinel.yaml
@@ -1,31 +1,10 @@
name: titan sentinel
description: "A colossal automaton, the bigger brother of the iron sentinel. Its armor is reinforced adamantite alloy and its optics burn with crimson fire."
-attack: 50
-strength: 52
-defense: 56
-hp: 132
-speed: 5
-aggressive: true
-respawn_ticks: 120
-attack_type: crush
-attack_bonus: 48
-strength_bonus: 45
-stab_defense: 90
-slash_defense: 90
-crush_defense: 80
-science_defense: -35
-ranged_defense: 60
-weakness: solar
idle_descriptions:
- "stands motionless, gyros humming"
- "scans the area with a sweeping crimson beam"
- "vents superheated exhaust"
- "rotates its armored torso with a deep grinding sound"
-combat_descriptions:
- - "smashes %s with a titan-grade fist"
- - "unleashes a devastating plasma barrage at %s"
- - "drives %s into the ground with overwhelming force"
-size: massive
drops:
loot:
- item_id: scrap
@@ -39,3 +18,33 @@ drops:
- item_id: deathjunk
weight: 5
quantity: 5
+combat:
+ kind: combat
+ stats:
+ hp: 132
+ attack: 50
+ strength: 52
+ defense: 56
+ attack_type: crush
+ speed: 5
+ aggressive: true
+ respawn_ticks: 120
+ bonuses:
+ attack_bonus: 48
+ strength_bonus: 45
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 90
+ slash_defense: 90
+ crush_defense: 80
+ science_defense: -35
+ ranged_defense: 60
+ weakness: solar
+ size: massive
+ combat_descriptions:
+ - "smashes %s with a titan-grade fist"
+ - "unleashes a devastating plasma barrage at %s"
+ - "drives %s into the ground with overwhelming force"
diff --git a/data/mobs/examples/veteran_merc.yaml b/data/mobs/examples/veteran_merc.yaml
index 88238b6..71e3826 100644
--- a/data/mobs/examples/veteran_merc.yaml
+++ b/data/mobs/examples/veteran_merc.yaml
@@ -1,31 +1,10 @@
name: veteran merc
description: "A battle-hardened soldier with a high-powered rifle and tactical armor covered in campaign patches. Their cybernetic eye locks onto you instantly."
-attack: 1
-strength: 1
-defense: 40
-hp: 93
-ranged: 79
-speed: 5
-aggressive: true
-respawn_ticks: 65
-attack_type: ranged
-attack_bonus: 0
-strength_bonus: 0
-stab_defense: 40
-slash_defense: 40
-crush_defense: 35
-science_defense: 20
-ranged_defense: 55
idle_descriptions:
- "checks their rifle's ammunition counter"
- "adjusts their tactical vest"
- "scans the area through their scope"
- "spits and mutters a war story"
-combat_descriptions:
- - "fires a high-caliber round at %s"
- - "puts %s in their crosshairs and squeezes the trigger"
- - "unleashes suppressive fire at %s"
-size: medium
drops:
remains: bones
loot:
@@ -40,3 +19,33 @@ drops:
quantity: 2
- table: herb_table_mid
weight: 15
+combat:
+ kind: combat
+ stats:
+ hp: 93
+ attack: 1
+ strength: 1
+ defense: 40
+ ranged: 79
+ attack_type: ranged
+ speed: 5
+ aggressive: true
+ respawn_ticks: 65
+ bonuses:
+ attack_bonus: 0
+ strength_bonus: 0
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 40
+ slash_defense: 40
+ crush_defense: 35
+ science_defense: 20
+ ranged_defense: 55
+ size: medium
+ combat_descriptions:
+ - "fires a high-caliber round at %s"
+ - "puts %s in their crosshairs and squeezes the trigger"
+ - "unleashes suppressive fire at %s"
diff --git a/data/mobs/examples/void_reaper.yaml b/data/mobs/examples/void_reaper.yaml
index e54d776..bf85470 100644
--- a/data/mobs/examples/void_reaper.yaml
+++ b/data/mobs/examples/void_reaper.yaml
@@ -1,33 +1,10 @@
name: void reaper
description: "A shadowy figure that seems to absorb light itself. Its form shifts between a hooded specter and an armored construct. A scythe of dark energy flickers in its grasp."
-attack: 62
-strength: 68
-defense: 72
-hp: 170
-speed: 3
-aggressive: true
-respawn_ticks: 200
-attack_type: slash
-attack_bonus: 60
-strength_bonus: 60
-stab_defense: 100
-slash_defense: 110
-crush_defense: 90
-science_defense: -45
-ranged_defense: 75
-weakness: bio
-assassin_level: 80
-finishing_blow: lawjunk
idle_descriptions:
- "flickers in and out of existence"
- "draws the warmth from the surrounding air"
- "whispers in a language that predates humanity"
- "reaches out with shadowy tendrils"
-combat_descriptions:
- - "swings its void scythe at %s"
- - "drains the life force from %s"
- - "envelops %s in absolute darkness"
-size: massive
drops:
remains: ectoplasm
loot:
@@ -50,3 +27,35 @@ drops:
quantity: 5
- table: herb_table_high
weight: 10
+combat:
+ kind: combat
+ stats:
+ hp: 170
+ attack: 62
+ strength: 68
+ defense: 72
+ attack_type: slash
+ speed: 3
+ aggressive: true
+ respawn_ticks: 200
+ bonuses:
+ attack_bonus: 60
+ strength_bonus: 60
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 100
+ slash_defense: 110
+ crush_defense: 90
+ science_defense: -45
+ ranged_defense: 75
+ weakness: bio
+ assassin_level: 80
+ finishing_blow: lawjunk
+ size: massive
+ combat_descriptions:
+ - "swings its void scythe at %s"
+ - "drains the life force from %s"
+ - "envelops %s in absolute darkness"
diff --git a/data/mobs/examples/war_drone.yaml b/data/mobs/examples/war_drone.yaml
index 587ad09..7255a45 100644
--- a/data/mobs/examples/war_drone.yaml
+++ b/data/mobs/examples/war_drone.yaml
@@ -1,31 +1,10 @@
name: war drone
description: "An upgraded combat drone with reinforced plating and a heavier weapons array. Its targeting systems whir as it locks onto you."
-attack: 25
-strength: 28
-defense: 25
-hp: 65
-speed: 4
-aggressive: true
-respawn_ticks: 50
-attack_type: slash
-attack_bonus: 20
-strength_bonus: 18
-stab_defense: 35
-slash_defense: 30
-crush_defense: 40
-science_defense: -10
-ranged_defense: 20
-weakness: solar
idle_descriptions:
- "hovers aggressively, weapons armed"
- "emits a low, threatening hum"
- "paints a targeting reticle on the wall"
- "cycles through weapon modes with a click"
-combat_descriptions:
- - "fires a plasma bolt at %s"
- - "slashes at %s with a rotary blade"
- - "launches a concussion grenade at %s"
-size: medium
drops:
remains: circuit_board
loot:
@@ -40,3 +19,33 @@ drops:
quantity: 500
- table: gem_table
weight: 10
+combat:
+ kind: combat
+ stats:
+ hp: 65
+ attack: 25
+ strength: 28
+ defense: 25
+ attack_type: slash
+ speed: 4
+ aggressive: true
+ respawn_ticks: 50
+ bonuses:
+ attack_bonus: 20
+ strength_bonus: 18
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 35
+ slash_defense: 30
+ crush_defense: 40
+ science_defense: -10
+ ranged_defense: 20
+ weakness: solar
+ size: medium
+ combat_descriptions:
+ - "fires a plasma bolt at %s"
+ - "slashes at %s with a rotary blade"
+ - "launches a concussion grenade at %s"
diff --git a/data/mobs/examples/weapons_smith.yaml b/data/mobs/examples/weapons_smith.yaml
index b12a543..359f9e3 100644
--- a/data/mobs/examples/weapons_smith.yaml
+++ b/data/mobs/examples/weapons_smith.yaml
@@ -1,24 +1,12 @@
-aggressive: false
-attack: 1
-attack_type: crush
-crush_defense: 0
-defense: 1
+name: Weaponsmith
description: A burly smith with soot-stained hands and a heavy leather apron, standing proudly by the forge.
-hp: 80
+protected: true
+unique: true
idle_descriptions:
- hammers at a glowing blade on the anvil
- wipes soot from his brow
- inspects a finished sword
- tends to the furnace fire
-name: Weaponsmith
-protected: true
-ranged_defense: 0
-respawn_ticks: 30
-science_defense: 0
-slash_defense: 0
-speed: 5
-stab_defense: 0
-strength: 1
shop:
message: The Smithy — buy or sell weapons and armor.
buys_anything: false
@@ -46,5 +34,3 @@ talk:
- '"Welcome to the Smithy! Type ''list'' to see my wares."'
options:
- text: '"Nothing right now."'
-unique: true
-size: small
diff --git a/data/mobs/examples/zombie.yaml b/data/mobs/examples/zombie.yaml
index f5989e0..77bb5ed 100644
--- a/data/mobs/examples/zombie.yaml
+++ b/data/mobs/examples/zombie.yaml
@@ -1,27 +1,10 @@
name: zombie
description: "A shambling corpse reanimated by residual asteroid radiation."
-attack: 10
-strength: 8
-defense: 8
-hp: 30
-speed: 6
-aggressive: true
-respawn_ticks: 35
-attack_type: crush
-attack_bonus: 4
-strength_bonus: 6
-stab_defense: 8
-slash_defense: 20
-crush_defense: -8
-science_defense: -15
-ranged_defense: 8
-weakness: solar
idle_descriptions:
- "groans and shuffles forward"
- "reaches out with decaying arms"
- "stumbles and catches itself"
- "stares blankly ahead"
-size: medium
drops:
remains: bones
loot:
@@ -31,3 +14,29 @@ drops:
- item_id: credits
weight: 40
quantity: 200
+combat:
+ kind: combat
+ stats:
+ hp: 30
+ attack: 10
+ strength: 8
+ defense: 8
+ attack_type: crush
+ speed: 6
+ aggressive: true
+ respawn_ticks: 35
+ bonuses:
+ attack_bonus: 4
+ strength_bonus: 6
+ science_bonus: 0
+ science_percent_bonus: 0
+ ranged_bonus: 0
+ ranged_strength_bonus: 0
+ defenses:
+ stab_defense: 8
+ slash_defense: 20
+ crush_defense: -8
+ science_defense: -15
+ ranged_defense: 8
+ weakness: solar
+ size: medium
diff --git a/data/mobs/flight_attendant_copy.yaml b/data/mobs/flight_attendant_copy.yaml
index abe3d56..a495732 100644
--- a/data/mobs/flight_attendant_copy.yaml
+++ b/data/mobs/flight_attendant_copy.yaml
@@ -1,29 +1,12 @@
-aggressive: false
-attack: 0
-bonuses:
- attack_bonus: 0
- attack_type: stab
- strength_bonus: 0
-defense: 0
-defenses:
- crush_defense: 0
- ranged_defense: 0
- science_defense: 0
- slash_defense: 0
- stab_defense: 0
+name: flight attendant
description: A smiling flight attendant in a crisp uniform, ready to assist passengers.
-hp: 0
-id: flight_attendant_copy
+unique: false
+protected: true
idle_descriptions:
- adjusts her name badge
- smiles politely at you
-kind: combat
-name: Credit Checker!
-protected: true
-ranged: 0
-respawn_ticks: 0
-science: 0
shop:
+ message: SHOP SHOP
buy_percentage: 0
buys_anything: true
change_percentage: 0
@@ -31,9 +14,6 @@ shop:
- item_id: bronze_pickaxe
restock_ticks: 0
stock: 5
- message: SHOP SHOP
-speed: 0
-strength: 0
talk:
nodes:
start:
@@ -41,4 +21,3 @@ talk:
- goto: ""
text: None!
- text: None
-unique: false
diff --git a/data/rooms/intro/1001.yaml b/data/rooms/intro/1001.yaml
index 66e8b4a..1ea5301 100644
--- a/data/rooms/intro/1001.yaml
+++ b/data/rooms/intro/1001.yaml
@@ -36,7 +36,6 @@ objects:
give_item: ""
heal: 0
reputation_cost: 0
- sawmill: false
set_flags: {}
set_player_flags:
1001_look_sign: true
diff --git a/internal/admin/static/mobeditor.js b/internal/admin/static/mobeditor.js
index 9928adb..3d6f4d4 100644
--- a/internal/admin/static/mobeditor.js
+++ b/internal/admin/static/mobeditor.js
@@ -12,66 +12,60 @@ var MOB_SECTIONS = [
['description', 'Description', 'textarea', 'A lanky man in a wrinkled grey uniform.'],
['unique', 'Unique', 'checkbox'],
['protected', 'Protected', 'checkbox'],
- ['aggressive', 'Aggressive', 'checkbox'],
- ['kind', 'Kind', 'select', 'combat|task'],
- ['respawn_ticks', 'Respawn Ticks', 'number', '', 'narrow'],
],
inline: [
{label:'Idle Descriptions', key:'idle_descriptions', type:'tags'},
- {label:'Combat Descriptions', key:'combat_descriptions', type:'tags'},
]
},
{
- id: 'combat', label: 'Combat Stats',
- detect: function(d) { return d.attack || d.strength || d.defense || d.hp; },
+ id: 'combat', label: 'Combat Stats', path: 'combat',
+ detect: function(d) { return d.combat; },
fields: [
- ['attack', 'Attack', 'number', '', 'narrow'],
- ['strength', 'Strength', 'number', '', 'narrow'],
- ['defense', 'Defense', 'number', '', 'narrow'],
- ['hp', 'HP', 'number', '', 'narrow'],
- ['ranged', 'Ranged', 'number', '', 'narrow'],
- ['science', 'Science', 'number', '', 'narrow'],
- ['speed', 'Speed', 'number', '', 'narrow'],
+ ['kind', 'Kind', 'select', 'combat|task'],
+ ['stats.hp', 'HP', 'number', '', 'narrow'],
+ ['stats.attack', 'Attack', 'number', '', 'narrow'],
+ ['stats.strength', 'Strength', 'number', '', 'narrow'],
+ ['stats.defense', 'Defense', 'number', '', 'narrow'],
+ ['stats.ranged', 'Ranged', 'number', '', 'narrow'],
+ ['stats.science', 'Science', 'number', '', 'narrow'],
+ ['stats.attack_type', 'Atk Type', 'select', 'stab|slash|crush|ranged|science'],
+ ['stats.speed', 'Speed', 'number', '', 'narrow'],
+ ['stats.aggressive', 'Aggressive', 'checkbox'],
+ ['stats.respawn_ticks', 'Respawn Ticks', 'number', '', 'narrow'],
+ ['stats.bonuses.attack_bonus', 'Atk Bonus', 'number', '', 'narrow'],
+ ['stats.bonuses.strength_bonus', 'Str Bonus', 'number', '', 'narrow'],
+ ['stats.bonuses.science_bonus', 'Sci Bonus', 'number', '', 'narrow'],
+ ['stats.bonuses.science_percent_bonus', 'Sci % Bonus', 'number', '', 'narrow'],
+ ['stats.bonuses.ranged_bonus', 'Rng Bonus', 'number', '', 'narrow'],
+ ['stats.bonuses.ranged_strength_bonus', 'Rng Str Bonus', 'number', '', 'narrow'],
+ ['stats.defenses.stab_defense', 'Stab Def', 'number', '', 'narrow'],
+ ['stats.defenses.slash_defense', 'Slash Def', 'number', '', 'narrow'],
+ ['stats.defenses.crush_defense', 'Crush Def', 'number', '', 'narrow'],
+ ['stats.defenses.science_defense', 'Sci Def', 'number', '', 'narrow'],
+ ['stats.defenses.ranged_defense', 'Rng Def', 'number', '', 'narrow'],
+ ['stats.defenses.weakness', 'Weakness', 'text'],
+ ['assassin_level', 'Assassin Lvl', 'number', '', 'narrow'],
+ ['finishing_blow', 'Finishing Blow', 'search', '', '', null, 'items'],
+ ['damage_without', 'Damage Without', 'search', '', '', null, 'items'],
+ ['size', 'Size', 'text'],
],
inline: [
- {label:'Bonuses', path:'bonuses', fields:[
- ['attack_bonus', 'Atk Bonus', 'number', '', 'narrow'],
- ['strength_bonus', 'Str Bonus', 'number', '', 'narrow'],
- ['attack_type', 'Atk Type', 'select', 'stab|slash|crush|ranged|science'],
- ]},
- {label:'Defenses', path:'defenses', fields:[
- ['stab_defense', 'Stab', 'number', '', 'narrow'],
- ['slash_defense', 'Slash', 'number', '', 'narrow'],
- ['crush_defense', 'Crush', 'number', '', 'narrow'],
- ['science_defense', 'Science', 'number', '', 'narrow'],
- ['ranged_defense', 'Ranged', 'number', '', 'narrow'],
- ['weakness', 'Weakness', 'text'],
- ]},
- ]
- },
- {
- id: 'steal', label: 'Steal',
- detect: function(d) { return d.steal_table || d.steal_level || d.steal_speed || d.steal_xp; },
- fields: [
- ['steal_table', 'Table ID', 'search', '', '', null, 'drops'],
- ['steal_level', 'Level', 'number', '', 'narrow'],
- ['steal_xp', 'XP', 'number', '', 'narrow'],
- ['steal_speed', 'Speed', 'number', '', 'narrow'],
+ {label:'Combat Descriptions', key:'combat_descriptions', type:'tags'},
]
},
{
- id: 'assassin', label: 'Assassin',
- detect: function(d) { return d.assassin_level || d.finishing_blow || d.damage_without || d.size; },
+ id: 'steal', label: 'Steal', path: 'steal',
+ detect: function(d) { return d.steal; },
fields: [
- ['assassin_level', 'Level', 'number', '', 'narrow'],
- ['finishing_blow', 'Finishing Blow', 'text'],
- ['damage_without', 'Damage Without', 'text'],
- ['size', 'Size', 'text'],
+ ['table', 'Table ID', 'search', '', '', null, 'drops'],
+ ['level', 'Level', 'number', '', 'narrow'],
+ ['xp', 'XP', 'number', '', 'narrow'],
+ ['speed', 'Speed', 'number', '', 'narrow'],
]
},
{
- id: 'task', label: 'Task',
- detect: function(d) { return d.kind === 'task'; },
+ id: 'task', label: 'Task', path: 'task',
+ detect: function(d) { return d.task; },
fields: [
['verb', 'Verb', 'text', 'work'],
['progress_noun', 'Progress Noun', 'text', 'construction'],
@@ -140,8 +134,6 @@ function loadMob(id) {
renderList('');
API.get('/api/mobs/' + encodeURIComponent(id)).then(function(data) {
mobData = data;
- // buys_anything defaults to true (Go treats absent as true); reflect that in
- // the checkbox unless the shop explicitly opted out with false.
if (mobData.shop && mobData.shop.buys_anything === undefined) {
mobData.shop.buys_anything = true;
}
@@ -193,7 +185,6 @@ function renderMobEditor(id, data) {
$('#editorMain').innerHTML = html;
ced_setupSearchFields();
- setupMobKindChange();
setupMobProtectedToggle();
MOB_SECTIONS.forEach(function(sec) {
@@ -225,6 +216,8 @@ function renderMobCard(sec, data) {
if (sec.id === 'core') {
h += renderMobCoreCard(data);
+ } else if (sec.id === 'combat') {
+ h += renderMobCombatCard(data);
} else if (sec.subtables) {
h += '<div class="obj-card-grid">';
sec.fields.forEach(function(f) {
@@ -232,23 +225,6 @@ function renderMobCard(sec, data) {
});
h += '</div>';
- if (sec.inline) {
- sec.inline.forEach(function(il) {
- if (il.type === 'tags') {
- h += ced_renderTags(sec, il, data);
- } else {
- h += '<div class="obj-inline-group">';
- h += '<span class="obj-inline-label">' + esc(il.label) + '</span>';
- h += '<div class="obj-card-grid" style="margin-top:4px">';
- il.fields.forEach(function(f) {
- h += renderMobField(sec, f, data, -1, il.path);
- });
- h += '</div>';
- h += '</div>';
- }
- });
- }
-
sec.subtables.forEach(function(st) {
h += renderMobSubtable(sec, st, data);
});
@@ -263,15 +239,6 @@ function renderMobCard(sec, data) {
sec.inline.forEach(function(il) {
if (il.type === 'tags') {
h += ced_renderTags(sec, il, data);
- } else {
- h += '<div class="obj-inline-group">';
- h += '<span class="obj-inline-label">' + esc(il.label) + '</span>';
- h += '<div class="obj-card-grid" style="margin-top:4px">';
- il.fields.forEach(function(f) {
- h += renderMobField(sec, f, data, -1, il.path);
- });
- h += '</div>';
- h += '</div>';
}
});
}
@@ -297,35 +264,81 @@ function renderMobCoreCard(data) {
sec.inline.forEach(function(il) {
h += ced_renderTags(sec, il, data);
});
- // Behavior fields (merged into Core).
h += '<div class="obj-card-grid" style="margin-top:6px">';
h += renderMobField(sec, byKey['unique'], data, -1);
h += renderMobField(sec, byKey['protected'], data, -1);
- h += renderMobField(sec, byKey['aggressive'], data, -1);
h += '</div>';
- h += '<div class="obj-card-grid" style="margin-top:6px">';
+ return h;
+}
+
+function renderMobCombatCard(data) {
+ var sec = MOB_SECTIONS.find(function(s) { return s.id === 'combat'; });
+ if (!sec) return '';
+ var byKey = {};
+ sec.fields.forEach(function(f) { byKey[f[0]] = f; });
+ var h = '<div class="obj-card-grid" style="margin-top:6px">';
h += renderMobField(sec, byKey['kind'], data, -1);
- h += renderMobField(sec, byKey['respawn_ticks'], data, -1);
h += '</div>';
+
+ h += '<div class="obj-inline-group">';
+ h += '<span class="obj-inline-label">Stats</span>';
+ h += '<div class="obj-card-grid" style="margin-top:4px">';
+ var statKeys = ['stats.hp','stats.attack','stats.strength','stats.defense','stats.ranged','stats.science'];
+ statKeys.forEach(function(k) { h += renderMobField(sec, byKey[k], data, -1); });
+ h += '</div>';
+ h += '<div class="obj-card-grid" style="margin-top:4px">';
+ var statKeys2 = ['stats.attack_type','stats.speed','stats.aggressive','stats.respawn_ticks'];
+ statKeys2.forEach(function(k) { h += renderMobField(sec, byKey[k], data, -1); });
+ h += '</div>';
+ h += '</div>';
+
+ h += '<div class="obj-inline-group">';
+ h += '<span class="obj-inline-label">Bonuses</span>';
+ h += '<div class="obj-card-grid" style="margin-top:4px">';
+ var bonusKeys = ['stats.bonuses.attack_bonus','stats.bonuses.strength_bonus','stats.bonuses.science_bonus',
+ 'stats.bonuses.science_percent_bonus','stats.bonuses.ranged_bonus','stats.bonuses.ranged_strength_bonus'];
+ bonusKeys.forEach(function(k) { h += renderMobField(sec, byKey[k], data, -1); });
+ h += '</div>';
+ h += '</div>';
+
+ h += '<div class="obj-inline-group">';
+ h += '<span class="obj-inline-label">Defenses</span>';
+ h += '<div class="obj-card-grid" style="margin-top:4px">';
+ var defKeys = ['stats.defenses.stab_defense','stats.defenses.slash_defense','stats.defenses.crush_defense',
+ 'stats.defenses.science_defense','stats.defenses.ranged_defense'];
+ defKeys.forEach(function(k) { h += renderMobField(sec, byKey[k], data, -1); });
+ h += '</div>';
+ h += '<div class="obj-card-grid" style="margin-top:4px">';
+ h += renderMobField(sec, byKey['stats.defenses.weakness'], data, -1);
+ h += '</div>';
+ h += '</div>';
+
+ h += '<div class="obj-card-grid" style="margin-top:6px">';
+ h += renderMobField(sec, byKey['assassin_level'], data, -1);
+ h += renderMobField(sec, byKey['size'], data, -1);
+ h += '</div>';
+ h += '<div class="obj-card-grid" style="margin-top:4px">';
+ h += renderMobField(sec, byKey['finishing_blow'], data, -1);
+ h += renderMobField(sec, byKey['damage_without'], data, -1);
+ h += '</div>';
+
+ sec.inline.forEach(function(il) {
+ h += ced_renderTags(sec, il, data);
+ });
return h;
}
-// setupMobProtectedToggle hides Aggressive, Respawn Ticks and Kind while
-// Protected is checked (protected mobs never attack, respawn, or work). Toggles
-// CSS only — no re-render — so other unsaved field edits are preserved.
+// setupMobProtectedToggle hides the entire Combat card when Protected is checked.
function setupMobProtectedToggle() {
var sec = MOB_SECTIONS.find(function(s) { return s.id === 'core'; });
if (!sec) return;
var protEl = document.getElementById(mobFieldID(sec, 'protected', -1));
if (!protEl) return;
function apply() {
- var hide = protEl.checked;
- ['aggressive', 'respawn_ticks', 'kind'].forEach(function(key) {
- var el = document.getElementById(mobFieldID(sec, key, -1));
- if (!el) return;
- var field = el.closest('.obj-field');
- if (field) field.style.display = hide ? 'none' : '';
- });
+ var combatCard = document.querySelector('.obj-card[data-card="combat"]');
+ if (combatCard) {
+ combatCard.style.display = protEl.checked ? 'none' : '';
+ }
}
if (!protEl._hasProtectedToggle) {
protEl._hasProtectedToggle = true;
@@ -399,10 +412,6 @@ function renderMobSubtable(sec, st, data) {
return h;
}
-// renderMobLootSubtable renders the Drops loot list where each row is either an
-// item drop (Item + Weight + Quantity) or a table drop (Table + Weight + Rolls).
-// A table entry's "Rolls" is stored in the `quantity` field and means the number
-// of independent draws from that table (see behavior.ResolveDropList).
function renderMobLootSubtable(sec, st, arr) {
var byKey = {};
st.fields.forEach(function(f) { byKey[f[0]] = f; });
@@ -433,13 +442,10 @@ function renderMobLootSubtable(sec, st, arr) {
return h;
}
-// Column width (px) for a non-search field, sized to fit its header label.
function mobTableColWidth(f) {
return Math.max(60, esc(f[1]).length * 8 + 20);
}
-// renderMobTableSubtable renders a subtable in the ingredients-style table
-// layout: a single column-header row (no card header) and one row per entry.
function renderMobTableSubtable(sec, st, arr) {
var h = '<div class="ingredients-table" style="margin-top:10px">';
h += '<div class="ingredients-header-row">';
@@ -465,8 +471,6 @@ function renderMobTableSubtable(sec, st, arr) {
'<input id="' + fid + '" value="' + escAttr(sval) + '" class="search-input" data-search-type="' + entity + '" placeholder="Search ' + entity + '...">' +
'<div class="search-results" style="display:none"></div></div></div></div>';
} else {
- // Numeric column. Blank a 0/unset value only when the field has a
- // placeholder, so the placeholder (e.g. "1000") shows through.
var hasPh = !!f[3];
var nval;
if (val === undefined || val === null || val === '') nval = '';
@@ -516,11 +520,23 @@ function mobAddSection() {
if (!sec) return;
if (sec.path) {
- if (sec.id === 'drops') {
+ if (id === 'combat') {
+ mobData[sec.path] = {
+ kind: 'combat',
+ stats: {
+ hp: 1, attack: 1, strength: 1, defense: 1,
+ attack_type: 'crush', speed: 5,
+ aggressive: false, respawn_ticks: 30,
+ bonuses: {attack_bonus:0, strength_bonus:0, science_bonus:0, science_percent_bonus:0, ranged_bonus:0, ranged_strength_bonus:0},
+ defenses: {stab_defense:0, slash_defense:0, crush_defense:0, science_defense:0, ranged_defense:0}
+ },
+ size: 'small'
+ };
+ } else if (id === 'drops') {
mobData[sec.path] = {remains:'bones', loot:[]};
- } else if (sec.id === 'talk') {
+ } else if (id === 'talk') {
mobData[sec.path] = {nodes:{start:{messages:[],options:[]}}};
- } else if (sec.id === 'shop') {
+ } else if (id === 'shop') {
mobData[sec.path] = {buy_percentage:40, change_percentage:3, buys_anything:true, items:[]};
} else {
mobData[sec.path] = {};
@@ -547,10 +563,6 @@ function removeMobSubRow(cardID, subKey, idx) {
renderCurrent();
}
-// addMobLootRow appends an item- or table-kind loot entry. The ephemeral _kind
-// marker is only used for rendering fresh empty rows; it's never saved (save
-// rebuilds rows from the visible inputs) and is re-inferred from item_id/table
-// on reload.
function addMobLootRow(kind) {
if (!mobData.drops) mobData.drops = {};
if (!Array.isArray(mobData.drops.loot)) mobData.drops.loot = [];
@@ -562,26 +574,20 @@ function addMobLootRow(kind) {
renderCurrent();
}
-// ---- Kind change handler (show/hide task fields) ----
-
-function setupMobKindChange() {
- var kindSel = document.getElementById(mobFieldID(MOB_SECTIONS.find(function(s){return s.id==='core';}), 'kind', -1));
- if (!kindSel) return;
- kindSel.addEventListener('change', function() {
- if (kindSel.value === 'task') {
- mobData.kind = 'task';
- if (!mobData.verb) mobData.verb = '';
- if (!mobData.progress_noun) mobData.progress_noun = '';
- if (!mobData.complete_message) mobData.complete_message = '';
- addedSections['task'] = true;
- expandedCards['task'] = true;
- renderCurrent();
- } else {
- mobData.kind = '';
- delete addedSections['task'];
- renderCurrent();
+// ---- Nested object helpers ----
+
+function unflattenObj(obj) {
+ var result = {};
+ Object.keys(obj).forEach(function(key) {
+ var parts = key.split('.');
+ var current = result;
+ for (var i = 0; i < parts.length - 1; i++) {
+ if (!current[parts[i]]) current[parts[i]] = {};
+ current = current[parts[i]];
}
+ current[parts[parts.length - 1]] = obj[key];
});
+ return result;
}
// ---- Save ----
@@ -611,13 +617,22 @@ function saveMob() {
}
if (sec.inline) {
- if (ced_saveInlineFields(sec, sectionObj, mobCardPath, mobFieldID)) hasValues = true;
+ sec.inline.forEach(function(il) {
+ if (il.type === 'tags') {
+ var fid = mobFieldID(sec, il.key);
+ var el = document.getElementById(fid);
+ if (el && el.value.trim()) {
+ sectionObj[il.key] = el.value.split(',').map(function(s) { return s.trim(); }).filter(function(s) { return s; });
+ hasValues = true;
+ }
+ }
+ });
}
if (sec.always) {
Object.keys(sectionObj).forEach(function(k) { out[k] = sectionObj[k]; });
} else if (hasValues && sec.path) {
- out[sec.path] = sectionObj;
+ out[sec.path] = unflattenObj(sectionObj);
} else if (hasValues && !sec.path) {
Object.keys(sectionObj).forEach(function(k) { out[k] = sectionObj[k]; });
}
diff --git a/internal/admin/static/objecteditor.js b/internal/admin/static/objecteditor.js
index 4d02295..d45c26e 100644
--- a/internal/admin/static/objecteditor.js
+++ b/internal/admin/static/objecteditor.js
@@ -121,12 +121,8 @@ var SECTIONS = [
['take_item', 'Take Item', 'text'],
['teleport', 'Teleport', 'number', '', 'narrow'],
['heal', 'Heal', 'number', '', 'narrow'],
- ['cost', 'Cost', 'number', '', 'narrow'],
- ['assign_task', 'Assign Task', 'checkbox'],
- ['skip_task', 'Skip Task', 'checkbox'],
- ['extend_task', 'Extend Task', 'checkbox'],
+ ['credits', 'Credits', 'number', '', 'narrow'],
['reputation_cost', 'Reputation Cost', 'number', '', 'narrow'],
- ['sawmill', 'Sawmill', 'checkbox'],
['aps_node', 'APS Node', 'checkbox'],
]
},
diff --git a/internal/game/look_entities.go b/internal/game/look_entities.go
index 3b0758b..c1befe3 100644
--- a/internal/game/look_entities.go
+++ b/internal/game/look_entities.go
@@ -42,10 +42,9 @@ func (g *Game) showRoomMobs(sess *net.Session, p *player.Player, room *world.Roo
}
var desc string
if g.Combat.IsMobInCombat(m.InstanceID) {
- def, err := g.MobStore.LoadDef(m.DefID)
- if err == nil && len(def.CombatDescriptions) > 0 {
+ if len(m.CombatDescriptions) > 0 {
target := g.Combat.MobTarget(m.InstanceID)
- pattern := def.CombatDescriptions[randInt(len(def.CombatDescriptions))]
+ pattern := m.CombatDescriptions[randInt(len(m.CombatDescriptions))]
desc = " " + fmt.Sprintf(pattern, target)
}
} else if m.IdleDescription != "" {
diff --git a/internal/game/sys_construction.go b/internal/game/sys_construction.go
deleted file mode 100644
index 06713cd..0000000
--- a/internal/game/sys_construction.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package game
-
-import (
- "fmt"
-
- "thehouseoficarus/internal/net"
- "thehouseoficarus/internal/player"
-)
-
-func (g *Game) processSawmill(sess *net.Session, p *player.Player) {
- logTypes := map[string]struct {
- plankID string
- cost int
- name string
- }{
- "logs": {"planks", 5, "regular planks"},
- "oak_logs": {"oak_planks", 10, "oak planks"},
- "teak_logs": {"teak_planks", 20, "teak planks"},
- "mahogany_logs": {"mahogany_planks", 40, "mahogany planks"},
- }
-
- totalCost := 0
- totalPlanks := 0
- type plankResult struct {
- plankID string
- qty int
- }
-
- var results []plankResult
-
- for logID, info := range logTypes {
- qty := p.CountItem(logID)
- if qty == 0 {
- continue
- }
- cost := qty * info.cost
- totalCost += cost
- totalPlanks += qty
- results = append(results, plankResult{info.plankID, qty})
- p.RemoveItem(logID, qty)
- }
-
- if totalPlanks == 0 {
- sess.WriteLine("You don't have any logs to process.")
- return
- }
-
- if p.Credits < totalCost {
- sess.WriteLine(fmt.Sprintf("You need %d credits to process all your logs (you have %d).", totalCost, p.Credits))
- return
- }
-
- p.Credits -= totalCost
-
- processed := 0
- for _, r := range results {
- for i := 0; i < r.qty; i++ {
- freeSlot := p.FirstFreeSlot()
- if freeSlot == -1 {
- g.World.AddGroundItem(p.RoomID, r.plankID, r.qty-i)
- break
- }
- p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: r.plankID, Quantity: 1})
- processed++
- }
- }
-
- g.AccountStore.SaveCharacter(p)
-
- sess.WriteLine(fmt.Sprintf("The sawmill operator processes your logs into %d planks for %d credits.", processed, totalCost))
- if processed < totalPlanks {
- sess.WriteLine(fmt.Sprintf("Your inventory is full. The remaining %d planks fall to the ground.", totalPlanks-processed))
- }
-}
diff --git a/internal/validate/checks.go b/internal/validate/checks.go
index cdeee44..a8f973f 100644
--- a/internal/validate/checks.go
+++ b/internal/validate/checks.go
@@ -316,19 +316,23 @@ func validateMobs(s Source) []Issue {
})
}
- if !def.Protected && def.HP <= 0 {
+ if !def.Protected && (def.Combat == nil || def.Combat.Stats.HP <= 0) {
+ hp := 0
+ if def.Combat != nil {
+ hp = def.Combat.Stats.HP
+ }
issues = append(issues, Issue{
Level: "ERROR",
Type: "reference",
- Message: fmt.Sprintf("Mob %q: is not protected but has HP=%d — mobs must have hp > 0 (or set protected: true)", id, def.HP),
+ Message: fmt.Sprintf("Mob %q: is not protected but has HP=%d — mobs must have hp > 0 (or set protected: true)", id, hp),
})
}
- if def.Kind != "" && def.Kind != "combat" && def.Kind != "task" {
+ if def.Combat != nil && def.Combat.Kind != "" && def.Combat.Kind != "combat" && def.Combat.Kind != "task" {
issues = append(issues, Issue{
Level: "ERROR",
Type: "reference",
- Message: fmt.Sprintf("Mob %q: invalid kind %q (must be \"combat\" or \"task\")", id, def.Kind),
+ Message: fmt.Sprintf("Mob %q: invalid kind %q (must be \"combat\" or \"task\")", id, def.Combat.Kind),
})
}
@@ -360,21 +364,21 @@ func validateMobs(s Source) []Issue {
}
}
- if def.StealTable != "" && !dropIDs[def.StealTable] {
+ if def.Steal != nil && def.Steal.Table != "" && !dropIDs[def.Steal.Table] {
issues = append(issues, Issue{
Level: "ERROR",
Type: "reference",
- Message: fmt.Sprintf("Mob %q: steal_table %q does not exist",
- id, def.StealTable),
+ Message: fmt.Sprintf("Mob %q: steal table %q does not exist",
+ id, def.Steal.Table),
})
}
- if def.FinishingBlow != "" && !itemIDs[def.FinishingBlow] {
+ if def.Combat != nil && def.Combat.FinishingBlow != "" && !itemIDs[def.Combat.FinishingBlow] {
issues = append(issues, Issue{
Level: "ERROR",
Type: "reference",
Message: fmt.Sprintf("Mob %q: finishing_blow item %q does not exist",
- id, def.FinishingBlow),
+ id, def.Combat.FinishingBlow),
})
}
diff --git a/internal/world/mob.go b/internal/world/mob.go
index 58bf769..19ec935 100644
--- a/internal/world/mob.go
+++ b/internal/world/mob.go
@@ -17,55 +17,75 @@ type MobDropTable struct {
Loot []behavior.DropEntry `yaml:"loot"`
}
+type MobSteal struct {
+ Table string `yaml:"table"`
+ Level int `yaml:"level"`
+ XP int `yaml:"xp"`
+ Speed float64 `yaml:"speed"`
+}
+
+type MobTask struct {
+ Verb string `yaml:"verb"`
+ ProgressNoun string `yaml:"progress_noun"`
+ CompleteMessage string `yaml:"complete_message"`
+}
+
+type MobCombatBonuses struct {
+ AttackBonus int `yaml:"attack_bonus"`
+ StrengthBonus int `yaml:"strength_bonus"`
+ ScienceBonus int `yaml:"science_bonus"`
+ SciencePercentBonus int `yaml:"science_percent_bonus"`
+ RangedBonus int `yaml:"ranged_bonus"`
+ RangedStrengthBonus int `yaml:"ranged_strength_bonus"`
+}
+
+type MobCombatDefenses struct {
+ StabDefense int `yaml:"stab_defense"`
+ SlashDefense int `yaml:"slash_defense"`
+ CrushDefense int `yaml:"crush_defense"`
+ ScienceDefense int `yaml:"science_defense"`
+ RangedDefense int `yaml:"ranged_defense"`
+ Weakness string `yaml:"weakness"`
+}
+
+type MobCombatStats struct {
+ HP int `yaml:"hp"`
+ Attack int `yaml:"attack"`
+ Strength int `yaml:"strength"`
+ Defense int `yaml:"defense"`
+ Ranged int `yaml:"ranged"`
+ Science int `yaml:"science"`
+ AttackType string `yaml:"attack_type"`
+ Speed float64 `yaml:"speed"`
+ Aggressive bool `yaml:"aggressive"`
+ RespawnTicks float64 `yaml:"respawn_ticks"`
+ Bonuses MobCombatBonuses `yaml:"bonuses"`
+ Defenses MobCombatDefenses `yaml:"defenses"`
+}
+
+type MobCombat struct {
+ Kind string `yaml:"kind"`
+ Stats MobCombatStats `yaml:"stats"`
+ AssassinLevel int `yaml:"assassin_level"`
+ FinishingBlow string `yaml:"finishing_blow"`
+ DamageWithout string `yaml:"damage_without"`
+ Size string `yaml:"size"`
+ CombatDescriptions []string `yaml:"combat_descriptions"`
+}
+
type MobDef struct {
- ID string `yaml:"id"`
- Name string `yaml:"name"`
- Description string `yaml:"description"`
- IdleDescriptions []string `yaml:"idle_descriptions"`
- CombatDescriptions []string `yaml:"combat_descriptions"`
- Attack int `yaml:"attack"`
- Strength int `yaml:"strength"`
- Defense int `yaml:"defense"`
- HP int `yaml:"hp"`
- Ranged int `yaml:"ranged"`
- Science int `yaml:"science"`
- Speed float64 `yaml:"speed"`
- Aggressive bool `yaml:"aggressive"`
- Protected bool `yaml:"protected"`
- Unique bool `yaml:"unique"`
- RespawnTicks float64 `yaml:"respawn_ticks"`
- Drops MobDropTable `yaml:"drops"`
-
- AttackBonus int `yaml:"attack_bonus"`
- StrengthBonus int `yaml:"strength_bonus"`
- AttackType string `yaml:"attack_type"`
-
- StabDefense int `yaml:"stab_defense"`
- SlashDefense int `yaml:"slash_defense"`
- CrushDefense int `yaml:"crush_defense"`
- ScienceDefense int `yaml:"science_defense"`
- RangedDefense int `yaml:"ranged_defense"`
-
- Weakness string `yaml:"weakness"`
- StealTable string `yaml:"steal_table"`
- StealLevel int `yaml:"steal_level"`
- StealXP int `yaml:"steal_xp"`
- StealSpeed float64 `yaml:"steal_speed"`
-
- AssassinLevel int `yaml:"assassin_level"`
- FinishingBlow string `yaml:"finishing_blow"`
- DamageWithout string `yaml:"damage_without"`
- Size string `yaml:"size"`
-
- // Kind discriminates a normal combat mob ("" or "combat") from a "task"
- // worksite (build a solar panel, survey a rock, etc.). A task mob reuses the
- // entire combat engine but its HP drains to 0 to COMPLETE the work; it never
- // attacks back (the room hazard, if any, supplies the danger). The progress
- // bar is displayed inverted (filling toward 100%).
- Kind string `yaml:"kind"`
- Verb string `yaml:"verb"` // flavor verb for messages (default "work")
- ProgressNoun string `yaml:"progress_noun"` // flavor noun, e.g. "construction"
- CompleteMessage string `yaml:"complete_message"` // shown on completion
+ ID string `yaml:"id"`
+ Name string `yaml:"name"`
+ Description string `yaml:"description"`
+ IdleDescriptions []string `yaml:"idle_descriptions"`
+ Protected bool `yaml:"protected"`
+ Unique bool `yaml:"unique"`
+ Drops MobDropTable `yaml:"drops"`
+
+ Steal *MobSteal `yaml:"steal,omitempty"`
+ Task *MobTask `yaml:"task,omitempty"`
+
+ Combat *MobCombat `yaml:"combat,omitempty"`
Talk *behavior.TalkConfig `yaml:"talk,omitempty"`
Shop *behavior.ShopConfig `yaml:"shop,omitempty"`
@@ -75,7 +95,7 @@ func (d *MobDef) IsTalkable() bool { return d.Talk != nil }
func (d *MobDef) HasShop() bool { return d.Shop != nil }
-func (d *MobDef) IsTask() bool { return d.Kind == "task" }
+func (d *MobDef) IsTask() bool { return d.Combat != nil && d.Combat.Kind == "task" }
type MobInstance struct {
InstanceID string
@@ -97,11 +117,12 @@ type MobInstance struct {
RoomID int
HomeRoomID int
Drops MobDropTable
- IdleDescription string
- WanderRooms []int
- WanderInterval float64
- WanderTickCounter int
- regenerateTick int
+ IdleDescription string
+ CombatDescriptions []string
+ WanderRooms []int
+ WanderInterval float64
+ WanderTickCounter int
+ regenerateTick int
AttackBonus int
StrengthBonus int
@@ -154,7 +175,80 @@ func (m *MobInstance) HasShop() bool { return m.Shop != nil }
func (m *MobInstance) IsTask() bool { return m.Kind == "task" }
func NewMobInstance(def *MobDef, instanceID string, roomID int, wanderRooms []int, wanderInterval float64) *MobInstance {
- hp := def.HP
+ hp := 0
+ attack := 0
+ strength := 0
+ defense := 0
+ ranged := 0
+ science := 0
+ speed := 0.0
+ aggressive := false
+ respawnTicks := 0.0
+ attackBonus := 0
+ strengthBonus := 0
+ attackType := ""
+ stabDef := 0
+ slashDef := 0
+ crushDef := 0
+ scienceDef := 0
+ rangedDef := 0
+ weakness := ""
+ assassinLevel := 0
+ finishingBlow := ""
+ damageWithout := ""
+ size := ""
+ kind := ""
+ verb := ""
+ progressNoun := ""
+ completeMessage := ""
+ var combatDescriptions []string
+ stealTable := ""
+ stealLevel := 0
+ stealXP := 0
+ stealSpeed := 0.0
+
+ if def.Combat != nil {
+ cs := def.Combat.Stats
+ hp = cs.HP
+ attack = cs.Attack
+ strength = cs.Strength
+ defense = cs.Defense
+ ranged = cs.Ranged
+ science = cs.Science
+ speed = cs.Speed
+ aggressive = cs.Aggressive
+ respawnTicks = cs.RespawnTicks
+ attackBonus = cs.Bonuses.AttackBonus
+ strengthBonus = cs.Bonuses.StrengthBonus
+ attackType = cs.AttackType
+ stabDef = cs.Defenses.StabDefense
+ slashDef = cs.Defenses.SlashDefense
+ crushDef = cs.Defenses.CrushDefense
+ scienceDef = cs.Defenses.ScienceDefense
+ rangedDef = cs.Defenses.RangedDefense
+ weakness = cs.Defenses.Weakness
+
+ assassinLevel = def.Combat.AssassinLevel
+ finishingBlow = def.Combat.FinishingBlow
+ damageWithout = def.Combat.DamageWithout
+ size = def.Combat.Size
+ kind = def.Combat.Kind
+ combatDescriptions = def.Combat.CombatDescriptions
+ }
+
+ if def.Steal != nil {
+ stealTable = def.Steal.Table
+ stealLevel = def.Steal.Level
+ stealXP = def.Steal.XP
+ stealSpeed = def.Steal.Speed
+ }
+
+ if def.Task != nil {
+ verb = def.Task.Verb
+ progressNoun = def.Task.ProgressNoun
+ completeMessage = def.Task.CompleteMessage
+ }
+
if def.Protected && hp <= 0 {
hp = 1
}
@@ -165,42 +259,43 @@ func NewMobInstance(def *MobDef, instanceID string, roomID int, wanderRooms []in
Description: def.Description,
HP: hp,
MaxHP: hp,
- Attack: def.Attack,
- Strength: def.Strength,
- Defense: def.Defense,
- Ranged: def.Ranged,
- Science: def.Science,
- Speed: def.Speed,
- Aggressive: def.Aggressive,
+ Attack: attack,
+ Strength: strength,
+ Defense: defense,
+ Ranged: ranged,
+ Science: science,
+ Speed: speed,
+ Aggressive: aggressive,
Protected: def.Protected,
Unique: def.Unique,
- RespawnTicks: def.RespawnTicks,
+ RespawnTicks: respawnTicks,
RoomID: roomID,
HomeRoomID: roomID,
WanderRooms: wanderRooms,
WanderInterval: wanderInterval,
Drops: def.Drops,
- AttackBonus: def.AttackBonus,
- StrengthBonus: def.StrengthBonus,
- AttackType: def.AttackType,
- StabDefense: def.StabDefense,
- SlashDefense: def.SlashDefense,
- CrushDefense: def.CrushDefense,
- ScienceDefense: def.ScienceDefense,
- RangedDefense: def.RangedDefense,
- Weakness: def.Weakness,
- StealTable: def.StealTable,
- StealLevel: def.StealLevel,
- StealXP: def.StealXP,
- StealSpeed: def.StealSpeed,
- AssassinLevel: def.AssassinLevel,
- FinishingBlow: def.FinishingBlow,
- DamageWithout: def.DamageWithout,
- Size: def.Size,
- Kind: def.Kind,
- Verb: def.Verb,
- ProgressNoun: def.ProgressNoun,
- CompleteMessage: def.CompleteMessage,
+ AttackBonus: attackBonus,
+ StrengthBonus: strengthBonus,
+ AttackType: attackType,
+ StabDefense: stabDef,
+ SlashDefense: slashDef,
+ CrushDefense: crushDef,
+ ScienceDefense: scienceDef,
+ RangedDefense: rangedDef,
+ Weakness: weakness,
+ StealTable: stealTable,
+ StealLevel: stealLevel,
+ StealXP: stealXP,
+ StealSpeed: stealSpeed,
+ AssassinLevel: assassinLevel,
+ FinishingBlow: finishingBlow,
+ DamageWithout: damageWithout,
+ Size: size,
+ Kind: kind,
+ Verb: verb,
+ ProgressNoun: progressNoun,
+ CompleteMessage: completeMessage,
+ CombatDescriptions: combatDescriptions,
TalkConfig: def.Talk,
}
if def.Shop != nil {