Files
aetherbound-guild/runtime/p9_3/core_loop_state.gd
T

124 lines
3.8 KiB
GDScript

class_name P93CoreLoopState
extends RefCounted
enum Phase { TITLE, HALL, ENCOUNTER, BATTLE, RESULT }
var revision := 0
var phase := Phase.TITLE
var coin := 24
var company: Array[String] = ["Hearthguard"]
var available_offers: Array[String] = ["Wayrunner", "Farstring", "Kindhand"]
var focused_offer := ""
var hired_member := ""
var selected_encounter := ""
var reward_committed := false
var last_reward := 0
var last_outcome := ""
var hire_receipts: Array[Dictionary] = []
var reward_receipts: Array[Dictionary] = []
var focused_equipment := ""
var equipped_items: Dictionary = {"Hearthguard": ""}
var equipment_receipts: Array[Dictionary] = []
var member_levels: Dictionary = {"Hearthguard": 1}
var member_xp: Dictionary = {"Hearthguard": 0}
var xp_receipts: Array[Dictionary] = []
func reset() -> void:
revision = 0
phase = Phase.TITLE
coin = 24
company.assign(["Hearthguard"])
available_offers.assign(["Wayrunner", "Farstring", "Kindhand"])
focused_offer = ""
hired_member = ""
selected_encounter = ""
reward_committed = false
last_reward = 0
last_outcome = ""
hire_receipts.clear()
reward_receipts.clear()
focused_equipment = ""
equipped_items = {"Hearthguard": ""}
equipment_receipts.clear()
member_levels = {"Hearthguard": 1}
member_xp = {"Hearthguard": 0}
xp_receipts.clear()
func snapshot() -> Dictionary:
return {
"revision": revision,
"phase": phase,
"coin": coin,
"company": company.duplicate(),
"capacity": 10,
"available_offers": available_offers.duplicate(),
"focused_offer": focused_offer,
"hired_member": hired_member,
"selected_encounter": selected_encounter,
"reward_committed": reward_committed,
"last_reward": last_reward,
"last_outcome": last_outcome,
"hire_receipts": hire_receipts.duplicate(true),
"reward_receipts": reward_receipts.duplicate(true),
"focused_equipment": focused_equipment,
"equipped_items": equipped_items.duplicate(true),
"equipment_receipts": equipment_receipts.duplicate(true),
"member_levels": member_levels.duplicate(true),
"member_xp": member_xp.duplicate(true),
"xp_receipts": xp_receipts.duplicate(true),
}.duplicate(true)
func invariants_hold() -> bool:
if revision < 0 or coin < 0:
return false
if phase < Phase.TITLE or phase > Phase.RESULT:
return false
if company.is_empty() or company.size() > 10:
return false
var seen := {}
for member_id in company:
if member_id not in ["Hearthguard", "Wayrunner", "Farstring", "Kindhand"] or seen.has(member_id):
return false
seen[member_id] = true
if not equipped_items.has(member_id) or String(equipped_items[member_id]) not in ["", "EQ-002", "EQ-012"]:
return false
if not member_levels.has(member_id) or int(member_levels[member_id]) < 1 or int(member_levels[member_id]) > 10:
return false
if not member_xp.has(member_id) or int(member_xp[member_id]) < 0:
return false
var level := int(member_levels[member_id])
if level < 10 and int(member_xp[member_id]) >= 20 + 10 * level:
return false
for member_id in equipped_items:
if member_id not in company:
return false
for member_id in member_levels:
if member_id not in company:
return false
for member_id in member_xp:
if member_id not in company:
return false
if not focused_equipment.is_empty() and focused_equipment not in ["EQ-002", "EQ-012"]:
return false
var owned_items := {}
for item_id in equipped_items.values():
if String(item_id).is_empty():
continue
if owned_items.has(item_id):
return false
owned_items[item_id] = true
for offer_id in available_offers:
if seen.has(offer_id):
return false
seen[offer_id] = true
if not focused_offer.is_empty() and focused_offer not in available_offers:
return false
if not selected_encounter.is_empty() and selected_encounter not in ["open_road", "crosswind", "bell_breach"]:
return false
if reward_committed and last_outcome != "victory":
return false
return true