diff options
| author | historia <[not public]> | 2026-07-05 22:35:21 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-07-05 22:35:21 -0400 |
| commit | 94823b52168b44894fb5e9c960358ed02ebb122b (patch) | |
| tree | 3060799b89bb7edfa708c72bdd981107d40f4d09 /internal/game/core_course.go | |
| parent | 843fa6db681e494bf46e191655323a40577542b5 (diff) | |
| download | thehouseoficarus-94823b52168b44894fb5e9c960358ed02ebb122b.tar.gz | |
feat: courses gui overhaul, add course tab to map, add hidden exits to give courses structure
Diffstat (limited to 'internal/game/core_course.go')
| -rw-r--r-- | internal/game/core_course.go | 78 |
1 files changed, 67 insertions, 11 deletions
diff --git a/internal/game/core_course.go b/internal/game/core_course.go index 5d5c7c5..54894fd 100644 --- a/internal/game/core_course.go +++ b/internal/game/core_course.go @@ -8,13 +8,29 @@ import ( "thehouseoficarus/internal/behavior" ) +// ObstaclePhase is a single phase of an obstacle's advancement sequence. +// Each phase prints a message after waiting Delay ticks, then optionally +// performs the failure check. +type ObstaclePhase struct { + Message string `yaml:"message"` + Delay float64 `yaml:"delay"` + FailCheck bool `yaml:"fail_check,omitempty"` +} + +// ObstacleDef is the YAML representation of a single agility obstacle. +// Two equivalent forms are supported: +// - Legacy: Messages (exactly 3) + TicksPerPhase + fail at phase index 1. +// - Preferred: Phases, an explicit ordered list with per-phase delays and +// an optional fail_check flag (at most one phase should carry it). type ObstacleDef struct { - RoomID int `yaml:"room_id"` - Verb string `yaml:"verb"` - TicksPerPhase float64 `yaml:"ticks_per_phase"` - XP int `yaml:"xp"` - FailDamage [2]int `yaml:"fail_damage"` - Messages []string `yaml:"messages"` + RoomID int `yaml:"room_id"` + Verb string `yaml:"verb"` + XP int `yaml:"xp"` + FailDamage [2]int `yaml:"fail_damage"` + FailChance *float64 `yaml:"fail_chance,omitempty"` + TicksPerPhase float64 `yaml:"ticks_per_phase"` + Messages []string `yaml:"messages"` + Phases []ObstaclePhase `yaml:"phases"` } type CourseConfig struct { @@ -26,16 +42,23 @@ type CourseConfig struct { Obstacles []ObstacleDef `yaml:"obstacles"` } +// PhaseInfo is the runtime-resolved form of an ObstaclePhase. +type PhaseInfo struct { + Message string + Delay float64 + FailCheck bool +} + type ObstacleInfo struct { CourseID string CourseName string ObstacleIndex int TotalObstacles int Verb string - Messages []string - TicksPerPhase float64 + Phases []PhaseInfo ObstacleXP int CompletionXP int + FailChance *float64 // nil => derived from agility level FailDamage [2]int NextRoom int StartRoom int @@ -104,6 +127,39 @@ func (cs *CourseStore) GetObstacle(roomID int) *ObstacleInfo { return cs.roomToObstacle[roomID] } +// resolvePhases converts an ObstacleDef into a normalized PhaseInfo list. +// Preferred form: explicit Phases. Legacy form: Messages with a shared +// TicksPerPhase and the failure check at the middle (index 1) phase. +func resolvePhases(obs ObstacleDef) []PhaseInfo { + if len(obs.Phases) > 0 { + phases := make([]PhaseInfo, 0, len(obs.Phases)) + for _, p := range obs.Phases { + phases = append(phases, PhaseInfo{ + Message: p.Message, + Delay: p.Delay, + FailCheck: p.FailCheck, + }) + } + return phases + } + msgs := obs.Messages + phases := make([]PhaseInfo, 0, len(msgs)) + for i, m := range msgs { + var delay float64 + if i == 0 { + delay = 0 + } else { + delay = obs.TicksPerPhase + } + phases = append(phases, PhaseInfo{ + Message: m, + Delay: delay, + FailCheck: i == 1, + }) + } + return phases +} + func (cs *CourseStore) loadAllLocked() { cs.loaded = true cs.roomToObstacle = make(map[int]*ObstacleInfo) @@ -135,10 +191,10 @@ func (cs *CourseStore) loadAllLocked() { ObstacleIndex: i, TotalObstacles: totalObstacles, Verb: obs.Verb, - Messages: obs.Messages, - TicksPerPhase: obs.TicksPerPhase, + Phases: resolvePhases(obs), ObstacleXP: obs.XP, CompletionXP: completionXP, + FailChance: obs.FailChance, FailDamage: obs.FailDamage, NextRoom: nextRoom, StartRoom: cfg.StartRoom, @@ -151,4 +207,4 @@ func (cs *CourseStore) loadAllLocked() { }) obstacleVerbs = localVerbs -} +}
\ No newline at end of file |
