# 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 @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) # 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) 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 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) 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) # Grüner Rand für Consumables style.set_border_width_all(2) # Klick-Handler slot.gui_input.connect(_on_slot_clicked.bind(index, item)) # Tooltip slot.tooltip_text = _get_item_tooltip(item) return slot func _on_slot_clicked(event: InputEvent, index: int, item): if event is InputEventMouseButton and event.pressed: 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 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 and event.shift_pressed: # Shift+Linksklick: Auf nächsten freien Aktionsleisten-Slot legen if player: _assign_consumable_to_bar(item) func _assign_consumable_to_bar(item: Consumable): # Nächsten freien Slot ab 2 finden for i in range(2, 9): if player.action_bar_items[i] == null: player.assign_to_action_bar(i, item) print(item.item_name + " auf Slot " + str(i + 1) + " gelegt") return # Kein freier Slot - auf Slot 2 legen player.assign_to_action_bar(2, item) print(item.item_name + " auf Slot 3 gelegt (überschrieben)") 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[Shift+Linksklick: Auf Leiste legen]" 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