fix(runtime): enforce frozen guild response IDs
This commit is contained in:
@@ -2,6 +2,7 @@ extends Control
|
||||
|
||||
const FirstSessionStateScript = preload("res://domain/p9_1/session_state.gd")
|
||||
const FirstSessionServiceScript = preload("res://domain/p9_1/session_service.gd")
|
||||
const P91ContractsScript = preload("res://domain/p9_1/contracts.gd")
|
||||
const PresentationSettingsScript = preload("res://presentation/presentation_settings.gd")
|
||||
const BattleClockScript = preload("res://presentation/battle_clock.gd")
|
||||
const AnimationAdapterScript = preload("res://presentation/animation_adapter.gd")
|
||||
@@ -264,8 +265,8 @@ var second_result_time: float:
|
||||
get: return battle_clock_owner.second_result_time
|
||||
set(value): battle_clock_owner.second_result_time = value
|
||||
var guild_choice: String:
|
||||
get: return session_state.guild_choice
|
||||
set(value): session_state.guild_choice = value
|
||||
get: return legacy_guild_choice(session_state.guild_response)
|
||||
set(value): set_legacy_guild_choice(value)
|
||||
var guild_committed: bool:
|
||||
get: return session_state.guild_committed
|
||||
set(value): session_state.guild_committed = value
|
||||
@@ -2263,12 +2264,32 @@ func open_guild_return() -> void:
|
||||
|
||||
|
||||
func choose_guild_option(id: String) -> void:
|
||||
if not session_service.choose_guild_response(id)["ok"]:
|
||||
if not session_service.choose_guild_response(domain_guild_response(id))["ok"]:
|
||||
return
|
||||
play_cue("select")
|
||||
render()
|
||||
|
||||
|
||||
func domain_guild_response(id: String) -> String:
|
||||
match id:
|
||||
"retain_item": return "retain_loan"
|
||||
"recruit_rear": return "add_recruit"
|
||||
return id
|
||||
|
||||
|
||||
func legacy_guild_choice(id: String) -> String:
|
||||
match id:
|
||||
"retain_loan": return "retain_item"
|
||||
"add_recruit": return "recruit_rear"
|
||||
return id
|
||||
|
||||
|
||||
func set_legacy_guild_choice(id: String) -> void:
|
||||
var response := domain_guild_response(id)
|
||||
if response.is_empty() or response in P91ContractsScript.GUILD_RESPONSE_IDS:
|
||||
session_state.guild_response = response
|
||||
|
||||
|
||||
func begin_third_battle() -> void:
|
||||
if not session_service.commit_guild_response()["ok"]:
|
||||
return
|
||||
|
||||
@@ -54,7 +54,7 @@ const ENCOUNTER_5: StringName = &"battle_5"
|
||||
const AUTO_FORMATION_ORDER: Array[String] = ["Hearthguard", "Wayrunner", "Farstring", "Kindhand"]
|
||||
const MEMBER_IDS: Array[String] = ["Hearthguard", "Wayrunner", "Farstring", "Kindhand"]
|
||||
const ADAPTATION_IDS: Array[String] = ["EQ-002", "EQ-061"]
|
||||
const GUILD_IDS: Array[String] = ["retain_item", "recruit_rear"]
|
||||
const GUILD_RESPONSE_IDS: Array[String] = ["retain_loan", "add_recruit"]
|
||||
const ROUTE_IDS: Array[String] = ["R6-01", "R6-02", "R6-03"]
|
||||
|
||||
const LEGACY_SCREEN_BY_PAGE := {
|
||||
|
||||
@@ -88,7 +88,7 @@ func open_adaptation() -> Dictionary:
|
||||
func open_guild_response() -> Dictionary:
|
||||
if state.screen != Contracts.SCREEN_RESULT_2 or not state.adaptation_committed:
|
||||
return _reject(Contracts.WRONG_SCREEN)
|
||||
state.guild_choice = ""
|
||||
state.guild_response = ""
|
||||
state.guild_committed = false
|
||||
state.retained_item = ""
|
||||
state.added_rear = ""
|
||||
@@ -159,12 +159,12 @@ func choose_guild_response(response_id: String) -> Dictionary:
|
||||
return _reject(Contracts.WRONG_SCREEN)
|
||||
if state.guild_committed:
|
||||
return _reject(Contracts.ALREADY_COMMITTED)
|
||||
if response_id not in Contracts.GUILD_IDS:
|
||||
if response_id not in Contracts.GUILD_RESPONSE_IDS:
|
||||
return _reject(Contracts.INVALID_ID)
|
||||
var cost := 12 if response_id == "retain_item" else 14
|
||||
var cost := 12 if response_id == "retain_loan" else 14
|
||||
if state.coin < cost:
|
||||
return _reject(Contracts.INSUFFICIENT_COIN)
|
||||
state.guild_choice = response_id
|
||||
state.guild_response = response_id
|
||||
return _success([_selection_event(&"guild_response", response_id)])
|
||||
|
||||
func commit_guild_response() -> Dictionary:
|
||||
@@ -172,14 +172,14 @@ func commit_guild_response() -> Dictionary:
|
||||
return _reject(Contracts.WRONG_SCREEN)
|
||||
if state.guild_committed:
|
||||
return _reject(Contracts.ALREADY_COMMITTED)
|
||||
if state.guild_choice not in Contracts.GUILD_IDS:
|
||||
if state.guild_response not in Contracts.GUILD_RESPONSE_IDS:
|
||||
return _reject(Contracts.SELECTION_REQUIRED)
|
||||
var cost := 12 if state.guild_choice == "retain_item" else 14
|
||||
var cost := 12 if state.guild_response == "retain_loan" else 14
|
||||
if state.coin < cost:
|
||||
return _reject(Contracts.INSUFFICIENT_COIN)
|
||||
state.guild_committed = true
|
||||
state.coin -= cost
|
||||
if state.guild_choice == "retain_item":
|
||||
if state.guild_response == "retain_loan":
|
||||
state.retained_item = state.adaptation_choice
|
||||
state.added_rear = ""
|
||||
else:
|
||||
@@ -190,7 +190,7 @@ func commit_guild_response() -> Dictionary:
|
||||
state.front_hp = 100
|
||||
state.enemy_hp = 130
|
||||
state.phase_impact_committed.clear()
|
||||
return _change_screen(Contracts.SCREEN_BATTLE_3, &"commit_guild_response", [_transaction_event(&"guild_response", state.guild_choice, -cost)])
|
||||
return _change_screen(Contracts.SCREEN_BATTLE_3, &"commit_guild_response", [_transaction_event(&"guild_response", state.guild_response, -cost)])
|
||||
|
||||
func choose_route(route_id: String) -> Dictionary:
|
||||
if state.screen != Contracts.SCREEN_ROUTE_BOARD:
|
||||
|
||||
@@ -25,7 +25,12 @@ var coin := 0
|
||||
var first_reward_committed := false
|
||||
var adaptation_choice := ""
|
||||
var adaptation_committed := false
|
||||
var guild_choice := ""
|
||||
var guild_response: String:
|
||||
get: return _guild_response
|
||||
set(value):
|
||||
if value.is_empty() or value in Contracts.GUILD_RESPONSE_IDS:
|
||||
_guild_response = value
|
||||
var _guild_response := ""
|
||||
var guild_committed := false
|
||||
var retained_item := ""
|
||||
var added_rear := ""
|
||||
@@ -48,6 +53,8 @@ func compat_patch(fields: Dictionary) -> bool:
|
||||
for field in fields:
|
||||
if field not in _compat_patch_fields():
|
||||
return false
|
||||
if field == &"guild_response" and not String(fields[field]).is_empty() and fields[field] not in Contracts.GUILD_RESPONSE_IDS:
|
||||
return false
|
||||
for field in fields:
|
||||
set(field, fields[field])
|
||||
return invariants_hold()
|
||||
@@ -59,7 +66,7 @@ func _compat_patch_fields() -> Array[StringName]:
|
||||
&"battle_playing", &"front_hp", &"rear_hp", &"enemy_hp", &"guard_events",
|
||||
&"rear_events", &"victory_events", &"phase_impact_committed", &"coin",
|
||||
&"first_reward_committed", &"adaptation_choice", &"adaptation_committed",
|
||||
&"guild_choice", &"guild_committed", &"retained_item", &"added_rear",
|
||||
&"guild_response", &"guild_committed", &"retained_item", &"added_rear",
|
||||
&"route_choice", &"route_committed", &"route_reward_committed", &"training_choice",
|
||||
&"growth_member_id", &"training_committed", &"trained_member", &"trained_member_id",
|
||||
&"fifth_reward_committed",
|
||||
@@ -92,7 +99,7 @@ func reset_transient() -> void:
|
||||
first_reward_committed = false
|
||||
adaptation_choice = ""
|
||||
adaptation_committed = false
|
||||
guild_choice = ""
|
||||
guild_response = ""
|
||||
guild_committed = false
|
||||
retained_item = ""
|
||||
added_rear = ""
|
||||
@@ -147,7 +154,7 @@ func snapshot() -> Dictionary:
|
||||
"resources": {"coin": coin},
|
||||
"decisions": {
|
||||
"adaptation": adaptation_choice,
|
||||
"guild_response": guild_choice,
|
||||
"guild_response": guild_response,
|
||||
"route": route_choice,
|
||||
"growth_member": trained_member_id,
|
||||
},
|
||||
@@ -196,6 +203,8 @@ func invariants_hold() -> bool:
|
||||
return false
|
||||
if formation_commit_count > 1:
|
||||
return false
|
||||
if not guild_response.is_empty() and guild_response not in Contracts.GUILD_RESPONSE_IDS:
|
||||
return false
|
||||
if front_hp < 0 or rear_hp < 0 or enemy_hp < 0 or coin < 0:
|
||||
return false
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user