Add shop sell-back
This commit is contained in:
@@ -256,6 +256,25 @@ func try_buy_item(item_id: String, price: int) -> bool:
|
||||
return false
|
||||
|
||||
|
||||
func try_sell_item(item_id: String, sale_price: int) -> bool:
|
||||
if item_id.is_empty() or sale_price <= 0:
|
||||
return false
|
||||
var previous_count := int(inventory.get(item_id, 0))
|
||||
if previous_count <= 0:
|
||||
return false
|
||||
var previous_gold := gold
|
||||
gold += sale_price
|
||||
if previous_count > 1:
|
||||
inventory[item_id] = previous_count - 1
|
||||
else:
|
||||
inventory.erase(item_id)
|
||||
if save_game():
|
||||
return true
|
||||
gold = previous_gold
|
||||
inventory[item_id] = previous_count
|
||||
return false
|
||||
|
||||
|
||||
func try_save_prebattle_loadout(roster_snapshot: Dictionary, inventory_snapshot: Dictionary) -> bool:
|
||||
var previous_roster := roster.duplicate(true)
|
||||
var previous_inventory := inventory.duplicate(true)
|
||||
|
||||
@@ -59,8 +59,11 @@ var briefing_panel: PanelContainer
|
||||
var briefing_label: Label
|
||||
var shop_button: Button
|
||||
var shop_menu: VBoxContainer
|
||||
var shop_buy_button: Button
|
||||
var shop_sell_button: Button
|
||||
var shop_list: VBoxContainer
|
||||
var shop_status_label: Label
|
||||
var shop_sell_mode := false
|
||||
var armory_button: Button
|
||||
var armory_menu: VBoxContainer
|
||||
var armory_list: VBoxContainer
|
||||
@@ -342,6 +345,20 @@ func _create_hud() -> void:
|
||||
shop_status_label.custom_minimum_size = Vector2(600, 22)
|
||||
shop_menu.add_child(shop_status_label)
|
||||
|
||||
var shop_mode_row := HBoxContainer.new()
|
||||
shop_mode_row.add_theme_constant_override("separation", 8)
|
||||
shop_menu.add_child(shop_mode_row)
|
||||
|
||||
shop_buy_button = Button.new()
|
||||
shop_buy_button.text = "Buy"
|
||||
shop_buy_button.pressed.connect(_on_shop_buy_mode_pressed)
|
||||
shop_mode_row.add_child(shop_buy_button)
|
||||
|
||||
shop_sell_button = Button.new()
|
||||
shop_sell_button.text = "Sell"
|
||||
shop_sell_button.pressed.connect(_on_shop_sell_mode_pressed)
|
||||
shop_mode_row.add_child(shop_sell_button)
|
||||
|
||||
var shop_scroll := ScrollContainer.new()
|
||||
shop_scroll.custom_minimum_size = Vector2(600, 190)
|
||||
shop_menu.add_child(shop_scroll)
|
||||
@@ -573,7 +590,7 @@ func _play_log_sfx(message: String) -> void:
|
||||
_play_sfx("fire_skill")
|
||||
elif message.contains(" moved to ") or message.contains(" advances to ") or message.contains(" takes formation at ") or message.contains(" arrives at "):
|
||||
_play_sfx("footstep")
|
||||
elif message.contains(" uses ") or message.contains(" equips ") or message.begins_with("Bought "):
|
||||
elif message.contains(" uses ") or message.contains(" equips ") or message.begins_with("Bought ") or message.begins_with("Sold "):
|
||||
_play_sfx("item_pickup")
|
||||
elif message.contains(" reaches Lv.") or message.contains(" promotes to "):
|
||||
_play_sfx("menu_confirm")
|
||||
@@ -1350,6 +1367,7 @@ func _on_restart_pressed() -> void:
|
||||
battle_result_applied = false
|
||||
battle_result_summary.clear()
|
||||
post_battle_dialogue_started = false
|
||||
shop_sell_mode = false
|
||||
selected_skill_id = ""
|
||||
selected_item_id = ""
|
||||
armory_unit_id = ""
|
||||
@@ -1438,7 +1456,7 @@ func _show_briefing() -> void:
|
||||
_hide_formation_menu()
|
||||
var prep_locked := _is_prebattle_prep_locked()
|
||||
if shop_button != null:
|
||||
shop_button.disabled = prep_locked or state.get_shop_item_ids().is_empty()
|
||||
shop_button.disabled = prep_locked or (state.get_shop_item_ids().is_empty() and _get_sellable_item_ids().is_empty())
|
||||
if armory_button != null:
|
||||
armory_button.disabled = prep_locked or state.get_controllable_player_units().is_empty()
|
||||
if roster_button != null:
|
||||
@@ -1473,6 +1491,7 @@ func _on_shop_pressed() -> void:
|
||||
if shop_menu != null and shop_menu.visible:
|
||||
_hide_shop_menu()
|
||||
else:
|
||||
shop_sell_mode = state.get_shop_item_ids().is_empty() and not _get_sellable_item_ids().is_empty()
|
||||
_hide_armory_menu()
|
||||
_hide_roster_menu()
|
||||
_hide_formation_menu()
|
||||
@@ -1817,11 +1836,24 @@ func _rebuild_shop_menu() -> void:
|
||||
return
|
||||
_clear_shop_list()
|
||||
if shop_status_label != null:
|
||||
shop_status_label.text = "Gold %d | %s" % [
|
||||
var mode_text := "Sell" if shop_sell_mode else "Buy"
|
||||
shop_status_label.text = "%s | Gold %d | %s" % [
|
||||
mode_text,
|
||||
campaign_state.gold,
|
||||
_format_inventory_status_text()
|
||||
]
|
||||
if shop_buy_button != null:
|
||||
shop_buy_button.disabled = not shop_sell_mode
|
||||
if shop_sell_button != null:
|
||||
shop_sell_button.disabled = shop_sell_mode or _get_sellable_item_ids().is_empty()
|
||||
|
||||
if shop_sell_mode:
|
||||
_rebuild_shop_sell_list()
|
||||
else:
|
||||
_rebuild_shop_buy_list()
|
||||
|
||||
|
||||
func _rebuild_shop_buy_list() -> void:
|
||||
var item_ids := state.get_shop_item_ids()
|
||||
if item_ids.is_empty():
|
||||
var empty_label := Label.new()
|
||||
@@ -1842,6 +1874,26 @@ func _rebuild_shop_menu() -> void:
|
||||
shop_list.add_child(buy_button)
|
||||
|
||||
|
||||
func _rebuild_shop_sell_list() -> void:
|
||||
var item_ids := _get_sellable_item_ids()
|
||||
if item_ids.is_empty():
|
||||
var empty_label := Label.new()
|
||||
empty_label.text = "No sellable stock"
|
||||
shop_list.add_child(empty_label)
|
||||
return
|
||||
|
||||
var inventory := campaign_state.get_inventory_snapshot()
|
||||
for item_id in item_ids:
|
||||
var normalized_id := str(item_id)
|
||||
var item := state.get_item_def(normalized_id)
|
||||
var sale_price := _sale_price_for_item(item)
|
||||
var owned := int(inventory.get(normalized_id, 0))
|
||||
var sell_button := Button.new()
|
||||
sell_button.text = _format_shop_sell_item_button_text(normalized_id, item, sale_price, owned)
|
||||
sell_button.pressed.connect(_on_shop_sell_item_pressed.bind(normalized_id))
|
||||
shop_list.add_child(sell_button)
|
||||
|
||||
|
||||
func _clear_shop_list() -> void:
|
||||
for child in shop_list.get_children():
|
||||
shop_list.remove_child(child)
|
||||
@@ -1861,6 +1913,15 @@ func _format_shop_item_button_text(item_id: String, item: Dictionary, price: int
|
||||
]
|
||||
|
||||
|
||||
func _format_shop_sell_item_button_text(item_id: String, item: Dictionary, sale_price: int, owned: int) -> String:
|
||||
return "%s Sell %dG %s Owned x%d" % [
|
||||
_item_display_name(item_id),
|
||||
sale_price,
|
||||
_format_shop_item_effect_text(item),
|
||||
owned
|
||||
]
|
||||
|
||||
|
||||
func _format_shop_item_effect_text(item: Dictionary) -> String:
|
||||
var kind := str(item.get("kind", "item"))
|
||||
if kind == "consumable":
|
||||
@@ -1897,6 +1958,66 @@ func _on_shop_item_pressed(item_id: String) -> void:
|
||||
_update_hud()
|
||||
|
||||
|
||||
func _on_shop_sell_item_pressed(item_id: String) -> void:
|
||||
if battle_started or _is_prebattle_prep_locked():
|
||||
return
|
||||
var item := state.get_item_def(item_id)
|
||||
var sale_price := _sale_price_for_item(item)
|
||||
var item_name := _item_display_name(item_id)
|
||||
if item.is_empty() or sale_price <= 0:
|
||||
return
|
||||
if campaign_state.try_sell_item(item_id, sale_price):
|
||||
state.set_inventory_snapshot(campaign_state.get_inventory_snapshot())
|
||||
_on_log_added("Sold %s for %d gold." % [item_name, sale_price])
|
||||
else:
|
||||
_play_ui_cancel()
|
||||
_on_log_added("Could not sell %s." % item_name)
|
||||
if _get_sellable_item_ids().is_empty():
|
||||
shop_sell_mode = false
|
||||
_rebuild_shop_menu()
|
||||
_update_hud()
|
||||
|
||||
|
||||
func _on_shop_buy_mode_pressed() -> void:
|
||||
if not shop_sell_mode:
|
||||
return
|
||||
_play_ui_click()
|
||||
shop_sell_mode = false
|
||||
_rebuild_shop_menu()
|
||||
_update_hud()
|
||||
|
||||
|
||||
func _on_shop_sell_mode_pressed() -> void:
|
||||
if shop_sell_mode or _get_sellable_item_ids().is_empty():
|
||||
return
|
||||
_play_ui_click()
|
||||
shop_sell_mode = true
|
||||
_rebuild_shop_menu()
|
||||
_update_hud()
|
||||
|
||||
|
||||
func _get_sellable_item_ids() -> Array:
|
||||
var item_ids := []
|
||||
var inventory := campaign_state.get_inventory_snapshot()
|
||||
for item_id in inventory.keys():
|
||||
var normalized_id := str(item_id)
|
||||
if normalized_id.is_empty() or int(inventory.get(normalized_id, 0)) <= 0:
|
||||
continue
|
||||
var item := state.get_item_def(normalized_id)
|
||||
if _sale_price_for_item(item) <= 0:
|
||||
continue
|
||||
item_ids.append(normalized_id)
|
||||
item_ids.sort()
|
||||
return item_ids
|
||||
|
||||
|
||||
func _sale_price_for_item(item: Dictionary) -> int:
|
||||
var price := int(item.get("price", 0))
|
||||
if price <= 0:
|
||||
return 0
|
||||
return max(1, int(floor(float(price) * 0.5)))
|
||||
|
||||
|
||||
func _is_input_locked() -> bool:
|
||||
return campaign_complete_screen or _is_dialogue_visible() or not battle_started or state.battle_status != BattleState.STATUS_ACTIVE
|
||||
|
||||
|
||||
Reference in New Issue
Block a user