Add camp talk supply claims

This commit is contained in:
2026-06-18 18:06:20 +09:00
parent 2816c07647
commit 87e75ea018
11 changed files with 404 additions and 11 deletions

View File

@@ -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

View File

@@ -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: