Files
dockipelago/worlds/tloz_oos/patching/data_manager/text.py
Jonathan Tinney 7971961166
Some checks failed
Analyze modified files / flake8 (push) Failing after 2m28s
Build / build-win (push) Has been cancelled
Build / build-ubuntu2204 (push) Has been cancelled
ctest / Test C++ ubuntu-latest (push) Has been cancelled
ctest / Test C++ windows-latest (push) Has been cancelled
Analyze modified files / mypy (push) Has been cancelled
Build and Publish Docker Images / Push Docker image to Docker Hub (push) Successful in 5m4s
Native Code Static Analysis / scan-build (push) Failing after 5m2s
type check / pyright (push) Successful in 1m7s
unittests / Test Python 3.11.2 ubuntu-latest (push) Failing after 16m23s
unittests / Test Python 3.12 ubuntu-latest (push) Failing after 28m19s
unittests / Test Python 3.13 ubuntu-latest (push) Failing after 14m49s
unittests / Test hosting with 3.13 on ubuntu-latest (push) Successful in 5m0s
unittests / Test Python 3.13 macos-latest (push) Has been cancelled
unittests / Test Python 3.11 windows-latest (push) Has been cancelled
unittests / Test Python 3.13 windows-latest (push) Has been cancelled
add schedule I, sonic 1/frontiers/heroes, spirit island
2026-04-02 23:46:36 -07:00

260 lines
10 KiB
Python

import json
from pathlib import Path
from typing import Any
import Utils
from ...common.patching.RomData import RomData
from ...common.patching.Util import simple_hex
from ...common.patching.data_manager.text import get_text_data
from ...common.patching.text import normalize_text
def load_modded_seasons_text_data() -> None | tuple[dict[str, str], dict[str, str]]:
from ...World import OracleOfSeasonsWorld
text_dir = Path(Utils.cache_path("oos_ooa/text"))
dict_file = text_dir.joinpath(f"seasons_dict.json")
if not dict_file.is_file():
return None
text_file = text_dir.joinpath(f"seasons_texts.json")
if text_file.is_file():
texts: dict[str, Any] = json.load(open(text_file, encoding="utf-8"))
version = texts.pop("version")
if version == OracleOfSeasonsWorld.version():
return json.load(open(dict_file, encoding="utf-8")), texts
vanilla_text_file = text_dir.joinpath(f"seasons_texts_vanilla.json")
if not vanilla_text_file.is_file():
return None
texts = json.load(open(vanilla_text_file, encoding="utf-8"))
apply_text_edits(texts)
save_seasons_edited_text_data(texts)
return json.load(open(dict_file, encoding="utf-8")), texts
def save_seasons_edited_text_data(texts: dict[str, str]) -> None:
from ...World import OracleOfSeasonsWorld
texts["version"] = OracleOfSeasonsWorld.version()
text_dir = Path(Utils.cache_path("oos_ooa/text"))
text_file = text_dir.joinpath(f"seasons_texts.json")
with text_file.open("w", encoding="utf-8") as f:
json.dump(texts, f, ensure_ascii=False)
del texts["version"]
def apply_text_edits(texts: dict[str, str]) -> None:
texts_to_blank = []
# New items
# Replace ring box 1
texts["TX_0034"] = ("You got 🟥Ember\n"
"Seeds⬜! Open\n"
"your 🟥Seed\n"
"Satchel⬜ to use\n"
"them.")
# Replace ring box 1 unused text
texts["TX_0057"] = ("You found an\n"
"item for another\n"
"world!")
# Replace ring box 2 unused text
texts["TX_0058"] = ("You got 🟥25\n"
"Ore Chunks⬜!")
# Brand-new texts, for 20 bombs
texts["TX_0094"] = texts["TX_004d"].replace("ten", "twenty")
# Trade items
# Cuccodex is fine
texts["TX_005b"] = ("You got a\n"
"\\col(84)🥚🟥 Lon Lon Egg⬜!\n"
"It's a\n"
"beauty aid?!?")
texts["TX_005c"] = ("You got a\n"
"\\col(84)🎎🟥 Ghastly Doll⬜!\n"
"Looking at it\n"
"gives you\n"
"chills!")
texts["TX_005d"] = ("You got an\n"
"\\col(84)⚗🟥 Iron Pot⬜.\n"
"It looks...\n"
"well-seasoned.")
# Soup is fine
texts["TX_005f"] = ("You got the\n"
"\\col(84)🏺🟥 Goron Vase⬜!\n"
"It's a very\n"
"nice vase...")
texts["TX_0060"] = ("You got a\n"
"\\col(84)🐟🟥 Fish⬜! It's\n"
"market fresh!")
texts["TX_0061"] = ("You got a\n"
"\\col(84)📢🟥 Megaphone⬜!\n"
"Give a shout!")
texts["TX_0062"] = ("You got a\n"
"\\col(84)🍄🟥 Mushroom⬜!\n"
"It smells weird.")
texts["TX_0063"] = ("You got a\n"
"\\col(84)🐦🟥 Wooden Bird⬜!\n"
"It looks real!")
texts["TX_0064"] = ("You got\n"
"\\col(84)🛢🟥 Engine Grease⬜.")
texts["TX_0065"] = ("You got a\n"
"\\col(84)📻🟥 Phonograph⬜!\n"
"What a tune!")
# Appraisal text
texts["TX_301c"] = ("You got the\n"
"\\call(fd)!")
# Cross items
# Obtain text
texts_to_blank.append("TX_003b") # Strange flute
texts_to_blank.append("TX_0051") # Warrior child heart
texts_to_blank.append("TX_0053") # Warrior child heart refill
texts_to_blank.append("TX_0054") # Unappraised ring
# Inventory text
texts_to_blank.append("TX_091d") # Replaces ring box 1
texts_to_blank.append("TX_091e") # Replaces ring box 2
texts_to_blank.append("TX_0917") # Replaces unappraised ring
texts_to_blank.append("TX_092e") # Replaces strange flute
# Note: 3 other seemingly unused seeds follow
# Map stuff, replaces the group 05 since it's all linked game dialogues
texts["TX_0500"] = "Unknown Portal"
texts["TX_0501"] = normalize_text("Portal to Eastern Suburbs")
texts["TX_0502"] = normalize_text("Portal to Spool Swamp")
texts["TX_0503"] = normalize_text("Portal to Mt. Cucco")
texts["TX_0504"] = normalize_text("Portal to Eyeglass Lake")
texts["TX_0505"] = normalize_text("Portal to Horon Village")
texts["TX_0506"] = normalize_text("Portal to Temple Remains")
texts["TX_0507"] = normalize_text("Portal to Temple Summit")
texts["TX_0508"] = normalize_text("Portal to Subrosian Village")
texts["TX_0509"] = normalize_text("Portal to Subrosian Market")
texts["TX_050a"] = normalize_text("Portal to Subrosian Wilds")
texts["TX_050b"] = normalize_text("Portal to Great Furnace")
texts["TX_050c"] = normalize_text("Portal to House of Pirates")
texts["TX_050d"] = normalize_text("Portal to Subrosian Volcanoes")
texts["TX_050e"] = normalize_text("Portal to Subrosian Dungeon")
# Reword the natzu deku to omit the secret and the full satchel
texts["TX_4c43"] = ("\\sfx(c6)Come back\n"
"with all five\n"
"kinds of 🟥seeds⬜!")
# Remove the mention of 777 ore chunks
unlucky_text: str = texts["TX_3a2f"]
index_777 = unlucky_text.index(" Get")
texts["TX_3a2f"] = unlucky_text[:index_777]
# Replace the shield selling part of dekus which will never be used
texts["TX_450a"] = ("\\sfx(c6)Greetings!\n"
"I can refill\n"
"your bag for\n"
"🟩30 Rupees⬜ only.\n"
" \\optOK \\optNo thanks")
# Impa refills
texts["TX_2503"] = ("Come see me if\n"
"you need a\n"
"refill!")
# Change D8 introduction text to “Sword & Shield Dungeon” from “Sword & Shield Maze”,
# since every other mention of it was using “Dungeon” naming
texts["TX_0208"] = texts["TX_0208"].replace("Maze", "Dungeon")
# Now unused text from Maku talking
texts["TX_1700"] = texts["TX_1701"] = ""
texts["TX_020b"] = "Linked\nHero's Cave"
texts["TX_0602"] = "Unknown Dungeon"
# FAQ room
texts["TX_5300"] = ("Welcome to the\n"
"OoS randomizer\n"
"for Archipelago!\n"
"Did you read\n"
"the FAQ?\n"
" \\optYes \\optNo")
texts["TX_5301"] = ("Reading the FAQ\n"
"is important, as\n"
"rando mechanics\n"
"are in it.\n"
"Please read it\n"
"\\optYes \\optWhere?")
texts["TX_5302"] = ("It is linked\n"
"in the setup.\n"
"If you don't\n"
"have it, check\n"
"tinyurl.com\n"
"/2cb35snu\n")
texts["TX_5303"] = ("How do you\n"
"refill your\n"
"satchel and\n"
"shield?\n"
"\\optShop \\optImpa")
texts["TX_5304"] = ("Wrong. Please\n"
"check the FAQ,\n"
"you will get\n"
"stuck otherwise.")
texts["TX_5305"] = ("Right! You can\n"
"get out of\n"
"here by warping\n"
"to the start")
texts["TX_5306"] = ("Just warp to\n"
"start, you\n"
"can do it\n"
"everywhere")
# Remove ring fortune
texts["TX_301f"] = normalize_text("Ring fortunes are disabled in randomizer.")
texts_to_blank.append("TX_3024")
texts_to_blank.append("TX_302e")
texts_to_blank.append("TX_300f")
texts_to_blank.append("TX_3031")
texts_to_blank.append("TX_302a")
texts_to_blank.append("TX_3020")
texts_to_blank.append("TX_3025")
texts_to_blank.append("TX_303d")
texts_to_blank.append("TX_3026")
texts_to_blank.append("TX_3023")
# There is probably more, and the red snake could also be attacked
# Maku tree talking texts are too big to be left there (unused)
texts_to_blank.append("TX_1704")
for i in range(0x1706, 0x1716):
texts_to_blank.append(f"TX_{simple_hex(i, 4)}")
for i in range(0x1719, 0x173a):
texts_to_blank.append(f"TX_{simple_hex(i, 4)}")
for text in texts_to_blank:
texts[text] = ""
def apply_ages_edits(seasons_texts: dict[str, str], ages_rom: RomData) -> None:
_, ages_texts = get_text_data(ages_rom, False, False)
# Cross items
# Obtain text
seasons_texts["TX_0053"] = ages_texts["TX_0073"] # Cane
seasons_texts["TX_003b"] = ages_texts["TX_0030"] # Hook 1
seasons_texts["TX_0051"] = ages_texts["TX_0028"] # Hook 2
seasons_texts["TX_0054"] = ages_texts["TX_002e"] # Shooter
# Inventory text
seasons_texts["TX_091d"] = ages_texts["TX_093c"] # Cane
seasons_texts["TX_091e"] = ages_texts["TX_093d"] # Hook 1
seasons_texts["TX_0917"] = ages_texts["TX_093e"] # Hook 2
seasons_texts["TX_092e"] = ages_texts["TX_0940"] # Shooter
save_seasons_edited_text_data(seasons_texts)
def get_modded_seasons_text_data(rom_data: RomData) -> tuple[dict[str, str], dict[str, str]]:
result = load_modded_seasons_text_data()
if result is not None:
return result
dictionary, texts = get_text_data(rom_data, True, True)
apply_text_edits(texts)
save_seasons_edited_text_data(texts)
return dictionary, texts