lots of changeru

This commit is contained in:
2026-01-25 16:27:19 +01:00
parent a95e22d2fa
commit 7abadb92a9
14 changed files with 855 additions and 106 deletions

View File

@@ -38,11 +38,40 @@ var equipment_selection_index: int = 0 # Current equipment slot index (0-5: main
@onready var sfx_food: AudioStreamPlayer2D = $SfxFood
@onready var sfx_armour: AudioStreamPlayer2D = $SfxArmour
# Bar layout constants (align X/Y + bar across rows)
const _BAR_WIDTH: int = 100
const _BAR_VALUE_MIN_WIDTH: int = 44 # "999/999"
const _BAR_LABEL_MIN_WIDTH: int = 52 # "Weight:", "Exp:", "HP:", "MP:", "Coin:"
# Weight UI elements (created programmatically)
var weight_container: HBoxContainer = null
var weight_label: Label = null
var weight_value_label: Label = null
var weight_progress_bar: ProgressBar = null
# Exp UI elements (like weight)
var exp_container: HBoxContainer = null
var exp_label: Label = null
var exp_value_label: Label = null
var exp_progress_bar: ProgressBar = null
# HP / MP bar elements
var hp_container: HBoxContainer = null
var hp_label: Label = null
var hp_value_label: Label = null
var hp_progress_bar: ProgressBar = null
var mp_container: HBoxContainer = null
var mp_label: Label = null
var mp_value_label: Label = null
var mp_progress_bar: ProgressBar = null
# Coin UI elements ("Coin:" + 6-frame sprite + "X N")
var coin_container: HBoxContainer = null
var coin_label: Label = null
var coin_sprite: Sprite2D = null
var coin_value_label: Label = null
var coin_anim_time: float = 0.0
# Store button/item mappings for selection highlighting
var inventory_buttons: Dictionary = {} # item -> button
var equipment_buttons: Dictionary = {} # slot_name -> button
@@ -80,8 +109,12 @@ func _ready():
# Create equipment slot buttons (dynamically)
_create_equipment_slots()
# Create weight progress bar
# Create HP/MP bars, then weight, exp, coin (order in stats panel)
_create_hp_ui()
_create_mp_ui()
_create_weight_ui()
_create_exp_ui()
_create_coin_ui()
# Setup selection rectangle (already in scene, just configure it)
_setup_selection_rectangle()
@@ -175,43 +208,75 @@ func _update_stats():
var race_text = char_stats.race
stats_label.text = "Stats - " + race_text
# Update base stats
label_base_stats_value.text = str(char_stats.level) + "\n\n" + \
str(int(char_stats.hp)) + "/" + str(int(char_stats.maxhp)) + "\n" + \
str(int(char_stats.mp)) + "/" + str(int(char_stats.maxmp)) + "\n\n" + \
str(char_stats.baseStats.str) + "\n" + \
str(char_stats.baseStats.dex) + "\n" + \
str(char_stats.baseStats.end) + "\n" + \
str(char_stats.baseStats.int) + "\n" + \
str(char_stats.baseStats.wis) + "\n" + \
str(char_stats.baseStats.lck)
# Base stats: Level, STR, DEX, END, INT, WIS, LCK, PER (HP/MP are bars below)
if label_base_stats:
label_base_stats.text = "Level\n\nSTR\nDEX\nEND\nINT\nWIS\nLCK\nPER"
if label_base_stats_value:
label_base_stats_value.text = str(char_stats.level) + "\n\n" + \
str(char_stats.baseStats.str) + "\n" + \
str(char_stats.baseStats.dex) + "\n" + \
str(char_stats.baseStats.end) + "\n" + \
str(char_stats.baseStats.int) + "\n" + \
str(char_stats.baseStats.wis) + "\n" + \
str(char_stats.baseStats.lck) + "\n" + \
str(char_stats.baseStats.get("per", 10))
# Update derived stats
label_derived_stats_value.text = str(int(char_stats.xp)) + "/" + str(int(char_stats.xp_to_next_level)) + "\n" + \
str(char_stats.coin) + "\n\n\n\n" + \
str(char_stats.damage) + "\n" + \
str(char_stats.defense) + "\n" + \
str(char_stats.move_speed) + "\n" + \
str(char_stats.attack_speed) + "\n" + \
str(char_stats.sight)
# Derived stats: DMG, DEF, MovSpd, AtkSpd, Sight, SpellAmp, Crit% (XP/Coin moved to exp meter & coin UI)
if label_derived_stats:
label_derived_stats.text = "DMG\nDEF\nMovSpd\nAtkSpd\nSight\nSpellAmp\nCrit%"
if label_derived_stats_value:
label_derived_stats_value.text = "%.1f\n%.1f\n%.2f\n%.2f\n%.1f\n%.1f\n%.1f%%" % [
char_stats.damage,
char_stats.defense,
char_stats.move_speed,
char_stats.attack_speed,
char_stats.sight,
char_stats.spell_amp,
char_stats.crit_chance
]
# Update weight progress bar
if weight_progress_bar and weight_label:
# HP bar
if hp_progress_bar and hp_value_label:
hp_progress_bar.max_value = max(1.0, char_stats.maxhp)
hp_progress_bar.value = char_stats.hp
hp_value_label.text = str(int(char_stats.hp)) + "/" + str(int(char_stats.maxhp))
# MP bar
if mp_progress_bar and mp_value_label:
mp_progress_bar.max_value = max(1.0, char_stats.maxmp)
mp_progress_bar.value = char_stats.mp
mp_value_label.text = str(int(char_stats.mp)) + "/" + str(int(char_stats.maxmp))
# Exp meter (like weight)
if exp_progress_bar and exp_value_label:
var xp = char_stats.xp
var xp_next = char_stats.xp_to_next_level
exp_progress_bar.max_value = max(1.0, xp_next)
exp_progress_bar.value = xp
exp_value_label.text = str(int(xp)) + "/" + str(int(xp_next))
var fill_exp = StyleBoxFlat.new()
fill_exp.bg_color = Color(0.55, 0.35, 0.95)
exp_progress_bar.add_theme_stylebox_override("fill", fill_exp)
# Coin: "Coin:" + 6-frame sprite + "X <count>"
if coin_value_label:
coin_value_label.text = "X " + str(char_stats.coin)
# Weight progress bar
if weight_progress_bar and weight_value_label:
var current_weight = char_stats.get_total_weight()
var max_weight = char_stats.get_carrying_capacity()
weight_progress_bar.max_value = max_weight
weight_progress_bar.value = current_weight
weight_label.text = "Weight: " + str(int(current_weight)) + "/" + str(int(max_weight))
# Change color based on weight (green -> yellow -> red)
weight_value_label.text = str(int(current_weight)) + "/" + str(int(max_weight))
var weight_ratio = current_weight / max_weight
var fill_style = StyleBoxFlat.new()
if weight_ratio < 0.7:
fill_style.bg_color = Color(0.6, 0.8, 0.3) # Green
fill_style.bg_color = Color(0.6, 0.8, 0.3)
elif weight_ratio < 0.9:
fill_style.bg_color = Color(0.9, 0.8, 0.2) # Yellow
fill_style.bg_color = Color(0.9, 0.8, 0.2)
else:
fill_style.bg_color = Color(0.9, 0.3, 0.2) # Red
fill_style.bg_color = Color(0.9, 0.3, 0.2)
weight_progress_bar.add_theme_stylebox_override("fill", fill_style)
func _create_equipment_slots():
@@ -269,45 +334,134 @@ func _create_equipment_slots():
equipment_slots[slot_name] = button
equipment_buttons[slot_name] = button
func _create_weight_ui():
# Create weight display (label + progress bar)
func _style_bar_font(lbl: Label) -> void:
lbl.add_theme_font_size_override("font_size", 10)
if ResourceLoader.exists("res://assets/fonts/standard_font.png"):
var fr = load("res://assets/fonts/standard_font.png")
if fr:
lbl.add_theme_font_override("font", fr)
func _make_progress_bar_background() -> StyleBoxFlat:
var bg = StyleBoxFlat.new()
bg.bg_color = Color(0.2, 0.2, 0.2, 0.8)
bg.border_color = Color(0.4, 0.4, 0.4)
bg.set_border_width_all(1)
return bg
func _create_bar_row(p_name: String, p_label_text: String) -> Dictionary:
var row = HBoxContainer.new()
row.name = p_name
row.add_theme_constant_override("separation", 4)
var left = Label.new()
left.text = p_label_text
left.custom_minimum_size.x = _BAR_LABEL_MIN_WIDTH
_style_bar_font(left)
var spacer = Control.new()
spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL
var value_lbl = Label.new()
value_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
value_lbl.custom_minimum_size.x = _BAR_VALUE_MIN_WIDTH
_style_bar_font(value_lbl)
var bar = ProgressBar.new()
bar.custom_minimum_size = Vector2(_BAR_WIDTH, 12)
bar.show_percentage = false
bar.add_theme_stylebox_override("background", _make_progress_bar_background())
row.add_child(left)
row.add_child(spacer)
row.add_child(value_lbl)
row.add_child(bar)
stats_panel.add_child(row)
return {"container": row, "label": left, "value_label": value_lbl, "progress_bar": bar}
func _create_hp_ui():
if not stats_panel:
return
# Create container for weight UI
weight_container = HBoxContainer.new()
weight_container.name = "WeightContainer"
weight_container.add_theme_constant_override("separation", 4)
# Create label
weight_label = Label.new()
weight_label.text = "Weight:"
weight_label.add_theme_font_size_override("font_size", 10)
if ResourceLoader.exists("res://assets/fonts/standard_font.png"):
var font_resource = load("res://assets/fonts/standard_font.png")
if font_resource:
weight_label.add_theme_font_override("font", font_resource)
weight_container.add_child(weight_label)
# Create progress bar
weight_progress_bar = ProgressBar.new()
weight_progress_bar.custom_minimum_size = Vector2(100, 12)
weight_progress_bar.show_percentage = false
# Style the progress bar
var progress_style = StyleBoxFlat.new()
progress_style.bg_color = Color(0.2, 0.2, 0.2, 0.8)
progress_style.border_color = Color(0.4, 0.4, 0.4)
progress_style.set_border_width_all(1)
weight_progress_bar.add_theme_stylebox_override("background", progress_style)
var fill_style = StyleBoxFlat.new()
fill_style.bg_color = Color(0.6, 0.8, 0.3) # Green color
weight_progress_bar.add_theme_stylebox_override("fill", fill_style)
weight_container.add_child(weight_progress_bar)
# Add to stats panel (after stats labels)
stats_panel.add_child(weight_container)
var d = _create_bar_row("HPContainer", "HP:")
hp_container = d.container
hp_label = d.label
hp_value_label = d.value_label
hp_progress_bar = d.progress_bar
var fill = StyleBoxFlat.new()
fill.bg_color = Color(0.85, 0.2, 0.2)
hp_progress_bar.add_theme_stylebox_override("fill", fill)
func _create_mp_ui():
if not stats_panel:
return
var d = _create_bar_row("MPContainer", "MP:")
mp_container = d.container
mp_label = d.label
mp_value_label = d.value_label
mp_progress_bar = d.progress_bar
var fill = StyleBoxFlat.new()
fill.bg_color = Color(0.25, 0.45, 0.9)
mp_progress_bar.add_theme_stylebox_override("fill", fill)
func _create_weight_ui():
if not stats_panel:
return
var d = _create_bar_row("WeightContainer", "Weight:")
weight_container = d.container
weight_label = d.label
weight_value_label = d.value_label
weight_progress_bar = d.progress_bar
var fill = StyleBoxFlat.new()
fill.bg_color = Color(0.6, 0.8, 0.3)
weight_progress_bar.add_theme_stylebox_override("fill", fill)
func _create_exp_ui():
if not stats_panel:
return
var d = _create_bar_row("ExpContainer", "Exp:")
exp_container = d.container
exp_label = d.label
exp_value_label = d.value_label
exp_progress_bar = d.progress_bar
var fill = StyleBoxFlat.new()
fill.bg_color = Color(0.55, 0.35, 0.95)
exp_progress_bar.add_theme_stylebox_override("fill", fill)
func _create_coin_ui():
if not stats_panel:
return
coin_container = HBoxContainer.new()
coin_container.name = "CoinContainer"
coin_container.add_theme_constant_override("separation", 4)
coin_label = Label.new()
coin_label.name = "CoinLabel"
coin_label.text = "Coin:"
coin_label.custom_minimum_size.x = _BAR_LABEL_MIN_WIDTH
_style_bar_font(coin_label)
coin_container.add_child(coin_label)
var coin_spacer = Control.new()
coin_spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL
coin_container.add_child(coin_spacer)
var coin_wrap = Control.new()
coin_wrap.custom_minimum_size = Vector2(16, 16)
coin_sprite = Sprite2D.new()
coin_sprite.name = "CoinSprite"
var tex = load("res://assets/gfx/pickups/gold_coin.png") as Texture2D
if tex:
coin_sprite.texture = tex
coin_sprite.hframes = 6
coin_sprite.vframes = 1
coin_sprite.frame = 0
coin_sprite.centered = false
# Scale down to fit; texture may be multi-frame
var tw = tex.get_width() / 6.0
var th = tex.get_height()
if tw > 0 and th > 0:
var s = min(16.0 / tw, 16.0 / th)
coin_sprite.scale = Vector2(s, s)
coin_wrap.add_child(coin_sprite)
coin_container.add_child(coin_wrap)
coin_value_label = Label.new()
coin_value_label.name = "CoinValueLabel"
coin_value_label.text = "X 0"
coin_value_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT
_style_bar_font(coin_value_label)
coin_container.add_child(coin_value_label)
stats_panel.add_child(coin_container)
func _has_equipment_in_slot(slot_name: String) -> bool:
# Check if there's an item equipped in this slot
@@ -338,11 +492,11 @@ func _on_equipment_slot_pressed(slot_name: String):
if is_updating_ui:
return
# Only select if there's an item equipped
# Only select if there's an item equipped (same as arrow-key navigation)
if not _has_equipment_in_slot(slot_name):
return
# Select this slot
# Select this slot (equivalent to arrow-key selecting this equipment)
selected_slot = slot_name
selected_item = local_player.character_stats.equipment[slot_name]
selected_type = "equipment" if selected_item else ""
@@ -353,6 +507,7 @@ func _on_equipment_slot_pressed(slot_name: String):
_update_selection_highlight()
_update_selection_rectangle()
_update_info_panel()
func _on_equipment_slot_gui_input(event: InputEvent, slot_name: String):
# Handle double-click to unequip
@@ -452,6 +607,11 @@ func _process(delta):
var stylebox = selected_button.get_meta("highlight_stylebox") as StyleBoxFlat
if stylebox:
stylebox.border_color = animated_color
# Animate 6-frame coin sprite
if coin_sprite and coin_sprite.hframes >= 6:
coin_anim_time += delta * 10.0
coin_sprite.frame = int(coin_anim_time) % 6
func _update_ui():
if not local_player or not local_player.character_stats: