@v12-engine/create 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +26 -2
  3. package/base/_gitignore +10 -0
  4. package/base/index.html +20 -0
  5. package/base/package.json +23 -0
  6. package/base/src/ground.worker.ts +8 -0
  7. package/base/src/main.ts +61 -0
  8. package/base/tsconfig.json +14 -0
  9. package/base/vite.config.ts +25 -0
  10. package/bin.mjs +10 -0
  11. package/cli.mjs +381 -0
  12. package/index.mjs +286 -0
  13. package/layers/assets/package.json +5 -0
  14. package/layers/editor/package.json +8 -0
  15. package/layers/editor/src/editor.ts +13 -0
  16. package/layers/rooms/server.ts +69 -0
  17. package/layers/server/package.json +8 -0
  18. package/layers/server/server.ts +34 -0
  19. package/layers/source/package.json +12 -0
  20. package/layers/source/tsconfig.json +5 -0
  21. package/layers/source/vite.config.ts +45 -0
  22. package/layers/tests/package.json +8 -0
  23. package/package.json +45 -5
  24. package/starters/campaign/README.md +61 -0
  25. package/starters/campaign/files.txt +42 -0
  26. package/starters/campaign/layers/editor/src/editor.ts +18 -0
  27. package/starters/campaign/layers/rooms/server.ts +39 -0
  28. package/starters/campaign/layers/server/server.ts +33 -0
  29. package/starters/campaign/layers/tests/tests/rules.test.ts +320 -0
  30. package/starters/campaign/public/games/campaign/assets.json +1 -0
  31. package/starters/campaign/src/campaign/campaign.json +52 -0
  32. package/starters/campaign/src/campaign/carry.ts +47 -0
  33. package/starters/campaign/src/campaign/cinematics/intro.json +148 -0
  34. package/starters/campaign/src/campaign/cinematics/outro.json +92 -0
  35. package/starters/campaign/src/campaign/data.json +1 -0
  36. package/starters/campaign/src/campaign/fx.json +1 -0
  37. package/starters/campaign/src/campaign/game.ts +6 -0
  38. package/starters/campaign/src/campaign/ids.ts +77 -0
  39. package/starters/campaign/src/campaign/index.ts +121 -0
  40. package/starters/campaign/src/campaign/kills.ts +16 -0
  41. package/starters/campaign/src/campaign/looks.json +1 -0
  42. package/starters/campaign/src/campaign/maps.ts +34 -0
  43. package/starters/campaign/src/campaign/missions/homecoming.ts +160 -0
  44. package/starters/campaign/src/campaign/missions/siege.ts +91 -0
  45. package/starters/campaign/src/campaign/missions/warlord.ts +177 -0
  46. package/starters/campaign/src/campaign/prefabs/watchpost.prefab.json +18 -0
  47. package/starters/campaign/src/campaign/scenes.ts +46 -0
  48. package/starters/campaign/src/campaign/tiles.ts +8 -0
  49. package/starters/campaign/src/campaign/units.ts +390 -0
  50. package/starters/campaign/src/campaign/view/cinematics.ts +59 -0
  51. package/starters/campaign/src/campaign/view/fire.ts +115 -0
  52. package/starters/campaign/src/campaign/view/index.ts +334 -0
  53. package/starters/campaign/src/campaign/view/labels.ts +105 -0
  54. package/starters/campaign/src/campaign/view/rubble.ts +40 -0
  55. package/starters/campaign/src/campaign/view/waveLane.ts +88 -0
  56. package/starters/campaign/src/campaign/waves.json +36 -0
  57. package/starters/campaign/src/campaign/waves.ts +186 -0
  58. package/starters/campaign/src/campaign-editor.ts +43 -0
  59. package/starters/campaign/src/game.ts +2 -0
  60. package/starters/campaign/src/main.ts +70 -0
  61. package/starters/campaign/src/maps/fort.names.ts +31 -0
  62. package/starters/campaign/src/maps/fort.vgmap.json +1162 -0
  63. package/starters/campaign/src/maps/homestead.names.ts +36 -0
  64. package/starters/campaign/src/maps/homestead.vgmap.json +916 -0
  65. package/starters/campaign/src/maps/pass.names.ts +40 -0
  66. package/starters/campaign/src/maps/pass.vgmap.json +522 -0
  67. package/starters/campaign/src/maps.ts +2 -0
  68. package/starters/campaign/src/rules.ts +20 -0
  69. package/starters/campaign/src/waves-panel.ts +355 -0
  70. package/starters/empty/README.md +71 -0
  71. package/starters/empty/layers/tests/tests/rules.test.ts +31 -0
  72. package/starters/empty/src/game.ts +79 -0
  73. package/starters/empty/src/generate.worker.ts +9 -0
  74. package/starters/empty/src/maps.ts +44 -0
  75. package/starters/empty/src/rules.ts +67 -0
  76. package/starters/empty/src/tiles.ts +12 -0
  77. package/starters/melee/README.md +61 -0
  78. package/starters/melee/files.txt +60 -0
  79. package/starters/melee/layers/editor/src/editor.ts +13 -0
  80. package/starters/melee/layers/tests/tests/rules.test.ts +58 -0
  81. package/starters/melee/src/game.ts +2 -0
  82. package/starters/melee/src/maps/bay.names.ts +28 -0
  83. package/starters/melee/src/maps/bay.vgmap.json +3123 -0
  84. package/starters/melee/src/maps.ts +20 -0
  85. package/starters/melee/src/melee/abilities.ts +376 -0
  86. package/starters/melee/src/melee/bay.ts +319 -0
  87. package/starters/melee/src/melee/blight.ts +102 -0
  88. package/starters/melee/src/melee/cellLayers.json +11 -0
  89. package/starters/melee/src/melee/data.json +18 -0
  90. package/starters/melee/src/melee/floats.json +199 -0
  91. package/starters/melee/src/melee/formations.ts +46 -0
  92. package/starters/melee/src/melee/fx.json +1 -0
  93. package/starters/melee/src/melee/game.ts +6 -0
  94. package/starters/melee/src/melee/generator.ts +116 -0
  95. package/starters/melee/src/melee/heroSpells.ts +38 -0
  96. package/starters/melee/src/melee/hud.json +269 -0
  97. package/starters/melee/src/melee/index.ts +182 -0
  98. package/starters/melee/src/melee/items.ts +362 -0
  99. package/starters/melee/src/melee/languages/he.json +96 -0
  100. package/starters/melee/src/melee/looks.json +1 -0
  101. package/starters/melee/src/melee/maps.ts +53 -0
  102. package/starters/melee/src/melee/pings.json +16 -0
  103. package/starters/melee/src/melee/pings.ts +34 -0
  104. package/starters/melee/src/melee/quality.json +1 -0
  105. package/starters/melee/src/melee/saves.ts +12 -0
  106. package/starters/melee/src/melee/sounds.json +1 -0
  107. package/starters/melee/src/melee/undead.ts +683 -0
  108. package/starters/melee/src/melee/units.ts +785 -0
  109. package/starters/melee/src/melee/view/buildings.ts +33 -0
  110. package/starters/melee/src/melee/view/cheerLane.ts +42 -0
  111. package/starters/melee/src/melee/view/heroSpellLooks.ts +21 -0
  112. package/starters/melee/src/melee/view/index.ts +268 -0
  113. package/starters/melee/src/melee/view/languages.ts +10 -0
  114. package/starters/melee/src/melee/view/looks.ts +659 -0
  115. package/starters/melee/src/melee/view/undeadLooks.ts +220 -0
  116. package/starters/melee/src/melee/view/walls.ts +59 -0
  117. package/starters/melee/src/rules.ts +24 -0
  118. package/starters.mjs +35 -0
  119. package/v12.mjs +111 -0
@@ -0,0 +1,186 @@
1
+ import { entityDied } from '@v12-engine/engine'
2
+ import {
3
+ defineCommand,
4
+ defineComponent,
5
+ defineEvent,
6
+ defineGameFile,
7
+ defineListener,
8
+ defineTimer,
9
+ earn,
10
+ type Registry,
11
+ type World
12
+ } from '@v12-engine/engine'
13
+ import { ENEMY, MSG, PLAYER, UNIT } from './ids'
14
+ import wavesData from './waves.json'
15
+
16
+ /*
17
+ * The waves of the siege (mission two): who comes out of the war camp, how often, and what beating a wave pays. They
18
+ * are the file `waves.json`, a file of the game's own (`wavesFile`, in `GameModule.files`): each world's registry holds
19
+ * what it plays (`siegeWaves(world)`), which the editor's Waves panel changes as it writes the file (saved with the
20
+ * map, undone like the rest). They go by timers and events: nothing looks at them every tick
21
+ */
22
+
23
+ export interface Wave {
24
+ /** Who comes, in order */
25
+ units: { type: string; count: number }[]
26
+ /** Seconds between one coming out of the camp and the next */
27
+ interval: number
28
+ /** Gold for beating the wave */
29
+ bonus: number
30
+ }
31
+
32
+ /** The waves' file, a file of the game's own: what the game lists (`GameModule.files`), read as waves */
33
+ export const wavesFile = defineGameFile('waves.json', wavesData, readWaves)
34
+
35
+ /** The waves a world, a screen or the editor plays, in order: its registry's (`registry.file`) */
36
+ export const siegeWaves = (of: { readonly registry: Registry }): Wave[] => of.registry.file(wavesFile)
37
+
38
+ /** The waves as the game was built with them, for what has no game to ask (a lane's label in the editor) */
39
+ export const builtWaves = (): Wave[] => wavesFile.read(wavesFile.data)
40
+
41
+ /** Waves as a file says them: what is not a wave of who comes, how often and for how much gold is left out */
42
+ export function readWaves(data: unknown): Wave[] {
43
+ if (!Array.isArray(data)) return []
44
+ return data.flatMap((wave): Wave[] => {
45
+ if (!wave || typeof wave !== 'object' || !Array.isArray(wave.units)) return []
46
+ const units = (wave.units as unknown[]).flatMap((unit) =>
47
+ unit && typeof unit === 'object' && typeof (unit as { type?: unknown }).type === 'string' && Number((unit as { count?: unknown }).count) > 0
48
+ ? [{ type: (unit as { type: string }).type, count: Math.floor(Number((unit as { count: number }).count)) }]
49
+ : []
50
+ )
51
+ const interval = Number(wave.interval)
52
+ const bonus = Number(wave.bonus)
53
+ return units.length ? [{ units, interval: interval > 0 ? interval : 1, bonus: bonus >= 0 ? bonus : 0 }] : []
54
+ })
55
+ }
56
+
57
+ /** Seconds before the first wave, and between one wave being beaten and the next coming */
58
+ export const FIRST_WAIT = 45
59
+ export const BETWEEN_WAVES = 25
60
+
61
+ /** Where the waves come out, and what they go for: points and names of the fort's map */
62
+ export const WAR_CAMP = 'warcamp'
63
+ export const HALL = 'hall'
64
+
65
+ export type Phase = 'idle' | 'waiting' | 'coming' | 'fighting' | 'over'
66
+
67
+ interface WaveState {
68
+ /** The wave that comes next, or is coming: 0 for the first */
69
+ wave: number
70
+ /** `idle` until a mission starts the waves */
71
+ phase: Phase
72
+ /** The timer the next wave waits for, while waiting */
73
+ timer: number
74
+ /** Who of the wave is still to come out, in order */
75
+ queue: string[]
76
+ }
77
+
78
+ /**
79
+ * The state of the waves, kept in the world: what the waves remember belongs to the world, not to the game module,
80
+ * which every world shares. As world state it goes into a save, and so do the timers it waits for
81
+ */
82
+ export const waves = defineComponent<WaveState>('campaign.waves', { default: () => ({ wave: 0, phase: 'idle', timer: 0, queue: [] }) })
83
+
84
+ export const wavesOf = (world: World): WaveState => world.state(waves)
85
+
86
+ /** The Red Hand still standing */
87
+ function raiders(world: World): number {
88
+ let count = 0
89
+ for (const entity of world.index.ownedBy(ENEMY)) if (entity.alive && entity.def.kind === 'unit') count++
90
+ return count
91
+ }
92
+
93
+ /** A wave was beaten: how many are, now. For whoever keeps count, like the mission */
94
+ export const waveBeaten = defineEvent<{ wave: number }>('campaign.waveBeaten')
95
+ /** A wave is coming out of the camp: for the mission (the gate shuts) and the screen (the horn, the flare) */
96
+ export const waveComing = defineEvent<{ wave: number; x: number; z: number }>('campaign.waveComing', { replicate: 'everyone' })
97
+
98
+ /** The next wave is due: its raiders come out of the camp, one every so often */
99
+ const waveComes = defineTimer('campaign.waveComes', (world) => {
100
+ if (world.winner !== null) return
101
+ const state = wavesOf(world)
102
+ const { units, interval } = siegeWaves(world)[state.wave]
103
+ // where Retry goes back to: the start of this wave
104
+ world.checkpoint({ key: MSG.checkpointWave, params: { wave: state.wave + 1 } })
105
+ state.phase = 'coming'
106
+ state.queue = units.flatMap(({ type, count }) => Array.from({ length: count }, () => type))
107
+ world.timers.every(interval, raiderComes, { times: state.queue.length, first: 0 })
108
+ const camp = world.map.point(WAR_CAMP)
109
+ world.events.emit(waveComing, { wave: state.wave + 1, x: camp.x, z: camp.z })
110
+ world.message(PLAYER, { key: MSG.waveComing, params: { wave: state.wave + 1 } }, 'info')
111
+ })
112
+
113
+ /** The next raider of the wave comes out, and goes for the hall. After the last, the wave is fought */
114
+ const raiderComes = defineTimer('campaign.raiderComes', (world, _data, { left }) => {
115
+ if (world.winner !== null) return
116
+ const state = wavesOf(world)
117
+ comeOut(world, state.queue.shift()!)
118
+ if (left === 0) state.phase = 'fighting'
119
+ })
120
+
121
+ /** The last raider of a wave died: the wave is beaten, for gold, and the next one is set to come */
122
+ const lastOfTheWave = defineListener({
123
+ event: entityDied,
124
+ id: 'campaign.lastOfTheWave',
125
+ run(world, { entity }) {
126
+ const state = wavesOf(world)
127
+ if (entity.owner !== ENEMY || state.phase !== 'fighting' || raiders(world) > 0 || world.winner !== null) return
128
+ const { bonus } = siegeWaves(world)[state.wave]
129
+ earn(world.player(PLAYER).resources, 'gold', bonus)
130
+ if (bonus) world.message(PLAYER, { key: MSG.waveBeaten, params: { wave: state.wave + 1, bonus } }, 'info')
131
+ state.wave++
132
+ world.events.emit(waveBeaten, { wave: state.wave })
133
+ if (state.wave >= siegeWaves(world).length) state.phase = 'over'
134
+ else waitForWave(world, BETWEEN_WAVES)
135
+ }
136
+ })
137
+
138
+ /** Waits for the next wave, `seconds` from now */
139
+ function waitForWave(world: World, seconds: number): void {
140
+ const state = wavesOf(world)
141
+ state.phase = 'waiting'
142
+ state.timer = world.timers.after(seconds, waveComes)
143
+ }
144
+
145
+ /** Sets the first wave to come. Called once, as the siege begins */
146
+ export const startWaves = (world: World) => waitForWave(world, FIRST_WAIT)
147
+
148
+ /** A raider comes out of the camp and goes for the hall: the order goes in as a command, the way every order does */
149
+ function comeOut(world: World, type: string): void {
150
+ const camp = world.map.point(WAR_CAMP)
151
+ const raider = world.spawn(type, ENEMY, camp, { facing: camp.facing })
152
+ const hall = world.named(HALL)
153
+ const order = hall?.alive
154
+ ? { type: 'attack', target: hall.id }
155
+ : { type: 'move', point: { x: world.terrain.width / 2, z: world.terrain.depth / 2 } }
156
+ world.issue({ type: 'order', player: ENEMY, entities: [raider.id], order })
157
+ }
158
+
159
+ /** Brings the next wave on now, instead of waiting for it. The seconds that were left are paid out in gold */
160
+ export const nextWave = defineCommand('nextWave', {}, (world, player) => {
161
+ const state = wavesOf(world)
162
+ if (player !== PLAYER || state.phase !== 'waiting' || world.winner !== null) return
163
+ earn(world.player(PLAYER).resources, 'gold', Math.ceil(world.timers.left(state.timer) ?? 0))
164
+ world.timers.cancel(state.timer)
165
+ waveComes.run(world, undefined, { id: state.timer, left: 0 })
166
+ })
167
+
168
+ /** What of the waves goes into the game module: the timers, so that a save finds them, and the listener */
169
+ export const waveTimers = [waveComes, raiderComes]
170
+ export const waveListeners = [lastOfTheWave]
171
+
172
+ /** What the player is told about the waves, for the HUD: see `GameModule.report`. Nothing until a mission starts them */
173
+ export function reportWaves(world: World): Record<string, unknown> {
174
+ const state = wavesOf(world)
175
+ if (state.phase === 'idle') return {}
176
+ return {
177
+ wave: Math.min(state.wave + 1, siegeWaves(world).length),
178
+ waves: siegeWaves(world).length,
179
+ phase: world.winner !== null ? 'over' : state.phase,
180
+ countdown: state.phase === 'waiting' ? Math.ceil(world.timers.left(state.timer) ?? 0) : 0,
181
+ left: raiders(world) + state.queue.length
182
+ }
183
+ }
184
+
185
+ /** The types the Waves panel offers */
186
+ export const WAVE_UNITS = [UNIT.raider, UNIT.warlock, UNIT.brute] as const
@@ -0,0 +1,43 @@
1
+ import { defineEditorExtension, type EditorIcon, type SearchSource } from '@v12-engine/editor'
2
+ import { siegeWaves } from './campaign/waves'
3
+ import { waveLane } from './campaign/view/waveLane'
4
+ import { wavesPanel } from './waves-panel'
5
+
6
+ /*
7
+ * What the campaign adds to its map editor: the Waves panel (`src/waves-panel.ts`), its icon, each wave in the search
8
+ * of everything, and its own lane of cinematics (`waveLane`). Declared as one extension (`defineEditorExtension`): the editor scene lists it
9
+ * (`extensions`), and saved while the editor is open (`npm run dev`) it is taken as it is
10
+ */
11
+
12
+ /** The campaign's own icons in its editor, by name: waves, drawn as the editor's own are (a line, in the colour of the words) */
13
+ export const editorIcons: Record<string, EditorIcon> = {
14
+ 'campaign.wave':
15
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 6c.6.5 1.2 1 2.5 1C7 7 7 5 9.5 5c2.6 0 2.4 2 5 2 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"/><path d="M2 12c.6.5 1.2 1 2.5 1 2.5 0 2.5-2 5-2 2.6 0 2.4 2 5 2 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"/><path d="M2 18c.6.5 1.2 1 2.5 1 2.5 0 2.5-2 5-2 2.6 0 2.4 2 5 2 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"/></svg>'
16
+ }
17
+
18
+ /** What the campaign adds to its editor's search: the missions' maps by name, to open */
19
+ export const editorSearch: SearchSource[] = [
20
+ {
21
+ id: 'campaign.waves',
22
+ name: 'The siege',
23
+ entries: (editor) =>
24
+ siegeWaves(editor).map((wave, index) => ({
25
+ id: `wave:${index}`,
26
+ label: `Wave ${index + 1} of the siege`,
27
+ kind: 'Wave',
28
+ words: wave.units.map((unit) => unit.type).join(' '),
29
+ run: (client) => client.panels.api('campaign.waves')?.pick(index)
30
+ }))
31
+ }
32
+ ]
33
+
34
+ export const campaignEditor = defineEditorExtension({
35
+ id: 'campaign',
36
+ name: 'The campaign',
37
+ panels: [wavesPanel],
38
+ icons: editorIcons,
39
+ search: editorSearch,
40
+ // the game's own lane of cinematics: the view plays it (`lanes` there), and here it is in the Cinematic panel with
41
+ // its fields, its ring on the map and its check, as the client's own lanes are
42
+ lanes: [waveLane]
43
+ })
@@ -0,0 +1,2 @@
1
+ /** The game, whole: the campaign's rules and how it looks (`src/campaign/game.ts`, its view in `src/campaign/view`) */
2
+ export { campaignGame as game } from './campaign/game'
@@ -0,0 +1,70 @@
1
+ /**
2
+ * The page: the game's start screen, and what it goes to from there, each a screen of an app of scenes (`startApp`,
3
+ * `@v12-engine/client/app`), one shown at a time. `appScenes` makes the start screen, the game, a random map when the
4
+ * rules have a generator, and the settings; the campaign adds its own menu and its mission scene
5
+ * (`src/campaign/scenes.ts`). Free play plays a map with its mission's rules and nothing kept.
6
+ // @if editor
7
+ * The map editor too, set up in `src/editor.ts`.
8
+ // @end
9
+ // @if server
10
+ * A seat at the game's server too (`npm run server`).
11
+ // @end
12
+ * The list is a plain array and its scenes plain objects: add a scene of your own, take one away, or change one. The
13
+ * address opens straight into a scene by its id (`sceneAsked`: `/?settings`, and those the README says), the start
14
+ * screen otherwise. The debug panel (🐞 on the top bar, Alt+Shift+D) and its cheats are in the game while developing
15
+ * (`npm run dev`), not in a built page: `debug` says otherwise
16
+ */
17
+ import { appScenes, type MenuScene, sceneAsked, startApp } from '@v12-engine/client/app'
18
+ import '@v12-engine/client/styles.css'
19
+ // the theme's typefaces come with the client: the page's own font stays what it was
20
+ import '@v12-engine/client/fonts.css'
21
+ import { theLongRoad } from './campaign/scenes'
22
+ // @if editor
23
+ import { editor } from './editor'
24
+ // @end
25
+ import { DEFAULT_MAP, maps } from './maps'
26
+ import { rules, start } from './rules'
27
+
28
+ const scenes = appScenes({
29
+ // the game's code (its looks, and the client that draws them) fetched as a scene first plays it: the start screen
30
+ // shows at once, its rules telling it what to say of the game
31
+ game: () => import('./game').then((module) => module.game),
32
+ rules,
33
+ maps,
34
+ map: DEFAULT_MAP,
35
+ start,
36
+ // @if editor
37
+ editor,
38
+ // @end
39
+ // @if single
40
+ server: true,
41
+ // @end
42
+ // @if rooms
43
+ server: { rooms: true },
44
+ // @end
45
+ menu: {
46
+ description: 'A campaign made with V12: three missions, a hero carried from one to the next.',
47
+ details: [{ label: 'Missions', value: 'three, played in order' }]
48
+ },
49
+ // the Credits on the start screen (`creditsScene`): who made the game, by parts, scrolling
50
+ credits: {
51
+ sections: [
52
+ { title: 'Made by', names: ['You'] },
53
+ { title: 'Made with', names: ['V12'] }
54
+ ]
55
+ }
56
+ })
57
+
58
+ // the campaign's menu and missions among the scenes, its button first on the start screen
59
+ scenes.push(...theLongRoad.scenes)
60
+ const home = scenes.find((scene) => scene.id === 'home') as MenuScene
61
+ home.buttons.unshift({ label: 'Campaign', scene: theLongRoad.menu })
62
+ // the game on its own is Free play: a map with its mission's rules, nothing carried or kept
63
+ for (const scene of scenes) if (scene.id === 'play') scene.name = 'Free play'
64
+ for (const button of home.buttons) if (button.scene?.id === 'play') button.label = 'Free play'
65
+
66
+ /** The ground's textures made in a worker of the page's (`src/ground.worker.ts`), made at the first texture: the page goes on while they are made */
67
+ const groundWorker = () => new Worker(new URL('./ground.worker.ts', import.meta.url), { type: 'module' })
68
+
69
+ const app = startApp({ target: '#game', title: rules.name, scenes, start: sceneAsked(scenes, 'home'), groundWorker })
70
+ Object.assign(window, { app })
@@ -0,0 +1,31 @@
1
+ // Written by the map editor with fort.vgmap.json, anew with every save: not to be changed by hand
2
+
3
+ /** What is named on the map, for `world.named<FortNames>(...)` */
4
+ export type FortNames =
5
+ | 'hall'
6
+ | 'hero'
7
+
8
+ /** The camps that are named on the map, for `campNamed(world, ...)` */
9
+ export type FortCamps = never
10
+
11
+ /** The regions of the map, for `world.areas` and `enteredArea` */
12
+ export type FortRegions = never
13
+
14
+ /** The points of the map, for `world.map.point(...)` */
15
+ export type FortPoints =
16
+ | 'warcamp'
17
+
18
+ /** The paths of the map, for `world.map.path(...)` */
19
+ export type FortPaths =
20
+ | 'road'
21
+
22
+ /** The lights of the map that are named, for `client.lights.named(...)` */
23
+ export type FortLights =
24
+ | 'bonfire'
25
+
26
+ /** The effects of the map that are named, for `client.mapEffects.named(...)` */
27
+ export type FortEffects =
28
+ | 'bonfire'
29
+
30
+ /** The ids of the regions, points and paths by name: what a field that names one keeps (it is handed the name) */
31
+ export const FortIds = { regions: { }, points: { "warcamp": 28 }, paths: { "road": 1 } } as const