Add camp talk supply claims
This commit is contained in:
@@ -274,11 +274,33 @@ func _normalized_camp_conversations(source) -> Array:
|
||||
"label": label,
|
||||
"speaker": str(entry.get("speaker", "")).strip_edges(),
|
||||
"summary": str(entry.get("summary", "")).strip_edges(),
|
||||
"lines": lines
|
||||
"lines": lines,
|
||||
"effects": _normalized_camp_conversation_effects(entry.get("effects", []))
|
||||
})
|
||||
return result
|
||||
|
||||
|
||||
func _normalized_camp_conversation_effects(source) -> Array:
|
||||
var result := []
|
||||
if typeof(source) != TYPE_ARRAY:
|
||||
return result
|
||||
for effect in source:
|
||||
if typeof(effect) != TYPE_DICTIONARY:
|
||||
continue
|
||||
var effect_type := str(effect.get("type", "")).strip_edges()
|
||||
if effect_type == "grant_item":
|
||||
var item_id := str(effect.get("item_id", effect.get("id", ""))).strip_edges()
|
||||
if item_id.is_empty():
|
||||
continue
|
||||
result.append({
|
||||
"type": "grant_item",
|
||||
"item_id": item_id,
|
||||
"count": maxi(1, int(effect.get("count", 1))),
|
||||
"text": str(effect.get("text", "")).strip_edges()
|
||||
})
|
||||
return result
|
||||
|
||||
|
||||
func _is_condition_shape_valid(condition) -> bool:
|
||||
return typeof(condition) == TYPE_DICTIONARY or typeof(condition) == TYPE_ARRAY
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ class_name CampaignState
|
||||
|
||||
const SAVE_PATH := "user://campaign_save.json"
|
||||
const MANUAL_SAVE_PATH := "user://campaign_manual_save.json"
|
||||
const SAVE_VERSION := 4
|
||||
const SAVE_VERSION := 5
|
||||
|
||||
var save_version := SAVE_VERSION
|
||||
var campaign_id := ""
|
||||
@@ -27,6 +27,7 @@ var joined_officers: Array[String] = []
|
||||
var applied_post_battle_choices := {}
|
||||
var pending_post_battle_choice_scenario_id := ""
|
||||
var shop_purchases := {}
|
||||
var claimed_camp_conversation_effects := {}
|
||||
|
||||
|
||||
func load_campaign(path: String) -> bool:
|
||||
@@ -138,6 +139,7 @@ func start_new(scenario_id: String) -> void:
|
||||
applied_post_battle_choices.clear()
|
||||
pending_post_battle_choice_scenario_id = ""
|
||||
shop_purchases.clear()
|
||||
claimed_camp_conversation_effects.clear()
|
||||
for officer_id in initial_joined_officers:
|
||||
joined_officers.append(officer_id)
|
||||
|
||||
@@ -353,6 +355,57 @@ func get_shop_purchase_count(scenario_id: String, item_id: String) -> int:
|
||||
return int(shop_purchases[scenario_key].get(item_key, 0))
|
||||
|
||||
|
||||
func has_claimed_camp_conversation_effects(scenario_id: String, conversation_id: String) -> bool:
|
||||
var scenario_key := scenario_id.strip_edges()
|
||||
var conversation_key := conversation_id.strip_edges()
|
||||
if scenario_key.is_empty() or conversation_key.is_empty():
|
||||
return false
|
||||
if not claimed_camp_conversation_effects.has(scenario_key):
|
||||
return false
|
||||
if typeof(claimed_camp_conversation_effects[scenario_key]) != TYPE_DICTIONARY:
|
||||
return false
|
||||
return bool((claimed_camp_conversation_effects[scenario_key] as Dictionary).get(conversation_key, false))
|
||||
|
||||
|
||||
func try_claim_camp_conversation_effects(scenario_id: String, conversation: Dictionary) -> bool:
|
||||
var scenario_key := scenario_id.strip_edges()
|
||||
var conversation_key := str(conversation.get("id", "")).strip_edges()
|
||||
if scenario_key.is_empty() or conversation_key.is_empty():
|
||||
return false
|
||||
if completed_scenarios.has(scenario_key):
|
||||
return false
|
||||
if has_claimed_camp_conversation_effects(scenario_key, conversation_key):
|
||||
return false
|
||||
var effects_value = conversation.get("effects", [])
|
||||
if typeof(effects_value) != TYPE_ARRAY:
|
||||
return false
|
||||
var previous_inventory := inventory.duplicate(true)
|
||||
var previous_claimed_effects := claimed_camp_conversation_effects.duplicate(true)
|
||||
var applied := false
|
||||
for effect in effects_value:
|
||||
if typeof(effect) != TYPE_DICTIONARY:
|
||||
continue
|
||||
if str(effect.get("type", "")).strip_edges() != "grant_item":
|
||||
continue
|
||||
var item_key := str(effect.get("item_id", effect.get("id", ""))).strip_edges()
|
||||
if item_key.is_empty():
|
||||
continue
|
||||
var count := maxi(1, int(effect.get("count", 1)))
|
||||
inventory[item_key] = int(inventory.get(item_key, 0)) + count
|
||||
applied = true
|
||||
if not applied:
|
||||
return false
|
||||
if not claimed_camp_conversation_effects.has(scenario_key) or typeof(claimed_camp_conversation_effects[scenario_key]) != TYPE_DICTIONARY:
|
||||
claimed_camp_conversation_effects[scenario_key] = {}
|
||||
var scenario_claims: Dictionary = claimed_camp_conversation_effects[scenario_key]
|
||||
scenario_claims[conversation_key] = true
|
||||
if save_game():
|
||||
return true
|
||||
inventory = previous_inventory
|
||||
claimed_camp_conversation_effects = previous_claimed_effects
|
||||
return false
|
||||
|
||||
|
||||
func try_buy_item(item_id: String, price: int, scenario_id: String = "", stock_limit: int = -1) -> bool:
|
||||
if item_id.is_empty() or price <= 0 or gold < price:
|
||||
return false
|
||||
@@ -818,7 +871,8 @@ func to_dict() -> Dictionary:
|
||||
"joined_officers": joined_officers.duplicate(),
|
||||
"applied_post_battle_choices": applied_post_battle_choices.duplicate(true),
|
||||
"pending_post_battle_choice_scenario_id": pending_post_battle_choice_scenario_id,
|
||||
"shop_purchases": shop_purchases.duplicate(true)
|
||||
"shop_purchases": shop_purchases.duplicate(true),
|
||||
"claimed_camp_conversation_effects": claimed_camp_conversation_effects.duplicate(true)
|
||||
}
|
||||
|
||||
|
||||
@@ -835,6 +889,7 @@ func _apply_save_data(parsed: Dictionary) -> void:
|
||||
applied_post_battle_choices = _copy_dictionary(parsed.get("applied_post_battle_choices", {}))
|
||||
pending_post_battle_choice_scenario_id = str(parsed.get("pending_post_battle_choice_scenario_id", ""))
|
||||
shop_purchases = _copy_dictionary(parsed.get("shop_purchases", {}))
|
||||
claimed_camp_conversation_effects = _copy_dictionary(parsed.get("claimed_camp_conversation_effects", {}))
|
||||
joined_officers.clear()
|
||||
var saved_joined = parsed.get("joined_officers", initial_joined_officers)
|
||||
for officer_id in saved_joined:
|
||||
|
||||
@@ -3457,6 +3457,9 @@ func _format_camp_conversation_button_text(conversation: Dictionary) -> String:
|
||||
parts.append(speaker)
|
||||
if not summary.is_empty():
|
||||
parts.append(summary)
|
||||
var effects_text := _format_camp_conversation_effects_text(conversation)
|
||||
if not effects_text.is_empty():
|
||||
parts.append(effects_text)
|
||||
return _join_strings(parts, " - ")
|
||||
|
||||
|
||||
@@ -3468,9 +3471,78 @@ func _on_camp_conversation_pressed(conversation_id: String) -> void:
|
||||
_play_ui_confirm()
|
||||
_hide_talk_menu()
|
||||
_show_camp_dialogue(conversation.get("lines", []))
|
||||
_apply_camp_conversation_effects(conversation)
|
||||
_update_hud()
|
||||
|
||||
|
||||
func _format_camp_conversation_effects_text(conversation: Dictionary) -> String:
|
||||
var effects: Array = conversation.get("effects", [])
|
||||
if effects.is_empty():
|
||||
return ""
|
||||
var parts := []
|
||||
for effect in effects:
|
||||
if typeof(effect) != TYPE_DICTIONARY:
|
||||
continue
|
||||
if str(effect.get("type", "")) != "grant_item":
|
||||
continue
|
||||
var item_id := str(effect.get("item_id", ""))
|
||||
var item := state.get_item_def(item_id)
|
||||
if item.is_empty():
|
||||
continue
|
||||
var count := maxi(1, int(effect.get("count", 1)))
|
||||
var count_text := "" if count == 1 else " x%d" % count
|
||||
parts.append("Supply %s%s" % [str(item.get("name", item_id)), count_text])
|
||||
if parts.is_empty():
|
||||
return ""
|
||||
var conversation_id := str(conversation.get("id", ""))
|
||||
var claimed_text := "claimed" if campaign_state.has_claimed_camp_conversation_effects(active_scenario_id, conversation_id) else "available"
|
||||
return "%s (%s)" % [_join_strings(parts, ", "), claimed_text]
|
||||
|
||||
|
||||
func _apply_camp_conversation_effects(conversation: Dictionary) -> void:
|
||||
if battle_started or _is_prebattle_prep_locked():
|
||||
return
|
||||
var conversation_id := str(conversation.get("id", ""))
|
||||
if conversation_id.is_empty():
|
||||
return
|
||||
if campaign_state.has_claimed_camp_conversation_effects(active_scenario_id, conversation_id):
|
||||
return
|
||||
var effects: Array = conversation.get("effects", [])
|
||||
if effects.is_empty():
|
||||
return
|
||||
if campaign_state.try_claim_camp_conversation_effects(active_scenario_id, conversation):
|
||||
state.set_inventory_snapshot(campaign_state.get_inventory_snapshot())
|
||||
_on_log_added(_format_camp_conversation_effect_claim_text(conversation))
|
||||
if talk_menu != null and talk_menu.visible:
|
||||
_rebuild_talk_menu()
|
||||
return
|
||||
_play_ui_cancel()
|
||||
_on_log_added("Could not claim camp supplies.")
|
||||
|
||||
|
||||
func _format_camp_conversation_effect_claim_text(conversation: Dictionary) -> String:
|
||||
var messages := []
|
||||
var effects: Array = conversation.get("effects", [])
|
||||
for effect in effects:
|
||||
if typeof(effect) != TYPE_DICTIONARY:
|
||||
continue
|
||||
if str(effect.get("type", "")) != "grant_item":
|
||||
continue
|
||||
var message := str(effect.get("text", "")).strip_edges()
|
||||
if not message.is_empty():
|
||||
messages.append(message)
|
||||
continue
|
||||
var item_id := str(effect.get("item_id", ""))
|
||||
if item_id.is_empty():
|
||||
continue
|
||||
var count := maxi(1, int(effect.get("count", 1)))
|
||||
var count_text := "" if count == 1 else " x%d" % count
|
||||
messages.append("Camp supplies received: %s%s." % [_item_display_name(item_id), count_text])
|
||||
if messages.is_empty():
|
||||
return "Camp supplies received."
|
||||
return _join_strings(messages, " ")
|
||||
|
||||
|
||||
func _camp_conversation_by_id(conversation_id: String) -> Dictionary:
|
||||
for conversation in _camp_conversation_entries():
|
||||
if str(conversation.get("id", "")) == conversation_id:
|
||||
@@ -4132,7 +4204,7 @@ func _apply_item_button_icon(button: Button, item: Dictionary) -> void:
|
||||
return
|
||||
button.icon = icon
|
||||
button.expand_icon = true
|
||||
button.icon_max_width = 30
|
||||
button.add_theme_constant_override("icon_max_width", 30)
|
||||
|
||||
|
||||
func _on_shop_item_pressed(item_id: String) -> void:
|
||||
|
||||
Reference in New Issue
Block a user