Merged in DR v0.4.0.8
This commit is contained in:
@@ -139,6 +139,7 @@ class World(object):
|
|||||||
set_player_attr('treasure_hunt_total', 0)
|
set_player_attr('treasure_hunt_total', 0)
|
||||||
set_player_attr('potshuffle', False)
|
set_player_attr('potshuffle', False)
|
||||||
set_player_attr('pot_contents', None)
|
set_player_attr('pot_contents', None)
|
||||||
|
set_player_attr('fakeboots', False)
|
||||||
|
|
||||||
set_player_attr('shopsanity', False)
|
set_player_attr('shopsanity', False)
|
||||||
set_player_attr('keydropshuffle', False)
|
set_player_attr('keydropshuffle', False)
|
||||||
@@ -2430,7 +2431,7 @@ access_mode = {"items": 0, "locations": 1, "none": 2}
|
|||||||
|
|
||||||
# byte 6: BSMC BBEE (big, small, maps, compass, bosses, enemies)
|
# byte 6: BSMC BBEE (big, small, maps, compass, bosses, enemies)
|
||||||
boss_mode = {"none": 0, "simple": 1, "full": 2, "random": 3, "chaos": 3}
|
boss_mode = {"none": 0, "simple": 1, "full": 2, "random": 3, "chaos": 3}
|
||||||
enemy_mode = {"none": 0, "shuffled": 1, "random": 2, "chaos": 2}
|
enemy_mode = {"none": 0, "shuffled": 1, "random": 2, "chaos": 2, "legacy": 3}
|
||||||
|
|
||||||
# byte 7: HHHD DP?? (enemy_health, enemy_dmg, potshuffle, ?)
|
# byte 7: HHHD DP?? (enemy_health, enemy_dmg, potshuffle, ?)
|
||||||
e_health = {"default": 0, "easy": 1, "normal": 2, "hard": 3, "expert": 4}
|
e_health = {"default": 0, "easy": 1, "normal": 2, "hard": 3, "expert": 4}
|
||||||
|
|||||||
3
CLI.py
3
CLI.py
@@ -98,7 +98,7 @@ def parse_cli(argv, no_defaults=False):
|
|||||||
'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'openpyramid',
|
'shuffle', 'door_shuffle', 'intensity', 'crystals_ganon', 'crystals_gt', 'openpyramid',
|
||||||
'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'startinventory',
|
'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'startinventory',
|
||||||
'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max',
|
'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max',
|
||||||
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks',
|
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'fakeboots',
|
||||||
'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
|
'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
|
||||||
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
|
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
|
||||||
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'heartbeep',
|
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'heartbeep',
|
||||||
@@ -149,6 +149,7 @@ def parse_settings():
|
|||||||
"ow_fluteshuffle": "vanilla",
|
"ow_fluteshuffle": "vanilla",
|
||||||
"shuffle": "vanilla",
|
"shuffle": "vanilla",
|
||||||
"shufflelinks": False,
|
"shufflelinks": False,
|
||||||
|
"fakeboots": False,
|
||||||
|
|
||||||
"shufflepots": False,
|
"shufflepots": False,
|
||||||
"shuffleenemies": "none",
|
"shuffleenemies": "none",
|
||||||
|
|||||||
@@ -1482,14 +1482,12 @@ def link_entrances(world, player):
|
|||||||
blacksmith_hut = blacksmith_doors.pop()
|
blacksmith_hut = blacksmith_doors.pop()
|
||||||
connect_entrance(world, blacksmith_hut, 'Blacksmiths Hut', player)
|
connect_entrance(world, blacksmith_hut, 'Blacksmiths Hut', player)
|
||||||
doors.remove(blacksmith_hut)
|
doors.remove(blacksmith_hut)
|
||||||
exit_pool.remove(blacksmith_hut)
|
|
||||||
|
|
||||||
# place dam and pyramid fairy, have limited options
|
# place dam and pyramid fairy, have limited options
|
||||||
random.shuffle(bomb_shop_doors)
|
random.shuffle(bomb_shop_doors)
|
||||||
bomb_shop = bomb_shop_doors.pop()
|
bomb_shop = bomb_shop_doors.pop()
|
||||||
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
|
connect_entrance(world, bomb_shop, 'Big Bomb Shop', player)
|
||||||
doors.remove(bomb_shop)
|
doors.remove(bomb_shop)
|
||||||
exit_pool.remove(bomb_shop)
|
|
||||||
|
|
||||||
# handle remaining caves
|
# handle remaining caves
|
||||||
for cave in caves:
|
for cave in caves:
|
||||||
|
|||||||
22
Fill.py
22
Fill.py
@@ -3,7 +3,7 @@ import logging
|
|||||||
|
|
||||||
from BaseClasses import CollectionState
|
from BaseClasses import CollectionState
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
from Regions import shop_to_location_table
|
from Regions import shop_to_location_table, retro_shops
|
||||||
|
|
||||||
|
|
||||||
class FillError(RuntimeError):
|
class FillError(RuntimeError):
|
||||||
@@ -496,6 +496,10 @@ def balance_multiworld_progression(world):
|
|||||||
new_location = replacement_locations.pop()
|
new_location = replacement_locations.pop()
|
||||||
|
|
||||||
new_location.item, old_location.item = old_location.item, new_location.item
|
new_location.item, old_location.item = old_location.item, new_location.item
|
||||||
|
if world.shopsanity[new_location.player]:
|
||||||
|
check_shop_swap(new_location)
|
||||||
|
if world.shopsanity[old_location.player]:
|
||||||
|
check_shop_swap(old_location)
|
||||||
new_location.event, old_location.event = True, False
|
new_location.event, old_location.event = True, False
|
||||||
state.collect(new_location.item, True, new_location)
|
state.collect(new_location.item, True, new_location)
|
||||||
replaced_items = True
|
replaced_items = True
|
||||||
@@ -516,6 +520,18 @@ def balance_multiworld_progression(world):
|
|||||||
raise RuntimeError('Not all required items reachable. Something went terribly wrong here.')
|
raise RuntimeError('Not all required items reachable. Something went terribly wrong here.')
|
||||||
|
|
||||||
|
|
||||||
|
def check_shop_swap(l):
|
||||||
|
if l.parent_region.name in shop_to_location_table:
|
||||||
|
if l.name in shop_to_location_table[l.parent_region.name]:
|
||||||
|
idx = shop_to_location_table[l.parent_region.name].index(l.name)
|
||||||
|
inv_slot = l.parent_region.shop.inventory[idx]
|
||||||
|
inv_slot['item'] = l.item.name
|
||||||
|
elif l.parent_region in retro_shops:
|
||||||
|
idx = retro_shops[l.parent_region.name].index(l.name)
|
||||||
|
inv_slot = l.parent_region.shop.inventory[idx]
|
||||||
|
inv_slot['item'] = l.item.name
|
||||||
|
|
||||||
|
|
||||||
def balance_money_progression(world):
|
def balance_money_progression(world):
|
||||||
logger = logging.getLogger('')
|
logger = logging.getLogger('')
|
||||||
state = CollectionState(world)
|
state = CollectionState(world)
|
||||||
@@ -557,7 +573,6 @@ def balance_money_progression(world):
|
|||||||
for player in range(1, world.players+1):
|
for player in range(1, world.players+1):
|
||||||
logger.debug(f'Money balance for P{player}: Needed: {total_price[player]} Available: {available_money[player]}')
|
logger.debug(f'Money balance for P{player}: Needed: {total_price[player]} Available: {available_money[player]}')
|
||||||
|
|
||||||
|
|
||||||
def get_sphere_locations(sphere_state, locations):
|
def get_sphere_locations(sphere_state, locations):
|
||||||
sphere_state.sweep_for_events(key_only=True, locations=locations)
|
sphere_state.sweep_for_events(key_only=True, locations=locations)
|
||||||
return [loc for loc in locations if sphere_state.can_reach(loc) and sphere_state.not_flooding_a_key(sphere_state.world, loc)]
|
return [loc for loc in locations if sphere_state.can_reach(loc) and sphere_state.not_flooding_a_key(sphere_state.world, loc)]
|
||||||
@@ -672,6 +687,7 @@ def balance_money_progression(world):
|
|||||||
logger.debug(f'Upgrading {best_target.item.name} @ {best_target.name} for 300 Rupees')
|
logger.debug(f'Upgrading {best_target.item.name} @ {best_target.name} for 300 Rupees')
|
||||||
best_target.item = ItemFactory('Rupees (300)', best_target.item.player)
|
best_target.item = ItemFactory('Rupees (300)', best_target.item.player)
|
||||||
best_target.item.location = best_target
|
best_target.item.location = best_target
|
||||||
|
check_shop_swap(best_target.item.location)
|
||||||
else:
|
else:
|
||||||
old_item = best_target.item
|
old_item = best_target.item
|
||||||
logger.debug(f'Swapping {best_target.item.name} @ {best_target.name} for {best_swap.item.name} @ {best_swap.name}')
|
logger.debug(f'Swapping {best_target.item.name} @ {best_target.name} for {best_swap.item.name} @ {best_swap.name}')
|
||||||
@@ -679,6 +695,8 @@ def balance_money_progression(world):
|
|||||||
best_target.item.location = best_target
|
best_target.item.location = best_target
|
||||||
best_swap.item = old_item
|
best_swap.item = old_item
|
||||||
best_swap.item.location = best_swap
|
best_swap.item.location = best_swap
|
||||||
|
check_shop_swap(best_target.item.location)
|
||||||
|
check_shop_swap(best_swap.item.location)
|
||||||
increase = best_value - old_value
|
increase = best_value - old_value
|
||||||
difference -= increase
|
difference -= increase
|
||||||
wallet[target_player] += increase
|
wallet[target_player] += increase
|
||||||
|
|||||||
7
Main.py
7
Main.py
@@ -28,7 +28,7 @@ from Fill import sell_potions, sell_keys, balance_multiworld_progression, balanc
|
|||||||
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops
|
from ItemList import generate_itempool, difficulties, fill_prizes, customize_shops
|
||||||
from Utils import output_path, parse_player_names
|
from Utils import output_path, parse_player_names
|
||||||
|
|
||||||
__version__ = '0.4.0.6-u'
|
__version__ = '0.4.0.8-u'
|
||||||
|
|
||||||
|
|
||||||
class EnemizerError(RuntimeError):
|
class EnemizerError(RuntimeError):
|
||||||
@@ -93,6 +93,7 @@ def main(args, seed=None, fish=None):
|
|||||||
world.treasure_hunt_count = args.triforce_goal.copy()
|
world.treasure_hunt_count = args.triforce_goal.copy()
|
||||||
world.treasure_hunt_total = args.triforce_pool.copy()
|
world.treasure_hunt_total = args.triforce_pool.copy()
|
||||||
world.shufflelinks = args.shufflelinks.copy()
|
world.shufflelinks = args.shufflelinks.copy()
|
||||||
|
world.fakeboots = args.fakeboots.copy()
|
||||||
|
|
||||||
world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)}
|
world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)}
|
||||||
|
|
||||||
@@ -263,12 +264,10 @@ def main(args, seed=None, fish=None):
|
|||||||
or world.enemy_health[player] != 'default' or world.enemy_damage[player] != 'default'
|
or world.enemy_health[player] != 'default' or world.enemy_damage[player] != 'default'
|
||||||
or sprite_random_on_hit)
|
or sprite_random_on_hit)
|
||||||
|
|
||||||
if use_enemizer:
|
|
||||||
base_patch = LocalRom(args.rom) # update base2current.json
|
|
||||||
|
|
||||||
rom = JsonRom() if args.jsonout or use_enemizer else LocalRom(args.rom)
|
rom = JsonRom() if args.jsonout or use_enemizer else LocalRom(args.rom)
|
||||||
|
|
||||||
if use_enemizer and (args.enemizercli or not args.jsonout):
|
if use_enemizer and (args.enemizercli or not args.jsonout):
|
||||||
|
base_patch = LocalRom(args.rom) # update base2current.json (side effect)
|
||||||
if args.rom and not(os.path.isfile(args.rom)):
|
if args.rom and not(os.path.isfile(args.rom)):
|
||||||
raise RuntimeError("Could not find valid base rom for enemizing at expected path %s." % args.rom)
|
raise RuntimeError("Could not find valid base rom for enemizing at expected path %s." % args.rom)
|
||||||
if os.path.exists(args.enemizercli):
|
if os.path.exists(args.enemizercli):
|
||||||
|
|||||||
19
Mystery.py
19
Mystery.py
@@ -150,6 +150,7 @@ def roll_settings(weights):
|
|||||||
ret.dungeon_counters = 'pickup' if ret.door_shuffle != 'vanilla' or ret.compassshuffle == 'on' else 'off'
|
ret.dungeon_counters = 'pickup' if ret.door_shuffle != 'vanilla' or ret.compassshuffle == 'on' else 'off'
|
||||||
|
|
||||||
ret.shufflelinks = get_choice('shufflelinks') == 'on'
|
ret.shufflelinks = get_choice('shufflelinks') == 'on'
|
||||||
|
ret.fakeboots = get_choice('fakeboots') == 'on'
|
||||||
ret.shopsanity = get_choice('shopsanity') == 'on'
|
ret.shopsanity = get_choice('shopsanity') == 'on'
|
||||||
ret.keydropshuffle = get_choice('keydropshuffle') == 'on'
|
ret.keydropshuffle = get_choice('keydropshuffle') == 'on'
|
||||||
ret.mixed_travel = get_choice('mixed_travel') if 'mixed_travel' in weights else 'prevent'
|
ret.mixed_travel = get_choice('mixed_travel') if 'mixed_travel' in weights else 'prevent'
|
||||||
@@ -202,15 +203,17 @@ def roll_settings(weights):
|
|||||||
boss_choice = old_style_bosses[boss_choice]
|
boss_choice = old_style_bosses[boss_choice]
|
||||||
ret.shufflebosses = boss_choice
|
ret.shufflebosses = boss_choice
|
||||||
|
|
||||||
ret.shuffleenemies = {'none': 'none',
|
enemy_choice = get_choice('enemy_shuffle')
|
||||||
'shuffled': 'shuffled',
|
if enemy_choice == 'chaos':
|
||||||
'random': 'chaos'
|
enemy_choice = 'random'
|
||||||
}[get_choice('enemy_shuffle')]
|
ret.shuffleenemies = enemy_choice
|
||||||
|
|
||||||
ret.enemy_damage = {'default': 'default',
|
old_style_damage = {'none': 'default',
|
||||||
'shuffled': 'shuffled',
|
'chaos': 'random'}
|
||||||
'random': 'chaos'
|
damage_choice = get_choice('enemy_damage')
|
||||||
}[get_choice('enemy_damage')]
|
if damage_choice in old_style_damage:
|
||||||
|
damage_choice = old_style_damage[damage_choice]
|
||||||
|
ret.enemy_damage = damage_choice
|
||||||
|
|
||||||
ret.enemy_health = get_choice('enemy_health')
|
ret.enemy_health = get_choice('enemy_health')
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,35 @@ Thanks to qadan, cheuer, & compiling
|
|||||||
|
|
||||||
# Bug Fixes and Notes.
|
# Bug Fixes and Notes.
|
||||||
|
|
||||||
|
* 0.4.0.8
|
||||||
|
* Ganon jokes added for when silvers aren't available
|
||||||
|
* Some text updated (Blind jokes, uncle text)
|
||||||
|
* Fixed some enemizer Mystery settings
|
||||||
|
* Added a setting that's random enemy shuffle without Unkillable Thieves possible
|
||||||
|
* Fixed shop spoiler when money balancing/multiworld balancing
|
||||||
|
* Fixed a problem with insanity
|
||||||
|
* Fixed an issue with the credit stats specific to DR (e.g. collection rate total)
|
||||||
|
* More helpful error message when bps is missing?
|
||||||
|
* Minor generation issues involving enemizer and the link sprite
|
||||||
|
* Baserom updates (from Bonta, kan, qwertymodo, ardnaxelark)
|
||||||
|
* Boss icon on dungeon map (if you have a compass)
|
||||||
|
* Progressive bow sprite replacement
|
||||||
|
* Quickswap - consecutive special swaps
|
||||||
|
* Bonk Counter
|
||||||
|
* One mind
|
||||||
|
* MSU fix
|
||||||
|
* Chest turn tracking (not yet in credits)
|
||||||
|
* Damaged and magic stats in credits (gt bk removed)
|
||||||
|
* Fix for infinite bombs
|
||||||
|
* Fake boots option
|
||||||
|
* Always allowed medallions for swordless (no option yet)
|
||||||
|
* 0.4.0.7
|
||||||
|
* Reduce flashing option added
|
||||||
|
* Sprite author credit added
|
||||||
|
* Ranged Crystal switch rules tweaked
|
||||||
|
* Baserom update: includes Credits Speedup, reduced flashing option, msu resume (but turned off by default)
|
||||||
|
* Create link sprite's zspr from local ROM and no longer attempts to download it from website
|
||||||
|
* Some minor bug fixes
|
||||||
* 0.4.0.6
|
* 0.4.0.6
|
||||||
* Hints now default to off
|
* Hints now default to off
|
||||||
* The maiden gives you a hint to the attic if you bring her to the unlit boss room
|
* The maiden gives you a hint to the attic if you bring her to the unlit boss room
|
||||||
|
|||||||
120
Rom.py
120
Rom.py
@@ -9,17 +9,20 @@ import random
|
|||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
|
try:
|
||||||
import bps.apply
|
import bps.apply
|
||||||
import bps.io
|
import bps.io
|
||||||
|
except ImportError:
|
||||||
|
raise Exception('Could not load BPS module')
|
||||||
|
|
||||||
from BaseClasses import CollectionState, ShopType, Region, Location, OWEdge, Door, DoorType, RegionType, PotItem
|
from BaseClasses import CollectionState, ShopType, Region, Location, OWEdge, Door, DoorType, RegionType, PotItem
|
||||||
from DoorShuffle import compass_data, DROptions, boss_indicator
|
from DoorShuffle import compass_data, DROptions, boss_indicator
|
||||||
from Dungeons import dungeon_music_addresses
|
from Dungeons import dungeon_music_addresses
|
||||||
from KeyDoorShuffle import count_locations_exclude_logic
|
|
||||||
from Regions import location_table, shop_to_location_table, retro_shops
|
from Regions import location_table, shop_to_location_table, retro_shops
|
||||||
from RoomData import DoorKind
|
from RoomData import DoorKind
|
||||||
from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable
|
from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable
|
||||||
from Text import Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts, junk_texts
|
from Text import Uncle_texts, Ganon1_texts, Ganon_Phase_3_No_Silvers_texts, TavernMan_texts, Sahasrahla2_texts
|
||||||
|
from Text import Triforce_texts, Blind_texts, BombShop2_texts, junk_texts
|
||||||
from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts, LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts, Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names
|
from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts, LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts, Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names
|
||||||
from Utils import output_path, local_path, int16_as_bytes, int32_as_bytes, snes_to_pc
|
from Utils import output_path, local_path, int16_as_bytes, int32_as_bytes, snes_to_pc
|
||||||
from Items import ItemFactory
|
from Items import ItemFactory
|
||||||
@@ -28,7 +31,7 @@ from OverworldShuffle import default_flute_connections, flute_data
|
|||||||
|
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = '5d2041f4387123c2de98dd41e6e5c4c6'
|
RANDOMIZERBASEHASH = 'f0a6138148c13414ff4dc89dc0101de6'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
@@ -201,7 +204,7 @@ def patch_enemizer(world, player, rom, baserom_path, enemizercli, random_sprite_
|
|||||||
options = {
|
options = {
|
||||||
'RandomizeEnemies': world.enemy_shuffle[player] != 'none',
|
'RandomizeEnemies': world.enemy_shuffle[player] != 'none',
|
||||||
'RandomizeEnemiesType': 3,
|
'RandomizeEnemiesType': 3,
|
||||||
'RandomizeBushEnemyChance': world.enemy_shuffle[player] == 'random',
|
'RandomizeBushEnemyChance': world.enemy_shuffle[player] in ['random', 'legacy'],
|
||||||
'RandomizeEnemyHealthRange': world.enemy_health[player] != 'default',
|
'RandomizeEnemyHealthRange': world.enemy_health[player] != 'default',
|
||||||
'RandomizeEnemyHealthType': {'default': 0, 'easy': 0, 'normal': 1, 'hard': 2, 'expert': 3}[world.enemy_health[player]],
|
'RandomizeEnemyHealthType': {'default': 0, 'easy': 0, 'normal': 1, 'hard': 2, 'expert': 3}[world.enemy_health[player]],
|
||||||
'OHKO': False,
|
'OHKO': False,
|
||||||
@@ -247,9 +250,9 @@ def patch_enemizer(world, player, rom, baserom_path, enemizercli, random_sprite_
|
|||||||
'SwordGraphics': "sword_gfx/normal.gfx",
|
'SwordGraphics': "sword_gfx/normal.gfx",
|
||||||
'BeeMizer': False,
|
'BeeMizer': False,
|
||||||
'BeesLevel': 0,
|
'BeesLevel': 0,
|
||||||
'RandomizeTileTrapPattern': world.enemy_shuffle[player] == 'random',
|
'RandomizeTileTrapPattern': world.enemy_shuffle[player] in ['random', 'legacy'],
|
||||||
'RandomizeTileTrapFloorTile': False,
|
'RandomizeTileTrapFloorTile': False,
|
||||||
'AllowKillableThief': bool(random.randint(0, 1)) if world.enemy_shuffle[player] == 'random' else world.enemy_shuffle[player] != 'none',
|
'AllowKillableThief': bool(random.randint(0, 1)) if world.enemy_shuffle[player] == 'legacy' else world.enemy_shuffle[player] != 'none',
|
||||||
'RandomizeSpriteOnHit': random_sprite_on_hit,
|
'RandomizeSpriteOnHit': random_sprite_on_hit,
|
||||||
'DebugMode': False,
|
'DebugMode': False,
|
||||||
'DebugForceEnemy': False,
|
'DebugForceEnemy': False,
|
||||||
@@ -891,7 +894,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
write_int16(rom, 0x187010, credits_total) # dynamic credits
|
write_int16(rom, 0x187010, credits_total) # dynamic credits
|
||||||
if credits_total != 216:
|
if credits_total != 216:
|
||||||
# collection rate address:
|
# collection rate address:
|
||||||
cr_address = 0x2391CC
|
cr_address = 0x2391C4
|
||||||
cr_pc = cr_address - 0x120000 # convert to pc
|
cr_pc = cr_address - 0x120000 # convert to pc
|
||||||
mid_top, mid_bot = credits_digit((credits_total // 10) % 10)
|
mid_top, mid_bot = credits_digit((credits_total // 10) % 10)
|
||||||
last_top, last_bot = credits_digit(credits_total % 10)
|
last_top, last_bot = credits_digit(credits_total % 10)
|
||||||
@@ -902,25 +905,6 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
rom.write_byte(cr_pc+0x3a, mid_bot)
|
rom.write_byte(cr_pc+0x3a, mid_bot)
|
||||||
rom.write_byte(cr_pc+0x3b, last_bot)
|
rom.write_byte(cr_pc+0x3b, last_bot)
|
||||||
|
|
||||||
if world.keydropshuffle[player] or world.doorShuffle[player] != 'vanilla':
|
|
||||||
gt = world.dungeon_layouts[player]['Ganons Tower']
|
|
||||||
gt_logic = world.key_logic[player]['Ganons Tower']
|
|
||||||
total = 0
|
|
||||||
for region in gt.master_sector.regions:
|
|
||||||
total += count_locations_exclude_logic(region.locations, gt_logic)
|
|
||||||
# rom.write_byte(0x187012, total) # dynamic credits
|
|
||||||
# gt big key address:
|
|
||||||
gtbk_address = 0x2390EE
|
|
||||||
gtbk_pc = gtbk_address - 0x120000 # convert to pc
|
|
||||||
mid_top, mid_bot = credits_digit(total // 10)
|
|
||||||
last_top, last_bot = credits_digit(total % 10)
|
|
||||||
# top half
|
|
||||||
rom.write_byte(gtbk_pc+0x1c, mid_top)
|
|
||||||
rom.write_byte(gtbk_pc+0x1d, last_top)
|
|
||||||
# bottom half
|
|
||||||
rom.write_byte(gtbk_pc+0x3a, mid_bot)
|
|
||||||
rom.write_byte(gtbk_pc+0x3b, last_bot)
|
|
||||||
|
|
||||||
# patch medallion requirements
|
# patch medallion requirements
|
||||||
if world.required_medallions[player][0] == 'Bombos':
|
if world.required_medallions[player][0] == 'Bombos':
|
||||||
rom.write_byte(0x180022, 0x00) # requirement
|
rom.write_byte(0x180022, 0x00) # requirement
|
||||||
@@ -1264,6 +1248,9 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
|
|||||||
rom.write_byte(0x18017E, 0x01) # Fairy fountains only trade in bottles
|
rom.write_byte(0x18017E, 0x01) # Fairy fountains only trade in bottles
|
||||||
|
|
||||||
# Starting equipment
|
# Starting equipment
|
||||||
|
if world.fakeboots[player]:
|
||||||
|
rom.write_byte(0x18008E, 0x01)
|
||||||
|
|
||||||
equip = [0] * (0x340 + 0x4F)
|
equip = [0] * (0x340 + 0x4F)
|
||||||
equip[0x36C] = 0x18
|
equip[0x36C] = 0x18
|
||||||
equip[0x36D] = 0x18
|
equip[0x36D] = 0x18
|
||||||
@@ -1724,7 +1711,8 @@ def hud_format_text(text):
|
|||||||
|
|
||||||
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite,
|
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite,
|
||||||
ow_palettes, uw_palettes, reduce_flashing):
|
ow_palettes, uw_palettes, reduce_flashing):
|
||||||
if not os.path.exists("data/sprites/official/001.link.1.zspr"):
|
|
||||||
|
if not os.path.exists("data/sprites/official/001.link.1.zspr") and rom.orig_buffer:
|
||||||
dump_zspr(rom.orig_buffer[0x80000:0x87000], rom.orig_buffer[0xdd308:0xdd380],
|
dump_zspr(rom.orig_buffer[0x80000:0x87000], rom.orig_buffer[0xdd308:0xdd380],
|
||||||
rom.orig_buffer[0xdedf5:0xdedf9], "data/sprites/official/001.link.1.zspr", "Nintendo", "Link")
|
rom.orig_buffer[0xdedf5:0xdedf9], "data/sprites/official/001.link.1.zspr", "Nintendo", "Link")
|
||||||
|
|
||||||
@@ -1812,7 +1800,6 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr
|
|||||||
|
|
||||||
if reduce_flashing:
|
if reduce_flashing:
|
||||||
rom.write_byte(0x18017f, 1)
|
rom.write_byte(0x18017f, 1)
|
||||||
|
|
||||||
default_ow_palettes(rom)
|
default_ow_palettes(rom)
|
||||||
if ow_palettes == 'random':
|
if ow_palettes == 'random':
|
||||||
randomize_ow_palettes(rom)
|
randomize_ow_palettes(rom)
|
||||||
@@ -1883,6 +1870,61 @@ def dump_zspr(basesprite, basepalette, baseglove, outfilename, author_name, spri
|
|||||||
with open('%s' % outfilename, "wb") as zspr_file:
|
with open('%s' % outfilename, "wb") as zspr_file:
|
||||||
zspr_file.write(write_buffer)
|
zspr_file.write(write_buffer)
|
||||||
|
|
||||||
|
# .zspr file dumping logic copied with permission from SpriteSomething:
|
||||||
|
# https://github.com/Artheau/SpriteSomething/blob/master/source/meta/classes/spritelib.py#L443 (thanks miketrethewey!)
|
||||||
|
def dump_zspr(basesprite, basepalette, baseglove, outfilename, author_name, sprite_name):
|
||||||
|
palettes = basepalette
|
||||||
|
# Add glove data
|
||||||
|
palettes.extend(baseglove)
|
||||||
|
HEADER_STRING = b"ZSPR"
|
||||||
|
VERSION = 0x01
|
||||||
|
SPRITE_TYPE = 0x01 # this format has "1" for the player sprite
|
||||||
|
RESERVED_BYTES = b'\x00\x00\x00\x00\x00\x00'
|
||||||
|
QUAD_BYTE_NULL_CHAR = b'\x00\x00\x00\x00'
|
||||||
|
DOUBLE_BYTE_NULL_CHAR = b'\x00\x00'
|
||||||
|
SINGLE_BYTE_NULL_CHAR = b'\x00'
|
||||||
|
|
||||||
|
write_buffer = bytearray()
|
||||||
|
|
||||||
|
write_buffer.extend(HEADER_STRING)
|
||||||
|
write_buffer.extend(struct.pack('B', VERSION)) # as_u8
|
||||||
|
checksum_start = len(write_buffer)
|
||||||
|
write_buffer.extend(QUAD_BYTE_NULL_CHAR) # checksum
|
||||||
|
sprite_sheet_pointer = len(write_buffer)
|
||||||
|
write_buffer.extend(QUAD_BYTE_NULL_CHAR)
|
||||||
|
write_buffer.extend(struct.pack('<H', len(basesprite))) # as_u16
|
||||||
|
palettes_pointer = len(write_buffer)
|
||||||
|
write_buffer.extend(QUAD_BYTE_NULL_CHAR)
|
||||||
|
write_buffer.extend(struct.pack('<H', len(palettes))) # as_u16
|
||||||
|
write_buffer.extend(struct.pack('<H', SPRITE_TYPE)) # as_u16
|
||||||
|
write_buffer.extend(RESERVED_BYTES)
|
||||||
|
# sprite.name
|
||||||
|
write_buffer.extend(sprite_name.encode('utf-16-le'))
|
||||||
|
write_buffer.extend(DOUBLE_BYTE_NULL_CHAR)
|
||||||
|
# author.name
|
||||||
|
write_buffer.extend(author_name.encode('utf-16-le'))
|
||||||
|
write_buffer.extend(DOUBLE_BYTE_NULL_CHAR)
|
||||||
|
# author.name-short
|
||||||
|
write_buffer.extend(author_name.encode('ascii'))
|
||||||
|
write_buffer.extend(SINGLE_BYTE_NULL_CHAR)
|
||||||
|
write_buffer[sprite_sheet_pointer:sprite_sheet_pointer +
|
||||||
|
4] = struct.pack('<L', len(write_buffer)) # as_u32
|
||||||
|
write_buffer.extend(basesprite)
|
||||||
|
write_buffer[palettes_pointer:palettes_pointer +
|
||||||
|
4] = struct.pack('<L', len(write_buffer)) # as_u32
|
||||||
|
write_buffer.extend(palettes)
|
||||||
|
|
||||||
|
checksum = (sum(write_buffer) + 0xFF + 0xFF) % 0x10000
|
||||||
|
checksum_complement = 0xFFFF - checksum
|
||||||
|
|
||||||
|
write_buffer[checksum_start:checksum_start +
|
||||||
|
2] = struct.pack('<H', checksum) # as_u16
|
||||||
|
write_buffer[checksum_start + 2:checksum_start +
|
||||||
|
4] = struct.pack('<H', checksum_complement) # as_u16
|
||||||
|
|
||||||
|
with open('%s' % outfilename, "wb") as zspr_file:
|
||||||
|
zspr_file.write(write_buffer)
|
||||||
|
|
||||||
def write_sprite(rom, sprite):
|
def write_sprite(rom, sprite):
|
||||||
if not sprite.valid:
|
if not sprite.valid:
|
||||||
return
|
return
|
||||||
@@ -2222,24 +2264,30 @@ def write_strings(rom, world, player, team):
|
|||||||
|
|
||||||
# We still need the older hints of course. Those are done here.
|
# We still need the older hints of course. Those are done here.
|
||||||
|
|
||||||
|
no_silver_text = Ganon_Phase_3_No_Silvers_texts[random.randint(0, len(Ganon_Phase_3_No_Silvers_texts) - 1)]
|
||||||
|
|
||||||
silverarrows = world.find_items('Silver Arrows', player)
|
silverarrows = world.find_items('Silver Arrows', player)
|
||||||
random.shuffle(silverarrows)
|
random.shuffle(silverarrows)
|
||||||
silverarrow_hint = (' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!'
|
if silverarrows:
|
||||||
tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
hint_phrase = hint_text(silverarrows[0]).replace("Ganon's", "my")
|
||||||
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
silverarrow_hint = f'Did you find the silver arrows {hint_phrase}?'
|
||||||
|
else:
|
||||||
|
silverarrow_hint = no_silver_text
|
||||||
|
tt['ganon_phase_3_no_silvers'] = silverarrow_hint
|
||||||
|
tt['ganon_phase_3_no_silvers_alt'] = silverarrow_hint
|
||||||
|
|
||||||
prog_bow_locs = world.find_items('Progressive Bow', player)
|
prog_bow_locs = world.find_items('Progressive Bow', player)
|
||||||
distinguished_prog_bow_loc = next((location for location in prog_bow_locs if location.item.code == 0x65), None)
|
distinguished_prog_bow_loc = next((location for location in prog_bow_locs if location.item.code == 0x65), None)
|
||||||
progressive_silvers = world.difficulty_requirements[player].progressive_bow_limit >= 2 or world.swords[player] == 'swordless'
|
progressive_silvers = world.difficulty_requirements[player].progressive_bow_limit >= 2 or world.swords[player] == 'swordless'
|
||||||
if distinguished_prog_bow_loc:
|
if distinguished_prog_bow_loc:
|
||||||
prog_bow_locs.remove(distinguished_prog_bow_loc)
|
prog_bow_locs.remove(distinguished_prog_bow_loc)
|
||||||
silverarrow_hint = (' %s?' % hint_text(distinguished_prog_bow_loc).replace('Ganon\'s', 'my')) if progressive_silvers else '?\nI think not!'
|
hint_phrase = hint_text(distinguished_prog_bow_loc).replace("Ganon's", "my")
|
||||||
tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
silverarrow_hint = f'Did you find the silver arrows {hint_phrase}?' if progressive_silvers else no_silver_text
|
||||||
|
tt['ganon_phase_3_no_silvers'] = silverarrow_hint
|
||||||
if any(prog_bow_locs):
|
if any(prog_bow_locs):
|
||||||
silverarrow_hint = (' %s?' % hint_text(random.choice(prog_bow_locs)).replace('Ganon\'s', 'my')) if progressive_silvers else '?\nI think not!'
|
hint_phrase = hint_text(random.choice(prog_bow_locs)).replace("Ganon's", "my")
|
||||||
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
silverarrow_hint = f'Did you find the silver arrows {hint_phrase}?' if progressive_silvers else no_silver_text
|
||||||
|
tt['ganon_phase_3_no_silvers_alt'] = silverarrow_hint
|
||||||
|
|
||||||
crystal5 = world.find_items('Crystal 5', player)[0]
|
crystal5 = world.find_items('Crystal 5', player)[0]
|
||||||
crystal6 = world.find_items('Crystal 6', player)[0]
|
crystal6 = world.find_items('Crystal 6', player)[0]
|
||||||
|
|||||||
93
Text.py
93
Text.py
@@ -21,13 +21,14 @@ text_addresses = {'Pedestal': (0x180300, 256),
|
|||||||
|
|
||||||
|
|
||||||
Uncle_texts = [
|
Uncle_texts = [
|
||||||
|
# these ones are er specific
|
||||||
'Good Luck!\nYou will need it.',
|
'Good Luck!\nYou will need it.',
|
||||||
'Forward this message to 10 other people or this seed will be awful.',
|
'Forward this message to 10 other people or this seed will be awful.',
|
||||||
'I hope you like your seeds bootless and fluteless.',
|
'I hope you like your seeds bootless and fluteless.',
|
||||||
'10\n9\n8\n7\n6\n5\n4\n3\n2\n1\nGo!',
|
'10\n9\n8\n7\n6\n5\n4\n3\n2\n1\nGo!',
|
||||||
'I\'m off to visit cousin Fritzl.',
|
'I\'m off to visit cousin Fritzl.',
|
||||||
'Don\'t forget to check Antlion Cave.'
|
'Don\'t forget to check Antlion Cave.'
|
||||||
] * 2 + [
|
# these ones are from web randomizer
|
||||||
"We're out of\nWeetabix. To\nthe store!",
|
"We're out of\nWeetabix. To\nthe store!",
|
||||||
"This seed is\nbootless\nuntil boots.",
|
"This seed is\nbootless\nuntil boots.",
|
||||||
"Why do we only\nhave one bed?",
|
"Why do we only\nhave one bed?",
|
||||||
@@ -66,15 +67,32 @@ Uncle_texts = [
|
|||||||
"Get to the\nchop...\ncastle!",
|
"Get to the\nchop...\ncastle!",
|
||||||
"Come with me\nif you want\nto live",
|
"Come with me\nif you want\nto live",
|
||||||
"I must go\nmy planet\nneeds me",
|
"I must go\nmy planet\nneeds me",
|
||||||
|
"Are we in\ngo mode yet?",
|
||||||
|
"Darn, I\nthought this\nwas combo.",
|
||||||
|
"Don't check\nanything I\nwouldn't!",
|
||||||
|
"I know where\nthe bow is!\n",
|
||||||
|
"This message\nwill self\ndestruct.",
|
||||||
|
"Time to cast\nMeteo on\nGanon!",
|
||||||
|
"I have a\nlong, full\nlife ahead!",
|
||||||
|
"Why did that\nsoda have a\nskull on it?",
|
||||||
|
"Something\nrandom just\ncame up.",
|
||||||
|
"I'm bad at\nthis. Can you\ndo it for me?",
|
||||||
|
"Link!\n Wake up!\n ... Bye!",
|
||||||
|
"Text me when\nyou hit\ngo mode.",
|
||||||
|
"Turn off the\nstove before\nyou leave.",
|
||||||
|
"It's raining.\nI'm taking\nthe umbrella.",
|
||||||
|
"Count to 30.\nThen come\nfind me.",
|
||||||
|
"Gonna shuffle\nall the items\nreal quick."
|
||||||
]
|
]
|
||||||
Triforce_texts = [
|
Triforce_texts = [
|
||||||
|
# these ones are er specific
|
||||||
'Product has Hole in center. Bad seller, 0 out of 5.',
|
'Product has Hole in center. Bad seller, 0 out of 5.',
|
||||||
'Who stole the fourth triangle?',
|
'Who stole the fourth triangle?',
|
||||||
'Trifource?\nMore Like Tritrice, am I right?'
|
'Trifource?\nMore Like Tritrice, am I right?'
|
||||||
'\n Well Done!',
|
'\n Well Done!',
|
||||||
'You just wasted 2 hours of your life.',
|
'You just wasted 2 hours of your life.',
|
||||||
'This was meant to be a trapezoid'
|
'This was meant to be a trapezoid',
|
||||||
] * 2 + [
|
# these ones are from web randomizer
|
||||||
"\n G G",
|
"\n G G",
|
||||||
"All your base\nare belong\nto us.",
|
"All your base\nare belong\nto us.",
|
||||||
"You have ended\nthe domination\nof Dr. Wily",
|
"You have ended\nthe domination\nof Dr. Wily",
|
||||||
@@ -107,6 +125,13 @@ Triforce_texts = [
|
|||||||
"You get one\nwish. Choose\nwisely, hero!",
|
"You get one\nwish. Choose\nwisely, hero!",
|
||||||
"Can you please\nbreak us three\nup? Thanks.",
|
"Can you please\nbreak us three\nup? Thanks.",
|
||||||
" Pick us up\n before we\n get dizzy!",
|
" Pick us up\n before we\n get dizzy!",
|
||||||
|
"Thank you,\nMikey. You’re\n2 minutes late",
|
||||||
|
"This was a\n7000 series\ntrain.",
|
||||||
|
" I'd buy\n that for\n a rupee!",
|
||||||
|
" Did you like\n that bow\n placement?",
|
||||||
|
"I promise the\nnext seed will\nbe better.",
|
||||||
|
"\n Honk.",
|
||||||
|
"Breakfast\nis served!",
|
||||||
]
|
]
|
||||||
BombShop2_texts = ['Bombs!\nBombs!\nBiggest!\nBestest!\nGreatest!\nBoomest!']
|
BombShop2_texts = ['Bombs!\nBombs!\nBiggest!\nBestest!\nGreatest!\nBoomest!']
|
||||||
Sahasrahla2_texts = ['You already got my item, idiot.', 'Why are you still talking to me?', 'This text won\'t change.', 'Have you met my brother, Hasarahshla?']
|
Sahasrahla2_texts = ['You already got my item, idiot.', 'Why are you still talking to me?', 'This text won\'t change.', 'Have you met my brother, Hasarahshla?']
|
||||||
@@ -145,6 +170,34 @@ Blind_texts = [
|
|||||||
"I tried to\ncatch fog,\nbut I mist.",
|
"I tried to\ncatch fog,\nbut I mist.",
|
||||||
"Winter is a\ngreat time\nto chill.",
|
"Winter is a\ngreat time\nto chill.",
|
||||||
"Do you think\nthe Ice Rod\nis cool?",
|
"Do you think\nthe Ice Rod\nis cool?",
|
||||||
|
"Pyramids?\nI never saw\nthe point.",
|
||||||
|
"Stone golems\nare created as\nblank slates.",
|
||||||
|
"Desert humor\nis often dry.\n",
|
||||||
|
"Ganon is a\nbacon of\ndespair!",
|
||||||
|
"Butchering\ncows means\nhigh steaks.",
|
||||||
|
"I can't search\nthe web...\nToo many links",
|
||||||
|
"I can whistle\nMost pitches\nbut I can't C",
|
||||||
|
"The Blinds\nStore is\ncurtain death",
|
||||||
|
"Dark Aga Rooms\nare not a\nbright idea.",
|
||||||
|
"Best advice\nfor a Goron?\nBe Boulder.",
|
||||||
|
"Equestrian\nservices are\na stable job.",
|
||||||
|
"Do I like\ndrills? Just\na bit.",
|
||||||
|
"I'd shell out\ngood rupees\nfor a conch.",
|
||||||
|
"Current\naffairs are\nshocking!",
|
||||||
|
"A lying Goron\ndeals in\nboulderdash.",
|
||||||
|
"A bread joke?\nEh, it'd be\nhalf baked.",
|
||||||
|
"I could take\na stab at a\nsword pun.",
|
||||||
|
"Gloves open\na handful\nof checks",
|
||||||
|
"Red mail?\nReturn to\nsender.",
|
||||||
|
"For sale:\nBaby boots,\nNever found",
|
||||||
|
"SRL or rtGG?\nI prefer the\nLadder",
|
||||||
|
"Ladders are\nalways up\nto something",
|
||||||
|
"Zelda's\nfashion is\nvery chic",
|
||||||
|
"Zombie geese\nare waterfoul.\n",
|
||||||
|
"I bought some\ncuccos for a\npoultry sum.",
|
||||||
|
"The stratus of\nclouds is up\nin the air.",
|
||||||
|
"Tie two ropes\ntogether?!\nI think knot!",
|
||||||
|
"Time for you\nto go on a\nBlind date!"
|
||||||
]
|
]
|
||||||
Ganon1_texts = [
|
Ganon1_texts = [
|
||||||
"Start your day\nsmiling with a\ndelicious\nwhole grain\nbreakfast\ncreated for\nyour\nincredible\ninsides.",
|
"Start your day\nsmiling with a\ndelicious\nwhole grain\nbreakfast\ncreated for\nyour\nincredible\ninsides.",
|
||||||
@@ -171,6 +224,40 @@ Ganon1_texts = [
|
|||||||
"Life, dreams,\nhope...\nWhere'd they\ncome from? And\nwhere are they\nheaded? These\nthings... I am\ngoing to\ndestroy!",
|
"Life, dreams,\nhope...\nWhere'd they\ncome from? And\nwhere are they\nheaded? These\nthings... I am\ngoing to\ndestroy!",
|
||||||
"My minions all\nfailed to\nguard those\nitems?!\n\nWhy am I\nsurrounded by\nincompetent\nfools?!",
|
"My minions all\nfailed to\nguard those\nitems?!\n\nWhy am I\nsurrounded by\nincompetent\nfools?!",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Ganon_Phase_3_No_Silvers_texts = [
|
||||||
|
"Did you find\nthe arrows on\nPlanet Zebes?",
|
||||||
|
"Did you find\nthe arrows?\nI think not.",
|
||||||
|
"Silver arrows?\nI have never\nheard of them",
|
||||||
|
"Did you find\nthe arrows on\nThe Moon?",
|
||||||
|
"Did you find\nthe arrows\nIn dev null?",
|
||||||
|
"I have sold\nthe arrows for\na green big 20",
|
||||||
|
"Did you find\nThe arrows in\nCount Dracula?",
|
||||||
|
"Error 404\nSilver arrows\nnot found.",
|
||||||
|
"No arrows for\nYou today,\nSorry",
|
||||||
|
"No arrows?\nCheck your\njunk mail."
|
||||||
|
"Careful, all\nthat spinning\nmakes me dizzy",
|
||||||
|
"Did you find\nthe arrows in\nJabu's belly?",
|
||||||
|
"Silver is not\nan appropriate\narrow material",
|
||||||
|
"Did you find\nthe arrows in\nNarnia?",
|
||||||
|
"Are you ready\nTo spin\nTo win?",
|
||||||
|
"DID YOU FIND\nTHE ARROWS IN\nKEFKA'S TOWER",
|
||||||
|
"Did you find\nthe arrows in\nRecycle Bin?",
|
||||||
|
"Silver Arrows?\n\nLUL",
|
||||||
|
"Imagine\nfinding the\narrows",
|
||||||
|
"Did you find\nsilvers in\nscenic Ohio?",
|
||||||
|
"Did you find\nThe arrows in\n*mumblemumble*",
|
||||||
|
"\nSpin To Win!\n",
|
||||||
|
"did you find\nthe arrows in\nthe hourglass?",
|
||||||
|
"Silver Arrows\nare so v30",
|
||||||
|
"OH, NO, THEY\nACTUALLY SAID\nSILVER MARROW",
|
||||||
|
"SURELY THE\nLEFTMOST TILES\nWILL STAY UP",
|
||||||
|
"Did you find\nthe arrows in\nWorld 4-2?",
|
||||||
|
"You Spin Me\nRight Round\nLike A Record",
|
||||||
|
"SILLY HERO,\nSILVER IS FOR\nWEREWOLVES!",
|
||||||
|
"Did you find\nthe silvers in\nganti's ears",
|
||||||
|
]
|
||||||
|
|
||||||
TavernMan_texts = [
|
TavernMan_texts = [
|
||||||
"What do you\ncall a blind\ndinosaur?\na doyouthink-\nhesaurus.",
|
"What do you\ncall a blind\ndinosaur?\na doyouthink-\nhesaurus.",
|
||||||
"A blind man\nwalks into\na bar.\nAnd a table.\nAnd a chair.",
|
"A blind man\nwalks into\na bar.\nAnd a table.\nAnd a chair.",
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ dw 0
|
|||||||
;Hooks
|
;Hooks
|
||||||
org $02a999
|
org $02a999
|
||||||
jsl OWEdgeTransition : nop #4 ;LDA $02A4E3,X : ORA $7EF3CA
|
jsl OWEdgeTransition : nop #4 ;LDA $02A4E3,X : ORA $7EF3CA
|
||||||
|
;org $02e238 ;LDX #$9E : - DEX : DEX : CMP $DAEE,X : BNE -
|
||||||
|
;jsl OWSpecialTransition : nop #5
|
||||||
|
|
||||||
; flute menu cancel
|
; flute menu cancel
|
||||||
org $0ab7af ;LDA $F2 : ORA $F0 : AND #$C0
|
org $0ab7af ;LDA $F2 : ORA $F0 : AND #$C0
|
||||||
@@ -285,7 +287,8 @@ OWNewDestination:
|
|||||||
++ lda $84 : !add 1,s : sta $84 : pla : pla
|
++ lda $84 : !add 1,s : sta $84 : pla : pla
|
||||||
|
|
||||||
.adjustMainAxis
|
.adjustMainAxis
|
||||||
LDA $84 : SEC : SBC #$0400 : AND #$0F00 : ASL : XBA : STA $88 ; vram
|
;LDA $84 : SEC : SBC #$0400 : AND #$0F80 : ASL : XBA : STA $88 ; vram
|
||||||
|
LDA $84 : SEC : SBC #$0400 : AND #$0F00 : ASL : XBA : STA $88
|
||||||
LDA $84 : SEC : SBC #$0010 : AND #$003E : LSR : STA $86
|
LDA $84 : SEC : SBC #$0010 : AND #$003E : LSR : STA $86
|
||||||
|
|
||||||
pla : pla : sep #$10 : ldy $418
|
pla : pla : sep #$10 : ldy $418
|
||||||
@@ -346,7 +349,7 @@ OWNewDestination:
|
|||||||
; turn into bunny
|
; turn into bunny
|
||||||
lda $5d : cmp #$17 : beq .return
|
lda $5d : cmp #$17 : beq .return
|
||||||
lda #$17 : sta $5d
|
lda #$17 : sta $5d
|
||||||
lda #$01 : sta $02e0
|
lda #$01 : sta $2e0
|
||||||
bra .return
|
bra .return
|
||||||
.nobunny
|
.nobunny
|
||||||
lda $5d : cmp #$17 : bne .return
|
lda $5d : cmp #$17 : bne .return
|
||||||
@@ -356,6 +359,11 @@ OWNewDestination:
|
|||||||
lda $05 : sta $8a
|
lda $05 : sta $8a
|
||||||
rep #$30 : rts
|
rep #$30 : rts
|
||||||
}
|
}
|
||||||
|
OWSpecialTransition:
|
||||||
|
{
|
||||||
|
LDX #$9E
|
||||||
|
- DEX : DEX : CMP $DAEE,X : BNE -
|
||||||
|
}
|
||||||
|
|
||||||
;Data
|
;Data
|
||||||
org $aaa000
|
org $aaa000
|
||||||
|
|||||||
Binary file not shown.
@@ -354,6 +354,10 @@
|
|||||||
"action": "store_true",
|
"action": "store_true",
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
},
|
},
|
||||||
|
"fakeboots": {
|
||||||
|
"action": "store_true",
|
||||||
|
"type": "bool"
|
||||||
|
},
|
||||||
"calc_playthrough": {
|
"calc_playthrough": {
|
||||||
"action": "store_false",
|
"action": "store_false",
|
||||||
"type": "bool"
|
"type": "bool"
|
||||||
@@ -384,7 +388,8 @@
|
|||||||
"choices": [
|
"choices": [
|
||||||
"none",
|
"none",
|
||||||
"shuffled",
|
"shuffled",
|
||||||
"random"
|
"random",
|
||||||
|
"legacy"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"enemy_health": {
|
"enemy_health": {
|
||||||
|
|||||||
@@ -290,6 +290,7 @@
|
|||||||
"Keys are universal, shooting arrows costs rupees,",
|
"Keys are universal, shooting arrows costs rupees,",
|
||||||
"and a few other little things make this more like Zelda-1. (default: %(default)s)"
|
"and a few other little things make this more like Zelda-1. (default: %(default)s)"
|
||||||
],
|
],
|
||||||
|
"fakeboots": [ " Players starts with fake boots that allow dashing but no item checks (default: %(default)s"],
|
||||||
"startinventory": [ "Specifies a list of items that will be in your starting inventory (separated by commas). (default: %(default)s)" ],
|
"startinventory": [ "Specifies a list of items that will be in your starting inventory (separated by commas). (default: %(default)s)" ],
|
||||||
"usestartinventory": [ "Toggle usage of Starting Inventory." ],
|
"usestartinventory": [ "Toggle usage of Starting Inventory." ],
|
||||||
"custom": [ "Not supported." ],
|
"custom": [ "Not supported." ],
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"gui": {
|
"gui": {
|
||||||
"adjust.nobgm": "Disable Music & MSU-1",
|
"adjust.nobgm": "Disable Music & MSU-1",
|
||||||
"adjust.quickswap": "L/R Quickswapping",
|
"adjust.quickswap": "L/R Quickswapping",
|
||||||
|
"adjust.reduce_flashing": "Reduce Flashing",
|
||||||
|
|
||||||
"adjust.heartcolor": "Heart Color",
|
"adjust.heartcolor": "Heart Color",
|
||||||
"adjust.heartcolor.red": "Red",
|
"adjust.heartcolor.red": "Red",
|
||||||
@@ -86,6 +87,7 @@
|
|||||||
"randomizer.enemizer.enemyshuffle.none": "None",
|
"randomizer.enemizer.enemyshuffle.none": "None",
|
||||||
"randomizer.enemizer.enemyshuffle.shuffled": "Shuffled",
|
"randomizer.enemizer.enemyshuffle.shuffled": "Shuffled",
|
||||||
"randomizer.enemizer.enemyshuffle.random": "Random",
|
"randomizer.enemizer.enemyshuffle.random": "Random",
|
||||||
|
"randomizer.enemizer.enemyshuffle.legacy": "Random (including Thieves)",
|
||||||
|
|
||||||
"randomizer.enemizer.bossshuffle": "Boss Shuffle",
|
"randomizer.enemizer.bossshuffle": "Boss Shuffle",
|
||||||
"randomizer.enemizer.bossshuffle.none": "None",
|
"randomizer.enemizer.bossshuffle.none": "None",
|
||||||
@@ -204,6 +206,7 @@
|
|||||||
|
|
||||||
"randomizer.item.hints": "Include Helpful Hints",
|
"randomizer.item.hints": "Include Helpful Hints",
|
||||||
"randomizer.item.retro": "Retro mode (universal keys)",
|
"randomizer.item.retro": "Retro mode (universal keys)",
|
||||||
|
"randomizer.item.fakeboots": "Start with Fake Boots",
|
||||||
|
|
||||||
"randomizer.item.worldstate": "World State",
|
"randomizer.item.worldstate": "World State",
|
||||||
"randomizer.item.worldstate.standard": "Standard",
|
"randomizer.item.worldstate.standard": "Standard",
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
"options": [
|
"options": [
|
||||||
"none",
|
"none",
|
||||||
"shuffled",
|
"shuffled",
|
||||||
"random"
|
"random",
|
||||||
|
"legacy"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"bossshuffle": {
|
"bossshuffle": {
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
"shopsanity": { "type": "checkbox" },
|
"shopsanity": { "type": "checkbox" },
|
||||||
"hints": {
|
"hints": {
|
||||||
"type": "checkbox"
|
"type": "checkbox"
|
||||||
}
|
},
|
||||||
|
"fakeboots": { "type": "checkbox" }
|
||||||
},
|
},
|
||||||
"leftItemFrame": {
|
"leftItemFrame": {
|
||||||
"worldstate": {
|
"worldstate": {
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ SETTINGSTOPROCESS = {
|
|||||||
"hints": "hints",
|
"hints": "hints",
|
||||||
"retro": "retro",
|
"retro": "retro",
|
||||||
"shopsanity": "shopsanity",
|
"shopsanity": "shopsanity",
|
||||||
|
"fakeboots": "fakeboots",
|
||||||
"worldstate": "mode",
|
"worldstate": "mode",
|
||||||
"logiclevel": "logic",
|
"logiclevel": "logic",
|
||||||
"goal": "goal",
|
"goal": "goal",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from tkinter import ttk, Frame, E, W, LEFT, RIGHT
|
from tkinter import ttk, Frame, E, W, LEFT, RIGHT, Label
|
||||||
import source.gui.widgets as widgets
|
import source.gui.widgets as widgets
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
@@ -17,6 +17,9 @@ def item_page(parent):
|
|||||||
self.frames["checkboxes"] = Frame(self)
|
self.frames["checkboxes"] = Frame(self)
|
||||||
self.frames["checkboxes"].pack(anchor=W)
|
self.frames["checkboxes"].pack(anchor=W)
|
||||||
|
|
||||||
|
various_options = Label(self.frames["checkboxes"], text="")
|
||||||
|
various_options.pack(side=LEFT)
|
||||||
|
|
||||||
self.frames["leftItemFrame"] = Frame(self)
|
self.frames["leftItemFrame"] = Frame(self)
|
||||||
self.frames["rightItemFrame"] = Frame(self)
|
self.frames["rightItemFrame"] = Frame(self)
|
||||||
self.frames["leftItemFrame"].pack(side=LEFT)
|
self.frames["leftItemFrame"].pack(side=LEFT)
|
||||||
@@ -34,7 +37,7 @@ def item_page(parent):
|
|||||||
self.widgets[key] = dictWidgets[key]
|
self.widgets[key] = dictWidgets[key]
|
||||||
packAttrs = {"anchor":E}
|
packAttrs = {"anchor":E}
|
||||||
if self.widgets[key].type == "checkbox":
|
if self.widgets[key].type == "checkbox":
|
||||||
packAttrs["anchor"] = W
|
packAttrs["side"] = LEFT
|
||||||
self.widgets[key].pack(packAttrs)
|
self.widgets[key].pack(packAttrs)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|||||||
Reference in New Issue
Block a user