MultiplayerFighter
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5.5 KiB

Weapon System Documentation

Overview

The weapon system is a modular, multiplayer-friendly system that allows players to:

  • Pick up weapons from the world
  • Equip weapons to their right hand (WeaponPoint bone attachment)
  • Drop equipped weapons
  • Attack with weapon-specific stats (damage, range, cooldown)

Architecture

Core Components

  1. WeaponData (level/scripts/weapon_data.gd) - Resource

    • Stores weapon stats: name, damage, attack_range, attack_cooldown
    • References a mesh scene for visuals
    • Reusable across multiple weapon instances
  2. BaseWeapon (level/scripts/base_weapon.gd) - Node3D

    • Equipped weapon attached to player's hand
    • Handles attack logic and damage application
    • Networked properly for multiplayer
  3. WorldWeapon (level/scripts/world_weapon.gd) - RigidBody3D

    • Physics-based pickup object in the world
    • Can be picked up by players
    • Automatically creates collision and pickup area

Creating New Weapons

Step 1: Create a Mesh Scene

Create a scene with your weapon's 3D model:

[Node3D] - WeaponMesh
  └─ [MeshInstance3D] - Your mesh here

Example: level/scenes/weapons/sword_mesh.tscn

Step 2: Create a WeaponData Resource

Create a .tres file in level/resources/:

[gd_resource type="Resource" script_class="WeaponData" load_steps=3 format=3]

[ext_resource type="Script" path="res://level/scripts/weapon_data.gd" id="1"]
[ext_resource type="PackedScene" path="res://level/scenes/weapons/your_mesh.tscn" id="2"]

[resource]
script = ExtResource("1")
weapon_name = "Your Weapon Name"
description = "Weapon description"
damage = 15.0
attack_range = 3.5
attack_cooldown = 0.6
attack_animation = "Attack1"
mesh_scene = ExtResource("2")
pickup_radius = 1.5
weight = 2.0

Step 3: Spawn Weapons in the Level

There are two ways to add weapons to your level:

  1. Open your level scene (e.g., level/scenes/level.tscn)
  2. Drag a WorldWeapon scene into WeaponsContainer:
    • From FileSystem panel: level/scenes/weapons/world_weapon_sword.tscn
    • Or: level/scenes/weapons/world_weapon_shield.tscn
    • Drop it as a child of WeaponsContainer
  3. Position the weapon in 3D space where you want it to spawn
  4. Save the scene

How it works:

  • The server automatically detects manually placed WorldWeapon nodes on startup
  • Each weapon is assigned a unique ID and tracked for multiplayer
  • Clients automatically receive synced copies via RPC
  • No code changes needed - just drag and drop!

Option B: Dynamic Spawning

Spawn weapons via code in level.gd:

# In _spawn_initial_weapons() or wherever you need
_weapon_spawn_counter += 1
rpc("spawn_world_weapon",
    "res://level/resources/weapon_sword.tres",
    Vector3(5, 1, 0),  # spawn position
    Vector3.ZERO,      # initial velocity
    _weapon_spawn_counter
)

This is useful for:

  • Spawning weapons at runtime
  • Procedural weapon placement
  • Loot drops from enemies

Testing

In Godot Editor

  1. Open level/scenes/level.tscn
  2. Add a manually placed weapon (see Option A above) or modify _spawn_initial_weapons() in level.gd
  3. Run the game (F5)
  4. Walk near the weapon and press E to pick it up

Controls

  • E - Pick up weapon (when near one) or drop equipped weapon
  • Left Mouse - Attack with equipped weapon (or unarmed if none)

Multiplayer Testing

  1. Run the game and click "Host"
  2. Run another instance and click "Join"
  3. Both players can:
    • Pick up weapons
    • Attack each other with weapons
    • Drop weapons (creates a WorldWeapon others can pick up)

How It Works

Pickup Flow

  1. WorldWeapon creates an Area3D with pickup radius
  2. Player has a WeaponPickupArea that detects nearby WorldWeapons
  3. When player presses "E" near a weapon:
    • Client calls try_pickup() via RPC to server
    • Server validates distance and availability
    • Server tells player to equip_weapon_from_world()
    • Server removes the WorldWeapon from scene
    • All clients see the weapon disappear and equipped on player

Attack Flow

  1. Player presses attack button
  2. Player checks if equipped_weapon exists
  3. If yes, calls equipped_weapon.perform_attack()
  4. Weapon checks cooldown and attack range
  5. Weapon finds targets using physics query
  6. Weapon sends damage request to server
  7. Server validates and applies damage via BaseUnit system

Drop Flow

  1. Player presses "E" while holding a weapon
  2. Player calls drop_weapon() RPC
  3. Server spawns a WorldWeapon at player's position
  4. All clients see weapon unequip and appear in world
  5. Weapon becomes a physics object that can be picked up

Physics Layers

  • Layer 1 (player) - Player collisions
  • Layer 2 (world) - Environment collisions
  • Layer 3 (weapon) - Weapon pickup objects

WorldWeapons:

  • collision_layer = 4 (layer 3)
  • collision_mask = 2 (collides with world)

Player WeaponPickupArea:

  • collision_mask = 4 (detects layer 3)

Example Weapons

Iron Sword

  • Damage: 15
  • Range: 3.5m
  • Cooldown: 0.6s
  • Resource: level/resources/weapon_sword.tres

Wooden Shield

  • Damage: 8
  • Range: 2.5m
  • Cooldown: 0.8s
  • Resource: level/resources/weapon_shield.tres

Notes

  • All weapon spawning/pickup is server-authoritative
  • Weapon stats are synced via WeaponData resource
  • Meshes are instantiated locally on each client
  • The system supports any number of weapon types
  • You can extend BaseWeapon for special weapon behaviors (e.g., ranged weapons, magic weapons)