# 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 can_attack = true var target = null # Aktuell markierter Gegner var equipped_weapon = null # Ausgerüstete Waffe (null = unbewaffnet, Schaden = 1) @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) # 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 and can_attack: autoattack() # Autoattack: greift wiederholt an solange Ziel gültig ist func autoattack(): if target == null or not is_instance_valid(target): target = null return if not can_attack: return var distance = global_position.distance_to(target.global_position) if distance <= get_attack_range(): can_attack = false var dmg = get_attack_damage() target.take_damage(dmg) print("Autoattack: ", dmg, " Schaden") await get_tree().create_timer(get_attack_cooldown()).timeout can_attack = true autoattack() else: await get_tree().create_timer(0.5).timeout autoattack() # 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): # 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: autoattack() if Input.is_action_just_pressed("action_2"): hud.set_active_slot(1) 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()