Manually spawn weapons fixed
Pop the world weapon scene into weaponcontainer
This commit is contained in:
+38
-11
@@ -62,27 +62,54 @@ pickup_radius = 1.5
|
||||
weight = 2.0
|
||||
```
|
||||
|
||||
### Step 3: Create a WorldWeapon Scene (Optional)
|
||||
### Step 3: Spawn Weapons in the Level
|
||||
|
||||
If you want to place weapons in the level:
|
||||
There are two ways to add weapons to your level:
|
||||
|
||||
```
|
||||
[RigidBody3D] - WorldWeaponYourWeapon
|
||||
└─ [CollisionShape3D] - Approximate weapon shape
|
||||
#### Option A: Manual Placement (Recommended)
|
||||
|
||||
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`:
|
||||
|
||||
```gdscript
|
||||
# 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
|
||||
)
|
||||
```
|
||||
|
||||
Set the script to `world_weapon.gd` and assign your WeaponData resource.
|
||||
|
||||
Example: `level/scenes/weapons/world_weapon_sword.tscn`
|
||||
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. Drag a WorldWeapon scene (e.g., `world_weapon_sword.tscn`) into the level
|
||||
3. Position it somewhere visible
|
||||
4. Run the game (F5)
|
||||
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
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[gd_resource type="Resource" script_class="WeaponData" load_steps=2 format=3 uid="uid://pqoldmf2q3t6"]
|
||||
[gd_resource type="Resource" script_class="WeaponData" load_steps=3 format=3 uid="uid://pqoldmf2q3t6"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://d2homvlmrg6xs" path="res://level/scripts/weapon_data.gd" id="1"]
|
||||
[ext_resource type="PackedScene" uid="uid://rkvkbxlweo60" path="res://level/scenes/weapons/TestSwordMesh.tscn" id="1_gdc1w"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1")
|
||||
@@ -10,4 +11,5 @@ damage = 20.0
|
||||
attack_range = 3.5
|
||||
attack_cooldown = 0.6
|
||||
knockback_force = 12.0
|
||||
mesh_scene = ExtResource("1_gdc1w")
|
||||
weight = 2.0
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
[gd_scene load_steps=18 format=3 uid="uid://dugaivbj1o66n"]
|
||||
[gd_scene load_steps=19 format=3 uid="uid://dugaivbj1o66n"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://d0dgljwwl463n" path="res://level/scripts/level.gd" id="1_e1sh7"]
|
||||
[ext_resource type="PackedScene" uid="uid://db06e8q8f8bdq" path="res://level/scenes/Player_Lilguy.tscn" id="1_uvcbi"]
|
||||
[ext_resource type="FontFile" uid="uid://diapabmalpcrj" path="res://assets/fonts/Kurland.ttf" id="3_icc4p"]
|
||||
[ext_resource type="PackedScene" uid="uid://b48oxbcgxu3d8" path="res://assets/Objects/Colosseum_10.fbx" id="4_u750a"]
|
||||
[ext_resource type="PackedScene" uid="uid://hd6pq287rgye" path="res://level/scenes/weapons/world_weapon_testsword.tscn" id="5_cwx4m"]
|
||||
|
||||
[sub_resource type="PlaneMesh" id="PlaneMesh_r5xs5"]
|
||||
size = Vector2(90, 90)
|
||||
@@ -346,6 +347,11 @@ offset_bottom = 40.0
|
||||
[node name="Colosseum_10" parent="." instance=ExtResource("4_u750a")]
|
||||
transform = Transform3D(15, 0, 0, 0, 15, 0, 0, 0, 15, 1.301034, -1.2294581, 2.0630608)
|
||||
|
||||
[node name="WeaponsContainer" type="Node3D" parent="."]
|
||||
|
||||
[node name="WorldWeaponSword" parent="WeaponsContainer" instance=ExtResource("5_cwx4m")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.0268106, 2.6057472, 8.836907)
|
||||
|
||||
[connection signal="pressed" from="Menu/MainContainer/MainMenu/Buttons/Host" to="." method="_on_host_pressed"]
|
||||
[connection signal="pressed" from="Menu/MainContainer/MainMenu/Buttons/Join" to="." method="_on_join_pressed"]
|
||||
[connection signal="pressed" from="Menu/MainContainer/MainMenu/Option4/Quit" to="." method="_on_quit_pressed"]
|
||||
|
||||
@@ -39,15 +39,81 @@ func _ready():
|
||||
add_child(weapons_container)
|
||||
print("Created WeaponsContainer")
|
||||
|
||||
# Clients: Remove manually placed weapons (server will sync them via RPC)
|
||||
if not multiplayer.is_server():
|
||||
_cleanup_manual_weapons_on_client()
|
||||
return
|
||||
|
||||
Network.connect("player_connected", Callable(self, "_on_player_connected"))
|
||||
multiplayer.peer_disconnected.connect(_remove_player)
|
||||
|
||||
# Initialize any manually placed weapons in the scene
|
||||
_initialize_manual_weapons()
|
||||
|
||||
# Spawn initial weapons when server starts
|
||||
_spawn_initial_weapons()
|
||||
|
||||
func _cleanup_manual_weapons_on_client():
|
||||
"""Remove manually placed weapons on clients (server will sync them via RPC)"""
|
||||
if not weapons_container:
|
||||
return
|
||||
|
||||
var weapons_to_remove = []
|
||||
for child in weapons_container.get_children():
|
||||
if child is WorldWeapon and child.weapon_id == -1:
|
||||
weapons_to_remove.append(child)
|
||||
|
||||
for weapon in weapons_to_remove:
|
||||
print("[Client] Removing manually placed weapon: ", weapon.name)
|
||||
weapon.queue_free()
|
||||
|
||||
func _initialize_manual_weapons():
|
||||
"""Initialize any WorldWeapon nodes manually placed in the level scene"""
|
||||
if not multiplayer.is_server():
|
||||
return
|
||||
|
||||
if not weapons_container:
|
||||
return
|
||||
|
||||
# Find all WorldWeapon nodes in the weapons container
|
||||
var manual_weapons = []
|
||||
for child in weapons_container.get_children():
|
||||
if child is WorldWeapon:
|
||||
manual_weapons.append(child)
|
||||
|
||||
if manual_weapons.is_empty():
|
||||
print("[Server] No manually placed weapons found")
|
||||
return
|
||||
|
||||
print("[Server] Found ", manual_weapons.size(), " manually placed weapon(s)")
|
||||
|
||||
# Initialize each manually placed weapon
|
||||
for weapon in manual_weapons:
|
||||
# Skip if already initialized (weapon_id != -1)
|
||||
if weapon.weapon_id != -1:
|
||||
continue
|
||||
|
||||
# Assign unique ID
|
||||
_weapon_spawn_counter += 1
|
||||
weapon.weapon_id = _weapon_spawn_counter
|
||||
|
||||
# Set deterministic name for networking
|
||||
var old_name = weapon.name
|
||||
weapon.name = "WorldWeapon_" + str(weapon.weapon_id)
|
||||
|
||||
# Track in active weapons
|
||||
_active_weapons[weapon.weapon_id] = weapon
|
||||
|
||||
# Connect cleanup signal
|
||||
weapon.tree_exiting.connect(_on_weapon_removed.bind(weapon.weapon_id))
|
||||
|
||||
print("[Server] Initialized manual weapon '", old_name, "' with ID: ", weapon.weapon_id, " at position: ", weapon.global_position)
|
||||
|
||||
# Verify weapon_data is set
|
||||
if not weapon.weapon_data:
|
||||
push_error("Manual weapon '", old_name, "' has no WeaponData assigned!")
|
||||
continue
|
||||
|
||||
func _spawn_initial_weapons():
|
||||
if not multiplayer.is_server():
|
||||
return
|
||||
|
||||
@@ -14,6 +14,8 @@ var _pickup_area: Area3D = null
|
||||
var _is_being_picked_up: bool = false
|
||||
|
||||
func _ready():
|
||||
print("[WorldWeapon ", name, "] _ready() called. weapon_id=", weapon_id, ", weapon_data=", weapon_data)
|
||||
|
||||
# Set collision layer to "weapon" (layer 3 = bit 4)
|
||||
collision_layer = 4
|
||||
collision_mask = 2 # Collide with world
|
||||
@@ -21,10 +23,14 @@ func _ready():
|
||||
# Set up physics
|
||||
if weapon_data:
|
||||
mass = weapon_data.weight
|
||||
print("[WorldWeapon ", name, "] Set mass to ", mass)
|
||||
|
||||
# Spawn mesh
|
||||
if weapon_data and weapon_data.mesh_scene:
|
||||
print("[WorldWeapon ", name, "] Spawning mesh from ", weapon_data.mesh_scene)
|
||||
_spawn_mesh()
|
||||
else:
|
||||
print("[WorldWeapon ", name, "] ERROR: Cannot spawn mesh. weapon_data=", weapon_data, ", mesh_scene=", weapon_data.mesh_scene if weapon_data else "null")
|
||||
|
||||
# Create collision shape if not exists
|
||||
_setup_collision()
|
||||
@@ -44,6 +50,7 @@ func _spawn_mesh():
|
||||
# Instantiate mesh
|
||||
_mesh_instance = weapon_data.mesh_scene.instantiate()
|
||||
add_child(_mesh_instance)
|
||||
print("[WorldWeapon ", name, "] Mesh spawned successfully: ", _mesh_instance)
|
||||
|
||||
func _setup_collision():
|
||||
# Check if we already have a collision shape
|
||||
|
||||
Reference in New Issue
Block a user