Split enemy shuffle into its components
This commit is contained in:
parent
c2e2c2d5f9
commit
cb4fa6dd33
|
@ -104,9 +104,12 @@ class World(object):
|
|||
set_player_attr('bigkeyshuffle', False)
|
||||
set_player_attr('difficulty_requirements', None)
|
||||
set_player_attr('boss_shuffle', 'none')
|
||||
set_player_attr('enemy_shuffle', 'none')
|
||||
set_player_attr('enemy_shuffle', False)
|
||||
set_player_attr('enemy_health', 'default')
|
||||
set_player_attr('enemy_damage', 'default')
|
||||
set_player_attr('killable_thieves', False)
|
||||
set_player_attr('tile_shuffle', False)
|
||||
set_player_attr('bush_shuffle', False)
|
||||
set_player_attr('beemizer', 0)
|
||||
set_player_attr('escape_assist', [])
|
||||
set_player_attr('crystals_needed_for_ganon', 7)
|
||||
|
@ -1231,6 +1234,9 @@ class Spoiler(object):
|
|||
'enemy_shuffle': self.world.enemy_shuffle,
|
||||
'enemy_health': self.world.enemy_health,
|
||||
'enemy_damage': self.world.enemy_damage,
|
||||
'killable_thieves': self.world.killable_thieves,
|
||||
'tile_shuffle': self.world.tile_shuffle,
|
||||
'bush_shuffle': self.world.bush_shuffle,
|
||||
'beemizer': self.world.beemizer,
|
||||
'progressive': self.world.progressive,
|
||||
'shufflepots': self.world.shufflepots,
|
||||
|
@ -1261,9 +1267,14 @@ class Spoiler(object):
|
|||
|
||||
def to_file(self, filename):
|
||||
self.parse_data()
|
||||
|
||||
def bool_to_text(variable: bool) -> str:
|
||||
return 'Yes' if variable else 'No'
|
||||
|
||||
with open(filename, 'w', encoding="utf-8-sig") as outfile:
|
||||
outfile.write(
|
||||
'ALttP Berserker\'s Multiworld Version %s - Seed: %s\n\n' % (self.metadata['version'], self.world.seed))
|
||||
'ALttP Berserker\'s Multiworld Version %s - Seed: %s\n\n' % (
|
||||
self.metadata['version'], self.world.seed))
|
||||
outfile.write('Filling Algorithm: %s\n' % self.world.algorithm)
|
||||
outfile.write('Players: %d\n' % self.world.players)
|
||||
outfile.write('Teams: %d\n' % self.world.teams)
|
||||
|
@ -1301,15 +1312,23 @@ class Spoiler(object):
|
|||
'Map shuffle: %s\n' % ('Yes' if self.metadata['mapshuffle'][player] else 'No'))
|
||||
outfile.write('Compass shuffle: %s\n' % (
|
||||
'Yes' if self.metadata['compassshuffle'][player] else 'No'))
|
||||
outfile.write('Small Key shuffle: %s\n' % ('Yes' if self.metadata['keyshuffle'][player] else 'No'))
|
||||
outfile.write('Big Key shuffle: %s\n' % ('Yes' if self.metadata['bigkeyshuffle'][player] else 'No'))
|
||||
outfile.write(
|
||||
'Small Key shuffle: %s\n' % ('Yes' if self.metadata['keyshuffle'][player] else 'No'))
|
||||
outfile.write('Big Key shuffle: %s\n' % (
|
||||
'Yes' if self.metadata['bigkeyshuffle'][player] else 'No'))
|
||||
outfile.write('Boss shuffle: %s\n' % self.metadata['boss_shuffle'][player])
|
||||
outfile.write('Enemy shuffle: %s\n' % self.metadata['enemy_shuffle'][player])
|
||||
outfile.write(
|
||||
'Enemy shuffle: %s\n' % bool_to_text(self.metadata['enemy_shuffle'][player]))
|
||||
outfile.write('Enemy health: %s\n' % self.metadata['enemy_health'][player])
|
||||
outfile.write('Enemy damage: %s\n' % self.metadata['enemy_damage'][player])
|
||||
outfile.write('Hints: %s\n' % ('Yes' if self.metadata['hints'][player] else 'No'))
|
||||
outfile.write(f'Killable thieves: {bool_to_text(self.metadata["killable_thieves"])}\n')
|
||||
outfile.write(f'Shuffled tiles: {bool_to_text(self.metadata["tile_shuffle"])}\n')
|
||||
outfile.write(f'Shuffled bushes: {bool_to_text(self.metadata["bush_shuffle"])}\n')
|
||||
outfile.write(
|
||||
'Hints: %s\n' % ('Yes' if self.metadata['hints'][player] else 'No'))
|
||||
outfile.write('Beemizer: %s\n' % self.metadata['beemizer'][player])
|
||||
outfile.write('Pot shuffle %s\n' % ('Yes' if self.metadata['shufflepots'][player] else 'No'))
|
||||
outfile.write(
|
||||
'Pot shuffle %s\n' % ('Yes' if self.metadata['shufflepots'][player] else 'No'))
|
||||
if self.entrances:
|
||||
outfile.write('\n\nEntrances:\n\n')
|
||||
outfile.write('\n'.join(['%s%s %s %s' % (f'{self.world.get_player_names(entry["player"])}: ' if self.world.players > 1 else '', entry['entrance'], '<=>' if entry['direction'] == 'both' else '<=' if entry['direction'] == 'exit' else '=>', entry['exit']) for entry in self.entrances.values()]))
|
||||
|
|
|
@ -293,8 +293,10 @@ def parse_arguments(argv, no_defaults=False):
|
|||
parser.add_argument('--enemizercli', default=defval('EnemizerCLI/EnemizerCLI.Core'))
|
||||
parser.add_argument('--shufflebosses', default=defval('none'), choices=['none', 'basic', 'normal', 'chaos',
|
||||
"singularity"])
|
||||
parser.add_argument('--shuffleenemies', default=defval('none'),
|
||||
choices=['none', 'shuffled', 'chaos', 'chaosthieves'])
|
||||
parser.add_argument('--enemy_shuffle', action='store_true')
|
||||
parser.add_argument('--killable_thieves', action='store_true')
|
||||
parser.add_argument('--tile_shuffle', action='store_true')
|
||||
parser.add_argument('--bush_shuffle', action='store_true')
|
||||
parser.add_argument('--enemy_health', default=defval('default'),
|
||||
choices=['default', 'easy', 'normal', 'hard', 'expert'])
|
||||
parser.add_argument('--enemy_damage', default=defval('default'), choices=['default', 'shuffled', 'chaos'])
|
||||
|
@ -336,10 +338,12 @@ def parse_arguments(argv, no_defaults=False):
|
|||
'shuffle', 'crystals_ganon', 'crystals_gt', 'openpyramid', 'timer',
|
||||
'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle', 'startinventory',
|
||||
'local_items', 'retro', 'accessibility', 'hints', 'beemizer',
|
||||
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
|
||||
'shufflebosses', 'enemy_shuffle', 'enemy_health', 'enemy_damage', 'shufflepots',
|
||||
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
|
||||
'heartbeep', "skip_progression_balancing", "triforce_pieces_available", "triforce_pieces_required",
|
||||
'remote_items', 'progressive', 'dungeon_counters', 'glitch_boots']:
|
||||
'heartbeep', "skip_progression_balancing", "triforce_pieces_available",
|
||||
"triforce_pieces_required",
|
||||
'remote_items', 'progressive', 'dungeon_counters', 'glitch_boots', 'killable_thieves',
|
||||
'tile_shuffle', 'bush_shuffle']:
|
||||
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
|
||||
if player == 1:
|
||||
setattr(ret, name, {1: value})
|
||||
|
|
55
Gui.py
55
Gui.py
|
@ -352,63 +352,75 @@ def guiMain(args=None):
|
|||
|
||||
|
||||
enemizerPathFrame = Frame(enemizerFrame)
|
||||
enemizerPathFrame.grid(row=0, column=0, columnspan=3, sticky=W+E, padx=3)
|
||||
enemizerPathFrame.grid(row=0, column=0, columnspan=4, sticky=W + E, padx=3)
|
||||
enemizerCLIlabel = Label(enemizerPathFrame, text="EnemizerCLI path: ")
|
||||
enemizerCLIlabel.pack(side=LEFT)
|
||||
enemizerCLIpathVar = StringVar(value="EnemizerCLI/EnemizerCLI.Core")
|
||||
enemizerCLIpathEntry = Entry(enemizerPathFrame, textvariable=enemizerCLIpathVar)
|
||||
enemizerCLIpathEntry.pack(side=LEFT, expand=True, fill=X)
|
||||
|
||||
def EnemizerSelectPath():
|
||||
path = filedialog.askopenfilename(filetypes=[("EnemizerCLI executable", "*EnemizerCLI*")])
|
||||
if path:
|
||||
enemizerCLIpathVar.set(path)
|
||||
|
||||
enemizerCLIbrowseButton = Button(enemizerPathFrame, text='...', command=EnemizerSelectPath)
|
||||
enemizerCLIbrowseButton.pack(side=LEFT)
|
||||
|
||||
potShuffleVar = IntVar()
|
||||
potShuffleButton = Checkbutton(enemizerFrame, text="Pot shuffle", variable=potShuffleVar)
|
||||
potShuffleButton.grid(row=0, column=3)
|
||||
|
||||
enemizerEnemyFrame = Frame(enemizerFrame)
|
||||
enemizerEnemyFrame.grid(row=1, column=0, pady=5)
|
||||
enemizerEnemyLabel = Label(enemizerEnemyFrame, text='Enemy shuffle')
|
||||
enemizerEnemyLabel.pack(side=LEFT)
|
||||
enemyShuffleVar = StringVar()
|
||||
enemyShuffleVar.set('none')
|
||||
enemizerEnemyOption = OptionMenu(enemizerEnemyFrame, enemyShuffleVar, 'none', 'shuffled', 'chaos', 'chaosthieves')
|
||||
enemizerEnemyOption.pack(side=LEFT)
|
||||
|
||||
enemyShuffleVar = IntVar()
|
||||
enemizerEnemyButton = Checkbutton(enemizerEnemyFrame, text="Enemy shuffle", variable=enemyShuffleVar)
|
||||
enemizerEnemyButton.pack(side=LEFT)
|
||||
|
||||
enemizerBossFrame = Frame(enemizerFrame)
|
||||
enemizerBossFrame.grid(row=1, column=1)
|
||||
enemizerBossLabel = Label(enemizerBossFrame, text='Boss shuffle')
|
||||
enemizerBossLabel.pack(side=LEFT)
|
||||
enemizerBossVar = StringVar()
|
||||
enemizerBossVar.set('none')
|
||||
enemizerBossOption = OptionMenu(enemizerBossFrame, enemizerBossVar, 'none', 'basic', 'normal', 'chaos',
|
||||
"singularity")
|
||||
enemizerBossOption.pack(side=LEFT)
|
||||
enemizerBossLabel = Label(enemizerBossFrame, text='Boss shuffle')
|
||||
enemizerBossLabel.pack(side=LEFT)
|
||||
|
||||
enemizerDamageFrame = Frame(enemizerFrame)
|
||||
enemizerDamageFrame.grid(row=1, column=2)
|
||||
enemizerDamageLabel = Label(enemizerDamageFrame, text='Enemy damage')
|
||||
enemizerDamageLabel.pack(side=LEFT)
|
||||
enemizerDamageVar = StringVar()
|
||||
enemizerDamageVar.set('default')
|
||||
enemizerDamageOption = OptionMenu(enemizerDamageFrame, enemizerDamageVar, 'default', 'shuffled', 'chaos')
|
||||
enemizerDamageOption.pack(side=LEFT)
|
||||
enemizerDamageLabel = Label(enemizerDamageFrame, text='Enemy damage')
|
||||
enemizerDamageLabel.pack(side=LEFT)
|
||||
|
||||
enemizerHealthFrame = Frame(enemizerFrame)
|
||||
enemizerHealthFrame.grid(row=1, column=3)
|
||||
enemizerHealthLabel = Label(enemizerHealthFrame, text='Enemy health')
|
||||
enemizerHealthLabel.pack(side=LEFT)
|
||||
enemizerHealthVar = StringVar()
|
||||
enemizerHealthVar.set('default')
|
||||
enemizerHealthOption = OptionMenu(enemizerHealthFrame, enemizerHealthVar, 'default', 'easy', 'normal', 'hard', 'expert')
|
||||
enemizerHealthOption = OptionMenu(enemizerHealthFrame, enemizerHealthVar, 'default', 'easy', 'normal', 'hard',
|
||||
'expert')
|
||||
enemizerHealthOption.pack(side=LEFT)
|
||||
enemizerHealthLabel = Label(enemizerHealthFrame, text='Enemy health')
|
||||
enemizerHealthLabel.pack(side=LEFT)
|
||||
|
||||
potShuffleVar = IntVar()
|
||||
potShuffleButton = Checkbutton(enemizerFrame, text="Pot shuffle", variable=potShuffleVar)
|
||||
potShuffleButton.grid(row=2, column=0, sticky=W)
|
||||
|
||||
tileShuffleVar = IntVar()
|
||||
tileShuffleButton = Checkbutton(enemizerFrame, text="Tile shuffle", variable=tileShuffleVar)
|
||||
tileShuffleButton.grid(row=2, column=1, sticky=W)
|
||||
|
||||
bushShuffleVar = IntVar()
|
||||
bushShuffleButton = Checkbutton(enemizerFrame, text="Bush shuffle", variable=bushShuffleVar)
|
||||
bushShuffleButton.grid(row=2, column=2, sticky=W)
|
||||
|
||||
killableThievesVar = IntVar()
|
||||
killable_thievesShuffleButton = Checkbutton(enemizerFrame, text="Killable Thieves", variable=killableThievesVar)
|
||||
killable_thievesShuffleButton.grid(row=2, column=3, sticky=W)
|
||||
|
||||
multiworldframe = LabelFrame(randomizerWindow, text="Multiworld", padx=5, pady=2)
|
||||
|
||||
|
||||
worldLabel = Label(multiworldframe, text='Worlds')
|
||||
worldVar = StringVar()
|
||||
worldSpinbox = Spinbox(multiworldframe, from_=1, to=255, width=5, textvariable=worldVar)
|
||||
|
@ -470,7 +482,10 @@ def guiMain(args=None):
|
|||
guiargs.hints = bool(hintsVar.get())
|
||||
guiargs.enemizercli = enemizerCLIpathVar.get()
|
||||
guiargs.shufflebosses = enemizerBossVar.get()
|
||||
guiargs.shuffleenemies = enemyShuffleVar.get()
|
||||
guiargs.enemy_shuffle = enemyShuffleVar.get()
|
||||
guiargs.bush_shuffle = bushShuffleVar.get()
|
||||
guiargs.tile_shuffle = tileShuffleVar.get()
|
||||
guiargs.killable_thieves = killableThievesVar.get()
|
||||
guiargs.enemy_health = enemizerHealthVar.get()
|
||||
guiargs.enemy_damage = enemizerDamageVar.get()
|
||||
guiargs.shufflepots = bool(potShuffleVar.get())
|
||||
|
|
10
Main.py
10
Main.py
|
@ -64,9 +64,12 @@ def main(args, seed=None):
|
|||
for player in range(1, world.players + 1)}
|
||||
world.open_pyramid = args.openpyramid.copy()
|
||||
world.boss_shuffle = args.shufflebosses.copy()
|
||||
world.enemy_shuffle = args.shuffleenemies.copy()
|
||||
world.enemy_shuffle = args.enemy_shuffle.copy()
|
||||
world.enemy_health = args.enemy_health.copy()
|
||||
world.enemy_damage = args.enemy_damage.copy()
|
||||
world.killable_thieves = args.killable_thieves.copy()
|
||||
world.bush_shuffle = args.bush_shuffle.copy()
|
||||
world.tile_shuffle = args.tile_shuffle.copy()
|
||||
world.beemizer = args.beemizer.copy()
|
||||
world.timer = args.timer.copy()
|
||||
world.shufflepots = args.shufflepots.copy()
|
||||
|
@ -180,9 +183,10 @@ def main(args, seed=None):
|
|||
|
||||
def _gen_rom(team: int, player: int):
|
||||
sprite_random_on_hit = type(args.sprite[player]) is str and args.sprite[player].lower() == 'randomonhit'
|
||||
use_enemizer = (world.boss_shuffle[player] != 'none' or world.enemy_shuffle[player] != 'none'
|
||||
use_enemizer = (world.boss_shuffle[player] != 'none' or world.enemy_shuffle[player]
|
||||
or world.enemy_health[player] != 'default' or world.enemy_damage[player] != 'default'
|
||||
or args.shufflepots[player] or sprite_random_on_hit)
|
||||
or world.shufflepots[player] or sprite_random_on_hit or world.bush_shuffle[player]
|
||||
or world.killable_thieves[player] or world.tile_shuffle[player])
|
||||
|
||||
rom = LocalRom(args.rom)
|
||||
|
||||
|
|
37
Mystery.py
37
Mystery.py
|
@ -329,17 +329,40 @@ def roll_settings(weights):
|
|||
ret.shufflebosses = {'none': 'none',
|
||||
'simple': 'basic',
|
||||
'full': 'normal',
|
||||
'random': 'chaos',
|
||||
'random': 'random',
|
||||
'singularity': 'singularity',
|
||||
'duality': 'singularity'
|
||||
}[get_choice('boss_shuffle', weights)]
|
||||
|
||||
ret.shuffleenemies = {'none': 'none',
|
||||
'shuffled': 'shuffled',
|
||||
'random': 'chaos',
|
||||
'chaosthieves': 'chaosthieves',
|
||||
'chaos': 'chaos'
|
||||
}[get_choice('enemy_shuffle', weights)]
|
||||
ret.enemy_shuffle = {'none': False,
|
||||
'shuffled': 'shuffled',
|
||||
'random': 'chaos',
|
||||
'chaosthieves': 'chaosthieves',
|
||||
'chaos': 'chaos',
|
||||
True: True,
|
||||
False: False,
|
||||
None: False
|
||||
}[get_choice('enemy_shuffle', weights, False)]
|
||||
|
||||
ret.killable_thieves = get_choice('killable_thieves', weights, False)
|
||||
ret.tile_shuffle = get_choice('tile_shuffle', weights, False)
|
||||
ret.bush_shuffle = get_choice('bush_shuffle', weights, False)
|
||||
|
||||
# legacy support for enemy shuffle
|
||||
if type(ret.enemy_shuffle) == str:
|
||||
if ret.enemy_shuffle == 'shuffled':
|
||||
ret.killable_thieves = True
|
||||
elif ret.enemy_shuffle == 'chaos':
|
||||
ret.killable_thieves = True
|
||||
ret.bush_shuffle = True
|
||||
ret.tile_shuffle = True
|
||||
elif ret.enemy_shuffle == "chaosthieves":
|
||||
ret.killable_thieves = False
|
||||
ret.bush_shuffle = True
|
||||
ret.tile_shuffle = True
|
||||
ret.enemy_shuffle = True
|
||||
logging.info(ret.enemy_shuffle)
|
||||
# end of legacy block
|
||||
|
||||
ret.enemy_damage = {'default': 'default',
|
||||
'shuffled': 'shuffled',
|
||||
|
|
9
Rom.py
9
Rom.py
|
@ -196,9 +196,9 @@ def patch_enemizer(world, player: int, rom: LocalRom, enemizercli, random_sprite
|
|||
|
||||
# write options file for enemizer
|
||||
options = {
|
||||
'RandomizeEnemies': world.enemy_shuffle[player] != 'none',
|
||||
'RandomizeEnemies': world.enemy_shuffle[player],
|
||||
'RandomizeEnemiesType': 3,
|
||||
'RandomizeBushEnemyChance': 'chaos' in world.enemy_shuffle[player],
|
||||
'RandomizeBushEnemyChance': world.bush_shuffle[player],
|
||||
'RandomizeEnemyHealthRange': world.enemy_health[player] != 'default',
|
||||
'RandomizeEnemyHealthType': {'default': 0, 'easy': 0, 'normal': 1, 'hard': 2, 'expert': 3}[
|
||||
world.enemy_health[player]],
|
||||
|
@ -247,10 +247,9 @@ def patch_enemizer(world, player: int, rom: LocalRom, enemizercli, random_sprite
|
|||
'SwordGraphics': "sword_gfx/normal.gfx",
|
||||
'BeeMizer': False,
|
||||
'BeesLevel': 0,
|
||||
'RandomizeTileTrapPattern': world.enemy_shuffle[player] == 'chaos',
|
||||
'RandomizeTileTrapPattern': world.tile_shuffle[player],
|
||||
'RandomizeTileTrapFloorTile': False,
|
||||
'AllowKillableThief': bool(world.rom_seeds[player].randint(0, 1)) if 'thieves' in world.enemy_shuffle[player] else
|
||||
world.enemy_shuffle[player] != 'none',
|
||||
'AllowKillableThief': world.killable_thieves[player],
|
||||
'RandomizeSpriteOnHit': random_sprite_on_hit,
|
||||
'DebugMode': False,
|
||||
'DebugForceEnemy': False,
|
||||
|
|
22
easy.yaml
22
easy.yaml
|
@ -145,18 +145,25 @@ item_functionality:
|
|||
progression_balancing:
|
||||
on: 1 # A system to reduce BK, as in times during which you can't do anything by moving your items into an earlier access sphere to make it likely you have stuff to do
|
||||
off: 0 # Turn this off if you don't mind a longer multiworld, or can glitch around missing items.
|
||||
### Enemizer Section ###
|
||||
boss_shuffle:
|
||||
none: 1 # Vanilla bosses
|
||||
simple: 0 # Existing bosses except Ganon and Agahnim are shuffled throughout dungeons
|
||||
full: 0 # 3 bosses can occur twice
|
||||
random: 0 # Any boss can appear any amount of times
|
||||
singularity: 0 # Picks any boss that can appear anywhere and puts that boss into every arena
|
||||
duality: 0 # Picks a boss that can only appear in some places and a boss that can appear anywhere, then attempts to put both in that order in every arena
|
||||
enemy_shuffle:
|
||||
none: 1 # Vanilla enemy placement
|
||||
chaos: 0 # Enemies are randomized
|
||||
random: 0 # Also shuffle bush enemies, random tile rooms, and random bush enemy spawn chance
|
||||
chaosthieves: 0 # Random + thieves may not be killable
|
||||
singularity: 0 # Picks a boss, tries to put it everywhere that works, if there's spaces remaining it picks a boss to fill those
|
||||
enemy_shuffle: # randomize enemy placement
|
||||
on: 0
|
||||
off: 1
|
||||
killable_thieves: # make thieves killable.
|
||||
on: 0 # usually turned on together with enemy_shuffle to make annoying thief placement more manageable
|
||||
off: 1
|
||||
tile_shuffle: # randomize the tile layouts in flying tile rooms
|
||||
on: 0
|
||||
off: 1
|
||||
bush_shuffle: # randomize the chance that bushes have enemies and the enemies under said bush
|
||||
on: 0
|
||||
off: 1
|
||||
enemy_damage:
|
||||
default: 1 # Vanilla enemy damage
|
||||
shuffled: 0 # Enemies deal 0 to 4 hearts and armor helps
|
||||
|
@ -169,6 +176,7 @@ enemy_health:
|
|||
pot_shuffle:
|
||||
'on': 0 # Keys, items, and buttons hidden under pots in dungeons are shuffled with other pots in their supertile
|
||||
'off': 1 # Default pot item locations
|
||||
### End of Enemizer Section ###
|
||||
beemizer: # Remove items from the global item pool and replace them with single bees and bee traps
|
||||
0: 1 # No bee traps are placed
|
||||
1: 0 # 25% of the non-essential item pool is replaced with bee traps
|
||||
|
|
Loading…
Reference in New Issue