godot-genre-shooter-fps
Expert blueprint for First-Person Shooters (Doom, Quake, Battlefield, Overwatch) focusing on physics-based movement, acceleration/friction, camera sway, weapon bobbing, and high-precision hit registration. Use when building tight, responsive FPS combat with advanced camera mechanics. Keywords FPS, movement physics, weapon bobbing, camera sway, hitscan, ground detection, air control.
What this skill does
# Genre: Shooter (FPS/TPS)
Gunplay feel, responsive combat, and competitive balance define shooters.
## NEVER Do (Expert Anti-Patterns)
### Gunplay & Hit Registration
- NEVER use `_process()` for hit detection; strictly use `_physics_process()` to maintain frame-rate independent accuracy.
- NEVER apply recoil to the physical weapon model; strictly apply it to **Camera Rotation (kick)** and **Weapon Bloom (spread)**.
- NEVER trust the client for hit registration in multiplayer; strictly use **Server-Authoritative** validation with lag compensation.
- NEVER synchronize every bullet over the network; strictly use **Client-Side Prediction** and send only initial "Fire" events.
- NEVER use `Area3D` or `move_and_collide()` for high-speed ballistics; strictly use `PhysicsDirectSpaceState3D.intersect_ray()` for 100x better performance.
- NEVER forget to exclude the player's own RID from hitscan raycasts; otherwise, shots will collide instantly with the barrel.
- NEVER use exact floating-point equality (==) for weapon cooldowns or timers; strictly use `is_equal_approx()`.
### Performance & Polish
- NEVER use a single `AudioStreamPlayer` for gunfire; strictly use **Layered Audio** (Mechanical + Shot + Reverb Tail).
- NEVER instantiate and `free()` hundreds of projectile nodes; strictly use **Object Pooling** or the `RenderingServer`.
- NEVER use `Sprite3D` or `QuadMesh` for bullet impacts; strictly use the **Decal** node for surface-conforming texture projection.
- NEVER leave decals in the scene indefinitely; strictly implement a fade-out and cleanup cycle.
- NEVER use `Transform3D.looking_at()` for forward shooting vectors; strictly extract the direction from `-transform.basis.z`.
- NEVER multiply velocity by `delta` before `move_and_slide()`; the method internalizes the timestep automatically.
### Input & Architecture
- NEVER poll mouse motion inside `_physics_process()`; strictly use `_input()` for zero-latency camera look.
- NEVER accumulate mouse rotation directly onto a `Transform3D`; strictly store **Yaw/Pitch variables** to avoid gimbal lock.
- NEVER hardcode weapon statistics (Damage, Recoil) inside logic; strictly use **Resource-based WeaponData** for balancing.
- NEVER tightly couple damage logic to specific classes; strictly use **Duck-Typing** (`has_method("take_damage")`) for environment interactivity.
- NEVER use standard Strings for high-frequency state identifiers; strictly use `StringName` (e.g., `&"reloading"`).
- NEVER use the `!` (NOT) operator in AnimationTree expressions; strictly use `is_firing == false`.
- NEVER connect weapon signals via string-based calls; strictly use **Signal-Object syntax** (`fired.connect`).
---
## ๐ Expert Components (scripts/)
### Original Expert Patterns
- [advanced_weapon_controller.gd](scripts/advanced_weapon_controller.gd) - Professional-grade weapon system with deterministic recoil, bloom, and dual hitscan/projectile modes.
### Modular Components
- [fps_camera_look.gd](scripts/fps_camera_look.gd) - Asynchronous mouse look for zero-latency aiming using raw input.
- [hitscan_weapon_query.gd](scripts/hitscan_weapon_query.gd) - Nodeless physics raycast pattern for instant hit registration.
- [fps_movement_logic.gd](scripts/fps_movement_logic.gd) - Physics-based movement with acceleration, friction, and gravity scaling.
- [weapon_bobbing_system.gd](scripts/weapon_bobbing_system.gd) - Procedural bobbing and sway using sine-wave oscillation.
- [bullet_decal_spawner.gd](scripts/bullet_decal_spawner.gd) - Dynamic surface decal projection for impact effects.
- [weapon_spread_calc.gd](scripts/weapon_spread_calc.gd) - Gaussian/Normal distribution logic for bullet clustering.
- [server_projectile_instance.gd](scripts/server_projectile_instance.gd) - High-volume visual bullets using RenderingServer RIDs.
- [weapon_state_machine.gd](scripts/weapon_state_machine.gd) - Optimized state transitions for fire, reload, and idle.
- [player_anim_bridge.gd](scripts/player_anim_bridge.gd) - Local velocity bridge for syncing movement with AnimationTree.
- [frame_perfect_input.gd](scripts/frame_perfect_input.gd) - Buffered semi-automatic input handling to prevent dropped shots.
---
## Core Loop
`Engage โ Aim โ Fire โ Kill Confirm โ Acquire Next`
---
## Weapon System Architecture
```gdscript
class_name Weapon
extends Node3D
@export_group("Stats")
@export var damage: int = 20
@export var fire_rate: float = 0.1 # Seconds between shots
@export var magazine_size: int = 30
@export var reload_time: float = 2.0
@export var range: float = 100.0
@export_group("Recoil")
@export var base_recoil: Vector2 = Vector2(0.5, 2.0) # X, Y degrees
@export var recoil_recovery_speed: float = 5.0
@export var max_spread: float = 5.0
@export_group("Type")
@export var is_hitscan: bool = true
@export var projectile_scene: PackedScene
var current_ammo: int
var can_fire: bool = true
var current_recoil: Vector2 = Vector2.ZERO
var current_spread: float = 0.0
signal fired
signal reloaded
signal ammo_changed(current: int, max: int)
```
---
## Hitscan vs Projectile
### Hitscan (Instant Hit)
```gdscript
func fire_hitscan() -> void:
if not can_fire or current_ammo <= 0:
return
current_ammo -= 1
ammo_changed.emit(current_ammo, magazine_size)
var camera := get_viewport().get_camera_3d()
var ray_origin := camera.global_position
var ray_direction := -camera.global_basis.z
# Apply spread
ray_direction = apply_spread(ray_direction)
var space := get_world_3d().direct_space_state
var query := PhysicsRayQueryParameters3D.create(
ray_origin,
ray_origin + ray_direction * range
)
query.collision_mask = collision_mask
var result := space.intersect_ray(query)
if result:
var hit_point: Vector3 = result.position
var hit_normal: Vector3 = result.normal
var hit_object: Object = result.collider
spawn_impact_effect(hit_point, hit_normal)
if hit_object.has_method("take_damage"):
var hit_zone := determine_hit_zone(result)
var final_damage := calculate_damage(damage, hit_zone)
hit_object.take_damage(final_damage, hit_zone)
apply_recoil()
start_fire_cooldown()
fired.emit()
func determine_hit_zone(result: Dictionary) -> String:
# Use collision shape name or bone detection for hitboxes
if "headshot" in result.collider.name.to_lower():
return "head"
elif "chest" in result.collider.name.to_lower():
return "chest"
return "body"
func calculate_damage(base: int, zone: String) -> int:
match zone:
"head": return int(base * 2.5)
"chest": return int(base * 1.0)
_: return int(base * 0.8)
```
### Projectile (Physical Bullet)
```gdscript
class_name Projectile
extends CharacterBody3D
@export var speed := 100.0
@export var damage := 20
@export var gravity_affected := true
@export var lifetime := 5.0
var direction: Vector3
var shooter: Node3D
func _ready() -> void:
await get_tree().create_timer(lifetime).timeout
queue_free()
func _physics_process(delta: float) -> void:
if gravity_affected:
velocity.y -= 9.8 * delta
velocity = direction * speed
var collision := move_and_collide(velocity * delta)
if collision:
var collider := collision.get_collider()
if collider != shooter and collider.has_method("take_damage"):
collider.take_damage(damage)
spawn_impact(collision.get_position(), collision.get_normal())
queue_free()
```
---
## Recoil System
Three types of recoil working together:
```gdscript
class_name RecoilSystem
extends Node
var visual_recoil: Vector2 = Vector2.ZERO # Camera kick
var pattern_offset: Vector2 = Vector2.ZERO # Deterministic pattern
var spread_bloom: float = 0.0 # Accuracy loss
@export var recoil_pattern: Array[Vector2] # Predefined spray pattern
var pattern_index: int = 0
funRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.