class_name Player extends CharacterBody2D const WEAPON_SWORD = preload("res://scenes/weapons/weapon_sword.tscn") @export var camera: Camera2D @export var main_ui: MainUI var weapon: WeaponBase @onready var sprite_2d: Sprite2D = $Sprite2D var player_stats: PlayerStats = PlayerStats.new() var modifiers: Array[PlayerStatsModifier] = [] var dead: bool = false var death_anim_done: bool = false var god_mode: bool = false func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("active"): weapon.do_active() func _ready() -> void: camera.position = global_position main_ui.player_ui.update_hp() GlobalConst.sig_debug_god_mode.connect(toggle_god_mode) if not weapon: weapon = WEAPON_SWORD.instantiate() add_child(weapon) func _physics_process(delta: float) -> void: if dead: return var input_direction = Input.get_vector("left", "right", "up", "down") var move_speed = player_stats.get_final("move_speed", modifiers) velocity = input_direction * move_speed move_and_slide() func _process(delta: float) -> void: camera.position_smoothing_enabled = true camera.position = global_position if dead and !death_anim_done: death_animation(delta) func take_damage(value: float) -> void: if dead or god_mode: return player_stats.current_health -= value player_stats.current_health = clampf( player_stats.current_health, -1.0, player_stats.get_final("max_health", modifiers) ) var current_hp = player_stats.get_final("current_health", modifiers) var max_hp = player_stats.get_final("max_health", modifiers) GlobalConst.sig_debug_stats_set.emit("current_health", "%f" % current_hp) GlobalConst.sig_debug_stats_set.emit("max_hp", "%f" % max_hp) var dm = preload("res://scenes/damage_numbers.tscn").instantiate() dm.damage_taken = value dm.player_damage = false add_child(dm) GlobalConst.sig_on_player_hp_change.emit(current_hp, max_hp) main_ui.player_ui.update_hp() if player_stats.current_health <= 0: die() func die(): dead = true remove_from_group("damagable") get_tree().call_group("enemy", "cheer") GlobalConst.sig_stop_spawning.emit(true) sprite_2d.z_index += 10 get_taunted() func death_animation(delta: float): # Engine.time_scale = clampf(lerpf(Engine.time_scale, 0.25, 0.5), 0.25, 0.9*delta) camera.zoom = lerp(camera.zoom, Vector2(8, 8), 0.99 * delta) rotation_degrees = lerpf(rotation_degrees, 90, 0.99 * delta) if rotation_degrees > 88: main_ui.pause_ui.toggle_pause_ui() death_anim_done = true func get_taunted(): var taunting_enemies: Array[EnemyBase] = [] for body in get_tree().get_nodes_in_group(GlobalConst.GROUP_ENEMY): if global_position.distance_to(body.global_position) < 1000.0: taunting_enemies.append(body) for i in range(taunting_enemies.size()): var angle = (TAU / taunting_enemies.size()) * i var target_pos = Vector2(cos(angle), sin(angle)) * 50 var new_target = Marker2D.new() new_target.position = target_pos add_child(new_target) taunting_enemies[i].target = new_target func toggle_god_mode(value: bool): god_mode = value func add_xp(amount: float) -> void: player_stats.current_xp += amount main_ui.player_ui.update_xp() _check_level_up() func _check_level_up() -> void: var required_for_level = player_stats.xp_required_for_level() if player_stats.current_xp >= required_for_level: player_stats.current_level += 1 player_stats.current_xp -= required_for_level _trigger_level_up() func _trigger_level_up() -> void: var choice_count = 3 var choices: Array[LevelUpChoice] = [] main_ui.level_up_ui.clear() for i in range(choice_count): # TODO: implement fortune var mod = GlobalConst.draw_random_mod(1.0) var l_choice = preload("res://scenes/managers/ui/level_up_choice.tscn").instantiate() l_choice.mod = mod l_choice.player = self main_ui.level_up_ui.add_choice(l_choice) Engine.time_scale = 0.0 main_ui.level_up_ui.visible = true func _on_pickup_area_area_entered(area: Area2D) -> void: var body: Node2D = area.get_parent() if body.is_in_group(GlobalConst.GROUP_XP_ORB): add_xp(body.value) GlobalConst.sig_debug_stats_set.emit("player_xp", "%s" % player_stats.current_xp) body.queue_free() elif body.is_in_group(GlobalConst.GROUP_PICKUP): body.pickup()