summer-engine 1.5.0 → 2.2.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.
- package/{marketplace.json → .claude-plugin/marketplace.json} +3 -3
- package/.claude-plugin/plugin.json +52 -11
- package/.codex-plugin/plugin.json +69 -8
- package/.cursor-plugin/plugin.json +53 -12
- package/.factory-plugin/plugin.json +20 -0
- package/.opencode/INSTALL.md +75 -0
- package/.opencode/plugins/summer.js +9 -6
- package/AGENTS.md +51 -0
- package/CHANGELOG.md +31 -1
- package/CLAUDE.md +5 -0
- package/GEMINI.md +56 -0
- package/README.md +409 -80
- package/_persona/summer/SKILL.md +113 -0
- package/dist/bin/summer.js +0 -0
- package/dist/commands/assets.d.ts +2 -0
- package/dist/commands/assets.js +189 -0
- package/dist/commands/create.js +55 -17
- package/dist/commands/debug.d.ts +2 -0
- package/dist/commands/debug.js +127 -0
- package/dist/commands/install.js +2 -2
- package/dist/commands/list.js +24 -5
- package/dist/commands/project.d.ts +2 -0
- package/dist/commands/project.js +170 -0
- package/dist/commands/scene.d.ts +2 -0
- package/dist/commands/scene.js +290 -0
- package/dist/lib/banner.js +2 -2
- package/dist/lib/log-filters.d.ts +53 -0
- package/dist/lib/log-filters.js +130 -0
- package/dist/lib/plugin-manifests.test.d.ts +1 -0
- package/dist/lib/plugin-manifests.test.js +134 -0
- package/dist/lib/remote-templates.d.ts +25 -0
- package/dist/lib/remote-templates.js +86 -0
- package/dist/lib/skills-registry.d.ts +283 -3
- package/dist/lib/skills-registry.js +522 -2
- package/dist/lib/telemetry.d.ts +13 -0
- package/dist/lib/telemetry.js +63 -0
- package/dist/lib/with-engine.d.ts +14 -0
- package/dist/lib/with-engine.js +109 -0
- package/dist/mcp/tools/asset-tools.js +12 -13
- package/dist/mcp/tools/debug-tools.js +32 -9
- package/dist/mcp/tools/generate-tools.js +101 -0
- package/dist/mcp/tools/with-engine.js +4 -0
- package/gemini-extension.json +2 -2
- package/hooks/pre-commit-doctor.sh +0 -0
- package/hooks/run-hook.cmd +0 -0
- package/hooks/session-start.sh +0 -0
- package/package.json +11 -5
- package/skills/2d-assets/character-portrait/SKILL.md +196 -0
- package/skills/2d-assets/concept-art/SKILL.md +152 -0
- package/skills/2d-assets/pixel-art/SKILL.md +180 -0
- package/skills/2d-assets/skybox-panorama/SKILL.md +207 -0
- package/skills/2d-assets/sprite-sheet/SKILL.md +239 -0
- package/skills/2d-assets/tileable-texture/SKILL.md +205 -0
- package/skills/2d-assets/ui-graphics/SKILL.md +210 -0
- package/skills/3d-assets/character-model/SKILL.md +225 -0
- package/skills/3d-assets/environment-kit/SKILL.md +164 -0
- package/skills/3d-assets/organic-model/SKILL.md +192 -0
- package/skills/3d-assets/prop-model/SKILL.md +133 -0
- package/skills/3d-assets/vehicle-model/SKILL.md +202 -0
- package/skills/README.md +1 -1
- package/skills/_meta/skill-create/SKILL.md +1 -1
- package/skills/_meta/skill-improve/SKILL.md +1 -1
- package/skills/_meta/skill-test/SKILL.md +1 -1
- package/skills/_meta/using-summer/SKILL.md +130 -0
- package/skills/ai-and-npcs/design-npc/SKILL.md +3 -1
- package/skills/animation/animation-tree/SKILL.md +260 -0
- package/skills/animation/facial-and-lipsync/SKILL.md +282 -0
- package/skills/animation/generate-motion/SKILL.md +129 -0
- package/skills/animation/procedural-animation/SKILL.md +234 -0
- package/skills/animation/retarget/SKILL.md +172 -0
- package/skills/asset-pipeline/asset-strategy/SKILL.md +102 -212
- package/skills/audio/adaptive-music/SKILL.md +326 -0
- package/skills/audio/ambient-bed/SKILL.md +278 -0
- package/skills/audio/music-track/SKILL.md +268 -0
- package/skills/audio/sound-effect/SKILL.md +237 -0
- package/skills/audio/voice-line/SKILL.md +253 -0
- package/skills/catalog.yaml +266 -5
- package/skills/character-controllers/fps-controller/SKILL.md +1 -1
- package/skills/debugging/debug/SKILL.md +102 -82
- package/skills/rendering-and-lighting/3d-lighting/SKILL.md +1 -1
- package/skills/scene-and-project/browse-templates/SKILL.md +105 -0
- package/skills/scene-and-project/make-game/SKILL.md +159 -346
- package/skills/scene-and-project/new-project/SKILL.md +106 -0
- package/skills/scene-and-project/scene-composition/SKILL.md +1 -1
- package/skills/scripting-patterns/gdscript-patterns/SKILL.md +1 -1
- package/skills/ui-and-ux/ui-basics/SKILL.md +1 -1
- package/skills/video/animated-loop/SKILL.md +200 -0
- package/skills/video/cinematic-cutscene/SKILL.md +204 -0
- package/skills/video/trailer-shot/SKILL.md +203 -0
- package/skills/visual-effects/_building-blocks/additive-billboard-particles.md +28 -0
- package/skills/visual-effects/_building-blocks/noise-3d-fbm.gdshaderinc +45 -0
- package/skills/visual-effects/_building-blocks/trauma-shake-snippet.md +51 -0
- package/skills/visual-effects/{vfx → game-feel}/SKILL.md +1 -1
- package/skills/visual-effects/recipes/dissolve/SKILL.md +349 -0
- package/skills/visual-effects/recipes/fire/SKILL.md +387 -0
- package/skills/visual-effects/recipes/hit-spark/SKILL.md +330 -0
- package/skills/visual-effects/recipes/lightning/SKILL.md +372 -0
- package/skills/visual-effects/recipes/magic-glow/SKILL.md +377 -0
- package/skills/visual-effects/recipes/muzzle-flash/SKILL.md +326 -0
- package/skills/visual-effects/recipes/smoke/SKILL.md +381 -0
- package/skills/visual-effects/recipes/water-ripple/SKILL.md +340 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: muzzle-flash
|
|
3
|
+
description: Use when authoring a muzzle-flash visual effect — a one-shot ~80 ms burst at a gun barrel built with a particle one-shot OR a flashing quad with a star-burst shader. Trigger on "muzzle flash", "gun fire", "weapon flash", "barrel flash", "shoot a gun", "spell-cast burst at hand".
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: [Cursor, Claude Code, Windsurf, Codex]
|
|
6
|
+
category: visual-effects
|
|
7
|
+
user-invocable: true
|
|
8
|
+
allowed-tools: Read Write Edit summer_add_node summer_set_prop summer_set_resource_property summer_inspect_node summer_save_scene
|
|
9
|
+
paths: ["**/*.tscn", "**/*.gd", "**/*.gdshader", "addons/vfx/**"]
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# muzzle-flash — One-Shot Star-Burst Flare
|
|
13
|
+
|
|
14
|
+
A muzzle flash is on screen for 60–100 ms. Long enough to read, too short to animate. The recipe: a single billboarded quad with a star-burst gradient shader, fired by `restart()` on a weapon's `fired` signal, plus an `OmniLight3D` snapping on for 60 ms to light the room. Optional: a tiny GPUParticles3D one-shot for sparks. Doom Eternal does this. Half-Life 2 did this. Every shooter does this.
|
|
15
|
+
|
|
16
|
+
## When to use
|
|
17
|
+
|
|
18
|
+
- "Add a muzzle flash to the rifle / pistol / shotgun."
|
|
19
|
+
- "When I fire, the gun should flash."
|
|
20
|
+
- "Spell-cast burst at the wizard's palm." (one-shot at hand position)
|
|
21
|
+
- "Cannon fires, big flash at the barrel."
|
|
22
|
+
- The user just hooked up a weapon and the firing reads as silent / weightless.
|
|
23
|
+
|
|
24
|
+
## When NOT to use
|
|
25
|
+
|
|
26
|
+
- The user wants a *continuous* flame (flamethrower) — use `fire`, not muzzle-flash.
|
|
27
|
+
- The user wants the impact spark on the wall the bullet hit — that's `hit-spark`.
|
|
28
|
+
- The user wants a tracer line from barrel to target — use a `Line3D`/`ImmediateMesh` recipe, not this. (Or pair this with `lightning` for an energy weapon.)
|
|
29
|
+
- The user wants a slow-glowing spell charge-up — use `magic-glow` for the buildup, then this for the release frame.
|
|
30
|
+
|
|
31
|
+
## Recipe
|
|
32
|
+
|
|
33
|
+
### 1. Files to create
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
addons/vfx/muzzle-flash/muzzle_flash.gdshader
|
|
37
|
+
addons/vfx/muzzle-flash/muzzle_flash.gd
|
|
38
|
+
addons/vfx/muzzle-flash/muzzle_flash.tscn (reusable scene)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 2. Shader code
|
|
42
|
+
|
|
43
|
+
`addons/vfx/muzzle-flash/muzzle_flash.gdshader`:
|
|
44
|
+
|
|
45
|
+
```glsl
|
|
46
|
+
shader_type spatial;
|
|
47
|
+
render_mode unshaded, blend_add, depth_draw_never, cull_disabled, shadows_disabled;
|
|
48
|
+
|
|
49
|
+
uniform vec4 flash_color : source_color = vec4(1.0, 0.85, 0.45, 1.0);
|
|
50
|
+
uniform vec4 core_color : source_color = vec4(1.0, 1.0, 0.95, 1.0);
|
|
51
|
+
uniform float intensity : hint_range(0.0, 1.0) = 1.0; // driven by the controller (1 → 0)
|
|
52
|
+
uniform float emission_boost : hint_range(0.0, 12.0) = 6.0;
|
|
53
|
+
uniform int ray_count : hint_range(2, 8) = 4;
|
|
54
|
+
uniform float ray_sharpness : hint_range(0.5, 32.0) = 8.0;
|
|
55
|
+
uniform float random_seed : hint_range(0.0, 6.2831) = 0.0; // rotates the star per shot
|
|
56
|
+
|
|
57
|
+
void vertex() {
|
|
58
|
+
MODELVIEW_MATRIX = VIEW_MATRIX * mat4(
|
|
59
|
+
INV_VIEW_MATRIX[0],
|
|
60
|
+
INV_VIEW_MATRIX[1],
|
|
61
|
+
INV_VIEW_MATRIX[2],
|
|
62
|
+
MODEL_MATRIX[3]
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
void fragment() {
|
|
67
|
+
vec2 c = UV - vec2(0.5);
|
|
68
|
+
float r = length(c) * 2.0;
|
|
69
|
+
float ang = atan(c.y, c.x) + random_seed;
|
|
70
|
+
|
|
71
|
+
// Soft radial core: hottest at center, falls off to zero at the edge.
|
|
72
|
+
float core = smoothstep(1.0, 0.0, r);
|
|
73
|
+
core = pow(core, 2.0);
|
|
74
|
+
|
|
75
|
+
// Star-burst rays: cosine of angle * ray_count gives N spokes.
|
|
76
|
+
float rays = pow(max(cos(ang * float(ray_count)), 0.0), ray_sharpness);
|
|
77
|
+
rays *= smoothstep(1.05, 0.05, r); // rays fade to edge
|
|
78
|
+
|
|
79
|
+
float mask = clamp(core + rays * 0.85, 0.0, 1.0);
|
|
80
|
+
|
|
81
|
+
// Mix core color (white-hot) into flash color at the very center.
|
|
82
|
+
vec3 col = mix(flash_color.rgb, core_color.rgb, pow(core, 4.0));
|
|
83
|
+
|
|
84
|
+
ALBEDO = col;
|
|
85
|
+
EMISSION = col * emission_boost * intensity;
|
|
86
|
+
ALPHA = mask * intensity;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 3. GDScript controller
|
|
91
|
+
|
|
92
|
+
`addons/vfx/muzzle-flash/muzzle_flash.gd`:
|
|
93
|
+
|
|
94
|
+
```gdscript
|
|
95
|
+
@tool
|
|
96
|
+
class_name MuzzleFlash
|
|
97
|
+
extends Node3D
|
|
98
|
+
|
|
99
|
+
## Spawn one of these as a child of the gun's barrel tip and call `fire()` on each shot.
|
|
100
|
+
|
|
101
|
+
@export var flash_color: Color = Color(1.0, 0.85, 0.45)
|
|
102
|
+
@export_range(0.02, 0.30) var flash_duration: float = 0.08 ## seconds visible
|
|
103
|
+
@export_range(0.10, 4.0) var flash_size: float = 0.6 ## meters across
|
|
104
|
+
@export_range(0.0, 12.0) var emission_boost: float = 6.0
|
|
105
|
+
@export_range(0.0, 8.0) var light_energy: float = 4.0
|
|
106
|
+
@export_range(0.5, 12.0) var light_range: float = 6.0
|
|
107
|
+
@export var spawn_sparks: bool = true
|
|
108
|
+
|
|
109
|
+
var _quad: MeshInstance3D
|
|
110
|
+
var _mat: ShaderMaterial
|
|
111
|
+
var _light: OmniLight3D
|
|
112
|
+
var _sparks: GPUParticles3D
|
|
113
|
+
var _t: float = 0.0
|
|
114
|
+
var _firing: bool = false
|
|
115
|
+
|
|
116
|
+
func _ready() -> void:
|
|
117
|
+
_quad = MeshInstance3D.new()
|
|
118
|
+
var mesh := QuadMesh.new()
|
|
119
|
+
mesh.size = Vector2(flash_size, flash_size)
|
|
120
|
+
_quad.mesh = mesh
|
|
121
|
+
_mat = ShaderMaterial.new()
|
|
122
|
+
_mat.shader = preload("res://addons/vfx/muzzle-flash/muzzle_flash.gdshader")
|
|
123
|
+
_mat.set_shader_parameter("flash_color", flash_color)
|
|
124
|
+
_mat.set_shader_parameter("emission_boost", emission_boost)
|
|
125
|
+
_mat.set_shader_parameter("intensity", 0.0)
|
|
126
|
+
_quad.material_override = _mat
|
|
127
|
+
_quad.visible = false
|
|
128
|
+
add_child(_quad)
|
|
129
|
+
|
|
130
|
+
_light = OmniLight3D.new()
|
|
131
|
+
_light.light_color = flash_color
|
|
132
|
+
_light.omni_range = light_range
|
|
133
|
+
_light.light_energy = 0.0
|
|
134
|
+
_light.shadow_enabled = false
|
|
135
|
+
add_child(_light)
|
|
136
|
+
|
|
137
|
+
if spawn_sparks:
|
|
138
|
+
_sparks = preload("res://addons/vfx/hit-spark/hit_spark.tscn").instantiate() if ResourceLoader.exists("res://addons/vfx/hit-spark/hit_spark.tscn") else null
|
|
139
|
+
if _sparks:
|
|
140
|
+
_sparks.one_shot = true
|
|
141
|
+
_sparks.emitting = false
|
|
142
|
+
add_child(_sparks)
|
|
143
|
+
|
|
144
|
+
set_process(false)
|
|
145
|
+
|
|
146
|
+
func fire() -> void:
|
|
147
|
+
_t = flash_duration
|
|
148
|
+
_firing = true
|
|
149
|
+
_quad.visible = true
|
|
150
|
+
_mat.set_shader_parameter("random_seed", randf() * TAU)
|
|
151
|
+
var random_scale := flash_size * randf_range(0.85, 1.15)
|
|
152
|
+
(_quad.mesh as QuadMesh).size = Vector2(random_scale, random_scale)
|
|
153
|
+
if _sparks:
|
|
154
|
+
_sparks.restart()
|
|
155
|
+
_sparks.emitting = true
|
|
156
|
+
set_process(true)
|
|
157
|
+
|
|
158
|
+
func _process(delta: float) -> void:
|
|
159
|
+
if not _firing:
|
|
160
|
+
return
|
|
161
|
+
_t -= delta
|
|
162
|
+
var k: float = clamp(_t / flash_duration, 0.0, 1.0)
|
|
163
|
+
# Snappy decay: spike, then exponential drop.
|
|
164
|
+
var intensity: float = pow(k, 0.5)
|
|
165
|
+
_mat.set_shader_parameter("intensity", intensity)
|
|
166
|
+
_light.light_energy = light_energy * intensity
|
|
167
|
+
if _t <= 0.0:
|
|
168
|
+
_firing = false
|
|
169
|
+
_quad.visible = false
|
|
170
|
+
_light.light_energy = 0.0
|
|
171
|
+
set_process(false)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### 4. Node tree
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
Node3D ("MuzzleFlash") [script: muzzle_flash.gd]
|
|
178
|
+
├── MeshInstance3D (created at runtime — the visual quad)
|
|
179
|
+
├── OmniLight3D (created at runtime — the room flash)
|
|
180
|
+
└── GPUParticles3D ("Sparks", optional — instantiated from hit-spark.tscn)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### 5. Wire it in (MCP calls)
|
|
184
|
+
|
|
185
|
+
Place the node at the **barrel tip** of the weapon. If your gun model has a `BarrelTip` Marker3D, parent there directly.
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
summer_add_node(parent="./Player/Weapon/BarrelTip", type="Node3D", name="MuzzleFlash")
|
|
189
|
+
summer_set_prop(path="./Player/Weapon/BarrelTip/MuzzleFlash", property="script", value="res://addons/vfx/muzzle-flash/muzzle_flash.gd")
|
|
190
|
+
summer_set_prop(path="./Player/Weapon/BarrelTip/MuzzleFlash", property="flash_size", value=0.6)
|
|
191
|
+
summer_set_prop(path="./Player/Weapon/BarrelTip/MuzzleFlash", property="flash_duration", value=0.08)
|
|
192
|
+
summer_set_prop(path="./Player/Weapon/BarrelTip/MuzzleFlash", property="light_energy", value=4.0)
|
|
193
|
+
summer_save_scene
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Then in your weapon script, on `fire()`:
|
|
197
|
+
|
|
198
|
+
```gdscript
|
|
199
|
+
$BarrelTip/MuzzleFlash.fire()
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Or connect a signal:
|
|
203
|
+
|
|
204
|
+
```gdscript
|
|
205
|
+
weapon.fired.connect($BarrelTip/MuzzleFlash.fire)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### 6. Parameters to tune
|
|
209
|
+
|
|
210
|
+
| Parameter | Range | Effect |
|
|
211
|
+
|---|---|---|
|
|
212
|
+
| `flash_duration` | 0.04–0.20 s | how long the flash is visible; >0.15 looks like a flamethrower |
|
|
213
|
+
| `flash_size` | 0.10–4.0 m | quad size; matches the weapon's caliber |
|
|
214
|
+
| `emission_boost` | 0.0–12.0 | bloom strength; higher needs Bloom in WorldEnvironment |
|
|
215
|
+
| `light_energy` | 0.0–8.0 | how much the muzzle lights the surroundings |
|
|
216
|
+
| `light_range` | 0.5–12.0 m | how far the flash light reaches |
|
|
217
|
+
| `ray_count` (shader) | 2–8 | spokes in the star-burst; pistol = 4, shotgun = 6 |
|
|
218
|
+
| `ray_sharpness` (shader) | 0.5–32.0 | tightness of each ray |
|
|
219
|
+
|
|
220
|
+
## Cookbook — named variants
|
|
221
|
+
|
|
222
|
+
### pistol-flash (default)
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
flash_duration = 0.06
|
|
226
|
+
flash_size = 0.35
|
|
227
|
+
emission_boost = 6.0
|
|
228
|
+
light_energy = 3.0
|
|
229
|
+
light_range = 4.0
|
|
230
|
+
ray_count = 4
|
|
231
|
+
ray_sharpness = 10.0
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### rifle-flash
|
|
235
|
+
|
|
236
|
+
Slightly longer flash, narrower star.
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
flash_duration = 0.08
|
|
240
|
+
flash_size = 0.50
|
|
241
|
+
emission_boost = 7.0
|
|
242
|
+
light_energy = 4.0
|
|
243
|
+
light_range = 6.0
|
|
244
|
+
ray_count = 4
|
|
245
|
+
ray_sharpness = 14.0
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### shotgun-blast
|
|
249
|
+
|
|
250
|
+
Wide, short, lots of spokes.
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
flash_duration = 0.09
|
|
254
|
+
flash_size = 0.95
|
|
255
|
+
emission_boost = 9.0
|
|
256
|
+
light_energy = 6.0
|
|
257
|
+
light_range = 9.0
|
|
258
|
+
ray_count = 6
|
|
259
|
+
ray_sharpness = 5.0
|
|
260
|
+
spawn_sparks = true
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### plasma-cast (sci-fi / spell)
|
|
264
|
+
|
|
265
|
+
Cool color, slightly longer hold, no random rotation.
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
flash_color = Color(0.45, 0.85, 1.0)
|
|
269
|
+
flash_duration = 0.12
|
|
270
|
+
flash_size = 0.70
|
|
271
|
+
emission_boost = 10.0
|
|
272
|
+
light_energy = 5.0
|
|
273
|
+
light_range = 7.0
|
|
274
|
+
ray_count = 8
|
|
275
|
+
ray_sharpness = 18.0
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Anti-patterns
|
|
279
|
+
|
|
280
|
+
- **Looping the flash.** It's a one-shot. `set_process(false)` after the timer; do NOT call `fire()` from `_process`.
|
|
281
|
+
- **Forgetting to randomize `random_seed` per shot.** Otherwise every flash is the identical orientation and the player notices it as a rendered sprite, not a flash.
|
|
282
|
+
- **Using `blend_mix` instead of `blend_add`.** A flash mixes light, it doesn't occlude. Always `blend_add`.
|
|
283
|
+
- **OmniLight3D with shadows enabled.** A 60 ms shadow pass costs more than the flash itself. `shadow_enabled = false`.
|
|
284
|
+
- **Flash duration > 150 ms.** Reads as a flamethrower or a stuck animation. Stay under 100 ms unless intentional.
|
|
285
|
+
- **Spawning a new MuzzleFlash each shot and freeing it.** Rapid-fire weapons leak. Reuse one anchored to the barrel and call `fire()`.
|
|
286
|
+
- **Generating an animated flash sprite.** That's the misroute this skill exists to prevent. The procedural shader rotates per shot for free, and you can recolor without regenerating.
|
|
287
|
+
|
|
288
|
+
## Performance notes
|
|
289
|
+
|
|
290
|
+
- One quad + one light + ~8 sparks = under 0.02 ms. Safe at any rate of fire.
|
|
291
|
+
- The `OmniLight3D` snapping on/off per shot will trigger a shadow re-bake on lights with `shadow_enabled = true` — keep it off, always.
|
|
292
|
+
- For full-auto weapons (10+ shots/sec), consider raising `flash_duration` to 0.10 and dropping `intensity` to 0.6 so consecutive flashes blend instead of strobe.
|
|
293
|
+
|
|
294
|
+
## Edge cases
|
|
295
|
+
|
|
296
|
+
- **First-person view, gun fills half the screen.** Your `flash_size` of 0.35 will look tiny because the camera is 0.3 m from the barrel. Bump to 0.6+ for FPS, scale down for third-person.
|
|
297
|
+
- **Weapon visible in a mirror / scope.** The additive quad will appear in reflections only if the reflection probe captures it; for scope ADS, render the flash into the scope's separate viewport.
|
|
298
|
+
- **Underwater shooting.** Tint the flash blue-green via `flash_color`, drop `light_range` to 30%.
|
|
299
|
+
- **Silenced weapon.** `flash_size = 0.10`, `light_energy = 0.5`, `flash_duration = 0.04`. Just a wink at the barrel.
|
|
300
|
+
- **Suppressed flash with a tracer.** Pair this with a `Line3D` tracer from barrel to hit point, fired in the same call.
|
|
301
|
+
|
|
302
|
+
## Fallback (no MCP)
|
|
303
|
+
|
|
304
|
+
VFX is code, no MCP required:
|
|
305
|
+
|
|
306
|
+
1. Create `addons/vfx/muzzle-flash/` and write the three files above.
|
|
307
|
+
2. In Godot, add a `Node3D` child to your weapon's barrel tip Marker3D.
|
|
308
|
+
3. Attach `muzzle_flash.gd` as the script. The runtime builds the quad + light.
|
|
309
|
+
4. In your weapon's fire code: `$BarrelTip/MuzzleFlash.fire()`.
|
|
310
|
+
|
|
311
|
+
## Handoff
|
|
312
|
+
|
|
313
|
+
After firing this recipe, suggest:
|
|
314
|
+
|
|
315
|
+
- `summer:visual-effects/recipes/hit-spark` — pair on the bullet impact end.
|
|
316
|
+
- `summer:visual-effects/recipes/smoke` — for a small puff at the barrel after the flash for high-caliber weapons.
|
|
317
|
+
- `summer:visual-effects/game-feel` — recoil camera kick + screen shake (`CameraShake.add_trauma(0.15)`) on every shot makes the flash feel 5× more powerful.
|
|
318
|
+
- `summer:audio/sound-effect` — generate `9mm pistol shot, sharp crack, indoor, short tail, 400ms` and play in the same `fire()`.
|
|
319
|
+
|
|
320
|
+
## See also
|
|
321
|
+
|
|
322
|
+
- `_building-blocks/additive-billboard-particles.md` — canonical additive material reference
|
|
323
|
+
- `_building-blocks/trauma-shake-snippet.md` — `CameraShake.add_trauma()` for the recoil punch
|
|
324
|
+
- `summer:visual-effects/recipes/hit-spark` — companion impact effect
|
|
325
|
+
- `summer:visual-effects/recipes/lightning` — for energy weapons (replace the flash with a beam)
|
|
326
|
+
- `summer:visual-effects/game-feel` — recoil + hit-stop wiring
|