aboutsummaryrefslogtreecommitdiff
path: root/internal/world/room.go
blob: aced96981ecc4bb4a899a67e6fad690958ae0a36 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package world

import (
	"gopkg.in/yaml.v3"
	"thehouseoficarus/internal/behavior"
)

type ExitDir string

const (
	North ExitDir = "north"
	South ExitDir = "south"
	East  ExitDir = "east"
	West  ExitDir = "west"
	Up    ExitDir = "up"
	Down  ExitDir = "down"
)

var ExitAliases = map[string]ExitDir{
	"n": North,
	"s": South,
	"e": East,
	"w": West,
	"u": Up,
	"d": Down,
}

var OppositeExit = map[ExitDir]ExitDir{
	North: South,
	South: North,
	East:  West,
	West:  East,
	Up:    Down,
	Down:  Up,
}

var ExitOrder = []ExitDir{
	North, South, East, West, Up, Down,
}

type SpawnDef struct {
	ID           string  `yaml:"id"`
	Quantity     int     `yaml:"quantity"`
	RespawnTicks float64 `yaml:"respawn_ticks"`
}

type ExitDef struct {
	Room           int                 `yaml:"room"`
	Condition      *behavior.Condition `yaml:"condition"`
	BlockedMessage string              `yaml:"blocked_message"`
	SetFlags       map[string]any      `yaml:"set_flags"`
	SetPlayerFlags map[string]any      `yaml:"set_player_flags"`
}

func (e *ExitDef) UnmarshalYAML(value *yaml.Node) error {
	if value.Kind == yaml.ScalarNode {
		var n int
		if err := value.Decode(&n); err != nil {
			return err
		}
		e.Room = n
		return nil
	}
	type raw ExitDef
	return value.Decode((*raw)(e))
}

type Room struct {
	ID          int                 `yaml:"id"`
	Name        string              `yaml:"name"`
	Description behavior.DescList   `yaml:"description"`
	Exits       map[ExitDir]ExitDef `yaml:"exits"`
	Objects     []RoomObject        `yaml:"objects"`
	ItemSpawns  []SpawnDef          `yaml:"item_spawns"`
	Mobs        []RoomMob           `yaml:"mobs"`
	OnEnter     []EnterStep         `yaml:"on_enter"`
	Hazard      string              `yaml:"hazard"`
	Triggers    []TriggerDef        `yaml:"triggers"`
}

type RoomMob struct {
	ID             string  `yaml:"id"`
	WanderRooms    []int   `yaml:"wander_rooms"`
	WanderInterval float64 `yaml:"wander_interval"`
}

func (rm *RoomMob) UnmarshalYAML(value *yaml.Node) error {
	if value.Kind == yaml.ScalarNode {
		var s string
		if err := value.Decode(&s); err != nil {
			return err
		}
		rm.ID = s
		return nil
	}
	type raw RoomMob
	return value.Decode((*raw)(rm))
}

type EnterStep struct {
	Message        string              `yaml:"message"`
	Condition      *behavior.Condition `yaml:"condition"`
	Delay          int                 `yaml:"delay"`
	SetFlags       map[string]any      `yaml:"set_flags"`
	SetPlayerFlags map[string]any      `yaml:"set_player_flags"`
	Broadcast       string          `yaml:"broadcast"`
	BroadcastGlobal string          `yaml:"broadcast_global"`
	SpawnMob        *SpawnMobConfig `yaml:"spawn_mob"`
	DespawnMob      string          `yaml:"despawn_mob"`
	GiveItem        string          `yaml:"give_item"`
	TakeItem        string          `yaml:"take_item"`
	Teleport        int             `yaml:"teleport"`
	Heal            int             `yaml:"heal"`
}

// IsTimed reports whether the step carries enter-sequence semantics (any
// non-zero field means it needs per-tick scheduling rather than synchronous
// printing).
func (e EnterStep) IsTimed() bool {
	return e.Delay > 0 || len(e.SetFlags) > 0 || len(e.SetPlayerFlags) > 0 ||
		e.Message != "" || e.Broadcast != "" || e.BroadcastGlobal != "" ||
		e.SpawnMob != nil || e.DespawnMob != "" || e.GiveItem != "" ||
		e.TakeItem != "" || e.Teleport != 0 || e.Heal != 0
}

type RoomObject struct {
	ID             string  `yaml:"id"`
	WanderRooms    []int   `yaml:"wander_rooms"`
	WanderInterval float64 `yaml:"wander_interval"`
}