class_name CostRules extends RefCounted const ITEM_ID_GEM := 105001 const ITEM_ID_GOLD := 105002 const ITEM_ID_STONE := 201000 const ITEM_ID_STEEL := 201001 static func parse_cost_string(cost_text: String) -> Array[Dictionary]: var costs: Array[Dictionary] = [] for raw_part in cost_text.split(",", false): var part := raw_part.strip_edges() if part.is_empty(): continue var pair := part.split(":", false) if pair.size() != 2: continue var item_id := int(pair[0]) var count := int(pair[1]) if item_id > 0 and count > 0: costs.append({"item_id": item_id, "count": count}) return costs static func aggregate_costs(costs: Array[Dictionary]) -> Dictionary: var result := {} for cost in costs: var item_id := int(cost.get("item_id", 0)) var count := int(cost.get("count", 0)) if item_id <= 0 or count <= 0: continue result[item_id] = int(result.get(item_id, 0)) + count return result static func get_owned_amount(item_id: int, player_data: Dictionary, warehouse_items: Array[Dictionary]) -> int: match item_id: ITEM_ID_GEM: return int(player_data.get("gem", 0)) ITEM_ID_GOLD: return int(player_data.get("gold", 0)) ITEM_ID_STONE: return int(player_data.get("stone", 0)) ITEM_ID_STEEL: return int(player_data.get("steel", 0)) _: for item in warehouse_items: if int(item.get("item_id", 0)) == item_id: return int(item.get("num", item.get("number", 0))) return 0 static func has_costs(cost_text: String, player_data: Dictionary, warehouse_items: Array[Dictionary]) -> bool: var aggregated := aggregate_costs(parse_cost_string(cost_text)) for item_id in aggregated.keys(): if get_owned_amount(int(item_id), player_data, warehouse_items) < int(aggregated[item_id]): return false return true