483 lines
20 KiB
GDScript
483 lines
20 KiB
GDScript
extends Control
|
|
|
|
const FacadeScript = preload("res://compat/p9_0_root_facade.gd")
|
|
const P92BattleServiceScript = preload("res://domain/p9_2/battle_service.gd")
|
|
const P92BattlePresenterScript = preload("res://presentation/p9_2_battle_presenter.gd")
|
|
const P93CoreLoopControllerScript = preload("res://p9_3/core_loop_controller.gd")
|
|
const P97RuntimeControllerScript = preload("res://p9_7/runtime_controller.gd")
|
|
const P97SaveServiceScript = preload("res://p9_7/save_service.gd")
|
|
const AppPage = FacadeScript.AppPage
|
|
const ANIMATION_SPECS = FacadeScript.ANIMATION_SPECS
|
|
const BATTLE_PHASE_DURATIONS = FacadeScript.BATTLE_PHASE_DURATIONS
|
|
const BATTLE_FEEDBACK_DURATION = FacadeScript.BATTLE_FEEDBACK_DURATION
|
|
|
|
var facade := FacadeScript.new()
|
|
var authoritative_battle_service := P92BattleServiceScript.new()
|
|
var authoritative_battle_presenter
|
|
var authoritative_battle_active := false
|
|
var authoritative_auto_advance := true
|
|
var authoritative_tick_accumulator := 0.0
|
|
var authoritative_speed_multiplier := 1
|
|
var authoritative_inspect_open := false
|
|
var authoritative_inspect_events: Array[Dictionary] = []
|
|
var authoritative_retreat_receipt: Dictionary = {}
|
|
var authoritative_last_command_code := ""
|
|
var authoritative_last_events: Array[Dictionary] = []
|
|
@export var p93_experience_enabled := true
|
|
var p93_experience
|
|
var p97_experience
|
|
|
|
var active_battle_feedback:
|
|
get: return facade.active_battle_feedback
|
|
set(value): facade.active_battle_feedback = value
|
|
var adaptation_choice:
|
|
get: return facade.adaptation_choice
|
|
set(value): facade.adaptation_choice = value
|
|
var adaptation_committed:
|
|
get: return facade.adaptation_committed
|
|
set(value): facade.adaptation_committed = value
|
|
var added_rear:
|
|
get: return facade.added_rear
|
|
set(value): facade.added_rear = value
|
|
var audio_enabled:
|
|
get: return facade.audio_enabled
|
|
set(value): facade.audio_enabled = value
|
|
var audio_player:
|
|
get: return facade.audio_player
|
|
set(value): facade.audio_player = value
|
|
var auto_boot:
|
|
get: return facade.auto_boot
|
|
set(value): facade.auto_boot = value
|
|
var battle_clock:
|
|
get: return facade.battle_clock
|
|
set(value): facade.battle_clock = value
|
|
var battle_feedback_clock:
|
|
get: return facade.battle_feedback_clock
|
|
set(value): facade.battle_feedback_clock = value
|
|
var battle_feedback_history:
|
|
get: return facade.battle_feedback_history
|
|
set(value): facade.battle_feedback_history = value
|
|
var battle_feedback_origin:
|
|
get: return facade.battle_feedback_origin
|
|
set(value): facade.battle_feedback_origin = value
|
|
var battle_phase:
|
|
get: return facade.battle_phase
|
|
set(value): facade.battle_phase = value
|
|
var battle_playing:
|
|
get: return facade.battle_playing
|
|
set(value): facade.battle_playing = value
|
|
var boot_failed_path:
|
|
get: return facade.boot_failed_path
|
|
set(value): facade.boot_failed_path = value
|
|
var boot_index:
|
|
get: return facade.boot_index
|
|
set(value): facade.boot_index = value
|
|
var boot_paths_override:
|
|
get: return facade.boot_paths_override
|
|
set(value): facade.boot_paths_override = value
|
|
var boot_verified:
|
|
get: return facade.boot_verified
|
|
set(value): facade.boot_verified = value
|
|
var coin:
|
|
get: return facade.coin
|
|
set(value): facade.coin = value
|
|
var enemy_hp:
|
|
get: return facade.enemy_hp
|
|
set(value): facade.enemy_hp = value
|
|
var enemy_sprite:
|
|
get: return facade.enemy_sprite
|
|
set(value): facade.enemy_sprite = value
|
|
var fifth_battle_elapsed:
|
|
get: return facade.fifth_battle_elapsed
|
|
set(value): facade.fifth_battle_elapsed = value
|
|
var fifth_reward_committed:
|
|
get: return facade.fifth_reward_committed
|
|
set(value): facade.fifth_reward_committed = value
|
|
var first_reward_committed:
|
|
get: return facade.first_reward_committed
|
|
set(value): facade.first_reward_committed = value
|
|
var formation_commit_count:
|
|
get: return facade.formation_commit_count
|
|
set(value): facade.formation_commit_count = value
|
|
var fourth_battle_elapsed:
|
|
get: return facade.fourth_battle_elapsed
|
|
set(value): facade.fourth_battle_elapsed = value
|
|
var fourth_result_time:
|
|
get: return facade.fourth_result_time
|
|
set(value): facade.fourth_result_time = value
|
|
var front_choice:
|
|
get: return facade.front_choice
|
|
set(value): facade.front_choice = value
|
|
var front_hp:
|
|
get: return facade.front_hp
|
|
set(value): facade.front_hp = value
|
|
var front_sprite:
|
|
get: return facade.front_sprite
|
|
set(value): facade.front_sprite = value
|
|
var guard_events:
|
|
get: return facade.guard_events
|
|
set(value): facade.guard_events = value
|
|
var guild_choice:
|
|
get: return facade.guild_choice
|
|
set(value): facade.guild_choice = value
|
|
var guild_committed:
|
|
get: return facade.guild_committed
|
|
set(value): facade.guild_committed = value
|
|
var locale:
|
|
get: return facade.locale
|
|
set(value): facade.locale = value
|
|
var muted:
|
|
get: return facade.muted
|
|
set(value): facade.muted = value
|
|
var page:
|
|
get: return facade.page
|
|
set(value): facade.page = value
|
|
var phase_impact_committed:
|
|
get: return facade.phase_impact_committed
|
|
set(value): facade.phase_impact_committed = value
|
|
var rear_choice:
|
|
get: return facade.rear_choice
|
|
set(value): facade.rear_choice = value
|
|
var rear_events:
|
|
get: return facade.rear_events
|
|
set(value): facade.rear_events = value
|
|
var rear_hp:
|
|
get: return facade.rear_hp
|
|
set(value): facade.rear_hp = value
|
|
var rear_sprite:
|
|
get: return facade.rear_sprite
|
|
set(value): facade.rear_sprite = value
|
|
var reduced_motion:
|
|
get: return facade.reduced_motion
|
|
set(value): facade.reduced_motion = value
|
|
var restart_confirmation:
|
|
get: return facade.restart_confirmation
|
|
set(value): facade.restart_confirmation = value
|
|
var retained_item:
|
|
get: return facade.retained_item
|
|
set(value): facade.retained_item = value
|
|
var route_choice:
|
|
get: return facade.route_choice
|
|
set(value): facade.route_choice = value
|
|
var route_committed:
|
|
get: return facade.route_committed
|
|
set(value): facade.route_committed = value
|
|
var route_reward_committed:
|
|
get: return facade.route_reward_committed
|
|
set(value): facade.route_reward_committed = value
|
|
var second_battle_elapsed:
|
|
get: return facade.second_battle_elapsed
|
|
set(value): facade.second_battle_elapsed = value
|
|
var second_result_time:
|
|
get: return facade.second_result_time
|
|
set(value): facade.second_result_time = value
|
|
var selected_recruits:
|
|
get: return facade.selected_recruits
|
|
set(value): facade.selected_recruits = value
|
|
var sfx_playback:
|
|
get: return facade.sfx_playback
|
|
set(value): facade.sfx_playback = value
|
|
var text_scale:
|
|
get: return facade.text_scale
|
|
set(value): facade.text_scale = value
|
|
var third_battle_elapsed:
|
|
get: return facade.third_battle_elapsed
|
|
set(value): facade.third_battle_elapsed = value
|
|
var third_result_time:
|
|
get: return facade.third_result_time
|
|
set(value): facade.third_result_time = value
|
|
var trained_member:
|
|
get: return facade.trained_member
|
|
set(value): facade.trained_member = value
|
|
var training_choice:
|
|
get: return facade.training_choice
|
|
set(value): facade.training_choice = value
|
|
var training_committed:
|
|
get: return facade.training_committed
|
|
set(value): facade.training_committed = value
|
|
var victory_events:
|
|
get: return facade.victory_events
|
|
set(value): facade.victory_events = value
|
|
|
|
func _ready() -> void:
|
|
var p97_resume_snapshot := _p97_resume_snapshot()
|
|
var should_start_p97: bool = auto_boot and p93_experience_enabled and not p97_resume_snapshot.is_empty()
|
|
var should_start_p93: bool = auto_boot and p93_experience_enabled and not should_start_p97
|
|
if should_start_p93 or should_start_p97:
|
|
facade.auto_boot = false
|
|
facade.name = "RuntimeFacade"
|
|
facade.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
add_child(facade)
|
|
theme = facade.theme
|
|
facade.authoritative_battle_requested.connect(start_authoritative_battle)
|
|
authoritative_battle_presenter = P92BattlePresenterScript.new(self)
|
|
if should_start_p93:
|
|
call_deferred("start_p93_experience")
|
|
elif should_start_p97:
|
|
call_deferred("start_p97_experience", p97_resume_snapshot)
|
|
|
|
func _get(property: StringName) -> Variant:
|
|
return facade.get(property)
|
|
|
|
func _set(property: StringName, value: Variant) -> bool:
|
|
facade.set(property, value)
|
|
return true
|
|
|
|
func _get_property_list() -> Array[Dictionary]:
|
|
var result: Array[Dictionary] = []
|
|
for property in facade.get_property_list():
|
|
var name: StringName = property["name"]
|
|
if name in [&"script", &"name", &"owner", &"process_mode", &"process_priority", &"process_physics_priority"]:
|
|
continue
|
|
result.append({
|
|
"name": name,
|
|
"type": property["type"],
|
|
"hint": property.get("hint", PROPERTY_HINT_NONE),
|
|
"hint_string": property.get("hint_string", ""),
|
|
"usage": PROPERTY_USAGE_DEFAULT,
|
|
})
|
|
return result
|
|
|
|
func _process(delta: float) -> void:
|
|
if is_instance_valid(p93_experience) or is_instance_valid(p97_experience):
|
|
return
|
|
if authoritative_battle_active:
|
|
_process_authoritative_battle(delta)
|
|
return
|
|
facade._process(delta)
|
|
|
|
func start_p93_experience() -> void:
|
|
if is_instance_valid(p93_experience) or is_instance_valid(p97_experience):
|
|
return
|
|
facade.visible = false
|
|
p93_experience = P93CoreLoopControllerScript.new()
|
|
p93_experience.name = "P93CoreLoop"
|
|
p93_experience.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
p93_experience.windglass_market_requested.connect(start_p97_experience)
|
|
add_child(p93_experience)
|
|
|
|
|
|
func start_p97_experience(snapshot: Dictionary) -> void:
|
|
if snapshot.is_empty() or is_instance_valid(p97_experience):
|
|
return
|
|
var source_locale := facade.locale
|
|
var source_text_scale := facade.text_scale
|
|
var source_reduced_motion := facade.reduced_motion
|
|
var source_muted := facade.muted
|
|
var source_low_power := false
|
|
if is_instance_valid(p93_experience):
|
|
source_locale = p93_experience.locale
|
|
source_text_scale = p93_experience.text_scale
|
|
source_reduced_motion = p93_experience.reduced_motion
|
|
source_muted = p93_experience.muted
|
|
source_low_power = p93_experience.low_power
|
|
p93_experience.visible = false
|
|
p93_experience.process_mode = Node.PROCESS_MODE_DISABLED
|
|
p93_experience.queue_free()
|
|
p93_experience = null
|
|
facade.visible = false
|
|
p97_experience = P97RuntimeControllerScript.new()
|
|
p97_experience.name = "P97WindglassRuntime"
|
|
p97_experience.locale = source_locale
|
|
p97_experience.text_scale = source_text_scale
|
|
p97_experience.reduced_motion = source_reduced_motion
|
|
p97_experience.muted = source_muted
|
|
p97_experience.low_power = source_low_power
|
|
p97_experience.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
p97_experience.configure_entry(snapshot)
|
|
add_child(p97_experience)
|
|
|
|
|
|
func _p97_resume_snapshot() -> Dictionary:
|
|
if not auto_boot or not p93_experience_enabled:
|
|
return {}
|
|
var loaded: Dictionary = P97SaveServiceScript.new().load_snapshot()
|
|
if not loaded.ok or int(loaded.get("source_version", -1)) != 2:
|
|
return {}
|
|
return Dictionary(loaded.snapshot).duplicate(true)
|
|
|
|
func start_authoritative_battle() -> bool:
|
|
var members: Array[String] = facade.session_state.current_member_ids()
|
|
if members.is_empty():
|
|
return false
|
|
var starting_hp: Dictionary = {}
|
|
for member_id in members:
|
|
starting_hp[member_id] = facade.session_state.member_health(member_id)
|
|
var result: Dictionary = authoritative_battle_service.start_fixture(members, 9201, starting_hp)
|
|
if not result.ok:
|
|
return false
|
|
authoritative_battle_active = true
|
|
authoritative_tick_accumulator = 0.0
|
|
authoritative_speed_multiplier = 1
|
|
authoritative_inspect_open = false
|
|
authoritative_inspect_events.clear()
|
|
authoritative_retreat_receipt.clear()
|
|
authoritative_last_command_code = ""
|
|
authoritative_last_events.clear()
|
|
for event in result.events:
|
|
authoritative_last_events.append(Dictionary(event).duplicate(true))
|
|
facade.visible = false
|
|
authoritative_battle_presenter.render(authoritative_battle_service.state.current_snapshot(), authoritative_last_events)
|
|
return true
|
|
|
|
func advance_authoritative_ticks(ticks: int) -> Dictionary:
|
|
if not authoritative_battle_active:
|
|
return {"ok": false, "code": "inactive", "events": []}
|
|
var result: Dictionary = authoritative_battle_service.advance_ticks(ticks)
|
|
return _accept_authoritative_result(result)
|
|
|
|
func toggle_authoritative_pause() -> Dictionary:
|
|
if not authoritative_battle_active:
|
|
return {"ok": false, "code": "inactive", "events": []}
|
|
var result: Dictionary = authoritative_battle_service.set_paused(not authoritative_battle_service.state.paused)
|
|
return _accept_authoritative_result(result)
|
|
|
|
func set_authoritative_speed(multiplier: int) -> Dictionary:
|
|
if not authoritative_battle_active:
|
|
return {"ok": false, "code": "inactive"}
|
|
if multiplier not in [1, 2]:
|
|
return {"ok": false, "code": "invalid_speed"}
|
|
authoritative_speed_multiplier = multiplier
|
|
authoritative_tick_accumulator = 0.0
|
|
authoritative_last_command_code = "speed_%dx" % multiplier
|
|
authoritative_battle_presenter.render(authoritative_battle_service.state.current_snapshot(), authoritative_last_events)
|
|
return {"ok": true, "code": authoritative_last_command_code, "speed": multiplier}
|
|
|
|
func toggle_authoritative_inspect() -> Dictionary:
|
|
if not authoritative_battle_active:
|
|
return {"ok": false, "code": "inactive"}
|
|
var result: Dictionary = authoritative_battle_service.inspect()
|
|
if not result.ok:
|
|
return result
|
|
authoritative_inspect_open = not authoritative_inspect_open
|
|
authoritative_inspect_events.clear()
|
|
for event in result.events:
|
|
authoritative_inspect_events.append(Dictionary(event).duplicate(true))
|
|
authoritative_last_command_code = "inspect_open" if authoritative_inspect_open else "inspect_closed"
|
|
authoritative_battle_presenter.render(result.snapshot, authoritative_last_events)
|
|
return {"ok": true, "code": authoritative_last_command_code, "snapshot": result.snapshot, "events": authoritative_inspect_events.duplicate(true)}
|
|
|
|
func request_authoritative_retreat() -> Dictionary:
|
|
if not authoritative_battle_active:
|
|
return {"ok": false, "code": "inactive", "events": []}
|
|
var result: Dictionary = authoritative_battle_service.request_retreat()
|
|
return _accept_authoritative_result(result)
|
|
|
|
func retry_authoritative_battle() -> bool:
|
|
if not authoritative_battle_active or not authoritative_battle_service.state.terminal:
|
|
return false
|
|
return start_authoritative_battle()
|
|
|
|
func exit_authoritative_battle_to_home() -> void:
|
|
if not authoritative_battle_active:
|
|
return
|
|
authoritative_battle_active = false
|
|
authoritative_auto_advance = true
|
|
authoritative_tick_accumulator = 0.0
|
|
authoritative_speed_multiplier = 1
|
|
authoritative_inspect_open = false
|
|
authoritative_inspect_events.clear()
|
|
authoritative_retreat_receipt.clear()
|
|
authoritative_last_command_code = "home"
|
|
authoritative_last_events.clear()
|
|
authoritative_battle_presenter.cleanup()
|
|
facade.visible = true
|
|
facade.go_home()
|
|
|
|
func _accept_authoritative_result(result: Dictionary) -> Dictionary:
|
|
authoritative_last_command_code = String(result.get("code", ""))
|
|
authoritative_last_events.clear()
|
|
for event in result.get("events", []):
|
|
authoritative_last_events.append(Dictionary(event).duplicate(true))
|
|
if String(event.get("kind", "")) == "retreat_started":
|
|
authoritative_retreat_receipt = {
|
|
"tick": int(event.get("tick", -1)),
|
|
"resolves_at": int(event.get("resolves_at", -1)),
|
|
}
|
|
if result.has("snapshot"):
|
|
authoritative_battle_presenter.render(result.snapshot, authoritative_last_events)
|
|
return result
|
|
|
|
func _process_authoritative_battle(delta: float) -> void:
|
|
if authoritative_battle_service.state.terminal:
|
|
return
|
|
if not authoritative_auto_advance:
|
|
return
|
|
if authoritative_battle_service.state.paused:
|
|
return
|
|
authoritative_tick_accumulator += maxf(0.0, delta) * float(authoritative_speed_multiplier)
|
|
var ticks := int(floor(authoritative_tick_accumulator / 0.1))
|
|
if ticks <= 0:
|
|
return
|
|
authoritative_tick_accumulator -= float(ticks) * 0.1
|
|
advance_authoritative_ticks(ticks)
|
|
func active_boot_paths() -> Array[String]: return facade.active_boot_paths()
|
|
func adaptation_effect(id: String) -> String: return facade.adaptation_effect(id)
|
|
func adaptation_name(id: String) -> String: return facade.adaptation_name(id)
|
|
func advance_battle_phase() -> void: facade.advance_battle_phase()
|
|
func animation_frame_index(character: String, state: String, elapsed: float) -> int: return facade.animation_frame_index(character, state, elapsed)
|
|
func animation_texture(character: String, state: String, elapsed: float) -> Texture2D: return facade.animation_texture(character, state, elapsed)
|
|
func assign_automatic_formation() -> bool: return facade.assign_automatic_formation()
|
|
func back_to_main_menu() -> void: facade.back_to_main_menu()
|
|
func begin_first_battle() -> void: facade.begin_first_battle()
|
|
func begin_second_battle() -> void: facade.begin_second_battle()
|
|
func begin_third_battle() -> void: facade.begin_third_battle()
|
|
func cancel_restart() -> void: facade.cancel_restart()
|
|
func cancel_route_review() -> void: facade.cancel_route_review()
|
|
func cancel_training_review() -> void: facade.cancel_training_review()
|
|
func candidate_name(profession: String) -> String: return facade.candidate_name(profession)
|
|
func choose_adaptation(id: String) -> void: facade.choose_adaptation(id)
|
|
func choose_candidate(profession: String) -> void: facade.choose_candidate(profession)
|
|
func choose_guild_option(id: String) -> void: facade.choose_guild_option(id)
|
|
func choose_route(id: String) -> void: facade.choose_route(id)
|
|
func choose_training(slot: String) -> void: facade.choose_training(slot)
|
|
func clear_experience() -> void: facade.clear_experience()
|
|
func commit_fifth_phase_impact(phase: int, refresh_runtime := true) -> void: facade.commit_fifth_phase_impact(phase, refresh_runtime)
|
|
func commit_fifth_reward() -> void: facade.commit_fifth_reward()
|
|
func commit_first_victory_reward() -> void: facade.commit_first_victory_reward()
|
|
func commit_formation() -> void: facade.commit_formation()
|
|
func commit_fourth_phase_impact(phase: int, refresh_runtime := true) -> void: facade.commit_fourth_phase_impact(phase, refresh_runtime)
|
|
func commit_phase_impact(phase: int, refresh_runtime := true) -> void: facade.commit_phase_impact(phase, refresh_runtime)
|
|
func commit_route() -> void: facade.commit_route()
|
|
func commit_route_reward() -> void: facade.commit_route_reward()
|
|
func commit_second_phase_impact(phase: int, refresh_runtime := true) -> void: facade.commit_second_phase_impact(phase, refresh_runtime)
|
|
func commit_third_phase_impact(phase: int, refresh_runtime := true) -> void: facade.commit_third_phase_impact(phase, refresh_runtime)
|
|
func commit_training() -> void: facade.commit_training()
|
|
func confirm_restart() -> void: facade.confirm_restart()
|
|
func depart() -> void: facade.depart()
|
|
func emit_battle_feedback(phase: int, target: String, delta: int, qualifier_zh: String, qualifier_en: String, tier: String) -> void: facade.emit_battle_feedback(phase, target, delta, qualifier_zh, qualifier_en, tier)
|
|
func enter_game() -> void: facade.enter_game()
|
|
func go_home() -> void: facade.go_home()
|
|
func later_preview_supports_pair() -> bool: return facade.later_preview_supports_pair()
|
|
func member_level(slot: String) -> int: return facade.member_level(slot)
|
|
func member_slots() -> Array[String]: return facade.member_slots()
|
|
func open_adaptation() -> void: facade.open_adaptation()
|
|
func open_game_intro() -> void: facade.open_game_intro()
|
|
func open_guild_return() -> void: facade.open_guild_return()
|
|
func open_recruit_selection() -> void: facade.open_recruit_selection()
|
|
func open_route_board() -> void: facade.open_route_board()
|
|
func open_route_review() -> void: facade.open_route_review()
|
|
func open_settings() -> void: facade.open_settings()
|
|
func open_training() -> void: facade.open_training()
|
|
func open_training_review() -> void: facade.open_training_review()
|
|
func phase_duration(phase: int) -> float: return facade.phase_duration(phase)
|
|
func render() -> void: facade.render()
|
|
func request_restart() -> void: facade.request_restart()
|
|
func review_automatic_formation() -> void: facade.review_automatic_formation()
|
|
func revise_recruit_selection() -> void: facade.revise_recruit_selection()
|
|
func route_coverage_state(id: String) -> String: return facade.route_coverage_state(id)
|
|
func route_reward(id: String) -> int: return facade.route_reward(id)
|
|
func run_boot_verification() -> void: await facade.run_boot_verification()
|
|
func second_battle_event_text() -> String: return facade.second_battle_event_text()
|
|
func second_result_explanation() -> String: return facade.second_result_explanation()
|
|
func start_adventure() -> void: facade.start_adventure()
|
|
func start_new_game() -> void: facade.start_new_game()
|
|
func toggle_locale() -> void: facade.toggle_locale()
|
|
func toggle_motion() -> void: facade.toggle_motion()
|
|
func toggle_mute() -> void: facade.toggle_mute()
|
|
func toggle_recruit(profession: String) -> void: facade.toggle_recruit(profession)
|
|
func toggle_text_scale() -> void: facade.toggle_text_scale()
|
|
func tr_text(zh: String, en: String) -> String: return facade.tr_text(zh, en)
|
|
func update_battle_feedback_visual() -> void: facade.update_battle_feedback_visual()
|
|
func victory_explanation() -> String: return facade.victory_explanation()
|