spawnpoint-studio 0.1.0__py3-none-any.whl

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 (118) hide show
  1. spawnpoint/__init__.py +3 -0
  2. spawnpoint/_data/examples/coin_hopper.json +228 -0
  3. spawnpoint/_data/examples/neon_arena.json +251 -0
  4. spawnpoint/_data/examples/pixel_arena.json +242 -0
  5. spawnpoint/_data/examples/pixel_hopper.json +221 -0
  6. spawnpoint/_data/godot/addons/spawn_point/components/aim_component.gd +63 -0
  7. spawnpoint/_data/godot/addons/spawn_point/components/animator_component.gd +66 -0
  8. spawnpoint/_data/godot/addons/spawn_point/components/chase_ai_component.gd +107 -0
  9. spawnpoint/_data/godot/addons/spawn_point/components/collectible_component.gd +58 -0
  10. spawnpoint/_data/godot/addons/spawn_point/components/gate_component.gd +64 -0
  11. spawnpoint/_data/godot/addons/spawn_point/components/health_component.gd +83 -0
  12. spawnpoint/_data/godot/addons/spawn_point/components/hitbox_component.gd +50 -0
  13. spawnpoint/_data/godot/addons/spawn_point/components/hurtbox_component.gd +48 -0
  14. spawnpoint/_data/godot/addons/spawn_point/components/juice_component.gd +219 -0
  15. spawnpoint/_data/godot/addons/spawn_point/components/patrol_ai_component.gd +63 -0
  16. spawnpoint/_data/godot/addons/spawn_point/components/platformer_movement_component.gd +204 -0
  17. spawnpoint/_data/godot/addons/spawn_point/components/player_input_component.gd +77 -0
  18. spawnpoint/_data/godot/addons/spawn_point/components/projectile_component.gd +64 -0
  19. spawnpoint/_data/godot/addons/spawn_point/components/spawner_component.gd +58 -0
  20. spawnpoint/_data/godot/addons/spawn_point/components/stomp_component.gd +56 -0
  21. spawnpoint/_data/godot/addons/spawn_point/components/top_down_movement_component.gd +101 -0
  22. spawnpoint/_data/godot/addons/spawn_point/components/trigger_zone_component.gd +32 -0
  23. spawnpoint/_data/godot/addons/spawn_point/components/weapon_component.gd +83 -0
  24. spawnpoint/_data/godot/addons/spawn_point/manifest.json +1509 -0
  25. spawnpoint/_data/godot/addons/spawn_point/runtime/camera_rig.gd +71 -0
  26. spawnpoint/_data/godot/addons/spawn_point/runtime/cockpit.gd +62 -0
  27. spawnpoint/_data/godot/addons/spawn_point/runtime/entity_core.gd +98 -0
  28. spawnpoint/_data/godot/addons/spawn_point/runtime/fx.gd +112 -0
  29. spawnpoint/_data/godot/addons/spawn_point/runtime/game_state.gd +111 -0
  30. spawnpoint/_data/godot/addons/spawn_point/runtime/hud.gd +155 -0
  31. spawnpoint/_data/godot/addons/spawn_point/runtime/level.gd +19 -0
  32. spawnpoint/_data/godot/addons/spawn_point/runtime/sfx.gd +58 -0
  33. spawnpoint/_data/godot/addons/spawn_point/runtime/sp.gd +121 -0
  34. spawnpoint/_data/godot/addons/spawn_point/runtime/world.gd +130 -0
  35. spawnpoint/_data/godot/addons/spawn_point/shaders/flash.gdshader +9 -0
  36. spawnpoint/_data/godot/addons/spawn_point/shaders/floor_grid.gdshader +13 -0
  37. spawnpoint/_data/godot/addons/spawn_point/tools/build.gd +612 -0
  38. spawnpoint/_data/godot/addons/spawn_point/tools/build.tscn +6 -0
  39. spawnpoint/_data/godot/addons/spawn_point/tools/capture.gd +42 -0
  40. spawnpoint/_data/godot/addons/spawn_point/tools/capture.tscn +6 -0
  41. spawnpoint/_data/godot/addons/spawn_point/tools/dump_manifest.gd +91 -0
  42. spawnpoint/_data/godot/addons/spawn_point/tools/dump_manifest.tscn +6 -0
  43. spawnpoint/_data/godot/addons/spawn_point/tools/playtest.gd +428 -0
  44. spawnpoint/_data/godot/addons/spawn_point/tools/playtest.tscn +6 -0
  45. spawnpoint/_data/godot/addons/spawn_point/tools/playtest_nav.gd +152 -0
  46. spawnpoint/_data/godot/addons/spawn_point/tools/record.gd +89 -0
  47. spawnpoint/_data/godot/addons/spawn_point/tools/record.tscn +6 -0
  48. spawnpoint/_data/godot/addons/spawn_point/tools/smoke.gd +72 -0
  49. spawnpoint/_data/godot/addons/spawn_point/tools/smoke.tscn +6 -0
  50. spawnpoint/analyze.py +387 -0
  51. spawnpoint/build.py +146 -0
  52. spawnpoint/cli.py +290 -0
  53. spawnpoint/cockpit/__init__.py +0 -0
  54. spawnpoint/cockpit/server.py +473 -0
  55. spawnpoint/cockpit/static/app.css +111 -0
  56. spawnpoint/cockpit/static/app.js +327 -0
  57. spawnpoint/cockpit/static/index.html +79 -0
  58. spawnpoint/diagnostics.py +91 -0
  59. spawnpoint/expr.py +219 -0
  60. spawnpoint/gif.py +58 -0
  61. spawnpoint/godot.py +107 -0
  62. spawnpoint/graph.py +175 -0
  63. spawnpoint/level.py +157 -0
  64. spawnpoint/llm_server.py +77 -0
  65. spawnpoint/manifest.py +222 -0
  66. spawnpoint/playtest/__init__.py +104 -0
  67. spawnpoint/playtest/report.py +148 -0
  68. spawnpoint/playtest/runner.py +51 -0
  69. spawnpoint/playtest/tuner.py +151 -0
  70. spawnpoint/project.py +94 -0
  71. spawnpoint/py.typed +0 -0
  72. spawnpoint/rules.py +310 -0
  73. spawnpoint/sfx.py +352 -0
  74. spawnpoint/sprites/__init__.py +0 -0
  75. spawnpoint/sprites/ai.py +222 -0
  76. spawnpoint/sprites/contour.py +147 -0
  77. spawnpoint/sprites/generate.py +507 -0
  78. spawnpoint/sprites/importer.py +212 -0
  79. spawnpoint/sprites/resolve.py +139 -0
  80. spawnpoint/sprites/spriteset.py +159 -0
  81. spawnpoint/sprites/tiles.py +102 -0
  82. spawnpoint/studio/__init__.py +0 -0
  83. spawnpoint/studio/assemble.py +528 -0
  84. spawnpoint/studio/brief.py +197 -0
  85. spawnpoint/studio/creative.py +124 -0
  86. spawnpoint/studio/dataset.py +136 -0
  87. spawnpoint/studio/edits.py +206 -0
  88. spawnpoint/studio/levelgen.py +352 -0
  89. spawnpoint/studio/llm.py +145 -0
  90. spawnpoint/studio/orchestrator.py +341 -0
  91. spawnpoint/studio/prompts.py +122 -0
  92. spawnpoint/studio/web.py +123 -0
  93. spawnpoint/studio/webcheck.py +210 -0
  94. spawnpoint/studio_cli.py +232 -0
  95. spawnpoint_studio-0.1.0.dist-info/METADATA +360 -0
  96. spawnpoint_studio-0.1.0.dist-info/RECORD +118 -0
  97. spawnpoint_studio-0.1.0.dist-info/WHEEL +5 -0
  98. spawnpoint_studio-0.1.0.dist-info/entry_points.txt +2 -0
  99. spawnpoint_studio-0.1.0.dist-info/licenses/LICENSE +21 -0
  100. spawnpoint_studio-0.1.0.dist-info/top_level.txt +2 -0
  101. tests/conftest.py +49 -0
  102. tests/test_ai_sprites.py +122 -0
  103. tests/test_analyze.py +116 -0
  104. tests/test_cockpit.py +148 -0
  105. tests/test_e2e.py +33 -0
  106. tests/test_expr.py +59 -0
  107. tests/test_gif.py +19 -0
  108. tests/test_godot_library.py +17 -0
  109. tests/test_graph.py +44 -0
  110. tests/test_level.py +64 -0
  111. tests/test_live_llm.py +38 -0
  112. tests/test_manifest.py +54 -0
  113. tests/test_playtest.py +129 -0
  114. tests/test_rules.py +85 -0
  115. tests/test_sfx.py +30 -0
  116. tests/test_sprites.py +261 -0
  117. tests/test_studio.py +335 -0
  118. tests/test_web.py +41 -0
@@ -0,0 +1,1509 @@
1
+ {
2
+ "godot": "4.6.2-stable (official)",
3
+ "components": [
4
+ {
5
+ "name": "Aim",
6
+ "class": "AimComponent",
7
+ "script": "res://addons/spawn_point/components/aim_component.gd",
8
+ "base": "Node",
9
+ "hosts": [],
10
+ "requires": [
11
+ "Weapon"
12
+ ],
13
+ "category": "controller",
14
+ "entity_params": [],
15
+ "params": [
16
+ {
17
+ "name": "mode",
18
+ "type": "String",
19
+ "hint": "enum",
20
+ "hint_string": "mouse,nearest_enemy,movement",
21
+ "default": "mouse",
22
+ "doc": "\"mouse\", \"nearest_enemy\" or \"movement\"."
23
+ },
24
+ {
25
+ "name": "rotate_visual",
26
+ "type": "bool",
27
+ "hint": "",
28
+ "hint_string": "",
29
+ "default": true,
30
+ "doc": "Rotate the visual to face the aim direction (top-down games)."
31
+ },
32
+ {
33
+ "name": "max_range",
34
+ "type": "float",
35
+ "hint": "range",
36
+ "hint_string": "0.0,5000.0,1.0",
37
+ "default": 600.0,
38
+ "doc": "Max distance for nearest_enemy targeting (px)."
39
+ }
40
+ ],
41
+ "state": [],
42
+ "signals": [],
43
+ "methods": [],
44
+ "doc": "Points the entity's Weapon (and visual) at the mouse, the nearest enemy, or the movement direction."
45
+ },
46
+ {
47
+ "name": "Animator",
48
+ "class": "AnimatorComponent",
49
+ "script": "res://addons/spawn_point/components/animator_component.gd",
50
+ "base": "Node",
51
+ "hosts": [],
52
+ "requires": [],
53
+ "category": "juice",
54
+ "entity_params": [],
55
+ "params": [
56
+ {
57
+ "name": "hurt_time",
58
+ "type": "float",
59
+ "hint": "range",
60
+ "hint_string": "0.0,2.0,0.01",
61
+ "default": 0.25,
62
+ "doc": "Seconds the hurt animation is shown after taking damage."
63
+ },
64
+ {
65
+ "name": "move_threshold",
66
+ "type": "float",
67
+ "hint": "range",
68
+ "hint_string": "0.0,200.0,1.0",
69
+ "default": 15.0,
70
+ "doc": "Speed (px/s) above which the entity counts as moving."
71
+ }
72
+ ],
73
+ "state": [
74
+ {
75
+ "name": "state",
76
+ "type": "String"
77
+ }
78
+ ],
79
+ "signals": [],
80
+ "methods": [
81
+ {
82
+ "name": "pick_state",
83
+ "args": [],
84
+ "default_count": 0,
85
+ "returns": "String",
86
+ "doc": "The state the entity is in right now."
87
+ }
88
+ ],
89
+ "doc": "Plays the entity sprite's animations from what the entity is doing: idle, run, jump, fall and hurt. Run speed follows movement speed. Attached automatically to entities that have a sprite."
90
+ },
91
+ {
92
+ "name": "ChaseAI",
93
+ "class": "ChaseAIComponent",
94
+ "script": "res://addons/spawn_point/components/chase_ai_component.gd",
95
+ "base": "Node",
96
+ "hosts": [
97
+ "CharacterBody2D"
98
+ ],
99
+ "requires": [],
100
+ "category": "controller",
101
+ "entity_params": [],
102
+ "params": [
103
+ {
104
+ "name": "detect_radius",
105
+ "type": "float",
106
+ "hint": "range",
107
+ "hint_string": "0.0,5000.0,1.0",
108
+ "default": 300.0,
109
+ "doc": "Distance at which the player is noticed (px)."
110
+ },
111
+ {
112
+ "name": "lose_radius",
113
+ "type": "float",
114
+ "hint": "range",
115
+ "hint_string": "0.0,5000.0,1.0",
116
+ "default": 480.0,
117
+ "doc": "Distance at which the chase is abandoned (px)."
118
+ },
119
+ {
120
+ "name": "keep_distance",
121
+ "type": "float",
122
+ "hint": "range",
123
+ "hint_string": "0.0,2000.0,1.0",
124
+ "default": 0.0,
125
+ "doc": "Stop approaching inside this distance (ranged enemies keep their distance)."
126
+ },
127
+ {
128
+ "name": "fire_range",
129
+ "type": "float",
130
+ "hint": "range",
131
+ "hint_string": "0.0,5000.0,1.0",
132
+ "default": 380.0,
133
+ "doc": "Weapon fires when the player is within this distance (px)."
134
+ },
135
+ {
136
+ "name": "wander",
137
+ "type": "bool",
138
+ "hint": "",
139
+ "hint_string": "",
140
+ "default": true,
141
+ "doc": "Wander around while idle."
142
+ },
143
+ {
144
+ "name": "wander_speed",
145
+ "type": "float",
146
+ "hint": "range",
147
+ "hint_string": "0.0,1.0,0.05",
148
+ "default": 0.35,
149
+ "doc": "Fraction of max speed used while wandering."
150
+ },
151
+ {
152
+ "name": "needs_line_of_sight",
153
+ "type": "bool",
154
+ "hint": "",
155
+ "hint_string": "",
156
+ "default": true,
157
+ "doc": "Require an unobstructed line to the player to chase/shoot."
158
+ }
159
+ ],
160
+ "state": [
161
+ {
162
+ "name": "state",
163
+ "type": "int"
164
+ }
165
+ ],
166
+ "signals": [],
167
+ "methods": [],
168
+ "doc": "Enemy brain: wanders until the player comes close, then chases (and shoots, if the entity has a Weapon and a clear line of sight). Works top-down; in platformers it only moves horizontally."
169
+ },
170
+ {
171
+ "name": "Collectible",
172
+ "class": "CollectibleComponent",
173
+ "script": "res://addons/spawn_point/components/collectible_component.gd",
174
+ "base": "Node",
175
+ "hosts": [
176
+ "Area2D"
177
+ ],
178
+ "requires": [],
179
+ "category": "core",
180
+ "entity_params": [],
181
+ "params": [
182
+ {
183
+ "name": "kind",
184
+ "type": "String",
185
+ "hint": "",
186
+ "hint_string": "",
187
+ "default": "coin",
188
+ "doc": "Free-form kind, usable in rules (\"coin\", \"key\", \"heart\")."
189
+ },
190
+ {
191
+ "name": "score",
192
+ "type": "int",
193
+ "hint": "range",
194
+ "hint_string": "0.0,100000.0",
195
+ "default": 1,
196
+ "doc": "Score added on pickup (0 = none)."
197
+ },
198
+ {
199
+ "name": "heal",
200
+ "type": "int",
201
+ "hint": "range",
202
+ "hint_string": "0.0,999.0",
203
+ "default": 0,
204
+ "doc": "Health restored to the collector on pickup (0 = none)."
205
+ },
206
+ {
207
+ "name": "bob_height",
208
+ "type": "float",
209
+ "hint": "range",
210
+ "hint_string": "0.0,32.0,0.5",
211
+ "default": 3.0,
212
+ "doc": "Bobbing height in px (0 = static)."
213
+ }
214
+ ],
215
+ "state": [],
216
+ "signals": [
217
+ {
218
+ "name": "collected",
219
+ "args": [
220
+ {
221
+ "name": "by",
222
+ "type": "Node"
223
+ }
224
+ ],
225
+ "doc": "Emitted when collected; [param by] is the collecting entity."
226
+ }
227
+ ],
228
+ "methods": [],
229
+ "doc": "A pickup (coin, gem, key...). Touching it adds [member score], emits [signal collected] and removes it. The visual bobs gently so pickups read as \"take me\"."
230
+ },
231
+ {
232
+ "name": "Gate",
233
+ "class": "GateComponent",
234
+ "script": "res://addons/spawn_point/components/gate_component.gd",
235
+ "base": "Node",
236
+ "hosts": [
237
+ "StaticBody2D"
238
+ ],
239
+ "requires": [],
240
+ "category": "core",
241
+ "entity_params": [],
242
+ "params": [
243
+ {
244
+ "name": "starts_open",
245
+ "type": "bool",
246
+ "hint": "",
247
+ "hint_string": "",
248
+ "default": false,
249
+ "doc": "Start open."
250
+ }
251
+ ],
252
+ "state": [
253
+ {
254
+ "name": "is_open",
255
+ "type": "bool"
256
+ }
257
+ ],
258
+ "signals": [
259
+ {
260
+ "name": "opened",
261
+ "args": [],
262
+ "doc": "Emitted when the gate opens."
263
+ },
264
+ {
265
+ "name": "closed",
266
+ "args": [],
267
+ "doc": "Emitted when the gate closes."
268
+ }
269
+ ],
270
+ "methods": [
271
+ {
272
+ "name": "open",
273
+ "args": [],
274
+ "default_count": 0,
275
+ "returns": "Nil",
276
+ "doc": "Opens the gate (no collision, faded visual)."
277
+ },
278
+ {
279
+ "name": "close",
280
+ "args": [],
281
+ "default_count": 0,
282
+ "returns": "Nil",
283
+ "doc": "Closes the gate."
284
+ },
285
+ {
286
+ "name": "toggle",
287
+ "args": [],
288
+ "default_count": 0,
289
+ "returns": "Nil",
290
+ "doc": "Opens if closed, closes if open."
291
+ }
292
+ ],
293
+ "doc": "A solid barrier that can be opened and closed by rules (doors, bridges, locked exits)."
294
+ },
295
+ {
296
+ "name": "Health",
297
+ "class": "HealthComponent",
298
+ "script": "res://addons/spawn_point/components/health_component.gd",
299
+ "base": "Node",
300
+ "hosts": [],
301
+ "requires": [],
302
+ "category": "core",
303
+ "entity_params": [],
304
+ "params": [
305
+ {
306
+ "name": "max_health",
307
+ "type": "int",
308
+ "hint": "range",
309
+ "hint_string": "1.0,999.0",
310
+ "default": 3,
311
+ "doc": "Maximum (and starting) hit points."
312
+ },
313
+ {
314
+ "name": "invincibility_time",
315
+ "type": "float",
316
+ "hint": "range",
317
+ "hint_string": "0.0,5.0,0.01",
318
+ "default": 0.6,
319
+ "doc": "Seconds of invincibility after being hit (prevents instant multi-hits)."
320
+ }
321
+ ],
322
+ "state": [
323
+ {
324
+ "name": "current",
325
+ "type": "int"
326
+ }
327
+ ],
328
+ "signals": [
329
+ {
330
+ "name": "damaged",
331
+ "args": [
332
+ {
333
+ "name": "amount",
334
+ "type": "int"
335
+ }
336
+ ],
337
+ "doc": "Emitted after taking damage that was not blocked."
338
+ },
339
+ {
340
+ "name": "healed",
341
+ "args": [
342
+ {
343
+ "name": "amount",
344
+ "type": "int"
345
+ }
346
+ ],
347
+ "doc": "Emitted after healing."
348
+ },
349
+ {
350
+ "name": "died",
351
+ "args": [],
352
+ "doc": "Emitted once when health reaches zero."
353
+ }
354
+ ],
355
+ "methods": [
356
+ {
357
+ "name": "damage",
358
+ "args": [
359
+ {
360
+ "name": "amount",
361
+ "type": "int"
362
+ }
363
+ ],
364
+ "default_count": 0,
365
+ "returns": "Nil",
366
+ "doc": "Deals [param amount] damage unless invincible or dead."
367
+ },
368
+ {
369
+ "name": "heal",
370
+ "args": [
371
+ {
372
+ "name": "amount",
373
+ "type": "int"
374
+ }
375
+ ],
376
+ "default_count": 0,
377
+ "returns": "Nil",
378
+ "doc": "Restores up to [param amount] hit points."
379
+ },
380
+ {
381
+ "name": "kill",
382
+ "args": [],
383
+ "default_count": 0,
384
+ "returns": "Nil",
385
+ "doc": "Kills the entity immediately, ignoring invincibility."
386
+ },
387
+ {
388
+ "name": "reset",
389
+ "args": [],
390
+ "default_count": 0,
391
+ "returns": "Nil",
392
+ "doc": "Restores full health."
393
+ },
394
+ {
395
+ "name": "grant_invincibility",
396
+ "args": [
397
+ {
398
+ "name": "seconds",
399
+ "type": "float"
400
+ }
401
+ ],
402
+ "default_count": 0,
403
+ "returns": "Nil",
404
+ "doc": "Makes the entity invincible for [param seconds]."
405
+ },
406
+ {
407
+ "name": "is_invincible",
408
+ "args": [],
409
+ "default_count": 0,
410
+ "returns": "bool",
411
+ "doc": "True while hits are ignored."
412
+ },
413
+ {
414
+ "name": "is_dead",
415
+ "args": [],
416
+ "default_count": 0,
417
+ "returns": "bool",
418
+ "doc": "True when health is zero."
419
+ }
420
+ ],
421
+ "doc": "Hit points with brief invincibility after each hit. When health reaches zero the entity dies (players respawn while lives remain)."
422
+ },
423
+ {
424
+ "name": "Hitbox",
425
+ "class": "HitboxComponent",
426
+ "script": "res://addons/spawn_point/components/hitbox_component.gd",
427
+ "base": "Area2D",
428
+ "hosts": [],
429
+ "requires": [],
430
+ "category": "core",
431
+ "entity_params": [],
432
+ "params": [
433
+ {
434
+ "name": "damage",
435
+ "type": "int",
436
+ "hint": "range",
437
+ "hint_string": "0.0,999.0",
438
+ "default": 1,
439
+ "doc": "Damage per hit."
440
+ },
441
+ {
442
+ "name": "knockback",
443
+ "type": "float",
444
+ "hint": "range",
445
+ "hint_string": "0.0,2000.0,1.0",
446
+ "default": 260.0,
447
+ "doc": "Push applied to the victim, in pixels/second."
448
+ },
449
+ {
450
+ "name": "size_scale",
451
+ "type": "float",
452
+ "hint": "range",
453
+ "hint_string": "0.1,2.0,0.05",
454
+ "default": 1.0,
455
+ "doc": "Hitbox size relative to the entity shape."
456
+ },
457
+ {
458
+ "name": "hurts_own_team",
459
+ "type": "bool",
460
+ "hint": "",
461
+ "hint_string": "",
462
+ "default": false,
463
+ "doc": "Neutral hitboxes (traps) hurt both teams."
464
+ }
465
+ ],
466
+ "state": [],
467
+ "signals": [
468
+ {
469
+ "name": "hit",
470
+ "args": [
471
+ {
472
+ "name": "target",
473
+ "type": "Node"
474
+ }
475
+ ],
476
+ "doc": "Emitted when this hitbox damages [param target] (the entity that was hit)."
477
+ }
478
+ ],
479
+ "methods": [],
480
+ "doc": "Deals damage to hurtboxes of the opposing team on contact (enemy bodies, bullets, spikes)."
481
+ },
482
+ {
483
+ "name": "Hurtbox",
484
+ "class": "HurtboxComponent",
485
+ "script": "res://addons/spawn_point/components/hurtbox_component.gd",
486
+ "base": "Area2D",
487
+ "hosts": [],
488
+ "requires": [
489
+ "Health"
490
+ ],
491
+ "category": "core",
492
+ "entity_params": [],
493
+ "params": [
494
+ {
495
+ "name": "size_scale",
496
+ "type": "float",
497
+ "hint": "range",
498
+ "hint_string": "0.1,2.0,0.05",
499
+ "default": 0.85,
500
+ "doc": "Hurtbox size relative to the entity shape. Below 1 is more forgiving for the player."
501
+ },
502
+ {
503
+ "name": "knockback_scale",
504
+ "type": "float",
505
+ "hint": "range",
506
+ "hint_string": "0.0,5.0,0.05",
507
+ "default": 1.0,
508
+ "doc": "Multiplies knockback received."
509
+ }
510
+ ],
511
+ "state": [
512
+ {
513
+ "name": "last_hit_by",
514
+ "type": "Object"
515
+ }
516
+ ],
517
+ "signals": [
518
+ {
519
+ "name": "hurt",
520
+ "args": [
521
+ {
522
+ "name": "amount",
523
+ "type": "int"
524
+ }
525
+ ],
526
+ "doc": "Emitted when a hit lands (after invincibility checks)."
527
+ }
528
+ ],
529
+ "methods": [],
530
+ "doc": "The area where this entity can be hit. Forwards damage to Health and pushes the entity back."
531
+ },
532
+ {
533
+ "name": "Juice",
534
+ "class": "JuiceComponent",
535
+ "script": "res://addons/spawn_point/components/juice_component.gd",
536
+ "base": "Node",
537
+ "hosts": [],
538
+ "requires": [],
539
+ "category": "juice",
540
+ "entity_params": [],
541
+ "params": [
542
+ {
543
+ "name": "squash",
544
+ "type": "bool",
545
+ "hint": "",
546
+ "hint_string": "",
547
+ "default": true,
548
+ "doc": "Squash & stretch on jump, land and hit."
549
+ },
550
+ {
551
+ "name": "squash_amount",
552
+ "type": "float",
553
+ "hint": "range",
554
+ "hint_string": "0.0,0.8,0.01",
555
+ "default": 0.28,
556
+ "doc": "Squash strength (0.3 = 30% deformation)."
557
+ },
558
+ {
559
+ "name": "flash",
560
+ "type": "bool",
561
+ "hint": "",
562
+ "hint_string": "",
563
+ "default": true,
564
+ "doc": "Flash white when damaged."
565
+ },
566
+ {
567
+ "name": "shake_on_hurt",
568
+ "type": "float",
569
+ "hint": "range",
570
+ "hint_string": "0.0,1.0,0.01",
571
+ "default": 0.35,
572
+ "doc": "Screen shake when this entity is hurt (0..1 trauma)."
573
+ },
574
+ {
575
+ "name": "shake_on_death",
576
+ "type": "float",
577
+ "hint": "range",
578
+ "hint_string": "0.0,1.0,0.01",
579
+ "default": 0.45,
580
+ "doc": "Screen shake when this entity dies."
581
+ },
582
+ {
583
+ "name": "shake_on_fire",
584
+ "type": "float",
585
+ "hint": "range",
586
+ "hint_string": "0.0,1.0,0.01",
587
+ "default": 0.06,
588
+ "doc": "Screen shake when this entity fires."
589
+ },
590
+ {
591
+ "name": "hitstop_on_hurt",
592
+ "type": "float",
593
+ "hint": "range",
594
+ "hint_string": "0.0,0.3,0.005",
595
+ "default": 0.06,
596
+ "doc": "Hit-stop (freeze frame) seconds when hurt."
597
+ },
598
+ {
599
+ "name": "hitstop_on_death",
600
+ "type": "float",
601
+ "hint": "range",
602
+ "hint_string": "0.0,0.3,0.005",
603
+ "default": 0.04,
604
+ "doc": "Hit-stop seconds when killed."
605
+ },
606
+ {
607
+ "name": "particles",
608
+ "type": "bool",
609
+ "hint": "",
610
+ "hint_string": "",
611
+ "default": true,
612
+ "doc": "Particle effects (death burst, landing dust, pickup sparkle)."
613
+ },
614
+ {
615
+ "name": "dash_trail",
616
+ "type": "bool",
617
+ "hint": "",
618
+ "hint_string": "",
619
+ "default": true,
620
+ "doc": "After-images while dashing."
621
+ },
622
+ {
623
+ "name": "face_movement",
624
+ "type": "bool",
625
+ "hint": "",
626
+ "hint_string": "",
627
+ "default": true,
628
+ "doc": "Turn the visual to face the movement direction."
629
+ },
630
+ {
631
+ "name": "sounds",
632
+ "type": "bool",
633
+ "hint": "",
634
+ "hint_string": "",
635
+ "default": true,
636
+ "doc": "Play sound effects."
637
+ },
638
+ {
639
+ "name": "pitch_variance",
640
+ "type": "float",
641
+ "hint": "range",
642
+ "hint_string": "0.0,0.5,0.01",
643
+ "default": 0.1,
644
+ "doc": "Random pitch variation for sounds (0.1 = ±10%)."
645
+ },
646
+ {
647
+ "name": "sound_jump",
648
+ "type": "String",
649
+ "hint": "",
650
+ "hint_string": "",
651
+ "default": "jump",
652
+ "doc": "Sound played on jump."
653
+ },
654
+ {
655
+ "name": "sound_land",
656
+ "type": "String",
657
+ "hint": "",
658
+ "hint_string": "",
659
+ "default": "land",
660
+ "doc": "Sound played on a hard landing."
661
+ },
662
+ {
663
+ "name": "sound_hurt",
664
+ "type": "String",
665
+ "hint": "",
666
+ "hint_string": "",
667
+ "default": "hurt",
668
+ "doc": "Sound played when damaged."
669
+ },
670
+ {
671
+ "name": "sound_death",
672
+ "type": "String",
673
+ "hint": "",
674
+ "hint_string": "",
675
+ "default": "explosion",
676
+ "doc": "Sound played on death."
677
+ },
678
+ {
679
+ "name": "sound_fire",
680
+ "type": "String",
681
+ "hint": "",
682
+ "hint_string": "",
683
+ "default": "shoot",
684
+ "doc": "Sound played when the Weapon fires."
685
+ },
686
+ {
687
+ "name": "sound_collect",
688
+ "type": "String",
689
+ "hint": "",
690
+ "hint_string": "",
691
+ "default": "coin",
692
+ "doc": "Sound played when collected (pitch rises on quick chains)."
693
+ },
694
+ {
695
+ "name": "sound_dash",
696
+ "type": "String",
697
+ "hint": "",
698
+ "hint_string": "",
699
+ "default": "dash",
700
+ "doc": "Sound played on dash."
701
+ }
702
+ ],
703
+ "state": [],
704
+ "signals": [],
705
+ "methods": [
706
+ {
707
+ "name": "squash_stretch",
708
+ "args": [
709
+ {
710
+ "name": "amount",
711
+ "type": "float"
712
+ },
713
+ {
714
+ "name": "duration",
715
+ "type": "float"
716
+ }
717
+ ],
718
+ "default_count": 1,
719
+ "returns": "Nil",
720
+ "doc": "Squash (x wider, y shorter) when [param amount] > 0, stretch when < 0, then spring back."
721
+ },
722
+ {
723
+ "name": "flash_white",
724
+ "args": [
725
+ {
726
+ "name": "duration",
727
+ "type": "float"
728
+ }
729
+ ],
730
+ "default_count": 1,
731
+ "returns": "Nil",
732
+ "doc": "Flashes the visual white for [param duration] seconds."
733
+ }
734
+ ],
735
+ "doc": "Game feel for one entity. Wires itself to whatever sibling components exist and adds feedback: squash & stretch on jump/land, white flash + shake + hit-stop when hurt, after-images on dash, particle bursts on death and pickup, recoil shake and sounds. Attached automatically to every entity unless the game disables juice."
736
+ },
737
+ {
738
+ "name": "PatrolAI",
739
+ "class": "PatrolAIComponent",
740
+ "script": "res://addons/spawn_point/components/patrol_ai_component.gd",
741
+ "base": "Node",
742
+ "hosts": [
743
+ "CharacterBody2D"
744
+ ],
745
+ "requires": [
746
+ "PlatformerMovement"
747
+ ],
748
+ "category": "controller",
749
+ "entity_params": [],
750
+ "params": [
751
+ {
752
+ "name": "start_direction",
753
+ "type": "String",
754
+ "hint": "enum",
755
+ "hint_string": "left,right",
756
+ "default": "left",
757
+ "doc": "Initial walking direction."
758
+ },
759
+ {
760
+ "name": "turn_at_ledges",
761
+ "type": "bool",
762
+ "hint": "",
763
+ "hint_string": "",
764
+ "default": true,
765
+ "doc": "Turn around instead of walking off ledges."
766
+ },
767
+ {
768
+ "name": "speed_scale",
769
+ "type": "float",
770
+ "hint": "range",
771
+ "hint_string": "0.0,1.0,0.05",
772
+ "default": 1.0,
773
+ "doc": "Fraction of the movement max_speed to walk at."
774
+ },
775
+ {
776
+ "name": "jump_interval",
777
+ "type": "float",
778
+ "hint": "range",
779
+ "hint_string": "0.0,30.0,0.1",
780
+ "default": 0.0,
781
+ "doc": "Seconds between hops (0 = never hop)."
782
+ }
783
+ ],
784
+ "state": [
785
+ {
786
+ "name": "direction",
787
+ "type": "int"
788
+ }
789
+ ],
790
+ "signals": [],
791
+ "methods": [],
792
+ "doc": "Platformer enemy brain: walks back and forth, turning at walls and (optionally) ledges. Can hop periodically."
793
+ },
794
+ {
795
+ "name": "PlatformerMovement",
796
+ "class": "PlatformerMovementComponent",
797
+ "script": "res://addons/spawn_point/components/platformer_movement_component.gd",
798
+ "base": "Node",
799
+ "hosts": [
800
+ "CharacterBody2D"
801
+ ],
802
+ "requires": [],
803
+ "category": "movement",
804
+ "entity_params": [],
805
+ "params": [
806
+ {
807
+ "name": "max_speed",
808
+ "type": "float",
809
+ "hint": "range",
810
+ "hint_string": "0.0,2000.0,1.0",
811
+ "default": 230.0,
812
+ "doc": "Top running speed (px/s)."
813
+ },
814
+ {
815
+ "name": "acceleration",
816
+ "type": "float",
817
+ "hint": "range",
818
+ "hint_string": "0.0,20000.0,10.0",
819
+ "default": 2200.0,
820
+ "doc": "Ground acceleration toward max speed (px/s²)."
821
+ },
822
+ {
823
+ "name": "deceleration",
824
+ "type": "float",
825
+ "hint": "range",
826
+ "hint_string": "0.0,20000.0,10.0",
827
+ "default": 2600.0,
828
+ "doc": "Ground deceleration when no input (px/s²)."
829
+ },
830
+ {
831
+ "name": "air_acceleration",
832
+ "type": "float",
833
+ "hint": "range",
834
+ "hint_string": "0.0,20000.0,10.0",
835
+ "default": 1500.0,
836
+ "doc": "Air acceleration (px/s²). Lower = less air control."
837
+ },
838
+ {
839
+ "name": "air_deceleration",
840
+ "type": "float",
841
+ "hint": "range",
842
+ "hint_string": "0.0,20000.0,10.0",
843
+ "default": 800.0,
844
+ "doc": "Air deceleration when no input (px/s²)."
845
+ },
846
+ {
847
+ "name": "jump_velocity",
848
+ "type": "float",
849
+ "hint": "range",
850
+ "hint_string": "0.0,3000.0,1.0",
851
+ "default": 620.0,
852
+ "doc": "Initial jump speed (px/s). Jump height ≈ jump_velocity² / (2·gravity)."
853
+ },
854
+ {
855
+ "name": "gravity_scale",
856
+ "type": "float",
857
+ "hint": "range",
858
+ "hint_string": "0.0,5.0,0.05",
859
+ "default": 1.0,
860
+ "doc": "Multiplies the project gravity for this entity."
861
+ },
862
+ {
863
+ "name": "fall_gravity_multiplier",
864
+ "type": "float",
865
+ "hint": "range",
866
+ "hint_string": "1.0,5.0,0.05",
867
+ "default": 1.7,
868
+ "doc": "Extra gravity while falling — makes jumps feel weighty instead of floaty."
869
+ },
870
+ {
871
+ "name": "jump_cut",
872
+ "type": "float",
873
+ "hint": "range",
874
+ "hint_string": "0.0,1.0,0.05",
875
+ "default": 0.45,
876
+ "doc": "Vertical speed is multiplied by this when jump is released while rising (short hop)."
877
+ },
878
+ {
879
+ "name": "apex_gravity_multiplier",
880
+ "type": "float",
881
+ "hint": "range",
882
+ "hint_string": "0.1,1.0,0.05",
883
+ "default": 0.6,
884
+ "doc": "Gravity multiplier near the top of a held jump (a little hang time)."
885
+ },
886
+ {
887
+ "name": "apex_threshold",
888
+ "type": "float",
889
+ "hint": "range",
890
+ "hint_string": "0.0,500.0,1.0",
891
+ "default": 70.0,
892
+ "doc": "Vertical speed below which the apex hang applies (px/s)."
893
+ },
894
+ {
895
+ "name": "max_fall_speed",
896
+ "type": "float",
897
+ "hint": "range",
898
+ "hint_string": "50.0,5000.0,1.0",
899
+ "default": 900.0,
900
+ "doc": "Terminal fall speed (px/s)."
901
+ },
902
+ {
903
+ "name": "coyote_time",
904
+ "type": "float",
905
+ "hint": "range",
906
+ "hint_string": "0.0,0.5,0.01",
907
+ "default": 0.1,
908
+ "doc": "Seconds after leaving a ledge during which jumping still works."
909
+ },
910
+ {
911
+ "name": "jump_buffer",
912
+ "type": "float",
913
+ "hint": "range",
914
+ "hint_string": "0.0,0.5,0.01",
915
+ "default": 0.12,
916
+ "doc": "Seconds a jump press is remembered before landing."
917
+ },
918
+ {
919
+ "name": "air_jumps",
920
+ "type": "int",
921
+ "hint": "range",
922
+ "hint_string": "0.0,5.0",
923
+ "default": 0,
924
+ "doc": "Extra jumps in the air (1 = double jump)."
925
+ },
926
+ {
927
+ "name": "dash_speed",
928
+ "type": "float",
929
+ "hint": "range",
930
+ "hint_string": "0.0,3000.0,1.0",
931
+ "default": 0.0,
932
+ "doc": "Dash speed (px/s). 0 disables dashing."
933
+ },
934
+ {
935
+ "name": "dash_duration",
936
+ "type": "float",
937
+ "hint": "range",
938
+ "hint_string": "0.02,1.0,0.01",
939
+ "default": 0.14,
940
+ "doc": "Dash duration in seconds."
941
+ },
942
+ {
943
+ "name": "dash_cooldown",
944
+ "type": "float",
945
+ "hint": "range",
946
+ "hint_string": "0.0,5.0,0.01",
947
+ "default": 0.45,
948
+ "doc": "Seconds between dashes."
949
+ }
950
+ ],
951
+ "state": [
952
+ {
953
+ "name": "move_vector",
954
+ "type": "Vector2"
955
+ },
956
+ {
957
+ "name": "jump_held",
958
+ "type": "bool"
959
+ },
960
+ {
961
+ "name": "facing",
962
+ "type": "int"
963
+ }
964
+ ],
965
+ "signals": [
966
+ {
967
+ "name": "jumped",
968
+ "args": [],
969
+ "doc": "Emitted when a jump starts (ground, coyote or air jump)."
970
+ },
971
+ {
972
+ "name": "landed",
973
+ "args": [
974
+ {
975
+ "name": "impact_speed",
976
+ "type": "float"
977
+ }
978
+ ],
979
+ "doc": "Emitted when touching the floor after being airborne. [param impact_speed] is the fall speed."
980
+ },
981
+ {
982
+ "name": "dashed",
983
+ "args": [],
984
+ "doc": "Emitted when a dash starts."
985
+ }
986
+ ],
987
+ "methods": [
988
+ {
989
+ "name": "request_jump",
990
+ "args": [],
991
+ "default_count": 0,
992
+ "returns": "Nil",
993
+ "doc": "Asks for a jump; it happens as soon as it is allowed (buffered)."
994
+ },
995
+ {
996
+ "name": "request_dash",
997
+ "args": [],
998
+ "default_count": 0,
999
+ "returns": "Nil",
1000
+ "doc": "Asks for a dash in the move / facing direction."
1001
+ },
1002
+ {
1003
+ "name": "bounce",
1004
+ "args": [
1005
+ {
1006
+ "name": "speed",
1007
+ "type": "float"
1008
+ }
1009
+ ],
1010
+ "default_count": 0,
1011
+ "returns": "Nil",
1012
+ "doc": "Launches the entity upward (e.g. after stomping an enemy). Not cut by releasing jump."
1013
+ },
1014
+ {
1015
+ "name": "apply_knockback",
1016
+ "args": [
1017
+ {
1018
+ "name": "impulse",
1019
+ "type": "Vector2"
1020
+ }
1021
+ ],
1022
+ "default_count": 0,
1023
+ "returns": "Nil",
1024
+ "doc": "Pushes the entity; player control is reduced briefly so the push is felt."
1025
+ },
1026
+ {
1027
+ "name": "is_dashing",
1028
+ "args": [],
1029
+ "default_count": 0,
1030
+ "returns": "bool",
1031
+ "doc": "True while dashing."
1032
+ }
1033
+ ],
1034
+ "doc": "Side-view running and jumping tuned for good game feel.\nIncludes coyote time (jump shortly after leaving a ledge), jump buffering (press jump shortly before landing), variable jump height (release early for a short hop), stronger gravity when falling, a little hang time at the apex, snappy turning and an optional dash. Reads intent (move_vector, jump requests) from a controller such as PlayerInput or PatrolAI."
1035
+ },
1036
+ {
1037
+ "name": "PlayerInput",
1038
+ "class": "PlayerInputComponent",
1039
+ "script": "res://addons/spawn_point/components/player_input_component.gd",
1040
+ "base": "Node",
1041
+ "hosts": [
1042
+ "CharacterBody2D"
1043
+ ],
1044
+ "requires": [],
1045
+ "category": "controller",
1046
+ "entity_params": [],
1047
+ "params": [],
1048
+ "state": [],
1049
+ "signals": [],
1050
+ "methods": [],
1051
+ "doc": "Keyboard/mouse controller for the player. Writes intent into the movement component and pulls weapon triggers. Registers its own input actions, so no project setup is needed.\nDefault keys: move = WASD / arrows, jump = Space / Z / W / Up, dash = Shift / C / K, shoot = X / J / left mouse."
1052
+ },
1053
+ {
1054
+ "name": "Projectile",
1055
+ "class": "ProjectileComponent",
1056
+ "script": "res://addons/spawn_point/components/projectile_component.gd",
1057
+ "base": "Node",
1058
+ "hosts": [
1059
+ "Area2D"
1060
+ ],
1061
+ "requires": [],
1062
+ "category": "core",
1063
+ "entity_params": [],
1064
+ "params": [
1065
+ {
1066
+ "name": "speed",
1067
+ "type": "float",
1068
+ "hint": "range",
1069
+ "hint_string": "0.0,5000.0,1.0",
1070
+ "default": 620.0,
1071
+ "doc": "Speed in px/s."
1072
+ },
1073
+ {
1074
+ "name": "lifetime",
1075
+ "type": "float",
1076
+ "hint": "range",
1077
+ "hint_string": "0.05,20.0,0.05",
1078
+ "default": 1.4,
1079
+ "doc": "Seconds before disappearing."
1080
+ },
1081
+ {
1082
+ "name": "pierce",
1083
+ "type": "int",
1084
+ "hint": "range",
1085
+ "hint_string": "0.0,99.0",
1086
+ "default": 0,
1087
+ "doc": "Number of extra targets it passes through."
1088
+ }
1089
+ ],
1090
+ "state": [
1091
+ {
1092
+ "name": "direction",
1093
+ "type": "Vector2"
1094
+ }
1095
+ ],
1096
+ "signals": [
1097
+ {
1098
+ "name": "expired",
1099
+ "args": [],
1100
+ "doc": "Emitted when the projectile disappears (wall, lifetime or last hit)."
1101
+ }
1102
+ ],
1103
+ "methods": [
1104
+ {
1105
+ "name": "expire",
1106
+ "args": [],
1107
+ "default_count": 0,
1108
+ "returns": "Nil",
1109
+ "doc": "Removes the projectile now."
1110
+ }
1111
+ ],
1112
+ "doc": "Moves its entity in a straight line; disappears on walls, after its lifetime, or after hitting [member pierce] + 1 targets. Pair with a Hitbox to deal damage."
1113
+ },
1114
+ {
1115
+ "name": "Spawner",
1116
+ "class": "SpawnerComponent",
1117
+ "script": "res://addons/spawn_point/components/spawner_component.gd",
1118
+ "base": "Node",
1119
+ "hosts": [],
1120
+ "requires": [],
1121
+ "category": "core",
1122
+ "entity_params": [
1123
+ "entity"
1124
+ ],
1125
+ "params": [
1126
+ {
1127
+ "name": "entity",
1128
+ "type": "String",
1129
+ "hint": "",
1130
+ "hint_string": "",
1131
+ "default": "",
1132
+ "doc": "Entity type to spawn."
1133
+ },
1134
+ {
1135
+ "name": "interval",
1136
+ "type": "float",
1137
+ "hint": "range",
1138
+ "hint_string": "0.05,600.0,0.05",
1139
+ "default": 3.0,
1140
+ "doc": "Seconds between spawns."
1141
+ },
1142
+ {
1143
+ "name": "start_delay",
1144
+ "type": "float",
1145
+ "hint": "range",
1146
+ "hint_string": "0.0,600.0,0.05",
1147
+ "default": 1.0,
1148
+ "doc": "Seconds before the first spawn."
1149
+ },
1150
+ {
1151
+ "name": "max_alive",
1152
+ "type": "int",
1153
+ "hint": "range",
1154
+ "hint_string": "1.0,500.0",
1155
+ "default": 5,
1156
+ "doc": "Do not spawn while this many spawned entities are alive."
1157
+ },
1158
+ {
1159
+ "name": "total",
1160
+ "type": "int",
1161
+ "hint": "range",
1162
+ "hint_string": "0.0,10000.0",
1163
+ "default": 0,
1164
+ "doc": "Total spawns before stopping (0 = unlimited)."
1165
+ },
1166
+ {
1167
+ "name": "radius",
1168
+ "type": "float",
1169
+ "hint": "range",
1170
+ "hint_string": "0.0,2000.0,1.0",
1171
+ "default": 0.0,
1172
+ "doc": "Random offset radius around the spawner (px)."
1173
+ }
1174
+ ],
1175
+ "state": [],
1176
+ "signals": [
1177
+ {
1178
+ "name": "spawned",
1179
+ "args": [
1180
+ {
1181
+ "name": "node",
1182
+ "type": "Node"
1183
+ }
1184
+ ],
1185
+ "doc": "Emitted after each spawn with the new node."
1186
+ }
1187
+ ],
1188
+ "methods": [
1189
+ {
1190
+ "name": "spawn_now",
1191
+ "args": [],
1192
+ "default_count": 0,
1193
+ "returns": "Object",
1194
+ "doc": "Spawns one entity immediately. Returns it (or null)."
1195
+ }
1196
+ ],
1197
+ "doc": "Spawns entities at its position on a timer (enemy waves, portals, hazards)."
1198
+ },
1199
+ {
1200
+ "name": "Stomp",
1201
+ "class": "StompComponent",
1202
+ "script": "res://addons/spawn_point/components/stomp_component.gd",
1203
+ "base": "Area2D",
1204
+ "hosts": [
1205
+ "CharacterBody2D"
1206
+ ],
1207
+ "requires": [
1208
+ "PlatformerMovement"
1209
+ ],
1210
+ "category": "core",
1211
+ "entity_params": [],
1212
+ "params": [
1213
+ {
1214
+ "name": "damage",
1215
+ "type": "int",
1216
+ "hint": "range",
1217
+ "hint_string": "0.0,999.0",
1218
+ "default": 1,
1219
+ "doc": "Damage dealt by a stomp."
1220
+ },
1221
+ {
1222
+ "name": "bounce_velocity",
1223
+ "type": "float",
1224
+ "hint": "range",
1225
+ "hint_string": "0.0,3000.0,1.0",
1226
+ "default": 480.0,
1227
+ "doc": "Upward speed after a stomp (px/s). Holding jump does not add to it."
1228
+ },
1229
+ {
1230
+ "name": "size_scale",
1231
+ "type": "float",
1232
+ "hint": "range",
1233
+ "hint_string": "0.1,2.0,0.05",
1234
+ "default": 1.0,
1235
+ "doc": "Stomp area size relative to the entity shape."
1236
+ }
1237
+ ],
1238
+ "state": [],
1239
+ "signals": [
1240
+ {
1241
+ "name": "stomped",
1242
+ "args": [
1243
+ {
1244
+ "name": "target",
1245
+ "type": "Node"
1246
+ }
1247
+ ],
1248
+ "doc": "Emitted after a successful stomp on [param target]."
1249
+ }
1250
+ ],
1251
+ "methods": [],
1252
+ "doc": "Platformer \"jump on their head\" attack: landing on an enemy from above damages it and bounces this entity up. Grants a moment of invincibility so the enemy's contact damage does not trigger in the same frame."
1253
+ },
1254
+ {
1255
+ "name": "TopDownMovement",
1256
+ "class": "TopDownMovementComponent",
1257
+ "script": "res://addons/spawn_point/components/top_down_movement_component.gd",
1258
+ "base": "Node",
1259
+ "hosts": [
1260
+ "CharacterBody2D"
1261
+ ],
1262
+ "requires": [],
1263
+ "category": "movement",
1264
+ "entity_params": [],
1265
+ "params": [
1266
+ {
1267
+ "name": "max_speed",
1268
+ "type": "float",
1269
+ "hint": "range",
1270
+ "hint_string": "0.0,2000.0,1.0",
1271
+ "default": 240.0,
1272
+ "doc": "Top speed (px/s)."
1273
+ },
1274
+ {
1275
+ "name": "acceleration",
1276
+ "type": "float",
1277
+ "hint": "range",
1278
+ "hint_string": "0.0,20000.0,10.0",
1279
+ "default": 2400.0,
1280
+ "doc": "Acceleration toward the input direction (px/s²)."
1281
+ },
1282
+ {
1283
+ "name": "friction",
1284
+ "type": "float",
1285
+ "hint": "range",
1286
+ "hint_string": "0.0,20000.0,10.0",
1287
+ "default": 2800.0,
1288
+ "doc": "Deceleration when there is no input (px/s²)."
1289
+ },
1290
+ {
1291
+ "name": "dash_speed",
1292
+ "type": "float",
1293
+ "hint": "range",
1294
+ "hint_string": "0.0,3000.0,1.0",
1295
+ "default": 0.0,
1296
+ "doc": "Dash speed (px/s). 0 disables dashing."
1297
+ },
1298
+ {
1299
+ "name": "dash_duration",
1300
+ "type": "float",
1301
+ "hint": "range",
1302
+ "hint_string": "0.02,1.0,0.01",
1303
+ "default": 0.12,
1304
+ "doc": "Dash duration in seconds."
1305
+ },
1306
+ {
1307
+ "name": "dash_cooldown",
1308
+ "type": "float",
1309
+ "hint": "range",
1310
+ "hint_string": "0.0,5.0,0.01",
1311
+ "default": 0.5,
1312
+ "doc": "Seconds between dashes."
1313
+ }
1314
+ ],
1315
+ "state": [
1316
+ {
1317
+ "name": "move_vector",
1318
+ "type": "Vector2"
1319
+ },
1320
+ {
1321
+ "name": "facing_dir",
1322
+ "type": "Vector2"
1323
+ },
1324
+ {
1325
+ "name": "facing",
1326
+ "type": "int"
1327
+ }
1328
+ ],
1329
+ "signals": [
1330
+ {
1331
+ "name": "dashed",
1332
+ "args": [],
1333
+ "doc": "Emitted when a dash starts."
1334
+ }
1335
+ ],
1336
+ "methods": [
1337
+ {
1338
+ "name": "request_dash",
1339
+ "args": [],
1340
+ "default_count": 0,
1341
+ "returns": "Nil",
1342
+ "doc": "Asks for a dash in the movement (or facing) direction."
1343
+ },
1344
+ {
1345
+ "name": "apply_knockback",
1346
+ "args": [
1347
+ {
1348
+ "name": "impulse",
1349
+ "type": "Vector2"
1350
+ }
1351
+ ],
1352
+ "default_count": 0,
1353
+ "returns": "Nil",
1354
+ "doc": "Pushes the entity; control is reduced briefly."
1355
+ },
1356
+ {
1357
+ "name": "is_dashing",
1358
+ "args": [],
1359
+ "default_count": 0,
1360
+ "returns": "bool",
1361
+ "doc": "True while dashing."
1362
+ }
1363
+ ],
1364
+ "doc": "Eight-direction movement seen from above, with acceleration, friction and an optional dash. Reads intent (move_vector, dash requests) from a controller such as PlayerInput or ChaseAI."
1365
+ },
1366
+ {
1367
+ "name": "TriggerZone",
1368
+ "class": "TriggerZoneComponent",
1369
+ "script": "res://addons/spawn_point/components/trigger_zone_component.gd",
1370
+ "base": "Node",
1371
+ "hosts": [
1372
+ "Area2D"
1373
+ ],
1374
+ "requires": [],
1375
+ "category": "core",
1376
+ "entity_params": [],
1377
+ "params": [
1378
+ {
1379
+ "name": "group",
1380
+ "type": "String",
1381
+ "hint": "",
1382
+ "hint_string": "",
1383
+ "default": "player",
1384
+ "doc": "Only bodies in this group trigger the zone (\"player\", an entity name, or \"\" for any)."
1385
+ },
1386
+ {
1387
+ "name": "once",
1388
+ "type": "bool",
1389
+ "hint": "",
1390
+ "hint_string": "",
1391
+ "default": true,
1392
+ "doc": "Trigger only the first time."
1393
+ }
1394
+ ],
1395
+ "state": [],
1396
+ "signals": [
1397
+ {
1398
+ "name": "triggered",
1399
+ "args": [
1400
+ {
1401
+ "name": "body",
1402
+ "type": "Node"
1403
+ }
1404
+ ],
1405
+ "doc": "Emitted when a matching body enters."
1406
+ }
1407
+ ],
1408
+ "methods": [],
1409
+ "doc": "An invisible-or-visible zone that fires [signal triggered] when an entity of [member group] enters (exit doors, checkpoints, kill zones, tutorial hints)."
1410
+ },
1411
+ {
1412
+ "name": "Weapon",
1413
+ "class": "WeaponComponent",
1414
+ "script": "res://addons/spawn_point/components/weapon_component.gd",
1415
+ "base": "Node2D",
1416
+ "hosts": [],
1417
+ "requires": [],
1418
+ "category": "core",
1419
+ "entity_params": [
1420
+ "projectile"
1421
+ ],
1422
+ "params": [
1423
+ {
1424
+ "name": "projectile",
1425
+ "type": "String",
1426
+ "hint": "",
1427
+ "hint_string": "",
1428
+ "default": "Bullet",
1429
+ "doc": "Entity type spawned as the projectile (must have a Projectile component)."
1430
+ },
1431
+ {
1432
+ "name": "fire_rate",
1433
+ "type": "float",
1434
+ "hint": "range",
1435
+ "hint_string": "0.1,60.0,0.1",
1436
+ "default": 6.0,
1437
+ "doc": "Shots per second."
1438
+ },
1439
+ {
1440
+ "name": "spread_deg",
1441
+ "type": "float",
1442
+ "hint": "range",
1443
+ "hint_string": "0.0,180.0,0.5",
1444
+ "default": 4.0,
1445
+ "doc": "Random spread in degrees (total cone width)."
1446
+ },
1447
+ {
1448
+ "name": "projectile_count",
1449
+ "type": "int",
1450
+ "hint": "range",
1451
+ "hint_string": "1.0,32.0",
1452
+ "default": 1,
1453
+ "doc": "Projectiles per shot (shotgun when > 1, spread evenly over spread_deg)."
1454
+ },
1455
+ {
1456
+ "name": "muzzle_distance",
1457
+ "type": "float",
1458
+ "hint": "range",
1459
+ "hint_string": "0.0,200.0,1.0",
1460
+ "default": 20.0,
1461
+ "doc": "Spawn distance from the entity center (px)."
1462
+ },
1463
+ {
1464
+ "name": "auto_fire",
1465
+ "type": "bool",
1466
+ "hint": "",
1467
+ "hint_string": "",
1468
+ "default": false,
1469
+ "doc": "Fire continuously without input (enemies, turrets)."
1470
+ },
1471
+ {
1472
+ "name": "recoil",
1473
+ "type": "float",
1474
+ "hint": "range",
1475
+ "hint_string": "0.0,2000.0,1.0",
1476
+ "default": 0.0,
1477
+ "doc": "Push applied to the shooter opposite to the shot (px/s). 0 = none."
1478
+ }
1479
+ ],
1480
+ "state": [
1481
+ {
1482
+ "name": "trigger_held",
1483
+ "type": "bool"
1484
+ },
1485
+ {
1486
+ "name": "aim_direction",
1487
+ "type": "Vector2"
1488
+ }
1489
+ ],
1490
+ "signals": [
1491
+ {
1492
+ "name": "fired",
1493
+ "args": [],
1494
+ "doc": "Emitted every time the weapon fires."
1495
+ }
1496
+ ],
1497
+ "methods": [
1498
+ {
1499
+ "name": "fire",
1500
+ "args": [],
1501
+ "default_count": 0,
1502
+ "returns": "Nil",
1503
+ "doc": "Fires immediately (ignores the trigger, respects nothing else)."
1504
+ }
1505
+ ],
1506
+ "doc": "Fires projectile entities. Aim comes from aim_direction (set by Aim or ChaseAI), otherwise from the movement facing. Projectiles inherit the shooter's team."
1507
+ }
1508
+ ]
1509
+ }