diff --git a/BaseClasses.py b/BaseClasses.py index 2c41fbfb..f922e11a 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -2625,7 +2625,7 @@ access_mode = {"items": 0, "locations": 1, "none": 2} # byte 6: BSMC BBEE (big, small, maps, compass, bosses, enemies) 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, ?) e_health = {"default": 0, "easy": 1, "normal": 2, "hard": 3, "expert": 4} diff --git a/Fill.py b/Fill.py index ee13e990..d2480df8 100644 --- a/Fill.py +++ b/Fill.py @@ -3,7 +3,7 @@ import logging from BaseClasses import CollectionState from Items import ItemFactory -from Regions import shop_to_location_table +from Regions import shop_to_location_table, retro_shops class FillError(RuntimeError): @@ -494,6 +494,10 @@ def balance_multiworld_progression(world): new_location = replacement_locations.pop() 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 state.collect(new_location.item, True, new_location) replaced_items = True @@ -514,6 +518,18 @@ def balance_multiworld_progression(world): 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): logger = logging.getLogger('') state = CollectionState(world) @@ -555,7 +571,6 @@ def balance_money_progression(world): for player in range(1, world.players+1): logger.debug(f'Money balance for P{player}: Needed: {total_price[player]} Available: {available_money[player]}') - def get_sphere_locations(sphere_state, 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)] @@ -670,6 +685,7 @@ def balance_money_progression(world): 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.location = best_target + check_shop_swap(best_target.item.location) else: old_item = best_target.item logger.debug(f'Swapping {best_target.item.name} @ {best_target.name} for {best_swap.item.name} @ {best_swap.name}') @@ -677,6 +693,8 @@ def balance_money_progression(world): best_target.item.location = best_target best_swap.item = old_item 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 difference -= increase wallet[target_player] += increase diff --git a/Main.py b/Main.py index 78fcaec8..339c2472 100644 --- a/Main.py +++ b/Main.py @@ -253,12 +253,10 @@ def main(args, seed=None, fish=None): or world.enemy_health[player] != 'default' or world.enemy_damage[player] != 'default' 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) 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)): raise RuntimeError("Could not find valid base rom for enemizing at expected path %s." % args.rom) if os.path.exists(args.enemizercli): diff --git a/Mystery.py b/Mystery.py index 6d0189f0..bd5581d6 100644 --- a/Mystery.py +++ b/Mystery.py @@ -195,15 +195,17 @@ def roll_settings(weights): boss_choice = old_style_bosses[boss_choice] ret.shufflebosses = boss_choice - ret.shuffleenemies = {'none': 'none', - 'shuffled': 'shuffled', - 'random': 'chaos' - }[get_choice('enemy_shuffle')] + enemy_choice = get_choice('enemy_shuffle') + if enemy_choice == 'chaos': + enemy_choice = 'random' + ret.shuffleenemies = enemy_choice - ret.enemy_damage = {'default': 'default', - 'shuffled': 'shuffled', - 'random': 'chaos' - }[get_choice('enemy_damage')] + old_style_damage = {'none': 'default', + 'chaos': 'random'} + damage_choice = 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') diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 112b2021..b6258011 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -17,6 +17,13 @@ Thanks to qadan, cheuer, & compiling * 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 * 0.4.0.7 * Reduce flashing option added * Sprite author credit added diff --git a/Rom.py b/Rom.py index 734b4779..7611aaa8 100644 --- a/Rom.py +++ b/Rom.py @@ -9,8 +9,11 @@ import random import struct import sys import subprocess -import bps.apply -import bps.io +try: + import bps.apply + import bps.io +except ImportError: + raise Exception('Could not load BPS module') from BaseClasses import CollectionState, ShopType, Region, Location, Door, DoorType, RegionType, PotItem from DoorShuffle import compass_data, DROptions, boss_indicator @@ -201,7 +204,7 @@ def patch_enemizer(world, player, rom, baserom_path, enemizercli, random_sprite_ options = { 'RandomizeEnemies': world.enemy_shuffle[player] != 'none', 'RandomizeEnemiesType': 3, - 'RandomizeBushEnemyChance': world.enemy_shuffle[player] == 'random', + 'RandomizeBushEnemyChance': world.enemy_shuffle[player] in ['random', 'legacy'], 'RandomizeEnemyHealthRange': world.enemy_health[player] != 'default', 'RandomizeEnemyHealthType': {'default': 0, 'easy': 0, 'normal': 1, 'hard': 2, 'expert': 3}[world.enemy_health[player]], 'OHKO': False, @@ -247,9 +250,9 @@ def patch_enemizer(world, player, rom, baserom_path, enemizercli, random_sprite_ 'SwordGraphics': "sword_gfx/normal.gfx", 'BeeMizer': False, 'BeesLevel': 0, - 'RandomizeTileTrapPattern': world.enemy_shuffle[player] == 'random', + 'RandomizeTileTrapPattern': world.enemy_shuffle[player] in ['random', 'legacy'], '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, 'DebugMode': False, 'DebugForceEnemy': False, @@ -806,7 +809,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): write_int16(rom, 0x187010, credits_total) # dynamic credits if credits_total != 216: # collection rate address: - cr_address = 0x2391BE + cr_address = 0x2391FA cr_pc = cr_address - 0x120000 # convert to pc mid_top, mid_bot = credits_digit((credits_total // 10) % 10) last_top, last_bot = credits_digit(credits_total % 10) @@ -825,7 +828,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False): total += count_locations_exclude_logic(region.locations, gt_logic) # rom.write_byte(0x187012, total) # dynamic credits # gt big key address: - gtbk_address = 0x2390E0 + gtbk_address = 0x23911C gtbk_pc = gtbk_address - 0x120000 # convert to pc mid_top, mid_bot = credits_digit(total // 10) last_top, last_bot = credits_digit(total % 10) @@ -1640,7 +1643,7 @@ def hud_format_text(text): def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite, 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], rom.orig_buffer[0xdedf5:0xdedf9], "data/sprites/official/001.link.1.zspr", "Nintendo", "Link") diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index 0dc97277..00d1c9db 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -340,7 +340,8 @@ "choices": [ "none", "shuffled", - "random" + "random", + "legacy" ] }, "enemy_health": { diff --git a/resources/app/gui/lang/en.json b/resources/app/gui/lang/en.json index 8ae98e81..850bb788 100644 --- a/resources/app/gui/lang/en.json +++ b/resources/app/gui/lang/en.json @@ -87,6 +87,7 @@ "randomizer.enemizer.enemyshuffle.none": "None", "randomizer.enemizer.enemyshuffle.shuffled": "Shuffled", "randomizer.enemizer.enemyshuffle.random": "Random", + "randomizer.enemizer.enemyshuffle.legacy": "Random (including Thieves)", "randomizer.enemizer.bossshuffle": "Boss Shuffle", "randomizer.enemizer.bossshuffle.none": "None", diff --git a/resources/app/gui/randomize/enemizer/widgets.json b/resources/app/gui/randomize/enemizer/widgets.json index bb731cc2..d987d41a 100644 --- a/resources/app/gui/randomize/enemizer/widgets.json +++ b/resources/app/gui/randomize/enemizer/widgets.json @@ -5,7 +5,8 @@ "options": [ "none", "shuffled", - "random" + "random", + "legacy" ] }, "bossshuffle": {