lots of changeru
This commit is contained in:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user