@almadar/std 2.1.1 → 2.4.1

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 (86) hide show
  1. package/dist/behaviors/async.d.ts +12 -7
  2. package/dist/behaviors/async.js +1085 -312
  3. package/dist/behaviors/async.js.map +1 -1
  4. package/dist/behaviors/data-management.d.ts +27 -13
  5. package/dist/behaviors/data-management.js +600 -244
  6. package/dist/behaviors/data-management.js.map +1 -1
  7. package/dist/behaviors/domain/commerce.d.ts +51 -0
  8. package/dist/behaviors/domain/commerce.js +1093 -0
  9. package/dist/behaviors/domain/commerce.js.map +1 -0
  10. package/dist/behaviors/domain/content.d.ts +51 -0
  11. package/dist/behaviors/domain/content.js +1294 -0
  12. package/dist/behaviors/domain/content.js.map +1 -0
  13. package/dist/behaviors/domain/dashboard.d.ts +45 -0
  14. package/dist/behaviors/domain/dashboard.js +783 -0
  15. package/dist/behaviors/domain/dashboard.js.map +1 -0
  16. package/dist/behaviors/domain/education.d.ts +41 -0
  17. package/dist/behaviors/domain/education.js +738 -0
  18. package/dist/behaviors/domain/education.js.map +1 -0
  19. package/dist/behaviors/domain/finance.d.ts +49 -0
  20. package/dist/behaviors/domain/finance.js +660 -0
  21. package/dist/behaviors/domain/finance.js.map +1 -0
  22. package/dist/behaviors/domain/game-2d-platformer.d.ts +50 -0
  23. package/dist/behaviors/domain/game-2d-platformer.js +810 -0
  24. package/dist/behaviors/domain/game-2d-platformer.js.map +1 -0
  25. package/dist/behaviors/domain/game-2d-puzzle.d.ts +42 -0
  26. package/dist/behaviors/domain/game-2d-puzzle.js +622 -0
  27. package/dist/behaviors/domain/game-2d-puzzle.js.map +1 -0
  28. package/dist/behaviors/domain/game-2d-rpg.d.ts +48 -0
  29. package/dist/behaviors/domain/game-2d-rpg.js +860 -0
  30. package/dist/behaviors/domain/game-2d-rpg.js.map +1 -0
  31. package/dist/behaviors/domain/game-2d-strategy.d.ts +48 -0
  32. package/dist/behaviors/domain/game-2d-strategy.js +692 -0
  33. package/dist/behaviors/domain/game-2d-strategy.js.map +1 -0
  34. package/dist/behaviors/domain/geospatial.d.ts +35 -0
  35. package/dist/behaviors/domain/geospatial.js +634 -0
  36. package/dist/behaviors/domain/geospatial.js.map +1 -0
  37. package/dist/behaviors/domain/healthcare.d.ts +36 -0
  38. package/dist/behaviors/domain/healthcare.js +1068 -0
  39. package/dist/behaviors/domain/healthcare.js.map +1 -0
  40. package/dist/behaviors/domain/iot.d.ts +45 -0
  41. package/dist/behaviors/domain/iot.js +589 -0
  42. package/dist/behaviors/domain/iot.js.map +1 -0
  43. package/dist/behaviors/domain/media.d.ts +41 -0
  44. package/dist/behaviors/domain/media.js +771 -0
  45. package/dist/behaviors/domain/media.js.map +1 -0
  46. package/dist/behaviors/domain/scheduling.d.ts +41 -0
  47. package/dist/behaviors/domain/scheduling.js +930 -0
  48. package/dist/behaviors/domain/scheduling.js.map +1 -0
  49. package/dist/behaviors/domain/simulation.d.ts +36 -0
  50. package/dist/behaviors/domain/simulation.js +706 -0
  51. package/dist/behaviors/domain/simulation.js.map +1 -0
  52. package/dist/behaviors/domain/social.d.ts +41 -0
  53. package/dist/behaviors/domain/social.js +840 -0
  54. package/dist/behaviors/domain/social.js.map +1 -0
  55. package/dist/behaviors/domain/workflow.d.ts +41 -0
  56. package/dist/behaviors/domain/workflow.js +879 -0
  57. package/dist/behaviors/domain/workflow.js.map +1 -0
  58. package/dist/behaviors/feedback.d.ts +10 -5
  59. package/dist/behaviors/feedback.js +279 -194
  60. package/dist/behaviors/feedback.js.map +1 -1
  61. package/dist/behaviors/game-core.d.ts +15 -8
  62. package/dist/behaviors/game-core.js +412 -80
  63. package/dist/behaviors/game-core.js.map +1 -1
  64. package/dist/behaviors/game-entity.d.ts +17 -10
  65. package/dist/behaviors/game-entity.js +544 -237
  66. package/dist/behaviors/game-entity.js.map +1 -1
  67. package/dist/behaviors/game-ui.d.ts +16 -8
  68. package/dist/behaviors/game-ui.js +451 -316
  69. package/dist/behaviors/game-ui.js.map +1 -1
  70. package/dist/behaviors/index.d.ts +18 -1
  71. package/dist/behaviors/index.js +18905 -2140
  72. package/dist/behaviors/index.js.map +1 -1
  73. package/dist/behaviors/infrastructure.d.ts +9 -8
  74. package/dist/behaviors/infrastructure.js +597 -169
  75. package/dist/behaviors/infrastructure.js.map +1 -1
  76. package/dist/behaviors/registry.d.ts +11 -11
  77. package/dist/behaviors/registry.js +18904 -2139
  78. package/dist/behaviors/registry.js.map +1 -1
  79. package/dist/behaviors/types.d.ts +19 -2
  80. package/dist/behaviors/types.js.map +1 -1
  81. package/dist/behaviors/ui-interaction.d.ts +20 -14
  82. package/dist/behaviors/ui-interaction.js +928 -518
  83. package/dist/behaviors/ui-interaction.js.map +1 -1
  84. package/dist/index.js +18906 -2141
  85. package/dist/index.js.map +1 -1
  86. package/package.json +1 -1
@@ -1,4 +1,217 @@
1
1
  // behaviors/game-entity.ts
2
+ var GAME_ENTITY_THEME = {
3
+ name: "game-entity-rose",
4
+ tokens: {
5
+ colors: {
6
+ primary: "#e11d48",
7
+ "primary-hover": "#be123c",
8
+ "primary-foreground": "#ffffff",
9
+ accent: "#fb7185",
10
+ "accent-foreground": "#000000",
11
+ success: "#22c55e",
12
+ warning: "#f59e0b",
13
+ error: "#ef4444"
14
+ }
15
+ }
16
+ };
17
+ var KFLOW_ASSETS = "https://almadar-kflow-assets.web.app/shared";
18
+ var GAME_MANIFEST = {
19
+ terrain: {
20
+ stone: "/terrain/Isometric/stoneSide_N.png",
21
+ dirt: "/terrain/Isometric/dirt_N.png",
22
+ bridge: "/terrain/Isometric/stoneStep_N.png",
23
+ wall: "/terrain/Isometric/stoneWallArchway_N.png"
24
+ },
25
+ units: {
26
+ guardian: "/sprite-sheets/guardian-sprite-sheet-se.png",
27
+ breaker: "/sprite-sheets/breaker-sprite-sheet-se.png",
28
+ archivist: "/sprite-sheets/archivist-sprite-sheet-se.png"
29
+ },
30
+ features: {
31
+ gold_mine: "/world-map/gold_mine.png",
32
+ portal: "/world-map/portal_open.png",
33
+ treasure: "/world-map/treasure_chest_closed.png"
34
+ }
35
+ };
36
+ var TILES_5X5 = [
37
+ { x: 0, y: 0, terrain: "stone" },
38
+ { x: 1, y: 0, terrain: "dirt" },
39
+ { x: 2, y: 0, terrain: "stone" },
40
+ { x: 3, y: 0, terrain: "dirt" },
41
+ { x: 4, y: 0, terrain: "stone" },
42
+ { x: 0, y: 1, terrain: "dirt" },
43
+ { x: 1, y: 1, terrain: "stone" },
44
+ { x: 2, y: 1, terrain: "dirt" },
45
+ { x: 3, y: 1, terrain: "stone" },
46
+ { x: 4, y: 1, terrain: "dirt" },
47
+ { x: 0, y: 2, terrain: "stone" },
48
+ { x: 1, y: 2, terrain: "dirt" },
49
+ { x: 2, y: 2, terrain: "bridge" },
50
+ { x: 3, y: 2, terrain: "dirt" },
51
+ { x: 4, y: 2, terrain: "stone" },
52
+ { x: 0, y: 3, terrain: "dirt" },
53
+ { x: 1, y: 3, terrain: "stone" },
54
+ { x: 2, y: 3, terrain: "dirt" },
55
+ { x: 3, y: 3, terrain: "stone" },
56
+ { x: 4, y: 3, terrain: "dirt" },
57
+ { x: 0, y: 4, terrain: "stone" },
58
+ { x: 1, y: 4, terrain: "dirt" },
59
+ { x: 2, y: 4, terrain: "stone" },
60
+ { x: 3, y: 4, terrain: "wall" },
61
+ { x: 4, y: 4, terrain: "stone" }
62
+ ];
63
+ var healthCanvasView = ["render-ui", "main", {
64
+ type: "isometric-canvas",
65
+ tiles: TILES_5X5,
66
+ units: [{ id: "guardian-1", unitType: "guardian", x: 2, y: 2 }],
67
+ scale: 1,
68
+ boardWidth: 5,
69
+ boardHeight: 5,
70
+ enableCamera: true,
71
+ assetBaseUrl: KFLOW_ASSETS,
72
+ assetManifest: GAME_MANIFEST,
73
+ tileClickEvent: "TILE_CLICK",
74
+ unitClickEvent: "UNIT_CLICK"
75
+ }];
76
+ var healthOverlayView = ["render-ui", "overlay", {
77
+ type: "game-hud",
78
+ elements: [
79
+ { type: "stat", label: "HP", value: "@entity.currentHealth", icon: "heart" },
80
+ { type: "stat", label: "Max HP", value: "@entity.maxHealth", icon: "heart" },
81
+ { type: "stat", label: "Invulnerable", value: "@entity.isInvulnerable", icon: "shield" },
82
+ { type: "button", label: "Damage", action: "DAMAGE", icon: "sword", variant: "secondary" },
83
+ { type: "button", label: "Heal", action: "HEAL", icon: "heart", variant: "primary" },
84
+ { type: "button", label: "Respawn", action: "RESPAWN", icon: "refresh-cw", variant: "secondary" }
85
+ ]
86
+ }];
87
+ var healthDamageEffectOverlay = ["render-ui", "overlay", {
88
+ type: "canvas-effect",
89
+ actionType: "hit",
90
+ x: 200,
91
+ y: 200,
92
+ duration: 600
93
+ }];
94
+ var scoreCanvasView = ["render-ui", "main", {
95
+ type: "isometric-canvas",
96
+ tiles: TILES_5X5,
97
+ units: [{ id: "scorer-1", unitType: "guardian", x: 2, y: 2 }],
98
+ scale: 1,
99
+ boardWidth: 5,
100
+ boardHeight: 5,
101
+ enableCamera: true,
102
+ assetBaseUrl: KFLOW_ASSETS,
103
+ assetManifest: GAME_MANIFEST,
104
+ tileClickEvent: "TILE_CLICK",
105
+ unitClickEvent: "UNIT_CLICK"
106
+ }];
107
+ var scoreOverlayView = ["render-ui", "overlay", {
108
+ type: "game-hud",
109
+ elements: [
110
+ { type: "stat", label: "Score", value: "@entity.currentScore", icon: "star" },
111
+ { type: "stat", label: "High Score", value: "@entity.highScore", icon: "award" },
112
+ { type: "stat", label: "Combo", value: "@entity.comboCount", icon: "zap" },
113
+ { type: "stat", label: "Multiplier", value: "@entity.multiplier", icon: "trending-up" },
114
+ { type: "button", label: "Add Points", action: "ADD_POINTS", icon: "plus", variant: "primary" },
115
+ { type: "button", label: "Reset", action: "RESET", icon: "refresh-cw", variant: "secondary" }
116
+ ]
117
+ }];
118
+ var movementCanvasView = ["render-ui", "main", {
119
+ type: "isometric-canvas",
120
+ tiles: TILES_5X5,
121
+ units: [{ id: "mover-1", unitType: "guardian", x: 2, y: 2 }],
122
+ scale: 1,
123
+ boardWidth: 5,
124
+ boardHeight: 5,
125
+ enableCamera: true,
126
+ assetBaseUrl: KFLOW_ASSETS,
127
+ assetManifest: GAME_MANIFEST,
128
+ tileClickEvent: "TILE_CLICK",
129
+ unitClickEvent: "UNIT_CLICK"
130
+ }];
131
+ var movementOverlayView = ["render-ui", "overlay", {
132
+ type: "game-hud",
133
+ elements: [
134
+ { type: "stat", label: "X", value: "@entity.x", icon: "arrow-right" },
135
+ { type: "stat", label: "Y", value: "@entity.y", icon: "arrow-up" },
136
+ { type: "stat", label: "Speed", value: "@entity.moveSpeed", icon: "gauge" },
137
+ { type: "stat", label: "Direction", value: "@entity.direction", icon: "compass" },
138
+ { type: "button", label: "Move Left", action: "MOVE_LEFT", icon: "arrow-left", variant: "secondary" },
139
+ { type: "button", label: "Move Right", action: "MOVE_RIGHT", icon: "arrow-right", variant: "secondary" },
140
+ { type: "button", label: "Jump", action: "JUMP", icon: "arrow-big-up", variant: "primary" },
141
+ { type: "button", label: "Stop", action: "STOP", icon: "square", variant: "secondary" }
142
+ ]
143
+ }];
144
+ var combatCanvasView = ["render-ui", "main", {
145
+ type: "isometric-canvas",
146
+ tiles: TILES_5X5,
147
+ units: [
148
+ { id: "attacker-1", unitType: "guardian", x: 1, y: 2 },
149
+ { id: "target-1", unitType: "breaker", x: 3, y: 2 }
150
+ ],
151
+ scale: 1,
152
+ boardWidth: 5,
153
+ boardHeight: 5,
154
+ enableCamera: true,
155
+ assetBaseUrl: KFLOW_ASSETS,
156
+ assetManifest: GAME_MANIFEST,
157
+ tileClickEvent: "TILE_CLICK",
158
+ unitClickEvent: "UNIT_CLICK"
159
+ }];
160
+ var combatLogOverlay = ["render-ui", "overlay", {
161
+ type: "combat-log",
162
+ events: [],
163
+ maxVisible: 10,
164
+ title: "Battle Log"
165
+ }];
166
+ var combatHudOverlay = ["render-ui", "overlay", {
167
+ type: "game-hud",
168
+ elements: [
169
+ { type: "stat", label: "Damage", value: "@entity.attackDamage", icon: "sword" },
170
+ { type: "stat", label: "Duration", value: "@entity.attackDuration", icon: "timer" },
171
+ { type: "stat", label: "Cooldown", value: "@entity.cooldownDuration", icon: "clock" },
172
+ { type: "stat", label: "Hit Count", value: "@entity.hitCount", icon: "target" },
173
+ { type: "button", label: "Attack", action: "ATTACK", icon: "sword", variant: "primary" },
174
+ { type: "button", label: "Defend", action: "DEFEND", icon: "shield", variant: "secondary" }
175
+ ]
176
+ }];
177
+ var combatAttackEffect = ["render-ui", "overlay", {
178
+ type: "canvas-effect",
179
+ actionType: "melee",
180
+ x: 200,
181
+ y: 200,
182
+ duration: 600
183
+ }];
184
+ var inventoryBrowseView = ["render-ui", "main", {
185
+ type: "inventory-panel",
186
+ items: "@entity",
187
+ slots: 12,
188
+ columns: 4,
189
+ selectSlotEvent: "SELECT",
190
+ showTooltips: true
191
+ }];
192
+ var inventoryDetailView = ["render-ui", "main", {
193
+ type: "stack",
194
+ direction: "vertical",
195
+ children: [
196
+ { type: "stack", direction: "horizontal", children: [
197
+ { type: "icon", name: "package" },
198
+ { type: "typography", content: "Item Detail", variant: "h2" }
199
+ ] },
200
+ { type: "divider" },
201
+ { type: "stack", direction: "vertical", gap: "md", children: [
202
+ { type: "typography", content: "@entity.name", variant: "h2" },
203
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
204
+ { type: "typography", content: "Quantity:", variant: "body" },
205
+ { type: "typography", content: "@entity.quantity", variant: "body" }
206
+ ] },
207
+ { type: "stack", direction: "horizontal", gap: "sm", children: [
208
+ { type: "typography", content: "Slot:", variant: "body" },
209
+ { type: "typography", content: "@entity.slot", variant: "body" }
210
+ ] },
211
+ { type: "badge", label: "@entity.isEquipped", variant: "outline" }
212
+ ] }
213
+ ]
214
+ }];
2
215
  var HEALTH_BEHAVIOR = {
3
216
  name: "std-health",
4
217
  version: "1.0.0",
@@ -6,8 +219,9 @@ var HEALTH_BEHAVIOR = {
6
219
  orbitals: [
7
220
  {
8
221
  name: "HealthOrbital",
222
+ theme: GAME_ENTITY_THEME,
9
223
  entity: {
10
- name: "HealthState",
224
+ name: "HealthData",
11
225
  persistence: "runtime",
12
226
  fields: [
13
227
  { name: "id", type: "string", required: true },
@@ -15,26 +229,32 @@ var HEALTH_BEHAVIOR = {
15
229
  { name: "maxHealth", type: "number", default: 100 },
16
230
  { name: "isInvulnerable", type: "boolean", default: false },
17
231
  { name: "lastDamageTime", type: "number", default: 0 },
18
- { name: "invulnerabilityTime", type: "number", default: 1e3 },
19
- { name: "onDeath", type: "string", default: null }
232
+ { name: "invulnerabilityTime", type: "number", default: 1e3 }
20
233
  ]
21
234
  },
22
235
  traits: [
23
236
  {
24
237
  name: "Health",
25
- linkedEntity: "HealthState",
238
+ linkedEntity: "HealthData",
26
239
  category: "interaction",
27
240
  stateMachine: {
28
241
  states: [
29
242
  { name: "Alive", isInitial: true },
30
243
  { name: "Damaged" },
31
- { name: "Invulnerable" },
32
- { name: "Dead", isTerminal: true }
244
+ { name: "Dead" }
33
245
  ],
34
246
  events: [
35
247
  { key: "INIT", name: "Initialize" },
36
- { key: "DAMAGE", name: "Damage" },
37
- { key: "HEAL", name: "Heal" },
248
+ {
249
+ key: "DAMAGE",
250
+ name: "Damage",
251
+ payloadSchema: [{ name: "amount", type: "number", required: true }]
252
+ },
253
+ {
254
+ key: "HEAL",
255
+ name: "Heal",
256
+ payloadSchema: [{ name: "amount", type: "number", required: true }]
257
+ },
38
258
  { key: "DIE", name: "Die" },
39
259
  { key: "RESPAWN", name: "Respawn" },
40
260
  { key: "INVULNERABILITY_END", name: "Invulnerability End" }
@@ -45,13 +265,11 @@ var HEALTH_BEHAVIOR = {
45
265
  to: "Alive",
46
266
  event: "INIT",
47
267
  effects: [
268
+ ["fetch", "HealthData"],
48
269
  ["set", "@entity.currentHealth", "@entity.maxHealth"],
49
270
  ["set", "@entity.isInvulnerable", false],
50
- ["render-ui", "hud-top", {
51
- type: "stats",
52
- label: "Health",
53
- value: "@entity.currentHealth"
54
- }]
271
+ healthCanvasView,
272
+ healthOverlayView
55
273
  ]
56
274
  },
57
275
  {
@@ -60,37 +278,62 @@ var HEALTH_BEHAVIOR = {
60
278
  event: "DAMAGE",
61
279
  guard: ["not", "@entity.isInvulnerable"],
62
280
  effects: [
281
+ ["fetch", "HealthData"],
63
282
  ["set", "@entity.currentHealth", ["math/max", 0, ["-", "@entity.currentHealth", "@payload.amount"]]],
64
283
  ["set", "@entity.lastDamageTime", "@now"],
65
- [
66
- "if",
67
- ["<=", "@entity.currentHealth", 0],
68
- ["emit", "DIE"],
69
- [
70
- "do",
71
- ["set", "@entity.isInvulnerable", true]
72
- ]
73
- ]
284
+ ["set", "@entity.isInvulnerable", true],
285
+ healthCanvasView,
286
+ healthOverlayView,
287
+ healthDamageEffectOverlay
74
288
  ]
75
289
  },
76
290
  {
77
291
  from: "Damaged",
78
- to: "Alive",
79
- event: "INVULNERABILITY_END",
80
- effects: [["set", "@entity.isInvulnerable", false]]
292
+ to: "Dead",
293
+ event: "DAMAGE",
294
+ guard: ["<=", "@entity.currentHealth", 0],
295
+ effects: [
296
+ ["fetch", "HealthData"],
297
+ ["set", "@entity.currentHealth", 0],
298
+ healthCanvasView,
299
+ healthOverlayView
300
+ ]
301
+ },
302
+ {
303
+ from: "Damaged",
304
+ to: "Damaged",
305
+ event: "DAMAGE",
306
+ guard: ["and", ["not", "@entity.isInvulnerable"], [">", "@entity.currentHealth", 0]],
307
+ effects: [
308
+ ["fetch", "HealthData"],
309
+ ["set", "@entity.currentHealth", ["math/max", 0, ["-", "@entity.currentHealth", "@payload.amount"]]],
310
+ ["set", "@entity.lastDamageTime", "@now"],
311
+ ["set", "@entity.isInvulnerable", true],
312
+ healthCanvasView,
313
+ healthOverlayView,
314
+ healthDamageEffectOverlay
315
+ ]
81
316
  },
82
317
  {
83
- from: "Invulnerable",
318
+ from: "Damaged",
84
319
  to: "Alive",
85
320
  event: "INVULNERABILITY_END",
86
- effects: [["set", "@entity.isInvulnerable", false]]
321
+ effects: [
322
+ ["fetch", "HealthData"],
323
+ ["set", "@entity.isInvulnerable", false],
324
+ healthCanvasView,
325
+ healthOverlayView
326
+ ]
87
327
  },
88
328
  {
89
329
  from: "Alive",
90
330
  to: "Alive",
91
331
  event: "HEAL",
92
332
  effects: [
93
- ["set", "@entity.currentHealth", ["math/min", "@entity.maxHealth", ["+", "@entity.currentHealth", "@payload.amount"]]]
333
+ ["fetch", "HealthData"],
334
+ ["set", "@entity.currentHealth", ["math/min", "@entity.maxHealth", ["+", "@entity.currentHealth", "@payload.amount"]]],
335
+ healthCanvasView,
336
+ healthOverlayView
94
337
  ]
95
338
  },
96
339
  {
@@ -98,7 +341,10 @@ var HEALTH_BEHAVIOR = {
98
341
  to: "Damaged",
99
342
  event: "HEAL",
100
343
  effects: [
101
- ["set", "@entity.currentHealth", ["math/min", "@entity.maxHealth", ["+", "@entity.currentHealth", "@payload.amount"]]]
344
+ ["fetch", "HealthData"],
345
+ ["set", "@entity.currentHealth", ["math/min", "@entity.maxHealth", ["+", "@entity.currentHealth", "@payload.amount"]]],
346
+ healthCanvasView,
347
+ healthOverlayView
102
348
  ]
103
349
  },
104
350
  {
@@ -106,8 +352,10 @@ var HEALTH_BEHAVIOR = {
106
352
  to: "Dead",
107
353
  event: "DIE",
108
354
  effects: [
355
+ ["fetch", "HealthData"],
109
356
  ["set", "@entity.currentHealth", 0],
110
- ["if", "@entity.onDeath", ["emit", "@entity.onDeath", { entityId: "@entity.id" }]]
357
+ healthCanvasView,
358
+ healthOverlayView
111
359
  ]
112
360
  },
113
361
  {
@@ -115,15 +363,23 @@ var HEALTH_BEHAVIOR = {
115
363
  to: "Dead",
116
364
  event: "DIE",
117
365
  effects: [
366
+ ["fetch", "HealthData"],
118
367
  ["set", "@entity.currentHealth", 0],
119
- ["if", "@entity.onDeath", ["emit", "@entity.onDeath", { entityId: "@entity.id" }]]
368
+ healthCanvasView,
369
+ healthOverlayView
120
370
  ]
121
371
  },
122
372
  {
123
373
  from: "Dead",
124
374
  to: "Alive",
125
375
  event: "RESPAWN",
126
- effects: [["emit", "INIT"]]
376
+ effects: [
377
+ ["fetch", "HealthData"],
378
+ ["set", "@entity.currentHealth", "@entity.maxHealth"],
379
+ ["set", "@entity.isInvulnerable", false],
380
+ healthCanvasView,
381
+ healthOverlayView
382
+ ]
127
383
  }
128
384
  ]
129
385
  },
@@ -132,12 +388,21 @@ var HEALTH_BEHAVIOR = {
132
388
  name: "InvulnerabilityTimer",
133
389
  interval: "frame",
134
390
  guard: ["and", "@entity.isInvulnerable", [">", ["-", "@now", "@entity.lastDamageTime"], "@entity.invulnerabilityTime"]],
135
- effects: [["emit", "INVULNERABILITY_END"]]
391
+ effects: [
392
+ ["set", "@entity.isInvulnerable", false]
393
+ ]
136
394
  }
137
395
  ]
138
396
  }
139
397
  ],
140
- pages: []
398
+ pages: [
399
+ {
400
+ name: "HealthPage",
401
+ path: "/health",
402
+ isInitial: true,
403
+ traits: [{ ref: "Health" }]
404
+ }
405
+ ]
141
406
  }
142
407
  ]
143
408
  };
@@ -148,8 +413,9 @@ var SCORE_BEHAVIOR = {
148
413
  orbitals: [
149
414
  {
150
415
  name: "ScoreOrbital",
416
+ theme: GAME_ENTITY_THEME,
151
417
  entity: {
152
- name: "ScoreState",
418
+ name: "ScoreData",
153
419
  persistence: "runtime",
154
420
  fields: [
155
421
  { name: "id", type: "string", required: true },
@@ -165,17 +431,20 @@ var SCORE_BEHAVIOR = {
165
431
  traits: [
166
432
  {
167
433
  name: "Score",
168
- linkedEntity: "ScoreState",
434
+ linkedEntity: "ScoreData",
169
435
  category: "interaction",
170
436
  stateMachine: {
171
437
  states: [{ name: "Active", isInitial: true }],
172
438
  events: [
173
439
  { key: "INIT", name: "Initialize" },
174
- { key: "ADD_POINTS", name: "Add Points" },
440
+ {
441
+ key: "ADD_POINTS",
442
+ name: "Add Points",
443
+ payloadSchema: [{ name: "points", type: "number", required: true }]
444
+ },
175
445
  { key: "COMBO_HIT", name: "Combo Hit" },
176
446
  { key: "COMBO_BREAK", name: "Combo Break" },
177
- { key: "RESET", name: "Reset" },
178
- { key: "SAVE_HIGH_SCORE", name: "Save High Score" }
447
+ { key: "RESET", name: "Reset" }
179
448
  ],
180
449
  transitions: [
181
450
  {
@@ -183,15 +452,12 @@ var SCORE_BEHAVIOR = {
183
452
  to: "Active",
184
453
  event: "INIT",
185
454
  effects: [
455
+ ["fetch", "ScoreData"],
186
456
  ["set", "@entity.currentScore", 0],
187
457
  ["set", "@entity.comboCount", 0],
188
458
  ["set", "@entity.multiplier", 1],
189
- ["render-ui", "hud-top", {
190
- type: "stats",
191
- label: "Score",
192
- value: "@entity.currentScore",
193
- subtitle: "High: @entity.highScore"
194
- }]
459
+ scoreCanvasView,
460
+ scoreOverlayView
195
461
  ]
196
462
  },
197
463
  {
@@ -199,8 +465,11 @@ var SCORE_BEHAVIOR = {
199
465
  to: "Active",
200
466
  event: "ADD_POINTS",
201
467
  effects: [
468
+ ["fetch", "ScoreData"],
202
469
  ["set", "@entity.currentScore", ["+", "@entity.currentScore", ["*", "@payload.points", "@entity.multiplier"]]],
203
- ["set", "@entity.lastScoreTime", "@now"]
470
+ ["set", "@entity.lastScoreTime", "@now"],
471
+ scoreCanvasView,
472
+ scoreOverlayView
204
473
  ]
205
474
  },
206
475
  {
@@ -208,9 +477,12 @@ var SCORE_BEHAVIOR = {
208
477
  to: "Active",
209
478
  event: "COMBO_HIT",
210
479
  effects: [
480
+ ["fetch", "ScoreData"],
211
481
  ["set", "@entity.comboCount", ["+", "@entity.comboCount", 1]],
212
482
  ["set", "@entity.multiplier", ["math/min", "@entity.maxMultiplier", ["+", 1, ["/", "@entity.comboCount", 5]]]],
213
- ["set", "@entity.lastScoreTime", "@now"]
483
+ ["set", "@entity.lastScoreTime", "@now"],
484
+ scoreCanvasView,
485
+ scoreOverlayView
214
486
  ]
215
487
  },
216
488
  {
@@ -218,31 +490,40 @@ var SCORE_BEHAVIOR = {
218
490
  to: "Active",
219
491
  event: "COMBO_BREAK",
220
492
  effects: [
493
+ ["fetch", "ScoreData"],
221
494
  ["set", "@entity.comboCount", 0],
222
- ["set", "@entity.multiplier", 1]
495
+ ["set", "@entity.multiplier", 1],
496
+ scoreCanvasView,
497
+ scoreOverlayView
223
498
  ]
224
499
  },
225
500
  {
226
501
  from: "Active",
227
502
  to: "Active",
228
503
  event: "RESET",
504
+ guard: [">", "@entity.currentScore", "@entity.highScore"],
229
505
  effects: [
230
- [
231
- "if",
232
- [">", "@entity.currentScore", "@entity.highScore"],
233
- ["set", "@entity.highScore", "@entity.currentScore"]
234
- ],
235
- ["emit", "INIT"]
506
+ ["fetch", "ScoreData"],
507
+ ["set", "@entity.highScore", "@entity.currentScore"],
508
+ ["set", "@entity.currentScore", 0],
509
+ ["set", "@entity.comboCount", 0],
510
+ ["set", "@entity.multiplier", 1],
511
+ scoreCanvasView,
512
+ scoreOverlayView
236
513
  ]
237
514
  },
238
515
  {
239
516
  from: "Active",
240
517
  to: "Active",
241
- event: "SAVE_HIGH_SCORE",
242
- guard: [">", "@entity.currentScore", "@entity.highScore"],
518
+ event: "RESET",
519
+ guard: ["<=", "@entity.currentScore", "@entity.highScore"],
243
520
  effects: [
244
- ["set", "@entity.highScore", "@entity.currentScore"],
245
- ["persist", "update", "HighScore", { score: "@entity.highScore" }]
521
+ ["fetch", "ScoreData"],
522
+ ["set", "@entity.currentScore", 0],
523
+ ["set", "@entity.comboCount", 0],
524
+ ["set", "@entity.multiplier", 1],
525
+ scoreCanvasView,
526
+ scoreOverlayView
246
527
  ]
247
528
  }
248
529
  ]
@@ -252,12 +533,22 @@ var SCORE_BEHAVIOR = {
252
533
  name: "ComboTimeout",
253
534
  interval: "frame",
254
535
  guard: ["and", [">", "@entity.comboCount", 0], [">", ["-", "@now", "@entity.lastScoreTime"], "@entity.comboTimeWindow"]],
255
- effects: [["emit", "COMBO_BREAK"]]
536
+ effects: [
537
+ ["set", "@entity.comboCount", 0],
538
+ ["set", "@entity.multiplier", 1]
539
+ ]
256
540
  }
257
541
  ]
258
542
  }
259
543
  ],
260
- pages: []
544
+ pages: [
545
+ {
546
+ name: "ScorePage",
547
+ path: "/score",
548
+ isInitial: true,
549
+ traits: [{ ref: "Score" }]
550
+ }
551
+ ]
261
552
  }
262
553
  ]
263
554
  };
@@ -268,8 +559,9 @@ var MOVEMENT_BEHAVIOR = {
268
559
  orbitals: [
269
560
  {
270
561
  name: "MovementOrbital",
562
+ theme: GAME_ENTITY_THEME,
271
563
  entity: {
272
- name: "MovementState",
564
+ name: "MovementData",
273
565
  persistence: "runtime",
274
566
  fields: [
275
567
  { name: "id", type: "string", required: true },
@@ -279,13 +571,13 @@ var MOVEMENT_BEHAVIOR = {
279
571
  { name: "facingRight", type: "boolean", default: true },
280
572
  { name: "canJump", type: "boolean", default: true },
281
573
  { name: "moveSpeed", type: "number", default: 5 },
282
- { name: "jumpForce", type: "number", default: -15 }
574
+ { name: "jumpForce", type: "number", default: 15 }
283
575
  ]
284
576
  },
285
577
  traits: [
286
578
  {
287
579
  name: "Movement",
288
- linkedEntity: "MovementState",
580
+ linkedEntity: "MovementData",
289
581
  category: "interaction",
290
582
  stateMachine: {
291
583
  states: [
@@ -295,37 +587,88 @@ var MOVEMENT_BEHAVIOR = {
295
587
  { name: "Falling" }
296
588
  ],
297
589
  events: [
298
- { key: "MOVE", name: "Move" },
590
+ { key: "INIT", name: "Initialize" },
591
+ {
592
+ key: "MOVE_RIGHT",
593
+ name: "Move Right"
594
+ },
595
+ {
596
+ key: "MOVE_LEFT",
597
+ name: "Move Left"
598
+ },
299
599
  { key: "STOP", name: "Stop" },
300
600
  { key: "JUMP", name: "Jump" },
301
- { key: "LAND", name: "Land" }
601
+ { key: "LAND", name: "Land" },
602
+ { key: "FALL", name: "Fall" }
302
603
  ],
303
604
  transitions: [
304
605
  {
305
606
  from: "Idle",
607
+ to: "Idle",
608
+ event: "INIT",
609
+ effects: [
610
+ ["fetch", "MovementData"],
611
+ ["set", "@entity.x", 0],
612
+ ["set", "@entity.y", 0],
613
+ ["set", "@entity.direction", 0],
614
+ ["set", "@entity.facingRight", true],
615
+ ["set", "@entity.canJump", true],
616
+ movementCanvasView,
617
+ movementOverlayView
618
+ ]
619
+ },
620
+ {
621
+ from: "Idle",
622
+ to: "Moving",
623
+ event: "MOVE_RIGHT",
624
+ effects: [
625
+ ["fetch", "MovementData"],
626
+ ["set", "@entity.direction", 1],
627
+ ["set", "@entity.facingRight", true],
628
+ movementCanvasView,
629
+ movementOverlayView
630
+ ]
631
+ },
632
+ {
633
+ from: "Idle",
634
+ to: "Moving",
635
+ event: "MOVE_LEFT",
636
+ effects: [
637
+ ["fetch", "MovementData"],
638
+ ["set", "@entity.direction", -1],
639
+ ["set", "@entity.facingRight", false],
640
+ movementCanvasView,
641
+ movementOverlayView
642
+ ]
643
+ },
644
+ {
645
+ from: "Moving",
306
646
  to: "Moving",
307
- event: "MOVE",
647
+ event: "MOVE_RIGHT",
308
648
  effects: [
309
- ["set", "@entity.direction", "@payload.direction"],
310
- ["if", [">", "@payload.direction", 0], ["set", "@entity.facingRight", true]],
311
- ["if", ["<", "@payload.direction", 0], ["set", "@entity.facingRight", false]]
649
+ ["set", "@entity.direction", 1],
650
+ ["set", "@entity.facingRight", true]
312
651
  ]
313
652
  },
314
653
  {
315
654
  from: "Moving",
316
655
  to: "Moving",
317
- event: "MOVE",
656
+ event: "MOVE_LEFT",
318
657
  effects: [
319
- ["set", "@entity.direction", "@payload.direction"],
320
- ["if", [">", "@payload.direction", 0], ["set", "@entity.facingRight", true]],
321
- ["if", ["<", "@payload.direction", 0], ["set", "@entity.facingRight", false]]
658
+ ["set", "@entity.direction", -1],
659
+ ["set", "@entity.facingRight", false]
322
660
  ]
323
661
  },
324
662
  {
325
663
  from: "Moving",
326
664
  to: "Idle",
327
665
  event: "STOP",
328
- effects: [["set", "@entity.direction", 0]]
666
+ effects: [
667
+ ["fetch", "MovementData"],
668
+ ["set", "@entity.direction", 0],
669
+ movementCanvasView,
670
+ movementOverlayView
671
+ ]
329
672
  },
330
673
  {
331
674
  from: "Idle",
@@ -333,8 +676,11 @@ var MOVEMENT_BEHAVIOR = {
333
676
  event: "JUMP",
334
677
  guard: "@entity.canJump",
335
678
  effects: [
679
+ ["fetch", "MovementData"],
336
680
  ["set", "@entity.canJump", false],
337
- ["emit", "APPLY_FORCE", { fx: 0, fy: "@entity.jumpForce" }]
681
+ ["set", "@entity.y", ["-", "@entity.y", "@entity.jumpForce"]],
682
+ movementCanvasView,
683
+ movementOverlayView
338
684
  ]
339
685
  },
340
686
  {
@@ -344,16 +690,25 @@ var MOVEMENT_BEHAVIOR = {
344
690
  guard: "@entity.canJump",
345
691
  effects: [
346
692
  ["set", "@entity.canJump", false],
347
- ["emit", "APPLY_FORCE", { fx: 0, fy: "@entity.jumpForce" }]
693
+ ["set", "@entity.y", ["-", "@entity.y", "@entity.jumpForce"]]
348
694
  ]
349
695
  },
696
+ {
697
+ from: "Jumping",
698
+ to: "Falling",
699
+ event: "FALL",
700
+ effects: []
701
+ },
350
702
  {
351
703
  from: "Jumping",
352
704
  to: "Idle",
353
705
  event: "LAND",
354
706
  effects: [
707
+ ["fetch", "MovementData"],
355
708
  ["set", "@entity.canJump", true],
356
- ["if", ["!=", "@entity.direction", 0], ["emit", "MOVE", { direction: "@entity.direction" }]]
709
+ ["set", "@entity.direction", 0],
710
+ movementCanvasView,
711
+ movementOverlayView
357
712
  ]
358
713
  },
359
714
  {
@@ -361,8 +716,11 @@ var MOVEMENT_BEHAVIOR = {
361
716
  to: "Idle",
362
717
  event: "LAND",
363
718
  effects: [
719
+ ["fetch", "MovementData"],
364
720
  ["set", "@entity.canJump", true],
365
- ["if", ["!=", "@entity.direction", 0], ["emit", "MOVE", { direction: "@entity.direction" }]]
721
+ ["set", "@entity.direction", 0],
722
+ movementCanvasView,
723
+ movementOverlayView
366
724
  ]
367
725
  }
368
726
  ]
@@ -379,7 +737,14 @@ var MOVEMENT_BEHAVIOR = {
379
737
  ]
380
738
  }
381
739
  ],
382
- pages: []
740
+ pages: [
741
+ {
742
+ name: "MovementPage",
743
+ path: "/movement",
744
+ isInitial: true,
745
+ traits: [{ ref: "Movement" }]
746
+ }
747
+ ]
383
748
  }
384
749
  ]
385
750
  };
@@ -390,25 +755,24 @@ var COMBAT_BEHAVIOR = {
390
755
  orbitals: [
391
756
  {
392
757
  name: "CombatOrbital",
758
+ theme: GAME_ENTITY_THEME,
393
759
  entity: {
394
- name: "CombatState",
760
+ name: "CombatData",
395
761
  persistence: "runtime",
396
762
  fields: [
397
763
  { name: "id", type: "string", required: true },
398
764
  { name: "isAttacking", type: "boolean", default: false },
399
765
  { name: "attackStartTime", type: "number", default: 0 },
400
- { name: "hitEntities", type: "array", default: [] },
401
766
  { name: "attackDamage", type: "number", default: 10 },
402
767
  { name: "attackDuration", type: "number", default: 300 },
403
768
  { name: "cooldownDuration", type: "number", default: 500 },
404
- { name: "hitboxOffset", type: "object", default: { x: 20, y: 0 } },
405
- { name: "hitboxSize", type: "object", default: { width: 30, height: 30 } }
769
+ { name: "hitCount", type: "number", default: 0 }
406
770
  ]
407
771
  },
408
772
  traits: [
409
773
  {
410
774
  name: "Combat",
411
- linkedEntity: "CombatState",
775
+ linkedEntity: "CombatData",
412
776
  category: "interaction",
413
777
  stateMachine: {
414
778
  states: [
@@ -417,43 +781,63 @@ var COMBAT_BEHAVIOR = {
417
781
  { name: "Cooldown" }
418
782
  ],
419
783
  events: [
784
+ { key: "INIT", name: "Initialize" },
420
785
  { key: "ATTACK", name: "Attack" },
421
786
  { key: "ATTACK_END", name: "Attack End" },
422
- { key: "HIT_CONNECT", name: "Hit Connect" },
423
787
  { key: "COOLDOWN_END", name: "Cooldown End" }
424
788
  ],
425
789
  transitions: [
426
790
  {
427
791
  from: "Ready",
428
- to: "Attacking",
429
- event: "ATTACK",
792
+ to: "Ready",
793
+ event: "INIT",
430
794
  effects: [
431
- ["set", "@entity.isAttacking", true],
432
- ["set", "@entity.attackStartTime", "@now"],
433
- ["set", "@entity.hitEntities", []]
795
+ ["fetch", "CombatData"],
796
+ ["set", "@entity.isAttacking", false],
797
+ ["set", "@entity.hitCount", 0],
798
+ ["set", "@entity.attackStartTime", 0],
799
+ combatCanvasView,
800
+ combatLogOverlay,
801
+ combatHudOverlay
434
802
  ]
435
803
  },
436
804
  {
437
- from: "Attacking",
805
+ from: "Ready",
438
806
  to: "Attacking",
439
- event: "HIT_CONNECT",
440
- guard: ["not", ["array/includes", "@entity.hitEntities", "@payload.entityId"]],
807
+ event: "ATTACK",
441
808
  effects: [
442
- ["set", "@entity.hitEntities", ["array/append", "@entity.hitEntities", "@payload.entityId"]],
443
- ["emit", "DAMAGE", { target: "@payload.entityId", amount: "@entity.attackDamage" }]
809
+ ["fetch", "CombatData"],
810
+ ["set", "@entity.isAttacking", true],
811
+ ["set", "@entity.attackStartTime", "@now"],
812
+ combatCanvasView,
813
+ combatLogOverlay,
814
+ combatHudOverlay,
815
+ combatAttackEffect
444
816
  ]
445
817
  },
446
818
  {
447
819
  from: "Attacking",
448
820
  to: "Cooldown",
449
821
  event: "ATTACK_END",
450
- effects: [["set", "@entity.isAttacking", false]]
822
+ effects: [
823
+ ["fetch", "CombatData"],
824
+ ["set", "@entity.isAttacking", false],
825
+ ["set", "@entity.hitCount", ["+", "@entity.hitCount", 1]],
826
+ combatCanvasView,
827
+ combatLogOverlay,
828
+ combatHudOverlay
829
+ ]
451
830
  },
452
831
  {
453
832
  from: "Cooldown",
454
833
  to: "Ready",
455
834
  event: "COOLDOWN_END",
456
- effects: []
835
+ effects: [
836
+ ["fetch", "CombatData"],
837
+ combatCanvasView,
838
+ combatLogOverlay,
839
+ combatHudOverlay
840
+ ]
457
841
  }
458
842
  ]
459
843
  },
@@ -462,18 +846,21 @@ var COMBAT_BEHAVIOR = {
462
846
  name: "AttackDuration",
463
847
  interval: "frame",
464
848
  guard: ["and", "@entity.isAttacking", [">", ["-", "@now", "@entity.attackStartTime"], "@entity.attackDuration"]],
465
- effects: [["emit", "ATTACK_END"]]
466
- },
467
- {
468
- name: "CooldownTimer",
469
- interval: "frame",
470
- guard: ["and", ["=", "@state", "Cooldown"], [">", ["-", "@now", "@entity.attackStartTime"], ["+", "@entity.attackDuration", "@entity.cooldownDuration"]]],
471
- effects: [["emit", "COOLDOWN_END"]]
849
+ effects: [
850
+ ["set", "@entity.isAttacking", false]
851
+ ]
472
852
  }
473
853
  ]
474
854
  }
475
855
  ],
476
- pages: []
856
+ pages: [
857
+ {
858
+ name: "CombatPage",
859
+ path: "/combat",
860
+ isInitial: true,
861
+ traits: [{ ref: "Combat" }]
862
+ }
863
+ ]
477
864
  }
478
865
  ]
479
866
  };
@@ -484,179 +871,99 @@ var INVENTORY_BEHAVIOR = {
484
871
  orbitals: [
485
872
  {
486
873
  name: "InventoryOrbital",
874
+ theme: GAME_ENTITY_THEME,
487
875
  entity: {
488
- name: "InventoryState",
876
+ name: "InventoryItem",
489
877
  persistence: "runtime",
490
878
  fields: [
491
879
  { name: "id", type: "string", required: true },
492
- { name: "x", type: "number", default: 0 },
493
- { name: "y", type: "number", default: 0 },
494
- { name: "items", type: "array", default: [] },
495
- { name: "selectedSlot", type: "number", default: 0 },
496
- { name: "isOpen", type: "boolean", default: false },
497
- { name: "equipped", type: "object", default: {} },
498
- { name: "maxSlots", type: "number", default: 20 }
880
+ { name: "name", type: "string", default: "" },
881
+ { name: "quantity", type: "number", default: 1 },
882
+ { name: "slot", type: "number", default: 0 },
883
+ { name: "isEquipped", type: "boolean", default: false }
499
884
  ]
500
885
  },
501
886
  traits: [
502
887
  {
503
- name: "Inventory",
504
- linkedEntity: "InventoryState",
888
+ name: "InventoryManagement",
889
+ linkedEntity: "InventoryItem",
505
890
  category: "interaction",
506
891
  stateMachine: {
507
892
  states: [
508
- { name: "Empty", isInitial: true },
509
- { name: "HasItems" },
510
- { name: "Full" }
893
+ { name: "browsing", isInitial: true },
894
+ { name: "viewing" }
511
895
  ],
512
896
  events: [
513
- { key: "COLLECT", name: "Collect" },
514
- { key: "USE", name: "Use" },
515
- { key: "DROP", name: "Drop" },
516
- { key: "EQUIP", name: "Equip" },
517
- { key: "UNEQUIP", name: "Unequip" },
518
- { key: "OPEN", name: "Open" },
519
- { key: "CLOSE", name: "Close" },
520
- { key: "INVENTORY_EMPTY", name: "Inventory Empty" }
521
- ],
522
- transitions: [
897
+ { key: "INIT", name: "Initialize" },
523
898
  {
524
- from: "Empty",
525
- to: "HasItems",
526
- event: "COLLECT",
527
- guard: ["<", ["array/len", "@entity.items"], "@entity.maxSlots"],
528
- effects: [
529
- ["set", "@entity.items", ["array/append", "@entity.items", "@payload.item"]],
530
- ["notify", "in_app", ["str/concat", "Collected ", "@payload.item.name"]]
531
- ]
532
- },
533
- {
534
- from: "HasItems",
535
- to: "HasItems",
536
- event: "COLLECT",
537
- guard: ["<", ["array/len", "@entity.items"], "@entity.maxSlots"],
538
- effects: [
539
- ["set", "@entity.items", ["array/append", "@entity.items", "@payload.item"]],
540
- ["notify", "in_app", ["str/concat", "Collected ", "@payload.item.name"]]
541
- ]
899
+ key: "SELECT",
900
+ name: "Select Item",
901
+ payloadSchema: [{ name: "itemId", type: "string", required: true }]
542
902
  },
903
+ { key: "BACK", name: "Back to List" },
904
+ { key: "EQUIP", name: "Equip Item" },
905
+ { key: "UNEQUIP", name: "Unequip Item" }
906
+ ],
907
+ transitions: [
543
908
  {
544
- from: "HasItems",
545
- to: "HasItems",
546
- event: "USE",
909
+ from: "browsing",
910
+ to: "browsing",
911
+ event: "INIT",
547
912
  effects: [
548
- [
549
- "let",
550
- [["item", ["array/nth", "@entity.items", "@payload.slot"]]],
551
- ["if", "@item.onUse", ["emit", "@item.onUse", { item: "@item" }]],
552
- [
553
- "if",
554
- "@item.consumable",
555
- ["set", "@entity.items", ["array/filter", "@entity.items", ["fn", "i", "idx", ["!=", "@idx", "@payload.slot"]]]]
556
- ]
557
- ],
558
- ["if", ["=", ["array/len", "@entity.items"], 0], ["emit", "INVENTORY_EMPTY"]]
913
+ ["fetch", "InventoryItem"],
914
+ inventoryBrowseView
559
915
  ]
560
916
  },
561
917
  {
562
- from: "HasItems",
563
- to: "HasItems",
564
- event: "DROP",
918
+ from: "browsing",
919
+ to: "viewing",
920
+ event: "SELECT",
565
921
  effects: [
566
- [
567
- "let",
568
- [["item", ["array/nth", "@entity.items", "@payload.slot"]]],
569
- ["set", "@entity.items", ["array/filter", "@entity.items", ["fn", "i", "idx", ["!=", "@idx", "@payload.slot"]]]],
570
- ["emit", "ITEM_DROPPED", { item: "@item", position: { x: "@entity.x", y: "@entity.y" } }]
571
- ],
572
- ["if", ["=", ["array/len", "@entity.items"], 0], ["emit", "INVENTORY_EMPTY"]]
922
+ ["fetch", "InventoryItem"],
923
+ inventoryDetailView
573
924
  ]
574
925
  },
575
926
  {
576
- from: "HasItems",
577
- to: "Empty",
578
- event: "INVENTORY_EMPTY",
579
- effects: []
580
- },
581
- {
582
- from: "Empty",
583
- to: "Empty",
584
- event: "EQUIP",
927
+ from: "viewing",
928
+ to: "browsing",
929
+ event: "BACK",
585
930
  effects: [
586
- ["set", "@entity.equipped", ["object/set", "@entity.equipped", "@payload.slot", "@payload.item"]],
587
- ["emit", "STATS_UPDATED", { equipped: "@entity.equipped" }]
931
+ ["fetch", "InventoryItem"],
932
+ inventoryBrowseView
588
933
  ]
589
934
  },
590
935
  {
591
- from: "HasItems",
592
- to: "HasItems",
936
+ from: "viewing",
937
+ to: "viewing",
593
938
  event: "EQUIP",
594
939
  effects: [
595
- ["set", "@entity.equipped", ["object/set", "@entity.equipped", "@payload.slot", "@payload.item"]],
596
- ["emit", "STATS_UPDATED", { equipped: "@entity.equipped" }]
940
+ ["fetch", "InventoryItem"],
941
+ ["set", "@entity.isEquipped", true],
942
+ inventoryDetailView
597
943
  ]
598
944
  },
599
945
  {
600
- from: "Empty",
601
- to: "Empty",
946
+ from: "viewing",
947
+ to: "viewing",
602
948
  event: "UNEQUIP",
603
949
  effects: [
604
- ["set", "@entity.equipped", ["object/remove", "@entity.equipped", "@payload.slot"]],
605
- ["emit", "STATS_UPDATED", { equipped: "@entity.equipped" }]
950
+ ["fetch", "InventoryItem"],
951
+ ["set", "@entity.isEquipped", false],
952
+ inventoryDetailView
606
953
  ]
607
- },
608
- {
609
- from: "HasItems",
610
- to: "HasItems",
611
- event: "UNEQUIP",
612
- effects: [
613
- ["set", "@entity.equipped", ["object/remove", "@entity.equipped", "@payload.slot"]],
614
- ["emit", "STATS_UPDATED", { equipped: "@entity.equipped" }]
615
- ]
616
- },
617
- {
618
- from: "Empty",
619
- to: "Empty",
620
- event: "OPEN",
621
- effects: [
622
- ["render-ui", "modal", {
623
- type: "modal",
624
- title: "Inventory",
625
- isOpen: "@entity.isOpen",
626
- onClose: "CLOSE"
627
- }]
628
- ]
629
- },
630
- {
631
- from: "HasItems",
632
- to: "HasItems",
633
- event: "OPEN",
634
- effects: [
635
- ["render-ui", "modal", {
636
- type: "modal",
637
- title: "Inventory",
638
- isOpen: "@entity.isOpen",
639
- onClose: "CLOSE"
640
- }]
641
- ]
642
- },
643
- {
644
- from: "Empty",
645
- to: "Empty",
646
- event: "CLOSE",
647
- effects: [["set", "@entity.isOpen", false]]
648
- },
649
- {
650
- from: "HasItems",
651
- to: "HasItems",
652
- event: "CLOSE",
653
- effects: [["set", "@entity.isOpen", false]]
654
954
  }
655
955
  ]
656
956
  }
657
957
  }
658
958
  ],
659
- pages: []
959
+ pages: [
960
+ {
961
+ name: "InventoryPage",
962
+ path: "/inventory",
963
+ isInitial: true,
964
+ traits: [{ ref: "InventoryManagement" }]
965
+ }
966
+ ]
660
967
  }
661
968
  ]
662
969
  };