Skip to content

Commit

Permalink
Transformed SigmaOpen intro a OptionSet and reworked slot_data output
Browse files Browse the repository at this point in the history
  • Loading branch information
TheLX5 committed May 24, 2024
1 parent 37c9d0e commit e91f90b
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 85 deletions.
48 changes: 24 additions & 24 deletions worlds/mmx/Options.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from dataclasses import dataclass
import typing

from Options import OptionGroup, Choice, Range, Toggle, DefaultOnToggle, DeathLink, PerGameCommonOptions, StartInventoryPool
#from Options import OptionGroup, Choice, Range, Toggle, DefaultOnToggle, DeathLink, PerGameCommonOptions, StartInventoryPool
from Options import Choice, Range, Toggle, DefaultOnToggle, OptionSet, DeathLink, PerGameCommonOptions, StartInventoryPool

class EnergyLink(DefaultOnToggle):
"""
Expand Down Expand Up @@ -69,8 +70,6 @@ class BossWeaknessStrictness(Choice):
weakness_and_buster: Only allow the weakness and buster to deal damage to the bosses
weakness_and_upgraded_buster: Only allow the weakness and buster charge levels 3 & 4 to deal damage to the bosses
only_weakness: Only the weakness will deal damage to the bosses
Z-Saber damage output will be cut to 50%/37.5%/25% of its original damage according to the strictness setting.
"""
display_name = "Boss Weakness Strictness"
option_not_strict = 0
Expand Down Expand Up @@ -147,29 +146,28 @@ class FortressBundleUnlock(Toggle):
"""
display_name = "Fortress Levels Bundle Unlock"

class SigmaOpen(Choice):
"""
Under what conditions will Sigma's Fortress open.
multiworld: Access will require an Access Code multiworld item, similar to the main stages.
medals: Access will be granted after collecting a certain amount of Maverick Medals.
weapons: Access will be granted after collecting a certain amount of weapons.
armor_upgrades: Access will be granted after collecting a certain amount of armor upgrades.
heart_tanks: Access will be granted after collecting a certain amount of Heart Tanks.
sub_tanks: Access will be granted after collecting a certain amount of Sub Tanks.
all: Access will be granted after collecting a certain amount of Medals, Weapons, Armor Upgrades
Heart Tanks and Sub Tanks.
Do not enable all on solo seeds without pickupsanity or sessions with very few items.
There's a big chance it'll cause an error.
class SigmaOpen(OptionSet):
"""
Under which conditions will Sigma's Fortress open.
If no options are selected a multiworld item granting access to the stage will be created.
Medals: Consider Maverick medals to get access to the fortress.
Weapons: Consider weapons to get access to the fortress.
Armor Upgrades: Consider upgrades to get access to the fortress.
Heart Tanks: Consider heart tanks to get access to the fortress.
Sub Tanks: Consider sub tanks to get access to the fortress.
"""
display_name = "Sigma Fortress Rules"
option_multiworld = 0
option_medals = 1
option_weapons = 2
option_armor_upgrades = 4
option_heart_tanks = 8
option_sub_tanks = 16
option_all = 31
default = 1
valid_keys = {
"Medals",
"Weapons",
"Armor Upgrades",
"Heart Tanks",
"Sub Tanks",
}
default = {
"Medals",
}

class SigmaMedalCount(Range):
"""
Expand Down Expand Up @@ -217,6 +215,7 @@ class SigmaSubTankCount(Range):
default = 4

mmx_option_groups = [
"""
OptionGroup("Sigma Fortress Options", [
SigmaOpen,
SigmaMedalCount,
Expand All @@ -242,6 +241,7 @@ class SigmaSubTankCount(Range):
LogicLegSigma,
LogicChargedShotgunIce,
]),
"""
]

@dataclass
Expand Down
18 changes: 14 additions & 4 deletions worlds/mmx/Rom.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import Utils
import hashlib
import os
from typing import Optional, TYPE_CHECKING
from pkgutil import get_data

from worlds.AutoWorld import World
Expand Down Expand Up @@ -178,8 +177,7 @@ def patch_rom(world: World, patch: MMXProcedurePatch):
0x20,0x42,0x59,0x20,0x4E,0x49,0x4E,0x54,
0x45,0x4E,0x44,0x4F,0x00]))

if world.options.boss_weakness_rando != "vanilla":
adjust_boss_damage_table(world, patch)
adjust_boss_damage_table(world, patch)

if world.options.boss_randomize_hp != "off":
adjust_boss_hp(world, patch)
Expand All @@ -194,7 +192,19 @@ def patch_rom(world: World, patch: MMXProcedurePatch):
patch.write_bytes(0x7FC0, patch.name)

# Write options to the ROM
patch.write_byte(0x17FFE0, world.options.sigma_open.value)
value = 0
sigma_open = world.options.sigma_open.value
if "Medals" in sigma_open:
value |= 0x01
if "Weapons" in sigma_open:
value |= 0x02
if "Armor Upgrades" in sigma_open:
value |= 0x04
if "Heart Tanks" in sigma_open:
value |= 0x08
if "Sub Tanks" in sigma_open:
value |= 0x10
patch.write_byte(0x17FFE0, value)
patch.write_byte(0x17FFE1, world.options.sigma_medal_count.value)
patch.write_byte(0x17FFE2, world.options.sigma_weapon_count.value)
patch.write_byte(0x17FFE3, world.options.sigma_upgrade_count.value)
Expand Down
29 changes: 13 additions & 16 deletions worlds/mmx/Rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,21 +89,22 @@ def set_rules(world: MMXWorld):
lambda state: state.has(ItemName.stage_storm_eagle, player))

# Fortress entrance rules
fortress_open = world.options.sigma_open
fortress_open = world.options.sigma_open.value
entrance = multiworld.get_entrance(f"{RegionName.intro} -> {RegionName.sigma_fortress}", player)

if fortress_open == "multiworld":
if len(fortress_open) == 0:
add_rule(entrance, lambda state: state.has(ItemName.stage_sigma_fortress, player))
if fortress_open in ("medals", "all") and world.options.sigma_medal_count.value > 0:
add_rule(entrance, lambda state: state.has(ItemName.maverick_medal, player, world.options.sigma_medal_count.value))
if fortress_open in ("weapons", "all") and world.options.sigma_weapon_count.value > 0:
add_rule(entrance, lambda state: state.has_group("Weapons", player, world.options.sigma_weapon_count.value))
if fortress_open in ("armor_upgrades", "all") and world.options.sigma_upgrade_count.value > 0:
add_rule(entrance, lambda state: state.has_group("Armor Upgrades", player, world.options.sigma_upgrade_count.value))
if fortress_open in ("heart_tanks", "all") and world.options.sigma_heart_tank_count.value > 0:
add_rule(entrance, lambda state: state.has(ItemName.heart_tank, player, world.options.sigma_heart_tank_count.value))
if fortress_open in ("sub_tanks", "all") and world.options.sigma_sub_tank_count.value > 0:
add_rule(entrance, lambda state: state.has(ItemName.sub_tank, player, world.options.sigma_sub_tank_count.value))
else:
if "Medals" in fortress_open and world.options.sigma_medal_count.value > 0:
add_rule(entrance, lambda state: state.has(ItemName.maverick_medal, player, world.options.sigma_medal_count.value))
if "Weapons" in fortress_open and world.options.sigma_weapon_count.value > 0:
add_rule(entrance, lambda state: state.has_group("Weapons", player, world.options.sigma_weapon_count.value))
if "Armor Upgrades" in fortress_open and world.options.sigma_upgrade_count.value > 0:
add_rule(entrance, lambda state: state.has_group("Armor Upgrades", player, world.options.sigma_upgrade_count.value))
if "Heart Tanks" in fortress_open and world.options.sigma_heart_tank_count.value > 0:
add_rule(entrance, lambda state: state.has(ItemName.heart_tank, player, world.options.sigma_heart_tank_count.value))
if "Sub Tanks" in fortress_open and world.options.sigma_sub_tank_count.value > 0:
add_rule(entrance, lambda state: state.has(ItemName.sub_tank, player, world.options.sigma_sub_tank_count.value))

if world.options.logic_leg_sigma.value:
add_rule(entrance, lambda state: state.has(ItemName.legs, player))
Expand Down Expand Up @@ -234,10 +235,6 @@ def add_boss_weakness_logic(world: MMXWorld):
multiworld = world.multiworld
jammed_buster = world.options.jammed_buster.value

if world.options.boss_weakness_rando == "vanilla":
from .Weaknesses import boss_weaknesses
world.boss_weaknesses = boss_weaknesses

for boss, regions in bosses.items():
weaknesses = world.boss_weaknesses[boss]
for weakness in weaknesses:
Expand Down
94 changes: 53 additions & 41 deletions worlds/mmx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from .Options import MMXOptions, mmx_option_groups
from .Client import MMXSNIClient
from .Levels import location_id_to_level_id
from .Weaknesses import randomize_weaknesses, boss_weaknesses, weapon_id
from .Weaknesses import handle_weaknesses, weapon_id
from .Rom import patch_rom, MMXProcedurePatch, HASH_US, HASH_LEGACY

class MMXSettings(settings.Group):
Expand All @@ -44,7 +44,7 @@ class MMXWeb(WebWorld):

tutorials = [setup_en]

option_groups = mmx_option_groups
#option_groups = mmx_option_groups


class MMXWorld(World):
Expand Down Expand Up @@ -108,36 +108,15 @@ def create_regions(self) -> None:
else:
itempool += [self.create_item(stage_list[i])]

if self.options.sigma_open == "multiworld":
if len(self.options.sigma_open.value) == 0:
itempool += [self.create_item(ItemName.stage_sigma_fortress)]

# Add weapons into the pool
if self.options.sigma_open == "weapons" or (self.options.sigma_open == "all" and self.options.sigma_weapon_count.value > 0):
itempool += [self.create_item(ItemName.electric_spark)]
itempool += [self.create_item(ItemName.homing_torpedo)]
itempool += [self.create_item(ItemName.storm_tornado)]
itempool += [self.create_item(ItemName.shotgun_ice)]
itempool += [self.create_item(ItemName.rolling_shield)]
else:
if self.options.logic_boss_weakness.value:
itempool += [self.create_item(ItemName.electric_spark)]
itempool += [self.create_item(ItemName.homing_torpedo)]
itempool += [self.create_item(ItemName.storm_tornado)]
else:
itempool += [self.create_item(ItemName.electric_spark, ItemClassification.useful)]
itempool += [self.create_item(ItemName.homing_torpedo, ItemClassification.useful)]
itempool += [self.create_item(ItemName.storm_tornado, ItemClassification.useful)]

if self.options.logic_boss_weakness.value or self.options.logic_charged_shotgun_ice.value:
itempool += [self.create_item(ItemName.shotgun_ice)]
else:
itempool += [self.create_item(ItemName.shotgun_ice, ItemClassification.useful)]

if self.options.logic_boss_weakness.value or self.options.pickupsanity.value:
itempool += [self.create_item(ItemName.rolling_shield)]
else:
itempool += [self.create_item(ItemName.rolling_shield, ItemClassification.useful)]

itempool += [self.create_item(ItemName.electric_spark)]
itempool += [self.create_item(ItemName.homing_torpedo)]
itempool += [self.create_item(ItemName.storm_tornado)]
itempool += [self.create_item(ItemName.shotgun_ice)]
itempool += [self.create_item(ItemName.rolling_shield)]
itempool += [self.create_item(ItemName.chameleon_sting)]
itempool += [self.create_item(ItemName.fire_wave)]
itempool += [self.create_item(ItemName.boomerang_cutter)]
Expand All @@ -146,7 +125,8 @@ def create_regions(self) -> None:
itempool += [self.create_item(ItemName.hadouken, ItemClassification.useful)]

# Add upgrades into the pool
if self.options.sigma_open == "armor_upgrades" or (self.options.sigma_open == "all" and self.options.sigma_upgrade_count.value > 0):
sigma_open = self.options.sigma_open.value
if "Armor Upgrades" in sigma_open and self.options.sigma_upgrade_count.value > 0:
itempool += [self.create_item(ItemName.body)]
else:
itempool += [self.create_item(ItemName.body, ItemClassification.useful)]
Expand All @@ -157,7 +137,7 @@ def create_regions(self) -> None:
itempool += [self.create_item(ItemName.legs)]

# Add heart tanks into the pool
if self.options.sigma_open == "heart_tanks" or (self.options.sigma_open == "all" and self.options.sigma_heart_tank_count.value > 0):
if "Heart Tanks" in sigma_open and self.options.sigma_heart_tank_count.value > 0:
i = self.options.sigma_heart_tank_count.value
itempool += [self.create_item(ItemName.heart_tank) for _ in range(i)]
if i != 8:
Expand All @@ -167,7 +147,7 @@ def create_regions(self) -> None:
itempool += [self.create_item(ItemName.heart_tank, ItemClassification.useful) for _ in range(8)]

# Add sub tanks into the pool
if self.options.sigma_open == "sub_tanks" or (self.options.sigma_open == "all" and self.options.sigma_sub_tank_count.value > 0):
if "Sub Tanks" in sigma_open and self.options.sigma_sub_tank_count.value > 0:
i = self.options.sigma_sub_tank_count.value
itempool += [self.create_item(ItemName.sub_tank) for _ in range(i)]
if i != 4:
Expand Down Expand Up @@ -235,22 +215,54 @@ def set_rules(self):

def fill_slot_data(self):
slot_data = {}
for option_name in (attr.name for attr in dataclasses.fields(MMXOptions)
if attr not in dataclasses.fields(PerGameCommonOptions)):
option = getattr(self.options, option_name)
slot_data[option_name] = option.value
# Write options to slot_data
slot_data["boss_weakness_rando"] = self.options.boss_weakness_rando.value
slot_data["boss_weakness_strictness"] = self.options.boss_weakness_strictness.value
slot_data["pickupsanity"] = self.options.pickupsanity.value
slot_data["jammed_buster"] = self.options.jammed_buster.value
slot_data["hadouken_in_pool"] = self.options.hadouken_in_pool.value
slot_data["pickupsanity"] = self.options.pickupsanity.value
slot_data["logic_boss_weakness"] = self.options.logic_boss_weakness.value
slot_data["logic_leg_sigma"] = self.options.logic_leg_sigma.value
slot_data["logic_charged_shotgun_ice"] = self.options.logic_charged_shotgun_ice.value
slot_data["sigma_all_levels"] = self.options.sigma_all_levels.value
value = 0
sigma_open = self.options.sigma_open.value
if "Medals" in sigma_open:
value |= 0x01
if "Weapons" in sigma_open:
value |= 0x02
if "Armor Upgrades" in sigma_open:
value |= 0x04
if "Heart Tanks" in sigma_open:
value |= 0x08
if "Sub Tanks" in sigma_open:
value |= 0x10
slot_data["sigma_open"] = value
slot_data["sigma_medal_count"] = self.options.sigma_medal_count.value
slot_data["sigma_weapon_count"] = self.options.sigma_weapon_count.value
slot_data["sigma_upgrade_count"] = self.options.sigma_upgrade_count.value
slot_data["sigma_heart_tank_count"] = self.options.sigma_heart_tank_count.value
slot_data["sigma_sub_tank_count"] = self.options.sigma_sub_tank_count.value

# Write boss weaknesses to slot_data
slot_data["boss_weaknesses"] = {}
for boss, entries in self.boss_weaknesses.items():
slot_data["boss_weaknesses"][boss] = []
for entry in entries:
slot_data["boss_weaknesses"][boss].append(entry[1])

return slot_data


def generate_early(self):
if self.options.early_legs:
self.multiworld.early_items[self.player][ItemName.legs] = 1

if self.options.boss_weakness_rando != "vanilla":
self.boss_weaknesses = {}
self.boss_weakness_data = {}
randomize_weaknesses(self)

self.boss_weaknesses = {}
self.boss_weakness_data = {}
handle_weaknesses(self)

early_stage = self.random.choice(list(item_groups["Access Codes"]))
self.multiworld.local_early_items[self.player][early_stage] = 1

Expand Down

0 comments on commit e91f90b

Please sign in to comment.