- Consumable-System: Tränke (HP/Mana) mit Stacking, Rechtsklick-Benutzung, Aktionsleisten-Zuweisung - Klassen-Ressourcen: ResourceType (NONE/MANA/RAGE/ENERGY) pro Klasse statt universelles Mana - Hauptmenü: Einstellungen für Auflösung, Fenstermodus, VSync, MSAA - Item-Icons: SVG-Icons für alle Equipment-Items und Tränke - Character Panel: Icon-Grid mit Hover-Tooltips statt Textanzeige - HUD: Ressourcen-Leiste mit klassenabhängiger Farbe - Loot: Consumable-Support in LootTable/LootWindow - Dokumentation vollständig aktualisiert Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
203 lines
7.1 KiB
GDScript
203 lines
7.1 KiB
GDScript
# CharacterPanel.gd
|
|
# Zeigt Charakterinfos: Klasse, Level, Stats und Equipment-Icons mit Tooltips
|
|
extends CanvasLayer
|
|
|
|
var panel_visible = false
|
|
|
|
const EQUIP_SLOT_SIZE = 48
|
|
|
|
@onready var panel = $Panel
|
|
@onready var class_label = $Panel/HBoxContainer/StatsColumn/ClassLabel
|
|
@onready var level_label = $Panel/HBoxContainer/StatsColumn/LevelLabel
|
|
@onready var str_label = $Panel/HBoxContainer/StatsColumn/StatsContainer/StrLabel
|
|
@onready var agi_label = $Panel/HBoxContainer/StatsColumn/StatsContainer/AgiLabel
|
|
@onready var int_label = $Panel/HBoxContainer/StatsColumn/StatsContainer/IntLabel
|
|
@onready var sta_label = $Panel/HBoxContainer/StatsColumn/StatsContainer/StaLabel
|
|
@onready var armor_label = $Panel/HBoxContainer/StatsColumn/StatsContainer/ArmorLabel
|
|
@onready var hp_label = $Panel/HBoxContainer/StatsColumn/HPLabel
|
|
@onready var damage_label = $Panel/HBoxContainer/EquipmentColumn/DamageLabel
|
|
@onready var dps_label = $Panel/HBoxContainer/EquipmentColumn/DPSLabel
|
|
@onready var equipment_grid = $Panel/HBoxContainer/EquipmentColumn/EquipmentGrid
|
|
|
|
# Slot-Reihenfolge und deutsche Namen
|
|
const SLOT_ORDER = [
|
|
Equipment.Slot.HEAD,
|
|
Equipment.Slot.CHEST,
|
|
Equipment.Slot.HANDS,
|
|
Equipment.Slot.LEGS,
|
|
Equipment.Slot.FEET,
|
|
Equipment.Slot.WEAPON,
|
|
Equipment.Slot.OFFHAND,
|
|
]
|
|
|
|
func _ready():
|
|
panel.visible = false
|
|
|
|
func toggle():
|
|
panel_visible = !panel_visible
|
|
panel.visible = panel_visible
|
|
|
|
func update_stats(player):
|
|
if player.character_class:
|
|
var main_stat_name = ""
|
|
match player.character_class.main_stat:
|
|
CharacterClass.MainStat.STRENGTH:
|
|
main_stat_name = "STR"
|
|
CharacterClass.MainStat.AGILITY:
|
|
main_stat_name = "AGI"
|
|
CharacterClass.MainStat.INTELLIGENCE:
|
|
main_stat_name = "INT"
|
|
class_label.text = player.character_class.class_name_de + " (Haupt: " + main_stat_name + ")"
|
|
else:
|
|
class_label.text = "Keine Klasse"
|
|
|
|
level_label.text = "Level " + str(player.level) + " (" + str(player.current_xp) + "/" + str(player.xp_to_next_level) + " XP)"
|
|
|
|
str_label.text = "Stärke: " + str(player.strength)
|
|
agi_label.text = "Beweglichkeit: " + str(player.agility)
|
|
int_label.text = "Intelligenz: " + str(player.intelligence)
|
|
sta_label.text = "Ausdauer: " + str(player.stamina)
|
|
armor_label.text = "Rüstung: " + str(player.armor)
|
|
|
|
hp_label.text = "HP: " + str(player.current_hp) + " / " + str(player.max_hp)
|
|
|
|
# Waffen-Stats
|
|
var weapon = player.get_equipped_weapon()
|
|
if weapon:
|
|
damage_label.text = "Schaden: " + str(weapon.min_damage) + "-" + str(weapon.max_damage) + " (%.1fs)" % weapon.attack_speed
|
|
else:
|
|
if player.character_class:
|
|
var min_dmg = player.character_class.unarmed_min_damage
|
|
var max_dmg = player.character_class.unarmed_max_damage
|
|
var atk_spd = player.character_class.unarmed_attack_speed
|
|
damage_label.text = "Unbewaffnet: " + str(min_dmg) + "-" + str(max_dmg) + " (%.1fs)" % atk_spd
|
|
else:
|
|
damage_label.text = "Unbewaffnet: 1-2 (2.0s)"
|
|
dps_label.text = "DPS: %.1f" % player.get_dps()
|
|
|
|
# Main-Stat hervorheben
|
|
str_label.modulate = Color(1, 1, 1)
|
|
agi_label.modulate = Color(1, 1, 1)
|
|
int_label.modulate = Color(1, 1, 1)
|
|
|
|
if player.character_class:
|
|
match player.character_class.main_stat:
|
|
CharacterClass.MainStat.STRENGTH:
|
|
str_label.modulate = Color(1, 0.8, 0.2)
|
|
CharacterClass.MainStat.AGILITY:
|
|
agi_label.modulate = Color(1, 0.8, 0.2)
|
|
CharacterClass.MainStat.INTELLIGENCE:
|
|
int_label.modulate = Color(1, 0.8, 0.2)
|
|
|
|
# Equipment-Grid mit Icons aktualisieren
|
|
_rebuild_equipment_grid(player)
|
|
|
|
func _rebuild_equipment_grid(player):
|
|
# Alte Slots entfernen
|
|
for child in equipment_grid.get_children():
|
|
child.queue_free()
|
|
|
|
# Slots als Icon-Panels erstellen
|
|
for slot_type in SLOT_ORDER:
|
|
var item = player.equipment[slot_type]
|
|
var slot_panel = _create_equip_slot(slot_type, item)
|
|
equipment_grid.add_child(slot_panel)
|
|
|
|
func _create_equip_slot(slot_type: Equipment.Slot, item: Equipment) -> Panel:
|
|
var slot = Panel.new()
|
|
slot.custom_minimum_size = Vector2(EQUIP_SLOT_SIZE, EQUIP_SLOT_SIZE)
|
|
|
|
# Hintergrund
|
|
var style = StyleBoxFlat.new()
|
|
style.bg_color = Color(0.12, 0.12, 0.12)
|
|
style.border_color = Color(0.3, 0.3, 0.3)
|
|
style.set_border_width_all(1)
|
|
style.set_corner_radius_all(4)
|
|
slot.add_theme_stylebox_override("panel", style)
|
|
|
|
if item != null:
|
|
# Rahmen in Seltenheitsfarbe
|
|
style.border_color = Equipment.get_rarity_color(item.rarity)
|
|
style.set_border_width_all(2)
|
|
|
|
if item.icon:
|
|
# Icon anzeigen
|
|
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(EQUIP_SLOT_SIZE - 6, EQUIP_SLOT_SIZE - 6)
|
|
icon.position = Vector2(3, 3)
|
|
slot.add_child(icon)
|
|
else:
|
|
# Fallback: Kurzname
|
|
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)
|
|
label.modulate = Equipment.get_rarity_color(item.rarity)
|
|
label.anchors_preset = Control.PRESET_FULL_RECT
|
|
slot.add_child(label)
|
|
|
|
# Tooltip mit Item-Eigenschaften
|
|
slot.tooltip_text = _get_item_tooltip(item)
|
|
else:
|
|
# Leerer Slot: Slot-Name als Tooltip
|
|
slot.tooltip_text = Equipment.get_slot_name(slot_type) + ": Leer"
|
|
|
|
# Slot-Kürzel anzeigen
|
|
var label = Label.new()
|
|
label.text = _get_slot_short(slot_type)
|
|
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
|
label.add_theme_font_size_override("font_size", 9)
|
|
label.modulate = Color(0.4, 0.4, 0.4)
|
|
label.anchors_preset = Control.PRESET_FULL_RECT
|
|
slot.add_child(label)
|
|
|
|
return slot
|
|
|
|
func _get_slot_short(slot_type: Equipment.Slot) -> String:
|
|
match slot_type:
|
|
Equipment.Slot.HEAD: return "Kopf"
|
|
Equipment.Slot.CHEST: return "Brust"
|
|
Equipment.Slot.HANDS: return "Hand"
|
|
Equipment.Slot.LEGS: return "Bein"
|
|
Equipment.Slot.FEET: return "Fuß"
|
|
Equipment.Slot.WEAPON: return "Waffe"
|
|
Equipment.Slot.OFFHAND: return "Neben"
|
|
return "?"
|
|
|
|
func _get_item_tooltip(item: Equipment) -> String:
|
|
var tooltip = item.item_name + "\n"
|
|
tooltip += Equipment.get_slot_name(item.slot) + "\n"
|
|
|
|
# Seltenheit
|
|
match item.rarity:
|
|
Equipment.Rarity.COMMON: tooltip += "Gewöhnlich\n"
|
|
Equipment.Rarity.UNCOMMON: tooltip += "Ungewöhnlich\n"
|
|
Equipment.Rarity.RARE: tooltip += "Selten\n"
|
|
Equipment.Rarity.EPIC: tooltip += "Episch\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"
|
|
tooltip += "Reichweite: " + str(item.weapon_range) + "\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"
|
|
|
|
return tooltip
|