diff --git a/PROJEKTDOKU.md b/PROJEKTDOKU.md index 2ddd905..408221f 100644 --- a/PROJEKTDOKU.md +++ b/PROJEKTDOKU.md @@ -190,6 +190,13 @@ Resource-Klasse für alle Ausrüstungsgegenstände. - **iron_helm.tres** — Eisenhelm (Kopf) - **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) Zeigt zwei Spalten: - **Stats-Spalte:** Stärke, Beweglichkeit, Intelligenz, Ausdauer, Rüstung, HP diff --git a/assets/Weapons/medieval_sword.glb b/assets/Weapons/medieval_sword.glb new file mode 100644 index 0000000..4b0bb35 Binary files /dev/null and b/assets/Weapons/medieval_sword.glb differ diff --git a/assets/Weapons/medieval_sword.glb.import b/assets/Weapons/medieval_sword.glb.import new file mode 100644 index 0000000..ffcd081 --- /dev/null +++ b/assets/Weapons/medieval_sword.glb.import @@ -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 diff --git a/assets/Weapons/medieval_sword_0.jpg b/assets/Weapons/medieval_sword_0.jpg new file mode 100644 index 0000000..1d4c000 Binary files /dev/null and b/assets/Weapons/medieval_sword_0.jpg differ diff --git a/assets/Weapons/medieval_sword_0.jpg.import b/assets/Weapons/medieval_sword_0.jpg.import new file mode 100644 index 0000000..df104a1 --- /dev/null +++ b/assets/Weapons/medieval_sword_0.jpg.import @@ -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 diff --git a/assets/Weapons/medieval_sword_1.png b/assets/Weapons/medieval_sword_1.png new file mode 100644 index 0000000..e1b2be9 Binary files /dev/null and b/assets/Weapons/medieval_sword_1.png differ diff --git a/assets/Weapons/medieval_sword_1.png.import b/assets/Weapons/medieval_sword_1.png.import new file mode 100644 index 0000000..0bd39cf --- /dev/null +++ b/assets/Weapons/medieval_sword_1.png.import @@ -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 diff --git a/assets/Weapons/medieval_sword_2.jpg b/assets/Weapons/medieval_sword_2.jpg new file mode 100644 index 0000000..3536486 Binary files /dev/null and b/assets/Weapons/medieval_sword_2.jpg differ diff --git a/assets/Weapons/medieval_sword_2.jpg.import b/assets/Weapons/medieval_sword_2.jpg.import new file mode 100644 index 0000000..907b6d6 --- /dev/null +++ b/assets/Weapons/medieval_sword_2.jpg.import @@ -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 diff --git a/equipment.gd b/equipment.gd index bc40061..a004763 100644 --- a/equipment.gd +++ b/equipment.gd @@ -38,6 +38,9 @@ enum Rarity { @export var attack_speed: float = 1.5 # Sekunden zwischen Angriffen @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 @export var icon: Texture2D diff --git a/equipment/iron_sword.tres b/equipment/iron_sword.tres index 9557429..be0c70c 100644 --- a/equipment/iron_sword.tres +++ b/equipment/iron_sword.tres @@ -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="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] script = ExtResource("1_equipment") @@ -9,4 +10,5 @@ item_name = "Eisenschwert" strength = 2 min_damage = 3 max_damage = 6 +model_scene = ExtResource("3_model") icon = ExtResource("2_icon") diff --git a/equipment/steel_sword.tres b/equipment/steel_sword.tres index a10502b..ddfb5f4 100644 --- a/equipment/steel_sword.tres +++ b/equipment/steel_sword.tres @@ -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="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] script = ExtResource("1_equipment") @@ -17,4 +18,5 @@ min_damage = 5 max_damage = 9 attack_speed = 1.4 weapon_range = 3.0 +model_scene = ExtResource("3_model") icon = ExtResource("2_icon") diff --git a/player.gd b/player.gd index 8a2f47b..2325a4e 100644 --- a/player.gd +++ b/player.gd @@ -141,6 +141,9 @@ var target = null # Aktuell markierter Gegner # ═══════════════════════════════════════════════════════════════ 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_dead: 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()) if character_panel and character_panel.panel_visible: character_panel.update_stats(self) + # Waffen-Modell aktualisieren + if slot == Equipment.Slot.WEAPON and weapon_attachment != null: + _attach_weapon_model(item) return old_item func get_equipped_weapon() -> Equipment: @@ -752,6 +758,51 @@ func _setup_animations(): _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): var scene = load(fbx_path) if scene == null: