Merge branch 'OverworldShuffleDev' into pr/27
This commit is contained in:
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,5 +1,16 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
# 0.6.1.11
|
||||||
|
- Fixed bonk drops duplicate counting and potentially overwriting arbitrary values
|
||||||
|
- Fixed boss icons on dungeon map check
|
||||||
|
- Fixed dungeon counters to autotrack correctly
|
||||||
|
- Key and chest counts in menu now display consistently (must have dungeon item or have visited dungeon to see the HUD)
|
||||||
|
- Money balancing will fail in less scenarios
|
||||||
|
- Fixed issue with Sanc pots not collecting
|
||||||
|
- Enemizer now allows more enemies on water
|
||||||
|
- Fix infinite pit fall issue with Old Man follower location
|
||||||
|
- Fix bad overworld tilemap drawing on HC and Pyramid screens in OW Layout Shuffle
|
||||||
|
|
||||||
## 0.6.1.10
|
## 0.6.1.10
|
||||||
- Emergency fix for bonk functionality
|
- Emergency fix for bonk functionality
|
||||||
|
|
||||||
|
|||||||
20
Fill.py
20
Fill.py
@@ -1024,7 +1024,10 @@ def balance_money_progression(world):
|
|||||||
'Rupees (100)': 100, 'Rupees (300)': 300}
|
'Rupees (100)': 100, 'Rupees (300)': 300}
|
||||||
rupee_rooms = {'Eastern Rupees': 90, 'Mire Key Rupees': 45, 'Mire Shooter Rupees': 90,
|
rupee_rooms = {'Eastern Rupees': 90, 'Mire Key Rupees': 45, 'Mire Shooter Rupees': 90,
|
||||||
'TR Rupees': 270, 'PoD Dark Basement': 270}
|
'TR Rupees': 270, 'PoD Dark Basement': 270}
|
||||||
acceptable_balancers = ['Bombs (3)', 'Arrows (10)', 'Bombs (10)']
|
acceptable_balancers = ['Single Bomb', 'Bombs (3)', 'Bombs (10)',
|
||||||
|
'Single Arrow', 'Arrows (5)', 'Arrows (10)',
|
||||||
|
'Small Magic', 'Big Magic', 'Small Heart',
|
||||||
|
'Fairy', 'Chicken', 'Nothing']
|
||||||
|
|
||||||
base_value = sum(rupee_rooms.values())
|
base_value = sum(rupee_rooms.values())
|
||||||
available_money = {player: base_value for player in range(1, world.players+1)}
|
available_money = {player: base_value for player in range(1, world.players+1)}
|
||||||
@@ -1125,10 +1128,11 @@ def balance_money_progression(world):
|
|||||||
unchecked_locations.remove(location)
|
unchecked_locations.remove(location)
|
||||||
if location.item:
|
if location.item:
|
||||||
if location.item.name.startswith('Rupee'):
|
if location.item.name.startswith('Rupee'):
|
||||||
wallet[location.item.player] += rupee_chart[location.item.name]
|
if not (location.item.name == 'Rupee (1)' and world.algorithm != 'district'):
|
||||||
if location.item.name != 'Rupees (300)':
|
wallet[location.item.player] += rupee_chart[location.item.name]
|
||||||
balance_locations[location.item.player].add(location)
|
if location.item.name != 'Rupees (300)':
|
||||||
if interesting_item(location, location.item, world, location.item.player):
|
balance_locations[location.item.player].add(location)
|
||||||
|
elif interesting_item(location, location.item, world, location.item.player):
|
||||||
checked_locations.append(location)
|
checked_locations.append(location)
|
||||||
elif location.item.name in acceptable_balancers:
|
elif location.item.name in acceptable_balancers:
|
||||||
balance_locations[location.item.player].add(location)
|
balance_locations[location.item.player].add(location)
|
||||||
@@ -1172,7 +1176,11 @@ def balance_money_progression(world):
|
|||||||
if len(increase_targets) == 0:
|
if len(increase_targets) == 0:
|
||||||
increase_targets = [x for x in balance_locations[target_player] if (rupee_chart[x.item.name] if x.item.name in rupee_chart else 0) < best_value]
|
increase_targets = [x for x in balance_locations[target_player] if (rupee_chart[x.item.name] if x.item.name in rupee_chart else 0) < best_value]
|
||||||
if len(increase_targets) == 0:
|
if len(increase_targets) == 0:
|
||||||
raise Exception('No early sphere swaps for rupees - money grind would be required - bailing for now')
|
if state.can_farm_rupees(target_player):
|
||||||
|
logger.warning(f'No more swap targets available. Short by {difference} rupees, but continuing (player can farm)')
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise Exception(f'No early sphere swaps for rupees - money grind would be required - bailing for now')
|
||||||
best_target = min(increase_targets, key=lambda t: rupee_chart[t.item.name] if t.item.name in rupee_chart else 0)
|
best_target = min(increase_targets, key=lambda t: rupee_chart[t.item.name] if t.item.name in rupee_chart else 0)
|
||||||
make_item_free = wallet[target_player] < 20
|
make_item_free = wallet[target_player] < 20
|
||||||
old_value = 0 if make_item_free else (rupee_chart[best_target.item.name] if best_target.item.name in rupee_chart else 0)
|
old_value = 0 if make_item_free else (rupee_chart[best_target.item.name] if best_target.item.name in rupee_chart else 0)
|
||||||
|
|||||||
2
Main.py
2
Main.py
@@ -40,7 +40,7 @@ from source.enemizer.DamageTables import DamageTable
|
|||||||
from source.enemizer.Enemizer import randomize_enemies
|
from source.enemizer.Enemizer import randomize_enemies
|
||||||
from source.rom.DataTables import init_data_tables
|
from source.rom.DataTables import init_data_tables
|
||||||
|
|
||||||
version_number = '1.5.0'
|
version_number = '1.5.2'
|
||||||
version_branch = '-u'
|
version_branch = '-u'
|
||||||
__version__ = f'{version_number}{version_branch}'
|
__version__ = f'{version_number}{version_branch}'
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType
|
|||||||
from OverworldGlitchRules import create_owg_connections
|
from OverworldGlitchRules import create_owg_connections
|
||||||
from Utils import bidict
|
from Utils import bidict
|
||||||
|
|
||||||
version_number = '0.6.1.10'
|
version_number = '0.6.1.11'
|
||||||
# branch indicator is intentionally different across branches
|
# branch indicator is intentionally different across branches
|
||||||
version_branch = '-u'
|
version_branch = '-u'
|
||||||
|
|
||||||
|
|||||||
14
Rom.py
14
Rom.py
@@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings
|
|||||||
|
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = 'f2eebfbec9c8ad638e922ed1047d1c10'
|
RANDOMIZERBASEHASH = '34c9d7b09fad982dea9e7c9e3ae885ee'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
@@ -1411,9 +1411,15 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None):
|
|||||||
| (0x04 if world.mapshuffle[player] != 'none' else 0x00)
|
| (0x04 if world.mapshuffle[player] != 'none' else 0x00)
|
||||||
| (0x08 if world.bigkeyshuffle[player] != 'none' else 0x00))) # free roaming item text boxes
|
| (0x08 if world.bigkeyshuffle[player] != 'none' else 0x00))) # free roaming item text boxes
|
||||||
rom.write_byte(0x18003B, 0x01 if world.mapshuffle[player] not in ['none', 'nearby'] else 0x00) # maps showing crystals on overworld
|
rom.write_byte(0x18003B, 0x01 if world.mapshuffle[player] not in ['none', 'nearby'] else 0x00) # maps showing crystals on overworld
|
||||||
if world.keyshuffle[player] != 'universal' and (world.mapshuffle[player] not in ['none', 'nearby'] or world.doorShuffle[player] != 'vanilla'
|
map_hud_mode = 0x00
|
||||||
or world.dropshuffle[player] != 'none' or world.pottery[player] not in ['none', 'cave']):
|
if world.dungeon_counters[player] == 'on':
|
||||||
rom.write_byte(0x18003A, 0x01) # show key counts on map pickup
|
map_hud_mode = 0x02 # always on
|
||||||
|
elif world.dungeon_counters[player] == 'off':
|
||||||
|
pass
|
||||||
|
elif world.keyshuffle[player] != 'universal' and (world.mapshuffle[player] not in ['none', 'nearby'] or world.doorShuffle[player] != 'vanilla'
|
||||||
|
or world.dropshuffle[player] != 'none' or world.pottery[player] not in ['none', 'cave'] or world.dungeon_counters[player] == 'pickup'):
|
||||||
|
map_hud_mode = 0x01 # show on pickup
|
||||||
|
rom.write_byte(0x18003A, map_hud_mode)
|
||||||
|
|
||||||
# compasses showing dungeon count
|
# compasses showing dungeon count
|
||||||
compass_mode = 0x80 if world.compassshuffle[player] not in ['none', 'nearby'] else 0x00
|
compass_mode = 0x80 if world.compassshuffle[player] not in ['none', 'nearby'] else 0x00
|
||||||
|
|||||||
Binary file not shown.
@@ -177,9 +177,9 @@ def init_sprite_requirements():
|
|||||||
SpriteRequirement(EnemySprite.Vulture).no_drop().sub_group(2, 0x12).exclude(NoFlyingRooms),
|
SpriteRequirement(EnemySprite.Vulture).no_drop().sub_group(2, 0x12).exclude(NoFlyingRooms),
|
||||||
SpriteRequirement(EnemySprite.CorrectPullSwitch).affix().sub_group(3, [0x52, 0x53]),
|
SpriteRequirement(EnemySprite.CorrectPullSwitch).affix().sub_group(3, [0x52, 0x53]),
|
||||||
SpriteRequirement(EnemySprite.WrongPullSwitch).affix().sub_group(3, [0x52, 0x53]),
|
SpriteRequirement(EnemySprite.WrongPullSwitch).affix().sub_group(3, [0x52, 0x53]),
|
||||||
SpriteRequirement(EnemySprite.Octorok).aquaphobia().sub_group(2, [0xc, 0x18]),
|
SpriteRequirement(EnemySprite.Octorok).sub_group(2, [0xc, 0x18]),
|
||||||
SpriteRequirement(EnemySprite.Moldorm).exalt().sub_group(2, 0x30),
|
SpriteRequirement(EnemySprite.Moldorm).exalt().sub_group(2, 0x30),
|
||||||
SpriteRequirement(EnemySprite.Octorok4Way).aquaphobia().sub_group(2, 0xc),
|
SpriteRequirement(EnemySprite.Octorok4Way).sub_group(2, 0xc),
|
||||||
SpriteRequirement(EnemySprite.Cucco).immune().sub_group(3, [0x15, 0x50]).exclude(NoFlyingRooms),
|
SpriteRequirement(EnemySprite.Cucco).immune().sub_group(3, [0x15, 0x50]).exclude(NoFlyingRooms),
|
||||||
SpriteRequirement(EnemySprite.Buzzblob).sub_group(3, 0x11),
|
SpriteRequirement(EnemySprite.Buzzblob).sub_group(3, 0x11),
|
||||||
SpriteRequirement(EnemySprite.Snapdragon).sub_group(0, 0x16).sub_group(2, 0x17),
|
SpriteRequirement(EnemySprite.Snapdragon).sub_group(0, 0x16).sub_group(2, 0x17),
|
||||||
@@ -191,7 +191,7 @@ def init_sprite_requirements():
|
|||||||
.exclude(NoFlyingRooms).exclude({0x40}), # no anti-fairies in aga tower bridge room
|
.exclude(NoFlyingRooms).exclude({0x40}), # no anti-fairies in aga tower bridge room
|
||||||
SpriteRequirement(EnemySprite.Wiseman).affix().sub_group(2, 0x4c),
|
SpriteRequirement(EnemySprite.Wiseman).affix().sub_group(2, 0x4c),
|
||||||
SpriteRequirement(EnemySprite.Hoarder).sub_group(3, 0x11).exclude({0x10c}),
|
SpriteRequirement(EnemySprite.Hoarder).sub_group(3, 0x11).exclude({0x10c}),
|
||||||
SpriteRequirement(EnemySprite.MiniMoldorm).aquaphobia().sub_group(1, 0x1e),
|
SpriteRequirement(EnemySprite.MiniMoldorm).sub_group(1, 0x1e),
|
||||||
SpriteRequirement(EnemySprite.Poe).no_drop().sub_group(3, 0x15).exclude(NoFlyingRooms),
|
SpriteRequirement(EnemySprite.Poe).no_drop().sub_group(3, 0x15).exclude(NoFlyingRooms),
|
||||||
SpriteRequirement(EnemySprite.Smithy).affix().sub_group(1, 0x1d).sub_group(3, 0x15),
|
SpriteRequirement(EnemySprite.Smithy).affix().sub_group(1, 0x1d).sub_group(3, 0x15),
|
||||||
SpriteRequirement(EnemySprite.Statue).stasis().immune().sub_group(3, [0x52, 0x53]),
|
SpriteRequirement(EnemySprite.Statue).stasis().immune().sub_group(3, [0x52, 0x53]),
|
||||||
@@ -225,12 +225,12 @@ def init_sprite_requirements():
|
|||||||
SpriteRequirement(EnemySprite.Hoarder2).sub_group(3, 0x11).exclude({0x10c}),
|
SpriteRequirement(EnemySprite.Hoarder2).sub_group(3, 0x11).exclude({0x10c}),
|
||||||
SpriteRequirement(EnemySprite.TutorialGuard).affix(),
|
SpriteRequirement(EnemySprite.TutorialGuard).affix(),
|
||||||
SpriteRequirement(EnemySprite.LightningGate).affix().sub_group(3, 0x3f),
|
SpriteRequirement(EnemySprite.LightningGate).affix().sub_group(3, 0x3f),
|
||||||
SpriteRequirement(EnemySprite.BlueGuard).aquaphobia().sub_group(1, [0xd, 0x49]).exclude(PitRooms),
|
SpriteRequirement(EnemySprite.BlueGuard).sub_group(1, [0xd, 0x49]).exclude(PitRooms),
|
||||||
SpriteRequirement(EnemySprite.BlueGuard).aquaphobia().sub_group(1, [0xd, 0x49]).sub_group(2, [0x29, 0x13]),
|
SpriteRequirement(EnemySprite.BlueGuard).sub_group(1, [0xd, 0x49]).sub_group(2, [0x29, 0x13]),
|
||||||
SpriteRequirement(EnemySprite.GreenGuard).aquaphobia().sub_group(1, 0x49).exclude(PitRooms),
|
SpriteRequirement(EnemySprite.GreenGuard).sub_group(1, 0x49).exclude(PitRooms),
|
||||||
SpriteRequirement(EnemySprite.GreenGuard).aquaphobia().sub_group(1, 0x49).sub_group(2, 0x13),
|
SpriteRequirement(EnemySprite.GreenGuard).sub_group(1, 0x49).sub_group(2, 0x13),
|
||||||
SpriteRequirement(EnemySprite.RedSpearGuard).aquaphobia().sub_group(1, [0xd, 0x49]).exclude(PitRooms),
|
SpriteRequirement(EnemySprite.RedSpearGuard).sub_group(1, [0xd, 0x49]).exclude(PitRooms),
|
||||||
SpriteRequirement(EnemySprite.RedSpearGuard).aquaphobia().sub_group(1, [0xd, 0x49]).sub_group(2, [0x29, 0x13]),
|
SpriteRequirement(EnemySprite.RedSpearGuard).sub_group(1, [0xd, 0x49]).sub_group(2, [0x29, 0x13]),
|
||||||
SpriteRequirement(EnemySprite.BluesainBolt).aquaphobia().sub_group(0, 0x46).sub_group(1, [0xd, 0x49]),
|
SpriteRequirement(EnemySprite.BluesainBolt).aquaphobia().sub_group(0, 0x46).sub_group(1, [0xd, 0x49]),
|
||||||
SpriteRequirement(EnemySprite.UsainBolt).aquaphobia().sub_group(1, [0xd, 0x49]),
|
SpriteRequirement(EnemySprite.UsainBolt).aquaphobia().sub_group(1, [0xd, 0x49]),
|
||||||
SpriteRequirement(EnemySprite.BlueArcher).sub_group(0, 0x48).sub_group(1, 0x49),
|
SpriteRequirement(EnemySprite.BlueArcher).sub_group(0, 0x48).sub_group(1, 0x49),
|
||||||
|
|||||||
@@ -141,10 +141,11 @@ class DataTables:
|
|||||||
bytes = sum(1+len(x)*3 for x in self.ow_enemy_table.values() if len(x) > 0)+1
|
bytes = sum(1+len(x)*3 for x in self.ow_enemy_table.values() if len(x) > 0)+1
|
||||||
self.pointer_addresses['ow_sprites'][1] = bytes
|
self.pointer_addresses['ow_sprites'][1] = bytes
|
||||||
# ending_byte = 0x09CB3B + bytes
|
# ending_byte = 0x09CB3B + bytes
|
||||||
max_per_state = {0: 0x40, 1: 0x90, 2: 0x90}
|
max_per_state = {0: 0x40, 1: 0x90, 2: 0x81} # dropped max on state 2 to steal space for extra sprites (Murahdahla, extra tutorial guard)
|
||||||
|
|
||||||
pointer_address = snes_to_pc(self.pointer_addresses['ow_sprites'][2][0])
|
pointer_address = snes_to_pc(self.pointer_addresses['ow_sprites'][2][0])
|
||||||
data_pointer = snes_to_pc(self.pointer_addresses['ow_sprites'][0])
|
self.pointer_addresses['ow_sprites'][0] = pointer_address + ((max_per_state[0] + max_per_state[1] + max_per_state[2]) * 2)
|
||||||
|
data_pointer = self.pointer_addresses['ow_sprites'][0]
|
||||||
empty_pointer = pc_to_snes(data_pointer) & 0xFFFF
|
empty_pointer = pc_to_snes(data_pointer) & 0xFFFF
|
||||||
rom.write_byte(data_pointer, 0xff)
|
rom.write_byte(data_pointer, 0xff)
|
||||||
cached_dark_world = {}
|
cached_dark_world = {}
|
||||||
@@ -177,6 +178,10 @@ class DataTables:
|
|||||||
data_pointer += len(data)
|
data_pointer += len(data)
|
||||||
rom.write_byte(data_pointer, 0xff)
|
rom.write_byte(data_pointer, 0xff)
|
||||||
data_pointer += 1
|
data_pointer += 1
|
||||||
|
# Check if OW sprite data has overwritten the UW sprite pointer table
|
||||||
|
max_allowed_address = snes_to_pc(0x09D62E)
|
||||||
|
if data_pointer > max_allowed_address:
|
||||||
|
raise Exception(f'OW sprite data will cause the UW sprite pointer table to overwrite the pots pointer table. Data end: {hex(pc_to_snes(data_pointer))}, Max allowed: $09D62E')
|
||||||
|
|
||||||
|
|
||||||
special_health_table = {
|
special_health_table = {
|
||||||
|
|||||||
@@ -156,11 +156,7 @@ def roll_settings(weights):
|
|||||||
ret.door_self_loops = get_choice_bool('door_self_loops')
|
ret.door_self_loops = get_choice_bool('door_self_loops')
|
||||||
ret.experimental = get_choice_bool('experimental')
|
ret.experimental = get_choice_bool('experimental')
|
||||||
ret.collection_rate = get_choice_bool('collection_rate')
|
ret.collection_rate = get_choice_bool('collection_rate')
|
||||||
|
|
||||||
ret.dungeon_counters = get_choice_non_bool('dungeon_counters') if 'dungeon_counters' in weights else 'default'
|
ret.dungeon_counters = get_choice_non_bool('dungeon_counters') if 'dungeon_counters' in weights else 'default'
|
||||||
if ret.dungeon_counters == 'default':
|
|
||||||
ret.dungeon_counters = 'pickup' if ret.door_shuffle != 'vanilla' or ret.compassshuffle != 'none' else 'off'
|
|
||||||
|
|
||||||
ret.pseudoboots = get_choice_bool('pseudoboots')
|
ret.pseudoboots = get_choice_bool('pseudoboots')
|
||||||
ret.mirrorscroll = get_choice_bool('mirrorscroll')
|
ret.mirrorscroll = get_choice_bool('mirrorscroll')
|
||||||
ret.shopsanity = get_choice_bool('shopsanity')
|
ret.shopsanity = get_choice_bool('shopsanity')
|
||||||
|
|||||||
Reference in New Issue
Block a user