MMBN3: Logic and Bug Fixes, New Checks (#3646)
* PMDs now check to make sure you have enough unlockers for all of them before any are in logic, to avoid softlocks * Adds Humor and BlckMnd to the pool and sets logic for Villain and Comedian. Patch not yet updated to remove starting inventory * Adds Serenade as a check * Fixes hide and seek completion to use proper Yoka Zoo map. Updates bsdiff patch to 1.2 * Adds option for excluding Secret Area, and item/location groups for further customization * Update worlds/mmbn3/Locations.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update worlds/mmbn3/Regions.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update worlds/mmbn3/__init__.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update worlds/mmbn3/__init__.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update worlds/mmbn3/__init__.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Replaces can_reach generic with can_reach_region or can_reach_location, where applciable * Unlocker is now a progression item, Excluded Locations is now a Set * Missed a merge marker * Excluded locations is no longer a set since you can't append to a set with += * Excluded locations is now a set again since you apparent can append to a set with |= * Replaces more lists with sets. Fixes wording in option descriptions * Update worlds/mmbn3/__init__.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com>
This commit is contained in:
parent
3d5c277c31
commit
d218dec826
|
@ -85,7 +85,7 @@ keyItemList: typing.List[ItemData] = [
|
|||
]
|
||||
|
||||
subChipList: typing.List[ItemData] = [
|
||||
ItemData(0xB31018, ItemName.Unlocker, ItemClassification.useful, ItemType.SubChip, 117),
|
||||
ItemData(0xB31018, ItemName.Unlocker, ItemClassification.progression, ItemType.SubChip, 117),
|
||||
ItemData(0xB31019, ItemName.Untrap, ItemClassification.filler, ItemType.SubChip, 115),
|
||||
ItemData(0xB3101A, ItemName.LockEnmy, ItemClassification.filler, ItemType.SubChip, 116),
|
||||
ItemData(0xB3101B, ItemName.MiniEnrg, ItemClassification.filler, ItemType.SubChip, 112),
|
||||
|
@ -290,7 +290,9 @@ programList: typing.List[ItemData] = [
|
|||
ItemData(0xB31099, ItemName.WpnLV_plus_Yellow, ItemClassification.filler, ItemType.Program, 35, ProgramColor.Yellow),
|
||||
ItemData(0xB3109A, ItemName.Press, ItemClassification.progression, ItemType.Program, 20, ProgramColor.White),
|
||||
|
||||
ItemData(0xB310B7, ItemName.UnderSht, ItemClassification.useful, ItemType.Program, 30, ProgramColor.White)
|
||||
ItemData(0xB310B7, ItemName.UnderSht, ItemClassification.useful, ItemType.Program, 30, ProgramColor.White),
|
||||
ItemData(0xB310E0, ItemName.Humor, ItemClassification.progression, ItemType.Program, 45, ProgramColor.Pink),
|
||||
ItemData(0xB310E1, ItemName.BlckMnd, ItemClassification.progression, ItemType.Program, 46, ProgramColor.White)
|
||||
]
|
||||
|
||||
zennyList: typing.List[ItemData] = [
|
||||
|
@ -338,8 +340,29 @@ item_frequencies: typing.Dict[str, int] = {
|
|||
ItemName.zenny_800z: 2,
|
||||
ItemName.zenny_1000z: 2,
|
||||
ItemName.zenny_1200z: 2,
|
||||
ItemName.bugfrag_01: 5,
|
||||
ItemName.bugfrag_01: 10,
|
||||
ItemName.bugfrag_10: 5
|
||||
}
|
||||
|
||||
item_groups: typing.Dict[str, typing.Set[str]] = {
|
||||
"Key Items": {loc.itemName for loc in keyItemList},
|
||||
"Subchips": {loc.itemName for loc in subChipList},
|
||||
"Programs": {loc.itemName for loc in programList},
|
||||
"BattleChips": {loc.itemName for loc in chipList},
|
||||
"Zenny": {loc.itemName for loc in zennyList},
|
||||
"BugFrags": {loc.itemName for loc in bugFragList},
|
||||
"Navi Chips": {
|
||||
ItemName.Roll_R, ItemName.RollV2_R, ItemName.RollV3_R, ItemName.GutsMan_G, ItemName.GutsManV2_G,
|
||||
ItemName.GutsManV3_G, ItemName.ProtoMan_B, ItemName.ProtoManV2_B, ItemName.ProtoManV3_B, ItemName.FlashMan_F,
|
||||
ItemName.FlashManV2_F, ItemName.FlashManV3_F, ItemName.BeastMan_B, ItemName.BeastManV2_B, ItemName.BeastManV3_B,
|
||||
ItemName.BubblMan_B, ItemName.BubblManV2_B, ItemName.BubblManV3_B, ItemName.DesertMan_D, ItemName.DesertManV2_D,
|
||||
ItemName.DesertManV3_D, ItemName.PlantMan_P, ItemName.PlantManV2_P, ItemName.PlantManV3_P, ItemName.FlamMan_F,
|
||||
ItemName.FlamManV2_F, ItemName.FlamManV3_F, ItemName.DrillMan_D, ItemName.DrillManV2_D, ItemName.DrillManV3_D,
|
||||
ItemName.MetalMan_M, ItemName.MetalManV2_M, ItemName.MetalManV3_M, ItemName.KingMan_K, ItemName.KingManV2_K,
|
||||
ItemName.KingManV3_K, ItemName.BowlMan_B, ItemName.BowlManV2_B, ItemName.BowlManV3_B
|
||||
}
|
||||
}
|
||||
|
||||
all_items: typing.List[ItemData] = keyItemList + subChipList + chipList + programList + zennyList + bugFragList
|
||||
item_table: typing.Dict[str, ItemData] = {item.itemName: item for item in all_items}
|
||||
items_by_id: typing.Dict[int, ItemData] = {item.code: item for item in all_items}
|
||||
|
|
|
@ -221,7 +221,8 @@ overworlds = [
|
|||
LocationData(LocationName.Hades_Boat_Dock, 0xb310ab, 0x200024c, 0x10, 0x7519B0, 223, [3]),
|
||||
LocationData(LocationName.WWW_Control_Room_1_Screen, 0xb310ac, 0x200024d, 0x40, 0x7596C4, 222, [3, 4]),
|
||||
LocationData(LocationName.WWW_Wilys_Desk, 0xb310ad, 0x200024d, 0x2, 0x759384, 229, [3]),
|
||||
LocationData(LocationName.Undernet_4_Pillar_Prog, 0xb310ae, 0x2000161, 0x1, 0x7746C8, 191, [0, 1])
|
||||
LocationData(LocationName.Undernet_4_Pillar_Prog, 0xb310ae, 0x2000161, 0x1, 0x7746C8, 191, [0, 1]),
|
||||
LocationData(LocationName.Serenade, 0xb3110f, 0x2000178, 0x40, 0x7B3C74, 1, [0])
|
||||
]
|
||||
|
||||
jobs = [
|
||||
|
@ -240,7 +241,8 @@ jobs = [
|
|||
# LocationData(LocationName.Gathering_Data, 0xb310bb, 0x2000300, 0x10, 0x739580, 193, [0]),
|
||||
LocationData(LocationName.Somebody_please_help, 0xb310bc, 0x2000301, 0x4, 0x73A14C, 193, [0]),
|
||||
LocationData(LocationName.Looking_for_condor, 0xb310bd, 0x2000301, 0x2, 0x749444, 203, [0]),
|
||||
LocationData(LocationName.Help_with_rehab, 0xb310be, 0x2000301, 0x1, 0x762CF0, 192, [3]),
|
||||
LocationData(LocationName.Help_with_rehab, 0xb310be, 0x2000301, 0x1, 0x762CF0, 192, [0]),
|
||||
LocationData(LocationName.Help_with_rehab_bonus, 0xb3110e, 0x2000301, 0x1, 0x762CF0, 192, [3]),
|
||||
LocationData(LocationName.Old_Master, 0xb310bf, 0x2000302, 0x80, 0x760E80, 193, [0]),
|
||||
LocationData(LocationName.Catching_gang_members, 0xb310c0, 0x2000302, 0x40, 0x76EAE4, 193, [0]),
|
||||
LocationData(LocationName.Please_adopt_a_virus, 0xb310c1, 0x2000302, 0x20, 0x76A4F4, 193, [0]),
|
||||
|
@ -250,7 +252,7 @@ jobs = [
|
|||
LocationData(LocationName.Hide_and_seek_Second_Child, 0xb310c5, 0x2000188, 0x2, 0x75ADA8, 191, [0]),
|
||||
LocationData(LocationName.Hide_and_seek_Third_Child, 0xb310c6, 0x2000188, 0x1, 0x75B5EC, 191, [0]),
|
||||
LocationData(LocationName.Hide_and_seek_Fourth_Child, 0xb310c7, 0x2000189, 0x80, 0x75BEB0, 191, [0]),
|
||||
LocationData(LocationName.Hide_and_seek_Completion, 0xb310c8, 0x2000302, 0x8, 0x7406A0, 193, [0]),
|
||||
LocationData(LocationName.Hide_and_seek_Completion, 0xb310c8, 0x2000302, 0x8, 0x742D40, 193, [0]),
|
||||
LocationData(LocationName.Finding_the_blue_Navi, 0xb310c9, 0x2000302, 0x4, 0x773700, 192, [0]),
|
||||
LocationData(LocationName.Give_your_support, 0xb310ca, 0x2000302, 0x2, 0x752D80, 192, [0]),
|
||||
LocationData(LocationName.Stamp_collecting, 0xb310cb, 0x2000302, 0x1, 0x756074, 193, [0]),
|
||||
|
@ -329,10 +331,7 @@ chocolate_shop = [
|
|||
LocationData(LocationName.Chocolate_Shop_32, 0xb3110d, 0x20001c3, 0x01, 0x73F8FC, 181, [0]),
|
||||
]
|
||||
|
||||
always_excluded_locations = [
|
||||
LocationName.Undernet_7_PMD,
|
||||
LocationName.Undernet_7_Northeast_BMD,
|
||||
LocationName.Undernet_7_Northwest_BMD,
|
||||
secret_locations = {
|
||||
LocationName.Secret_1_Northwest_BMD,
|
||||
LocationName.Secret_1_Northeast_BMD,
|
||||
LocationName.Secret_1_South_BMD,
|
||||
|
@ -341,19 +340,23 @@ always_excluded_locations = [
|
|||
LocationName.Secret_2_Island_BMD,
|
||||
LocationName.Secret_3_Island_BMD,
|
||||
LocationName.Secret_3_BugFrag_BMD,
|
||||
LocationName.Secret_3_South_BMD
|
||||
]
|
||||
LocationName.Secret_3_South_BMD,
|
||||
LocationName.Serenade
|
||||
}
|
||||
|
||||
location_groups: typing.Dict[str, typing.Set[str]] = {
|
||||
"BMDs": {loc.name for loc in bmds},
|
||||
"PMDs": {loc.name for loc in pmds},
|
||||
"Jobs": {loc.name for loc in jobs},
|
||||
"Number Trader": {loc.name for loc in number_traders},
|
||||
"Bugfrag Trader": {loc.name for loc in chocolate_shop},
|
||||
"Secret Area": {LocationName.Secret_1_Northwest_BMD, LocationName.Secret_1_Northeast_BMD,
|
||||
LocationName.Secret_1_South_BMD, LocationName.Secret_2_Upper_BMD, LocationName.Secret_2_Lower_BMD,
|
||||
LocationName.Secret_2_Island_BMD, LocationName.Secret_3_Island_BMD,
|
||||
LocationName.Secret_3_BugFrag_BMD, LocationName.Secret_3_South_BMD, LocationName.Serenade},
|
||||
}
|
||||
|
||||
all_locations: typing.List[LocationData] = bmds + pmds + overworlds + jobs + number_traders + chocolate_shop
|
||||
scoutable_locations: typing.List[LocationData] = [loc for loc in all_locations if loc.hint_flag is not None]
|
||||
location_table: typing.Dict[str, int] = {locData.name: locData.id for locData in all_locations}
|
||||
location_data_table: typing.Dict[str, LocationData] = {locData.name: locData for locData in all_locations}
|
||||
|
||||
|
||||
"""
|
||||
def setup_locations(world, player: int):
|
||||
# If we later include options to change what gets added to the random pool,
|
||||
# this is where they would be changed
|
||||
return {locData.name: locData.id for locData in all_locations}
|
||||
"""
|
||||
|
|
|
@ -173,6 +173,8 @@ class ItemName():
|
|||
WpnLV_plus_White = "WpnLV+1 (White)"
|
||||
Press = "Press"
|
||||
UnderSht = "UnderSht"
|
||||
Humor = "Humor"
|
||||
BlckMnd = "BlckMnd"
|
||||
|
||||
## Currency
|
||||
zenny_200z = "200z"
|
||||
|
|
|
@ -210,6 +210,7 @@ class LocationName():
|
|||
WWW_Control_Room_1_Screen = "WWW Control Room 1 Screen"
|
||||
WWW_Wilys_Desk = "WWW Wily's Desk"
|
||||
Undernet_4_Pillar_Prog = "Undernet 4 Pillar Prog"
|
||||
Serenade = "Serenade"
|
||||
|
||||
## Numberman Codes
|
||||
Numberman_Code_01 = "Numberman Code 01"
|
||||
|
@ -261,6 +262,7 @@ class LocationName():
|
|||
Somebody_please_help = "Job: Somebody, please help!"
|
||||
Looking_for_condor = "Job: Looking for condor"
|
||||
Help_with_rehab = "Job: Help with rehab"
|
||||
Help_with_rehab_bonus = "Job: Help with rehab bonus"
|
||||
Old_Master = "Job: Old Master"
|
||||
Catching_gang_members = "Job: Catching gang members"
|
||||
Please_adopt_a_virus = "Job: Please adopt a virus!"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from dataclasses import dataclass
|
||||
from Options import Choice, Range, DefaultOnToggle, PerGameCommonOptions
|
||||
from Options import Choice, Range, DefaultOnToggle, Toggle, PerGameCommonOptions
|
||||
|
||||
|
||||
class ExtraRanks(Range):
|
||||
|
@ -17,10 +17,17 @@ class ExtraRanks(Range):
|
|||
|
||||
class IncludeJobs(DefaultOnToggle):
|
||||
"""
|
||||
Whether Jobs can be included in logic.
|
||||
Whether Jobs can contain progression or useful items.
|
||||
"""
|
||||
display_name = "Include Jobs"
|
||||
|
||||
|
||||
class IncludeSecretArea(Toggle):
|
||||
"""
|
||||
Whether the Secret Area (including Serenade) can contain progression or useful items.
|
||||
"""
|
||||
display_name = "Include Secret Area"
|
||||
|
||||
# Possible logic options:
|
||||
# - Include Number Trader
|
||||
# - Include Secret Area
|
||||
|
@ -46,5 +53,6 @@ class TradeQuestHinting(Choice):
|
|||
class MMBN3Options(PerGameCommonOptions):
|
||||
extra_ranks: ExtraRanks
|
||||
include_jobs: IncludeJobs
|
||||
include_secret: IncludeSecretArea
|
||||
trade_quest_hinting: TradeQuestHinting
|
||||
|
|
@ -135,6 +135,7 @@ regions = [
|
|||
LocationName.Somebody_please_help,
|
||||
LocationName.Looking_for_condor,
|
||||
LocationName.Help_with_rehab,
|
||||
LocationName.Help_with_rehab_bonus,
|
||||
LocationName.Old_Master,
|
||||
LocationName.Catching_gang_members,
|
||||
LocationName.Please_adopt_a_virus,
|
||||
|
@ -349,6 +350,7 @@ regions = [
|
|||
LocationName.Secret_2_Upper_BMD,
|
||||
LocationName.Secret_3_Island_BMD,
|
||||
LocationName.Secret_3_South_BMD,
|
||||
LocationName.Secret_3_BugFrag_BMD
|
||||
LocationName.Secret_3_BugFrag_BMD,
|
||||
LocationName.Serenade
|
||||
])
|
||||
]
|
||||
|
|
|
@ -9,14 +9,14 @@ from BaseClasses import Item, MultiWorld, Tutorial, ItemClassification, Region,
|
|||
from worlds.AutoWorld import WebWorld, World
|
||||
|
||||
from .Rom import MMBN3DeltaPatch, LocalRom, get_base_rom_path
|
||||
from .Items import MMBN3Item, ItemData, item_table, all_items, item_frequencies, items_by_id, ItemType
|
||||
from .Items import MMBN3Item, ItemData, item_table, all_items, item_frequencies, items_by_id, ItemType, item_groups
|
||||
from .Locations import Location, MMBN3Location, all_locations, location_table, location_data_table, \
|
||||
always_excluded_locations, jobs
|
||||
secret_locations, jobs, location_groups
|
||||
from .Options import MMBN3Options
|
||||
from .Regions import regions, RegionName
|
||||
from .Names.ItemName import ItemName
|
||||
from .Names.LocationName import LocationName
|
||||
from worlds.generic.Rules import add_item_rule
|
||||
from worlds.generic.Rules import add_item_rule, add_rule
|
||||
|
||||
|
||||
class MMBN3Settings(settings.Group):
|
||||
|
@ -57,12 +57,16 @@ class MMBN3World(World):
|
|||
settings: typing.ClassVar[MMBN3Settings]
|
||||
topology_present = False
|
||||
|
||||
|
||||
item_name_to_id = {name: data.code for name, data in item_table.items()}
|
||||
location_name_to_id = {loc_data.name: loc_data.id for loc_data in all_locations}
|
||||
|
||||
excluded_locations: typing.List[str]
|
||||
excluded_locations: typing.Set[str]
|
||||
item_frequencies: typing.Dict[str, int]
|
||||
|
||||
location_name_groups = location_groups
|
||||
item_name_groups = item_groups
|
||||
|
||||
web = MMBN3Web()
|
||||
|
||||
def generate_early(self) -> None:
|
||||
|
@ -74,10 +78,11 @@ class MMBN3World(World):
|
|||
if self.options.extra_ranks > 0:
|
||||
self.item_frequencies[ItemName.Progressive_Undernet_Rank] = 8 + self.options.extra_ranks
|
||||
|
||||
self.excluded_locations = set()
|
||||
if not self.options.include_secret:
|
||||
self.excluded_locations |= secret_locations
|
||||
if not self.options.include_jobs:
|
||||
self.excluded_locations = always_excluded_locations + [job.name for job in jobs]
|
||||
else:
|
||||
self.excluded_locations = always_excluded_locations
|
||||
self.excluded_locations |= {job.name for job in jobs}
|
||||
|
||||
def create_regions(self) -> None:
|
||||
"""
|
||||
|
@ -140,19 +145,19 @@ class MMBN3World(World):
|
|||
if connection == RegionName.SciLab_Cyberworld:
|
||||
entrance.access_rule = lambda state: \
|
||||
state.has(ItemName.CSciPas, self.player) or \
|
||||
state.can_reach(RegionName.SciLab_Overworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.SciLab_Overworld, self.player)
|
||||
self.multiworld.register_indirect_condition(self.get_region(RegionName.SciLab_Overworld), entrance)
|
||||
if connection == RegionName.Yoka_Cyberworld:
|
||||
entrance.access_rule = lambda state: \
|
||||
state.has(ItemName.CYokaPas, self.player) or \
|
||||
(
|
||||
state.can_reach(RegionName.SciLab_Overworld, "Region", self.player) and
|
||||
state.can_reach_region(RegionName.SciLab_Overworld, self.player) and
|
||||
state.has(ItemName.Press, self.player)
|
||||
)
|
||||
self.multiworld.register_indirect_condition(self.get_region(RegionName.SciLab_Overworld), entrance)
|
||||
if connection == RegionName.Beach_Cyberworld:
|
||||
entrance.access_rule = lambda state: state.has(ItemName.CBeacPas, self.player) and\
|
||||
state.can_reach(RegionName.Yoka_Overworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Yoka_Overworld, self.player)
|
||||
self.multiworld.register_indirect_condition(self.get_region(RegionName.Yoka_Overworld), entrance)
|
||||
if connection == RegionName.Undernet:
|
||||
entrance.access_rule = lambda state: self.explore_score(state) > 8 and\
|
||||
|
@ -198,122 +203,138 @@ class MMBN3World(World):
|
|||
|
||||
# Set WWW ID requirements
|
||||
def has_www_id(state): return state.has(ItemName.WWW_ID, self.player)
|
||||
self.multiworld.get_location(LocationName.ACDC_1_PMD, self.player).access_rule = has_www_id
|
||||
self.multiworld.get_location(LocationName.SciLab_1_WWW_BMD, self.player).access_rule = has_www_id
|
||||
self.multiworld.get_location(LocationName.Yoka_1_WWW_BMD, self.player).access_rule = has_www_id
|
||||
self.multiworld.get_location(LocationName.Undernet_1_WWW_BMD, self.player).access_rule = has_www_id
|
||||
add_rule(self.multiworld.get_location(LocationName.ACDC_1_PMD, self.player), has_www_id)
|
||||
add_rule(self.multiworld.get_location(LocationName.SciLab_1_WWW_BMD, self.player), has_www_id)
|
||||
add_rule(self.multiworld.get_location(LocationName.Yoka_1_WWW_BMD, self.player), has_www_id)
|
||||
add_rule(self.multiworld.get_location(LocationName.Undernet_1_WWW_BMD, self.player), has_www_id)
|
||||
|
||||
# Set Press Program requirements
|
||||
def has_press(state): return state.has(ItemName.Press, self.player)
|
||||
self.multiworld.get_location(LocationName.Yoka_1_PMD, self.player).access_rule = has_press
|
||||
self.multiworld.get_location(LocationName.Yoka_2_Upper_BMD, self.player).access_rule = has_press
|
||||
self.multiworld.get_location(LocationName.Beach_2_East_BMD, self.player).access_rule = has_press
|
||||
self.multiworld.get_location(LocationName.Hades_South_BMD, self.player).access_rule = has_press
|
||||
self.multiworld.get_location(LocationName.Secret_3_BugFrag_BMD, self.player).access_rule = has_press
|
||||
self.multiworld.get_location(LocationName.Secret_3_Island_BMD, self.player).access_rule = has_press
|
||||
add_rule(self.multiworld.get_location(LocationName.Yoka_1_PMD, self.player), has_press)
|
||||
add_rule(self.multiworld.get_location(LocationName.Yoka_2_Upper_BMD, self.player), has_press)
|
||||
add_rule(self.multiworld.get_location(LocationName.Beach_2_East_BMD, self.player), has_press)
|
||||
add_rule(self.multiworld.get_location(LocationName.Hades_South_BMD, self.player), has_press)
|
||||
add_rule(self.multiworld.get_location(LocationName.Secret_3_BugFrag_BMD, self.player), has_press)
|
||||
add_rule(self.multiworld.get_location(LocationName.Secret_3_Island_BMD, self.player), has_press)
|
||||
|
||||
# Set Purple Mystery Data Unlocker access
|
||||
def can_unlock(state): return state.can_reach_region(RegionName.SciLab_Overworld, self.player) or \
|
||||
state.can_reach_region(RegionName.SciLab_Cyberworld, self.player) or \
|
||||
state.can_reach_region(RegionName.Yoka_Cyberworld, self.player) or \
|
||||
state.has(ItemName.Unlocker, self.player, 8) # There are 8 PMDs that aren't in one of the above areas
|
||||
add_rule(self.multiworld.get_location(LocationName.ACDC_1_PMD, self.player), can_unlock)
|
||||
add_rule(self.multiworld.get_location(LocationName.Yoka_1_PMD, self.player), can_unlock)
|
||||
add_rule(self.multiworld.get_location(LocationName.Beach_1_PMD, self.player), can_unlock)
|
||||
add_rule(self.multiworld.get_location(LocationName.Undernet_7_PMD, self.player), can_unlock)
|
||||
add_rule(self.multiworld.get_location(LocationName.Mayls_HP_PMD, self.player), can_unlock)
|
||||
add_rule(self.multiworld.get_location(LocationName.SciLab_Dads_Computer_PMD, self.player), can_unlock)
|
||||
add_rule(self.multiworld.get_location(LocationName.Zoo_Panda_PMD, self.player), can_unlock)
|
||||
add_rule(self.multiworld.get_location(LocationName.Beach_DNN_Security_Panel_PMD, self.player), can_unlock)
|
||||
add_rule(self.multiworld.get_location(LocationName.Beach_DNN_Main_Console_PMD, self.player), can_unlock)
|
||||
add_rule(self.multiworld.get_location(LocationName.Tamakos_HP_PMD, self.player), can_unlock)
|
||||
|
||||
# Set Job additional area access
|
||||
self.multiworld.get_location(LocationName.Please_deliver_this, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.ACDC_Overworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.ACDC_Cyberworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.ACDC_Overworld, self.player) and \
|
||||
state.can_reach_region(RegionName.ACDC_Cyberworld, self.player)
|
||||
self.multiworld.get_location(LocationName.My_Navi_is_sick, self.player).access_rule =\
|
||||
lambda state: \
|
||||
state.has(ItemName.Recov30_star, self.player)
|
||||
self.multiworld.get_location(LocationName.Help_me_with_my_son, self.player).access_rule =\
|
||||
lambda state:\
|
||||
state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.ACDC_Cyberworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Yoka_Overworld, self.player) and \
|
||||
state.can_reach_region(RegionName.ACDC_Cyberworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Transmission_error, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Yoka_Overworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Yoka_Overworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Chip_Prices, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.ACDC_Cyberworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.SciLab_Cyberworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.ACDC_Cyberworld, self.player) and \
|
||||
state.can_reach_region(RegionName.SciLab_Cyberworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Im_broke, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.Yoka_Cyberworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Yoka_Overworld, self.player) and \
|
||||
state.can_reach_region(RegionName.Yoka_Cyberworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Rare_chips_for_cheap, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.ACDC_Overworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.ACDC_Overworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Be_my_boyfriend, self.player).access_rule =\
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Beach_Cyberworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Beach_Cyberworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Will_you_deliver, self.player).access_rule=\
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.Beach_Overworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.ACDC_Cyberworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Yoka_Overworld, self.player) and \
|
||||
state.can_reach_region(RegionName.Beach_Overworld, self.player) and \
|
||||
state.can_reach_region(RegionName.ACDC_Cyberworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Somebody_please_help, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.ACDC_Overworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.ACDC_Overworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Looking_for_condor, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.Beach_Overworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.ACDC_Overworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Yoka_Overworld, self.player) and \
|
||||
state.can_reach_region(RegionName.Beach_Overworld, self.player) and \
|
||||
state.can_reach_region(RegionName.ACDC_Overworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Help_with_rehab, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Beach_Overworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Beach_Overworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Old_Master, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.ACDC_Overworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.Beach_Overworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.ACDC_Overworld, self.player) and \
|
||||
state.can_reach_region(RegionName.Beach_Overworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Catching_gang_members, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Yoka_Cyberworld, "Region", self.player) and \
|
||||
state.can_reach_region(RegionName.Yoka_Cyberworld, self.player) and \
|
||||
state.has(ItemName.Press, self.player)
|
||||
self.multiworld.get_location(LocationName.Please_adopt_a_virus, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.SciLab_Cyberworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.SciLab_Cyberworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Legendary_Tomes, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Beach_Overworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.Undernet, "Region", self.player) and \
|
||||
state.can_reach(RegionName.Deep_Undernet, "Region", self.player) and \
|
||||
state.can_reach_region(RegionName.Beach_Overworld, self.player) and \
|
||||
state.can_reach_region(RegionName.Undernet, self.player) and \
|
||||
state.can_reach_region(RegionName.Deep_Undernet, self.player) and \
|
||||
state.has_all({ItemName.Press, ItemName.Magnum1_A}, self.player)
|
||||
self.multiworld.get_location(LocationName.Legendary_Tomes_Treasure, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.ACDC_Overworld, "Region", self.player) and \
|
||||
state.can_reach(LocationName.Legendary_Tomes, "Location", self.player)
|
||||
state.can_reach_region(RegionName.ACDC_Overworld, self.player) and \
|
||||
state.can_reach_location(LocationName.Legendary_Tomes, self.player)
|
||||
self.multiworld.get_location(LocationName.Hide_and_seek_First_Child, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Yoka_Overworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Yoka_Overworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Hide_and_seek_Second_Child, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Yoka_Overworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Yoka_Overworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Hide_and_seek_Third_Child, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Yoka_Overworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Yoka_Overworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Hide_and_seek_Fourth_Child, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Yoka_Overworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Yoka_Overworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Hide_and_seek_Completion, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Yoka_Overworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Yoka_Overworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Finding_the_blue_Navi, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Undernet, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Undernet, self.player)
|
||||
self.multiworld.get_location(LocationName.Give_your_support, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Beach_Overworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Beach_Overworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Stamp_collecting, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.Beach_Overworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.ACDC_Cyberworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.SciLab_Cyberworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.Yoka_Cyberworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.Beach_Cyberworld, "Region", self.player)
|
||||
state.can_reach_region(RegionName.Beach_Overworld, self.player) and \
|
||||
state.can_reach_region(RegionName.ACDC_Cyberworld, self.player) and \
|
||||
state.can_reach_region(RegionName.SciLab_Cyberworld, self.player) and \
|
||||
state.can_reach_region(RegionName.Yoka_Cyberworld, self.player) and \
|
||||
state.can_reach_region(RegionName.Beach_Cyberworld, self.player)
|
||||
self.multiworld.get_location(LocationName.Help_with_a_will, self.player).access_rule = \
|
||||
lambda state: \
|
||||
state.can_reach(RegionName.ACDC_Overworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.ACDC_Cyberworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.Yoka_Overworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.Yoka_Cyberworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.Beach_Overworld, "Region", self.player) and \
|
||||
state.can_reach(RegionName.Undernet, "Region", self.player)
|
||||
state.can_reach_region(RegionName.ACDC_Overworld, self.player) and \
|
||||
state.can_reach_region(RegionName.ACDC_Cyberworld, self.player) and \
|
||||
state.can_reach_region(RegionName.Yoka_Overworld, self.player) and \
|
||||
state.can_reach_region(RegionName.Yoka_Cyberworld, self.player) and \
|
||||
state.can_reach_region(RegionName.Beach_Overworld, self.player) and \
|
||||
state.can_reach_region(RegionName.Undernet, self.player)
|
||||
|
||||
# Set Trade quests
|
||||
self.multiworld.get_location(LocationName.ACDC_SonicWav_W_Trade, self.player).access_rule =\
|
||||
|
@ -390,6 +411,11 @@ class MMBN3World(World):
|
|||
self.multiworld.get_location(LocationName.Numberman_Code_31, self.player).access_rule =\
|
||||
lambda state: self.explore_score(state) > 10
|
||||
|
||||
#miscellaneous locations with extra requirements
|
||||
add_rule(self.multiworld.get_location(LocationName.Comedian, self.player),
|
||||
lambda state: state.has(ItemName.Humor, self.player))
|
||||
add_rule(self.multiworld.get_location(LocationName.Villain, self.player),
|
||||
lambda state: state.has(ItemName.BlckMnd, self.player))
|
||||
def not_undernet(item): return item.code != item_table[ItemName.Progressive_Undernet_Rank].code or item.player != self.player
|
||||
self.multiworld.get_location(LocationName.WWW_1_Central_BMD, self.player).item_rule = not_undernet
|
||||
self.multiworld.get_location(LocationName.WWW_1_East_BMD, self.player).item_rule = not_undernet
|
||||
|
@ -500,24 +526,24 @@ class MMBN3World(World):
|
|||
Determine roughly how much of the game you can explore to make certain checks not restrict much movement
|
||||
"""
|
||||
score = 0
|
||||
if state.can_reach(RegionName.WWW_Island, "Region", self.player):
|
||||
if state.can_reach_region(RegionName.WWW_Island, self.player):
|
||||
return 999
|
||||
if state.can_reach(RegionName.SciLab_Overworld, "Region", self.player):
|
||||
if state.can_reach_region(RegionName.SciLab_Overworld, self.player):
|
||||
score += 3
|
||||
if state.can_reach(RegionName.SciLab_Cyberworld, "Region", self.player):
|
||||
if state.can_reach_region(RegionName.SciLab_Cyberworld, self.player):
|
||||
score += 1
|
||||
if state.can_reach(RegionName.Yoka_Overworld, "Region", self.player):
|
||||
if state.can_reach_region(RegionName.Yoka_Overworld, self.player):
|
||||
score += 2
|
||||
if state.can_reach(RegionName.Yoka_Cyberworld, "Region", self.player):
|
||||
if state.can_reach_region(RegionName.Yoka_Cyberworld, self.player):
|
||||
score += 1
|
||||
if state.can_reach(RegionName.Beach_Overworld, "Region", self.player):
|
||||
if state.can_reach_region(RegionName.Beach_Overworld, self.player):
|
||||
score += 3
|
||||
if state.can_reach(RegionName.Beach_Cyberworld, "Region", self.player):
|
||||
if state.can_reach_region(RegionName.Beach_Cyberworld, self.player):
|
||||
score += 1
|
||||
if state.can_reach(RegionName.Undernet, "Region", self.player):
|
||||
if state.can_reach_region(RegionName.Undernet, self.player):
|
||||
score += 2
|
||||
if state.can_reach(RegionName.Deep_Undernet, "Region", self.player):
|
||||
if state.can_reach_region(RegionName.Deep_Undernet, self.player):
|
||||
score += 1
|
||||
if state.can_reach(RegionName.Secret_Area, "Region", self.player):
|
||||
if state.can_reach_region(RegionName.Secret_Area, self.player):
|
||||
score += 1
|
||||
return score
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue