MM2: fix plando and weakness special cases (#4561)

This commit is contained in:
Silvris 2025-01-28 14:45:28 -06:00 committed by GitHub
parent a53bcb4697
commit 9466d5274e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 28 deletions

View File

@ -175,7 +175,7 @@ class WeaknessPlando(OptionDict):
display_name = "Plando Weaknesses" display_name = "Plando Weaknesses"
schema = Schema({ schema = Schema({
Optional(And(str, Use(str.title), lambda s: s in bosses)): { Optional(And(str, Use(str.title), lambda s: s in bosses)): {
And(str, Use(str.title), lambda s: s in weapons_to_id): And(int, lambda i: i in range(-1, 14)) And(str, Use(str.title), lambda s: s in weapons_to_id): And(int, lambda i: i in range(-1, 15))
} }
}) })
default = {} default = {}

View File

@ -135,41 +135,47 @@ def set_rules(world: "MM2World") -> None:
world.weapon_damage[weapon][i] = 0 world.weapon_damage[weapon][i] = 0
for p_boss in world.options.plando_weakness: for p_boss in world.options.plando_weakness:
boss = bosses[p_boss]
for p_weapon in world.options.plando_weakness[p_boss]: for p_weapon in world.options.plando_weakness[p_boss]:
if world.options.plando_weakness[p_boss][p_weapon] < minimum_weakness_requirement[p_weapon] \ weapon = weapons_to_id[p_weapon]
and not any(w != p_weapon if world.options.plando_weakness[p_boss][p_weapon] < minimum_weakness_requirement[weapon] \
and world.weapon_damage[w][bosses[p_boss]] > minimum_weakness_requirement[w] and not any(w != weapon
and world.weapon_damage[w][boss] >= minimum_weakness_requirement[w]
for w in world.weapon_damage): for w in world.weapon_damage):
# we need to replace this weakness # we need to replace this weakness
weakness = world.random.choice([key for key in world.weapon_damage if key != p_weapon]) weakness = world.random.choice([key for key in world.weapon_damage if key != weapon])
world.weapon_damage[weakness][bosses[p_boss]] = minimum_weakness_requirement[weakness] world.weapon_damage[weakness][boss] = minimum_weakness_requirement[weakness]
world.weapon_damage[weapons_to_id[p_weapon]][bosses[p_boss]] \ world.weapon_damage[weapon][boss] = world.options.plando_weakness[p_boss][p_weapon]
= world.options.plando_weakness[p_boss][p_weapon]
# handle special cases # handle special cases
for boss in range(14): for boss in range(14):
for weapon in (1, 2, 3, 6, 8): for weapon in (1, 2, 3, 6, 8):
if (0 < world.weapon_damage[weapon][boss] < minimum_weakness_requirement[weapon] and if (0 < world.weapon_damage[weapon][boss] < minimum_weakness_requirement[weapon] and
not any(world.weapon_damage[i][boss] >= minimum_weakness_requirement[weapon] not any(world.weapon_damage[i][boss] >= minimum_weakness_requirement[i]
for i in range(9) if i != weapon)): for i in range(9) if i != weapon)):
# Weapon does not have enough possible ammo to kill the boss, raise the damage # Weapon does not have enough possible ammo to kill the boss, raise the damage
if boss == 9:
if weapon in (1, 6):
# Atomic Fire and Crash Bomber cannot be Picopico-kun's only weakness
world.weapon_damage[weapon][boss] = 0
weakness = world.random.choice((2, 3, 4, 5, 7, 8))
world.weapon_damage[weakness][boss] = minimum_weakness_requirement[weakness]
elif boss == 11:
if weapon == 1:
# Atomic Fire cannot be Boobeam Trap's only weakness
world.weapon_damage[weapon][boss] = 0
weakness = world.random.choice((2, 3, 4, 5, 6, 7, 8))
world.weapon_damage[weakness][boss] = minimum_weakness_requirement[weakness]
else:
world.weapon_damage[weapon][boss] = minimum_weakness_requirement[weapon] world.weapon_damage[weapon][boss] = minimum_weakness_requirement[weapon]
for weapon in (1, 6):
if (world.weapon_damage[weapon][9] >= minimum_weakness_requirement[weapon] and
not any(world.weapon_damage[i][9] >= minimum_weakness_requirement[i]
for i in range(9) if i not in (1, 6))):
# Atomic Fire and Crash Bomber cannot be Picopico-kun's only weakness
world.weapon_damage[weapon][9] = 0
weakness = world.random.choice((2, 3, 4, 5, 7, 8))
world.weapon_damage[weakness][9] = minimum_weakness_requirement[weakness]
if (world.weapon_damage[1][11] >= minimum_weakness_requirement[1] and
not any(world.weapon_damage[i][11] >= minimum_weakness_requirement[i]
for i in range(9) if i != 1)):
# Atomic Fire cannot be Boobeam Trap's only weakness
world.weapon_damage[1][11] = 0
weakness = world.random.choice((2, 3, 4, 5, 6, 7, 8))
world.weapon_damage[weakness][11] = minimum_weakness_requirement[weakness]
if world.weapon_damage[0][world.options.starting_robot_master.value] < 1: if world.weapon_damage[0][world.options.starting_robot_master.value] < 1:
world.weapon_damage[0][world.options.starting_robot_master.value] = weapon_damage[0][world.options.starting_robot_master.value] world.weapon_damage[0][world.options.starting_robot_master.value] = \
weapon_damage[0][world.options.starting_robot_master.value]
# final special case # final special case
# There's a vanilla crash if Time Stopper kills Wily phase 1 # There's a vanilla crash if Time Stopper kills Wily phase 1
@ -218,9 +224,10 @@ def set_rules(world: "MM2World") -> None:
# we are out of weapons that can actually damage the boss # we are out of weapons that can actually damage the boss
# so find the weapon that has the most uses, and apply that as an additional weakness # so find the weapon that has the most uses, and apply that as an additional weakness
# it should be impossible to be out of energy, simply because even if every boss took 1 from # it should be impossible to be out of energy, simply because even if every boss took 1 from
# Quick Boomerang and no other, it would only be 28 off from defeating all 9, which Metal Blade should # Quick Boomerang and no other, it would only be 28 off from defeating all 9,
# be able to cover # which Metal Blade should be able to cover
wp, max_uses = max((weapon, weapon_energy[weapon] // weapon_costs[weapon]) for weapon in weapon_weight wp, max_uses = max((weapon, weapon_energy[weapon] // weapon_costs[weapon])
for weapon in weapon_weight
if weapon != 0 and (weapon != 8 or boss != 12)) if weapon != 0 and (weapon != 8 or boss != 12))
# Wily Machine cannot under any circumstances take damage from Time Stopper, prevent this # Wily Machine cannot under any circumstances take damage from Time Stopper, prevent this
world.weapon_damage[wp][boss] = minimum_weakness_requirement[wp] world.weapon_damage[wp][boss] = minimum_weakness_requirement[wp]