Files
aetherbound-guild/runtime/entry/contract_choice_page_controller.gd
T

112 lines
4.5 KiB
GDScript

class_name ABGContractChoicePageController
extends RefCounted
const GuildContractService = preload("res://entry/guild_contract_service.gd")
## UI-independent Contract Choice view-data assembly.
## Contract creation remains owned by GuildContractService; this controller only
## describes the stable choice surface and whether the Confirm boundary may be
## exposed.
func snapshot(company: Dictionary, selected_difficulty := "standard", locale := "zh_CN") -> Dictionary:
if company.is_empty():
return {"ok": false, "code": "COMPANY_REQUIRED"}
var active_contract = company.get("active_contract", {})
if not active_contract is Dictionary:
return {"ok": false, "code": "COMPANY_INVALID"}
if not Dictionary(active_contract).is_empty():
return {"ok": false, "code": "CONTRACT_ALREADY_ACTIVE"}
var normalized := normalize_difficulty(selected_difficulty)
var catalog := _difficulty_catalog(locale, normalized)
var recruits := _copy_array(company.get("owned_recruits", []))
var company_data := {
"company_id": String(company.get("company_id", "")),
"owned_count": recruits.size(),
"recruits": recruits,
}
var creation_facts := {
"contract_id": GuildContractService.FIRST_CONTRACT_ID,
"route_id": "windglass_verge",
"route_title": _tr("风镜初渡", "FIRST WINDGLASS CROSSING", locale),
"route_copy": _tr("穿越悬浮风镜,建立公会的第一条安全通路。", "Cross the suspended windglass and establish the Guild's first safe route.", locale),
"starting_coin": GuildContractService.STARTING_COIN,
"line_capacity": GuildContractService.STARTING_LINE_CAPACITY,
"market_counts": {"recruit": 3, "equipment": 4, "battle": 3},
}
return {
"ok": true,
"page_id": "contract_choice",
"company": company_data,
"contract": creation_facts,
"difficulties": catalog,
"selected_difficulty": normalized,
"confirm": {
"eligible": true,
"reason": "ready",
},
"locale": String(locale),
}
func normalize_difficulty(value: String) -> String:
return value if value in GuildContractService.DIFFICULTIES else "standard"
func is_valid_difficulty(value: String) -> bool:
return value in GuildContractService.DIFFICULTIES
func confirm_state(company: Dictionary, selected_difficulty := "standard") -> Dictionary:
if company.is_empty():
return {"eligible": false, "reason": "company_required"}
var active_contract = company.get("active_contract", {})
if not active_contract is Dictionary:
return {"eligible": false, "reason": "company_invalid"}
if not Dictionary(active_contract).is_empty():
return {"eligible": false, "reason": "contract_already_active"}
if not is_valid_difficulty(selected_difficulty):
return {"eligible": false, "reason": "invalid_difficulty"}
return {"eligible": true, "reason": "ready"}
func _difficulty_catalog(locale: String, selected: String) -> Array[Dictionary]:
var result: Array[Dictionary] = []
for difficulty in GuildContractService.DIFFICULTIES:
var id := String(difficulty)
result.append({
"id": id,
"name": _difficulty_name(id, locale),
"copy": _difficulty_copy(id, locale),
"selected": id == selected,
})
return result
func _difficulty_name(value: String, locale: String) -> String:
match value:
"wayfinder": return _tr("引路", "Wayfinder", locale)
"stormbound": return _tr("风暴", "Stormbound", locale)
"iron_oath": return _tr("铁誓", "Iron Oath", locale)
return _tr("标准", "Standard", locale)
func _difficulty_copy(value: String, locale: String) -> String:
match value:
"wayfinder": return _tr("较宽容的敌方参数;所有系统、进度与记录仍然可用。", "More forgiving enemy parameters; all systems, progression and Records remain available.", locale)
"stormbound": return _tr("更高压力与回报;目标规则和远征团所有权不变。", "Higher pressure and rewards; target rules and Company ownership remain unchanged.", locale)
"iron_oath": return _tr("最高压力;只改变敌人与回报参数,不隐藏规则。", "Highest pressure; only enemy and reward parameters change, never hidden rules.", locale)
return _tr("完整的标准平衡;不需要额外永久战力。", "The complete standard balance; no extra permanent power is required.", locale)
func _copy_array(value) -> Array:
var result: Array = []
if value is Array:
for item in value:
result.append(item.duplicate(true) if item is Dictionary or item is Array else item)
return result
func _tr(zh: String, en: String, locale: String) -> String:
return en if String(locale).to_lower().begins_with("en") else zh