Merge branch 'OverworldShuffleDev' into OverworldShuffle
This commit is contained in:
@@ -1,5 +1,12 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.6.0.6
|
||||||
|
- Added ability to change GT entry cutscene GFX thru customizer
|
||||||
|
- Chicken as a standing item is no longer a star gfx
|
||||||
|
- Fix issue in DR with music silence in pre-Aga room
|
||||||
|
- Other various music fixes
|
||||||
|
- Fixed issue with Mystery subweights not correctly evaluating boolean settings
|
||||||
|
|
||||||
## 0.6.0.5
|
## 0.6.0.5
|
||||||
- Emergency fix for map/key totals in non-DR
|
- Emergency fix for map/key totals in non-DR
|
||||||
|
|
||||||
|
|||||||
@@ -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.0.5'
|
version_number = '0.6.0.6'
|
||||||
# branch indicator is intentionally different across branches
|
# branch indicator is intentionally different across branches
|
||||||
version_branch = ''
|
version_branch = ''
|
||||||
|
|
||||||
|
|||||||
26
Rom.py
26
Rom.py
@@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings
|
|||||||
|
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = '94672b7a306b32c8a1d9e64f0e6a9be0'
|
RANDOMIZERBASEHASH = 'b8c930c1922fb15018c76be902cc15d9'
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
@@ -1089,8 +1089,8 @@ def patch_rom(world, rom, player, team, is_mystery=False):
|
|||||||
0x51, 0x00 if world.bombbag[player] else 0x06, 0x31 if world.bombbag[player] else 0x52, 0xFF, # 6 +5 bomb upgrades -> +10 bomb upgrade. If bombbag -> turns into Bombs (10)
|
0x51, 0x00 if world.bombbag[player] else 0x06, 0x31 if world.bombbag[player] else 0x52, 0xFF, # 6 +5 bomb upgrades -> +10 bomb upgrade. If bombbag -> turns into Bombs (10)
|
||||||
0x53, 0x06, 0x54, 0xFF, # 6 +5 arrow upgrades -> +10 arrow upgrade
|
0x53, 0x06, 0x54, 0xFF, # 6 +5 arrow upgrades -> +10 arrow upgrade
|
||||||
0x58, 0x01, 0x36 if world.bow_mode[player].startswith('retro') else 0x43, 0xFF, # silver arrows -> single arrow (red 20 in retro mode)
|
0x58, 0x01, 0x36 if world.bow_mode[player].startswith('retro') else 0x43, 0xFF, # silver arrows -> single arrow (red 20 in retro mode)
|
||||||
0x3E, difficulty.boss_heart_container_limit, 0x47, 0xff, # boss heart -> green 20
|
0x3E, difficulty.boss_heart_container_limit, GREEN_TWENTY_RUPEES, 0xff, # boss heart -> green 20
|
||||||
0x17, difficulty.heart_piece_limit, 0x47, 0xff, # piece of heart -> green 20
|
0x17, difficulty.heart_piece_limit, GREEN_TWENTY_RUPEES, 0xff, # piece of heart -> green 20
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, # end of table sentinel
|
0xFF, 0xFF, 0xFF, 0xFF, # end of table sentinel
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -1642,6 +1642,26 @@ def patch_rom(world, rom, player, team, is_mystery=False):
|
|||||||
write_enemizer_tweaks(rom, world, player)
|
write_enemizer_tweaks(rom, world, player)
|
||||||
write_strings(rom, world, player, team)
|
write_strings(rom, world, player, team)
|
||||||
|
|
||||||
|
# gt entry
|
||||||
|
if world.customizer:
|
||||||
|
gtentry = world.customizer.get_gtentry()
|
||||||
|
if gtentry and player in gtentry:
|
||||||
|
gtentry = gtentry[player]
|
||||||
|
if 'cutscene_gfx' in gtentry:
|
||||||
|
gfx = gtentry['cutscene_gfx']
|
||||||
|
if type(gfx) is str:
|
||||||
|
from Tables import item_gfx_table
|
||||||
|
if gfx.lower() == 'random':
|
||||||
|
gfx = random.choice(list(item_gfx_table.keys()))
|
||||||
|
if gfx in item_gfx_table:
|
||||||
|
write_int16(rom, snes_to_pc(0x3081AA), item_gfx_table[gfx][1] + (0x8000 if not item_gfx_table[gfx][0] else 0))
|
||||||
|
rom.write_byte(snes_to_pc(0x3081AC), item_gfx_table[gfx][2])
|
||||||
|
else:
|
||||||
|
logging.getLogger('').warning('Invalid name "%s" in customized GT entry cutscene gfx', gfx)
|
||||||
|
else:
|
||||||
|
write_int16(rom, snes_to_pc(0x3081AA), gfx[0])
|
||||||
|
rom.write_byte(snes_to_pc(0x3081AC), gfx[1])
|
||||||
|
|
||||||
# write initial sram
|
# write initial sram
|
||||||
rom.write_initial_sram()
|
rom.write_initial_sram()
|
||||||
|
|
||||||
|
|||||||
99
Tables.py
99
Tables.py
@@ -146,3 +146,102 @@ bonk_prize_lookup = {
|
|||||||
'Arrows (10)': (0xe2, 0, None),
|
'Arrows (10)': (0xe2, 0, None),
|
||||||
'Fairy': (0xe3, 15, None)
|
'Fairy': (0xe3, 15, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# item name: (custom gfx, address offset, palette)
|
||||||
|
# decompressed gfx loaded at $7F8000
|
||||||
|
# custom gfx loaded at $228000
|
||||||
|
item_gfx_table = {
|
||||||
|
'Green Rupees (20)': (False, 0x0000, 0x04),
|
||||||
|
'Pegasus Boots': (False, 0x0040, 0x01),
|
||||||
|
'Psuedoboots': (False, 0x0040, 0x02),
|
||||||
|
'Blue Pendant': (False, 0x0080, 0x02),
|
||||||
|
'Red Pendant': (False, 0x0080, 0x01),
|
||||||
|
'Warp Tile': (False, 0x00C0, 0x04),
|
||||||
|
'Open Chest': (False, 0x0100, 0x02),
|
||||||
|
'Chicken': (False, 0x0140, 0x04),
|
||||||
|
'Duck': (False, 0x0180, 0x01),
|
||||||
|
'Chest': (False, 0x0400, 0x02),
|
||||||
|
'Frog': (False, 0x0440, 0x04),
|
||||||
|
'Kiki (Head)': (False, 0x0480, 0x04),
|
||||||
|
'Purple Chest': (False, 0x0500, 0x04),
|
||||||
|
'Super Bomb': (False, 0x0540, 0x04),
|
||||||
|
'Blacksmith': (False, 0x0580, 0x04),
|
||||||
|
'Bug Net': (False, 0x0860, 0x01),
|
||||||
|
'Crystal': (False, 0x08A0, 0x06),
|
||||||
|
'Silver Arrows': (False, 0x08E0, 0x01),
|
||||||
|
'Bow': (False, 0x0920, 0x02),
|
||||||
|
'Bottle (Fairy)': (False, 0x0960, 0x02),
|
||||||
|
'Bottle (Bee)': (False, 0x09A0, 0x02),
|
||||||
|
'Piece of Heart': (False, 0x0C00, 0x01),
|
||||||
|
'Ocarina': (False, 0x0C40, 0x02),
|
||||||
|
'Mirror Shield': (False, 0x0C80, 0x04),
|
||||||
|
'Rupees (100)': (False, 0x0D20, 0x04),
|
||||||
|
'Rupees (50)': (False, 0x0D60, 0x04),
|
||||||
|
'Rupees (300)': (False, 0x0DA0, 0x04),
|
||||||
|
'Flippers': (False, 0x1000, 0x02),
|
||||||
|
'Mirror': (False, 0x1040, 0x02),
|
||||||
|
'Bomb': (False, 0x1080, 0x02),
|
||||||
|
'Lamp': (False, 0x10C0, 0x01),
|
||||||
|
'Psuedolamp': (False, 0x10C0, 0x02),
|
||||||
|
'Magic Cape': (False, 0x1100, 0x01),
|
||||||
|
'Compass': (False, 0x1140, 0x02),
|
||||||
|
'Moon Pearl': (False, 0x1180, 0x01),
|
||||||
|
'Ether': (False, 0x1400, 0x04),
|
||||||
|
'Bombos': (False, 0x1440, 0x04),
|
||||||
|
'Quake': (False, 0x1480, 0x04),
|
||||||
|
'Bottle': (False, 0x14C0, 0x01),
|
||||||
|
'Bottle (Red Potion)': (False, 0x1500, 0x01),
|
||||||
|
'Bottle (Green Potion)': (False, 0x1500, 0x04),
|
||||||
|
'Bottle (Blue Potion)': (False, 0x1500, 0x02),
|
||||||
|
'Mushroom': (False, 0x1540, 0x04),
|
||||||
|
'Map': (False, 0x1580, 0x04),
|
||||||
|
'Big Key': (False, 0x15C0, 0x04),
|
||||||
|
'Bombs (3)': (False, 0x1840, 0x02),
|
||||||
|
'Arrows (10)': (False, 0x1880, 0x02),
|
||||||
|
'Heart Container': (False, 0x18C0, 0x01),
|
||||||
|
'Green Mail': (False, 0x1900, 0x04),
|
||||||
|
'Blue Mail': (False, 0x1900, 0x02),
|
||||||
|
'Red Mail': (False, 0x1900, 0x01),
|
||||||
|
'Fire Sheild': (False, 0x1980, 0x04),
|
||||||
|
'Blue Shield': (False, 0x19C0, 0x02),
|
||||||
|
'Magic Powder': (False, 0x1CC0, 0x02),
|
||||||
|
'Bombs (10)': (False, 0x1D00, 0x02),
|
||||||
|
'Power Glove': (False, 0x1D40, 0x01),
|
||||||
|
'Titans Mitts': (False, 0x1D40, 0x04),
|
||||||
|
'Book of Mudora': (False, 0x1D80, 0x04),
|
||||||
|
'Maiden (Head)': (False, 0x2000, 0x04),
|
||||||
|
'Zelda (Head)': (False, 0x2080, 0x04),
|
||||||
|
'Old Man (Head)': (False, 0x2140, 0x04),
|
||||||
|
'Locksmith (Head)': (False, 0x2180, 0x04),
|
||||||
|
'Fire': (False, 0x25C0, 0x04),
|
||||||
|
'Apples': (False, 0x30A0, 0x04),
|
||||||
|
'Fairy': (False, 0x3140, 0x01),
|
||||||
|
'Whirlpool': (False, 0x31C0, 0x01),
|
||||||
|
|
||||||
|
'Triforce': (True, 0x0060, 0x04),
|
||||||
|
'Fighter Sword': (True, 0x00A0, 0x02),
|
||||||
|
'Master Sword': (True, 0x00E0, 0x02),
|
||||||
|
'Tempered Sword': (True, 0x0120, 0x01),
|
||||||
|
'Golden Sword': (True, 0x0160, 0x04),
|
||||||
|
'Half Magic': (True, 0x01A0, 0x04),
|
||||||
|
'Quarter Magic': (True, 0x01E0, 0x04),
|
||||||
|
'Bomb Upgrade (+5)': (True, 0x0420, 0x04),
|
||||||
|
'Bomb Upgrade (+10)': (True, 0x0460, 0x04),
|
||||||
|
'Bomb Upgrade (50)': (True, 0x04A0, 0x04),
|
||||||
|
'Bombbag': (True, 0x04E0, 0x02),
|
||||||
|
'Arrow Upgrade (+5)': (True, 0x0520, 0x02),
|
||||||
|
'Arrow Upgrade (+10)': (True, 0x0560, 0x02),
|
||||||
|
'Arrows (70)': (True, 0x05A0, 0x02),
|
||||||
|
'Silver Arrows (Ag)': (True, 0x05E0, 0x01),
|
||||||
|
'Green Pendant': (True, 0x0820, 0x04),
|
||||||
|
'Sword and Shield': (True, 0x0860, 0x02),
|
||||||
|
'Green Potion': (True, 0x08A0, 0x04),
|
||||||
|
'Blue Potion': (True, 0x08E0, 0x02),
|
||||||
|
'Red Potion': (True, 0x0920, 0x01),
|
||||||
|
'Bee Trap': (True, 0x0960, 0x02),
|
||||||
|
'Red Crystal': (True, 0x0C60, 0x01),
|
||||||
|
'Egg': (True, 0x1020, 0x02),
|
||||||
|
'Master Key': (True, 0x1060, 0x02),
|
||||||
|
'Lumberjack (Head)': (True, 0x11A0, 0x02),
|
||||||
|
'Power Star': (True, 0x11E0, 0x04),
|
||||||
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -334,7 +334,7 @@ drops:
|
|||||||
|
|
||||||
Prize packs expect a list of eight items each (anything not specified will be whatever randomization would have normally occurred). The special drops expect a single item. Packs 1 through 7 are supported. Prize pack 0 is not customizable.
|
Prize packs expect a list of eight items each (anything not specified will be whatever randomization would have normally occurred). The special drops expect a single item. Packs 1 through 7 are supported. Prize pack 0 is not customizable.
|
||||||
|
|
||||||
## prices
|
### prices
|
||||||
|
|
||||||
This must be defined by player. You may have the prices of items in shops defined using the following
|
This must be defined by player. You may have the prices of items in shops defined using the following
|
||||||
|
|
||||||
@@ -348,3 +348,27 @@ prices:
|
|||||||
Dark Death Mountain Shop - Right: 300
|
Dark Death Mountain Shop - Right: 300
|
||||||
Dark Lake Hylia Shop - Left: 200
|
Dark Lake Hylia Shop - Left: 200
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### gt_entry
|
||||||
|
|
||||||
|
This must be defined by player. This is where you are able to customize aspects of GT entry
|
||||||
|
|
||||||
|
#### cutscene_gfx
|
||||||
|
|
||||||
|
This is where you can define custom GFX to be used in the GT entry cutscene. For convenience, there are a number of pre-defined names that can be used to indicate already known GFX values built into the ROM. There are too many to list, but a full list can be found in `item_gfx_table` in `Tables.py`. You can also use `Random` and it will take a random one from the aforementioned table.
|
||||||
|
|
||||||
|
```
|
||||||
|
gt_entry:
|
||||||
|
1:
|
||||||
|
cutscene_gfx: Mirror Shield
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you may also supply a custom address and palette ID, respectively, if you are injecting your own personal custom GFX into the ROM.
|
||||||
|
|
||||||
|
```
|
||||||
|
gt_entry:
|
||||||
|
1:
|
||||||
|
cutscene_gfx:
|
||||||
|
- 0x8140
|
||||||
|
- 0x04
|
||||||
|
```
|
||||||
|
|||||||
@@ -299,6 +299,11 @@ class CustomSettings(object):
|
|||||||
return self.file_source['enemies']
|
return self.file_source['enemies']
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_gtentry(self):
|
||||||
|
if 'gt_entry' in self.file_source:
|
||||||
|
return self.file_source['gt_entry']
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_attribute_by_player_composite(self, attribute, player):
|
def get_attribute_by_player_composite(self, attribute, player):
|
||||||
attempt = self.get_attribute_by_player_new(attribute, player)
|
attempt = self.get_attribute_by_player_new(attribute, player)
|
||||||
|
|||||||
@@ -16,6 +16,16 @@ def get_weights(path):
|
|||||||
return yaml.load(urllib.request.urlopen(path), Loader=yaml.FullLoader)
|
return yaml.load(urllib.request.urlopen(path), Loader=yaml.FullLoader)
|
||||||
|
|
||||||
def roll_settings(weights):
|
def roll_settings(weights):
|
||||||
|
while True:
|
||||||
|
subweights = weights.get('subweights', {})
|
||||||
|
if len(subweights) == 0:
|
||||||
|
break
|
||||||
|
chances = ({k: int(v['chance']) for (k, v) in subweights.items()})
|
||||||
|
subweight_name = random.choices(list(chances.keys()), weights=list(chances.values()))[0]
|
||||||
|
subweights = weights.get('subweights', {}).get(subweight_name, {}).get('weights', {})
|
||||||
|
subweights['subweights'] = subweights.get('subweights', {})
|
||||||
|
weights = {**weights, **subweights}
|
||||||
|
|
||||||
def get_choice(option, root=None):
|
def get_choice(option, root=None):
|
||||||
root = weights if root is None else root
|
root = weights if root is None else root
|
||||||
if option not in root:
|
if option not in root:
|
||||||
@@ -65,16 +75,6 @@ def roll_settings(weights):
|
|||||||
return default
|
return default
|
||||||
return choice
|
return choice
|
||||||
|
|
||||||
while True:
|
|
||||||
subweights = weights.get('subweights', {})
|
|
||||||
if len(subweights) == 0:
|
|
||||||
break
|
|
||||||
chances = ({k: int(v['chance']) for (k, v) in subweights.items()})
|
|
||||||
subweight_name = random.choices(list(chances.keys()), weights=list(chances.values()))[0]
|
|
||||||
subweights = weights.get('subweights', {}).get(subweight_name, {}).get('weights', {})
|
|
||||||
subweights['subweights'] = subweights.get('subweights', {})
|
|
||||||
weights = {**weights, **subweights}
|
|
||||||
|
|
||||||
ret = argparse.Namespace()
|
ret = argparse.Namespace()
|
||||||
|
|
||||||
ret.algorithm = get_choice('algorithm')
|
ret.algorithm = get_choice('algorithm')
|
||||||
|
|||||||
Reference in New Issue
Block a user