# InventoryPanel.gd # UI für das Spieler-Inventar (Equipment + Consumables) extends CanvasLayer signal item_selected(item, index: int) var panel_visible = false var player = null # Drag & Drop var dragging = false var drag_item = null # Equipment oder Consumable var drag_from_index: int = -1 # Inventar-Index von dem gedraggt wird var drag_icon: TextureRect = null var drag_highlight_slot: int = -1 # Aktuell hervorgehobener Inventar-Slot @onready var panel = $Panel @onready var gold_label = $Panel/VBoxContainer/Header/GoldLabel @onready var item_grid = $Panel/VBoxContainer/ScrollContainer/ItemGrid const SLOT_SIZE = 50 func _ready(): panel.visible = false func setup(p): player = p if player and player.inventory: player.inventory.inventory_changed.connect(_on_inventory_changed) player.inventory.gold_changed.connect(_on_gold_changed) _refresh_inventory() func toggle(): panel_visible = !panel_visible panel.visible = panel_visible if panel_visible: _refresh_inventory() func _on_inventory_changed(): if panel_visible: _refresh_inventory() func _on_gold_changed(new_amount: int): gold_label.text = str(new_amount) + " Gold" func _refresh_inventory(): if player == null or player.inventory == null: return # Gold aktualisieren gold_label.text = str(player.inventory.gold) + " Gold" # Alte Slots entfernen for child in item_grid.get_children(): child.queue_free() # Slots erstellen (immer MAX_SLOTS anzeigen) for i in range(Inventory.MAX_SLOTS): var slot = _create_slot(i) item_grid.add_child(slot) func _create_slot(index: int) -> Panel: var slot = Panel.new() slot.custom_minimum_size = Vector2(SLOT_SIZE, SLOT_SIZE) # Slot-Hintergrund stylen var style = StyleBoxFlat.new() style.bg_color = Color(0.15, 0.15, 0.15) style.border_color = Color(0.3, 0.3, 0.3) style.set_border_width_all(1) slot.add_theme_stylebox_override("panel", style) # Alle Slots brauchen gui_input für Drop-Erkennung slot.gui_input.connect(_on_slot_input.bind(index)) # Item vorhanden? if player.inventory and index < player.inventory.item_count(): var item = player.inventory.get_item(index) if item: var item_icon = null if item is Consumable: item_icon = item.icon elif item is Equipment: item_icon = item.icon if item_icon: var icon = TextureRect.new() icon.texture = item_icon icon.expand_mode = TextureRect.EXPAND_FIT_WIDTH_PROPORTIONAL icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED icon.custom_minimum_size = Vector2(SLOT_SIZE - 4, SLOT_SIZE - 4) icon.position = Vector2(2, 2) icon.mouse_filter = Control.MOUSE_FILTER_IGNORE slot.add_child(icon) else: # Fallback: Text var label = Label.new() label.text = item.item_name.substr(0, 3) label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER label.add_theme_font_size_override("font_size", 10) if item is Equipment: label.modulate = Equipment.get_rarity_color(item.rarity) label.anchors_preset = Control.PRESET_FULL_RECT label.mouse_filter = Control.MOUSE_FILTER_IGNORE slot.add_child(label) # Stack-Count für Consumables if item is Consumable and item.stack_size > 1: var stack_label = Label.new() stack_label.text = str(item.stack_size) stack_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT stack_label.vertical_alignment = VERTICAL_ALIGNMENT_BOTTOM stack_label.add_theme_font_size_override("font_size", 11) stack_label.size = Vector2(SLOT_SIZE - 4, SLOT_SIZE - 4) stack_label.position = Vector2(0, 0) stack_label.mouse_filter = Control.MOUSE_FILTER_IGNORE slot.add_child(stack_label) # Rahmen if item is Equipment: style.border_color = Equipment.get_rarity_color(item.rarity) elif item is Consumable: style.border_color = Color(0.3, 0.7, 0.3) style.set_border_width_all(2) # Tooltip slot.tooltip_text = _get_item_tooltip(item) return slot func _on_slot_input(event: InputEvent, index: int): if event is InputEventMouseButton and event.pressed: var item = null if player.inventory and index < player.inventory.item_count(): item = player.inventory.get_item(index) if item == null: return if item is Equipment: if event.button_index == MOUSE_BUTTON_RIGHT: # Rechtsklick auf Equipment: Anlegen if player: var old_item = player.equip_item(item) player.inventory.remove_item(item) if old_item: player.inventory.add_item(old_item) _refresh_inventory() elif event.button_index == MOUSE_BUTTON_LEFT: # Linksklick: Drag starten _start_drag(item, index) elif item is Consumable: if event.button_index == MOUSE_BUTTON_RIGHT: # Rechtsklick auf Consumable: Direkt benutzen if player: if player.use_consumable(item): if item.stack_size <= 0: player.inventory.remove_item(item) _refresh_inventory() player._update_action_bar_stacks() elif event.button_index == MOUSE_BUTTON_LEFT: # Linksklick: Drag starten _start_drag(item, index) # Drag & Drop System func _start_drag(item, index: int): dragging = true drag_item = item drag_from_index = index # Icon am Mauszeiger erstellen var tex = item.icon if item.icon else null drag_icon = TextureRect.new() if tex: drag_icon.texture = tex drag_icon.custom_minimum_size = Vector2(40, 40) drag_icon.size = Vector2(40, 40) drag_icon.expand_mode = TextureRect.EXPAND_FIT_WIDTH_PROPORTIONAL drag_icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED drag_icon.mouse_filter = Control.MOUSE_FILTER_IGNORE # Eigene CanvasLayer damit Icon über allem anderen liegt var drag_layer = CanvasLayer.new() drag_layer.name = "DragLayer" drag_layer.layer = 200 drag_layer.add_child(drag_icon) get_tree().root.add_child(drag_layer) drag_icon.position = get_viewport().get_mouse_position() - Vector2(20, 20) # Highlight auf HUD aktivieren if player and player.hud: player.hud.set_drag_active(true) func _process(_delta): if dragging and drag_icon: drag_icon.position = get_viewport().get_mouse_position() - Vector2(20, 20) var mouse_pos = get_viewport().get_mouse_position() # HUD Slots highlighten if player and player.hud: player.hud.update_drag_hover(mouse_pos) # Inventar-Slots highlighten _update_inventory_hover(mouse_pos) func _input(event): if not dragging: return if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and not event.pressed: # Maus losgelassen - Drop prüfen _end_drag() func _end_drag(): if not dragging: return var mouse_pos = get_viewport().get_mouse_position() # Prüfen ob über einem Inventar-Slot var inv_slot = _get_inventory_slot_at(mouse_pos) if inv_slot >= 0 and inv_slot != drag_from_index: # Innerhalb Inventar verschieben/tauschen player.inventory.move_item(drag_from_index, inv_slot) else: # Prüfen ob über einem Action-Slot (nur Consumables) if player and player.hud: var action_slot = player.hud.get_slot_at_position(mouse_pos) if action_slot >= 0 and action_slot <= 8 and drag_item: if drag_item is Consumable: player.assign_to_action_bar(action_slot, drag_item) print(drag_item.item_name + " auf Aktionsleiste Slot " + str(action_slot + 1) + " gelegt") # HUD Highlight deaktivieren if player and player.hud: player.hud.set_drag_active(false) # Inventar Highlight entfernen _clear_inventory_highlight() # Aufräumen if drag_icon: var drag_layer = drag_icon.get_parent() drag_layer.queue_free() drag_icon = null dragging = false drag_item = null drag_from_index = -1 # Inventar-Slot unter Mausposition finden func _get_inventory_slot_at(mouse_pos: Vector2) -> int: for i in range(item_grid.get_child_count()): var slot = item_grid.get_child(i) var rect = slot.get_global_rect() if rect.has_point(mouse_pos): return i return -1 # Inventar-Slot Highlight während Drag func _update_inventory_hover(mouse_pos: Vector2): var hovered = _get_inventory_slot_at(mouse_pos) if hovered == drag_highlight_slot: return _clear_inventory_highlight() if hovered >= 0 and hovered != drag_from_index: drag_highlight_slot = hovered var slot = item_grid.get_child(hovered) var style = StyleBoxFlat.new() style.bg_color = Color(0.15, 0.15, 0.15) style.border_color = Color(1, 0.9, 0, 1) # Gelber Rand style.set_border_width_all(3) slot.add_theme_stylebox_override("panel", style) func _clear_inventory_highlight(): if drag_highlight_slot >= 0 and drag_highlight_slot < item_grid.get_child_count(): # Style zurücksetzen var slot = item_grid.get_child(drag_highlight_slot) var item = null if player.inventory and drag_highlight_slot < player.inventory.item_count(): item = player.inventory.get_item(drag_highlight_slot) var style = StyleBoxFlat.new() style.bg_color = Color(0.15, 0.15, 0.15) if item is Equipment: style.border_color = Equipment.get_rarity_color(item.rarity) style.set_border_width_all(2) elif item is Consumable: style.border_color = Color(0.3, 0.7, 0.3) style.set_border_width_all(2) else: style.border_color = Color(0.3, 0.3, 0.3) style.set_border_width_all(1) slot.add_theme_stylebox_override("panel", style) drag_highlight_slot = -1 func _get_item_tooltip(item) -> String: if item is Consumable: return _get_consumable_tooltip(item) elif item is Equipment: return _get_equipment_tooltip(item) return item.item_name func _get_consumable_tooltip(item: Consumable) -> String: var tooltip = item.item_name + "\n" tooltip += "Verbrauchbar\n" tooltip += "---\n" tooltip += item.get_effect_text() + "\n" tooltip += "Cooldown: " + str(item.cooldown) + "s\n" tooltip += "Anzahl: " + str(item.stack_size) + "/" + str(item.max_stack) + "\n" tooltip += "\n[Rechtsklick: Benutzen]\n[Linksklick: Ziehen]" return tooltip func _get_equipment_tooltip(item: Equipment) -> String: var tooltip = item.item_name + "\n" tooltip += Equipment.get_slot_name(item.slot) + "\n" tooltip += "---\n" if item.slot == Equipment.Slot.WEAPON: tooltip += "Schaden: " + str(item.min_damage) + "-" + str(item.max_damage) + "\n" tooltip += "Tempo: " + str(item.attack_speed) + "s\n" if item.armor > 0: tooltip += "Rüstung: +" + str(item.armor) + "\n" if item.strength > 0: tooltip += "Stärke: +" + str(item.strength) + "\n" if item.agility > 0: tooltip += "Beweglichkeit: +" + str(item.agility) + "\n" if item.intelligence > 0: tooltip += "Intelligenz: +" + str(item.intelligence) + "\n" if item.stamina > 0: tooltip += "Ausdauer: +" + str(item.stamina) + "\n" if item.haste > 0: tooltip += "Tempo: +" + str(int(item.haste * 100)) + "%\n" tooltip += "\n[Rechtsklick zum Anlegen]" return tooltip