extends CharacterBody2D @onready var collision_shape_2d: CollisionShape2D = $CollisionShape2D @onready var animated_sprite: AnimatedSprite2D = $AnimatedSprite2D @onready var player: CharacterBody2D = $"." @onready var movementlabel: Label = $CanvasLayer/VBoxContainer/MovementType var hovered = null var selected = null var hover_indicator = preload("res://assets/sprites/ui/ui_icons_green_down4.png") var selected_indicator = preload("res://assets/sprites/ui/ui_icons_blue_down4.png") var map_renderer = null @export var move_speed: float = 200.0 # Speed for free movement @export var tile_size: Vector2 = Vector2(32, 16) @export var combat_move_time: float = 0.3 enum MovementMode { FREE, COMBAT } var current_mode: MovementMode = MovementMode.FREE var is_moving: bool = false var target_position: Vector2 = Vector2.ZERO var start_position: Vector2 = Vector2.ZERO var move_progress: float = 0.0 var move_direction: Vector2 = Vector2.ZERO func set_map_renderer(renderer): map_renderer = renderer func _ready(): var hover_sprite = Sprite2D.new() hover_sprite.texture = hover_indicator hover_sprite.position.y = -15 hover_sprite.visible = false hover_sprite.name = "HoverIndicator" hover_sprite.z_index = 100 player.add_child(hover_sprite) target_position = position func toggle_selection(): selected = !selected map_renderer.set_unit_selected_state(selected) if selected: get_node("HoverIndicator").texture = selected_indicator # Tell the map renderer to darken everything if map_renderer: map_renderer.darken_all_except_player(self) else: get_node("HoverIndicator").texture = hover_indicator # Reset darkening if map_renderer: map_renderer.reset_darkening() # Keep indicator visible when selected get_node("HoverIndicator").visible = selected or hovered == player var player_data = { "stats": { "health": 100, "mana": 100, "speed": 3, "attack": 10, "defense": 5, "actionpoints": 5, }, "inventory": [], "name": "Hero" } func _input(event): if event is InputEventMouseMotion: check_hover() if event is InputEventKey and event.pressed: if event.keycode == KEY_H: debug_detection_at_mouse() func debug_detection_at_mouse(): var mouse_pos = get_viewport().get_mouse_position() print(mouse_pos) func _unhandled_input(event): if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed: # If we're being hovered and clicked if hovered == player: toggle_selection() else: selected = false func check_hover(): var mouse_pos = get_global_mouse_position() var was_hovered = hovered != null # print("Mouse pos: ", mouse_pos, " Player pos: ", player.position) if hovered: hovered.get_node("HoverIndicator").visible = false hovered = null if player.has_node("CollisionShape2D"): var collision = player.get_node("CollisionShape2D") var shape = collision.shape var local_pos = player.to_local(mouse_pos) if shape is RectangleShape2D: var extents = shape.extents if local_pos.x >= -extents.x and local_pos.x <= extents.x and \ local_pos.y >= -extents.y and local_pos.y <= extents.y: hovered = player player.get_node("HoverIndicator").visible = true if (was_hovered != (hovered != null)) and map_renderer: map_renderer.set_unit_hover_state(hovered != null) func set_unit_position(x, y, z): var z_layer = z var x_position = x + 16 var y_position = y # Update the main node position global_position = Vector2(x_position, y_position) # Update the visual z-index directly animated_sprite.z_index = z_layer # Keep sprite centered at node position animated_sprite.position = Vector2.ZERO print("Player Z-Layer: ", z_layer) print("Player position updated to: ", global_position) func get_sprite_size(): return collision_shape_2d.shape func _process(delta: float): check_hover() match current_mode: MovementMode.FREE: play_player_animation("movement") process_free_movement(delta) MovementMode.COMBAT: play_player_animation("idle") #process_combat_movement(delta) func process_free_movement(_delta): # Get input direction var direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") # Convert direction to isometric (optional - depends on your camera setup) var iso_direction = Vector2(direction.x, direction.y) # Set velocity and move velocity = iso_direction.normalized() * move_speed move_and_slide() func process_combat_movement(delta): if is_moving: # Continue current movement move_progress += delta / combat_move_time if move_progress >= 1.0: # Movement complete position = target_position is_moving = false else: # Interpolate position position = start_position.lerp(target_position, move_progress) else: # Check for new movement input var direction = Vector2.ZERO if Input.is_action_just_pressed("ui_right"): direction = Vector2(1, 0) elif Input.is_action_just_pressed("ui_left"): direction = Vector2(-1, 0) elif Input.is_action_just_pressed("ui_down"): direction = Vector2(0, 1) elif Input.is_action_just_pressed("ui_up"): direction = Vector2(0, -1) if direction != Vector2.ZERO: start_tile_movement(direction) # Start a new tile movement func start_tile_movement(direction: Vector2): # Convert direction to isometric var iso_direction = Vector2(direction.x - direction.y, (direction.x + direction.y) / 2) # Calculate target position start_position = position target_position = position + (iso_direction * tile_size) # Start movement is_moving = true move_progress = 0.0 move_direction = direction # Toggle between movement modes func toggle_movement_mode(): if current_mode == MovementMode.FREE: current_mode = MovementMode.COMBAT # Snap to nearest tile when entering combat mode position = Vector2( round(position.x / tile_size.x) * tile_size.x, round(position.y / tile_size.y) * tile_size.y ) else: current_mode = MovementMode.FREE print("Movement mode switched to: ", "FREE" if current_mode == MovementMode.FREE else "COMBAT") func play_player_animation(state="idle"): if state == "idle": animated_sprite.play("down") if state == "movement": animated_sprite.play("down") func _on_toggle_movement_pressed() -> void: player.toggle_movement_mode() if player.current_mode == player.MovementMode.FREE: movementlabel.text = "Mode: Non-Combat (Free)" else: movementlabel.text = "Mode: Combat (Tile-Based)"