Damage Table shuffle

This commit is contained in:
2025-07-22 12:44:57 -05:00
parent a886b4ee10
commit dc3ec0238d
7 changed files with 79 additions and 1 deletions

View File

@@ -73,6 +73,7 @@ class World(object):
self.shuffle_ganon = shuffle_ganon
self.dark_rooms = {}
self.damage_challenge = {}
self.shuffle_damage_table = {}
self.custom = custom
self.customitemarray = customitemarray
self.can_take_damage = {}
@@ -174,6 +175,7 @@ class World(object):
set_player_attr('can_take_damage', True)
set_player_attr('dark_rooms', 'require_lamp')
set_player_attr('damage_challenge', 'normal')
set_player_attr('shuffle_damage_table', 'vanilla')
set_player_attr('crystal_book', False)
set_player_attr('collection_rate', False)
set_player_attr('colorizepots', True)
@@ -3075,6 +3077,7 @@ class Spoiler(object):
'can_take_damage': self.world.can_take_damage,
'dark_rooms': self.world.dark_rooms,
'damage_challenge': self.world.damage_challenge,
'shuffle_damage_table': self.world.shuffle_damage_table,
'crystal_book': self.world.crystal_book,
'triforcegoal': self.world.treasure_hunt_count,
'triforcepool': self.world.treasure_hunt_total,
@@ -3328,6 +3331,7 @@ class Spoiler(object):
outfile.write('Mirror Scroll:'.ljust(line_width) + '%s\n' % yn(self.metadata['mirrorscroll'][player]))
outfile.write('Dark Rooms:'.ljust(line_width) + '%s\n' % self.metadata['dark_rooms'][player])
outfile.write('Damage Challenge:'.ljust(line_width) + '%s\n' % self.metadata['damage_challenge'][player])
outfile.write('Damage Table Randomization:'.ljust(line_width) + '%s\n' % self.metadata['shuffle_damage_table'][player])
outfile.write('Crystal Book:'.ljust(line_width) + '%s\n' % yn(self.metadata['crystal_book'][player]))
outfile.write('Hints:'.ljust(line_width) + '%s\n' % yn(self.metadata['hints'][player]))
outfile.write('Race:'.ljust(line_width) + '%s\n' % yn(self.world.settings.world_rep['meta']['race']))

3
CLI.py
View File

@@ -139,7 +139,7 @@ def parse_cli(argv, no_defaults=False):
'triforce_max_difference', 'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max',
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'shuffletavern',
'skullwoods', 'linked_drops',
'pseudoboots', 'mirrorscroll', 'dark_rooms', 'damage_challenge', 'crystal_book', 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
'pseudoboots', 'mirrorscroll', 'dark_rooms', 'damage_challenge', 'shuffle_damage_table', 'crystal_book', 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
'heartbeep', 'remote_items', 'shopsanity', 'dropshuffle', 'pottery', 'keydropshuffle',
@@ -213,6 +213,7 @@ def parse_settings():
"mirrorscroll": False,
"dark_rooms": "require_lamp",
"damage_challenge": "normal",
"shuffle_damage_table": "vanilla",
"crystal_book": False,
"shuffleenemies": "none",

49
DamageTable.py Normal file
View File

@@ -0,0 +1,49 @@
from dataclasses import dataclass, field
from typing import List
import RaceRandom as random
def _load_entries():
entries = []
with open("data/damage_table.bin", 'rb') as stream:
for sprite in range(0x100):
entries.append([])
for pair in range(8):
byte = stream.read(1)[0]
entries[sprite].append(byte >> 4)
entries[sprite].append(byte & 0x0F)
return entries
@dataclass
class DamageTable:
_entries: List[int] = field(default_factory=_load_entries)
def randomize_sword_subclasses(self):
for sprite in range(0xD8):
for dclass in range(1, 6):
if self._entries[sprite][dclass] > 0:
self._entries[sprite][dclass] = random.randint(1, 7)
def get_bytes(self):
values = []
for sprite in range(0x100):
for dclass in range(0, 16, 2):
cur = self._entries[sprite][dclass] & 0xF
nex = self._entries[sprite][dclass + 1] & 0xF
values.append((cur << 4) | nex)
return values
if __name__ == '__main__':
def print_table(table):
bytelist = table.get_bytes()
for sprite in range(0x100):
for byte in range(8):
print(format(bytelist.pop(0), "02X"), end=" ")
print()
print()
dmg = DamageTable()
print_table(dmg)
dmg.randomize_sword_subclasses()
print_table(dmg)

View File

@@ -515,6 +515,7 @@ def init_world(args, fish):
world.mirrorscroll = args.mirrorscroll.copy()
world.dark_rooms = args.dark_rooms.copy()
world.damage_challenge = args.damage_challenge.copy()
world.shuffle_damage_table = args.shuffle_damage_table.copy()
world.crystal_book = args.crystal_book.copy()
world.overworld_map = args.overworld_map.copy()
world.take_any = args.take_any.copy()
@@ -621,6 +622,7 @@ def copy_world(world):
ret.mirrorscroll = world.mirrorscroll.copy()
ret.dark_rooms = world.dark_rooms.copy()
ret.damage_challenge = world.damage_challenge.copy()
ret.shuffle_damage_table = world.shuffle_damage_table.copy()
ret.crystal_book = world.crystal_book.copy()
ret.overworld_map = world.overworld_map.copy()
ret.take_any = world.take_any.copy()
@@ -845,6 +847,7 @@ def copy_world_premature(world, player):
ret.mirrorscroll = world.mirrorscroll.copy()
ret.dark_rooms = world.dark_rooms.copy()
ret.damage_challenge = world.damage_challenge.copy()
ret.shuffle_damage_table = world.shuffle_damage_table.copy()
ret.crystal_book = world.crystal_book.copy()
ret.overworld_map = world.overworld_map.copy()
ret.take_any = world.take_any.copy()

15
Rom.py
View File

@@ -33,6 +33,7 @@ from source.overworld.EntranceData import door_addresses, ow_prize_table
from source.overworld.EntranceShuffle2 import exit_ids
from OverworldShuffle import default_flute_connections, flute_data
from InitialSram import InitialSram
from DamageTable import DamageTable
from source.classes.SFX import randomize_sfx, randomize_sfxinstruments, randomize_songinstruments
from source.item.FillUtil import valid_pot_items
@@ -1667,6 +1668,7 @@ def patch_rom(world, rom, player, team, is_mystery=False):
world.data_tables[player].write_to_rom(rom, colorize_pots, world.enemy_shuffle[player] == 'random')
write_enemizer_tweaks(rom, world, player)
randomize_damage_table(rom, world, player)
write_strings(rom, world, player, team)
# write initial sram
@@ -1766,6 +1768,19 @@ def write_enemizer_tweaks(rom, world, player):
rom.write_byte(snes_to_pc(0x0DB6B3), 0x82) # hovers don't need water necessarily?
def randomize_damage_table(rom, world, player):
if world.shuffle_damage_table[player] == 'randomized':
rom.write_bytes(snes_to_pc(0x0DB8F9),
[0x00, 0x01, 0x02, 0x03, 0x04, 0x08, 0x10, 0x40,
0x00, 0x01, 0x02, 0x03, 0x04, 0x08, 0x10, 0x40,
0x00, 0x01, 0x02, 0x03, 0x04, 0x08, 0x10, 0x40,
0x00, 0x01, 0x02, 0x03, 0x04, 0x08, 0x10, 0x40,
0x00, 0x01, 0x02, 0x03, 0x04, 0x08, 0x10, 0x40])
dmg_table = DamageTable()
dmg_table.randomize_sword_subclasses()
rom.write_bytes(snes_to_pc(0x31C800), dmg_table.get_bytes())
def hud_format_text(text):
output = bytes()
for char in text.lower():

BIN
data/damage_table.bin Normal file

Binary file not shown.

View File

@@ -616,6 +616,12 @@
"mimics"
]
},
"shuffle_damage_table": {
"choices": [
"vanilla",
"randomized"
]
},
"enemy_health": {
"choices": [
"default",