Waffen-Modell an Spielerhand via BoneAttachment3D
Schwert (medieval_sword.glb) wird zur Laufzeit an mixamorig_RightHand gehängt. Modell erscheint/verschwindet beim Ausrüsten/Ablegen. Equipment-Ressource um model_scene Property erweitert. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e4efb239f2
commit
9ed18e034c
13 changed files with 241 additions and 2 deletions
|
|
@ -190,6 +190,13 @@ Resource-Klasse für alle Ausrüstungsgegenstände.
|
||||||
- **iron_helm.tres** — Eisenhelm (Kopf)
|
- **iron_helm.tres** — Eisenhelm (Kopf)
|
||||||
- **wooden_shield.tres** — Holzschild (Nebenhand)
|
- **wooden_shield.tres** — Holzschild (Nebenhand)
|
||||||
|
|
||||||
|
### Waffen-Modell am Charakter (BoneAttachment3D)
|
||||||
|
- Schwert-Modell (`medieval_sword.glb`) wird zur Laufzeit an die rechte Hand (`mixamorig_RightHand`) des Spielers gehängt
|
||||||
|
- Verwendet `BoneAttachment3D` am Skeleton3D des Spielermodells
|
||||||
|
- Modell wird beim Ausrüsten einer Waffe (`equip_item`) angezeigt und beim Ablegen entfernt
|
||||||
|
- Position/Rotation/Scale werden im Code gesetzt: `Vector3(0.5, 0.2, 0)`, `Vector3(90, 180, 0)`, `Vector3(0.8, 0.8, 0.8)`
|
||||||
|
- Funktionen: `_setup_weapon_attachment()`, `_attach_weapon_model()`, `_remove_weapon_model()`
|
||||||
|
|
||||||
### Character Panel (character_panel.gd, C-Taste)
|
### Character Panel (character_panel.gd, C-Taste)
|
||||||
Zeigt zwei Spalten:
|
Zeigt zwei Spalten:
|
||||||
- **Stats-Spalte:** Stärke, Beweglichkeit, Intelligenz, Ausdauer, Rüstung, HP
|
- **Stats-Spalte:** Stärke, Beweglichkeit, Intelligenz, Ausdauer, Rüstung, HP
|
||||||
|
|
|
||||||
BIN
assets/Weapons/medieval_sword.glb
Normal file
BIN
assets/Weapons/medieval_sword.glb
Normal file
Binary file not shown.
42
assets/Weapons/medieval_sword.glb.import
Normal file
42
assets/Weapons/medieval_sword.glb.import
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="scene"
|
||||||
|
importer_version=1
|
||||||
|
type="PackedScene"
|
||||||
|
uid="uid://8klqbvdg43b3"
|
||||||
|
path="res://.godot/imported/medieval_sword.glb-6bd5ad7fbf20317ed64b8bc381ee05fb.scn"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/Weapons/medieval_sword.glb"
|
||||||
|
dest_files=["res://.godot/imported/medieval_sword.glb-6bd5ad7fbf20317ed64b8bc381ee05fb.scn"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
nodes/root_type=""
|
||||||
|
nodes/root_name=""
|
||||||
|
nodes/root_script=null
|
||||||
|
nodes/apply_root_scale=true
|
||||||
|
nodes/root_scale=1.0
|
||||||
|
nodes/import_as_skeleton_bones=false
|
||||||
|
nodes/use_name_suffixes=true
|
||||||
|
nodes/use_node_type_suffixes=true
|
||||||
|
meshes/ensure_tangents=true
|
||||||
|
meshes/generate_lods=true
|
||||||
|
meshes/create_shadow_meshes=true
|
||||||
|
meshes/light_baking=1
|
||||||
|
meshes/lightmap_texel_size=0.2
|
||||||
|
meshes/force_disable_compression=false
|
||||||
|
skins/use_named_skins=true
|
||||||
|
animation/import=true
|
||||||
|
animation/fps=30
|
||||||
|
animation/trimming=false
|
||||||
|
animation/remove_immutable_tracks=true
|
||||||
|
animation/import_rest_as_RESET=false
|
||||||
|
import_script/path=""
|
||||||
|
materials/extract=0
|
||||||
|
materials/extract_format=0
|
||||||
|
materials/extract_path=""
|
||||||
|
_subresources={}
|
||||||
|
gltf/naming_version=2
|
||||||
|
gltf/embedded_image_handling=1
|
||||||
BIN
assets/Weapons/medieval_sword_0.jpg
Normal file
BIN
assets/Weapons/medieval_sword_0.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 362 KiB |
44
assets/Weapons/medieval_sword_0.jpg.import
Normal file
44
assets/Weapons/medieval_sword_0.jpg.import
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cr8svhu2algti"
|
||||||
|
path.s3tc="res://.godot/imported/medieval_sword_0.jpg-94723da2994d60d5619ffcd032251761.s3tc.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
generator_parameters={
|
||||||
|
"md5": "e8adc51a863b1e90561d52d69ad93bfc"
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/Weapons/medieval_sword_0.jpg"
|
||||||
|
dest_files=["res://.godot/imported/medieval_sword_0.jpg-94723da2994d60d5619ffcd032251761.s3tc.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=0
|
||||||
BIN
assets/Weapons/medieval_sword_1.png
Normal file
BIN
assets/Weapons/medieval_sword_1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 476 KiB |
44
assets/Weapons/medieval_sword_1.png.import
Normal file
44
assets/Weapons/medieval_sword_1.png.import
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://51b8qklemnky"
|
||||||
|
path.s3tc="res://.godot/imported/medieval_sword_1.png-a07317cea2a7cf66dc265905e26d7546.s3tc.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
generator_parameters={
|
||||||
|
"md5": "694b37b7841572959ed4f217aef8380f"
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/Weapons/medieval_sword_1.png"
|
||||||
|
dest_files=["res://.godot/imported/medieval_sword_1.png-a07317cea2a7cf66dc265905e26d7546.s3tc.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=8
|
||||||
|
roughness/src_normal="res://assets/Weapons/medieval_sword_2.jpg"
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=0
|
||||||
BIN
assets/Weapons/medieval_sword_2.jpg
Normal file
BIN
assets/Weapons/medieval_sword_2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 589 KiB |
44
assets/Weapons/medieval_sword_2.jpg.import
Normal file
44
assets/Weapons/medieval_sword_2.jpg.import
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dwb4r1domnogc"
|
||||||
|
path.s3tc="res://.godot/imported/medieval_sword_2.jpg-5b274ce8d251c67b5d49b4af74f182a1.s3tc.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
generator_parameters={
|
||||||
|
"md5": "c9583464c97ca6ecfbb32b19e1fa9180"
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/Weapons/medieval_sword_2.jpg"
|
||||||
|
dest_files=["res://.godot/imported/medieval_sword_2.jpg-5b274ce8d251c67b5d49b4af74f182a1.s3tc.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=1
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=1
|
||||||
|
roughness/src_normal="res://assets/Weapons/medieval_sword_2.jpg"
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=0
|
||||||
|
|
@ -38,6 +38,9 @@ enum Rarity {
|
||||||
@export var attack_speed: float = 1.5 # Sekunden zwischen Angriffen
|
@export var attack_speed: float = 1.5 # Sekunden zwischen Angriffen
|
||||||
@export var weapon_range: float = 3.0
|
@export var weapon_range: float = 3.0
|
||||||
|
|
||||||
|
# 3D-Modell (GLB/GLTF) – wird an der Hand des Spielers angezeigt
|
||||||
|
@export var model_scene: PackedScene
|
||||||
|
|
||||||
# Icon für UI
|
# Icon für UI
|
||||||
@export var icon: Texture2D
|
@export var icon: Texture2D
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
[gd_resource type="Resource" script_class="Equipment" format=3 uid="uid://vprfv2phlcbc"]
|
[gd_resource type="Resource" script_class="Equipment" load_steps=4 format=3 uid="uid://vprfv2phlcbc"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://re0xiie1udfq" path="res://equipment.gd" id="1_equipment"]
|
[ext_resource type="Script" uid="uid://re0xiie1udfq" path="res://equipment.gd" id="1_equipment"]
|
||||||
[ext_resource type="Texture2D" uid="uid://bi7sh66txlj1c" path="res://icons/iron_sword_icon.svg" id="2_icon"]
|
[ext_resource type="Texture2D" uid="uid://bi7sh66txlj1c" path="res://icons/iron_sword_icon.svg" id="2_icon"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://8klqbvdg43b3" path="res://assets/Weapons/medieval_sword.glb" id="3_model"]
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_equipment")
|
script = ExtResource("1_equipment")
|
||||||
|
|
@ -9,4 +10,5 @@ item_name = "Eisenschwert"
|
||||||
strength = 2
|
strength = 2
|
||||||
min_damage = 3
|
min_damage = 3
|
||||||
max_damage = 6
|
max_damage = 6
|
||||||
|
model_scene = ExtResource("3_model")
|
||||||
icon = ExtResource("2_icon")
|
icon = ExtResource("2_icon")
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
[gd_resource type="Resource" script_class="Equipment" load_steps=3 format=3]
|
[gd_resource type="Resource" script_class="Equipment" load_steps=4 format=3]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://equipment.gd" id="1_equipment"]
|
[ext_resource type="Script" path="res://equipment.gd" id="1_equipment"]
|
||||||
[ext_resource type="Texture2D" path="res://icons/steel_sword_icon.svg" id="2_icon"]
|
[ext_resource type="Texture2D" path="res://icons/steel_sword_icon.svg" id="2_icon"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://8klqbvdg43b3" path="res://assets/Weapons/medieval_sword.glb" id="3_model"]
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_equipment")
|
script = ExtResource("1_equipment")
|
||||||
|
|
@ -17,4 +18,5 @@ min_damage = 5
|
||||||
max_damage = 9
|
max_damage = 9
|
||||||
attack_speed = 1.4
|
attack_speed = 1.4
|
||||||
weapon_range = 3.0
|
weapon_range = 3.0
|
||||||
|
model_scene = ExtResource("3_model")
|
||||||
icon = ExtResource("2_icon")
|
icon = ExtResource("2_icon")
|
||||||
|
|
|
||||||
51
player.gd
51
player.gd
|
|
@ -141,6 +141,9 @@ var target = null # Aktuell markierter Gegner
|
||||||
# ═══════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
var anim_player: AnimationPlayer = null
|
var anim_player: AnimationPlayer = null
|
||||||
|
var skeleton: Skeleton3D = null
|
||||||
|
var weapon_attachment: BoneAttachment3D = null
|
||||||
|
var current_weapon_model: Node3D = null
|
||||||
var is_attacking: bool = false
|
var is_attacking: bool = false
|
||||||
var is_dead: bool = false
|
var is_dead: bool = false
|
||||||
var is_walking: bool = false
|
var is_walking: bool = false
|
||||||
|
|
@ -346,6 +349,9 @@ func equip_item(item: Equipment) -> Equipment:
|
||||||
hud.update_resource(current_resource, max_resource, get_resource_name())
|
hud.update_resource(current_resource, max_resource, get_resource_name())
|
||||||
if character_panel and character_panel.panel_visible:
|
if character_panel and character_panel.panel_visible:
|
||||||
character_panel.update_stats(self)
|
character_panel.update_stats(self)
|
||||||
|
# Waffen-Modell aktualisieren
|
||||||
|
if slot == Equipment.Slot.WEAPON and weapon_attachment != null:
|
||||||
|
_attach_weapon_model(item)
|
||||||
return old_item
|
return old_item
|
||||||
|
|
||||||
func get_equipped_weapon() -> Equipment:
|
func get_equipped_weapon() -> Equipment:
|
||||||
|
|
@ -752,6 +758,51 @@ func _setup_animations():
|
||||||
|
|
||||||
_play_anim("idle")
|
_play_anim("idle")
|
||||||
|
|
||||||
|
# Waffen-Attachment einrichten
|
||||||
|
_setup_weapon_attachment()
|
||||||
|
|
||||||
|
func _setup_weapon_attachment():
|
||||||
|
if model == null:
|
||||||
|
print("Player Weapon: Kein Model!")
|
||||||
|
return
|
||||||
|
skeleton = model.find_child("Skeleton3D", true, false) as Skeleton3D
|
||||||
|
if skeleton == null:
|
||||||
|
push_warning("Player: Kein Skeleton3D gefunden!")
|
||||||
|
return
|
||||||
|
# Alle Bones auflisten zum Debuggen
|
||||||
|
print("Player Bones: ", skeleton.get_bone_count())
|
||||||
|
for i in range(skeleton.get_bone_count()):
|
||||||
|
if "Hand" in skeleton.get_bone_name(i) or "hand" in skeleton.get_bone_name(i):
|
||||||
|
print(" Bone ", i, ": ", skeleton.get_bone_name(i))
|
||||||
|
var bone_idx = skeleton.find_bone("mixamorig_RightHand")
|
||||||
|
if bone_idx == -1:
|
||||||
|
push_warning("Player: Bone 'mixamorig_RightHand' nicht gefunden!")
|
||||||
|
return
|
||||||
|
print("Player Weapon: RightHand Bone gefunden (idx=", bone_idx, ")")
|
||||||
|
weapon_attachment = BoneAttachment3D.new()
|
||||||
|
weapon_attachment.bone_name = "mixamorig_RightHand"
|
||||||
|
skeleton.add_child(weapon_attachment)
|
||||||
|
|
||||||
|
func _attach_weapon_model(weapon: Equipment):
|
||||||
|
_remove_weapon_model()
|
||||||
|
if weapon == null or weapon.model_scene == null:
|
||||||
|
print("Player Weapon: Kein Model an Waffe! model_scene=", weapon.model_scene if weapon else "null")
|
||||||
|
return
|
||||||
|
if weapon_attachment == null:
|
||||||
|
print("Player Weapon: Kein weapon_attachment!")
|
||||||
|
return
|
||||||
|
current_weapon_model = weapon.model_scene.instantiate()
|
||||||
|
current_weapon_model.rotation_degrees = Vector3(90, 180, 0)
|
||||||
|
current_weapon_model.position = Vector3(0.5, 0.2, 0)
|
||||||
|
current_weapon_model.scale = Vector3(0.8, 0.8, 0.8)
|
||||||
|
weapon_attachment.add_child(current_weapon_model)
|
||||||
|
print("Player Weapon: Schwert angehängt! Scale=", current_weapon_model.scale)
|
||||||
|
|
||||||
|
func _remove_weapon_model():
|
||||||
|
if current_weapon_model != null and is_instance_valid(current_weapon_model):
|
||||||
|
current_weapon_model.queue_free()
|
||||||
|
current_weapon_model = null
|
||||||
|
|
||||||
func _load_anim_from_fbx(fbx_path: String, anim_name: String, loop: bool = false):
|
func _load_anim_from_fbx(fbx_path: String, anim_name: String, loop: bool = false):
|
||||||
var scene = load(fbx_path)
|
var scene = load(fbx_path)
|
||||||
if scene == null:
|
if scene == null:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue