aboutsummaryrefslogtreecommitdiff
path: root/internal/world/room_migrate.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-07-09 22:15:54 -0400
committerhistoria <[not public]>2026-07-09 22:15:54 -0400
commitecba7f726f70b37126d852c38c7e3eec7b04d730 (patch)
tree9129215c6e5015336fde1116395336d82bb952d1 /internal/world/room_migrate.go
parentb3d4c616f59ad2519f3a0b77e3b47d6571cd2486 (diff)
downloadthehouseoficarus-ecba7f726f70b37126d852c38c7e3eec7b04d730.tar.gz
feat: old standalone trigger systems completely unified into trigger->condition->action system
Diffstat (limited to 'internal/world/room_migrate.go')
-rw-r--r--internal/world/room_migrate.go162
1 files changed, 135 insertions, 27 deletions
diff --git a/internal/world/room_migrate.go b/internal/world/room_migrate.go
index 946417f..d609c6a 100644
--- a/internal/world/room_migrate.go
+++ b/internal/world/room_migrate.go
@@ -1,66 +1,174 @@
package world
+import (
+ "thehouseoficarus/internal/behavior"
+)
+
// RewriteRoomIDs remaps every genuine room-ID reference in this room per idMap
-// (oldID -> newID): exit targets, trigger Room/Teleport/DespawnRooms, on-enter
-// Teleport/DespawnRooms, and mob WanderRooms. It does NOT touch author-chosen
-// set_flags/set_player_flags values or condition `value:` fields — those are not
-// structural room references (and historically the swapid regex rewrote them
-// incorrectly as a side effect of matching any bare integer).
+// (oldID -> newID): exit targets; every Step.Teleport and Step.SpawnMob
+// .DespawnRooms inside on_enter/on_exit/on_flag_change/on_global_flag_change/
+// on_traverse/on_use/on_look/on_kill blocks; every Condition.Room anywhere in
+// the room (exits, descriptions, trigger conditions, per-step conditions,
+// including nested all_of/any_of); and mob WanderRooms. It does NOT touch
+// author-chosen set_flags/set_player_flags values or condition `value:` fields
+// — those are not structural room references.
//
// idMap is assumed to be a bijection (each old ID maps to a distinct new ID);
-// this holds for both swap (A<->B) and rename-to-unused (A->B). Returns whether
-// any field was changed.
+// this holds for both swap (A<->B) and rename-to-unused (A->B). Returns
+// whether any field was changed.
func (r *Room) RewriteRoomIDs(idMap map[int]int) bool {
if r == nil || len(idMap) == 0 {
return false
}
changed := false
+
+ // Exit targets + their on_traverse steps + exit/desc conditions.
for dir, exit := range r.Exits {
var exitChanged bool
if remapInt(idMap, &exit.Room) {
exitChanged = true
}
- for i := range exit.OnTraverse {
- if exit.OnTraverse[i].Action != nil {
- if remapInt(idMap, &exit.OnTraverse[i].Action.Teleport) {
- exitChanged = true
- }
- if exit.OnTraverse[i].Action.SpawnMob != nil &&
- remapIntSlice(idMap, exit.OnTraverse[i].Action.SpawnMob.DespawnRooms) {
- exitChanged = true
- }
- }
+ if remapTriggers(idMap, exit.OnTraverse) {
+ exitChanged = true
+ }
+ if exit.Condition != nil && remapCondition(idMap, exit.Condition) {
+ exitChanged = true
}
if exitChanged {
r.Exits[dir] = exit
changed = true
}
}
- for i := range r.Triggers {
- if remapInt(idMap, &r.Triggers[i].Room) {
+
+ // Every trigger-shaped block on the room shares the Step list + Condition
+ // structure. Remap their steps and conditions uniformly.
+ for i := range r.OnEnter {
+ c := false
+ if remapStepList(idMap, r.OnEnter[i].Steps) {
+ c = true
+ }
+ if remapCondition(idMap, r.OnEnter[i].Condition) {
+ c = true
+ }
+ changed = changed || c
+ }
+ for i := range r.OnExit {
+ c := false
+ if remapStepList(idMap, r.OnExit[i].Steps) {
+ c = true
+ }
+ if remapCondition(idMap, r.OnExit[i].Condition) {
+ c = true
+ }
+ changed = changed || c
+ }
+ for i := range r.OnFlagChange {
+ c := false
+ if remapStepList(idMap, r.OnFlagChange[i].Steps) {
+ c = true
+ }
+ if remapCondition(idMap, r.OnFlagChange[i].Condition) {
+ c = true
+ }
+ changed = changed || c
+ }
+ for i := range r.OnGlobalFlagChange {
+ c := false
+ if remapStepList(idMap, r.OnGlobalFlagChange[i].Steps) {
+ c = true
+ }
+ if remapCondition(idMap, r.OnGlobalFlagChange[i].Condition) {
+ c = true
+ }
+ changed = changed || c
+ }
+
+ // Conditional room descriptions carry a Condition.
+ for i := range r.Description {
+ if remapCondition(idMap, r.Description[i].Condition) {
changed = true
}
- for j := range r.Triggers[i].Steps {
- s := &r.Triggers[i].Steps[j]
- if remapInt(idMap, &s.Teleport) {
+ }
+
+ // Per-room local objects: on_use/on_look steps + object desc conditions.
+ for i := range r.Objects {
+ if r.Objects[i].Local != nil {
+ loc := r.Objects[i].Local
+ if remapTriggers(idMap, loc.OnUse) {
changed = true
}
- if s.SpawnMob != nil && remapIntSlice(idMap, s.SpawnMob.DespawnRooms) {
+ if remapTriggers(idMap, loc.OnLook) {
changed = true
}
+ for j := range loc.Description {
+ if remapCondition(idMap, loc.Description[j].Condition) {
+ changed = true
+ }
+ }
}
}
- for i := range r.OnEnter {
- s := &r.OnEnter[i]
+
+ for i := range r.Mobs {
+ if remapIntSlice(idMap, r.Mobs[i].WanderRooms) {
+ changed = true
+ }
+ }
+ return changed
+}
+
+// remapTriggers remaps step fields across a []behavior.Trigger (each trigger's
+// Steps + per-step Condition + trigger-level Condition).
+func remapTriggers(idMap map[int]int, list []behavior.Trigger) bool {
+ changed := false
+ for i := range list {
+ c := false
+ if remapStepList(idMap, list[i].Steps) {
+ c = true
+ }
+ if remapCondition(idMap, list[i].Condition) {
+ c = true
+ }
+ changed = changed || c
+ }
+ return changed
+}
+
+// remapStepList remaps Step.Teleport and Step.SpawnMob.DespawnRooms plus every
+// step's per-step Condition.Room across a single Trigger's Steps.
+func remapStepList(idMap map[int]int, steps []behavior.Step) bool {
+ changed := false
+ for i := range steps {
+ s := &steps[i]
if remapInt(idMap, &s.Teleport) {
changed = true
}
if s.SpawnMob != nil && remapIntSlice(idMap, s.SpawnMob.DespawnRooms) {
changed = true
}
+ if remapCondition(idMap, s.Condition) {
+ changed = true
+ }
}
- for i := range r.Mobs {
- if remapIntSlice(idMap, r.Mobs[i].WanderRooms) {
+ return changed
+}
+
+// remapCondition walks a Condition tree and remaps any Room field (a
+// structural room reference) it finds, recursing into AllOf/AnyOf.
+func remapCondition(idMap map[int]int, c *behavior.Condition) bool {
+ if c == nil {
+ return false
+ }
+ changed := false
+ if c.Room != 0 && remapInt(idMap, &c.Room) {
+ changed = true
+ }
+ for i := range c.AllOf {
+ if remapCondition(idMap, &c.AllOf[i]) {
+ changed = true
+ }
+ }
+ for i := range c.AnyOf {
+ if remapCondition(idMap, &c.AnyOf[i]) {
changed = true
}
}