mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
Pokemon R/B: Version 5 Update (#3566)
* Quiz updates * Enable Partial Trainersanity * Losable Key Items Still Count * New options api * Type Chart Seed * Continue switching to new options API * Level Scaling and Quiz fixes * Level Scaling and Quiz fixes * Clarify that palettes are only for Super Gameboy * Type chart seed groups use one random players' options * remove goal option again * Text updates * Trainersanity Trainers ignore Blind Trainers setting * Re-order simple connecting interiors so that directions are preserved when possible * Dexsanity exact number * Year update * Dexsanity Doc update * revert accidental file deletion * Fixes * Add world parameter to logic calls * restore correct seeded random object * missing world.options changes * Trainersanity table bug fix * delete entrances as well as exits when restarting door shuffle * Do not collect route 25 item for level scaling if trainer is trainersanity * world.options in level_scaling.py * Update worlds/pokemon_rb/level_scaling.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update worlds/pokemon_rb/encounters.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update worlds/pokemon_rb/encounters.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * world -> multiworld * Fix Cerulean Cave Hidden Item Center Rocks region * Fix Cerulean Cave Hidden Item Center Rocks region for real * Remove "self-locking" rules * Update worlds/pokemon_rb/regions.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Fossil events * Update worlds/pokemon_rb/level_scaling.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> --------- Co-authored-by: alchav <alchav@jalchavware.com> Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> Co-authored-by: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com>
This commit is contained in:
@@ -13,22 +13,22 @@ from .regions import PokemonRBWarp, map_ids, town_map_coords
|
||||
from . import poke_data
|
||||
|
||||
|
||||
def write_quizzes(self, data, random):
|
||||
def write_quizzes(world, data, random):
|
||||
|
||||
def get_quiz(q, a):
|
||||
if q == 0:
|
||||
r = random.randint(0, 3)
|
||||
if r == 0:
|
||||
mon = self.trade_mons["Trade_Dux"]
|
||||
mon = world.trade_mons["Trade_Dux"]
|
||||
text = "A woman in<LINE>Vermilion City<CONT>"
|
||||
elif r == 1:
|
||||
mon = self.trade_mons["Trade_Lola"]
|
||||
mon = world.trade_mons["Trade_Lola"]
|
||||
text = "A man in<LINE>Cerulean City<CONT>"
|
||||
elif r == 2:
|
||||
mon = self.trade_mons["Trade_Marcel"]
|
||||
mon = world.trade_mons["Trade_Marcel"]
|
||||
text = "Someone on Route 2<LINE>"
|
||||
elif r == 3:
|
||||
mon = self.trade_mons["Trade_Spot"]
|
||||
mon = world.trade_mons["Trade_Spot"]
|
||||
text = "Someone on Route 5<LINE>"
|
||||
if not a:
|
||||
answers.append(0)
|
||||
@@ -38,21 +38,30 @@ def write_quizzes(self, data, random):
|
||||
|
||||
return encode_text(f"{text}was looking for<CONT>{mon}?<DONE>")
|
||||
elif q == 1:
|
||||
for location in self.multiworld.get_filled_locations():
|
||||
if location.item.name == "Secret Key" and location.item.player == self.player:
|
||||
for location in world.multiworld.get_filled_locations():
|
||||
if location.item.name == "Secret Key" and location.item.player == world.player:
|
||||
break
|
||||
player_name = self.multiworld.player_name[location.player]
|
||||
player_name = world.multiworld.player_name[location.player]
|
||||
if not a:
|
||||
if len(self.multiworld.player_name) > 1:
|
||||
if len(world.multiworld.player_name) > 1:
|
||||
old_name = player_name
|
||||
while old_name == player_name:
|
||||
player_name = random.choice(list(self.multiworld.player_name.values()))
|
||||
player_name = random.choice(list(world.multiworld.player_name.values()))
|
||||
else:
|
||||
return encode_text("You're playing<LINE>in a multiworld<CONT>with other<CONT>players?<DONE>")
|
||||
if player_name == self.multiworld.player_name[self.player]:
|
||||
player_name = "yourself"
|
||||
player_name = encode_text(player_name, force=True, safety=True)
|
||||
return encode_text(f"The Secret Key was<LINE>found by<CONT>") + player_name + encode_text("<DONE>")
|
||||
if world.multiworld.get_entrance(
|
||||
"Cinnabar Island-G to Cinnabar Gym", world.player).connected_region.name == "Cinnabar Gym":
|
||||
if player_name == world.multiworld.player_name[world.player]:
|
||||
player_name = "yourself"
|
||||
player_name = encode_text(player_name, force=True, safety=True)
|
||||
return encode_text(f"The Secret Key was<LINE>found by<CONT>") + player_name + encode_text("?<DONE>")
|
||||
else:
|
||||
# Might not have found it yet
|
||||
if player_name == world.multiworld.player_name[world.player]:
|
||||
return encode_text(f"The Secret Key was<LINE>placed in<CONT>your own world?<DONE>")
|
||||
player_name = encode_text(player_name, force=True, safety=True)
|
||||
return (encode_text(f"The Secret Key was<LINE>placed in<CONT>") + player_name
|
||||
+ encode_text("'s<CONT>world?<DONE>"))
|
||||
elif q == 2:
|
||||
if a:
|
||||
return encode_text(f"#mon is<LINE>pronounced<CONT>Po-kay-mon?<DONE>")
|
||||
@@ -62,8 +71,8 @@ def write_quizzes(self, data, random):
|
||||
else:
|
||||
return encode_text(f"#mon is<LINE>pronounced<CONT>Po-kuh-mon?<DONE>")
|
||||
elif q == 3:
|
||||
starters = [" ".join(self.multiworld.get_location(
|
||||
f"Oak's Lab - Starter {i}", self.player).item.name.split(" ")[1:]) for i in range(1, 4)]
|
||||
starters = [" ".join(world.multiworld.get_location(
|
||||
f"Oak's Lab - Starter {i}", world.player).item.name.split(" ")[1:]) for i in range(1, 4)]
|
||||
mon = random.choice(starters)
|
||||
nots = random.choice(range(8, 16, 2))
|
||||
if random.randint(0, 1):
|
||||
@@ -82,10 +91,10 @@ def write_quizzes(self, data, random):
|
||||
return encode_text(text)
|
||||
elif q == 4:
|
||||
if a:
|
||||
tm_text = self.local_tms[27]
|
||||
tm_text = world.local_tms[27]
|
||||
else:
|
||||
if self.multiworld.randomize_tm_moves[self.player]:
|
||||
wrong_tms = self.local_tms.copy()
|
||||
if world.options.randomize_tm_moves:
|
||||
wrong_tms = world.local_tms.copy()
|
||||
wrong_tms.pop(27)
|
||||
tm_text = random.choice(wrong_tms)
|
||||
else:
|
||||
@@ -102,12 +111,36 @@ def write_quizzes(self, data, random):
|
||||
i = random.randint(0, random.choice([9, 99]))
|
||||
return encode_text(f"POLIWAG evolves {i}<LINE>times?<DONE>")
|
||||
elif q == 7:
|
||||
entity = "Motor Carrier"
|
||||
if not a:
|
||||
entity = random.choice(["Driver", "Shipper"])
|
||||
return encode_text("Title 49 of the<LINE>U.S. Code of<CONT>Federal<CONT>Regulations part<CONT>397.67 states"
|
||||
f"<CONT>that the<CONT>{entity}<CONT>is responsible<CONT>for planning<CONT>routes when"
|
||||
"<CONT>hazardous<CONT>materials are<CONT>transported?<DONE>")
|
||||
q2 = random.randint(0, 2)
|
||||
if q2 == 0:
|
||||
entity = "Motor Carrier"
|
||||
if not a:
|
||||
entity = random.choice(["Driver", "Shipper"])
|
||||
return encode_text("Title 49 of the<LINE>U.S. Code of<CONT>Federal<CONT>Regulations part<CONT>397.67 "
|
||||
f"states<CONT>that the<CONT>{entity}<CONT>is responsible<CONT>for planning<CONT>"
|
||||
"routes when<CONT>hazardous<CONT>materials are<CONT>transported?<DONE>")
|
||||
elif q2 == 1:
|
||||
if a:
|
||||
state = random.choice(
|
||||
['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut',
|
||||
'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas',
|
||||
'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota',
|
||||
'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Jersey', 'New Mexico',
|
||||
'New York', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania',
|
||||
'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont',
|
||||
'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'])
|
||||
else:
|
||||
state = "New Hampshire"
|
||||
return encode_text(
|
||||
f"As of 2024,<LINE>{state}<CONT>has a law<CONT>requiring all<CONT>front seat vehicle<CONT>occupants to use<CONT>seatbelts?<DONE>")
|
||||
elif q2 == 2:
|
||||
if a:
|
||||
country = random.choice(["The United States", "Mexico", "Canada", "Germany", "France", "China",
|
||||
"Russia", "Spain", "Brazil", "Ukraine", "Saudi Arabia", "Egypt"])
|
||||
else:
|
||||
country = random.choice(["The U.K.", "Pakistan", "India", "Japan", "Australia",
|
||||
"New Zealand", "Thailand"])
|
||||
return encode_text(f"As of 2020,<LINE>drivers in<CONT>{country}<CONT>drive on the<CONT>right side of<CONT>the road?<DONE>")
|
||||
elif q == 8:
|
||||
mon = random.choice(list(poke_data.evolution_levels.keys()))
|
||||
level = poke_data.evolution_levels[mon]
|
||||
@@ -115,17 +148,17 @@ def write_quizzes(self, data, random):
|
||||
level += random.choice(range(1, 6)) * random.choice((-1, 1))
|
||||
return encode_text(f"{mon} evolves<LINE>at level {level}?<DONE>")
|
||||
elif q == 9:
|
||||
move = random.choice(list(self.local_move_data.keys()))
|
||||
actual_type = self.local_move_data[move]["type"]
|
||||
move = random.choice(list(world.local_move_data.keys()))
|
||||
actual_type = world.local_move_data[move]["type"]
|
||||
question_type = actual_type
|
||||
while question_type == actual_type and not a:
|
||||
question_type = random.choice(list(poke_data.type_ids.keys()))
|
||||
return encode_text(f"{move} is<LINE>{question_type} type?<DONE>")
|
||||
elif q == 10:
|
||||
mon = random.choice(list(poke_data.pokemon_data.keys()))
|
||||
actual_type = self.local_poke_data[mon][random.choice(("type1", "type2"))]
|
||||
actual_type = world.local_poke_data[mon][random.choice(("type1", "type2"))]
|
||||
question_type = actual_type
|
||||
while question_type in [self.local_poke_data[mon]["type1"], self.local_poke_data[mon]["type2"]] and not a:
|
||||
while question_type in [world.local_poke_data[mon]["type1"], world.local_poke_data[mon]["type2"]] and not a:
|
||||
question_type = random.choice(list(poke_data.type_ids.keys()))
|
||||
return encode_text(f"{mon} is<LINE>{question_type} type?<DONE>")
|
||||
elif q == 11:
|
||||
@@ -147,8 +180,8 @@ def write_quizzes(self, data, random):
|
||||
return encode_text(f"{equation}<LINE>= {question_result}?<DONE>")
|
||||
elif q == 12:
|
||||
route = random.choice((12, 16))
|
||||
actual_mon = self.multiworld.get_location(f"Route {route} - Sleeping Pokemon",
|
||||
self.player).item.name.split("Static ")[1]
|
||||
actual_mon = world.multiworld.get_location(f"Route {route} - Sleeping Pokemon",
|
||||
world.player).item.name.split("Static ")[1]
|
||||
question_mon = actual_mon
|
||||
while question_mon == actual_mon and not a:
|
||||
question_mon = random.choice(list(poke_data.pokemon_data.keys()))
|
||||
@@ -157,7 +190,7 @@ def write_quizzes(self, data, random):
|
||||
type1 = random.choice(list(poke_data.type_ids.keys()))
|
||||
type2 = random.choice(list(poke_data.type_ids.keys()))
|
||||
eff_msgs = ["super effective<CONT>", "no ", "not very<CONT>effective<CONT>", "normal "]
|
||||
for matchup in self.type_chart:
|
||||
for matchup in world.type_chart:
|
||||
if matchup[0] == type1 and matchup[1] == type2:
|
||||
if matchup[2] > 10:
|
||||
eff = eff_msgs[0]
|
||||
@@ -175,15 +208,25 @@ def write_quizzes(self, data, random):
|
||||
eff = random.choice(eff_msgs)
|
||||
return encode_text(f"{type1} deals<LINE>{eff}damage to<CONT>{type2} type?<DONE>")
|
||||
elif q == 14:
|
||||
fossil_level = self.multiworld.get_location("Fossil Level - Trainer Parties",
|
||||
self.player).party_data[0]['level']
|
||||
fossil_level = world.multiworld.get_location("Fossil Level - Trainer Parties",
|
||||
world.player).party_data[0]['level']
|
||||
if not a:
|
||||
fossil_level += random.choice((-5, 5))
|
||||
return encode_text(f"Fossil #MON<LINE>revive at level<CONT>{fossil_level}?<DONE>")
|
||||
elif q == 15:
|
||||
if a:
|
||||
fodmap = random.choice(["garlic", "onion", "milk", "watermelon", "cherries", "wheat", "barley",
|
||||
"pistachios", "cashews", "kidney beans", "apples", "honey"])
|
||||
else:
|
||||
fodmap = random.choice(["carrots", "potatoes", "oranges", "pineapple", "blueberries", "parmesan",
|
||||
"eggs", "beef", "chicken", "oat", "rice", "maple syrup", "peanuts"])
|
||||
are_is = "are" if fodmap[-1] == "s" else "is"
|
||||
return encode_text(f"According to<LINE>Monash Uni.,<CONT>{fodmap} {are_is}<CONT>considered high<CONT>in FODMAPs?<DONE>")
|
||||
|
||||
answers = [random.randint(0, 1) for _ in range(6)]
|
||||
|
||||
questions = random.sample((range(0, 15)), 6)
|
||||
questions = random.sample((range(0, 16)), 6)
|
||||
|
||||
question_texts = []
|
||||
for i, question in enumerate(questions):
|
||||
question_texts.append(get_quiz(question, answers[i]))
|
||||
@@ -193,9 +236,9 @@ def write_quizzes(self, data, random):
|
||||
write_bytes(data, question_texts[i], rom_addresses[f"Text_Quiz_{quiz}"])
|
||||
|
||||
|
||||
def generate_output(self, output_directory: str):
|
||||
random = self.multiworld.per_slot_randoms[self.player]
|
||||
game_version = self.multiworld.game_version[self.player].current_key
|
||||
def generate_output(world, output_directory: str):
|
||||
random = world.random
|
||||
game_version = world.options.game_version.current_key
|
||||
data = bytes(get_base_rom_bytes(game_version))
|
||||
|
||||
base_patch = pkgutil.get_data(__name__, f'basepatch_{game_version}.bsdiff4')
|
||||
@@ -205,8 +248,8 @@ def generate_output(self, output_directory: str):
|
||||
basemd5 = hashlib.md5()
|
||||
basemd5.update(data)
|
||||
|
||||
pallet_connections = {entrance: self.multiworld.get_entrance(f"Pallet Town to {entrance}",
|
||||
self.player).connected_region.name for
|
||||
pallet_connections = {entrance: world.multiworld.get_entrance(f"Pallet Town to {entrance}",
|
||||
world.player).connected_region.name for
|
||||
entrance in ["Player's House 1F", "Oak's Lab",
|
||||
"Rival's House"]}
|
||||
paths = None
|
||||
@@ -222,11 +265,11 @@ def generate_output(self, output_directory: str):
|
||||
elif pallet_connections["Oak's Lab"] == "Player's House 1F":
|
||||
write_bytes(data, [0x5F, 0xC7, 0x0C, 0x0C, 0x00, 0x00], rom_addresses["Pallet_Fly_Coords"])
|
||||
|
||||
for region in self.multiworld.get_regions(self.player):
|
||||
for region in world.multiworld.get_regions(world.player):
|
||||
for entrance in region.exits:
|
||||
if isinstance(entrance, PokemonRBWarp):
|
||||
self.multiworld.spoiler.set_entrance(entrance.name, entrance.connected_region.name, "entrance",
|
||||
self.player)
|
||||
world.multiworld.spoiler.set_entrance(entrance.name, entrance.connected_region.name, "entrance",
|
||||
world.player)
|
||||
warp_ids = (entrance.warp_id,) if isinstance(entrance.warp_id, int) else entrance.warp_id
|
||||
warp_to_ids = (entrance.target,) if isinstance(entrance.target, int) else entrance.target
|
||||
for i, warp_id in enumerate(warp_ids):
|
||||
@@ -241,32 +284,32 @@ def generate_output(self, output_directory: str):
|
||||
data[address] = 0 if "Elevator" in connected_map_name else warp_to_ids[i]
|
||||
data[address + 1] = map_ids[connected_map_name]
|
||||
|
||||
if self.multiworld.door_shuffle[self.player] == "simple":
|
||||
if world.options.door_shuffle == "simple":
|
||||
for (entrance, _, _, map_coords_entries, map_name, _) in town_map_coords.values():
|
||||
destination = self.multiworld.get_entrance(entrance, self.player).connected_region.name
|
||||
destination = world.multiworld.get_entrance(entrance, world.player).connected_region.name
|
||||
(_, x, y, _, _, map_order_entry) = town_map_coords[destination]
|
||||
for map_coord_entry in map_coords_entries:
|
||||
data[rom_addresses["Town_Map_Coords"] + (map_coord_entry * 4) + 1] = (y << 4) | x
|
||||
data[rom_addresses["Town_Map_Order"] + map_order_entry] = map_ids[map_name]
|
||||
|
||||
if not self.multiworld.key_items_only[self.player]:
|
||||
if not world.options.key_items_only:
|
||||
for i, gym_leader in enumerate(("Pewter Gym - Brock TM", "Cerulean Gym - Misty TM",
|
||||
"Vermilion Gym - Lt. Surge TM", "Celadon Gym - Erika TM",
|
||||
"Fuchsia Gym - Koga TM", "Saffron Gym - Sabrina TM",
|
||||
"Cinnabar Gym - Blaine TM", "Viridian Gym - Giovanni TM")):
|
||||
item_name = self.multiworld.get_location(gym_leader, self.player).item.name
|
||||
item_name = world.multiworld.get_location(gym_leader, world.player).item.name
|
||||
if item_name.startswith("TM"):
|
||||
try:
|
||||
tm = int(item_name[2:4])
|
||||
move = poke_data.moves[self.local_tms[tm - 1]]["id"]
|
||||
move = poke_data.moves[world.local_tms[tm - 1]]["id"]
|
||||
data[rom_addresses["Gym_Leader_Moves"] + (2 * i)] = move
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def set_trade_mon(address, loc):
|
||||
mon = self.multiworld.get_location(loc, self.player).item.name
|
||||
mon = world.multiworld.get_location(loc, world.player).item.name
|
||||
data[rom_addresses[address]] = poke_data.pokemon_data[mon]["id"]
|
||||
self.trade_mons[address] = mon
|
||||
world.trade_mons[address] = mon
|
||||
|
||||
if game_version == "red":
|
||||
set_trade_mon("Trade_Terry", "Safari Zone Center - Wild Pokemon - 5")
|
||||
@@ -282,10 +325,10 @@ def generate_output(self, output_directory: str):
|
||||
set_trade_mon("Trade_Doris", "Cerulean Cave 1F - Wild Pokemon - 9")
|
||||
set_trade_mon("Trade_Crinkles", "Route 12 - Wild Pokemon - 4")
|
||||
|
||||
data[rom_addresses['Fly_Location']] = self.fly_map_code
|
||||
data[rom_addresses['Map_Fly_Location']] = self.town_map_fly_map_code
|
||||
data[rom_addresses['Fly_Location']] = world.fly_map_code
|
||||
data[rom_addresses['Map_Fly_Location']] = world.town_map_fly_map_code
|
||||
|
||||
if self.multiworld.fix_combat_bugs[self.player]:
|
||||
if world.options.fix_combat_bugs:
|
||||
data[rom_addresses["Option_Fix_Combat_Bugs"]] = 1
|
||||
data[rom_addresses["Option_Fix_Combat_Bugs_Focus_Energy"]] = 0x28 # jr z
|
||||
data[rom_addresses["Option_Fix_Combat_Bugs_HP_Drain_Dream_Eater"]] = 0x1A # ld a, (de)
|
||||
@@ -298,25 +341,25 @@ def generate_output(self, output_directory: str):
|
||||
data[rom_addresses["Option_Fix_Combat_Bugs_Heal_Effect"] + 1] = 5 # 5 bytes ahead
|
||||
data[rom_addresses["Option_Fix_Combat_Bugs_Heal_Stat_Modifiers"]] = 1
|
||||
|
||||
if self.multiworld.poke_doll_skip[self.player] == "in_logic":
|
||||
if world.options.poke_doll_skip == "in_logic":
|
||||
data[rom_addresses["Option_Silph_Scope_Skip"]] = 0x00 # nop
|
||||
data[rom_addresses["Option_Silph_Scope_Skip"] + 1] = 0x00 # nop
|
||||
data[rom_addresses["Option_Silph_Scope_Skip"] + 2] = 0x00 # nop
|
||||
|
||||
if self.multiworld.bicycle_gate_skips[self.player] == "patched":
|
||||
if world.options.bicycle_gate_skips == "patched":
|
||||
data[rom_addresses["Option_Route_16_Gate_Fix"]] = 0x00 # nop
|
||||
data[rom_addresses["Option_Route_16_Gate_Fix"] + 1] = 0x00 # nop
|
||||
data[rom_addresses["Option_Route_18_Gate_Fix"]] = 0x00 # nop
|
||||
data[rom_addresses["Option_Route_18_Gate_Fix"] + 1] = 0x00 # nop
|
||||
|
||||
if self.multiworld.door_shuffle[self.player]:
|
||||
if world.options.door_shuffle:
|
||||
data[rom_addresses["Entrance_Shuffle_Fuji_Warp"]] = 1 # prevent warping to Fuji's House from Pokemon Tower 7F
|
||||
|
||||
if self.multiworld.all_elevators_locked[self.player]:
|
||||
if world.options.all_elevators_locked:
|
||||
data[rom_addresses["Option_Locked_Elevator_Celadon"]] = 0x20 # jr nz
|
||||
data[rom_addresses["Option_Locked_Elevator_Silph"]] = 0x20 # jr nz
|
||||
|
||||
if self.multiworld.tea[self.player].value:
|
||||
if world.options.tea:
|
||||
data[rom_addresses["Option_Tea"]] = 1
|
||||
data[rom_addresses["Guard_Drink_List"]] = 0x54
|
||||
data[rom_addresses["Guard_Drink_List"] + 1] = 0
|
||||
@@ -325,90 +368,94 @@ def generate_output(self, output_directory: str):
|
||||
"<PARA>Oh wait there,<LINE>the road's closed.<DONE>"),
|
||||
rom_addresses["Text_Saffron_Gate"])
|
||||
|
||||
data[rom_addresses["Tea_Key_Item_A"]] = 0x28 # jr .z
|
||||
data[rom_addresses["Tea_Key_Item_B"]] = 0x28 # jr .z
|
||||
data[rom_addresses["Tea_Key_Item_C"]] = 0x28 # jr .z
|
||||
|
||||
data[rom_addresses["Fossils_Needed_For_Second_Item"]] = (
|
||||
self.multiworld.second_fossil_check_condition[self.player].value)
|
||||
world.options.second_fossil_check_condition.value)
|
||||
|
||||
data[rom_addresses["Option_Lose_Money"]] = int(not self.multiworld.lose_money_on_blackout[self.player].value)
|
||||
data[rom_addresses["Option_Lose_Money"]] = int(not world.options.lose_money_on_blackout.value)
|
||||
|
||||
if self.multiworld.extra_key_items[self.player]:
|
||||
if world.options.extra_key_items:
|
||||
data[rom_addresses['Option_Extra_Key_Items_A']] = 1
|
||||
data[rom_addresses['Option_Extra_Key_Items_B']] = 1
|
||||
data[rom_addresses['Option_Extra_Key_Items_C']] = 1
|
||||
data[rom_addresses['Option_Extra_Key_Items_D']] = 1
|
||||
data[rom_addresses["Option_Split_Card_Key"]] = self.multiworld.split_card_key[self.player].value
|
||||
data[rom_addresses["Option_Blind_Trainers"]] = round(self.multiworld.blind_trainers[self.player].value * 2.55)
|
||||
data[rom_addresses["Option_Cerulean_Cave_Badges"]] = self.multiworld.cerulean_cave_badges_condition[self.player].value
|
||||
data[rom_addresses["Option_Cerulean_Cave_Key_Items"]] = self.multiworld.cerulean_cave_key_items_condition[self.player].total
|
||||
write_bytes(data, encode_text(str(self.multiworld.cerulean_cave_badges_condition[self.player].value)), rom_addresses["Text_Cerulean_Cave_Badges"])
|
||||
write_bytes(data, encode_text(str(self.multiworld.cerulean_cave_key_items_condition[self.player].total) + " key items."), rom_addresses["Text_Cerulean_Cave_Key_Items"])
|
||||
data[rom_addresses['Option_Encounter_Minimum_Steps']] = self.multiworld.minimum_steps_between_encounters[self.player].value
|
||||
data[rom_addresses['Option_Route23_Badges']] = self.multiworld.victory_road_condition[self.player].value
|
||||
data[rom_addresses['Option_Victory_Road_Badges']] = self.multiworld.route_22_gate_condition[self.player].value
|
||||
data[rom_addresses['Option_Elite_Four_Pokedex']] = self.multiworld.elite_four_pokedex_condition[self.player].total
|
||||
data[rom_addresses['Option_Elite_Four_Key_Items']] = self.multiworld.elite_four_key_items_condition[self.player].total
|
||||
data[rom_addresses['Option_Elite_Four_Badges']] = self.multiworld.elite_four_badges_condition[self.player].value
|
||||
write_bytes(data, encode_text(str(self.multiworld.elite_four_badges_condition[self.player].value)), rom_addresses["Text_Elite_Four_Badges"])
|
||||
write_bytes(data, encode_text(str(self.multiworld.elite_four_key_items_condition[self.player].total) + " key items, and"), rom_addresses["Text_Elite_Four_Key_Items"])
|
||||
write_bytes(data, encode_text(str(self.multiworld.elite_four_pokedex_condition[self.player].total) + " #MON"), rom_addresses["Text_Elite_Four_Pokedex"])
|
||||
write_bytes(data, encode_text(str(self.total_key_items), length=2), rom_addresses["Trainer_Screen_Total_Key_Items"])
|
||||
data[rom_addresses["Option_Split_Card_Key"]] = world.options.split_card_key.value
|
||||
data[rom_addresses["Option_Blind_Trainers"]] = round(world.options.blind_trainers.value * 2.55)
|
||||
data[rom_addresses["Option_Cerulean_Cave_Badges"]] = world.options.cerulean_cave_badges_condition.value
|
||||
data[rom_addresses["Option_Cerulean_Cave_Key_Items"]] = world.options.cerulean_cave_key_items_condition.total
|
||||
write_bytes(data, encode_text(str(world.options.cerulean_cave_badges_condition.value)), rom_addresses["Text_Cerulean_Cave_Badges"])
|
||||
write_bytes(data, encode_text(str(world.options.cerulean_cave_key_items_condition.total) + " key items."), rom_addresses["Text_Cerulean_Cave_Key_Items"])
|
||||
data[rom_addresses['Option_Encounter_Minimum_Steps']] = world.options.minimum_steps_between_encounters.value
|
||||
data[rom_addresses['Option_Route23_Badges']] = world.options.victory_road_condition.value
|
||||
data[rom_addresses['Option_Victory_Road_Badges']] = world.options.route_22_gate_condition.value
|
||||
data[rom_addresses['Option_Elite_Four_Pokedex']] = world.options.elite_four_pokedex_condition.total
|
||||
data[rom_addresses['Option_Elite_Four_Key_Items']] = world.options.elite_four_key_items_condition.total
|
||||
data[rom_addresses['Option_Elite_Four_Badges']] = world.options.elite_four_badges_condition.value
|
||||
write_bytes(data, encode_text(str(world.options.elite_four_badges_condition.value)), rom_addresses["Text_Elite_Four_Badges"])
|
||||
write_bytes(data, encode_text(str(world.options.elite_four_key_items_condition.total) + " key items, and"), rom_addresses["Text_Elite_Four_Key_Items"])
|
||||
write_bytes(data, encode_text(str(world.options.elite_four_pokedex_condition.total) + " #MON"), rom_addresses["Text_Elite_Four_Pokedex"])
|
||||
write_bytes(data, encode_text(str(world.total_key_items), length=2), rom_addresses["Trainer_Screen_Total_Key_Items"])
|
||||
|
||||
data[rom_addresses['Option_Viridian_Gym_Badges']] = self.multiworld.viridian_gym_condition[self.player].value
|
||||
data[rom_addresses['Option_EXP_Modifier']] = self.multiworld.exp_modifier[self.player].value
|
||||
if not self.multiworld.require_item_finder[self.player]:
|
||||
data[rom_addresses['Option_Viridian_Gym_Badges']] = world.options.viridian_gym_condition.value
|
||||
data[rom_addresses['Option_EXP_Modifier']] = world.options.exp_modifier.value
|
||||
if not world.options.require_item_finder:
|
||||
data[rom_addresses['Option_Itemfinder']] = 0 # nop
|
||||
if self.multiworld.extra_strength_boulders[self.player]:
|
||||
if world.options.extra_strength_boulders:
|
||||
for i in range(0, 3):
|
||||
data[rom_addresses['Option_Boulders'] + (i * 3)] = 0x15
|
||||
if self.multiworld.extra_key_items[self.player]:
|
||||
if world.options.extra_key_items:
|
||||
for i in range(0, 4):
|
||||
data[rom_addresses['Option_Rock_Tunnel_Extra_Items'] + (i * 3)] = 0x15
|
||||
if self.multiworld.old_man[self.player] == "open_viridian_city":
|
||||
if world.options.old_man == "open_viridian_city":
|
||||
data[rom_addresses['Option_Old_Man']] = 0x11
|
||||
data[rom_addresses['Option_Old_Man_Lying']] = 0x15
|
||||
data[rom_addresses['Option_Route3_Guard_B']] = self.multiworld.route_3_condition[self.player].value
|
||||
if self.multiworld.route_3_condition[self.player] == "open":
|
||||
data[rom_addresses['Option_Route3_Guard_B']] = world.options.route_3_condition.value
|
||||
if world.options.route_3_condition == "open":
|
||||
data[rom_addresses['Option_Route3_Guard_A']] = 0x11
|
||||
if not self.multiworld.robbed_house_officer[self.player]:
|
||||
if not world.options.robbed_house_officer:
|
||||
data[rom_addresses['Option_Trashed_House_Guard_A']] = 0x15
|
||||
data[rom_addresses['Option_Trashed_House_Guard_B']] = 0x11
|
||||
if self.multiworld.require_pokedex[self.player]:
|
||||
if world.options.require_pokedex:
|
||||
data[rom_addresses["Require_Pokedex_A"]] = 1
|
||||
data[rom_addresses["Require_Pokedex_B"]] = 1
|
||||
data[rom_addresses["Require_Pokedex_C"]] = 1
|
||||
else:
|
||||
data[rom_addresses["Require_Pokedex_D"]] = 0x18 # jr
|
||||
if self.multiworld.dexsanity[self.player]:
|
||||
if world.options.dexsanity:
|
||||
data[rom_addresses["Option_Dexsanity_A"]] = 1
|
||||
data[rom_addresses["Option_Dexsanity_B"]] = 1
|
||||
if self.multiworld.all_pokemon_seen[self.player]:
|
||||
if world.options.all_pokemon_seen:
|
||||
data[rom_addresses["Option_Pokedex_Seen"]] = 1
|
||||
money = str(self.multiworld.starting_money[self.player].value).zfill(6)
|
||||
money = str(world.options.starting_money.value).zfill(6)
|
||||
data[rom_addresses["Starting_Money_High"]] = int(money[:2], 16)
|
||||
data[rom_addresses["Starting_Money_Middle"]] = int(money[2:4], 16)
|
||||
data[rom_addresses["Starting_Money_Low"]] = int(money[4:], 16)
|
||||
data[rom_addresses["Text_Badges_Needed_Viridian_Gym"]] = encode_text(
|
||||
str(self.multiworld.viridian_gym_condition[self.player].value))[0]
|
||||
str(world.options.viridian_gym_condition.value))[0]
|
||||
data[rom_addresses["Text_Rt23_Badges_A"]] = encode_text(
|
||||
str(self.multiworld.victory_road_condition[self.player].value))[0]
|
||||
str(world.options.victory_road_condition.value))[0]
|
||||
data[rom_addresses["Text_Rt23_Badges_B"]] = encode_text(
|
||||
str(self.multiworld.victory_road_condition[self.player].value))[0]
|
||||
str(world.options.victory_road_condition.value))[0]
|
||||
data[rom_addresses["Text_Rt23_Badges_C"]] = encode_text(
|
||||
str(self.multiworld.victory_road_condition[self.player].value))[0]
|
||||
str(world.options.victory_road_condition.value))[0]
|
||||
data[rom_addresses["Text_Rt23_Badges_D"]] = encode_text(
|
||||
str(self.multiworld.victory_road_condition[self.player].value))[0]
|
||||
str(world.options.victory_road_condition.value))[0]
|
||||
data[rom_addresses["Text_Badges_Needed"]] = encode_text(
|
||||
str(self.multiworld.elite_four_badges_condition[self.player].value))[0]
|
||||
str(world.options.elite_four_badges_condition.value))[0]
|
||||
write_bytes(data, encode_text(
|
||||
" ".join(self.multiworld.get_location("Route 4 Pokemon Center - Pokemon For Sale", self.player).item.name.upper().split()[1:])),
|
||||
" ".join(world.multiworld.get_location("Route 4 Pokemon Center - Pokemon For Sale", world.player).item.name.upper().split()[1:])),
|
||||
rom_addresses["Text_Magikarp_Salesman"])
|
||||
|
||||
if self.multiworld.badges_needed_for_hm_moves[self.player].value == 0:
|
||||
if world.options.badges_needed_for_hm_moves.value == 0:
|
||||
for hm_move in poke_data.hm_moves:
|
||||
write_bytes(data, bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
|
||||
rom_addresses["HM_" + hm_move + "_Badge_a"])
|
||||
elif self.extra_badges:
|
||||
elif world.extra_badges:
|
||||
written_badges = {}
|
||||
for hm_move, badge in self.extra_badges.items():
|
||||
for hm_move, badge in world.extra_badges.items():
|
||||
data[rom_addresses["HM_" + hm_move + "_Badge_b"]] = {"Boulder Badge": 0x47, "Cascade Badge": 0x4F,
|
||||
"Thunder Badge": 0x57, "Rainbow Badge": 0x5F,
|
||||
"Soul Badge": 0x67, "Marsh Badge": 0x6F,
|
||||
@@ -427,7 +474,7 @@ def generate_output(self, output_directory: str):
|
||||
write_bytes(data, encode_text("Nothing"), rom_addresses["Badge_Text_" + badge.replace(" ", "_")])
|
||||
|
||||
type_loc = rom_addresses["Type_Chart"]
|
||||
for matchup in self.type_chart:
|
||||
for matchup in world.type_chart:
|
||||
if matchup[2] != 10: # don't needlessly divide damage by 10 and multiply by 10
|
||||
data[type_loc] = poke_data.type_ids[matchup[0]]
|
||||
data[type_loc + 1] = poke_data.type_ids[matchup[1]]
|
||||
@@ -437,52 +484,49 @@ def generate_output(self, output_directory: str):
|
||||
data[type_loc + 1] = 0xFF
|
||||
data[type_loc + 2] = 0xFF
|
||||
|
||||
if self.multiworld.normalize_encounter_chances[self.player].value:
|
||||
if world.options.normalize_encounter_chances.value:
|
||||
chances = [25, 51, 77, 103, 129, 155, 180, 205, 230, 255]
|
||||
for i, chance in enumerate(chances):
|
||||
data[rom_addresses['Encounter_Chances'] + (i * 2)] = chance
|
||||
|
||||
for mon, mon_data in self.local_poke_data.items():
|
||||
for mon, mon_data in world.local_poke_data.items():
|
||||
if mon == "Mew":
|
||||
address = rom_addresses["Base_Stats_Mew"]
|
||||
else:
|
||||
address = rom_addresses["Base_Stats"] + (28 * (mon_data["dex"] - 1))
|
||||
data[address + 1] = self.local_poke_data[mon]["hp"]
|
||||
data[address + 2] = self.local_poke_data[mon]["atk"]
|
||||
data[address + 3] = self.local_poke_data[mon]["def"]
|
||||
data[address + 4] = self.local_poke_data[mon]["spd"]
|
||||
data[address + 5] = self.local_poke_data[mon]["spc"]
|
||||
data[address + 6] = poke_data.type_ids[self.local_poke_data[mon]["type1"]]
|
||||
data[address + 7] = poke_data.type_ids[self.local_poke_data[mon]["type2"]]
|
||||
data[address + 8] = self.local_poke_data[mon]["catch rate"]
|
||||
data[address + 15] = poke_data.moves[self.local_poke_data[mon]["start move 1"]]["id"]
|
||||
data[address + 16] = poke_data.moves[self.local_poke_data[mon]["start move 2"]]["id"]
|
||||
data[address + 17] = poke_data.moves[self.local_poke_data[mon]["start move 3"]]["id"]
|
||||
data[address + 18] = poke_data.moves[self.local_poke_data[mon]["start move 4"]]["id"]
|
||||
write_bytes(data, self.local_poke_data[mon]["tms"], address + 20)
|
||||
if mon in self.learnsets and self.learnsets[mon]:
|
||||
data[address + 1] = world.local_poke_data[mon]["hp"]
|
||||
data[address + 2] = world.local_poke_data[mon]["atk"]
|
||||
data[address + 3] = world.local_poke_data[mon]["def"]
|
||||
data[address + 4] = world.local_poke_data[mon]["spd"]
|
||||
data[address + 5] = world.local_poke_data[mon]["spc"]
|
||||
data[address + 6] = poke_data.type_ids[world.local_poke_data[mon]["type1"]]
|
||||
data[address + 7] = poke_data.type_ids[world.local_poke_data[mon]["type2"]]
|
||||
data[address + 8] = world.local_poke_data[mon]["catch rate"]
|
||||
data[address + 15] = poke_data.moves[world.local_poke_data[mon]["start move 1"]]["id"]
|
||||
data[address + 16] = poke_data.moves[world.local_poke_data[mon]["start move 2"]]["id"]
|
||||
data[address + 17] = poke_data.moves[world.local_poke_data[mon]["start move 3"]]["id"]
|
||||
data[address + 18] = poke_data.moves[world.local_poke_data[mon]["start move 4"]]["id"]
|
||||
write_bytes(data, world.local_poke_data[mon]["tms"], address + 20)
|
||||
if mon in world.learnsets and world.learnsets[mon]:
|
||||
address = rom_addresses["Learnset_" + mon.replace(" ", "")]
|
||||
for i, move in enumerate(self.learnsets[mon]):
|
||||
for i, move in enumerate(world.learnsets[mon]):
|
||||
data[(address + 1) + i * 2] = poke_data.moves[move]["id"]
|
||||
|
||||
data[rom_addresses["Option_Aide_Rt2"]] = self.multiworld.oaks_aide_rt_2[self.player].value
|
||||
data[rom_addresses["Option_Aide_Rt11"]] = self.multiworld.oaks_aide_rt_11[self.player].value
|
||||
data[rom_addresses["Option_Aide_Rt15"]] = self.multiworld.oaks_aide_rt_15[self.player].value
|
||||
data[rom_addresses["Option_Aide_Rt2"]] = world.options.oaks_aide_rt_2.value
|
||||
data[rom_addresses["Option_Aide_Rt11"]] = world.options.oaks_aide_rt_11.value
|
||||
data[rom_addresses["Option_Aide_Rt15"]] = world.options.oaks_aide_rt_15.value
|
||||
|
||||
if self.multiworld.safari_zone_normal_battles[self.player].value == 1:
|
||||
if world.options.safari_zone_normal_battles.value == 1:
|
||||
data[rom_addresses["Option_Safari_Zone_Battle_Type"]] = 255
|
||||
|
||||
if self.multiworld.reusable_tms[self.player].value:
|
||||
if world.options.reusable_tms.value:
|
||||
data[rom_addresses["Option_Reusable_TMs"]] = 0xC9
|
||||
|
||||
for i in range(1, 10):
|
||||
data[rom_addresses[f"Option_Trainersanity{i}"]] = self.multiworld.trainersanity[self.player].value
|
||||
data[rom_addresses["Option_Always_Half_STAB"]] = int(not world.options.same_type_attack_bonus.value)
|
||||
|
||||
data[rom_addresses["Option_Always_Half_STAB"]] = int(not self.multiworld.same_type_attack_bonus[self.player].value)
|
||||
|
||||
if self.multiworld.better_shops[self.player]:
|
||||
if world.options.better_shops:
|
||||
inventory = ["Poke Ball", "Great Ball", "Ultra Ball"]
|
||||
if self.multiworld.better_shops[self.player].value == 2:
|
||||
if world.options.better_shops.value == 2:
|
||||
inventory.append("Master Ball")
|
||||
inventory += ["Potion", "Super Potion", "Hyper Potion", "Max Potion", "Full Restore", "Revive", "Antidote",
|
||||
"Awakening", "Burn Heal", "Ice Heal", "Paralyze Heal", "Full Heal", "Repel", "Super Repel",
|
||||
@@ -492,30 +536,30 @@ def generate_output(self, output_directory: str):
|
||||
shop_data.append(0xFF)
|
||||
for shop in range(1, 11):
|
||||
write_bytes(data, shop_data, rom_addresses[f"Shop{shop}"])
|
||||
if self.multiworld.stonesanity[self.player]:
|
||||
if world.options.stonesanity:
|
||||
write_bytes(data, bytearray([0xFE, 1, item_table["Poke Doll"].id - 172000000, 0xFF]), rom_addresses[f"Shop_Stones"])
|
||||
|
||||
price = str(self.multiworld.master_ball_price[self.player].value).zfill(6)
|
||||
price = str(world.options.master_ball_price.value).zfill(6)
|
||||
price = bytearray([int(price[:2], 16), int(price[2:4], 16), int(price[4:], 16)])
|
||||
write_bytes(data, price, rom_addresses["Price_Master_Ball"]) # Money values in Red and Blue are weird
|
||||
|
||||
for item in reversed(self.multiworld.precollected_items[self.player]):
|
||||
for item in reversed(world.multiworld.precollected_items[world.player]):
|
||||
if data[rom_addresses["Start_Inventory"] + item.code - 172000000] < 255:
|
||||
data[rom_addresses["Start_Inventory"] + item.code - 172000000] += 1
|
||||
|
||||
set_mon_palettes(self, random, data)
|
||||
set_mon_palettes(world, random, data)
|
||||
|
||||
for move_data in self.local_move_data.values():
|
||||
for move_data in world.local_move_data.values():
|
||||
if move_data["id"] == 0:
|
||||
continue
|
||||
address = rom_addresses["Move_Data"] + ((move_data["id"] - 1) * 6)
|
||||
write_bytes(data, bytearray([move_data["id"], move_data["effect"], move_data["power"],
|
||||
poke_data.type_ids[move_data["type"]], round(move_data["accuracy"] * 2.55), move_data["pp"]]), address)
|
||||
|
||||
TM_IDs = bytearray([poke_data.moves[move]["id"] for move in self.local_tms])
|
||||
TM_IDs = bytearray([poke_data.moves[move]["id"] for move in world.local_tms])
|
||||
write_bytes(data, TM_IDs, rom_addresses["TM_Moves"])
|
||||
|
||||
if self.multiworld.randomize_rock_tunnel[self.player]:
|
||||
if world.options.randomize_rock_tunnel:
|
||||
seed = randomize_rock_tunnel(data, random)
|
||||
write_bytes(data, encode_text(f"SEED: <LINE>{seed}"), rom_addresses["Text_Rock_Tunnel_Sign"])
|
||||
|
||||
@@ -524,44 +568,44 @@ def generate_output(self, output_directory: str):
|
||||
data[rom_addresses['Title_Mon_First']] = mons.pop()
|
||||
for mon in range(0, 16):
|
||||
data[rom_addresses['Title_Mons'] + mon] = mons.pop()
|
||||
if self.multiworld.game_version[self.player].value:
|
||||
mons.sort(key=lambda mon: 0 if mon == self.multiworld.get_location("Oak's Lab - Starter 1", self.player).item.name
|
||||
else 1 if mon == self.multiworld.get_location("Oak's Lab - Starter 2", self.player).item.name else
|
||||
2 if mon == self.multiworld.get_location("Oak's Lab - Starter 3", self.player).item.name else 3)
|
||||
if world.options.game_version.value:
|
||||
mons.sort(key=lambda mon: 0 if mon == world.multiworld.get_location("Oak's Lab - Starter 1", world.player).item.name
|
||||
else 1 if mon == world.multiworld.get_location("Oak's Lab - Starter 2", world.player).item.name else
|
||||
2 if mon == world.multiworld.get_location("Oak's Lab - Starter 3", world.player).item.name else 3)
|
||||
else:
|
||||
mons.sort(key=lambda mon: 0 if mon == self.multiworld.get_location("Oak's Lab - Starter 2", self.player).item.name
|
||||
else 1 if mon == self.multiworld.get_location("Oak's Lab - Starter 1", self.player).item.name else
|
||||
2 if mon == self.multiworld.get_location("Oak's Lab - Starter 3", self.player).item.name else 3)
|
||||
write_bytes(data, encode_text(self.multiworld.seed_name[-20:], 20, True), rom_addresses['Title_Seed'])
|
||||
mons.sort(key=lambda mon: 0 if mon == world.multiworld.get_location("Oak's Lab - Starter 2", world.player).item.name
|
||||
else 1 if mon == world.multiworld.get_location("Oak's Lab - Starter 1", world.player).item.name else
|
||||
2 if mon == world.multiworld.get_location("Oak's Lab - Starter 3", world.player).item.name else 3)
|
||||
write_bytes(data, encode_text(world.multiworld.seed_name[-20:], 20, True), rom_addresses['Title_Seed'])
|
||||
|
||||
slot_name = self.multiworld.player_name[self.player]
|
||||
slot_name = world.multiworld.player_name[world.player]
|
||||
slot_name.replace("@", " ")
|
||||
slot_name.replace("<", " ")
|
||||
slot_name.replace(">", " ")
|
||||
write_bytes(data, encode_text(slot_name, 16, True, True), rom_addresses['Title_Slot_Name'])
|
||||
|
||||
if self.trainer_name == "choose_in_game":
|
||||
if world.trainer_name == "choose_in_game":
|
||||
data[rom_addresses["Skip_Player_Name"]] = 0
|
||||
else:
|
||||
write_bytes(data, self.trainer_name, rom_addresses['Player_Name'])
|
||||
if self.rival_name == "choose_in_game":
|
||||
write_bytes(data, world.trainer_name, rom_addresses['Player_Name'])
|
||||
if world.rival_name == "choose_in_game":
|
||||
data[rom_addresses["Skip_Rival_Name"]] = 0
|
||||
else:
|
||||
write_bytes(data, self.rival_name, rom_addresses['Rival_Name'])
|
||||
write_bytes(data, world.rival_name, rom_addresses['Rival_Name'])
|
||||
|
||||
data[0xFF00] = 2 # client compatibility version
|
||||
rom_name = bytearray(f'AP{Utils.__version__.replace(".", "")[0:3]}_{self.player}_{self.multiworld.seed:11}\0',
|
||||
rom_name = bytearray(f'AP{Utils.__version__.replace(".", "")[0:3]}_{world.player}_{world.multiworld.seed:11}\0',
|
||||
'utf8')[:21]
|
||||
rom_name.extend([0] * (21 - len(rom_name)))
|
||||
write_bytes(data, rom_name, 0xFFC6)
|
||||
write_bytes(data, self.multiworld.seed_name.encode(), 0xFFDB)
|
||||
write_bytes(data, self.multiworld.player_name[self.player].encode(), 0xFFF0)
|
||||
write_bytes(data, world.multiworld.seed_name.encode(), 0xFFDB)
|
||||
write_bytes(data, world.multiworld.player_name[world.player].encode(), 0xFFF0)
|
||||
|
||||
self.finished_level_scaling.wait()
|
||||
world.finished_level_scaling.wait()
|
||||
|
||||
write_quizzes(self, data, random)
|
||||
write_quizzes(world, data, random)
|
||||
|
||||
for location in self.multiworld.get_locations(self.player):
|
||||
for location in world.multiworld.get_locations(world.player):
|
||||
if location.party_data:
|
||||
for party in location.party_data:
|
||||
if not isinstance(party["party_address"], list):
|
||||
@@ -588,7 +632,7 @@ def generate_output(self, output_directory: str):
|
||||
continue
|
||||
elif location.rom_address is None:
|
||||
continue
|
||||
if location.item and location.item.player == self.player:
|
||||
if location.item and location.item.player == world.player:
|
||||
if location.rom_address:
|
||||
rom_address = location.rom_address
|
||||
if not isinstance(rom_address, list):
|
||||
@@ -599,7 +643,7 @@ def generate_output(self, output_directory: str):
|
||||
elif " ".join(location.item.name.split()[1:]) in poke_data.pokemon_data.keys():
|
||||
data[address] = poke_data.pokemon_data[" ".join(location.item.name.split()[1:])]["id"]
|
||||
else:
|
||||
item_id = self.item_name_to_id[location.item.name] - 172000000
|
||||
item_id = world.item_name_to_id[location.item.name] - 172000000
|
||||
if item_id > 255:
|
||||
item_id -= 256
|
||||
data[address] = item_id
|
||||
@@ -613,18 +657,18 @@ def generate_output(self, output_directory: str):
|
||||
for address in rom_address:
|
||||
data[address] = 0x2C # AP Item
|
||||
|
||||
outfilepname = f'_P{self.player}'
|
||||
outfilepname += f"_{self.multiworld.get_file_safe_player_name(self.player).replace(' ', '_')}" \
|
||||
if self.multiworld.player_name[self.player] != 'Player%d' % self.player else ''
|
||||
rompath = os.path.join(output_directory, f'AP_{self.multiworld.seed_name}{outfilepname}.gb')
|
||||
outfilepname = f'_P{world.player}'
|
||||
outfilepname += f"_{world.multiworld.get_file_safe_player_name(world.player).replace(' ', '_')}" \
|
||||
if world.multiworld.player_name[world.player] != 'Player%d' % world.player else ''
|
||||
rompath = os.path.join(output_directory, f'AP_{world.multiworld.seed_name}{outfilepname}.gb')
|
||||
with open(rompath, 'wb') as outfile:
|
||||
outfile.write(data)
|
||||
if self.multiworld.game_version[self.player].current_key == "red":
|
||||
patch = RedDeltaPatch(os.path.splitext(rompath)[0] + RedDeltaPatch.patch_file_ending, player=self.player,
|
||||
player_name=self.multiworld.player_name[self.player], patched_path=rompath)
|
||||
if world.options.game_version.current_key == "red":
|
||||
patch = RedDeltaPatch(os.path.splitext(rompath)[0] + RedDeltaPatch.patch_file_ending, player=world.player,
|
||||
player_name=world.multiworld.player_name[world.player], patched_path=rompath)
|
||||
else:
|
||||
patch = BlueDeltaPatch(os.path.splitext(rompath)[0] + BlueDeltaPatch.patch_file_ending, player=self.player,
|
||||
player_name=self.multiworld.player_name[self.player], patched_path=rompath)
|
||||
patch = BlueDeltaPatch(os.path.splitext(rompath)[0] + BlueDeltaPatch.patch_file_ending, player=world.player,
|
||||
player_name=world.multiworld.player_name[world.player], patched_path=rompath)
|
||||
|
||||
patch.write()
|
||||
os.unlink(rompath)
|
||||
|
Reference in New Issue
Block a user