diff --git a/assets/Warrior+Animation/castle_guard_01.fbx b/assets/Warrior+Animation/castle_guard_01.fbx new file mode 100644 index 0000000..858fe3d Binary files /dev/null and b/assets/Warrior+Animation/castle_guard_01.fbx differ diff --git a/assets/Warrior+Animation/idle.fbx b/assets/Warrior+Animation/idle.fbx new file mode 100644 index 0000000..ccc21ff Binary files /dev/null and b/assets/Warrior+Animation/idle.fbx differ diff --git a/assets/Warrior+Animation/jump.fbx b/assets/Warrior+Animation/jump.fbx new file mode 100644 index 0000000..cf721e5 Binary files /dev/null and b/assets/Warrior+Animation/jump.fbx differ diff --git a/assets/Warrior+Animation/left strafe walking.fbx b/assets/Warrior+Animation/left strafe walking.fbx new file mode 100644 index 0000000..5645972 Binary files /dev/null and b/assets/Warrior+Animation/left strafe walking.fbx differ diff --git a/assets/Warrior+Animation/left strafe.fbx b/assets/Warrior+Animation/left strafe.fbx new file mode 100644 index 0000000..881914f Binary files /dev/null and b/assets/Warrior+Animation/left strafe.fbx differ diff --git a/assets/Warrior+Animation/left turn 90.fbx b/assets/Warrior+Animation/left turn 90.fbx new file mode 100644 index 0000000..9d0a292 Binary files /dev/null and b/assets/Warrior+Animation/left turn 90.fbx differ diff --git a/assets/Warrior+Animation/left turn.fbx b/assets/Warrior+Animation/left turn.fbx new file mode 100644 index 0000000..cee6230 Binary files /dev/null and b/assets/Warrior+Animation/left turn.fbx differ diff --git a/assets/Warrior+Animation/right strafe walking.fbx b/assets/Warrior+Animation/right strafe walking.fbx new file mode 100644 index 0000000..d56012f Binary files /dev/null and b/assets/Warrior+Animation/right strafe walking.fbx differ diff --git a/assets/Warrior+Animation/right strafe.fbx b/assets/Warrior+Animation/right strafe.fbx new file mode 100644 index 0000000..c533196 Binary files /dev/null and b/assets/Warrior+Animation/right strafe.fbx differ diff --git a/assets/Warrior+Animation/right turn 90.fbx b/assets/Warrior+Animation/right turn 90.fbx new file mode 100644 index 0000000..18fe6d4 Binary files /dev/null and b/assets/Warrior+Animation/right turn 90.fbx differ diff --git a/assets/Warrior+Animation/right turn.fbx b/assets/Warrior+Animation/right turn.fbx new file mode 100644 index 0000000..6c202f1 Binary files /dev/null and b/assets/Warrior+Animation/right turn.fbx differ diff --git a/assets/Warrior+Animation/running.fbx b/assets/Warrior+Animation/running.fbx new file mode 100644 index 0000000..9c32abe Binary files /dev/null and b/assets/Warrior+Animation/running.fbx differ diff --git a/assets/Warrior+Animation/walking.fbx b/assets/Warrior+Animation/walking.fbx new file mode 100644 index 0000000..501429c Binary files /dev/null and b/assets/Warrior+Animation/walking.fbx differ diff --git a/assets/animations/Idle.fbx b/assets/animations/Idle.fbx new file mode 100644 index 0000000..9ae9979 Binary files /dev/null and b/assets/animations/Idle.fbx differ diff --git a/assets/animations/Idle.fbx.import b/assets/animations/Idle.fbx.import new file mode 100644 index 0000000..105a47b --- /dev/null +++ b/assets/animations/Idle.fbx.import @@ -0,0 +1,44 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://cxr7xlsq3vvhi" +path="res://.godot/imported/Idle.fbx-ecf8c7ec9efbd10accf3a620e1992827.scn" + +[deps] + +source_file="res://assets/animations/Idle.fbx" +dest_files=["res://.godot/imported/Idle.fbx-ecf8c7ec9efbd10accf3a620e1992827.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=true +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={} +fbx/importer=0 +fbx/allow_geometry_helper_nodes=false +fbx/embedded_image_handling=1 +fbx/naming_version=2 diff --git a/assets/animations/Stop Walking.fbx b/assets/animations/Stop Walking.fbx new file mode 100644 index 0000000..2e5a804 Binary files /dev/null and b/assets/animations/Stop Walking.fbx differ diff --git a/assets/animations/Stop Walking.fbx.import b/assets/animations/Stop Walking.fbx.import new file mode 100644 index 0000000..be1dc26 --- /dev/null +++ b/assets/animations/Stop Walking.fbx.import @@ -0,0 +1,44 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dusjhgyamhmgt" +path="res://.godot/imported/Stop Walking.fbx-3d24a0466a0c2e2a6357ddcab01c8e7a.scn" + +[deps] + +source_file="res://assets/animations/Stop Walking.fbx" +dest_files=["res://.godot/imported/Stop Walking.fbx-3d24a0466a0c2e2a6357ddcab01c8e7a.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=true +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={} +fbx/importer=0 +fbx/allow_geometry_helper_nodes=false +fbx/embedded_image_handling=1 +fbx/naming_version=2 diff --git a/player_backup.gd b/player_backup.gd new file mode 100644 index 0000000..226fe32 --- /dev/null +++ b/player_backup.gd @@ -0,0 +1,251 @@ +# Player.gd +# Steuert den Spielercharakter: Bewegung, Kamera, HP, Angriff, Zielauswahl +extends CharacterBody3D + +const SPEED = 5.0 +const JUMP_VELOCITY = 4.5 +const GRAVITY = 9.8 + +var max_hp = 100 +var current_hp = 100 +var target = null # Aktuell markierter Gegner +var equipped_weapon = null # Ausgerüstete Waffe (null = unbewaffnet, Schaden = 1) + +# Global Cooldown System (GCD) +var global_cooldown = 0.0 +const GLOBAL_COOLDOWN_TIME = 1.5 # GCD in Sekunden +var autoattack_active = false # Ob Autoattack nach GCD weiterlaufen soll + +# Skills System - individuelle Cooldowns (zusätzlich zum GCD) +var heavy_strike_cooldown = 0.0 +const HEAVY_STRIKE_DAMAGE_MIN = 10 +const HEAVY_STRIKE_DAMAGE_MAX = 15 +const HEAVY_STRIKE_COOLDOWN = 3.0 +const HEAVY_STRIKE_RANGE = 2.0 + +@onready var camera_pivot = $CameraPivot +@onready var camera = $CameraPivot/Camera3D +@onready var hud = $HUD + +func _ready(): + hud.update_health(current_hp, max_hp) + hud.set_active_slot(0) + # Icons für Skills setzen + hud.set_slot_icon(0, "res://icons/autoattack_icon.svg") # Slot 1: Autoattack + hud.set_slot_icon(1, "res://icons/heavy_strike_icon.svg") # Slot 2: Heavy Strike + + # HUD-Klicks verbinden + hud.slot_clicked.connect(_on_slot_clicked) + +# Handler für HUD-Slot-Klicks +func _on_slot_clicked(slot_index: int): + match slot_index: + 0: # Autoattack manuell starten + if target != null and global_cooldown <= 0: + start_autoattack() + perform_autoattack() + 1: # Heavy Strike + use_heavy_strike() + +# Schaden am Spieler abziehen und HP-Leiste aktualisieren +func take_damage(amount): + current_hp = clamp(current_hp - amount, 0, max_hp) + hud.update_health(current_hp, max_hp) + if current_hp <= 0: + die() + +# HP heilen und HP-Leiste aktualisieren +func heal(amount): + current_hp = clamp(current_hp + amount, 0, max_hp) + hud.update_health(current_hp, max_hp) + +func die(): + print("Spieler gestorben!") + +# Schaden basierend auf ausgerüsteter Waffe (unbewaffnet = 1) +func get_attack_damage() -> int: + if equipped_weapon == null: + return 1 + return randi_range(equipped_weapon.min_damage, equipped_weapon.max_damage) + +# Reichweite basierend auf ausgerüsteter Waffe (unbewaffnet = 1.5) +func get_attack_range() -> float: + if equipped_weapon == null: + return 1.5 + return equipped_weapon.range + +# Angriffsgeschwindigkeit basierend auf ausgerüsteter Waffe (unbewaffnet = 1.5s) +func get_attack_cooldown() -> float: + if equipped_weapon == null: + return 1.5 + return equipped_weapon.attack_speed + +# Ziel markieren — start_attack=true startet sofort die Autoattack +func set_target(new_target, start_attack: bool = false): + if target != null and is_instance_valid(target): + target.hide_health() + target = new_target + target.show_health() + print("Ziel markiert: ", target.name) + if start_attack: + start_autoattack() + +# Autoattack aktivieren +func start_autoattack(): + autoattack_active = true + print("Autoattack aktiviert") + +# Autoattack deaktivieren +func stop_autoattack(): + autoattack_active = false + print("Autoattack deaktiviert") + +# Führt einen Autoattack aus (wird vom GCD-System aufgerufen) +func perform_autoattack(): + if target == null or not is_instance_valid(target): + target = null + autoattack_active = false + return + + var distance = global_position.distance_to(target.global_position) + if distance <= get_attack_range(): + var dmg = get_attack_damage() + target.take_damage(dmg) + print("Autoattack: ", dmg, " Schaden") + trigger_global_cooldown() + else: + print("Ziel zu weit entfernt für Autoattack") + +# Global Cooldown auslösen +func trigger_global_cooldown(): + global_cooldown = GLOBAL_COOLDOWN_TIME + +# Heavy Strike: Starker Angriff mit Cooldown +func use_heavy_strike(): + if target == null or not is_instance_valid(target): + print("Kein Ziel für Heavy Strike!") + return + + # GCD Check + if global_cooldown > 0: + print("Global Cooldown aktiv: ", "%.1f" % global_cooldown, "s") + return + + # Skill-eigener Cooldown Check + if heavy_strike_cooldown > 0: + print("Heavy Strike noch im Cooldown: ", "%.1f" % heavy_strike_cooldown, "s") + return + + var distance = global_position.distance_to(target.global_position) + if distance > HEAVY_STRIKE_RANGE: + print("Ziel zu weit entfernt für Heavy Strike!") + return + + var damage = randi_range(HEAVY_STRIKE_DAMAGE_MIN, HEAVY_STRIKE_DAMAGE_MAX) + target.take_damage(damage) + heavy_strike_cooldown = HEAVY_STRIKE_COOLDOWN + trigger_global_cooldown() + start_autoattack() # Autoattack nach Skill automatisch aktivieren + print("Heavy Strike! ", damage, " Schaden") + +# Raycast von der Kamera auf Mausposition — trifft Gegner mit take_damage() +func _try_select_target(start_attack: bool = false): + var space_state = get_world_3d().direct_space_state + var viewport = get_viewport() + var mouse_pos = viewport.get_mouse_position() + var ray_origin = camera.project_ray_origin(mouse_pos) + var ray_end = ray_origin + camera.project_ray_normal(mouse_pos) * 100.0 + var query = PhysicsRayQueryParameters3D.create(ray_origin, ray_end) + query.exclude = [self] + var result = space_state.intersect_ray(query) + if result and result.collider.has_method("take_damage"): + set_target(result.collider, start_attack) + +func _physics_process(delta): + # Global Cooldown herunterzählen + var gcd_was_active = global_cooldown > 0 + if global_cooldown > 0: + global_cooldown -= delta + + # Wenn GCD gerade abgelaufen ist und Autoattack aktiv, führe Autoattack aus + if gcd_was_active and global_cooldown <= 0 and autoattack_active: + perform_autoattack() + + # Skill-Cooldowns herunterzählen + if heavy_strike_cooldown > 0: + heavy_strike_cooldown -= delta + + # HUD Cooldowns aktualisieren + hud.set_slot_cooldown(0, global_cooldown) # Slot 1: GCD für Autoattack + hud.set_slot_cooldown(1, max(global_cooldown, heavy_strike_cooldown)) # Slot 2: max(GCD, Skill-CD) + + # Schwerkraft + if not is_on_floor(): + velocity.y -= GRAVITY * delta + + # Springen + if Input.is_action_just_pressed("ui_accept") and is_on_floor(): + velocity.y = JUMP_VELOCITY + + # Linksklick: nur markieren + if Input.is_action_just_pressed("select_target"): + _try_select_target(false) + + # Rechtsklick: markieren + angreifen + if Input.is_action_just_pressed("ui_right_mouse"): + _try_select_target(true) + + # Aktionsleiste 1-9 + if Input.is_action_just_pressed("action_1"): + hud.set_active_slot(0) + if target != null and global_cooldown <= 0: + start_autoattack() + perform_autoattack() + if Input.is_action_just_pressed("action_2"): + hud.set_active_slot(1) + use_heavy_strike() + if Input.is_action_just_pressed("action_3"): + hud.set_active_slot(2) + if Input.is_action_just_pressed("action_4"): + hud.set_active_slot(3) + if Input.is_action_just_pressed("action_5"): + hud.set_active_slot(4) + if Input.is_action_just_pressed("action_6"): + hud.set_active_slot(5) + if Input.is_action_just_pressed("action_7"): + hud.set_active_slot(6) + if Input.is_action_just_pressed("action_8"): + hud.set_active_slot(7) + if Input.is_action_just_pressed("action_9"): + hud.set_active_slot(8) + + # TEST: T drücken = 10 Schaden + if Input.is_action_just_pressed("test_damage"): + take_damage(10) + + # Eingabe + var input_dir = Vector2.ZERO + if Input.is_action_pressed("move_forward"): + input_dir.y -= 1 + if Input.is_action_pressed("move_back"): + input_dir.y += 1 + if Input.is_action_pressed("move_left"): + input_dir.x -= 1 + if Input.is_action_pressed("move_right"): + input_dir.x += 1 + + # Bewegung relativ zur Kamera + var world_yaw = rotation.y + camera_pivot.rotation.y + var forward = Vector3(-sin(world_yaw), 0, -cos(world_yaw)).normalized() + var right = Vector3(cos(world_yaw), 0, -sin(world_yaw)).normalized() + var direction = (forward * -input_dir.y + right * input_dir.x) + + velocity.x = direction.x * SPEED + velocity.z = direction.z * SPEED + + # RMB gehalten: Spieler schaut in Kamerarichtung + if Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT): + rotation.y = world_yaw + camera_pivot.rotation.y = 0 + + move_and_slide() diff --git a/player_backup.gd.uid b/player_backup.gd.uid new file mode 100644 index 0000000..60348d3 --- /dev/null +++ b/player_backup.gd.uid @@ -0,0 +1 @@ +uid://31iu6aebwmoc