@almadar/std 16.178.0 → 16.180.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 (80) hide show
  1. package/behaviors/lolo/ui/core/atoms/std-detail-layout.lolo +82 -0
  2. package/behaviors/lolo/ui/core/molecules/ui-breadcrumb.lolo +20 -2
  3. package/behaviors/lolo/ui/core/molecules/ui-fx-overlay.lolo +63 -0
  4. package/behaviors/lolo/ui/core/molecules/ui-page-header.lolo +1 -1
  5. package/behaviors/lolo/ui/core/organisms/ui-detail-panel.lolo +6 -0
  6. package/behaviors/lolo/ui/core/organisms/ui-form-section.lolo +2 -2
  7. package/behaviors/lolo/ui/core/organisms/ui-form.lolo +2 -2
  8. package/behaviors/lolo/ui/core/templates/ui-dashboard-layout.lolo +2 -2
  9. package/behaviors/lolo/ui/game/atoms/std-fx-particles.lolo +23 -4
  10. package/behaviors/lolo/ui/game/atoms/std-platformer-body.lolo +251 -0
  11. package/behaviors/lolo/ui/game/atoms/ui-draw-fx-layer.lolo +109 -0
  12. package/behaviors/lolo/ui/game/organisms/std-arcade-board-3d.lolo +32 -2
  13. package/behaviors/lolo/ui/game/organisms/std-crew-board-2d.lolo +32 -2
  14. package/behaviors/lolo/ui/game/organisms/std-dungeon-board-2d.lolo +32 -2
  15. package/behaviors/lolo/ui/game/organisms/std-market-board-3d.lolo +32 -2
  16. package/behaviors/lolo/ui/game/organisms/std-objective-board-3d.lolo +32 -2
  17. package/behaviors/lolo/ui/game/organisms/std-platformer-board-2d.lolo +391 -0
  18. package/behaviors/lolo/ui/game/organisms/std-survival-board-3d.lolo +32 -2
  19. package/behaviors/lolo/ui/game/organisms/std-tactics-board-2d.lolo +34 -6
  20. package/behaviors/lolo/ui/game/organisms/std-tactics-board-3d.lolo +34 -4
  21. package/behaviors/lolo/ui/learning/atoms/std-learn-arrangement.lolo +8 -0
  22. package/behaviors/lolo/ui/learning/atoms/std-learn-classify.lolo +8 -0
  23. package/behaviors/lolo/ui/learning/atoms/std-learn-derivation.lolo +8 -0
  24. package/behaviors/lolo/ui/learning/atoms/std-learn-doser.lolo +9 -0
  25. package/behaviors/lolo/ui/learning/atoms/std-learn-estimate.lolo +8 -0
  26. package/behaviors/lolo/ui/learning/atoms/std-learn-fx-cues.lolo +147 -0
  27. package/behaviors/lolo/ui/learning/atoms/std-learn-goal-seek.lolo +8 -0
  28. package/behaviors/lolo/ui/learning/atoms/std-learn-hotspot.lolo +8 -0
  29. package/behaviors/lolo/ui/learning/atoms/std-learn-predict.lolo +8 -0
  30. package/behaviors/lolo/ui/learning/atoms/std-learn-scatter-fit.lolo +9 -0
  31. package/behaviors/lolo/ui/learning/atoms/std-learn-speed-drill.lolo +8 -0
  32. package/behaviors/lolo/ui/learning/atoms/std-learn-tour-3d.lolo +9 -0
  33. package/behaviors/registry/ui/core/atoms/std-detail-layout.orb +265 -0
  34. package/behaviors/registry/ui/core/molecules/ui-breadcrumb.orb +55 -17
  35. package/behaviors/registry/ui/core/molecules/ui-fx-overlay.orb +281 -0
  36. package/behaviors/registry/ui/core/molecules/ui-page-header.orb +1 -1
  37. package/behaviors/registry/ui/core/organisms/ui-detail-panel.orb +8 -0
  38. package/behaviors/registry/ui/core/organisms/ui-form-section.orb +6 -0
  39. package/behaviors/registry/ui/core/organisms/ui-form.orb +6 -0
  40. package/behaviors/registry/ui/core/templates/ui-dashboard-layout.orb +2 -2
  41. package/behaviors/registry/ui/game/atoms/std-fx-particles.orb +265 -4
  42. package/behaviors/registry/ui/game/atoms/std-platformer-body.orb +2136 -0
  43. package/behaviors/registry/ui/game/atoms/ui-draw-fx-layer.orb +523 -0
  44. package/behaviors/registry/ui/game/organisms/std-arcade-board-3d.orb +159 -70
  45. package/behaviors/registry/ui/game/organisms/std-crew-board-2d.orb +148 -58
  46. package/behaviors/registry/ui/game/organisms/std-dungeon-board-2d.orb +169 -58
  47. package/behaviors/registry/ui/game/organisms/std-market-board-3d.orb +160 -70
  48. package/behaviors/registry/ui/game/organisms/std-objective-board-3d.orb +151 -60
  49. package/behaviors/registry/ui/game/organisms/std-platformer-board-2d.orb +2981 -0
  50. package/behaviors/registry/ui/game/organisms/std-survival-board-3d.orb +150 -60
  51. package/behaviors/registry/ui/game/organisms/std-tactics-board-2d.orb +163 -316
  52. package/behaviors/registry/ui/game/organisms/std-tactics-board-3d.orb +156 -184
  53. package/behaviors/registry/ui/learning/atoms/std-learn-arrangement.orb +62 -0
  54. package/behaviors/registry/ui/learning/atoms/std-learn-classify.orb +73 -0
  55. package/behaviors/registry/ui/learning/atoms/std-learn-derivation.orb +66 -0
  56. package/behaviors/registry/ui/learning/atoms/std-learn-doser.orb +71 -0
  57. package/behaviors/registry/ui/learning/atoms/std-learn-estimate.orb +72 -0
  58. package/behaviors/registry/ui/learning/atoms/std-learn-fx-cues.orb +1546 -0
  59. package/behaviors/registry/ui/learning/atoms/std-learn-goal-seek.orb +58 -0
  60. package/behaviors/registry/ui/learning/atoms/std-learn-hotspot.orb +72 -0
  61. package/behaviors/registry/ui/learning/atoms/std-learn-predict.orb +72 -0
  62. package/behaviors/registry/ui/learning/atoms/std-learn-scatter-fit.orb +71 -0
  63. package/behaviors/registry/ui/learning/atoms/std-learn-speed-drill.orb +72 -0
  64. package/behaviors/registry/ui/learning/atoms/std-learn-tour-3d.orb +176 -0
  65. package/canonical-operators.json +14 -2
  66. package/dist/behaviors/exports-reader.js +8655 -5239
  67. package/dist/behaviors/functions/index.d.ts +686 -16
  68. package/dist/behaviors/functions/index.js +8637 -5240
  69. package/dist/behaviors/index.d.ts +1 -1
  70. package/dist/behaviors/index.js +8656 -5240
  71. package/dist/behaviors/query.js +8655 -5239
  72. package/dist/behaviors-embeddings.hash.json +3 -3
  73. package/dist/behaviors-embeddings.json +381 -353
  74. package/dist/behaviors-registry.json +2415 -443
  75. package/dist/index.d.ts +1 -1
  76. package/dist/index.js +8656 -5240
  77. package/dist/knob-embeddings.hash.json +3 -3
  78. package/dist/knob-embeddings.json +1 -1
  79. package/dist/registry/factory-signatures.json +1 -1
  80. package/package.json +2 -2
@@ -0,0 +1,2136 @@
1
+ {
2
+ "description": "Headless run/jump platformer-physics authority: the SOLE writer of body + fell + hazardId + goalId on side-view boards. Where std-motion-body owns free 2D drift (no collision), this atom owns the platformer contract: every 33ms physics tick it integrates gravity into the body's vertical velocity, steps position in per-second units, and collides the body rect against the config platforms with one-way semantics — a body moving in the gravity direction that overlaps a ground/platform tile lands on its anti-gravity face (vy zeroed, grounded set), while a body moving against gravity passes through, so jumping up through a platform and walking up a staircase both just work. The sign of gravity IS the vertical convention: positive pulls toward +y (screen boards, y down — sprite canvases), negative toward −y (math canvases, y up); jumps always fire against it. Intents: STEER sets horizontal velocity (dir −1/0/1 × moveSpeed, hold-to-run: keydown steers, keyup steers 0), JUMP kicks vertical velocity when grounded, PLACE teleports (spawns, hazard respawns), RESTART reseeds. Emits BODY_MOVED every tick for the render layer (boards that don't subscribe pay nothing), plus the sparse rule signals a board needs to score: BODY_JUMPED, BODY_LANDED (with impact speed), BODY_HAZARD (once per hazard entry, re-arms on exit), BODY_GOAL (same arming), BODY_FELL (once per fall past killY, re-armed by PLACE/RESTART). Curve skating: when config.skate is on and the grounded body comes within skateSnap of the config.skateCurve surface, the body rides the curve — y snaps to the interpolated surface and tangential gravity (g·slope/(1+slope²)) accelerates vx, so the body slides downhill along the graph itself and launches ballistically off its ends; jumping kicks free. Sparse BODY_SKATE_START/BODY_SKATE_END signals fire on engage/disengage so boards can layer fx. Lives, score, and win/lose stay downstream — this atom simulates, it never judges. Renders nothing.",
3
+ "ledger": {
4
+ "entries": {
5
+ "ent_01M0H2SJBB5TG61D238AWJW3KC": {
6
+ "bakedName": "PlatformerBodyData",
7
+ "curName": "PlatformerBodyData",
8
+ "id": "ent_01M0H2SJBB5TG61D238AWJW3KC",
9
+ "kind": "entity",
10
+ "owner": "workspace",
11
+ "renames": []
12
+ },
13
+ "evt_01M0H2SJBB0ZDAJA2NJYDKJPJB": {
14
+ "bakedName": "STEER",
15
+ "curName": "STEER",
16
+ "id": "evt_01M0H2SJBB0ZDAJA2NJYDKJPJB",
17
+ "kind": "event",
18
+ "owner": "workspace",
19
+ "parent": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2",
20
+ "renames": []
21
+ },
22
+ "evt_01M0H2SJBB1WZWWVDCP2FHNFXK": {
23
+ "bakedName": "INIT",
24
+ "curName": "INIT",
25
+ "id": "evt_01M0H2SJBB1WZWWVDCP2FHNFXK",
26
+ "kind": "event",
27
+ "owner": "workspace",
28
+ "parent": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2",
29
+ "renames": []
30
+ },
31
+ "evt_01M0H2SJBB3Y7Z6D7EX8VQ750V": {
32
+ "bakedName": "BODY_SKATE_START",
33
+ "curName": "BODY_SKATE_START",
34
+ "id": "evt_01M0H2SJBB3Y7Z6D7EX8VQ750V",
35
+ "kind": "event",
36
+ "owner": "workspace",
37
+ "parent": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2",
38
+ "renames": []
39
+ },
40
+ "evt_01M0H2SJBB642M21GBGMF4GVN3": {
41
+ "bakedName": "BODY_SKATE_END",
42
+ "curName": "BODY_SKATE_END",
43
+ "id": "evt_01M0H2SJBB642M21GBGMF4GVN3",
44
+ "kind": "event",
45
+ "owner": "workspace",
46
+ "parent": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2",
47
+ "renames": []
48
+ },
49
+ "evt_01M0H2SJBBANN279Z3VG3DKD9E": {
50
+ "bakedName": "BODY_HAZARD",
51
+ "curName": "BODY_HAZARD",
52
+ "id": "evt_01M0H2SJBBANN279Z3VG3DKD9E",
53
+ "kind": "event",
54
+ "owner": "workspace",
55
+ "parent": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2",
56
+ "renames": []
57
+ },
58
+ "evt_01M0H2SJBBBE4DVTXJ13J4TKN4": {
59
+ "bakedName": "BODY_FELL",
60
+ "curName": "BODY_FELL",
61
+ "id": "evt_01M0H2SJBBBE4DVTXJ13J4TKN4",
62
+ "kind": "event",
63
+ "owner": "workspace",
64
+ "parent": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2",
65
+ "renames": []
66
+ },
67
+ "evt_01M0H2SJBBDPMZN6QSYNP2C76E": {
68
+ "bakedName": "PLACE",
69
+ "curName": "PLACE",
70
+ "id": "evt_01M0H2SJBBDPMZN6QSYNP2C76E",
71
+ "kind": "event",
72
+ "owner": "workspace",
73
+ "parent": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2",
74
+ "renames": []
75
+ },
76
+ "evt_01M0H2SJBBFC49QWKCF4NSV7CS": {
77
+ "bakedName": "BODY_LANDED",
78
+ "curName": "BODY_LANDED",
79
+ "id": "evt_01M0H2SJBBFC49QWKCF4NSV7CS",
80
+ "kind": "event",
81
+ "owner": "workspace",
82
+ "parent": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2",
83
+ "renames": []
84
+ },
85
+ "evt_01M0H2SJBBJDVE4W1X027A4S5A": {
86
+ "bakedName": "BODY_MOVED",
87
+ "curName": "BODY_MOVED",
88
+ "id": "evt_01M0H2SJBBJDVE4W1X027A4S5A",
89
+ "kind": "event",
90
+ "owner": "workspace",
91
+ "parent": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2",
92
+ "renames": []
93
+ },
94
+ "evt_01M0H2SJBBNFYE3SP6AK8T0MCX": {
95
+ "bakedName": "BODY_GOAL",
96
+ "curName": "BODY_GOAL",
97
+ "id": "evt_01M0H2SJBBNFYE3SP6AK8T0MCX",
98
+ "kind": "event",
99
+ "owner": "workspace",
100
+ "parent": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2",
101
+ "renames": []
102
+ },
103
+ "evt_01M0H2SJBBSCEAJH5FZN8AAX45": {
104
+ "bakedName": "RESTART",
105
+ "curName": "RESTART",
106
+ "id": "evt_01M0H2SJBBSCEAJH5FZN8AAX45",
107
+ "kind": "event",
108
+ "owner": "workspace",
109
+ "parent": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2",
110
+ "renames": []
111
+ },
112
+ "evt_01M0H2SJBBSRSS0T8AN9VZM3R1": {
113
+ "bakedName": "JUMP",
114
+ "curName": "JUMP",
115
+ "id": "evt_01M0H2SJBBSRSS0T8AN9VZM3R1",
116
+ "kind": "event",
117
+ "owner": "workspace",
118
+ "parent": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2",
119
+ "renames": []
120
+ },
121
+ "evt_01M0H2SJBBW0HRTFT8DPEEPFH5": {
122
+ "bakedName": "BODY_JUMPED",
123
+ "curName": "BODY_JUMPED",
124
+ "id": "evt_01M0H2SJBBW0HRTFT8DPEEPFH5",
125
+ "kind": "event",
126
+ "owner": "workspace",
127
+ "parent": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2",
128
+ "renames": []
129
+ },
130
+ "orb_01M0H2SJBB6B28C7NXBC5BWW23": {
131
+ "bakedName": "PlatformerBodyOrbital",
132
+ "curName": "PlatformerBodyOrbital",
133
+ "id": "orb_01M0H2SJBB6B28C7NXBC5BWW23",
134
+ "kind": "orbital",
135
+ "owner": "workspace",
136
+ "renames": []
137
+ },
138
+ "pag_01M0H2SJBBMRH9A3PNVT1TPGQ9": {
139
+ "bakedName": "PlatformerBodyPage",
140
+ "curName": "PlatformerBodyPage",
141
+ "id": "pag_01M0H2SJBBMRH9A3PNVT1TPGQ9",
142
+ "kind": "page",
143
+ "owner": "workspace",
144
+ "renames": []
145
+ },
146
+ "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2": {
147
+ "bakedName": "PlatformerBody",
148
+ "curName": "PlatformerBody",
149
+ "id": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2",
150
+ "kind": "trait",
151
+ "owner": "workspace",
152
+ "renames": []
153
+ }
154
+ },
155
+ "schemaVersion": 1
156
+ },
157
+ "name": "std-platformer-body",
158
+ "orbitals": [
159
+ {
160
+ "entity": {
161
+ "fields": [
162
+ {
163
+ "name": "id",
164
+ "required": true,
165
+ "type": "string"
166
+ },
167
+ {
168
+ "default": {
169
+ "facingRight": true,
170
+ "grounded": false,
171
+ "height": 1.0,
172
+ "vx": 0.0,
173
+ "vy": 0.0,
174
+ "width": 1.0,
175
+ "x": 0.0,
176
+ "y": 0.0
177
+ },
178
+ "name": "body",
179
+ "properties": {
180
+ "facingRight": {
181
+ "name": "facingRight",
182
+ "required": false,
183
+ "type": "boolean"
184
+ },
185
+ "grounded": {
186
+ "name": "grounded",
187
+ "required": false,
188
+ "type": "boolean"
189
+ },
190
+ "height": {
191
+ "name": "height",
192
+ "required": true,
193
+ "type": "number"
194
+ },
195
+ "vx": {
196
+ "name": "vx",
197
+ "required": false,
198
+ "type": "number"
199
+ },
200
+ "vy": {
201
+ "name": "vy",
202
+ "required": false,
203
+ "type": "number"
204
+ },
205
+ "width": {
206
+ "name": "width",
207
+ "required": true,
208
+ "type": "number"
209
+ },
210
+ "x": {
211
+ "name": "x",
212
+ "required": true,
213
+ "type": "number"
214
+ },
215
+ "y": {
216
+ "name": "y",
217
+ "required": true,
218
+ "type": "number"
219
+ }
220
+ },
221
+ "type": "object"
222
+ },
223
+ {
224
+ "default": false,
225
+ "name": "fell",
226
+ "type": "boolean"
227
+ },
228
+ {
229
+ "default": "",
230
+ "name": "hazardId",
231
+ "type": "string"
232
+ },
233
+ {
234
+ "default": "",
235
+ "name": "goalId",
236
+ "type": "string"
237
+ },
238
+ {
239
+ "default": false,
240
+ "name": "skating",
241
+ "type": "boolean"
242
+ }
243
+ ],
244
+ "id": "ent_01M0H2SJBB5TG61D238AWJW3KC",
245
+ "name": "PlatformerBodyData",
246
+ "persistence": "runtime",
247
+ "shared": true
248
+ },
249
+ "id": "orb_01M0H2SJBB6B28C7NXBC5BWW23",
250
+ "name": "PlatformerBodyOrbital",
251
+ "pages": [
252
+ {
253
+ "id": "pag_01M0H2SJBBMRH9A3PNVT1TPGQ9",
254
+ "name": "PlatformerBodyPage",
255
+ "path": "/platformer-body",
256
+ "traits": [
257
+ {
258
+ "ref": "PlatformerBody",
259
+ "refId": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2"
260
+ }
261
+ ]
262
+ }
263
+ ],
264
+ "traits": [
265
+ {
266
+ "category": "lifecycle",
267
+ "config": {
268
+ "gravity": {
269
+ "default": 24.0,
270
+ "description": "Units/s² added to vertical velocity; the SIGN is the vertical convention — positive pulls toward +y (screen boards, y down), negative toward −y (math canvases, y up) — and jumps always fire against it",
271
+ "label": "Gravity",
272
+ "tier": "domain",
273
+ "type": "number"
274
+ },
275
+ "jumpStrength": {
276
+ "default": 11.0,
277
+ "description": "Vertical speed in units/s imparted by JUMP, directed against gravity; apex height ≈ jumpStrength² / (2·|gravity|)",
278
+ "label": "Jump Strength",
279
+ "tier": "domain",
280
+ "type": "number"
281
+ },
282
+ "killY": {
283
+ "default": 1000000.0,
284
+ "description": "Fall line: crossing it in the gravity direction fires BODY_FELL once (past it downward on y-down boards, below it on y-up canvases); y-up consumers must set a value below their world floor",
285
+ "label": "Kill Y",
286
+ "tier": "domain",
287
+ "type": "number"
288
+ },
289
+ "maxFallSpeed": {
290
+ "default": 14.0,
291
+ "description": "Terminal velocity cap in units/s applied to vertical speed each tick",
292
+ "label": "Max Fall Speed",
293
+ "tier": "presentation",
294
+ "type": "number"
295
+ },
296
+ "moveSpeed": {
297
+ "default": 5.0,
298
+ "description": "Horizontal run speed in units/s applied by STEER dir ±1",
299
+ "label": "Move Speed",
300
+ "tier": "domain",
301
+ "type": "number"
302
+ },
303
+ "platforms": {
304
+ "default": [],
305
+ "description": "Level geometry as min-corner rects: ground/platform tiles are solid one-way landing surfaces, hazard tiles emit BODY_HAZARD on touch, goal tiles emit BODY_GOAL",
306
+ "items": {
307
+ "properties": {
308
+ "height": {
309
+ "name": "height",
310
+ "required": true,
311
+ "type": "number"
312
+ },
313
+ "id": {
314
+ "name": "id",
315
+ "required": false,
316
+ "type": "string"
317
+ },
318
+ "type": {
319
+ "name": "type",
320
+ "required": false,
321
+ "type": "string",
322
+ "values": [
323
+ "ground",
324
+ "platform",
325
+ "hazard",
326
+ "goal"
327
+ ]
328
+ },
329
+ "width": {
330
+ "name": "width",
331
+ "required": true,
332
+ "type": "number"
333
+ },
334
+ "x": {
335
+ "name": "x",
336
+ "required": true,
337
+ "type": "number"
338
+ },
339
+ "y": {
340
+ "name": "y",
341
+ "required": true,
342
+ "type": "number"
343
+ }
344
+ },
345
+ "type": "object"
346
+ },
347
+ "label": "Platforms",
348
+ "tier": "domain",
349
+ "type": "[PlatformerPlatform]"
350
+ },
351
+ "running": {
352
+ "default": true,
353
+ "description": "When true the 33ms physics tick integrates and collides; toggle to freeze the body",
354
+ "label": "Running",
355
+ "tier": "domain",
356
+ "type": "boolean"
357
+ },
358
+ "skate": {
359
+ "default": false,
360
+ "description": "When true, a grounded body within skateSnap of the skateCurve surface rides the curve: y snaps to the interpolated surface and tangential gravity (g·slope/(1+slope²)) accelerates vx, so the body slides downhill along the graph and launches off its ends; JUMP kicks free",
361
+ "label": "Curve Skating",
362
+ "tier": "domain",
363
+ "type": "boolean"
364
+ },
365
+ "skateCurve": {
366
+ "default": [],
367
+ "description": "Surface samples (x strictly increasing) the body skates when skate is on; y is the surface height for the body's MIN corner, linearly interpolated between bracketing samples — mirror the render-side curve so what you see is what you ride",
368
+ "items": {
369
+ "properties": {
370
+ "x": {
371
+ "name": "x",
372
+ "required": true,
373
+ "type": "number"
374
+ },
375
+ "y": {
376
+ "name": "y",
377
+ "required": true,
378
+ "type": "number"
379
+ }
380
+ },
381
+ "type": "object"
382
+ },
383
+ "label": "Skate Curve",
384
+ "tier": "domain",
385
+ "type": "[PlatformerCurveSample]"
386
+ },
387
+ "skateSnap": {
388
+ "default": 0.75,
389
+ "description": "Max vertical gap (world units) between the body's min corner and the curve surface for skating to engage or stay engaged; larger values grab earlier on landing, smaller values release sooner on bumps",
390
+ "label": "Skate Snap",
391
+ "tier": "domain",
392
+ "type": "number"
393
+ },
394
+ "spawn": {
395
+ "default": {
396
+ "facingRight": true,
397
+ "grounded": false,
398
+ "height": 0.6,
399
+ "vx": 0.0,
400
+ "vy": 0.0,
401
+ "width": 0.6,
402
+ "x": 2.0,
403
+ "y": 8.0
404
+ },
405
+ "description": "Initial body rect (min-corner x/y plus width/height) seeded on INIT/RESTART; width/height also define the collision box",
406
+ "label": "Spawn Body",
407
+ "properties": {
408
+ "facingRight": {
409
+ "name": "facingRight",
410
+ "required": false,
411
+ "type": "boolean"
412
+ },
413
+ "grounded": {
414
+ "name": "grounded",
415
+ "required": false,
416
+ "type": "boolean"
417
+ },
418
+ "height": {
419
+ "name": "height",
420
+ "required": true,
421
+ "type": "number"
422
+ },
423
+ "vx": {
424
+ "name": "vx",
425
+ "required": false,
426
+ "type": "number"
427
+ },
428
+ "vy": {
429
+ "name": "vy",
430
+ "required": false,
431
+ "type": "number"
432
+ },
433
+ "width": {
434
+ "name": "width",
435
+ "required": true,
436
+ "type": "number"
437
+ },
438
+ "x": {
439
+ "name": "x",
440
+ "required": true,
441
+ "type": "number"
442
+ },
443
+ "y": {
444
+ "name": "y",
445
+ "required": true,
446
+ "type": "number"
447
+ }
448
+ },
449
+ "tier": "domain",
450
+ "type": "PlatformerBody"
451
+ },
452
+ "xMax": {
453
+ "default": 1000000.0,
454
+ "description": "Largest x the body's min corner may hold (world bounds, not level geometry)",
455
+ "label": "Right Wall",
456
+ "tier": "presentation",
457
+ "type": "number"
458
+ },
459
+ "xMin": {
460
+ "default": -1000000.0,
461
+ "description": "Smallest x the body's min corner may hold (world bounds, not level geometry)",
462
+ "label": "Left Wall",
463
+ "tier": "presentation",
464
+ "type": "number"
465
+ }
466
+ },
467
+ "emits": [
468
+ {
469
+ "description": "The body after this physics tick: position, velocity, grounded and skating flags, and scalar speed; render layers subscribe (or read the shared entity), rule layers stay on the sparse signals",
470
+ "event": "BODY_MOVED",
471
+ "eventId": "evt_01M0H2SJBBJDVE4W1X027A4S5A",
472
+ "payloadSchema": [
473
+ {
474
+ "name": "x",
475
+ "required": true,
476
+ "type": "number"
477
+ },
478
+ {
479
+ "name": "y",
480
+ "required": true,
481
+ "type": "number"
482
+ },
483
+ {
484
+ "name": "vx",
485
+ "required": true,
486
+ "type": "number"
487
+ },
488
+ {
489
+ "name": "vy",
490
+ "required": true,
491
+ "type": "number"
492
+ },
493
+ {
494
+ "name": "grounded",
495
+ "required": true,
496
+ "type": "boolean"
497
+ },
498
+ {
499
+ "name": "skating",
500
+ "required": true,
501
+ "type": "boolean"
502
+ },
503
+ {
504
+ "name": "speed",
505
+ "required": true,
506
+ "type": "number"
507
+ }
508
+ ],
509
+ "scope": "external",
510
+ "tier": "domain"
511
+ },
512
+ {
513
+ "description": "Body engaged curve skating this tick (grounded within skateSnap of the skateCurve surface); slope is the local dy/dx — boards layer fx and equation readouts",
514
+ "event": "BODY_SKATE_START",
515
+ "eventId": "evt_01M0H2SJBB3Y7Z6D7EX8VQ750V",
516
+ "payloadSchema": [
517
+ {
518
+ "name": "x",
519
+ "required": true,
520
+ "type": "number"
521
+ },
522
+ {
523
+ "name": "y",
524
+ "required": true,
525
+ "type": "number"
526
+ },
527
+ {
528
+ "name": "slope",
529
+ "required": true,
530
+ "type": "number"
531
+ }
532
+ ],
533
+ "scope": "external",
534
+ "tier": "domain"
535
+ },
536
+ {
537
+ "description": "Body left the curve surface (jumped, walked past an end, or drifted beyond skateSnap); boards tear down skate fx",
538
+ "event": "BODY_SKATE_END",
539
+ "eventId": "evt_01M0H2SJBB642M21GBGMF4GVN3",
540
+ "payloadSchema": [
541
+ {
542
+ "name": "x",
543
+ "required": true,
544
+ "type": "number"
545
+ },
546
+ {
547
+ "name": "y",
548
+ "required": true,
549
+ "type": "number"
550
+ }
551
+ ],
552
+ "scope": "external",
553
+ "tier": "domain"
554
+ },
555
+ {
556
+ "description": "Jump accepted (grounded at intent time) and vertical velocity kicked against gravity; boards layer squash/sound fx",
557
+ "event": "BODY_JUMPED",
558
+ "eventId": "evt_01M0H2SJBBW0HRTFT8DPEEPFH5",
559
+ "payloadSchema": [
560
+ {
561
+ "name": "x",
562
+ "required": true,
563
+ "type": "number"
564
+ },
565
+ {
566
+ "name": "y",
567
+ "required": true,
568
+ "type": "number"
569
+ }
570
+ ],
571
+ "scope": "external",
572
+ "tier": "domain"
573
+ },
574
+ {
575
+ "description": "Body transitioned airborne → standing on a ground/platform tile this tick; impact is the pre-landing fall speed in units/s so boards can scale dust or damage",
576
+ "event": "BODY_LANDED",
577
+ "eventId": "evt_01M0H2SJBBFC49QWKCF4NSV7CS",
578
+ "payloadSchema": [
579
+ {
580
+ "name": "x",
581
+ "required": true,
582
+ "type": "number"
583
+ },
584
+ {
585
+ "name": "y",
586
+ "required": true,
587
+ "type": "number"
588
+ },
589
+ {
590
+ "name": "impact",
591
+ "required": true,
592
+ "type": "number"
593
+ }
594
+ ],
595
+ "scope": "external",
596
+ "tier": "domain"
597
+ },
598
+ {
599
+ "description": "Body entered overlap with a hazard tile; fires once per entry and re-arms only after the body leaves, so damage rules stay sparse",
600
+ "event": "BODY_HAZARD",
601
+ "eventId": "evt_01M0H2SJBBANN279Z3VG3DKD9E",
602
+ "payloadSchema": [
603
+ {
604
+ "name": "id",
605
+ "required": true,
606
+ "type": "string"
607
+ },
608
+ {
609
+ "name": "x",
610
+ "required": true,
611
+ "type": "number"
612
+ },
613
+ {
614
+ "name": "y",
615
+ "required": true,
616
+ "type": "number"
617
+ }
618
+ ],
619
+ "scope": "external",
620
+ "tier": "domain"
621
+ },
622
+ {
623
+ "description": "Body entered overlap with a goal tile; fires once per entry and re-arms only after the body leaves — the board's win-rule trigger",
624
+ "event": "BODY_GOAL",
625
+ "eventId": "evt_01M0H2SJBBNFYE3SP6AK8T0MCX",
626
+ "payloadSchema": [
627
+ {
628
+ "name": "id",
629
+ "required": true,
630
+ "type": "string"
631
+ },
632
+ {
633
+ "name": "x",
634
+ "required": true,
635
+ "type": "number"
636
+ },
637
+ {
638
+ "name": "y",
639
+ "required": true,
640
+ "type": "number"
641
+ }
642
+ ],
643
+ "scope": "external",
644
+ "tier": "domain"
645
+ },
646
+ {
647
+ "description": "Body crossed killY in the gravity direction (pit fall); fires once per fall and re-arms on PLACE/RESTART, leaving the respawn rule to the board",
648
+ "event": "BODY_FELL",
649
+ "eventId": "evt_01M0H2SJBBBE4DVTXJ13J4TKN4",
650
+ "payloadSchema": [
651
+ {
652
+ "name": "x",
653
+ "required": true,
654
+ "type": "number"
655
+ },
656
+ {
657
+ "name": "y",
658
+ "required": true,
659
+ "type": "number"
660
+ }
661
+ ],
662
+ "scope": "external",
663
+ "tier": "domain"
664
+ }
665
+ ],
666
+ "entityContract": {
667
+ "provides": [
668
+ "body",
669
+ "fell",
670
+ "goalId",
671
+ "hazardId",
672
+ "skating"
673
+ ],
674
+ "requires": []
675
+ },
676
+ "entityRebindable": true,
677
+ "entityRefIds": {
678
+ "PlatformerBodyData": "ent_01M0H2SJBB5TG61D238AWJW3KC"
679
+ },
680
+ "id": "trt_01M0H2SJBBCZW9WSQ3YBCVRKM2",
681
+ "linkedEntity": "PlatformerBodyData",
682
+ "linkedEntityId": "ent_01M0H2SJBB5TG61D238AWJW3KC",
683
+ "name": "PlatformerBody",
684
+ "scope": "instance",
685
+ "stateMachine": {
686
+ "events": [
687
+ {
688
+ "id": "evt_01M0H2SJBB1WZWWVDCP2FHNFXK",
689
+ "key": "INIT",
690
+ "name": "Initialize"
691
+ },
692
+ {
693
+ "id": "evt_01M0H2SJBB0ZDAJA2NJYDKJPJB",
694
+ "key": "STEER",
695
+ "name": "Steer",
696
+ "payloadSchema": [
697
+ {
698
+ "name": "dir",
699
+ "required": true,
700
+ "type": "number"
701
+ }
702
+ ]
703
+ },
704
+ {
705
+ "id": "evt_01M0H2SJBBSRSS0T8AN9VZM3R1",
706
+ "key": "JUMP",
707
+ "name": "Jump",
708
+ "payloadSchema": [
709
+ {
710
+ "name": "id",
711
+ "type": "string"
712
+ }
713
+ ]
714
+ },
715
+ {
716
+ "id": "evt_01M0H2SJBBDPMZN6QSYNP2C76E",
717
+ "key": "PLACE",
718
+ "name": "Place",
719
+ "payloadSchema": [
720
+ {
721
+ "name": "x",
722
+ "required": true,
723
+ "type": "number"
724
+ },
725
+ {
726
+ "name": "y",
727
+ "required": true,
728
+ "type": "number"
729
+ }
730
+ ]
731
+ },
732
+ {
733
+ "id": "evt_01M0H2SJBBSCEAJH5FZN8AAX45",
734
+ "key": "RESTART",
735
+ "name": "Restart",
736
+ "payloadSchema": [
737
+ {
738
+ "name": "id",
739
+ "type": "string"
740
+ }
741
+ ]
742
+ },
743
+ {
744
+ "description": "The body after this physics tick: position, velocity, grounded and skating flags, and scalar speed; render layers subscribe (or read the shared entity), rule layers stay on the sparse signals",
745
+ "id": "evt_01M0H2SJBBJDVE4W1X027A4S5A",
746
+ "key": "BODY_MOVED",
747
+ "name": "Body Moved",
748
+ "payloadSchema": [
749
+ {
750
+ "name": "x",
751
+ "required": true,
752
+ "type": "number"
753
+ },
754
+ {
755
+ "name": "y",
756
+ "required": true,
757
+ "type": "number"
758
+ },
759
+ {
760
+ "name": "vx",
761
+ "required": true,
762
+ "type": "number"
763
+ },
764
+ {
765
+ "name": "vy",
766
+ "required": true,
767
+ "type": "number"
768
+ },
769
+ {
770
+ "name": "grounded",
771
+ "required": true,
772
+ "type": "boolean"
773
+ },
774
+ {
775
+ "name": "skating",
776
+ "required": true,
777
+ "type": "boolean"
778
+ },
779
+ {
780
+ "name": "speed",
781
+ "required": true,
782
+ "type": "number"
783
+ }
784
+ ],
785
+ "tier": "domain"
786
+ },
787
+ {
788
+ "description": "Body engaged curve skating this tick (grounded within skateSnap of the skateCurve surface); slope is the local dy/dx — boards layer fx and equation readouts",
789
+ "id": "evt_01M0H2SJBB3Y7Z6D7EX8VQ750V",
790
+ "key": "BODY_SKATE_START",
791
+ "name": "Body Skate Start",
792
+ "payloadSchema": [
793
+ {
794
+ "name": "x",
795
+ "required": true,
796
+ "type": "number"
797
+ },
798
+ {
799
+ "name": "y",
800
+ "required": true,
801
+ "type": "number"
802
+ },
803
+ {
804
+ "name": "slope",
805
+ "required": true,
806
+ "type": "number"
807
+ }
808
+ ],
809
+ "tier": "domain"
810
+ },
811
+ {
812
+ "description": "Body left the curve surface (jumped, walked past an end, or drifted beyond skateSnap); boards tear down skate fx",
813
+ "id": "evt_01M0H2SJBB642M21GBGMF4GVN3",
814
+ "key": "BODY_SKATE_END",
815
+ "name": "Body Skate End",
816
+ "payloadSchema": [
817
+ {
818
+ "name": "x",
819
+ "required": true,
820
+ "type": "number"
821
+ },
822
+ {
823
+ "name": "y",
824
+ "required": true,
825
+ "type": "number"
826
+ }
827
+ ],
828
+ "tier": "domain"
829
+ },
830
+ {
831
+ "description": "Jump accepted (grounded at intent time) and vertical velocity kicked against gravity; boards layer squash/sound fx",
832
+ "id": "evt_01M0H2SJBBW0HRTFT8DPEEPFH5",
833
+ "key": "BODY_JUMPED",
834
+ "name": "Body Jumped",
835
+ "payloadSchema": [
836
+ {
837
+ "name": "x",
838
+ "required": true,
839
+ "type": "number"
840
+ },
841
+ {
842
+ "name": "y",
843
+ "required": true,
844
+ "type": "number"
845
+ }
846
+ ],
847
+ "tier": "domain"
848
+ },
849
+ {
850
+ "description": "Body transitioned airborne → standing on a ground/platform tile this tick; impact is the pre-landing fall speed in units/s so boards can scale dust or damage",
851
+ "id": "evt_01M0H2SJBBFC49QWKCF4NSV7CS",
852
+ "key": "BODY_LANDED",
853
+ "name": "Body Landed",
854
+ "payloadSchema": [
855
+ {
856
+ "name": "x",
857
+ "required": true,
858
+ "type": "number"
859
+ },
860
+ {
861
+ "name": "y",
862
+ "required": true,
863
+ "type": "number"
864
+ },
865
+ {
866
+ "name": "impact",
867
+ "required": true,
868
+ "type": "number"
869
+ }
870
+ ],
871
+ "tier": "domain"
872
+ },
873
+ {
874
+ "description": "Body entered overlap with a hazard tile; fires once per entry and re-arms only after the body leaves, so damage rules stay sparse",
875
+ "id": "evt_01M0H2SJBBANN279Z3VG3DKD9E",
876
+ "key": "BODY_HAZARD",
877
+ "name": "Body Hazard",
878
+ "payloadSchema": [
879
+ {
880
+ "name": "id",
881
+ "required": true,
882
+ "type": "string"
883
+ },
884
+ {
885
+ "name": "x",
886
+ "required": true,
887
+ "type": "number"
888
+ },
889
+ {
890
+ "name": "y",
891
+ "required": true,
892
+ "type": "number"
893
+ }
894
+ ],
895
+ "tier": "domain"
896
+ },
897
+ {
898
+ "description": "Body entered overlap with a goal tile; fires once per entry and re-arms only after the body leaves — the board's win-rule trigger",
899
+ "id": "evt_01M0H2SJBBNFYE3SP6AK8T0MCX",
900
+ "key": "BODY_GOAL",
901
+ "name": "Body Goal",
902
+ "payloadSchema": [
903
+ {
904
+ "name": "id",
905
+ "required": true,
906
+ "type": "string"
907
+ },
908
+ {
909
+ "name": "x",
910
+ "required": true,
911
+ "type": "number"
912
+ },
913
+ {
914
+ "name": "y",
915
+ "required": true,
916
+ "type": "number"
917
+ }
918
+ ],
919
+ "tier": "domain"
920
+ },
921
+ {
922
+ "description": "Body crossed killY in the gravity direction (pit fall); fires once per fall and re-arms on PLACE/RESTART, leaving the respawn rule to the board",
923
+ "id": "evt_01M0H2SJBBBE4DVTXJ13J4TKN4",
924
+ "key": "BODY_FELL",
925
+ "name": "Body Fell",
926
+ "payloadSchema": [
927
+ {
928
+ "name": "x",
929
+ "required": true,
930
+ "type": "number"
931
+ },
932
+ {
933
+ "name": "y",
934
+ "required": true,
935
+ "type": "number"
936
+ }
937
+ ],
938
+ "tier": "domain"
939
+ }
940
+ ],
941
+ "states": [
942
+ {
943
+ "isInitial": true,
944
+ "name": "active"
945
+ }
946
+ ],
947
+ "transitions": [
948
+ {
949
+ "effects": [
950
+ [
951
+ "set",
952
+ "@entity.body",
953
+ "@config.spawn"
954
+ ],
955
+ [
956
+ "set",
957
+ "@entity.fell",
958
+ false
959
+ ],
960
+ [
961
+ "set",
962
+ "@entity.hazardId",
963
+ ""
964
+ ],
965
+ [
966
+ "set",
967
+ "@entity.goalId",
968
+ ""
969
+ ],
970
+ [
971
+ "set",
972
+ "@entity.skating",
973
+ false
974
+ ]
975
+ ],
976
+ "event": "INIT",
977
+ "eventId": "evt_01M0H2SJBB1WZWWVDCP2FHNFXK",
978
+ "from": "active",
979
+ "to": "active"
980
+ },
981
+ {
982
+ "effects": [
983
+ [
984
+ "set",
985
+ "@entity.body",
986
+ [
987
+ "object/merge",
988
+ "@entity.body",
989
+ {
990
+ "facingRight": [
991
+ "if",
992
+ [
993
+ "!=",
994
+ "@payload.dir",
995
+ 0.0
996
+ ],
997
+ [
998
+ ">",
999
+ "@payload.dir",
1000
+ 0.0
1001
+ ],
1002
+ "@entity.body.facingRight"
1003
+ ],
1004
+ "vx": [
1005
+ "*",
1006
+ "@payload.dir",
1007
+ "@config.moveSpeed"
1008
+ ]
1009
+ }
1010
+ ]
1011
+ ]
1012
+ ],
1013
+ "event": "STEER",
1014
+ "eventId": "evt_01M0H2SJBB0ZDAJA2NJYDKJPJB",
1015
+ "from": "active",
1016
+ "guard": "@config.running",
1017
+ "to": "active"
1018
+ },
1019
+ {
1020
+ "effects": [
1021
+ [
1022
+ "set",
1023
+ "@entity.body",
1024
+ [
1025
+ "object/merge",
1026
+ "@entity.body",
1027
+ {
1028
+ "grounded": false,
1029
+ "vy": [
1030
+ "if",
1031
+ [
1032
+ ">",
1033
+ "@config.gravity",
1034
+ 0.0
1035
+ ],
1036
+ [
1037
+ "-",
1038
+ 0.0,
1039
+ "@config.jumpStrength"
1040
+ ],
1041
+ "@config.jumpStrength"
1042
+ ]
1043
+ }
1044
+ ]
1045
+ ],
1046
+ [
1047
+ "emit",
1048
+ "BODY_JUMPED",
1049
+ {
1050
+ "x": "@entity.body.x",
1051
+ "y": "@entity.body.y"
1052
+ }
1053
+ ]
1054
+ ],
1055
+ "event": "JUMP",
1056
+ "eventId": "evt_01M0H2SJBBSRSS0T8AN9VZM3R1",
1057
+ "from": "active",
1058
+ "guard": [
1059
+ "and",
1060
+ "@config.running",
1061
+ [
1062
+ "==",
1063
+ "@entity.body.grounded",
1064
+ true
1065
+ ]
1066
+ ],
1067
+ "to": "active"
1068
+ },
1069
+ {
1070
+ "effects": [
1071
+ [
1072
+ "set",
1073
+ "@entity.body",
1074
+ [
1075
+ "object/merge",
1076
+ "@entity.body",
1077
+ {
1078
+ "grounded": false,
1079
+ "vx": 0.0,
1080
+ "vy": 0.0,
1081
+ "x": "@payload.x",
1082
+ "y": "@payload.y"
1083
+ }
1084
+ ]
1085
+ ],
1086
+ [
1087
+ "set",
1088
+ "@entity.fell",
1089
+ false
1090
+ ],
1091
+ [
1092
+ "set",
1093
+ "@entity.hazardId",
1094
+ ""
1095
+ ],
1096
+ [
1097
+ "set",
1098
+ "@entity.skating",
1099
+ false
1100
+ ]
1101
+ ],
1102
+ "event": "PLACE",
1103
+ "eventId": "evt_01M0H2SJBBDPMZN6QSYNP2C76E",
1104
+ "from": "active",
1105
+ "to": "active"
1106
+ },
1107
+ {
1108
+ "effects": [
1109
+ [
1110
+ "set",
1111
+ "@entity.body",
1112
+ "@config.spawn"
1113
+ ],
1114
+ [
1115
+ "set",
1116
+ "@entity.fell",
1117
+ false
1118
+ ],
1119
+ [
1120
+ "set",
1121
+ "@entity.hazardId",
1122
+ ""
1123
+ ],
1124
+ [
1125
+ "set",
1126
+ "@entity.goalId",
1127
+ ""
1128
+ ],
1129
+ [
1130
+ "set",
1131
+ "@entity.skating",
1132
+ false
1133
+ ]
1134
+ ],
1135
+ "event": "RESTART",
1136
+ "eventId": "evt_01M0H2SJBBSCEAJH5FZN8AAX45",
1137
+ "from": "active",
1138
+ "to": "active"
1139
+ }
1140
+ ]
1141
+ },
1142
+ "ticks": [
1143
+ {
1144
+ "effects": [
1145
+ [
1146
+ "let",
1147
+ [
1148
+ [
1149
+ "gdir",
1150
+ [
1151
+ "if",
1152
+ [
1153
+ ">",
1154
+ "@config.gravity",
1155
+ 0.0
1156
+ ],
1157
+ 1.0,
1158
+ -1.0
1159
+ ]
1160
+ ]
1161
+ ],
1162
+ [
1163
+ "let",
1164
+ [
1165
+ [
1166
+ "vy1",
1167
+ [
1168
+ "math/clamp",
1169
+ [
1170
+ "+",
1171
+ "@entity.body.vy",
1172
+ [
1173
+ "*",
1174
+ "@config.gravity",
1175
+ 0.033
1176
+ ]
1177
+ ],
1178
+ [
1179
+ "-",
1180
+ 0.0,
1181
+ "@config.maxFallSpeed"
1182
+ ],
1183
+ "@config.maxFallSpeed"
1184
+ ]
1185
+ ]
1186
+ ],
1187
+ [
1188
+ "let",
1189
+ [
1190
+ [
1191
+ "bw",
1192
+ [
1193
+ "object/get",
1194
+ "@entity.body",
1195
+ "width"
1196
+ ]
1197
+ ],
1198
+ [
1199
+ "bh",
1200
+ [
1201
+ "object/get",
1202
+ "@entity.body",
1203
+ "height"
1204
+ ]
1205
+ ]
1206
+ ],
1207
+ [
1208
+ "let",
1209
+ [
1210
+ [
1211
+ "nx",
1212
+ [
1213
+ "math/clamp",
1214
+ [
1215
+ "+",
1216
+ "@entity.body.x",
1217
+ [
1218
+ "*",
1219
+ "@entity.body.vx",
1220
+ 0.033
1221
+ ]
1222
+ ],
1223
+ "@config.xMin",
1224
+ "@config.xMax"
1225
+ ]
1226
+ ]
1227
+ ],
1228
+ [
1229
+ "let",
1230
+ [
1231
+ [
1232
+ "ny",
1233
+ [
1234
+ "+",
1235
+ "@entity.body.y",
1236
+ [
1237
+ "*",
1238
+ "@vy1",
1239
+ 0.033
1240
+ ]
1241
+ ]
1242
+ ]
1243
+ ],
1244
+ [
1245
+ "let",
1246
+ [
1247
+ [
1248
+ "rect",
1249
+ {
1250
+ "h": "@bh",
1251
+ "w": "@bw",
1252
+ "x": "@nx",
1253
+ "y": "@ny"
1254
+ }
1255
+ ]
1256
+ ],
1257
+ [
1258
+ "let",
1259
+ [
1260
+ [
1261
+ "hit",
1262
+ [
1263
+ "array/find",
1264
+ "@config.platforms",
1265
+ [
1266
+ "fn",
1267
+ "p",
1268
+ [
1269
+ "and",
1270
+ [
1271
+ "or",
1272
+ [
1273
+ "==",
1274
+ [
1275
+ "object/get",
1276
+ "@p",
1277
+ "type"
1278
+ ],
1279
+ "ground"
1280
+ ],
1281
+ [
1282
+ "==",
1283
+ [
1284
+ "object/get",
1285
+ "@p",
1286
+ "type"
1287
+ ],
1288
+ "platform"
1289
+ ]
1290
+ ],
1291
+ [
1292
+ "geo/aabb-overlap",
1293
+ "@rect",
1294
+ {
1295
+ "h": "@p.height",
1296
+ "w": "@p.width",
1297
+ "x": "@p.x",
1298
+ "y": "@p.y"
1299
+ }
1300
+ ]
1301
+ ]
1302
+ ]
1303
+ ]
1304
+ ]
1305
+ ],
1306
+ [
1307
+ "let",
1308
+ [
1309
+ [
1310
+ "landed",
1311
+ [
1312
+ "and",
1313
+ [
1314
+ "!=",
1315
+ "@hit",
1316
+ null
1317
+ ],
1318
+ [
1319
+ ">",
1320
+ [
1321
+ "*",
1322
+ "@vy1",
1323
+ "@gdir"
1324
+ ],
1325
+ 0.0
1326
+ ]
1327
+ ]
1328
+ ]
1329
+ ],
1330
+ [
1331
+ "let",
1332
+ [
1333
+ [
1334
+ "ny2",
1335
+ [
1336
+ "if",
1337
+ "@landed",
1338
+ [
1339
+ "if",
1340
+ [
1341
+ ">",
1342
+ "@gdir",
1343
+ 0.0
1344
+ ],
1345
+ [
1346
+ "-",
1347
+ [
1348
+ "object/get",
1349
+ "@hit",
1350
+ "y"
1351
+ ],
1352
+ "@bh"
1353
+ ],
1354
+ [
1355
+ "+",
1356
+ [
1357
+ "object/get",
1358
+ "@hit",
1359
+ "y"
1360
+ ],
1361
+ [
1362
+ "object/get",
1363
+ "@hit",
1364
+ "height"
1365
+ ]
1366
+ ]
1367
+ ],
1368
+ "@ny"
1369
+ ]
1370
+ ],
1371
+ [
1372
+ "vy2",
1373
+ [
1374
+ "if",
1375
+ "@landed",
1376
+ 0.0,
1377
+ "@vy1"
1378
+ ]
1379
+ ]
1380
+ ],
1381
+ [
1382
+ "let",
1383
+ [
1384
+ [
1385
+ "cx",
1386
+ [
1387
+ "+",
1388
+ "@nx",
1389
+ [
1390
+ "/",
1391
+ "@bw",
1392
+ 2.0
1393
+ ]
1394
+ ]
1395
+ ]
1396
+ ],
1397
+ [
1398
+ "let",
1399
+ [
1400
+ [
1401
+ "inRange",
1402
+ [
1403
+ "and",
1404
+ "@config.skate",
1405
+ [
1406
+ "and",
1407
+ [
1408
+ ">",
1409
+ [
1410
+ "array/len",
1411
+ "@config.skateCurve"
1412
+ ],
1413
+ 1.0
1414
+ ],
1415
+ [
1416
+ "and",
1417
+ [
1418
+ ">=",
1419
+ "@cx",
1420
+ [
1421
+ "object/get",
1422
+ [
1423
+ "array/first",
1424
+ "@config.skateCurve"
1425
+ ],
1426
+ "x"
1427
+ ]
1428
+ ],
1429
+ [
1430
+ "<",
1431
+ "@cx",
1432
+ [
1433
+ "object/get",
1434
+ [
1435
+ "array/last",
1436
+ "@config.skateCurve"
1437
+ ],
1438
+ "x"
1439
+ ]
1440
+ ]
1441
+ ]
1442
+ ]
1443
+ ]
1444
+ ]
1445
+ ],
1446
+ [
1447
+ "let",
1448
+ [
1449
+ [
1450
+ "leftSamp",
1451
+ [
1452
+ "if",
1453
+ "@inRange",
1454
+ [
1455
+ "array/last",
1456
+ [
1457
+ "array/filter",
1458
+ "@config.skateCurve",
1459
+ [
1460
+ "fn",
1461
+ "s",
1462
+ [
1463
+ "<=",
1464
+ [
1465
+ "object/get",
1466
+ "@s",
1467
+ "x"
1468
+ ],
1469
+ "@cx"
1470
+ ]
1471
+ ]
1472
+ ]
1473
+ ],
1474
+ {
1475
+ "x": 0.0,
1476
+ "y": 0.0
1477
+ }
1478
+ ]
1479
+ ]
1480
+ ],
1481
+ [
1482
+ "let",
1483
+ [
1484
+ [
1485
+ "rightSamp",
1486
+ [
1487
+ "if",
1488
+ "@inRange",
1489
+ [
1490
+ "array/first",
1491
+ [
1492
+ "array/filter",
1493
+ "@config.skateCurve",
1494
+ [
1495
+ "fn",
1496
+ "s",
1497
+ [
1498
+ ">",
1499
+ [
1500
+ "object/get",
1501
+ "@s",
1502
+ "x"
1503
+ ],
1504
+ "@cx"
1505
+ ]
1506
+ ]
1507
+ ]
1508
+ ],
1509
+ {
1510
+ "x": 1.0,
1511
+ "y": 0.0
1512
+ }
1513
+ ]
1514
+ ]
1515
+ ],
1516
+ [
1517
+ "let",
1518
+ [
1519
+ [
1520
+ "slope",
1521
+ [
1522
+ "if",
1523
+ "@inRange",
1524
+ [
1525
+ "/",
1526
+ [
1527
+ "-",
1528
+ [
1529
+ "object/get",
1530
+ "@rightSamp",
1531
+ "y"
1532
+ ],
1533
+ [
1534
+ "object/get",
1535
+ "@leftSamp",
1536
+ "y"
1537
+ ]
1538
+ ],
1539
+ [
1540
+ "-",
1541
+ [
1542
+ "object/get",
1543
+ "@rightSamp",
1544
+ "x"
1545
+ ],
1546
+ [
1547
+ "object/get",
1548
+ "@leftSamp",
1549
+ "x"
1550
+ ]
1551
+ ]
1552
+ ],
1553
+ 0.0
1554
+ ]
1555
+ ]
1556
+ ],
1557
+ [
1558
+ "let",
1559
+ [
1560
+ [
1561
+ "curveY",
1562
+ [
1563
+ "if",
1564
+ "@inRange",
1565
+ [
1566
+ "+",
1567
+ [
1568
+ "object/get",
1569
+ "@leftSamp",
1570
+ "y"
1571
+ ],
1572
+ [
1573
+ "*",
1574
+ "@slope",
1575
+ [
1576
+ "-",
1577
+ "@cx",
1578
+ [
1579
+ "object/get",
1580
+ "@leftSamp",
1581
+ "x"
1582
+ ]
1583
+ ]
1584
+ ]
1585
+ ],
1586
+ 0.0
1587
+ ]
1588
+ ]
1589
+ ],
1590
+ [
1591
+ "let",
1592
+ [
1593
+ [
1594
+ "movingUp",
1595
+ [
1596
+ "<",
1597
+ [
1598
+ "*",
1599
+ "@vy1",
1600
+ "@gdir"
1601
+ ],
1602
+ -0.01
1603
+ ]
1604
+ ]
1605
+ ],
1606
+ [
1607
+ "let",
1608
+ [
1609
+ [
1610
+ "skateNow",
1611
+ [
1612
+ "and",
1613
+ "@inRange",
1614
+ [
1615
+ "and",
1616
+ [
1617
+ "<=",
1618
+ [
1619
+ "math/abs",
1620
+ [
1621
+ "-",
1622
+ "@ny2",
1623
+ "@curveY"
1624
+ ]
1625
+ ],
1626
+ "@config.skateSnap"
1627
+ ],
1628
+ [
1629
+ "and",
1630
+ [
1631
+ "or",
1632
+ "@landed",
1633
+ "@entity.skating"
1634
+ ],
1635
+ [
1636
+ "or",
1637
+ "@entity.body.grounded",
1638
+ [
1639
+ "not",
1640
+ "@movingUp"
1641
+ ]
1642
+ ]
1643
+ ]
1644
+ ]
1645
+ ]
1646
+ ]
1647
+ ],
1648
+ [
1649
+ "let",
1650
+ [
1651
+ [
1652
+ "vx2",
1653
+ [
1654
+ "if",
1655
+ "@skateNow",
1656
+ [
1657
+ "math/clamp",
1658
+ [
1659
+ "+",
1660
+ "@entity.body.vx",
1661
+ [
1662
+ "*",
1663
+ [
1664
+ "/",
1665
+ [
1666
+ "*",
1667
+ "@config.gravity",
1668
+ "@slope"
1669
+ ],
1670
+ [
1671
+ "+",
1672
+ 1.0,
1673
+ [
1674
+ "*",
1675
+ "@slope",
1676
+ "@slope"
1677
+ ]
1678
+ ]
1679
+ ],
1680
+ 0.033
1681
+ ]
1682
+ ],
1683
+ [
1684
+ "-",
1685
+ 0.0,
1686
+ "@config.maxFallSpeed"
1687
+ ],
1688
+ "@config.maxFallSpeed"
1689
+ ],
1690
+ "@entity.body.vx"
1691
+ ]
1692
+ ]
1693
+ ],
1694
+ [
1695
+ "let",
1696
+ [
1697
+ [
1698
+ "fy",
1699
+ [
1700
+ "if",
1701
+ "@skateNow",
1702
+ "@curveY",
1703
+ "@ny2"
1704
+ ]
1705
+ ],
1706
+ [
1707
+ "fvy",
1708
+ [
1709
+ "if",
1710
+ "@skateNow",
1711
+ [
1712
+ "*",
1713
+ "@slope",
1714
+ "@vx2"
1715
+ ],
1716
+ "@vy2"
1717
+ ]
1718
+ ],
1719
+ [
1720
+ "fgrounded",
1721
+ [
1722
+ "or",
1723
+ "@landed",
1724
+ "@skateNow"
1725
+ ]
1726
+ ]
1727
+ ],
1728
+ [
1729
+ "let",
1730
+ [
1731
+ [
1732
+ "hazardHit",
1733
+ [
1734
+ "array/find",
1735
+ "@config.platforms",
1736
+ [
1737
+ "fn",
1738
+ "p",
1739
+ [
1740
+ "and",
1741
+ [
1742
+ "==",
1743
+ [
1744
+ "object/get",
1745
+ "@p",
1746
+ "type"
1747
+ ],
1748
+ "hazard"
1749
+ ],
1750
+ [
1751
+ "geo/aabb-overlap",
1752
+ "@rect",
1753
+ {
1754
+ "h": "@p.height",
1755
+ "w": "@p.width",
1756
+ "x": "@p.x",
1757
+ "y": "@p.y"
1758
+ }
1759
+ ]
1760
+ ]
1761
+ ]
1762
+ ]
1763
+ ]
1764
+ ],
1765
+ [
1766
+ "let",
1767
+ [
1768
+ [
1769
+ "goalHit",
1770
+ [
1771
+ "array/find",
1772
+ "@config.platforms",
1773
+ [
1774
+ "fn",
1775
+ "p",
1776
+ [
1777
+ "and",
1778
+ [
1779
+ "==",
1780
+ [
1781
+ "object/get",
1782
+ "@p",
1783
+ "type"
1784
+ ],
1785
+ "goal"
1786
+ ],
1787
+ [
1788
+ "geo/aabb-overlap",
1789
+ "@rect",
1790
+ {
1791
+ "h": "@p.height",
1792
+ "w": "@p.width",
1793
+ "x": "@p.x",
1794
+ "y": "@p.y"
1795
+ }
1796
+ ]
1797
+ ]
1798
+ ]
1799
+ ]
1800
+ ]
1801
+ ],
1802
+ [
1803
+ "let",
1804
+ [
1805
+ [
1806
+ "fellNow",
1807
+ [
1808
+ "if",
1809
+ [
1810
+ ">",
1811
+ "@gdir",
1812
+ 0.0
1813
+ ],
1814
+ [
1815
+ ">",
1816
+ "@fy",
1817
+ "@config.killY"
1818
+ ],
1819
+ [
1820
+ "<",
1821
+ "@fy",
1822
+ "@config.killY"
1823
+ ]
1824
+ ]
1825
+ ]
1826
+ ],
1827
+ [
1828
+ "do",
1829
+ [
1830
+ "set",
1831
+ "@entity.body",
1832
+ [
1833
+ "object/merge",
1834
+ "@entity.body",
1835
+ {
1836
+ "grounded": "@fgrounded",
1837
+ "vx": [
1838
+ "if",
1839
+ [
1840
+ "or",
1841
+ [
1842
+ "==",
1843
+ "@nx",
1844
+ "@config.xMin"
1845
+ ],
1846
+ [
1847
+ "==",
1848
+ "@nx",
1849
+ "@config.xMax"
1850
+ ]
1851
+ ],
1852
+ 0.0,
1853
+ "@vx2"
1854
+ ],
1855
+ "vy": "@fvy",
1856
+ "x": "@nx",
1857
+ "y": "@fy"
1858
+ }
1859
+ ]
1860
+ ],
1861
+ [
1862
+ "set",
1863
+ "@entity.skating",
1864
+ "@skateNow"
1865
+ ],
1866
+ [
1867
+ "if",
1868
+ [
1869
+ "and",
1870
+ "@skateNow",
1871
+ [
1872
+ "==",
1873
+ "@entity.skating",
1874
+ false
1875
+ ]
1876
+ ],
1877
+ [
1878
+ "emit",
1879
+ "BODY_SKATE_START",
1880
+ {
1881
+ "slope": "@slope",
1882
+ "x": "@nx",
1883
+ "y": "@fy"
1884
+ }
1885
+ ],
1886
+ null
1887
+ ],
1888
+ [
1889
+ "if",
1890
+ [
1891
+ "and",
1892
+ [
1893
+ "==",
1894
+ "@skateNow",
1895
+ false
1896
+ ],
1897
+ [
1898
+ "==",
1899
+ "@entity.skating",
1900
+ true
1901
+ ]
1902
+ ],
1903
+ [
1904
+ "emit",
1905
+ "BODY_SKATE_END",
1906
+ {
1907
+ "x": "@nx",
1908
+ "y": "@fy"
1909
+ }
1910
+ ],
1911
+ null
1912
+ ],
1913
+ [
1914
+ "if",
1915
+ [
1916
+ "and",
1917
+ "@landed",
1918
+ [
1919
+ "==",
1920
+ "@entity.body.grounded",
1921
+ false
1922
+ ]
1923
+ ],
1924
+ [
1925
+ "emit",
1926
+ "BODY_LANDED",
1927
+ {
1928
+ "impact": [
1929
+ "*",
1930
+ "@vy1",
1931
+ "@gdir"
1932
+ ],
1933
+ "x": "@nx",
1934
+ "y": "@fy"
1935
+ }
1936
+ ],
1937
+ null
1938
+ ],
1939
+ [
1940
+ "if",
1941
+ [
1942
+ "!=",
1943
+ "@hazardHit",
1944
+ null
1945
+ ],
1946
+ [
1947
+ "if",
1948
+ [
1949
+ "!=",
1950
+ "@entity.hazardId",
1951
+ [
1952
+ "object/get",
1953
+ "@hazardHit",
1954
+ "id",
1955
+ ""
1956
+ ]
1957
+ ],
1958
+ [
1959
+ "do",
1960
+ [
1961
+ "set",
1962
+ "@entity.hazardId",
1963
+ [
1964
+ "object/get",
1965
+ "@hazardHit",
1966
+ "id",
1967
+ ""
1968
+ ]
1969
+ ],
1970
+ [
1971
+ "emit",
1972
+ "BODY_HAZARD",
1973
+ {
1974
+ "id": [
1975
+ "object/get",
1976
+ "@hazardHit",
1977
+ "id",
1978
+ ""
1979
+ ],
1980
+ "x": "@nx",
1981
+ "y": "@fy"
1982
+ }
1983
+ ]
1984
+ ],
1985
+ null
1986
+ ],
1987
+ [
1988
+ "set",
1989
+ "@entity.hazardId",
1990
+ ""
1991
+ ]
1992
+ ],
1993
+ [
1994
+ "if",
1995
+ [
1996
+ "!=",
1997
+ "@goalHit",
1998
+ null
1999
+ ],
2000
+ [
2001
+ "if",
2002
+ [
2003
+ "!=",
2004
+ "@entity.goalId",
2005
+ [
2006
+ "object/get",
2007
+ "@goalHit",
2008
+ "id",
2009
+ ""
2010
+ ]
2011
+ ],
2012
+ [
2013
+ "do",
2014
+ [
2015
+ "set",
2016
+ "@entity.goalId",
2017
+ [
2018
+ "object/get",
2019
+ "@goalHit",
2020
+ "id",
2021
+ ""
2022
+ ]
2023
+ ],
2024
+ [
2025
+ "emit",
2026
+ "BODY_GOAL",
2027
+ {
2028
+ "id": [
2029
+ "object/get",
2030
+ "@goalHit",
2031
+ "id",
2032
+ ""
2033
+ ],
2034
+ "x": "@nx",
2035
+ "y": "@fy"
2036
+ }
2037
+ ]
2038
+ ],
2039
+ null
2040
+ ],
2041
+ [
2042
+ "set",
2043
+ "@entity.goalId",
2044
+ ""
2045
+ ]
2046
+ ],
2047
+ [
2048
+ "if",
2049
+ [
2050
+ "and",
2051
+ "@fellNow",
2052
+ [
2053
+ "==",
2054
+ "@entity.fell",
2055
+ false
2056
+ ]
2057
+ ],
2058
+ [
2059
+ "do",
2060
+ [
2061
+ "set",
2062
+ "@entity.fell",
2063
+ true
2064
+ ],
2065
+ [
2066
+ "emit",
2067
+ "BODY_FELL",
2068
+ {
2069
+ "x": "@nx",
2070
+ "y": "@fy"
2071
+ }
2072
+ ]
2073
+ ],
2074
+ null
2075
+ ],
2076
+ [
2077
+ "emit",
2078
+ "BODY_MOVED",
2079
+ {
2080
+ "grounded": "@fgrounded",
2081
+ "skating": "@skateNow",
2082
+ "speed": [
2083
+ "math/hypot",
2084
+ "@entity.body.vx",
2085
+ "@fvy"
2086
+ ],
2087
+ "vx": "@entity.body.vx",
2088
+ "vy": "@fvy",
2089
+ "x": "@nx",
2090
+ "y": "@fy"
2091
+ }
2092
+ ]
2093
+ ]
2094
+ ]
2095
+ ]
2096
+ ]
2097
+ ]
2098
+ ]
2099
+ ]
2100
+ ]
2101
+ ]
2102
+ ]
2103
+ ]
2104
+ ]
2105
+ ]
2106
+ ]
2107
+ ]
2108
+ ]
2109
+ ]
2110
+ ]
2111
+ ]
2112
+ ]
2113
+ ]
2114
+ ]
2115
+ ]
2116
+ ],
2117
+ "guard": [
2118
+ "and",
2119
+ "@config.running",
2120
+ [
2121
+ ">",
2122
+ "@entity.body.width",
2123
+ 0.0
2124
+ ]
2125
+ ],
2126
+ "interval": 33.0,
2127
+ "name": "physicsTick"
2128
+ }
2129
+ ]
2130
+ }
2131
+ ]
2132
+ }
2133
+ ],
2134
+ "schemaVersion": 1,
2135
+ "version": "1.0.0"
2136
+ }