From 057f385f4a4f7feba570dc1b4c41621d610c1bdf Mon Sep 17 00:00:00 2001 From: TrippSC2 Date: Sat, 4 Apr 2020 20:41:36 -0400 Subject: [PATCH] Reworked event structure to optimize performance. Incremented version from 0.7.0 to 0.7.1 for release. --- OpenTracker.Models/Boss.cs | 204 +- OpenTracker.Models/BossDictionary.cs | 5 +- OpenTracker.Models/BossSection.cs | 625 +++- OpenTracker.Models/EntranceSection.cs | 1424 +++---- OpenTracker.Models/Game.cs | 8 +- OpenTracker.Models/ItemSection.cs | 3288 +++++++++++------ OpenTracker.Models/Location.cs | 2 - OpenTracker.Models/MapLocation.cs | 1 - OpenTracker.Models/Mode.cs | 3 + OpenTracker.Models/OpenTracker.Models.csproj | 1 + OpenTracker.Models/Region.cs | 1024 ++--- OpenTracker.Setup/OpenTracker.Setup.vdproj | 8 +- OpenTracker/OpenTracker.csproj | 6 +- OpenTracker/ViewModels/MainWindowVM.cs | 2 +- .../ViewModels/MapLocationControlVM.cs | 4 +- 15 files changed, 4070 insertions(+), 2535 deletions(-) diff --git a/OpenTracker.Models/Boss.cs b/OpenTracker.Models/Boss.cs index afa219a6..2537e8ec 100644 --- a/OpenTracker.Models/Boss.cs +++ b/OpenTracker.Models/Boss.cs @@ -8,6 +8,9 @@ namespace OpenTracker.Models public class Boss : INotifyPropertyChanged { private readonly Game _game; + private readonly bool _updateOnItemPlacementChange; + private readonly Dictionary _itemSubscriptions; + private readonly Dictionary _itemIsSubscribed; public BossType Type { get; } public Func GetAccessibility { get; } @@ -31,11 +34,11 @@ private set public Boss(Game game, BossType type) { _game = game; - Type = type; - _game.Mode.PropertyChanged += OnGameModeChanged; + _itemSubscriptions = new Dictionary(); + _itemIsSubscribed = new Dictionary(); - List itemRequirements = new List(); + Type = type; switch (Type) { @@ -54,17 +57,17 @@ public Boss(Game game, BossType type) return AccessibilityLevel.None; }; - itemRequirements.Add(_game.Items[ItemType.Sword]); - itemRequirements.Add(_game.Items[ItemType.Hammer]); - itemRequirements.Add(_game.Items[ItemType.Bow]); - itemRequirements.Add(_game.Items[ItemType.Boomerang]); - itemRequirements.Add(_game.Items[ItemType.RedBoomerang]); - itemRequirements.Add(_game.Items[ItemType.Bottle]); - itemRequirements.Add(_game.Items[ItemType.HalfMagic]); - itemRequirements.Add(_game.Items[ItemType.FireRod]); - itemRequirements.Add(_game.Items[ItemType.IceRod]); - itemRequirements.Add(_game.Items[ItemType.CaneOfByrna]); - itemRequirements.Add(_game.Items[ItemType.CaneOfSomaria]); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Bow, new Mode()); + _itemSubscriptions.Add(ItemType.Boomerang, new Mode()); + _itemSubscriptions.Add(ItemType.RedBoomerang, new Mode()); + _itemSubscriptions.Add(ItemType.Bottle, new Mode()); + _itemSubscriptions.Add(ItemType.HalfMagic, new Mode()); + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.IceRod, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfByrna, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfSomaria, new Mode()); break; case BossType.Lanmolas: @@ -80,13 +83,13 @@ public Boss(Game game, BossType type) return AccessibilityLevel.SequenceBreak; }; - itemRequirements.Add(_game.Items[ItemType.Sword]); - itemRequirements.Add(_game.Items[ItemType.Hammer]); - itemRequirements.Add(_game.Items[ItemType.Bow]); - itemRequirements.Add(_game.Items[ItemType.FireRod]); - itemRequirements.Add(_game.Items[ItemType.IceRod]); - itemRequirements.Add(_game.Items[ItemType.CaneOfByrna]); - itemRequirements.Add(_game.Items[ItemType.CaneOfSomaria]); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Bow, new Mode()); + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.IceRod, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfByrna, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfSomaria, new Mode()); break; case BossType.Moldorm: @@ -99,8 +102,8 @@ public Boss(Game game, BossType type) return AccessibilityLevel.None; }; - itemRequirements.Add(_game.Items[ItemType.Sword]); - itemRequirements.Add(_game.Items[ItemType.Hammer]); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); break; case BossType.HelmasaurKing: @@ -118,7 +121,6 @@ public Boss(Game game, BossType type) (_game.Items.Has(ItemType.FireRod) || _game.Items.Has(ItemType.IceRod))))) { if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Mode.WorldState == WorldState.Inverted || _game.Items.Swordless() || _game.Items.Has(ItemType.Sword, 2)) return AccessibilityLevel.Normal; @@ -128,14 +130,16 @@ public Boss(Game game, BossType type) return AccessibilityLevel.None; }; - itemRequirements.Add(_game.Items[ItemType.Hookshot]); - itemRequirements.Add(_game.Items[ItemType.Hammer]); - itemRequirements.Add(_game.Items[ItemType.Sword]); - itemRequirements.Add(_game.Items[ItemType.Bottle]); - itemRequirements.Add(_game.Items[ItemType.HalfMagic]); - itemRequirements.Add(_game.Items[ItemType.Bow]); - itemRequirements.Add(_game.Items[ItemType.FireRod]); - itemRequirements.Add(_game.Items[ItemType.IceRod]); + _updateOnItemPlacementChange = true; + + _itemSubscriptions.Add(ItemType.Hookshot, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Bottle, new Mode()); + _itemSubscriptions.Add(ItemType.HalfMagic, new Mode()); + _itemSubscriptions.Add(ItemType.Bow, new Mode()); + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.IceRod, new Mode()); break; case BossType.Mothula: @@ -147,7 +151,6 @@ public Boss(Game game, BossType type) _game.Items.Has(ItemType.CaneOfSomaria) || _game.Items.Has(ItemType.CaneOfByrna)))) { if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Mode.WorldState == WorldState.Inverted || _game.Items.Has(ItemType.Sword, 2) || (_game.Items.CanExtendMagic(2) && _game.Items.Has(ItemType.FireRod))) return AccessibilityLevel.Normal; @@ -158,13 +161,15 @@ public Boss(Game game, BossType type) return AccessibilityLevel.None; }; - itemRequirements.Add(_game.Items[ItemType.Sword]); - itemRequirements.Add(_game.Items[ItemType.Hammer]); - itemRequirements.Add(_game.Items[ItemType.Bottle]); - itemRequirements.Add(_game.Items[ItemType.HalfMagic]); - itemRequirements.Add(_game.Items[ItemType.FireRod]); - itemRequirements.Add(_game.Items[ItemType.CaneOfSomaria]); - itemRequirements.Add(_game.Items[ItemType.CaneOfByrna]); + _updateOnItemPlacementChange = true; + + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Bottle, new Mode()); + _itemSubscriptions.Add(ItemType.HalfMagic, new Mode()); + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfSomaria, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfByrna, new Mode()); break; case BossType.Blind: @@ -175,7 +180,6 @@ public Boss(Game game, BossType type) _game.Items.Has(ItemType.CaneOfSomaria) || _game.Items.Has(ItemType.CaneOfByrna)) { if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Mode.WorldState == WorldState.Inverted || _game.Items.Swordless() || (_game.Items.Has(ItemType.Sword) && (_game.Items.Has(ItemType.Cape) || _game.Items.Has(ItemType.CaneOfByrna)))) return AccessibilityLevel.Normal; @@ -186,11 +190,13 @@ public Boss(Game game, BossType type) return AccessibilityLevel.None; }; - itemRequirements.Add(_game.Items[ItemType.Sword]); - itemRequirements.Add(_game.Items[ItemType.Cape]); - itemRequirements.Add(_game.Items[ItemType.Hammer]); - itemRequirements.Add(_game.Items[ItemType.CaneOfSomaria]); - itemRequirements.Add(_game.Items[ItemType.CaneOfByrna]); + _updateOnItemPlacementChange = true; + + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfSomaria, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfByrna, new Mode()); + _itemSubscriptions.Add(ItemType.Cape, new Mode() { ItemPlacement = ItemPlacement.Advanced }); break; case BossType.Kholdstare: @@ -204,7 +210,6 @@ public Boss(Game game, BossType type) && _game.Items.Has(ItemType.Bombos) && _game.Items.Swordless()))) { if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Mode.WorldState == WorldState.Inverted || _game.Items.Has(ItemType.Sword, 2) || (_game.Items.CanExtendMagic(3) && _game.Items.Has(ItemType.FireRod)) || (_game.Items.Has(ItemType.Bombos) && @@ -218,12 +223,14 @@ public Boss(Game game, BossType type) return AccessibilityLevel.None; }; - itemRequirements.Add(_game.Items[ItemType.FireRod]); - itemRequirements.Add(_game.Items[ItemType.Bombos]); - itemRequirements.Add(_game.Items[ItemType.Sword]); - itemRequirements.Add(_game.Items[ItemType.Hammer]); - itemRequirements.Add(_game.Items[ItemType.Bottle]); - itemRequirements.Add(_game.Items[ItemType.HalfMagic]); + _updateOnItemPlacementChange = true; + + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.Bombos, new Mode()); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Bottle, new Mode()); + _itemSubscriptions.Add(ItemType.HalfMagic, new Mode()); break; case BossType.Vitreous: @@ -234,7 +241,6 @@ public Boss(Game game, BossType type) _game.Items.Has(ItemType.Bow)) { if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Mode.WorldState == WorldState.Inverted || _game.Items.Has(ItemType.Sword, 2) || _game.Items.Has(ItemType.Bow)) return AccessibilityLevel.Normal; @@ -244,9 +250,11 @@ public Boss(Game game, BossType type) return AccessibilityLevel.None; }; - itemRequirements.Add(_game.Items[ItemType.Hammer]); - itemRequirements.Add(_game.Items[ItemType.Sword]); - itemRequirements.Add(_game.Items[ItemType.Bow]); + _updateOnItemPlacementChange = true; + + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Bow, new Mode()); break; case BossType.Trinexx: @@ -259,7 +267,6 @@ public Boss(Game game, BossType type) (_game.Items.CanExtendMagic(4) && _game.Items.Has(ItemType.Sword)))) { if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Mode.WorldState == WorldState.Inverted || _game.Items.Swordless() || _game.Items.Has(ItemType.Sword, 3) || (_game.Items.CanExtendMagic(2) && _game.Items.Has(ItemType.Sword, 2))) return AccessibilityLevel.Normal; @@ -270,12 +277,14 @@ public Boss(Game game, BossType type) return AccessibilityLevel.None; }; - itemRequirements.Add(_game.Items[ItemType.FireRod]); - itemRequirements.Add(_game.Items[ItemType.IceRod]); - itemRequirements.Add(_game.Items[ItemType.Sword]); - itemRequirements.Add(_game.Items[ItemType.Hammer]); - itemRequirements.Add(_game.Items[ItemType.Bottle]); - itemRequirements.Add(_game.Items[ItemType.HalfMagic]); + _updateOnItemPlacementChange = true; + + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.IceRod, new Mode()); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Bottle, new Mode()); + _itemSubscriptions.Add(ItemType.HalfMagic, new Mode()); break; case BossType.Aga: @@ -289,42 +298,79 @@ public Boss(Game game, BossType type) return AccessibilityLevel.None; }; - itemRequirements.Add(_game.Items[ItemType.Sword]); - itemRequirements.Add(_game.Items[ItemType.Hammer]); - itemRequirements.Add(_game.Items[ItemType.Net]); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Net, new Mode()); break; } - foreach (Item item in itemRequirements) - item.PropertyChanged += OnItemRequirementChanged; + _game.Mode.PropertyChanged += OnGameModeChanged; + UpdateItemSubscriptions(); UpdateAccessibility(); } - private void UpdateAccessibility() + private void OnPropertyChanged(string propertyName) { - Accessibility = GetAccessibility(); + if (PropertyChanged != null) + PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private void OnGameModeChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == "WorldState") - UpdateAccessibility(); - - if (e.PropertyName == "ItemPlacement") + if (e.PropertyName == "ItemPlacement" && _updateOnItemPlacementChange) + { + UpdateItemSubscriptions(); UpdateAccessibility(); + } } - private void OnItemRequirementChanged(object sender, PropertyChangedEventArgs e) + private void OnRequirementChanged(object sender, PropertyChangedEventArgs e) { UpdateAccessibility(); } - private void OnPropertyChanged(string propertyName) + private void UpdateItemSubscriptions() { - if (PropertyChanged != null) - PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); + foreach (ItemType item in _itemSubscriptions.Keys) + { + if (_game.Mode.Validate(_itemSubscriptions[item])) + { + if (_itemIsSubscribed.ContainsKey(item)) + { + if (!_itemIsSubscribed[item]) + { + _itemIsSubscribed[item] = true; + _game.Items[item].PropertyChanged += OnRequirementChanged; + } + } + else + { + _itemIsSubscribed.Add(item, true); + _game.Items[item].PropertyChanged += OnRequirementChanged; + } + } + else + { + if (_itemIsSubscribed.ContainsKey(item)) + { + if (_itemIsSubscribed[item]) + { + _itemIsSubscribed[item] = false; + _game.Items[item].PropertyChanged -= OnRequirementChanged; + } + } + else + _itemIsSubscribed.Add(item, false); + } + } + } + + private void UpdateAccessibility() + { + Accessibility = GetAccessibility(); } + } } diff --git a/OpenTracker.Models/BossDictionary.cs b/OpenTracker.Models/BossDictionary.cs index 0feea07b..72fdb5d1 100644 --- a/OpenTracker.Models/BossDictionary.cs +++ b/OpenTracker.Models/BossDictionary.cs @@ -6,8 +6,6 @@ namespace OpenTracker.Models { public class BossDictionary : Dictionary, INotifyPropertyChanged { - private readonly Game _game; - public event PropertyChangedEventHandler PropertyChanged; private AccessibilityLevel _unknownBossAccessibility; @@ -24,9 +22,8 @@ private set } } - public BossDictionary(Game game, int capacity) : base(capacity) + public BossDictionary(int capacity) : base(capacity) { - _game = game; } private void OnPropertyChanged(string propertyName) diff --git a/OpenTracker.Models/BossSection.cs b/OpenTracker.Models/BossSection.cs index 85eba669..d0f3ba40 100644 --- a/OpenTracker.Models/BossSection.cs +++ b/OpenTracker.Models/BossSection.cs @@ -10,7 +10,14 @@ public class BossSection : ISection, INotifyPropertyChanging { private readonly Game _game; private readonly Boss _defaultBoss; - private readonly Region _region; + private readonly bool _updateOnItemPlacementChange; + private readonly bool _updateOnWorldStateChange; + private readonly bool _updateOnEnemyShuffleChange; + private readonly Dictionary _regionSubscriptions; + private readonly Dictionary _regionIsSubscribed; + private readonly Dictionary _itemSubscriptions; + private readonly Dictionary _itemIsSubscribed; + private Boss _currentBossSubscription; public string Name { get => "Boss"; } public bool HasMarking { get => false; } @@ -83,9 +90,14 @@ public Item Prize public BossSection(Game game, LocationID iD) { _game = game; - RequiredMode = new Mode(); - List itemReqs = new List(); + _regionSubscriptions = new Dictionary(); + _regionIsSubscribed = new Dictionary(); + _itemSubscriptions = new Dictionary(); + _itemIsSubscribed = new Dictionary(); + + RequiredMode = new Mode(); + Available = true; switch (iD) { @@ -94,248 +106,346 @@ public BossSection(Game game, LocationID iD) _defaultBoss = _game.Bosses[BossType.Aga]; _boss = _game.Bosses[BossType.Aga]; Prize = _game.Items[ItemType.Aga]; - _region = _game.Regions[RegionID.Agahnim]; GetAccessibility = () => { - if (_game.Items.Has(ItemType.ATSmallKey, 2) && _game.Items.CanRemoveCurtains()) + if (_game.Regions[RegionID.Agahnim].Accessibility >= AccessibilityLevel.SequenceBreak) { - if (_game.Items.Has(ItemType.Lamp)) - return AccessibilityLevel.Normal; - - return AccessibilityLevel.SequenceBreak; + if (_game.Items.Has(ItemType.ATSmallKey, 2) && _game.Items.CanRemoveCurtains()) + { + if (_game.Items.Has(ItemType.Lamp)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Normal, + (byte)_game.Regions[RegionID.Agahnim].Accessibility); + } + + return AccessibilityLevel.SequenceBreak; + } } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.ATSmallKey]); - itemReqs.Add(_game.Items[ItemType.Sword]); - itemReqs.Add(_game.Items[ItemType.Lamp]); + _regionSubscriptions.Add(RegionID.Agahnim, new Mode()); + + _itemSubscriptions.Add(ItemType.ATSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); break; case LocationID.EasternPalace: _defaultBoss = _game.Bosses[BossType.Armos]; - _region = _game.Regions[RegionID.EasternPalace]; GetAccessibility = () => { - if (_game.Items.Has(ItemType.EPBigKey) && - (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value)) + if (_game.Regions[RegionID.EasternPalace].Accessibility >= AccessibilityLevel.SequenceBreak) { - if (_game.Items.Has(ItemType.Lamp) || (_game.Items.Has(ItemType.FireRod) && - (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Mode.WorldState == WorldState.Inverted))) - return AccessibilityLevel.Normal; - - return AccessibilityLevel.SequenceBreak; + if ((_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) && + _game.Items.Has(ItemType.EPBigKey)) + { + if (_game.Items.Has(ItemType.Lamp) || (_game.Items.Has(ItemType.FireRod) && + _game.Mode.ItemPlacement == ItemPlacement.Advanced)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Normal, + (byte)_game.Regions[RegionID.EasternPalace].Accessibility); + } + + return AccessibilityLevel.SequenceBreak; + } } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.EPBigKey]); - itemReqs.Add(_game.Items[ItemType.Bow]); - itemReqs.Add(_game.Items[ItemType.Lamp]); - itemReqs.Add(_game.Items[ItemType.FireRod]); + _updateOnItemPlacementChange = true; + _updateOnEnemyShuffleChange = true; + + _regionSubscriptions.Add(RegionID.EasternPalace, new Mode()); + + _itemSubscriptions.Add(ItemType.Bow, new Mode() { EnemyShuffle = false }); + _itemSubscriptions.Add(ItemType.EPBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); + _itemSubscriptions.Add(ItemType.FireRod, new Mode() { ItemPlacement = ItemPlacement.Advanced }); break; case LocationID.DesertPalace: _defaultBoss = _game.Bosses[BossType.Lanmolas]; - _region = _game.Regions[RegionID.DesertPalace]; GetAccessibility = () => { - if (_game.Items.Has(ItemType.Gloves) && (_game.Items.Has(ItemType.FireRod) || - _game.Items.Has(ItemType.Lamp)) && _game.Items.Has(ItemType.DPBigKey)) - return AccessibilityLevel.Normal; + if (_game.Regions[RegionID.DesertPalace].Accessibility >= AccessibilityLevel.SequenceBreak) + { + if (_game.Items.Has(ItemType.Gloves) && (_game.Items.Has(ItemType.FireRod) || + _game.Items.Has(ItemType.Lamp)) && _game.Items.Has(ItemType.DPBigKey)) + { + if (_game.Items.Has(ItemType.DPSmallKey)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Normal, + (byte)_game.Regions[RegionID.DesertPalace].Accessibility); + } + + return AccessibilityLevel.SequenceBreak; + } + } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.FireRod]); - itemReqs.Add(_game.Items[ItemType.Lamp]); - itemReqs.Add(_game.Items[ItemType.DPBigKey]); + _regionSubscriptions.Add(RegionID.DesertPalace, new Mode()); + + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); + _itemSubscriptions.Add(ItemType.DPBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); + _itemSubscriptions.Add(ItemType.DPSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); break; case LocationID.TowerOfHera: _defaultBoss = _game.Bosses[BossType.Moldorm]; - _region = _game.Regions[RegionID.TowerOfHera]; GetAccessibility = () => { - if (_game.Items.Has(ItemType.ToHBigKey)) - return AccessibilityLevel.Normal; - - if (_game.Items.Has(ItemType.Hookshot)) - return AccessibilityLevel.SequenceBreak; + if (_game.Regions[RegionID.TowerOfHera].Accessibility >= AccessibilityLevel.SequenceBreak) + { + if (_game.Mode.DungeonItemShuffle == DungeonItemShuffle.Keysanity) + { + if (_game.Items.Has(ItemType.ToHBigKey)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Normal, + (byte)_game.Regions[RegionID.TowerOfHera].Accessibility); + } + + if (_game.Items.Has(ItemType.Hookshot)) + return AccessibilityLevel.SequenceBreak; + } + else + { + if (_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Normal, + (byte)_game.Regions[RegionID.TowerOfHera].Accessibility); + } + + return AccessibilityLevel.SequenceBreak; + } + } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.ToHBigKey]); - itemReqs.Add(_game.Items[ItemType.Hookshot]); + _regionSubscriptions.Add(RegionID.TowerOfHera, new Mode()); + + _itemSubscriptions.Add(ItemType.ToHBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); + _itemSubscriptions.Add(ItemType.Hookshot, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); break; case LocationID.PalaceOfDarkness: _defaultBoss = _game.Bosses[BossType.HelmasaurKing]; - _region = _game.Regions[RegionID.PalaceOfDarkness]; GetAccessibility = () => { - if (_game.Items.Has(ItemType.PoDBigKey) && _game.Items.Has(ItemType.PoDSmallKey) && - _game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.Bow)) + if (_game.Regions[RegionID.PalaceOfDarkness].Accessibility >= AccessibilityLevel.SequenceBreak) { - if (_game.Items.Has(ItemType.Lamp)) - return AccessibilityLevel.Normal; - - return AccessibilityLevel.SequenceBreak; + if (_game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.Bow) && + _game.Items.Has(ItemType.PoDBigKey) && _game.Items.Has(ItemType.PoDSmallKey)) + { + if (_game.Items.Has(ItemType.Lamp)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Normal, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } + + return AccessibilityLevel.SequenceBreak; + } } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.PoDBigKey]); - itemReqs.Add(_game.Items[ItemType.PoDSmallKey]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Bow]); - itemReqs.Add(_game.Items[ItemType.Lamp]); + _regionSubscriptions.Add(RegionID.PalaceOfDarkness, new Mode()); + + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Bow, new Mode()); + _itemSubscriptions.Add(ItemType.PoDBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); + _itemSubscriptions.Add(ItemType.PoDSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); break; case LocationID.SwampPalace: _defaultBoss = _game.Bosses[BossType.Arrghus]; - _region = _game.Regions[RegionID.SwampPalace]; GetAccessibility = () => { - if (_game.Items.Has(ItemType.Flippers) && _game.Items.Has(ItemType.Hookshot) && - _game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.SPSmallKey)) - return AccessibilityLevel.Normal; + if (_game.Regions[RegionID.SwampPalace].Accessibility >= AccessibilityLevel.SequenceBreak) + { + if (_game.Items.Has(ItemType.Flippers) && _game.Items.Has(ItemType.Hookshot) && + _game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.SPSmallKey)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Normal, + (byte)_game.Regions[RegionID.SwampPalace].Accessibility); + } + } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Flippers]); - itemReqs.Add(_game.Items[ItemType.Hookshot]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.SPSmallKey]); + _regionSubscriptions.Add(RegionID.SwampPalace, new Mode()); + + _itemSubscriptions.Add(ItemType.Flippers, new Mode()); + _itemSubscriptions.Add(ItemType.Hookshot, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.SPSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); break; case LocationID.SkullWoods: _defaultBoss = _game.Bosses[BossType.Mothula]; - _region = _game.Regions[RegionID.SkullWoods]; GetAccessibility = () => { - if (_game.Items.Has(ItemType.FireRod) && _game.Items.CanRemoveCurtains()) - return AccessibilityLevel.Normal; + if (_game.Regions[RegionID.SkullWoods].Accessibility >= AccessibilityLevel.SequenceBreak) + { + if ((_game.Items.Has(ItemType.FireRod) || _game.Mode.EntranceShuffle.Value) && + _game.Items.CanRemoveCurtains()) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Normal, + (byte)_game.Regions[RegionID.SkullWoods].Accessibility); + } + } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.FireRod]); - itemReqs.Add(_game.Items[ItemType.Sword]); + _regionSubscriptions.Add(RegionID.SkullWoods, new Mode()); + + _itemSubscriptions.Add(ItemType.FireRod, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); break; case LocationID.ThievesTown: _defaultBoss = _game.Bosses[BossType.Blind]; - _region = _game.Regions[RegionID.ThievesTown]; GetAccessibility = () => { - if (_game.Items.Has(ItemType.TTBigKey)) - return AccessibilityLevel.Normal; + if (_game.Regions[RegionID.ThievesTown].Accessibility >= AccessibilityLevel.SequenceBreak) + { + if (_game.Items.Has(ItemType.TTBigKey)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Normal, + (byte)_game.Regions[RegionID.ThievesTown].Accessibility); + } + } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.TTBigKey]); + _regionSubscriptions.Add(RegionID.ThievesTown, new Mode()); + + _itemSubscriptions.Add(ItemType.TTBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); break; case LocationID.IcePalace: _defaultBoss = _game.Bosses[BossType.Kholdstare]; - _region = _game.Regions[RegionID.IcePalace]; GetAccessibility = () => { - if (_game.Items.CanMeltThings() && _game.Items.Has(ItemType.Hammer) && - (_game.Items.Has(ItemType.CaneOfSomaria) || _game.Items.Has(ItemType.IPSmallKey))) - return AccessibilityLevel.Normal; + if (_game.Regions[RegionID.IcePalace].Accessibility >= AccessibilityLevel.SequenceBreak) + { + if (_game.Items.CanMeltThings() && _game.Items.Has(ItemType.Hammer) && + (_game.Items.Has(ItemType.CaneOfSomaria) || _game.Items.Has(ItemType.IPSmallKey))) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Normal, + (byte)_game.Regions[RegionID.IcePalace].Accessibility); + } + } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.FireRod]); - itemReqs.Add(_game.Items[ItemType.Bombos]); - itemReqs.Add(_game.Items[ItemType.Sword]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.CaneOfSomaria]); - itemReqs.Add(_game.Items[ItemType.IPSmallKey]); + _regionSubscriptions.Add(RegionID.IcePalace, new Mode()); + + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.Bombos, new Mode()); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfSomaria, new Mode()); + _itemSubscriptions.Add(ItemType.IPSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); break; case LocationID.MiseryMire: _defaultBoss = _game.Bosses[BossType.Vitreous]; - _region = _game.Regions[RegionID.MiseryMire]; GetAccessibility = () => { - if ((_game.Items.Has(ItemType.Hookshot) || _game.Items.Has(ItemType.Boots)) && - _game.Items.Has(ItemType.CaneOfSomaria) && _game.Items.Has(ItemType.MMBigKey)) + if (_game.Regions[RegionID.MiseryMire].Accessibility >= AccessibilityLevel.SequenceBreak) { - if ((_game.Items.Has(ItemType.Hookshot) || (_game.Items.Has(ItemType.Boots) && - (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Mode.WorldState == WorldState.Inverted))) && _game.Items.Has(ItemType.Lamp)) - return AccessibilityLevel.Normal; + if ((_game.Items.Has(ItemType.Hookshot) || _game.Items.Has(ItemType.Boots)) && + _game.Items.Has(ItemType.CaneOfSomaria) && _game.Items.Has(ItemType.MMBigKey)) + { + if ((_game.Items.Has(ItemType.Hookshot) || (_game.Items.Has(ItemType.Boots) && + _game.Mode.ItemPlacement == ItemPlacement.Advanced)) && _game.Items.Has(ItemType.Lamp)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Normal, + (byte)_game.Regions[RegionID.MiseryMire].Accessibility); + } - return AccessibilityLevel.SequenceBreak; + return AccessibilityLevel.SequenceBreak; + } } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Hookshot]); - itemReqs.Add(_game.Items[ItemType.Boots]); - itemReqs.Add(_game.Items[ItemType.CaneOfSomaria]); - itemReqs.Add(_game.Items[ItemType.MMBigKey]); - itemReqs.Add(_game.Items[ItemType.Lamp]); + _updateOnItemPlacementChange = true; + + _regionSubscriptions.Add(RegionID.MiseryMire, new Mode()); + + _itemSubscriptions.Add(ItemType.Hookshot, new Mode()); + _itemSubscriptions.Add(ItemType.Boots, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfSomaria, new Mode()); + _itemSubscriptions.Add(ItemType.MMBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); break; case LocationID.TurtleRock: _defaultBoss = _game.Bosses[BossType.Trinexx]; - _region = _game.Regions[RegionID.TurtleRock]; GetAccessibility = () => { if (_game.Mode.EntranceShuffle.Value) { - if (_game.Items.Has(ItemType.TRBigKey) && _game.Items.Has(ItemType.TRSmallKey)) + if (_game.Items.Has(ItemType.CaneOfSomaria) && _game.Items.Has(ItemType.TRBigKey) + && _game.Items.Has(ItemType.TRSmallKey)) return AccessibilityLevel.Normal; } if (_game.Mode.WorldState == WorldState.StandardOpen) { - if (_game.Items.Has(ItemType.CaneOfSomaria) && _game.Items.Has(ItemType.TRBigKey) && - _game.Items.Has(ItemType.TRSmallKey, 3)) + if (_game.Regions[RegionID.TurtleRock].Accessibility >= AccessibilityLevel.SequenceBreak) { - if (_game.Items.Has(ItemType.Lamp)) + if (_game.Items.Has(ItemType.CaneOfSomaria) && _game.Items.Has(ItemType.TRBigKey) && + _game.Items.Has(ItemType.TRSmallKey, 3)) { - if (_game.Mode.DungeonItemShuffle < DungeonItemShuffle.MapsCompassesSmallKeys && - _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Normal; + if (_game.Items.Has(ItemType.Lamp)) + { + if (_game.Mode.DungeonItemShuffle < DungeonItemShuffle.MapsCompassesSmallKeys && + _game.Items.Has(ItemType.FireRod)) + return AccessibilityLevel.Normal; + } + + return AccessibilityLevel.SequenceBreak; } - - return AccessibilityLevel.SequenceBreak; } } @@ -377,22 +487,25 @@ public BossSection(Game game, LocationID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.TRBigKey]); - itemReqs.Add(_game.Items[ItemType.TRSmallKey]); - itemReqs.Add(_game.Items[ItemType.CaneOfSomaria]); - itemReqs.Add(_game.Items[ItemType.Lamp]); - itemReqs.Add(_game.Items[ItemType.FireRod]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.Sword]); - itemReqs.Add(_game.Items[ItemType.Bombos]); - itemReqs.Add(_game.Items[ItemType.BombosDungeons]); - itemReqs.Add(_game.Items[ItemType.Ether]); - itemReqs.Add(_game.Items[ItemType.EtherDungeons]); - itemReqs.Add(_game.Items[ItemType.Quake]); - itemReqs.Add(_game.Items[ItemType.QuakeDungeons]); - - _game.Regions[RegionID.DeathMountainEastTop].PropertyChanged += OnRequirementChanged; - _game.Regions[RegionID.DarkDeathMountainTop].PropertyChanged += OnRequirementChanged; + _updateOnWorldStateChange = true; + + _regionSubscriptions.Add(RegionID.TurtleRock, new Mode()); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode() { WorldState = WorldState.Inverted }); + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode() { WorldState = WorldState.Inverted }); + + _itemSubscriptions.Add(ItemType.CaneOfSomaria, new Mode()); + _itemSubscriptions.Add(ItemType.TRBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); + _itemSubscriptions.Add(ItemType.TRSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.Sword, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.Bombos, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.BombosDungeons, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.Ether, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.EtherDungeons, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.Quake, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.QuakeDungeons, new Mode() { WorldState = WorldState.Inverted }); break; @@ -401,80 +514,123 @@ public BossSection(Game game, LocationID iD) _defaultBoss = _game.Bosses[BossType.Aga]; _boss = _game.Bosses[BossType.Aga]; Prize = _game.Items[ItemType.Aga2]; - _region = _game.Regions[RegionID.GanonsTower]; GetAccessibility = () => { - if ((_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) && - _game.Items.Has(ItemType.GTSmallKey, 1) && _game.Items.Has(ItemType.GTBigKey)) - return AccessibilityLevel.Normal; + if (_game.Regions[RegionID.GanonsTower].Accessibility >= AccessibilityLevel.SequenceBreak) + { + if (_game.Mode.DungeonItemShuffle == DungeonItemShuffle.Keysanity) + { + if ((_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) && + _game.Items.Has(ItemType.GTSmallKey) && _game.Items.Has(ItemType.GTBigKey)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Normal, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } + } + else + { + if (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) + { + if (_game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.Hookshot) && + _game.Items.Has(ItemType.Boots) && _game.Items.Has(ItemType.CaneOfSomaria) && + _game.Items.Has(ItemType.FireRod) && _game.Items.Has(ItemType.GTSmallKey, 2)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Normal, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } + + return AccessibilityLevel.SequenceBreak; + } + } + } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Bow]); - itemReqs.Add(_game.Items[ItemType.GTSmallKey]); - itemReqs.Add(_game.Items[ItemType.GTBigKey]); + _updateOnEnemyShuffleChange = true; + + _regionSubscriptions.Add(RegionID.GanonsTower, new Mode()); + + _itemSubscriptions.Add(ItemType.Bow, new Mode() { EnemyShuffle = false }); + _itemSubscriptions.Add(ItemType.GTSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); + _itemSubscriptions.Add(ItemType.GTBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Hookshot, new Mode()); + _itemSubscriptions.Add(ItemType.Boots, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfSomaria, new Mode()); + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); break; } - foreach (Item item in itemReqs) - item.PropertyChanged += OnRequirementChanged; - + _game.Bosses.PropertyChanged += OnRequirementChanged; _game.Mode.PropertyChanged += OnModeChanged; - _defaultBoss.PropertyChanged += OnBossChanged; - if (_region != null) - _region.PropertyChanged += OnRegionChanged; - - Available = true; + UpdateRegionSubscriptions(); + UpdateItemSubscriptions(); + UpdateBossSubscription(); UpdateAccessibility(); } - private void UpdateAccessibility() + private void OnPropertyChanging(string propertyName) { - AccessibilityLevel? regionAccessibility = null; - AccessibilityLevel sectionAccessibility = GetAccessibility(); - AccessibilityLevel bossAccessibility = AccessibilityLevel.None; - - if (_region != null) - regionAccessibility = _region.Accessibility; + if (propertyName == nameof(Prize) && Prize != null && !Available) + Prize.Change(-1, true); - if (_game.Mode.BossShuffle.Value) + if (PropertyChanging != null) + PropertyChanging.Invoke(this, new PropertyChangingEventArgs(propertyName)); + } + + private void OnPropertyChanged(string propertyName) + { + if (propertyName == nameof(Available) && Prize != null) { - if (Boss == null) - bossAccessibility = _game.Bosses.UnknownBossAccessibility; + if (Available) + Prize.Change(-1, true); else - bossAccessibility = Boss.Accessibility; + Prize.Change(1, true); } - else + + if (propertyName == nameof(Boss)) { - if (_defaultBoss != null) - bossAccessibility = _defaultBoss.Accessibility; + UpdateBossSubscription(); + UpdateAccessibility(); } - if (regionAccessibility != null) - Accessibility = (AccessibilityLevel)Math.Min(Math.Min((byte)regionAccessibility.Value, - (byte)sectionAccessibility), (byte)bossAccessibility); - else - Accessibility = (AccessibilityLevel)Math.Min((byte)sectionAccessibility, (byte)bossAccessibility); - } - - private void OnRegionChanged(object sender, PropertyChangedEventArgs e) - { - UpdateAccessibility(); - } + if (propertyName == nameof(Prize) && Prize != null && !Available) + Prize.Change(1, true); - private void OnBossChanged(object sender, PropertyChangedEventArgs e) - { - UpdateAccessibility(); + if (PropertyChanged != null) + PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private void OnModeChanged(object sender, PropertyChangedEventArgs e) { - UpdateAccessibility(); + if (e.PropertyName == nameof(_game.Mode.ItemPlacement) && _updateOnItemPlacementChange) + UpdateAccessibility(); + + if (e.PropertyName == nameof(_game.Mode.DungeonItemShuffle)) + UpdateAccessibility(); + + if (e.PropertyName == nameof(_game.Mode.WorldState) && _updateOnWorldStateChange) + UpdateAccessibility(); + + if (e.PropertyName == nameof(_game.Mode.EntranceShuffle)) + UpdateAccessibility(); + + if (e.PropertyName == nameof(_game.Mode.BossShuffle)) + { + UpdateBossSubscription(); + UpdateAccessibility(); + } + + if (e.PropertyName == nameof(_game.Mode.EnemyShuffle) && _updateOnEnemyShuffleChange) + UpdateAccessibility(); + + UpdateRegionSubscriptions(); + UpdateItemSubscriptions(); } private void OnRequirementChanged(object sender, PropertyChangedEventArgs e) @@ -482,54 +638,135 @@ private void OnRequirementChanged(object sender, PropertyChangedEventArgs e) UpdateAccessibility(); } - private void OnPropertyChanging(string propertyName) + private void UpdateRegionSubscriptions() { - if (propertyName == nameof(Boss)) + foreach (RegionID region in _regionSubscriptions.Keys) { - if (Boss == null) - _game.Bosses.PropertyChanged -= OnBossChanged; - else if (Boss != _defaultBoss) - Boss.PropertyChanged -= OnBossChanged; + if (_game.Mode.Validate(_regionSubscriptions[region])) + { + if (_regionIsSubscribed.ContainsKey(region)) + { + if (!_regionIsSubscribed[region]) + { + _regionIsSubscribed[region] = true; + _game.Regions[region].PropertyChanged += OnRequirementChanged; + } + } + else + { + _regionIsSubscribed.Add(region, true); + _game.Regions[region].PropertyChanged += OnRequirementChanged; + } + } + else + { + if (_regionIsSubscribed.ContainsKey(region)) + { + if (_regionIsSubscribed[region]) + { + _regionIsSubscribed[region] = false; + _game.Regions[region].PropertyChanged -= OnRequirementChanged; + } + } + else + _regionIsSubscribed.Add(region, false); + } } - - if (propertyName == nameof(Prize) && Prize != null && - !Available) - Prize.Change(-1, true); - - if (PropertyChanging != null) - PropertyChanging.Invoke(this, new PropertyChangingEventArgs(propertyName)); } - private void OnPropertyChanged(string propertyName) + private void UpdateItemSubscriptions() { - if (propertyName == nameof(Available) && Prize != null) + foreach (ItemType item in _itemSubscriptions.Keys) { - if (Available) - Prize.Change(-1, true); + if (_game.Mode.Validate(_itemSubscriptions[item])) + { + if (_itemIsSubscribed.ContainsKey(item)) + { + if (!_itemIsSubscribed[item]) + { + _itemIsSubscribed[item] = true; + _game.Items[item].PropertyChanged += OnRequirementChanged; + } + } + else + { + _itemIsSubscribed.Add(item, true); + _game.Items[item].PropertyChanged += OnRequirementChanged; + } + } else - Prize.Change(1, true); + { + if (_itemIsSubscribed.ContainsKey(item)) + { + if (_itemIsSubscribed[item]) + { + _itemIsSubscribed[item] = false; + _game.Items[item].PropertyChanged -= OnRequirementChanged; + } + } + else + _itemIsSubscribed.Add(item, false); + } } + } - if (propertyName == nameof(Boss)) + private void UpdateBossSubscription() + { + if (_game.Mode.BossShuffle.Value) { - if (Boss == null) - _game.Bosses.PropertyChanged += OnBossChanged; - else if (Boss != _defaultBoss) - Boss.PropertyChanged += OnBossChanged; + if (Boss != _currentBossSubscription) + { + if (_currentBossSubscription == null) + _game.Bosses.PropertyChanged -= OnRequirementChanged; + else + _currentBossSubscription.PropertyChanged -= OnRequirementChanged; - UpdateAccessibility(); + _currentBossSubscription = Boss; + + if (_currentBossSubscription == null) + _game.Bosses.PropertyChanged += OnRequirementChanged; + else + _currentBossSubscription.PropertyChanged += OnRequirementChanged; + } } + else + { + if (_defaultBoss != _currentBossSubscription) + { + if (_currentBossSubscription == null) + _game.Bosses.PropertyChanged -= OnRequirementChanged; + else + _currentBossSubscription.PropertyChanged -= OnRequirementChanged; - if (propertyName == nameof(Prize) && Prize != null && - !Available) - Prize.Change(1, true); + _currentBossSubscription = _defaultBoss; - if (PropertyChanged != null) - PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); + if (_currentBossSubscription == null) + _game.Bosses.PropertyChanged += OnRequirementChanged; + else + _currentBossSubscription.PropertyChanged += OnRequirementChanged; + } + } + } + private void UpdateAccessibility() + { + AccessibilityLevel sectionAccessibility = GetAccessibility(); + AccessibilityLevel bossAccessibility = AccessibilityLevel.None; + + if (_game.Mode.BossShuffle.Value) + { + if (Boss == null) + bossAccessibility = _game.Bosses.UnknownBossAccessibility; + else + bossAccessibility = Boss.Accessibility; + } + else + { + if (_defaultBoss != null) + bossAccessibility = _defaultBoss.Accessibility; + } - if (propertyName == nameof(Boss)) - UpdateAccessibility(); + Accessibility = (AccessibilityLevel)Math.Min((byte)sectionAccessibility, (byte)bossAccessibility); } public void Clear() diff --git a/OpenTracker.Models/EntranceSection.cs b/OpenTracker.Models/EntranceSection.cs index 524ce110..5e3194b0 100644 --- a/OpenTracker.Models/EntranceSection.cs +++ b/OpenTracker.Models/EntranceSection.cs @@ -9,10 +9,12 @@ namespace OpenTracker.Models public class EntranceSection : ISection { private readonly Game _game; - private readonly Region _standardRegion; - private readonly Region _invertedRegion; private readonly Item _standardItemProvided; private readonly Item _invertedItemProvided; + private readonly Dictionary _regionSubscriptions; + private readonly Dictionary _regionIsSubscribed; + private readonly Dictionary _itemSubscriptions; + private readonly Dictionary _itemIsSubscribed; public string Name { get; } public bool HasMarking { get => true; } @@ -67,8 +69,13 @@ public MarkingType? Marking public EntranceSection(Game game, LocationID iD) { _game = game; - RequiredMode = new Mode(); + _regionSubscriptions = new Dictionary(); + _regionIsSubscribed = new Dictionary(); + _itemSubscriptions = new Dictionary(); + _itemIsSubscribed = new Dictionary(); + + RequiredMode = new Mode(); Available = true; List itemReqs = new List(); @@ -80,10 +87,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.LumberjackCaveEntrance: @@ -91,30 +98,30 @@ public EntranceSection(Game game, LocationID iD) Name = "Dropdown"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Aga) && _game.Items.Has(ItemType.Boots)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.Aga) && _game.Items.Has(ItemType.Boots) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.Inspect; }; - itemReqs.Add(_game.Items[ItemType.Aga]); - itemReqs.Add(_game.Items[ItemType.Boots]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Aga, new Mode()); + _itemSubscriptions.Add(ItemType.Boots, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.DeathMountainEntryCave: @@ -122,28 +129,28 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Gloves)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.Gloves) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.DeathMountainExitCave: @@ -151,8 +158,6 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DeathMountainExitAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainExitAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { @@ -165,8 +170,8 @@ public EntranceSection(Game game, LocationID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.BumperCaveAccess]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _itemSubscriptions.Add(ItemType.BumperCaveAccess, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.KakarikoFortuneTeller: @@ -174,10 +179,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.WomanLeftDoor: @@ -185,10 +190,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.WomanRightDoor: @@ -196,10 +201,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.LeftSnitchHouse: @@ -207,10 +212,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.RightSnitchHouse: @@ -218,10 +223,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.BlindsHouseEntrance: @@ -229,10 +234,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.TheWellEntrance: @@ -240,10 +245,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.ChickenHouseEntrance: @@ -251,10 +256,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.GrassHouse: @@ -262,24 +267,24 @@ public EntranceSection(Game game, LocationID iD) Name = "Move your lawn"; _standardItemProvided = _game.Items[ItemType.GrassHouseAccess]; _invertedItemProvided = _game.Items[ItemType.GrassHouseAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.TavernFront: @@ -287,10 +292,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.KakarikoShop: @@ -298,10 +303,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.BombHut: @@ -309,24 +314,24 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.SickKidEntrance: @@ -334,10 +339,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.BlacksmithHouse: @@ -345,10 +350,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.MagicBatEntrance: @@ -356,34 +361,49 @@ public EntranceSection(Game game, LocationID iD) Name = "Dropdown"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { + AccessibilityLevel direct = AccessibilityLevel.None; + AccessibilityLevel mirror = AccessibilityLevel.None; + if (_game.Items.Has(ItemType.Hammer)) - return AccessibilityLevel.Normal; + direct = _game.Regions[RegionID.LightWorld].Accessibility; + else + { + direct = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); + } if (_game.Items.Has(ItemType.Mirror) && _game.Items.Has(ItemType.Gloves, 2) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + mirror = AccessibilityLevel.Normal; + + return (AccessibilityLevel)Math.Max((byte)direct, (byte)mirror); } if (_game.Mode.WorldState == WorldState.Inverted) { - if (_game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + if (_game.Regions[RegionID.LightWorld].Accessibility >= AccessibilityLevel.SequenceBreak) + { + if (_game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.MoonPearl)) + return _game.Regions[RegionID.LightWorld].Accessibility; + + return AccessibilityLevel.Inspect; + } } - return AccessibilityLevel.Inspect; + return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode()); break; case LocationID.ChestGame: @@ -391,10 +411,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.RaceHouseLeft: @@ -402,21 +422,21 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.RaceGameAccess]; _invertedItemProvided = _game.Items[ItemType.RaceGameAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldSouth]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Mirror)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouth].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode() { WorldState = WorldState.StandardOpen }); + + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.RaceHouseRight: @@ -424,10 +444,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.LibraryEntrance: @@ -435,10 +455,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.ForestHideout: @@ -446,24 +466,24 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } - return AccessibilityLevel.Inspect; + return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.ForestChestGame: @@ -471,10 +491,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.CastleSecretEntrance: @@ -482,24 +502,29 @@ public EntranceSection(Game game, LocationID iD) Name = "Dropdown"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { - if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + if (_game.Regions[RegionID.LightWorld].Accessibility >= AccessibilityLevel.SequenceBreak) + { + if (_game.Items.Has(ItemType.MoonPearl)) + return _game.Regions[RegionID.LightWorld].Accessibility; + + return AccessibilityLevel.Inspect; + } } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.CastleMainEntrance: @@ -507,10 +532,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Dungeon"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.CastleLeftEntrance: @@ -518,10 +543,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Dungeon"; _standardItemProvided = _game.Items[ItemType.HyruleCastleSecondFloorAccess]; _invertedItemProvided = _game.Items[ItemType.HyruleCastleSecondFloorAccess]; - _standardRegion = _game.Regions[RegionID.HyruleCastleSecondFloor]; - _invertedRegion = _game.Regions[RegionID.HyruleCastleSecondFloor]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.HyruleCastleSecondFloor].Accessibility; }; + + _regionSubscriptions.Add(RegionID.HyruleCastleSecondFloor, new Mode()); break; case LocationID.CastleRightEntrance: @@ -529,10 +554,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Dungeon"; _standardItemProvided = _game.Items[ItemType.HyruleCastleSecondFloorAccess]; _invertedItemProvided = _game.Items[ItemType.HyruleCastleSecondFloorAccess]; - _standardRegion = _game.Regions[RegionID.HyruleCastleSecondFloor]; - _invertedRegion = _game.Regions[RegionID.HyruleCastleSecondFloor]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.HyruleCastleSecondFloor].Accessibility; }; + + _regionSubscriptions.Add(RegionID.HyruleCastleSecondFloor, new Mode()); break; case LocationID.CastleTowerEntrance: @@ -540,32 +565,32 @@ public EntranceSection(Game game, LocationID iD) Name = "Dungeon"; _standardItemProvided = _game.Items[ItemType.HyruleCastleSecondFloorAccess]; _invertedItemProvided = _game.Items[ItemType.HyruleCastleSecondFloorAccess]; - _standardRegion = _game.Regions[RegionID.HyruleCastleSecondFloor]; - _invertedRegion = _game.Regions[RegionID.HyruleCastleSecondFloor]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.CanClearAgaTowerBarrier()) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.HyruleCastleSecondFloor].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.TowerCrystals)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.HyruleCastleSecondFloor].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Cape]); - itemReqs.Add(_game.Items[ItemType.Sword]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.TowerCrystals]); - itemReqs.Add(_game.Items[ItemType.Crystal]); - itemReqs.Add(_game.Items[ItemType.RedCrystal]); + _regionSubscriptions.Add(RegionID.HyruleCastleSecondFloor, new Mode()); + + _itemSubscriptions.Add(ItemType.Cape, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Sword, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Hammer, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.TowerCrystals, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.Crystal, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.RedCrystal, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.DamEntrance: @@ -573,10 +598,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.CentralBonkRocks: @@ -584,8 +609,6 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { @@ -604,8 +627,10 @@ public EntranceSection(Game game, LocationID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Boots]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Boots, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.WitchsHutEntrance: @@ -613,24 +638,24 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.WitchsHutAccess]; _invertedItemProvided = _game.Items[ItemType.WitchsHutAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.WaterfallFairyEntrance: @@ -638,35 +663,41 @@ public EntranceSection(Game game, LocationID iD) Name = "Waterfall Cave"; _standardItemProvided = _game.Items[ItemType.WaterfallFairyAccess]; _invertedItemProvided = _game.Items[ItemType.WaterfallFairyAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { - if (_game.Items.Has(ItemType.Flippers)) - return AccessibilityLevel.Normal; + if (_game.Regions[RegionID.LightWorld].Accessibility >= AccessibilityLevel.SequenceBreak) + { + if (_game.Items.Has(ItemType.Flippers)) + return _game.Regions[RegionID.LightWorld].Accessibility; - return AccessibilityLevel.SequenceBreak; + return AccessibilityLevel.SequenceBreak; + } } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) { - if (_game.Items.Has(ItemType.Flippers)) - return AccessibilityLevel.Normal; + if (_game.Regions[RegionID.LightWorld].Accessibility >= AccessibilityLevel.SequenceBreak) + { + if (_game.Items.Has(ItemType.Flippers)) + return _game.Regions[RegionID.LightWorld].Accessibility; - return AccessibilityLevel.SequenceBreak; + return AccessibilityLevel.SequenceBreak; + } } } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Flippers]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Flippers, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.SahasrahlasHutEntrance: @@ -674,10 +705,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.TreesFairyCave: @@ -685,10 +716,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.PegsFairyCave: @@ -696,10 +727,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.EasternPalaceEntrance: @@ -707,10 +738,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Dungeon"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.HoulihanHole: @@ -718,24 +749,29 @@ public EntranceSection(Game game, LocationID iD) Name = "Dropdown"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { - if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + if (_game.Regions[RegionID.LightWorld].Accessibility >= AccessibilityLevel.SequenceBreak) + { + if (_game.Items.Has(ItemType.MoonPearl)) + return _game.Regions[RegionID.LightWorld].Accessibility; + + return AccessibilityLevel.Inspect; + } } - return AccessibilityLevel.Inspect; + return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.SanctuaryGrave: @@ -743,32 +779,38 @@ public EntranceSection(Game game, LocationID iD) Name = "Dropdown"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { - if (_game.Items.Has(ItemType.Gloves)) - return AccessibilityLevel.Normal; + if (_game.Regions[RegionID.LightWorld].Accessibility >= AccessibilityLevel.SequenceBreak) + { + if (_game.Items.Has(ItemType.Gloves)) + return _game.Regions[RegionID.LightWorld].Accessibility; - return AccessibilityLevel.Inspect; + return AccessibilityLevel.Inspect; + } } if (_game.Mode.WorldState == WorldState.Inverted) { - if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Gloves)) - return AccessibilityLevel.Normal; + if (_game.Regions[RegionID.LightWorld].Accessibility >= AccessibilityLevel.SequenceBreak) + { + if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Gloves)) + return _game.Regions[RegionID.LightWorld].Accessibility; - return AccessibilityLevel.Inspect; + return AccessibilityLevel.Inspect; + } } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.NorthBonkRocks: @@ -776,28 +818,28 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Boots)) - return AccessibilityLevel.Normal; - } + return _game.Regions[RegionID.LightWorld].Accessibility; + } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.Boots) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Boots]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Boots, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.KingsTombEntrance: @@ -805,8 +847,6 @@ public EntranceSection(Game game, LocationID iD) Name = "The Crypt"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { @@ -814,11 +854,16 @@ public EntranceSection(Game game, LocationID iD) { if (_game.Items.Has(ItemType.Boots)) { + AccessibilityLevel lightWorld = AccessibilityLevel.None; + AccessibilityLevel dWWest = AccessibilityLevel.None; + if (_game.Items.Has(ItemType.Gloves, 2)) - return AccessibilityLevel.Normal; + lightWorld = _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Items.Has(ItemType.Mirror) && _game.Items.Has(ItemType.MoonPearl)) - return _game.Regions[RegionID.DarkWorldWest].Accessibility; + dWWest = _game.Regions[RegionID.DarkWorldWest].Accessibility; + + return (AccessibilityLevel)Math.Max((byte)lightWorld, (byte)dWWest); } } @@ -826,18 +871,19 @@ public EntranceSection(Game game, LocationID iD) { if (_game.Items.Has(ItemType.Gloves, 2) && _game.Items.Has(ItemType.Boots) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Boots]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode() { WorldState = WorldState.StandardOpen }); - _game.Regions[RegionID.DarkWorldWest].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.Boots, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode()); break; case LocationID.GraveyardLedgeEntrance: @@ -845,15 +891,13 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Mirror)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldWest].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) @@ -865,8 +909,11 @@ public EntranceSection(Game game, LocationID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode() { WorldState = WorldState.StandardOpen }); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.DesertLeftEntrance: @@ -874,8 +921,6 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DesertLeftAccess]; _invertedItemProvided = _game.Items[ItemType.DesertLeftAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { @@ -898,12 +943,12 @@ public EntranceSection(Game game, LocationID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DesertBackAccess]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.MireArea, new Mode() { WorldState = WorldState.StandardOpen }); - _game.Regions[RegionID.MireArea].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.DesertBackAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.DesertBackEntrance: @@ -933,12 +978,12 @@ public EntranceSection(Game game, LocationID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DesertLeftAccess]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.MireArea, new Mode() { WorldState = WorldState.StandardOpen }); - _game.Regions[RegionID.MireArea].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.DesertLeftAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.DesertRightEntrance: @@ -946,54 +991,58 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.MireArea]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Mirror)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.MireArea].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.MireArea, new Mode() { WorldState = WorldState.StandardOpen }); + + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.DesertFrontEntrance: Name = "Cave"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { + AccessibilityLevel direct = AccessibilityLevel.None; + AccessibilityLevel mirror = AccessibilityLevel.None; + if (_game.Items.Has(ItemType.Book)) - return AccessibilityLevel.Normal; + direct = _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Items.Has(ItemType.Mirror)) - return _game.Regions[RegionID.MireArea].Accessibility; + mirror = _game.Regions[RegionID.MireArea].Accessibility; + + return (AccessibilityLevel)Math.Max((byte)direct, (byte)mirror); } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Book)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Book]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + _regionSubscriptions.Add(RegionID.MireArea, new Mode() { WorldState = WorldState.StandardOpen }); - _game.Regions[RegionID.MireArea].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.Book, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.AginahsCaveEntrance: @@ -1001,10 +1050,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.ThiefCave: @@ -1012,10 +1061,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.RupeeCave: @@ -1023,28 +1072,28 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Gloves)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.Gloves) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.SkullWoodsBack: @@ -1052,28 +1101,28 @@ public EntranceSection(Game game, LocationID iD) Name = "Dungeon"; _standardItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.FireRod) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldWest].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldWest].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.FireRod]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); + + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.ThievesTownEntrance: @@ -1081,24 +1130,24 @@ public EntranceSection(Game game, LocationID iD) Name = "Dungeon"; _standardItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldWest].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldWest].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.CShapedHouseEntrance: @@ -1106,10 +1155,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldWest].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); break; case LocationID.HammerHouse: @@ -1117,28 +1166,38 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.HammerHouseAccess]; _invertedItemProvided = _game.Items[ItemType.HammerHouseAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldWest].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { + AccessibilityLevel direct = AccessibilityLevel.None; + AccessibilityLevel mirror = AccessibilityLevel.None; + if (_game.Items.Has(ItemType.Hammer)) - return AccessibilityLevel.Normal; + direct = _game.Regions[RegionID.DarkWorldWest].Accessibility; + + if (_game.Items.Has(ItemType.Mirror) && _game.Items.Has(ItemType.MoonPearl)) + mirror = _game.Regions[RegionID.LightWorld].Accessibility; + + return (AccessibilityLevel)Math.Max((byte)direct, (byte)mirror); } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); + + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.DarkVillageFortuneTeller: @@ -1146,10 +1205,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldWest].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); break; case LocationID.DarkChapel: @@ -1157,10 +1216,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldWest].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); break; case LocationID.ShieldShop: @@ -1168,10 +1227,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldWest].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); break; case LocationID.DarkLumberjack: @@ -1179,10 +1238,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldWest].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); break; case LocationID.TreasureGameEntrance: @@ -1190,10 +1249,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldWest].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); break; case LocationID.BombableShackEntrance: @@ -1201,24 +1260,24 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldWest].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldWest].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.HammerPegsEntrance: @@ -1226,8 +1285,6 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; GetAccessibility = () => { @@ -1235,7 +1292,7 @@ public EntranceSection(Game game, LocationID iD) { if (_game.Items.Has(ItemType.Gloves, 2) && _game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldWest].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) @@ -1243,7 +1300,7 @@ public EntranceSection(Game game, LocationID iD) if (_game.Items.Has(ItemType.Hammer)) { if (_game.Items.Has(ItemType.Gloves, 2)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldWest].Accessibility; if (_game.Items.Has(ItemType.Mirror)) return _game.Regions[RegionID.LightWorld].Accessibility; @@ -1253,12 +1310,13 @@ public EntranceSection(Game game, LocationID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); - _game.Regions[RegionID.LightWorld].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.BumperCaveExit: @@ -1279,8 +1337,8 @@ public EntranceSection(Game game, LocationID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DeathMountainExitAccess]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _itemSubscriptions.Add(ItemType.DeathMountainExitAccess, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.BumperCaveEntrance: @@ -1288,28 +1346,28 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldWestAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Gloves) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldWest].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.Gloves)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldWest].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); + + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.HypeCaveEntrance: @@ -1317,24 +1375,25 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkWorldSouthAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldSouthAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldSouth]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouth]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouth].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouth].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode()); + + _itemSubscriptions.Add(ItemType.Boots, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.SwampPalaceEntrance: @@ -1342,10 +1401,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkWorldSouthAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldSouthAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldSouth]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouth]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldSouth].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode()); break; case LocationID.DarkCentralBonkRocks: @@ -1353,28 +1412,28 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkWorldSouthAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldSouthAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldSouth]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouth]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Boots) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouth].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.Boots)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouth].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Boots]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode()); + + _itemSubscriptions.Add(ItemType.Boots, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.SouthOfGroveEntrance: @@ -1382,24 +1441,25 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldSouth]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Mirror)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouth].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode() { WorldState = WorldState.StandardOpen }); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); + + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.BombShop: @@ -1407,10 +1467,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.DarkWorldSouthAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldSouthAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldSouth]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouth]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldSouth].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode()); break; case LocationID.ArrowGame: @@ -1418,10 +1478,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.DarkWorldSouthAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldSouthAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldSouth]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouth]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldSouth].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode()); break; case LocationID.DarkHyliaFortuneTeller: @@ -1429,10 +1489,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.DarkWorldSouthAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldSouthAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldSouth]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouth]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldSouth].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode()); break; case LocationID.DarkTreesFairyCave: @@ -1440,10 +1500,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkWorldEastAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldEastAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldEast]; - _invertedRegion = _game.Regions[RegionID.DarkWorldEast]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldEast].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldEast, new Mode()); break; case LocationID.DarkSahasrahla: @@ -1451,10 +1511,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.DarkWorldEastAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldEastAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldEast]; - _invertedRegion = _game.Regions[RegionID.DarkWorldEast]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldEast].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldEast, new Mode()); break; case LocationID.PalaceOfDarknessEntrance: @@ -1462,24 +1522,24 @@ public EntranceSection(Game game, LocationID iD) Name = "Dungeon"; _standardItemProvided = _game.Items[ItemType.DarkWorldEastAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldEastAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldEast]; - _invertedRegion = _game.Regions[RegionID.DarkWorldEast]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldEast].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldEast].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldEast, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.DarkWitchsHut: @@ -1487,10 +1547,10 @@ public EntranceSection(Game game, LocationID iD) Name = "House"; _standardItemProvided = _game.Items[ItemType.DarkWorldWitchAreaAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldWitchAreaAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldWitchArea]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWitchArea]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldWitchArea].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldWitchArea, new Mode()); break; case LocationID.DarkFluteSpotFive: @@ -1498,10 +1558,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkWorldEastAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldEastAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldEast]; - _invertedRegion = _game.Regions[RegionID.DarkWorldEast]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldEast].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldEast, new Mode()); break; case LocationID.FatFairyEntrance: @@ -1509,31 +1569,28 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkWorldEastAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldEastAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldEast]; - _invertedRegion = _game.Regions[RegionID.DarkWorldEast]; GetAccessibility = () => { - // Standard and Open modes if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.RedCrystal, 2)) return AccessibilityLevel.Normal; } - // Inverted mode if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.RedCrystal, 2)) return AccessibilityLevel.Normal; } - // Default to no access return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.RedCrystal]); + _regionSubscriptions.Add(RegionID.DarkWorldEast, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.RedCrystal, new Mode()); break; case LocationID.GanonHole: @@ -1541,31 +1598,33 @@ public EntranceSection(Game game, LocationID iD) Name = "Dropdown"; _standardItemProvided = _game.Items[ItemType.DarkWorldEastAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldEast]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Aga2)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldEast].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { - if (_game.Items.Has(ItemType.Aga2)) + if (_game.Regions[RegionID.HyruleCastleSecondFloor].Accessibility >= AccessibilityLevel.SequenceBreak && + _game.Items.Has(ItemType.Aga2)) return _game.Regions[RegionID.HyruleCastleSecondFloor].Accessibility; - return AccessibilityLevel.Inspect; + if (_game.Regions[RegionID.LightWorld].Accessibility >= AccessibilityLevel.SequenceBreak) + return AccessibilityLevel.Inspect; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Aga2]); + _regionSubscriptions.Add(RegionID.DarkWorldEast, new Mode() { WorldState = WorldState.StandardOpen }); + _regionSubscriptions.Add(RegionID.HyruleCastleSecondFloor, new Mode() { WorldState = WorldState.Inverted }); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); - _game.Regions[RegionID.HyruleCastleSecondFloor].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.Aga2, new Mode()); break; case LocationID.DarkIceRodCave: @@ -1573,24 +1632,24 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkWorldSouthEastAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldSouthEastAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldSouthEast]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouthEast]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouthEast].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouthEast].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldSouthEast, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.DarkFakeIceRodCave: @@ -1598,10 +1657,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkWorldSouthEastAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldSouthEastAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldSouthEast]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouthEast]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldSouthEast].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldSouthEast, new Mode()); break; case LocationID.DarkIceRodRock: @@ -1609,28 +1668,28 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkWorldSouthEastAccess]; _invertedItemProvided = _game.Items[ItemType.DarkWorldSouthEastAccess]; - _standardRegion = _game.Regions[RegionID.DarkWorldSouthEast]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouthEast]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Gloves)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouthEast].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.Gloves)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouthEast].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Gloves]); + _regionSubscriptions.Add(RegionID.DarkWorldSouthEast, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); break; case LocationID.HypeFairyCave: @@ -1638,24 +1697,24 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.FortuneTeller: @@ -1663,10 +1722,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.LakeShop: @@ -1674,10 +1733,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.UpgradeFairy: @@ -1685,18 +1744,19 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LakeHyliaFairyIslandAccess]; _invertedItemProvided = _game.Items[ItemType.LakeHyliaFairyIslandAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { - if (_game.Items.Has(ItemType.Flippers)) + if (_game.Regions[RegionID.LightWorld].Accessibility == AccessibilityLevel.Normal && + _game.Items.Has(ItemType.Flippers)) return AccessibilityLevel.Normal; if (_game.Items.Has(ItemType.IcePalaceAccess) && _game.Items.Has(ItemType.Mirror)) return AccessibilityLevel.Normal; + if (_game.Regions[RegionID.LightWorld].Accessibility >= AccessibilityLevel.SequenceBreak) return AccessibilityLevel.SequenceBreak; } @@ -1726,13 +1786,15 @@ public EntranceSection(Game game, LocationID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Flippers]); - itemReqs.Add(_game.Items[ItemType.IcePalaceAccess]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode() { WorldState = WorldState.Inverted }); + _regionSubscriptions.Add(RegionID.DarkWorldSouthEast, new Mode() { WorldState = WorldState.Inverted }); - _game.Regions[RegionID.LightWorld].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.Flippers, new Mode()); + _itemSubscriptions.Add(ItemType.IcePalaceAccess, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.MiniMoldormCaveEntrance: @@ -1740,24 +1802,24 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.IceRodCaveEntrance: @@ -1765,24 +1827,24 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.IceBeeCave: @@ -1790,10 +1852,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.IceFairyCave: @@ -1801,28 +1863,28 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Gloves)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Gloves)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Gloves]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.IcePalaceEntrance: @@ -1830,7 +1892,6 @@ public EntranceSection(Game game, LocationID iD) Name = "Dungeon"; _standardItemProvided = _game.Items[ItemType.IcePalaceAccess]; _invertedItemProvided = _game.Items[ItemType.IcePalaceAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { @@ -1838,52 +1899,69 @@ public EntranceSection(Game game, LocationID iD) { if (_game.Items.Has(ItemType.Gloves, 2)) { - if (_game.Items.Has(ItemType.Flippers)) - return AccessibilityLevel.Normal; - if (_game.Items.Has(ItemType.LakeHyliaFairyIslandAccess)) return AccessibilityLevel.Normal; - return AccessibilityLevel.SequenceBreak; + if (_game.Regions[RegionID.LightWorld].Accessibility >= AccessibilityLevel.SequenceBreak) + { + if (_game.Items.Has(ItemType.Flippers)) + return _game.Regions[RegionID.LightWorld].Accessibility; + + return AccessibilityLevel.SequenceBreak; + } } } if (_game.Mode.WorldState == WorldState.Inverted) { - if ((_game.Regions[RegionID.DarkWorldSouth].Accessibility == AccessibilityLevel.Normal || - _game.Regions[RegionID.DarkWorldSouthEast].Accessibility == AccessibilityLevel.Normal) && - _game.Items.Has(ItemType.Flippers)) - return AccessibilityLevel.Normal; + AccessibilityLevel dWSouth = AccessibilityLevel.None; + AccessibilityLevel dWSouthEast = AccessibilityLevel.None; + AccessibilityLevel lightWorld = AccessibilityLevel.None; - if (_game.Items.Has(ItemType.Mirror)) + if (_game.Items.Has(ItemType.Flippers)) { - if (_game.Items.Has(ItemType.LakeHyliaFairyIslandAccess)) - return AccessibilityLevel.Normal; - - if (_game.Regions[RegionID.LightWorld].Accessibility == AccessibilityLevel.Normal && - _game.Items.Has(ItemType.Flippers) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + dWSouth = _game.Regions[RegionID.DarkWorldSouth].Accessibility; + dWSouthEast = _game.Regions[RegionID.DarkWorldSouthEast].Accessibility; + } + else + { + dWSouth = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DarkWorldSouth].Accessibility); + dWSouthEast = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DarkWorldSouthEast].Accessibility); + } - if (_game.Regions[RegionID.LightWorld].Accessibility >= AccessibilityLevel.SequenceBreak && - _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.SequenceBreak; + if (_game.Items.Has(ItemType.Mirror)) + { + if (_game.Items.Has(ItemType.LakeHyliaFairyIslandAccess) || + (_game.Items.Has(ItemType.Flippers) && _game.Items.Has(ItemType.MoonPearl))) + lightWorld = _game.Regions[RegionID.LightWorld].Accessibility; + else if (_game.Items.Has(ItemType.MoonPearl)) + { + lightWorld = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); + } } if (_game.Regions[RegionID.DarkWorldSouth].Accessibility >= AccessibilityLevel.SequenceBreak || _game.Regions[RegionID.DarkWorldSouthEast].Accessibility >= AccessibilityLevel.SequenceBreak) return AccessibilityLevel.SequenceBreak; + + return (AccessibilityLevel)Math.Max(Math.Max((byte)dWSouth, (byte)dWSouthEast), (byte)lightWorld); } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Flippers]); - itemReqs.Add(_game.Items[ItemType.LakeHyliaFairyIslandAccess]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode() { WorldState = WorldState.Inverted }); + _regionSubscriptions.Add(RegionID.DarkWorldSouthEast, new Mode() { WorldState = WorldState.Inverted }); - _game.Regions[RegionID.LightWorld].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.LakeHyliaFairyIslandAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Flippers, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.MiseryMireEntrance: @@ -1891,8 +1969,6 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.MireAreaAccess]; _invertedItemProvided = _game.Items[ItemType.MireAreaAccess]; - _standardRegion = _game.Regions[RegionID.MireArea]; - _invertedRegion = _game.Regions[RegionID.MireArea]; GetAccessibility = () => { @@ -1910,7 +1986,7 @@ public EntranceSection(Game game, LocationID iD) (_game.Items.Has(ItemType.Quake) && (_game.Items[ItemType.QuakeDungeons].Current == 1 || _game.Items[ItemType.QuakeDungeons].Current == 3)))) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.MireArea].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) @@ -1927,21 +2003,23 @@ public EntranceSection(Game game, LocationID iD) (_game.Items.Has(ItemType.Quake) && (_game.Items[ItemType.QuakeDungeons].Current == 1 || _game.Items[ItemType.QuakeDungeons].Current == 3)))) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.MireArea].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Sword]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Bombos]); - itemReqs.Add(_game.Items[ItemType.BombosDungeons]); - itemReqs.Add(_game.Items[ItemType.Ether]); - itemReqs.Add(_game.Items[ItemType.EtherDungeons]); - itemReqs.Add(_game.Items[ItemType.Quake]); - itemReqs.Add(_game.Items[ItemType.QuakeDungeons]); + _regionSubscriptions.Add(RegionID.MireArea, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Bombos, new Mode()); + _itemSubscriptions.Add(ItemType.BombosDungeons, new Mode()); + _itemSubscriptions.Add(ItemType.Ether, new Mode()); + _itemSubscriptions.Add(ItemType.EtherDungeons, new Mode()); + _itemSubscriptions.Add(ItemType.Quake, new Mode()); + _itemSubscriptions.Add(ItemType.QuakeDungeons, new Mode()); break; case LocationID.MireShackEntrance: @@ -1949,10 +2027,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.MireAreaAccess]; _invertedItemProvided = _game.Items[ItemType.MireAreaAccess]; - _standardRegion = _game.Regions[RegionID.MireArea]; - _invertedRegion = _game.Regions[RegionID.MireArea]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.MireArea].Accessibility; }; + + _regionSubscriptions.Add(RegionID.MireArea, new Mode()); break; case LocationID.MireRightShack: @@ -1960,10 +2038,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.MireAreaAccess]; _invertedItemProvided = _game.Items[ItemType.MireAreaAccess]; - _standardRegion = _game.Regions[RegionID.MireArea]; - _invertedRegion = _game.Regions[RegionID.MireArea]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.MireArea].Accessibility; }; + + _regionSubscriptions.Add(RegionID.MireArea, new Mode()); break; case LocationID.MireCave: @@ -1971,40 +2049,41 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.MireAreaAccess]; _invertedItemProvided = _game.Items[ItemType.MireAreaAccess]; - _standardRegion = _game.Regions[RegionID.MireArea]; - _invertedRegion = _game.Regions[RegionID.MireArea]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.MireArea].Accessibility; }; + + _regionSubscriptions.Add(RegionID.MireArea, new Mode()); break; case LocationID.CheckerboardCaveEntrance: Name = "Cave"; _standardItemProvided = _game.Items[ItemType.CheckerboardCaveAccess]; - _invertedItemProvided = _game.Items[ItemType.CheckerboardCaveAccess]; - _standardRegion = _game.Regions[RegionID.MireArea]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; + _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Mirror) && _game.Items.Has(ItemType.Gloves)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.MireArea].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Gloves)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.MireArea, new Mode() { WorldState = WorldState.StandardOpen }); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); + + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.DeathMountainEntranceBack: @@ -2012,10 +2091,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DeathMountainWestBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainWestBottomAccess]; - _standardRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - _invertedRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainWestBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainWestBottom, new Mode()); break; case LocationID.OldManResidence: @@ -2023,10 +2102,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DeathMountainWestBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainWestBottomAccess]; - _standardRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - _invertedRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainWestBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainWestBottom, new Mode()); break; case LocationID.OldManBackResidence: @@ -2034,10 +2113,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DeathMountainWestBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainWestBottomAccess]; - _standardRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - _invertedRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainWestBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainWestBottom, new Mode()); break; case LocationID.DeathMountainExitFront: @@ -2045,10 +2124,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DeathMountainWestBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainWestBottomAccess]; - _standardRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - _invertedRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainWestBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainWestBottom, new Mode()); break; case LocationID.SpectacleRockLeft: @@ -2056,10 +2135,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DeathMountainWestBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainWestBottomAccess]; - _standardRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - _invertedRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainWestBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainWestBottom, new Mode()); break; case LocationID.SpectacleRockRight: @@ -2067,10 +2146,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DeathMountainWestBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainWestBottomAccess]; - _standardRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - _invertedRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainWestBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainWestBottom, new Mode()); break; case LocationID.SpectacleRockTop: @@ -2078,10 +2157,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DeathMountainWestBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainWestBottomAccess]; - _standardRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - _invertedRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainWestBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainWestBottom, new Mode()); break; case LocationID.SpikeCaveEntrance: @@ -2089,10 +2168,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkDeathMountainWestBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DarkDeathMountainWestBottomAccess]; - _standardRegion = _game.Regions[RegionID.DarkDeathMountainWestBottom]; - _invertedRegion = _game.Regions[RegionID.DarkDeathMountainWestBottom]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkDeathMountainWestBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkDeathMountainWestBottom, new Mode()); break; case LocationID.DarkMountainFairy: @@ -2100,10 +2179,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkDeathMountainWestBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DarkDeathMountainWestBottomAccess]; - _standardRegion = _game.Regions[RegionID.DarkDeathMountainWestBottom]; - _invertedRegion = _game.Regions[RegionID.DarkDeathMountainWestBottom]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkDeathMountainWestBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkDeathMountainWestBottom, new Mode()); break; case LocationID.TowerOfHeraEntrance: @@ -2111,10 +2190,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Dungeon"; _standardItemProvided = _game.Items[ItemType.DeathMountainWestTopAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainWestTopAccess]; - _standardRegion = _game.Regions[RegionID.DeathMountainWestTop]; - _invertedRegion = _game.Regions[RegionID.DeathMountainWestTop]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainWestTop].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainWestTop, new Mode()); break; case LocationID.SpiralCaveBottom: @@ -2122,10 +2201,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DeathMountainEastBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainEastBottomAccess]; - _standardRegion = _game.Regions[RegionID.DeathMountainEastBottom]; - _invertedRegion = _game.Regions[RegionID.DeathMountainEastBottom]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainEastBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainEastBottom, new Mode()); break; case LocationID.EDMFairyCave: @@ -2133,10 +2212,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DeathMountainEastBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainEastBottomAccess]; - _standardRegion = _game.Regions[RegionID.DeathMountainEastBottom]; - _invertedRegion = _game.Regions[RegionID.DeathMountainEastBottom]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainEastBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainEastBottom, new Mode()); break; case LocationID.ParadoxCaveMiddle: @@ -2144,10 +2223,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DeathMountainEastBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainEastBottomAccess]; - _standardRegion = _game.Regions[RegionID.DeathMountainEastBottom]; - _invertedRegion = _game.Regions[RegionID.DeathMountainEastBottom]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainEastBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainEastBottom, new Mode()); break; case LocationID.ParadoxCaveBottom: @@ -2155,10 +2234,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DeathMountainEastBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainEastBottomAccess]; - _standardRegion = _game.Regions[RegionID.DeathMountainEastBottom]; - _invertedRegion = _game.Regions[RegionID.DeathMountainEastBottom]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainEastBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainEastBottom, new Mode()); break; case LocationID.EDMConnectorBottom: @@ -2166,49 +2245,58 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DeathMountainEastBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainEastBottomAccess]; - _standardRegion = _game.Regions[RegionID.DeathMountainEastBottom]; - _invertedRegion = _game.Regions[RegionID.DeathMountainEastBottom]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { - if (_game.Items.Has(ItemType.Gloves, 2)) - return AccessibilityLevel.Normal; - - if (_game.Items.Has(ItemType.DeathMountainEastTopConnectorAccess)) - return AccessibilityLevel.Normal; - AccessibilityLevel dMEastTop = _game.Regions[RegionID.DeathMountainEastTop].Accessibility; + AccessibilityLevel dMEastBottom = AccessibilityLevel.None; AccessibilityLevel dDMEastBottom = AccessibilityLevel.None; + if (_game.Items.Has(ItemType.DeathMountainEastTopConnectorAccess) || + _game.Items.Has(ItemType.Gloves, 2)) + dMEastBottom = _game.Regions[RegionID.DeathMountainEastBottom].Accessibility; + if (_game.Items.Has(ItemType.Mirror)) { if (_game.Items.Has(ItemType.TurtleRockSafetyDoorAccess)) return AccessibilityLevel.Normal; - dDMEastBottom = _game.Regions[RegionID.DarkDeathMountainEastBottom].Accessibility; + if (_game.Items.Has(ItemType.MoonPearl)) + dDMEastBottom = _game.Regions[RegionID.DarkDeathMountainEastBottom].Accessibility; } - return (AccessibilityLevel)Math.Max((byte)dMEastTop, (byte)dDMEastBottom); + return (AccessibilityLevel)Math.Max(Math.Max((byte)dMEastTop, (byte)dMEastBottom), + (byte)dDMEastBottom); } if (_game.Mode.WorldState == WorldState.Inverted) { - if (_game.Items.Has(ItemType.Gloves, 2) && _game.Items.Has(ItemType.MoonPearl)) + if (_game.Items.Has(ItemType.DeathMountainEastTopConnectorAccess)) return AccessibilityLevel.Normal; - return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; + AccessibilityLevel dMEastTop = _game.Regions[RegionID.DeathMountainEastTop].Accessibility; + AccessibilityLevel dMEastBottom = AccessibilityLevel.None; + + if (_game.Items.Has(ItemType.Gloves, 2) && _game.Items.Has(ItemType.MoonPearl)) + dMEastBottom = _game.Regions[RegionID.DeathMountainEastBottom].Accessibility; + + return (AccessibilityLevel)Math.Max((byte)dMEastTop, (byte)dMEastBottom); } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.DeathMountainEastTopConnectorAccess]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.TurtleRockSafetyDoorAccess]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode()); + _regionSubscriptions.Add(RegionID.DeathMountainEastBottom, new Mode()); + _regionSubscriptions.Add(RegionID.DarkDeathMountainEastBottom, new Mode() { WorldState = WorldState.StandardOpen }); + + _itemSubscriptions.Add(ItemType.DeathMountainEastTopConnectorAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.TurtleRockSafetyDoorAccess, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode()); _game.Regions[RegionID.DeathMountainEastTop].PropertyChanged += OnRequirementChanged; _game.Regions[RegionID.DarkDeathMountainEastBottom].PropertyChanged += OnRequirementChanged; @@ -2219,8 +2307,6 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.SpiralCaveTopAccess]; _invertedItemProvided = _game.Items[ItemType.SpiralCaveTopAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.DeathMountainEastTop]; GetAccessibility = () => { @@ -2233,13 +2319,15 @@ public EntranceSection(Game game, LocationID iD) } if (_game.Mode.WorldState == WorldState.Inverted) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.TurtleRockTunnelAccess]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode()); + + _itemSubscriptions.Add(ItemType.TurtleRockTunnelAccess, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.MimicCaveEntrance: @@ -2247,24 +2335,25 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.MimicCaveAccess]; _invertedItemProvided = _game.Items[ItemType.MimicCaveAccess]; - _standardRegion = _game.Regions[RegionID.TurtleRockTunnel]; - _invertedRegion = _game.Regions[RegionID.DeathMountainEastTop]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Mirror)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.TurtleRockTunnel].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.TurtleRockTunnel, new Mode() { WorldState = WorldState.StandardOpen }); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode() { WorldState = WorldState.Inverted }); + + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.EDMConnectorTop: @@ -2272,8 +2361,6 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DeathMountainEastTopConnectorAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainEastTopConnectorAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.DeathMountainEastTop]; GetAccessibility = () => { @@ -2287,13 +2374,15 @@ public EntranceSection(Game game, LocationID iD) } if (_game.Mode.WorldState == WorldState.Inverted) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.TurtleRockSafetyDoorAccess]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode()); + + _itemSubscriptions.Add(ItemType.TurtleRockSafetyDoorAccess, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.ParadoxCaveTop: @@ -2301,10 +2390,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DeathMountainEastTopAccess]; _invertedItemProvided = _game.Items[ItemType.DeathMountainEastTopAccess]; - _standardRegion = _game.Regions[RegionID.DeathMountainEastTop]; - _invertedRegion = _game.Regions[RegionID.DeathMountainEastTop]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode()); break; case LocationID.SuperBunnyCaveBottom: @@ -2312,10 +2401,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkDeathMountainEastBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DarkDeathMountainEastBottomAccess]; - _standardRegion = _game.Regions[RegionID.DarkDeathMountainEastBottom]; - _invertedRegion = _game.Regions[RegionID.DarkDeathMountainEastBottom]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainEastBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainEastBottom, new Mode()); break; case LocationID.DeathMountainShop: @@ -2323,10 +2412,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkDeathMountainEastBottomAccess]; _invertedItemProvided = _game.Items[ItemType.DarkDeathMountainEastBottomAccess]; - _standardRegion = _game.Regions[RegionID.DarkDeathMountainEastBottom]; - _invertedRegion = _game.Regions[RegionID.DarkDeathMountainEastBottom]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainEastBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainEastBottom, new Mode()); break; case LocationID.SuperBunnyCaveTop: @@ -2334,10 +2423,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkDeathMountainTopAccess]; _invertedItemProvided = _game.Items[ItemType.DarkDeathMountainTopAccess]; - _standardRegion = _game.Regions[RegionID.DarkDeathMountainTop]; - _invertedRegion = _game.Regions[RegionID.DarkDeathMountainTop]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkDeathMountainTop].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode()); break; case LocationID.HookshotCaveEntrance: @@ -2345,28 +2434,28 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkDeathMountainTopAccess]; _invertedItemProvided = _game.Items[ItemType.DarkDeathMountainTopAccess]; - _standardRegion = _game.Regions[RegionID.DarkDeathMountainTop]; - _invertedRegion = _game.Regions[RegionID.DarkDeathMountainTop]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Gloves) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkDeathMountainTop].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.Gloves)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkDeathMountainTop].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode()); + + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.TurtleRockEntrance: @@ -2374,8 +2463,6 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkDeathMountainTopAccess]; _invertedItemProvided = _game.Items[ItemType.DarkDeathMountainTopAccess]; - _standardRegion = _game.Regions[RegionID.DeathMountainEastTop]; - _invertedRegion = _game.Regions[RegionID.DarkDeathMountainTop]; GetAccessibility = () => { @@ -2391,7 +2478,7 @@ public EntranceSection(Game game, LocationID iD) _game.Items[ItemType.EtherDungeons].Current >= 2) || (_game.Items.Has(ItemType.Quake) && _game.Items[ItemType.QuakeDungeons].Current >= 2))) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) @@ -2404,22 +2491,25 @@ public EntranceSection(Game game, LocationID iD) _game.Items[ItemType.EtherDungeons].Current >= 2) || (_game.Items.Has(ItemType.Quake) && _game.Items[ItemType.QuakeDungeons].Current >= 2))) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkDeathMountainTop].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Sword]); - itemReqs.Add(_game.Items[ItemType.Bombos]); - itemReqs.Add(_game.Items[ItemType.BombosDungeons]); - itemReqs.Add(_game.Items[ItemType.Ether]); - itemReqs.Add(_game.Items[ItemType.EtherDungeons]); - itemReqs.Add(_game.Items[ItemType.Quake]); - itemReqs.Add(_game.Items[ItemType.QuakeDungeons]); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode() { WorldState = WorldState.StandardOpen }); + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode() { WorldState = WorldState.Inverted }); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Hammer, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Bombos, new Mode()); + _itemSubscriptions.Add(ItemType.BombosDungeons, new Mode()); + _itemSubscriptions.Add(ItemType.Ether, new Mode()); + _itemSubscriptions.Add(ItemType.EtherDungeons, new Mode()); + _itemSubscriptions.Add(ItemType.Quake, new Mode()); + _itemSubscriptions.Add(ItemType.QuakeDungeons, new Mode()); break; case LocationID.GanonsTowerEntrance: @@ -2427,26 +2517,26 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkDeathMountainTopAccess]; _invertedItemProvided = _game.Items[ItemType.DarkDeathMountainTopAccess]; - _standardRegion = _game.Regions[RegionID.DarkDeathMountainTop]; - _invertedRegion = _game.Regions[RegionID.DarkDeathMountainTop]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.TowerCrystals)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkDeathMountainTop].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkDeathMountainTop].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.TowerCrystals]); - itemReqs.Add(_game.Items[ItemType.Crystal]); - itemReqs.Add(_game.Items[ItemType.RedCrystal]); + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode()); + + _itemSubscriptions.Add(ItemType.TowerCrystals, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Crystal, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.RedCrystal, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.TRLedgeLeft: @@ -2454,10 +2544,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.TurtleRockTunnelAccess]; _invertedItemProvided = _game.Items[ItemType.TurtleRockTunnelAccess]; - _standardRegion = _game.Regions[RegionID.TurtleRockTunnel]; - _invertedRegion = _game.Regions[RegionID.TurtleRockTunnel]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.TurtleRockTunnel].Accessibility; }; + + _regionSubscriptions.Add(RegionID.TurtleRockTunnel, new Mode()); break; case LocationID.TRLedgeRight: @@ -2465,10 +2555,10 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.TurtleRockTunnelAccess]; _invertedItemProvided = _game.Items[ItemType.TurtleRockTunnelAccess]; - _standardRegion = _game.Regions[RegionID.TurtleRockTunnel]; - _invertedRegion = _game.Regions[RegionID.TurtleRockTunnel]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.TurtleRockTunnel].Accessibility; }; + + _regionSubscriptions.Add(RegionID.TurtleRockTunnel, new Mode()); break; case LocationID.TRSafetyDoor: @@ -2476,7 +2566,6 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.TurtleRockSafetyDoorAccess]; _invertedItemProvided = _game.Items[ItemType.TurtleRockSafetyDoorAccess]; - _standardRegion = _game.Regions[RegionID.DarkDeathMountainTop]; GetAccessibility = () => { @@ -2494,10 +2583,10 @@ public EntranceSection(Game game, LocationID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.DeathMountainEastTopConnectorAccess]); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode() { WorldState = WorldState.Inverted }); - _game.Regions[RegionID.DeathMountainEastTop].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.DeathMountainEastTopConnectorAccess, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.HookshotCaveTop: @@ -2505,21 +2594,21 @@ public EntranceSection(Game game, LocationID iD) Name = "Cave"; _standardItemProvided = _game.Items[ItemType.DarkDeathMountainFloatingIslandAccess]; _invertedItemProvided = _game.Items[ItemType.DarkDeathMountainFloatingIslandAccess]; - _standardRegion = _game.Regions[RegionID.DarkDeathMountainEastBottom]; - _invertedRegion = _game.Regions[RegionID.DeathMountainEastTop]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.Mirror)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkDeathMountainEastBottom].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DarkDeathMountainEastBottom, new Mode() { WorldState = WorldState.Inverted }); + + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.LinksHouseEntrance: @@ -2527,72 +2616,80 @@ public EntranceSection(Game game, LocationID iD) Name = "Link's House"; _standardItemProvided = _game.Items[ItemType.LightWorldAccess]; _invertedItemProvided = _game.Items[ItemType.LightWorldAccess]; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; } - if (GetAccessibility == null) - GetAccessibility = () => { return AccessibilityLevel.None; }; - _game.Mode.PropertyChanged += OnModeChanged; - foreach (Item item in itemReqs) - item.PropertyChanged += OnRequirementChanged; - - if (_standardRegion != null) - _standardRegion.PropertyChanged += OnRequirementChanged; - - if (_invertedRegion != null) - _invertedRegion.PropertyChanged += OnRequirementChanged; + UpdateRegionSubscriptions(); + UpdateItemSubscriptions(); UpdateAccessibility(); } - private void UpdateAccessibility() + private void OnPropertyChanged(string propertyName) { - AccessibilityLevel? regionAccessibility = null; - - if (_game.Mode.WorldState == WorldState.StandardOpen && _standardRegion != null) - regionAccessibility = _standardRegion.Accessibility; - - if (_game.Mode.WorldState == WorldState.Inverted && _invertedRegion != null) - regionAccessibility = _invertedRegion.Accessibility; + if (PropertyChanged != null) + PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); - if (regionAccessibility != null) + if (propertyName == nameof(Available)) { - AccessibilityLevel sectionAccessibility = GetAccessibility(); - Accessibility = (AccessibilityLevel)Math.Min((byte)regionAccessibility.Value, - (byte)sectionAccessibility); + if (_game.Mode.WorldState == WorldState.StandardOpen && _standardItemProvided != null) + { + if (Available) + _standardItemProvided.Change(-1, true); + else + _standardItemProvided.Change(1, true); + } + + if (_game.Mode.WorldState == WorldState.Inverted && _invertedItemProvided != null) + { + if (Available) + _invertedItemProvided.Change(-1, true); + else + _invertedItemProvided.Change(1, true); + } } - else - Accessibility = GetAccessibility(); } private void OnModeChanged(object sender, PropertyChangedEventArgs e) { - if (!Available && e.PropertyName == nameof(_game.Mode.WorldState)) + if (e.PropertyName == nameof(_game.Mode.WorldState)) { - if (_standardItemProvided != null && _invertedItemProvided != null) + if (!Available) { - if (_game.Mode.WorldState == WorldState.StandardOpen) + if (_standardItemProvided != null) { - _invertedItemProvided.Change(-1, true); - _standardItemProvided.Change(1, true); + if (_game.Mode.WorldState == WorldState.StandardOpen) + _standardItemProvided.Change(1, true); + + if (_game.Mode.WorldState == WorldState.Inverted) + _standardItemProvided.Change(-1, true); } - if (_game.Mode.WorldState == WorldState.Inverted) + if (_invertedItemProvided != null) { - _standardItemProvided.Change(-1, true); - _invertedItemProvided.Change(1, true); + if (_game.Mode.WorldState == WorldState.StandardOpen) + _invertedItemProvided.Change(-1, true); + + if (_game.Mode.WorldState == WorldState.Inverted) + _invertedItemProvided.Change(1, true); } } + + UpdateRegionSubscriptions(); + UpdateItemSubscriptions(); + + UpdateAccessibility(); } - UpdateAccessibility(); + if (e.PropertyName == nameof(_game.Mode.EntranceShuffle)) + UpdateAccessibility(); } private void OnRequirementChanged(object sender, PropertyChangedEventArgs e) @@ -2600,31 +2697,84 @@ private void OnRequirementChanged(object sender, PropertyChangedEventArgs e) UpdateAccessibility(); } - private void OnPropertyChanged(string propertyName) + private void UpdateRegionSubscriptions() { - if (PropertyChanged != null) - PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); - - if (propertyName == nameof(Available)) + foreach (RegionID region in _regionSubscriptions.Keys) { - if (_game.Mode.WorldState == WorldState.StandardOpen && _standardItemProvided != null) + if (_game.Mode.Validate(_regionSubscriptions[region])) { - if (Available) - _standardItemProvided.Change(-1, true); + if (_regionIsSubscribed.ContainsKey(region)) + { + if (!_regionIsSubscribed[region]) + { + _regionIsSubscribed[region] = true; + _game.Regions[region].PropertyChanged += OnRequirementChanged; + } + } else - _standardItemProvided.Change(1, true); + { + _regionIsSubscribed.Add(region, true); + _game.Regions[region].PropertyChanged += OnRequirementChanged; + } + } + else + { + if (_regionIsSubscribed.ContainsKey(region)) + { + if (_regionIsSubscribed[region]) + { + _regionIsSubscribed[region] = false; + _game.Regions[region].PropertyChanged -= OnRequirementChanged; + } + } + else + _regionIsSubscribed.Add(region, false); } + } + } - if (_game.Mode.WorldState == WorldState.Inverted && _invertedItemProvided != null) + private void UpdateItemSubscriptions() + { + foreach (ItemType item in _itemSubscriptions.Keys) + { + if (_game.Mode.Validate(_itemSubscriptions[item])) { - if (Available) - _invertedItemProvided.Change(-1, true); + if (_itemIsSubscribed.ContainsKey(item)) + { + if (!_itemIsSubscribed[item]) + { + _itemIsSubscribed[item] = true; + _game.Items[item].PropertyChanged += OnRequirementChanged; + } + } else - _invertedItemProvided.Change(1, true); + { + _itemIsSubscribed.Add(item, true); + _game.Items[item].PropertyChanged += OnRequirementChanged; + } + } + else + { + if (_itemIsSubscribed.ContainsKey(item)) + { + if (_itemIsSubscribed[item]) + { + _itemIsSubscribed[item] = false; + _game.Items[item].PropertyChanged -= OnRequirementChanged; + } + } + else + _itemIsSubscribed.Add(item, false); } } } + private void UpdateAccessibility() + { + if (_game.Mode.EntranceShuffle.Value) + Accessibility = GetAccessibility(); + } + public void Clear() { Available = false; diff --git a/OpenTracker.Models/Game.cs b/OpenTracker.Models/Game.cs index a1b32a97..464e3f9e 100644 --- a/OpenTracker.Models/Game.cs +++ b/OpenTracker.Models/Game.cs @@ -24,7 +24,7 @@ public Game() EnemyShuffle = false }; - Bosses = new BossDictionary(this, Enum.GetValues(typeof(BossType)).Length); + Bosses = new BossDictionary(Enum.GetValues(typeof(BossType)).Length); Items = new ItemDictionary(Mode, Enum.GetValues(typeof(ItemType)).Length); Regions = new Dictionary(Enum.GetValues(typeof(RegionID)).Length); Locations = new LocationDictionary(Enum.GetValues(typeof(LocationID)).Length); @@ -41,11 +41,13 @@ public Game() Regions.Add(iD, new Region(this, iD)); foreach (Region region in Regions.Values) - region.SubscribeToRegions(); + { + region.UpdateRegionSubscriptions(); + region.UpdateAccessibility(); + } foreach (LocationID iD in Enum.GetValues(typeof(LocationID))) Locations.Add(iD, new Location(this, iD)); - } public void Reset() diff --git a/OpenTracker.Models/ItemSection.cs b/OpenTracker.Models/ItemSection.cs index 98f690b2..78321883 100644 --- a/OpenTracker.Models/ItemSection.cs +++ b/OpenTracker.Models/ItemSection.cs @@ -10,12 +10,17 @@ public class ItemSection : ISection { private readonly Game _game; private readonly Location _location; - private readonly Region _standardRegion; - private readonly Region _invertedRegion; private readonly int _mapCompass; private readonly int _smallKey; private readonly int _bigKey; private readonly int _baseTotal; + private readonly bool _updateOnDungeonItemShuffleChange; + private readonly bool _updateOnItemPlacementChange; + private readonly bool _updateOnEnemyShuffleChange; + private readonly Dictionary _regionSubscriptions; + private readonly Dictionary _regionIsSubscribed; + private readonly Dictionary _itemSubscriptions; + private readonly Dictionary _itemIsSubscribed; public string Name { get; } public int Total { get; private set; } @@ -73,9 +78,10 @@ public ItemSection(Game game, Location location, int index = 0) _game = game; _location = location; - _game.Mode.PropertyChanged += OnModeChanged; - - List itemReqs = new List(); + _regionSubscriptions = new Dictionary(); + _regionIsSubscribed = new Dictionary(); + _itemSubscriptions = new Dictionary(); + _itemIsSubscribed = new Dictionary(); switch (_location.ID) { @@ -84,31 +90,36 @@ public ItemSection(Game game, Location location, int index = 0) _baseTotal = 1; Name = "Pedestal"; HasMarking = true; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { - if (_game.Items.Has(ItemType.GreenPendant) && _game.Items.Has(ItemType.Pendant, 2)) + if (_game.Regions[RegionID.LightWorld].Accessibility >= AccessibilityLevel.SequenceBreak) { - // Basic Item Placement requires Book in logic - if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Mode.WorldState == WorldState.Inverted || - _game.Items.Has(ItemType.Book)) - return AccessibilityLevel.Normal; + if (_game.Items.Has(ItemType.GreenPendant) && _game.Items.Has(ItemType.Pendant, 2)) + { + // Basic Item Placement requires Book in logic + if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || + _game.Items.Has(ItemType.Book)) + return _game.Regions[RegionID.LightWorld].Accessibility; + + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); + } - return AccessibilityLevel.SequenceBreak; + if (_game.Items.Has(ItemType.Book)) + return AccessibilityLevel.Inspect; } - - if (_game.Items.Has(ItemType.Book)) - return AccessibilityLevel.Inspect; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.GreenPendant]); - itemReqs.Add(_game.Items[ItemType.Pendant]); - itemReqs.Add(_game.Items[ItemType.Book]); + _updateOnItemPlacementChange = true; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.GreenPendant, new Mode()); + _itemSubscriptions.Add(ItemType.Pendant, new Mode()); + _itemSubscriptions.Add(ItemType.Book, new Mode() { ItemPlacement = ItemPlacement.Basic }); break; case LocationID.LumberjackCave: @@ -116,196 +127,207 @@ public ItemSection(Game game, Location location, int index = 0) _baseTotal = 1; Name = "Cave"; HasMarking = true; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Aga) && _game.Items.Has(ItemType.Boots)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.Aga) && _game.Items.Has(ItemType.Boots) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.Inspect; }; - itemReqs.Add(_game.Items[ItemType.Aga]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Boots]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Aga, new Mode()); + _itemSubscriptions.Add(ItemType.Boots, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.BlindsHouse when index == 0: _baseTotal = 4; Name = "Main"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.BlindsHouse: _baseTotal = 1; Name = "Bomb"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.TheWell when index == 0: _baseTotal = 4; Name = "Cave"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => + { + if (_game.Mode.WorldState == WorldState.StandardOpen) + return _game.Regions[RegionID.LightWorld].Accessibility; + + if (_game.Mode.WorldState == WorldState.Inverted) + { + if (_game.Items.Has(ItemType.MoonPearl)) + return _game.Regions[RegionID.LightWorld].Accessibility; + } + + return AccessibilityLevel.None; + }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.TheWell: _baseTotal = 1; Name = "Bomb"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } - + return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.BottleVendor: _baseTotal = 1; Name = "This Jerk"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.ChickenHouse: _baseTotal = 1; Name = "Bombable Wall"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } - + return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.Tavern: _baseTotal = 1; Name = "Back Room"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.SickKid: _baseTotal = 1; Name = "By The Bed"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Items.Has(ItemType.Bottle)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Bottle]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Bottle, new Mode()); break; case LocationID.MagicBat: _baseTotal = 1; Name = "Magic Bowl"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { @@ -314,7 +336,7 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.Powder)) { if (_game.Items.Has(ItemType.Hammer)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Gloves, 2) && _game.Items.Has(ItemType.Mirror)) @@ -324,7 +346,10 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.Mushroom) && _game.Items.Has(ItemType.CaneOfSomaria)) { if (_game.Items.Has(ItemType.Hammer)) - return AccessibilityLevel.SequenceBreak; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); + } if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Gloves, 2) && _game.Items.Has(ItemType.Mirror)) @@ -337,23 +362,28 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Hammer)) { if (_game.Items.Has(ItemType.Powder)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Items.Has(ItemType.Mushroom) && _game.Items.Has(ItemType.CaneOfSomaria)) - return AccessibilityLevel.SequenceBreak; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); + } } } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Powder]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.Mushroom]); - itemReqs.Add(_game.Items[ItemType.CaneOfSomaria]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Powder, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mushroom, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfSomaria, new Mode()); break; case LocationID.RaceGame: @@ -361,8 +391,6 @@ public ItemSection(Game game, Location location, int index = 0) _baseTotal = 1; Name = "Take This Trash"; HasMarking = true; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { @@ -371,12 +399,21 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.RaceGameAccess)) return AccessibilityLevel.Normal; + AccessibilityLevel lightWorld = AccessibilityLevel.None; + AccessibilityLevel dWSouth = AccessibilityLevel.None; + if (!_game.Mode.EntranceShuffle.Value) - return AccessibilityLevel.Normal; + lightWorld = _game.Regions[RegionID.LightWorld].Accessibility; + else + { + lightWorld = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); + } - if (_game.Regions[RegionID.DarkWorldSouth].Accessibility >= AccessibilityLevel.SequenceBreak && - _game.Items.Has(ItemType.Mirror)) - return _game.Regions[RegionID.DarkWorldWest].Accessibility; + if (_game.Items.Has(ItemType.Mirror)) + dWSouth = _game.Regions[RegionID.DarkWorldWest].Accessibility; + + return (AccessibilityLevel)Math.Max((byte)lightWorld, (byte)dWSouth); } if (_game.Mode.WorldState == WorldState.Inverted) @@ -387,16 +424,22 @@ public ItemSection(Game game, Location location, int index = 0) return AccessibilityLevel.Normal; if (!_game.Mode.EntranceShuffle.Value) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; + + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); } } - return AccessibilityLevel.Inspect; + return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.RaceGameAccess]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode() { WorldState = WorldState.StandardOpen }); + + _itemSubscriptions.Add(ItemType.RaceGameAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); _game.Regions[RegionID.DarkWorldWest].PropertyChanged += OnRequirementChanged; @@ -406,28 +449,34 @@ public ItemSection(Game game, Location location, int index = 0) _baseTotal = 1; Name = "On The Shelf"; HasMarking = true; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Boots)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; + + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Boots)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; + + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); } - return AccessibilityLevel.Inspect; + return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Boots]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Boots, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.LostWoods when index == 0: @@ -435,140 +484,138 @@ public ItemSection(Game game, Location location, int index = 0) _baseTotal = 1; Name = "Shroom"; HasMarking = true; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } - return AccessibilityLevel.Inspect; + return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.LostWoods: _baseTotal = 1; Name = "Hideout"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - - GetAccessibility = () => { return AccessibilityLevel.Normal; }; RequiredMode = new Mode() { EntranceShuffle = false }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + break; case LocationID.CastleSecret when index == 0: _baseTotal = 1; Name = "Uncle"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.CastleSecret: _baseTotal = 1; Name = "Hallway"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } - + return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.LinksHouse: _baseTotal = 1; Name = "By The Door"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouth]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.LightWorld].Accessibility; }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); break; case LocationID.GroveDiggingSpot: _baseTotal = 1; Name = "Hidden Treasure"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Shovel)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Shovel)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Shovel]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Shovel, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.PyramidLedge: _baseTotal = 1; Name = "Ledge"; - _standardRegion = _game.Regions[RegionID.DarkWorldEast]; - _invertedRegion = _game.Regions[RegionID.DarkWorldEast]; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DarkWorldEast].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DarkWorldEast, new Mode()); break; case LocationID.FatFairy: _baseTotal = 2; Name = "Big Bomb Spot"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouth]; GetAccessibility = () => { @@ -577,26 +624,29 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.RedCrystal, 2)) { if (_game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.Gloves)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Items.Has(ItemType.Aga)) { if (_game.Items.Has(ItemType.Hammer)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Items.Has(ItemType.Mirror)) { if (_game.Items.Has(ItemType.Gloves, 2)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Items.Has(ItemType.Hookshot) && (_game.Items.Has(ItemType.Flippers) || _game.Items.Has(ItemType.Gloves))) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } } if (_game.Items.Has(ItemType.Gloves, 2)) - return AccessibilityLevel.SequenceBreak; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); + } } } @@ -609,59 +659,64 @@ public ItemSection(Game game, Location location, int index = 0) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.RedCrystal]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Aga]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.Hookshot]); - itemReqs.Add(_game.Items[ItemType.Flippers]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); - _game.Regions[RegionID.LightWorld].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.RedCrystal, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Aga, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode()); + _itemSubscriptions.Add(ItemType.Hookshot, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Flippers, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.HauntedGrove: _baseTotal = 1; Name = "Stumpy"; - _standardRegion = _game.Regions[RegionID.DarkWorldSouth]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouth]; GetAccessibility = () => { - if (_game.Mode.WorldState == WorldState.Inverted || - _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + if (_game.Mode.WorldState == WorldState.StandardOpen) + { + if (_game.Items.Has(ItemType.MoonPearl)) + return _game.Regions[RegionID.DarkWorldSouth].Accessibility; + } + + if (_game.Mode.WorldState == WorldState.Inverted) + return _game.Regions[RegionID.DarkWorldSouth].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.HypeCave: _baseTotal = 5; Name = "Cave"; - _standardRegion = _game.Regions[RegionID.DarkWorldSouth]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouth]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouth].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouth].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.BombosTablet: @@ -669,8 +724,6 @@ public ItemSection(Game game, Location location, int index = 0) _baseTotal = 1; Name = "Tablet"; HasMarking = true; - _standardRegion = _game.Regions[RegionID.DarkWorldSouth]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { @@ -679,9 +732,10 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.Book) && _game.Items.Has(ItemType.Mirror)) { if (_game.Items.CanActivateTablets()) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouth].Accessibility; - return AccessibilityLevel.Inspect; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.DarkWorldSouth].Accessibility); } } @@ -690,116 +744,120 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.Book)) { if (_game.Items.CanActivateTablets()) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; - return AccessibilityLevel.Inspect; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); } } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Book]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.Sword]); - itemReqs.Add(_game.Items[ItemType.Hammer]); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode() { WorldState = WorldState.StandardOpen }); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); + + _itemSubscriptions.Add(ItemType.Book, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); break; case LocationID.SouthOfGrove: _baseTotal = 1; Name = "Circle of Bushes"; - _standardRegion = _game.Regions[RegionID.DarkWorldSouth]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Mirror)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouth].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode() { WorldState = WorldState.StandardOpen }); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); + + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.DiggingGame: _baseTotal = 1; Name = "Dig For Treasure"; - _standardRegion = _game.Regions[RegionID.DarkWorldSouth]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouth]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouth].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldSouth].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.WitchsHut: _baseTotal = 1; Name = "Assistant"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Mushroom)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Mushroom)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Mushroom]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Mushroom, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.WaterfallFairy: _baseTotal = 2; Name = "Waterfall Cave"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Flippers)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); } if (_game.Mode.WorldState == WorldState.Inverted) @@ -807,34 +865,36 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.MoonPearl)) { if (_game.Items.Has(ItemType.Flippers)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); } } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Flippers]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Flippers, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.ZoraArea when index == 0: _baseTotal = 1; Name = "King Zora"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Gloves) || _game.Items.Has(ItemType.Flippers)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); } if (_game.Mode.WorldState == WorldState.Inverted) @@ -842,18 +902,21 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.MoonPearl)) { if (_game.Items.Has(ItemType.Gloves) || _game.Items.Has(ItemType.Flippers)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); } } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Flippers]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.Flippers, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.ZoraArea: @@ -861,17 +924,16 @@ public ItemSection(Game game, Location location, int index = 0) _baseTotal = 1; Name = "Ledge"; HasMarking = true; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Flippers)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); } if (_game.Mode.WorldState == WorldState.Inverted) @@ -879,123 +941,124 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.MoonPearl)) { if (_game.Items.Has(ItemType.Flippers)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); } } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Flippers]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Flippers, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.Catfish: _baseTotal = 1; Name = "Ring of Stones"; - _standardRegion = _game.Regions[RegionID.DarkWorldEast]; - _invertedRegion = _game.Regions[RegionID.DarkWorldEast]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Gloves) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldEast].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.Gloves)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkWorldEast].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldEast, new Mode()); + + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.SahasrahlasHut when index == 0: _baseTotal = 3; Name = "Back Room"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.SahasrahlasHut: _baseTotal = 1; Name = "Shabba"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Items.Has(ItemType.GreenPendant)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.GreenPendant]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.GreenPendant, new Mode()); break; case LocationID.BonkRocks: _baseTotal = 1; Name = "Cave"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Boots)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.Boots) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Boots]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Boots, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.KingsTomb: _baseTotal = 1; Name = "The Crypt"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { @@ -1003,11 +1066,16 @@ public ItemSection(Game game, Location location, int index = 0) { if (_game.Items.Has(ItemType.Boots)) { + AccessibilityLevel direct = AccessibilityLevel.None; + AccessibilityLevel mirror = AccessibilityLevel.None; + if (_game.Items.Has(ItemType.Gloves, 2)) - return AccessibilityLevel.Normal; + direct = _game.Regions[RegionID.LightWorld].Accessibility; - if (_game.Items.Has(ItemType.Mirror)) - return _game.Regions[RegionID.DarkWorldWest].Accessibility; + if (_game.Items.Has(ItemType.Mirror) && _game.Items.Has(ItemType.MoonPearl)) + mirror = _game.Regions[RegionID.DarkWorldWest].Accessibility; + + return (AccessibilityLevel)Math.Max((byte)direct, (byte)mirror); } } @@ -1021,40 +1089,42 @@ public ItemSection(Game game, Location location, int index = 0) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Boots]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode() { WorldState = WorldState.StandardOpen }); - _game.Regions[RegionID.DarkWorldWest].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.Boots, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode()); break; case LocationID.GraveyardLedge: _baseTotal = 1; Name = "Cave"; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { - if (_game.Items.Has(ItemType.Mirror)) - return AccessibilityLevel.Normal; + if (_game.Items.Has(ItemType.Mirror) && _game.Items.Has(ItemType.MoonPearl)) + return _game.Regions[RegionID.DarkWorldWest].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode() { WorldState = WorldState.StandardOpen }); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); + + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode()); break; case LocationID.DesertLedge: @@ -1062,8 +1132,6 @@ public ItemSection(Game game, Location location, int index = 0) _baseTotal = 1; Name = "Ledge"; HasMarking = true; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { @@ -1075,12 +1143,19 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.DesertBackAccess) && _game.Items.Has(ItemType.Gloves)) return AccessibilityLevel.Normal; + AccessibilityLevel lightWorld = AccessibilityLevel.None; + AccessibilityLevel mireArea = AccessibilityLevel.None; + if (!_game.Mode.EntranceShuffle.Value && _game.Items.Has(ItemType.Book)) - return AccessibilityLevel.Normal; + lightWorld = _game.Regions[RegionID.LightWorld].Accessibility; + else + lightWorld = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); - if (_game.Regions[RegionID.MireArea].Accessibility >= AccessibilityLevel.SequenceBreak && - _game.Items.Has(ItemType.Mirror)) - return _game.Regions[RegionID.MireArea].Accessibility; + if (_game.Items.Has(ItemType.Mirror)) + mireArea = _game.Regions[RegionID.MireArea].Accessibility; + + return (AccessibilityLevel)Math.Max((byte)lightWorld, (byte)mireArea); } if (_game.Mode.WorldState == WorldState.Inverted) @@ -1091,178 +1166,271 @@ public ItemSection(Game game, Location location, int index = 0) return AccessibilityLevel.Normal; if (!_game.Mode.EntranceShuffle.Value && _game.Items.Has(ItemType.Book)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } + + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); } - return AccessibilityLevel.Inspect; + return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DesertLeftAccess]); - itemReqs.Add(_game.Items[ItemType.DesertBackAccess]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Book]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + _regionSubscriptions.Add(RegionID.MireArea, new Mode() { WorldState = WorldState.StandardOpen }); - _game.Regions[RegionID.MireArea].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.DesertLeftAccess, new Mode()); + _itemSubscriptions.Add(ItemType.DesertBackAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.Book, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.AginahsCave: _baseTotal = 1; Name = "Cave"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; - - GetAccessibility = () => { return AccessibilityLevel.Normal; }; - - break; - case LocationID.CShapedHouse: - _baseTotal = 1; - Name = "House"; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; - - GetAccessibility = () => { return AccessibilityLevel.Normal; }; - - break; - case LocationID.TreasureGame: - - _baseTotal = 1; - Name = "Prize"; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; + GetAccessibility = () => + { + if (_game.Mode.WorldState == WorldState.StandardOpen) + return _game.Regions[RegionID.LightWorld].Accessibility; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + if (_game.Mode.WorldState == WorldState.Inverted) + { + if (_game.Items.Has(ItemType.MoonPearl)) + return _game.Regions[RegionID.LightWorld].Accessibility; + } - break; - case LocationID.BombableShack: + return AccessibilityLevel.None; + }; - _baseTotal = 1; - Name = "Downstairs"; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; - case LocationID.Blacksmith: + case LocationID.CShapedHouse: _baseTotal = 1; Name = "House"; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { - if (_game.Items.Has(ItemType.Gloves, 2)) - { - if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Items.Has(ItemType.Mirror)) - return AccessibilityLevel.Normal; - - return AccessibilityLevel.SequenceBreak; - } + if (_game.Items.Has(ItemType.MoonPearl)) + return _game.Regions[RegionID.DarkWorldWest].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) - { - if (_game.Items.Has(ItemType.Gloves, 2)) - return AccessibilityLevel.Normal; - - if (_game.Items.Has(ItemType.Mirror)) - return _game.Regions[RegionID.LightWorld].Accessibility; - } + return _game.Regions[RegionID.DarkWorldWest].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); - _game.Regions[RegionID.LightWorld].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); break; - case LocationID.PurpleChest: + case LocationID.TreasureGame: _baseTotal = 1; - Name = "Show To Gary"; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; + Name = "Prize"; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { - if (_game.Items.Has(ItemType.Gloves, 2)) - return AccessibilityLevel.Normal; - } + if (_game.Items.Has(ItemType.MoonPearl)) + return _game.Regions[RegionID.DarkWorldWest].Accessibility; + } + + if (_game.Mode.WorldState == WorldState.Inverted) + return _game.Regions[RegionID.DarkWorldWest].Accessibility; + + return AccessibilityLevel.None; + }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + + break; + case LocationID.BombableShack: + + _baseTotal = 1; + Name = "Downstairs"; + + GetAccessibility = () => + { + if (_game.Mode.WorldState == WorldState.StandardOpen) + { + if (_game.Items.Has(ItemType.MoonPearl)) + return _game.Regions[RegionID.DarkWorldWest].Accessibility; + } + + if (_game.Mode.WorldState == WorldState.Inverted) + return _game.Regions[RegionID.DarkWorldWest].Accessibility; + + return AccessibilityLevel.None; + }; + + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + + break; + case LocationID.Blacksmith: + + _baseTotal = 1; + Name = "House"; + + GetAccessibility = () => + { + if (_game.Mode.WorldState == WorldState.StandardOpen) + { + if (_game.Items.Has(ItemType.Gloves, 2) && _game.Items.Has(ItemType.MoonPearl)) + { + AccessibilityLevel dWWest = AccessibilityLevel.None; + AccessibilityLevel lightWorld = _game.Regions[RegionID.LightWorld].Accessibility; + + if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || + _game.Items.Has(ItemType.Mirror)) + dWWest = _game.Regions[RegionID.DarkWorldWest].Accessibility; + + dWWest = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DarkWorldWest].Accessibility); + + return (AccessibilityLevel)Math.Min((byte)dWWest, (byte)lightWorld); + } + } if (_game.Mode.WorldState == WorldState.Inverted) { + AccessibilityLevel lightWorld = _game.Regions[RegionID.LightWorld].Accessibility; + AccessibilityLevel dWWest = AccessibilityLevel.None; + + if (_game.Items.Has(ItemType.Mirror)) + return lightWorld; + if (_game.Items.Has(ItemType.Gloves, 2)) - return AccessibilityLevel.Normal; + { + dWWest = _game.Regions[RegionID.DarkWorldWest].Accessibility; + + return (AccessibilityLevel)Math.Min((byte)lightWorld, (byte)dWWest); + } + } + + return AccessibilityLevel.None; + }; + + _updateOnItemPlacementChange = true; + + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode()); + + break; + case LocationID.PurpleChest: + + _baseTotal = 1; + Name = "Show To Gary"; + + GetAccessibility = () => + { + if (_game.Mode.WorldState == WorldState.StandardOpen) + { + if (_game.Items.Has(ItemType.Gloves, 2) && _game.Items.Has(ItemType.MoonPearl)) + { + AccessibilityLevel dWWest = AccessibilityLevel.None; + AccessibilityLevel lightWorld = _game.Regions[RegionID.LightWorld].Accessibility; + + dWWest = _game.Regions[RegionID.DarkWorldWest].Accessibility; + + return (AccessibilityLevel)Math.Min((byte)dWWest, (byte)lightWorld); + } + } + + if (_game.Mode.WorldState == WorldState.Inverted) + { + AccessibilityLevel lightWorld = _game.Regions[RegionID.LightWorld].Accessibility; + AccessibilityLevel dWWest = AccessibilityLevel.None; if (_game.Items.Has(ItemType.Mirror)) - return _game.Regions[RegionID.LightWorld].Accessibility; + return lightWorld; + + if (_game.Items.Has(ItemType.Gloves, 2)) + { + dWWest = _game.Regions[RegionID.DarkWorldWest].Accessibility; + + return (AccessibilityLevel)Math.Min((byte)lightWorld, (byte)dWWest); + } } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); - _game.Regions[RegionID.LightWorld].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode()); break; case LocationID.HammerPegs: _baseTotal = 1; Name = "Cave"; - _standardRegion = _game.Regions[RegionID.DarkWorldWest]; - _invertedRegion = _game.Regions[RegionID.DarkWorldWest]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { - if (_game.Items.Has(ItemType.Gloves, 2) && _game.Items.Has(ItemType.Hammer)) - return AccessibilityLevel.Normal; + if (_game.Items.Has(ItemType.Gloves, 2) && _game.Items.Has(ItemType.Hammer) && + _game.Items.Has(ItemType.MoonPearl)) + return _game.Regions[RegionID.DarkWorldWest].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.Hammer)) { + AccessibilityLevel dWWest = AccessibilityLevel.None; + AccessibilityLevel lightWorld = AccessibilityLevel.None; + if (_game.Items.Has(ItemType.Gloves, 2)) - return AccessibilityLevel.Normal; + dWWest = _game.Regions[RegionID.DarkWorldWest].Accessibility; if (_game.Items.Has(ItemType.Mirror)) - return _game.Regions[RegionID.LightWorld].Accessibility; + lightWorld = _game.Regions[RegionID.LightWorld].Accessibility; + + return (AccessibilityLevel)Math.Max((byte)dWWest, (byte)lightWorld); } } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); - _game.Regions[RegionID.LightWorld].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.BumperCave: _baseTotal = 1; Name = "Ledge"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouth]; HasMarking = true; GetAccessibility = () => @@ -1272,24 +1440,27 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Mode.WorldState == WorldState.StandardOpen) { - AccessibilityLevel dWWest = _game.Regions[RegionID.DarkWorldWest].Accessibility; + AccessibilityLevel dWWest = AccessibilityLevel.None; + AccessibilityLevel inspect = AccessibilityLevel.None; - if (dWWest >= AccessibilityLevel.SequenceBreak) + if (!_game.Mode.EntranceShuffle.Value) { - if (!_game.Mode.EntranceShuffle.Value) + if (_game.Items.Has(ItemType.Gloves) && _game.Items.Has(ItemType.Cape) && + _game.Items.Has(ItemType.MoonPearl)) { - if (_game.Items.Has(ItemType.Gloves) && _game.Items.Has(ItemType.Cape)) - { - if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Items.Has(ItemType.Hookshot)) - return dWWest; - - return (AccessibilityLevel)Math.Min((byte)dWWest, (byte)AccessibilityLevel.SequenceBreak); - } + if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || + _game.Items.Has(ItemType.Hookshot)) + dWWest = _game.Regions[RegionID.DarkWorldWest].Accessibility; + else + dWWest = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DarkWorldWest].Accessibility); } - - return AccessibilityLevel.Inspect; } + + inspect = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.DarkWorldWest].Accessibility); + + return (AccessibilityLevel)Math.Max((byte)dWWest, (byte)inspect); } if (_game.Mode.WorldState == WorldState.Inverted) @@ -1297,27 +1468,34 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.DeathMountainExitAccess) && _game.Items.Has(ItemType.Mirror)) return AccessibilityLevel.Normal; - AccessibilityLevel lightWorld = _game.Regions[RegionID.LightWorld].Accessibility; + AccessibilityLevel lightWorld = AccessibilityLevel.None; + AccessibilityLevel dWWest = AccessibilityLevel.None; if (!_game.Mode.EntranceShuffle.Value && _game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Cape) && _game.Items.Has(ItemType.Gloves) && - _game.Items.Has(ItemType.Mirror) && lightWorld >= AccessibilityLevel.SequenceBreak) - return (AccessibilityLevel)Math.Min((byte)lightWorld, (byte)AccessibilityLevel.Normal); + _game.Items.Has(ItemType.Mirror)) + lightWorld = _game.Regions[RegionID.LightWorld].Accessibility; + + dWWest = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.DarkWorldWest].Accessibility); - if (_game.Regions[RegionID.DarkWorldWest].Accessibility >= AccessibilityLevel.SequenceBreak) - return AccessibilityLevel.Inspect; + return (AccessibilityLevel)Math.Max((byte)lightWorld, (byte)dWWest); } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.BumperCaveAccess]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Cape]); - itemReqs.Add(_game.Items[ItemType.Hookshot]); - itemReqs.Add(_game.Items[ItemType.DeathMountainExitAccess]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _updateOnItemPlacementChange = true; + + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); + + _itemSubscriptions.Add(ItemType.BumperCaveAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.Cape, new Mode()); + _itemSubscriptions.Add(ItemType.Hookshot, new Mode() { ItemPlacement = ItemPlacement.Advanced }); + _itemSubscriptions.Add(ItemType.DeathMountainExitAccess, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode()); _game.Regions[RegionID.DarkWorldWest].PropertyChanged += OnRequirementChanged; @@ -1326,97 +1504,97 @@ public ItemSection(Game game, Location location, int index = 0) _baseTotal = 1; Name = "Inside"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; RequiredMode = new Mode() { EntranceShuffle = false }; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.Dam: _baseTotal = 1; Name = "Outside"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.MiniMoldormCave: _baseTotal = 5; Name = "Cave"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.IceRodCave: _baseTotal = 1; Name = "Cave"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.LakeHyliaIsland: @@ -1424,65 +1602,80 @@ public ItemSection(Game game, Location location, int index = 0) _baseTotal = 1; Name = "Island"; HasMarking = true; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { + AccessibilityLevel lightWorld = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); + AccessibilityLevel dWEast = AccessibilityLevel.None; + AccessibilityLevel dWSouth = AccessibilityLevel.None; + AccessibilityLevel dWSouthEast = AccessibilityLevel.None; + if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Mirror)) { - if (_game.Regions[RegionID.DarkWorldEast].Accessibility == AccessibilityLevel.Normal || - _game.Regions[RegionID.DarkWorldSouth].Accessibility == AccessibilityLevel.Normal || - _game.Regions[RegionID.DarkWorldSouthEast].Accessibility == AccessibilityLevel.Normal) + if (_game.Items.Has(ItemType.Flippers)) { - if (_game.Items.Has(ItemType.Flippers)) - return AccessibilityLevel.Normal; - - return AccessibilityLevel.SequenceBreak; + dWEast = _game.Regions[RegionID.DarkWorldWest].Accessibility; + dWSouth = _game.Regions[RegionID.DarkWorldSouth].Accessibility; + dWSouthEast = _game.Regions[RegionID.DarkWorldSouthEast].Accessibility; + } + else + { + dWEast = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DarkWorldWest].Accessibility); + dWSouth = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DarkWorldSouth].Accessibility); + dWSouthEast = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DarkWorldSouthEast].Accessibility); } - - if (_game.Regions[RegionID.DarkWorldEast].Accessibility == AccessibilityLevel.SequenceBreak || - _game.Regions[RegionID.DarkWorldSouth].Accessibility == AccessibilityLevel.SequenceBreak || - _game.Regions[RegionID.DarkWorldSouthEast].Accessibility == AccessibilityLevel.SequenceBreak) - return AccessibilityLevel.SequenceBreak; } + + return (AccessibilityLevel)Math.Max(Math.Max(Math.Max((byte)lightWorld, (byte)dWEast), + (byte)dWSouth), (byte)dWSouthEast); } if (_game.Mode.WorldState == WorldState.Inverted) { - if (_game.Items.Has(ItemType.Flippers) && _game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + if (_game.Items.Has(ItemType.MoonPearl)) + { + if (_game.Items.Has(ItemType.Flippers)) + return _game.Regions[RegionID.LightWorld].Accessibility; + + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); + + } } return AccessibilityLevel.Inspect; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.Flippers]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + _regionSubscriptions.Add(RegionID.DarkWorldEast, new Mode() { WorldState = WorldState.StandardOpen }); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode() { WorldState = WorldState.StandardOpen }); + _regionSubscriptions.Add(RegionID.DarkWorldSouthEast, new Mode() { WorldState = WorldState.StandardOpen }); - _game.Regions[RegionID.DarkWorldEast].PropertyChanged += OnRequirementChanged; - _game.Regions[RegionID.DarkWorldSouth].PropertyChanged += OnRequirementChanged; - _game.Regions[RegionID.DarkWorldSouthEast].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Flippers, new Mode()); break; case LocationID.Hobo: _baseTotal = 1; Name = "Under The Bridge"; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.Flippers)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); } if (_game.Mode.WorldState == WorldState.Inverted) @@ -1490,137 +1683,149 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.MoonPearl)) { if (_game.Items.Has(ItemType.Flippers)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.LightWorld].Accessibility); } } return AccessibilityLevel.SequenceBreak; }; - itemReqs.Add(_game.Items[ItemType.Flippers]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode()); + + _itemSubscriptions.Add(ItemType.Flippers, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.MireShack: _baseTotal = 2; Name = "Shack"; - _standardRegion = _game.Regions[RegionID.MireArea]; - _invertedRegion = _game.Regions[RegionID.MireArea]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.MireArea].Accessibility; if (_game.Items.Has(ItemType.Mirror)) - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.MireArea].Accessibility); } if (_game.Mode.WorldState == WorldState.Inverted) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.MireArea].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.MireArea, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.CheckerboardCave: _baseTotal = 1; Name = "Cave"; - _standardRegion = _game.Regions[RegionID.MireArea]; - _invertedRegion = _game.Regions[RegionID.LightWorld]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { - if (_game.Items.Has(ItemType.Mirror)) - return AccessibilityLevel.Normal; + if (_game.Items.Has(ItemType.Mirror) && _game.Items.Has(ItemType.Gloves)) + return _game.Regions[RegionID.MireArea].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.Gloves)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.LightWorld].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.Gloves]); + _regionSubscriptions.Add(RegionID.MireArea, new Mode() { WorldState = WorldState.StandardOpen }); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); + + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); break; case LocationID.OldMan: _baseTotal = 1; Name = "Bring Him Home"; - _standardRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - _invertedRegion = _game.Regions[RegionID.DeathMountainWestBottom]; GetAccessibility = () => { if (_game.Items.Has(ItemType.Lamp)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DeathMountainWestBottom].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DeathMountainWestBottom].Accessibility); }; - itemReqs.Add(_game.Items[ItemType.Lamp]); + _regionSubscriptions.Add(RegionID.DeathMountainWestBottom, new Mode()); + + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); break; case LocationID.SpectacleRock when index == 0: _baseTotal = 1; Name = "Cave"; - _standardRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - _invertedRegion = _game.Regions[RegionID.DeathMountainWestBottom]; + RequiredMode = new Mode() { EntranceShuffle = false }; - GetAccessibility = () => { return AccessibilityLevel.Normal; }; + GetAccessibility = () => { return _game.Regions[RegionID.DeathMountainWestBottom].Accessibility; }; + + _regionSubscriptions.Add(RegionID.DeathMountainWestBottom, new Mode()); break; case LocationID.SpectacleRock: _baseTotal = 1; Name = "Up On Top"; - _standardRegion = _game.Regions[RegionID.DeathMountainWestBottom]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouth]; HasMarking = true; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { + AccessibilityLevel dMWestBottom = AccessibilityLevel.None; + AccessibilityLevel inspect = AccessibilityLevel.None; + if (_game.Items.Has(ItemType.Mirror)) - return AccessibilityLevel.Normal; + dMWestBottom = _game.Regions[RegionID.DeathMountainWestBottom].Accessibility; + + inspect = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.DeathMountainWestBottom].Accessibility); - return AccessibilityLevel.Inspect; + return (AccessibilityLevel)Math.Max((byte)dMWestBottom, (byte)inspect); } if (_game.Mode.WorldState == WorldState.Inverted) { - if (_game.Regions[RegionID.DeathMountainWestTop].Accessibility >= AccessibilityLevel.SequenceBreak) - return _game.Regions[RegionID.DeathMountainWestTop].Accessibility; + AccessibilityLevel dMWestTop = _game.Regions[RegionID.DeathMountainWestTop].Accessibility; + AccessibilityLevel inspect = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.DeathMountainWestBottom].Accessibility); - if (_game.Regions[RegionID.DeathMountainWestBottom].Accessibility >= AccessibilityLevel.SequenceBreak) - return AccessibilityLevel.Inspect; + return (AccessibilityLevel)Math.Max((byte)dMWestTop, (byte)inspect); } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DeathMountainWestBottom, new Mode()); + _regionSubscriptions.Add(RegionID.DeathMountainWestTop, new Mode() { WorldState = WorldState.Inverted }); - _game.Regions[RegionID.DeathMountainWestTop].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.EtherTablet: @@ -1628,33 +1833,37 @@ public ItemSection(Game game, Location location, int index = 0) _baseTotal = 1; Name = "Tablet"; HasMarking = true; - _standardRegion = _game.Regions[RegionID.DeathMountainWestTop]; - _invertedRegion = _game.Regions[RegionID.DeathMountainWestTop]; GetAccessibility = () => { + AccessibilityLevel dMWestTop = AccessibilityLevel.None; + AccessibilityLevel inspect = AccessibilityLevel.None; + if (_game.Items.Has(ItemType.Book)) { if (_game.Items.CanActivateTablets()) - return AccessibilityLevel.Normal; + dMWestTop = _game.Regions[RegionID.DeathMountainWestTop].Accessibility; - return AccessibilityLevel.Inspect; + inspect = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.DeathMountainWestTop].Accessibility); + + return (AccessibilityLevel)Math.Max((byte)dMWestTop, (byte)inspect); } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Book]); - itemReqs.Add(_game.Items[ItemType.Sword]); - itemReqs.Add(_game.Items[ItemType.Hammer]); + _regionSubscriptions.Add(RegionID.DeathMountainWestTop, new Mode()); + + _itemSubscriptions.Add(ItemType.Book, new Mode()); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); break; case LocationID.SpikeCave: _baseTotal = 1; Name = "Cave"; - _standardRegion = _game.Regions[RegionID.DarkDeathMountainWestBottom]; - _invertedRegion = _game.Regions[RegionID.DarkDeathMountainWestBottom]; GetAccessibility = () => { @@ -1665,9 +1874,10 @@ public ItemSection(Game game, Location location, int index = 0) { if (_game.Items.Has(ItemType.CaneOfByrna) || (_game.Items.Has(ItemType.Cape) && (_game.Items.Has(ItemType.HalfMagic) || _game.Items.Has(ItemType.Bottle)))) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkDeathMountainWestBottom].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DarkDeathMountainWestBottom].Accessibility); } } @@ -1677,132 +1887,130 @@ public ItemSection(Game game, Location location, int index = 0) { if (_game.Items.Has(ItemType.CaneOfByrna) || (_game.Items.Has(ItemType.Cape) && (_game.Items.Has(ItemType.HalfMagic) || _game.Items.Has(ItemType.Bottle)))) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkDeathMountainWestBottom].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DarkDeathMountainWestBottom].Accessibility); } } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.CaneOfByrna]); - itemReqs.Add(_game.Items[ItemType.Cape]); - itemReqs.Add(_game.Items[ItemType.HalfMagic]); - itemReqs.Add(_game.Items[ItemType.Bottle]); + _regionSubscriptions.Add(RegionID.DarkDeathMountainWestBottom, new Mode()); + + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.CaneOfByrna, new Mode()); + _itemSubscriptions.Add(ItemType.Cape, new Mode()); + _itemSubscriptions.Add(ItemType.HalfMagic, new Mode()); + _itemSubscriptions.Add(ItemType.Bottle, new Mode()); break; case LocationID.SpiralCave: _baseTotal = 1; Name = "Cave"; - _standardRegion = _game.Regions[RegionID.DeathMountainEastTop]; - _invertedRegion = _game.Regions[RegionID.DeathMountainEastTop]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.ParadoxCave when index == 0: _baseTotal = 2; Name = "Bottom"; - _standardRegion = _game.Regions[RegionID.DeathMountainEastTop]; - _invertedRegion = _game.Regions[RegionID.DeathMountainEastTop]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; - - return AccessibilityLevel.SequenceBreak; + return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.ParadoxCave: _baseTotal = 5; Name = "Top"; - _standardRegion = _game.Regions[RegionID.DeathMountainEastTop]; - _invertedRegion = _game.Regions[RegionID.DeathMountainEastTop]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; - - return AccessibilityLevel.SequenceBreak; + return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.SuperBunnyCave: _baseTotal = 2; Name = "Cave"; - _standardRegion = _game.Regions[RegionID.DarkDeathMountainTop]; - _invertedRegion = _game.Regions[RegionID.DarkDeathMountainTop]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { if (_game.Items.Has(ItemType.MoonPearl)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkDeathMountainTop].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DarkDeathMountainTop].Accessibility); } if (_game.Mode.WorldState == WorldState.Inverted) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkDeathMountainTop].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.HookshotCave when index == 0: _baseTotal = 1; Name = "Bonkable Chest"; - _standardRegion = _game.Regions[RegionID.DarkDeathMountainTop]; - _invertedRegion = _game.Regions[RegionID.DarkDeathMountainTop]; GetAccessibility = () => { @@ -1813,10 +2021,13 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.Hookshot) || (_game.Items.Has(ItemType.Boots) && (_game.Mode.ItemPlacement == ItemPlacement.Advanced))) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkDeathMountainTop].Accessibility; if (_game.Items.Has(ItemType.Boots)) - return AccessibilityLevel.SequenceBreak; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DarkDeathMountainTop].Accessibility); + } } } @@ -1824,24 +2035,26 @@ public ItemSection(Game game, Location location, int index = 0) { if (_game.Items.Has(ItemType.Gloves) && (_game.Items.Has(ItemType.Hookshot) || _game.Items.Has(ItemType.Boots))) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkDeathMountainTop].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Hookshot]); - itemReqs.Add(_game.Items[ItemType.Boots]); + _updateOnItemPlacementChange = true; + + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode()); + + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.Hookshot, new Mode()); + _itemSubscriptions.Add(ItemType.Boots, new Mode()); break; case LocationID.HookshotCave: _baseTotal = 3; Name = "Back"; - _standardRegion = _game.Regions[RegionID.DarkDeathMountainTop]; - _invertedRegion = _game.Regions[RegionID.DarkDeathMountainTop]; GetAccessibility = () => { @@ -1849,21 +2062,23 @@ public ItemSection(Game game, Location location, int index = 0) { if (_game.Items.Has(ItemType.Gloves) && _game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Hookshot)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkDeathMountainTop].Accessibility; } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.Gloves) && _game.Items.Has(ItemType.Hookshot)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DarkDeathMountainTop].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Hookshot]); + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode()); + + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Hookshot, new Mode()); break; case LocationID.FloatingIsland: @@ -1871,52 +2086,49 @@ public ItemSection(Game game, Location location, int index = 0) _baseTotal = 1; Name = "Island"; HasMarking = true; - _standardRegion = _game.Regions[RegionID.LightWorld]; - _invertedRegion = _game.Regions[RegionID.DarkWorldSouth]; GetAccessibility = () => { if (_game.Mode.WorldState == WorldState.StandardOpen) { + AccessibilityLevel dDMTop = AccessibilityLevel.None; + AccessibilityLevel inspect = AccessibilityLevel.None; + if (_game.Items.Has(ItemType.Mirror)) { if (_game.Items.Has(ItemType.DarkDeathMountainFloatingIslandAccess)) return AccessibilityLevel.Normal; if (!_game.Mode.EntranceShuffle.Value && _game.Items.Has(ItemType.Gloves) && - _game.Items.Has(ItemType.MoonPearl) && - _game.Regions[RegionID.DarkDeathMountainTop].Accessibility >= AccessibilityLevel.SequenceBreak) - return _game.Regions[RegionID.DarkDeathMountainTop].Accessibility; + _game.Items.Has(ItemType.MoonPearl)) + dDMTop = _game.Regions[RegionID.DarkDeathMountainTop].Accessibility; } + + inspect = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Inspect, + (byte)_game.Regions[RegionID.DeathMountainEastTop].Accessibility); - if (_game.Regions[RegionID.DeathMountainEastTop].Accessibility >= AccessibilityLevel.SequenceBreak) - return AccessibilityLevel.Inspect; + return (AccessibilityLevel)Math.Max((byte)dDMTop, (byte)inspect); } if (_game.Mode.WorldState == WorldState.Inverted) - { - if (_game.Regions[RegionID.DeathMountainEastTop].Accessibility >= AccessibilityLevel.SequenceBreak) - return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; - } + return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.DarkDeathMountainFloatingIslandAccess]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode() { WorldState = WorldState.StandardOpen }); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode()); - _game.Regions[RegionID.DarkDeathMountainTop].PropertyChanged += OnRequirementChanged; - _game.Regions[RegionID.DeathMountainEastTop].PropertyChanged += OnRequirementChanged; + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.DarkDeathMountainFloatingIslandAccess, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); break; case LocationID.MimicCave: _baseTotal = 1; Name = "Cave"; - _standardRegion = _game.Regions[RegionID.TurtleRock]; - _invertedRegion = _game.Regions[RegionID.DeathMountainEastTop]; GetAccessibility = () => { @@ -1928,27 +2140,37 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.TRSmallKey, 2) && (_game.Mode.DungeonItemShuffle.Value >= DungeonItemShuffle.MapsCompassesSmallKeys || _game.Items.Has(ItemType.FireRod))) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.TurtleRock].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.TurtleRock].Accessibility); } } if (_game.Mode.WorldState == WorldState.Inverted) { if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Hammer)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.CaneOfSomaria]); - itemReqs.Add(_game.Items[ItemType.TRSmallKey]); - itemReqs.Add(_game.Items[ItemType.FireRod]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _updateOnDungeonItemShuffleChange = true; + + _regionSubscriptions.Add(RegionID.TurtleRock, new Mode() { WorldState = WorldState.StandardOpen }); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode() { WorldState = WorldState.Inverted }); + + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfSomaria, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.TRSmallKey, new Mode() + { + WorldState = WorldState.StandardOpen, + DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys + }); + _itemSubscriptions.Add(ItemType.FireRod, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case LocationID.HyruleCastle: @@ -1957,40 +2179,54 @@ public ItemSection(Game game, Location location, int index = 0) _smallKey = 1; _baseTotal = 6; Name = "Escape"; - _standardRegion = _game.Regions[RegionID.HyruleCastle]; - _invertedRegion = _game.Regions[RegionID.HyruleCastle]; GetAccessibility = () => { - if (_game.Mode.WorldState == WorldState.StandardOpen) + switch (_game.Mode.DungeonItemShuffle.Value) { - if (_game.Items.Has(ItemType.Gloves) || (_game.Items.Has(ItemType.HCSmallKey) && - _game.Mode.DungeonItemShuffle >= DungeonItemShuffle.MapsCompassesSmallKeys)) - { - if (_game.Items.Has(ItemType.Lamp) || - (_game.Mode.ItemPlacement.Value == ItemPlacement.Advanced && - _game.Items.Has(ItemType.FireRod))) - return AccessibilityLevel.Normal; - } - } + case DungeonItemShuffle.Standard: + case DungeonItemShuffle.MapsCompasses: - if (_game.Mode.WorldState == WorldState.Inverted) - { - if (_game.Items.Has(ItemType.Gloves) || (_game.Items.Has(ItemType.HCSmallKey) && - _game.Mode.DungeonItemShuffle >= DungeonItemShuffle.MapsCompassesSmallKeys)) - { - if (_game.Items.Has(ItemType.Lamp)) - return AccessibilityLevel.Normal; - } + if (_game.Items.Has(ItemType.Gloves) && (_game.Items.Has(ItemType.Lamp) || + (_game.Mode.ItemPlacement == ItemPlacement.Advanced && + _game.Items.Has(ItemType.FireRod)))) + return _game.Regions[RegionID.HyruleCastle].Accessibility; + + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.HyruleCastle].Accessibility); + + case DungeonItemShuffle.MapsCompassesSmallKeys: + case DungeonItemShuffle.Keysanity: + + if (_game.Items.Has(ItemType.Gloves) || _game.Items.Has(ItemType.HCSmallKey)) + { + if (_game.Items.Has(ItemType.Lamp) || + (_game.Mode.ItemPlacement.Value == ItemPlacement.Advanced && + _game.Items.Has(ItemType.FireRod))) + return _game.Regions[RegionID.HyruleCastle].Accessibility; + } + + if (Available > 3) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.HyruleCastle].Accessibility); + } + + break; } - return AccessibilityLevel.SequenceBreak; + return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.HCSmallKey]); - itemReqs.Add(_game.Items[ItemType.Lamp]); - itemReqs.Add(_game.Items[ItemType.FireRod]); + _updateOnItemPlacementChange = true; + _updateOnDungeonItemShuffleChange = true; + + _regionSubscriptions.Add(RegionID.HyruleCastle, new Mode()); + + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.HCSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); + _itemSubscriptions.Add(ItemType.FireRod, new Mode() { ItemPlacement = ItemPlacement.Basic }); break; case LocationID.AgahnimTower: @@ -1998,8 +2234,6 @@ public ItemSection(Game game, Location location, int index = 0) _baseTotal = 0; _smallKey = 2; Name = "Dungeon"; - _standardRegion = _game.Regions[RegionID.Agahnim]; - _invertedRegion = _game.Regions[RegionID.Agahnim]; RequiredMode = new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }; @@ -2008,19 +2242,25 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.ATSmallKey)) { if (_game.Items.Has(ItemType.Lamp)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.Agahnim].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.Agahnim].Accessibility); } - if (Available == 2) - return AccessibilityLevel.Partial; + if (Available > 1) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.Agahnim].Accessibility); + } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Lamp]); - itemReqs.Add(_game.Items[ItemType.ATSmallKey]); + _regionSubscriptions.Add(RegionID.Agahnim, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); + + _itemSubscriptions.Add(ItemType.Lamp, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); + _itemSubscriptions.Add(ItemType.ATSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); PropertyChanged += OnRequirementChanged; @@ -2031,41 +2271,77 @@ public ItemSection(Game game, Location location, int index = 0) _bigKey = 1; _baseTotal = 3; Name = "Dungeon"; - _standardRegion = _game.Regions[RegionID.EasternPalace]; - _invertedRegion = _game.Regions[RegionID.EasternPalace]; GetAccessibility = () => { - if (_game.Mode.DungeonItemShuffle <= DungeonItemShuffle.MapsCompassesSmallKeys) + switch (_game.Mode.DungeonItemShuffle.Value) { - if (_game.Items.Has(ItemType.Lamp) && - (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value)) - return AccessibilityLevel.Normal; - - return AccessibilityLevel.SequenceBreak; - } - - if (_game.Items.Has(ItemType.EPBigKey) && - (_game.Mode.EnemyShuffle.Value || _game.Items.Has(ItemType.Bow))) - { - if (_game.Items.Has(ItemType.Lamp)) - return AccessibilityLevel.Normal; - - return AccessibilityLevel.SequenceBreak; - } + case DungeonItemShuffle.Standard: - if (_game.Items.Has(ItemType.EPBigKey) && Available > 1) - return AccessibilityLevel.Partial; - - if (Available > 2) - return AccessibilityLevel.Partial; + if (_game.Items.Has(ItemType.Lamp) && + (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value)) + return _game.Regions[RegionID.EasternPalace].Accessibility; + + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.EasternPalace].Accessibility); + + case DungeonItemShuffle.MapsCompasses: + case DungeonItemShuffle.MapsCompassesSmallKeys: + + if (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) + { + if (_game.Items.Has(ItemType.Lamp)) + return _game.Regions[RegionID.EasternPalace].Accessibility; + + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.EasternPalace].Accessibility); + } + + if (Available > 1) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.EasternPalace].Accessibility); + } + + break; + case DungeonItemShuffle.Keysanity: + + if (_game.Items.Has(ItemType.EPBigKey) && + (_game.Mode.EnemyShuffle.Value || _game.Items.Has(ItemType.Bow))) + { + if (_game.Items.Has(ItemType.Lamp)) + return _game.Regions[RegionID.EasternPalace].Accessibility; + + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.EasternPalace].Accessibility); + } + + if (Available > 1 && _game.Items.Has(ItemType.EPBigKey)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.EasternPalace].Accessibility); + } + + if (Available > 2) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.EasternPalace].Accessibility); + } + + break; + } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Lamp]); - itemReqs.Add(_game.Items[ItemType.Bow]); - itemReqs.Add(_game.Items[ItemType.EPBigKey]); + _updateOnDungeonItemShuffleChange = true; + _updateOnEnemyShuffleChange = true; + + _regionSubscriptions.Add(RegionID.EasternPalace, new Mode()); + + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); + _itemSubscriptions.Add(ItemType.Bow, new Mode() { EnemyShuffle = false }); + _itemSubscriptions.Add(ItemType.EPBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); PropertyChanged += OnRequirementChanged; @@ -2078,8 +2354,6 @@ public ItemSection(Game game, Location location, int index = 0) _baseTotal = 2; Name = "Dungeon"; HasMarking = true; - _standardRegion = _game.Regions[RegionID.DesertPalace]; - _invertedRegion = _game.Regions[RegionID.DesertPalace]; GetAccessibility = () => { @@ -2090,23 +2364,30 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.Boots) && (_game.Items.Has(ItemType.Gloves) || _game.Mode.EntranceShuffle.Value) && (_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod))) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DesertPalace].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DesertPalace].Accessibility); case DungeonItemShuffle.MapsCompasses: if (_game.Items.Has(ItemType.Boots) && (_game.Items.Has(ItemType.Gloves) || _game.Mode.EntranceShuffle.Value) && (_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod))) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DesertPalace].Accessibility; if ((_game.Items.Has(ItemType.Gloves) || _game.Mode.EntranceShuffle.Value) && (_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod))) - return AccessibilityLevel.SequenceBreak; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DesertPalace].Accessibility); + } if (Available > 1) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.DesertPalace].Accessibility); + } break; case DungeonItemShuffle.MapsCompassesSmallKeys: @@ -2114,21 +2395,35 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.Boots) && _game.Items.Has(ItemType.DPSmallKey) && (_game.Items.Has(ItemType.Gloves) || _game.Mode.EntranceShuffle.Value) && (_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod))) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DesertPalace].Accessibility; if (_game.Items.Has(ItemType.DPSmallKey) && (_game.Items.Has(ItemType.Gloves) || _game.Mode.EntranceShuffle.Value) && (_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod))) - return AccessibilityLevel.SequenceBreak; - - if (_game.Items.Has(ItemType.DPSmallKey)) { - if (Available > 1) - return AccessibilityLevel.Partial; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DesertPalace].Accessibility); + } + + if (Available > 1 && _game.Items.Has(ItemType.DPSmallKey)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.DesertPalace].Accessibility); + } + + if (Available > 2 && + (_game.Items.Has(ItemType.Gloves) || _game.Mode.EntranceShuffle.Value) && + (_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod))) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.DesertPalace].Accessibility); } if (Available > 3) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.DesertPalace].Accessibility); + } break; case DungeonItemShuffle.Keysanity: @@ -2137,17 +2432,23 @@ public ItemSection(Game game, Location location, int index = 0) _game.Items.Has(ItemType.DPSmallKey) && (_game.Items.Has(ItemType.Gloves) || _game.Mode.EntranceShuffle.Value) && (_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod))) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.DesertPalace].Accessibility; if (_game.Items.Has(ItemType.DPBigKey) && _game.Items.Has(ItemType.DPSmallKey) && (_game.Items.Has(ItemType.Gloves) || _game.Mode.EntranceShuffle.Value) && (_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod))) - return AccessibilityLevel.SequenceBreak; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DesertPalace].Accessibility); + } if (_game.Items.Has(ItemType.DPBigKey) && _game.Items.Has(ItemType.DPSmallKey)) { if (Available > 1) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.DesertPalace].Accessibility); + } } if (_game.Items.Has(ItemType.DPBigKey) && @@ -2155,23 +2456,35 @@ public ItemSection(Game game, Location location, int index = 0) (_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod))) { if (Available > 2) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.DesertPalace].Accessibility); + } } if (_game.Items.Has(ItemType.DPSmallKey)) { if (Available > 2) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.DesertPalace].Accessibility); + } } if (_game.Items.Has(ItemType.DPBigKey)) { if (Available > 3) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.DesertPalace].Accessibility); + } } if (Available > 4) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.DesertPalace].Accessibility); + } break; } @@ -2179,12 +2492,16 @@ public ItemSection(Game game, Location location, int index = 0) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Boots]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Lamp]); - itemReqs.Add(_game.Items[ItemType.FireRod]); - itemReqs.Add(_game.Items[ItemType.DPBigKey]); - itemReqs.Add(_game.Items[ItemType.DPSmallKey]); + _updateOnDungeonItemShuffleChange = true; + + _regionSubscriptions.Add(RegionID.DesertPalace, new Mode()); + + _itemSubscriptions.Add(ItemType.Boots, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.DPBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); + _itemSubscriptions.Add(ItemType.DPSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); PropertyChanged += OnRequirementChanged; @@ -2196,8 +2513,6 @@ public ItemSection(Game game, Location location, int index = 0) _bigKey = 1; _baseTotal = 2; Name = "Dungeon"; - _standardRegion = _game.Regions[RegionID.TowerOfHera]; - _invertedRegion = _game.Regions[RegionID.TowerOfHera]; GetAccessibility = () => { @@ -2207,47 +2522,59 @@ public ItemSection(Game game, Location location, int index = 0) case DungeonItemShuffle.MapsCompasses: if (_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.TowerOfHera].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.TowerOfHera].Accessibility); case DungeonItemShuffle.MapsCompassesSmallKeys: if ((_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod)) && _game.Items.Has(ItemType.ToHSmallKey)) - return AccessibilityLevel.Normal; - - if (Available > 1) - return AccessibilityLevel.Partial; + return _game.Regions[RegionID.TowerOfHera].Accessibility; + + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.TowerOfHera].Accessibility); - break; case DungeonItemShuffle.Keysanity: if ((_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod)) && _game.Items.Has(ItemType.ToHSmallKey) && _game.Items.Has(ItemType.ToHBigKey)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.TowerOfHera].Accessibility; if ((_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod)) && _game.Items.Has(ItemType.ToHSmallKey)) { - if (Available > 3) - return AccessibilityLevel.Partial; + if (Available > 1 && _game.Items.Has(ItemType.Hookshot)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.TowerOfHera].Accessibility); + } - if (_game.Items.Has(ItemType.Hookshot) && Available > 1) - return AccessibilityLevel.Partial; + if (Available > 3) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.TowerOfHera].Accessibility); + } } - if (_game.Items.Has(ItemType.ToHBigKey)) + if (Available > 1 && _game.Items.Has(ItemType.ToHBigKey)) { - if (Available > 1) - return AccessibilityLevel.Partial; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.TowerOfHera].Accessibility); } - if (_game.Items.Has(ItemType.Hookshot) && Available > 2) - return AccessibilityLevel.Partial; + if (Available > 2 && _game.Items.Has(ItemType.Hookshot)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.TowerOfHera].Accessibility); + } if (Available > 4) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.TowerOfHera].Accessibility); + } break; } @@ -2255,11 +2582,15 @@ public ItemSection(Game game, Location location, int index = 0) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Lamp]); - itemReqs.Add(_game.Items[ItemType.FireRod]); - itemReqs.Add(_game.Items[ItemType.ToHSmallKey]); - itemReqs.Add(_game.Items[ItemType.ToHBigKey]); - itemReqs.Add(_game.Items[ItemType.Hookshot]); + _updateOnDungeonItemShuffleChange = true; + + _regionSubscriptions.Add(RegionID.TowerOfHera, new Mode()); + + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.ToHSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); + _itemSubscriptions.Add(ItemType.ToHBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); + _itemSubscriptions.Add(ItemType.Hookshot, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); PropertyChanged += OnRequirementChanged; @@ -2271,8 +2602,6 @@ public ItemSection(Game game, Location location, int index = 0) _bigKey = 1; _baseTotal = 5; Name = "Dungeon"; - _standardRegion = _game.Regions[RegionID.PalaceOfDarkness]; - _invertedRegion = _game.Regions[RegionID.PalaceOfDarkness]; GetAccessibility = () => { @@ -2282,9 +2611,10 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.Lamp) && _game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.Bow)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.PalaceOfDarkness].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); case DungeonItemShuffle.MapsCompasses: @@ -2293,13 +2623,16 @@ public ItemSection(Game game, Location location, int index = 0) return AccessibilityLevel.Normal; if (_game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.Bow)) - return AccessibilityLevel.SequenceBreak; - - if (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) - return AccessibilityLevel.SequenceBreak; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } if (Available > 1) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } break; case DungeonItemShuffle.MapsCompassesSmallKeys: @@ -2310,41 +2643,78 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.Bow) && _game.Items.Has(ItemType.PoDSmallKey, 4)) - return AccessibilityLevel.SequenceBreak; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } - if (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) + if (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value || + _game.Items.Has(ItemType.Bottle)) { if (Available > 1 && (_game.Items.Has(ItemType.PoDSmallKey, 4) || (_game.Items.Has(ItemType.PoDSmallKey, 3) && _game.Items.Has(ItemType.Hammer)))) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } if (Available > 2 && (_game.Items.Has(ItemType.PoDSmallKey, 3) || (_game.Items.Has(ItemType.PoDSmallKey, 2) && _game.Items.Has(ItemType.Hammer)))) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } if (Available > 3 && (_game.Items.Has(ItemType.PoDSmallKey, 2) || (_game.Items.Has(ItemType.PoDSmallKey) && _game.Items.Has(ItemType.Hammer)))) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } if (Available > 8 && (_game.Items.Has(ItemType.PoDSmallKey) || _game.Items.Has(ItemType.Hammer))) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } + + if (Available > 10) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } } if (_game.Items.Has(ItemType.PoDSmallKey, 4) && Available > 3) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } if (_game.Items.Has(ItemType.PoDSmallKey, 3) && Available > 4) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } if (_game.Items.Has(ItemType.PoDSmallKey, 2) && Available > 5) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } if (_game.Items.Has(ItemType.PoDSmallKey) && Available > 10) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } if (Available > 12) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } break; case DungeonItemShuffle.Keysanity: @@ -2356,77 +2726,132 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.Bow) && _game.Items.Has(ItemType.PoDSmallKey, 4) && _game.Items.Has(ItemType.PoDBigKey)) - return AccessibilityLevel.SequenceBreak; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } - if (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) + if (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value || + _game.Items.Has(ItemType.Bottle)) { if (_game.Items.Has(ItemType.PoDSmallKey, 4) || (_game.Items.Has(ItemType.PoDSmallKey, 3) && _game.Items.Has(ItemType.Hammer))) { if (_game.Items.Has(ItemType.PoDBigKey) && Available > 1) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } if (Available > 2) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } } if (_game.Items.Has(ItemType.PoDSmallKey, 3) || (_game.Items.Has(ItemType.PoDSmallKey, 2) && _game.Items.Has(ItemType.Hammer))) { if (_game.Items.Has(ItemType.PoDBigKey) && Available > 2) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } if (Available > 3) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } } if (_game.Items.Has(ItemType.PoDSmallKey, 2) || (_game.Items.Has(ItemType.PoDSmallKey) && _game.Items.Has(ItemType.Hammer))) { if (_game.Items.Has(ItemType.PoDBigKey) && Available > 3) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } if (Available > 4) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } } if (Available > 9 && (_game.Items.Has(ItemType.PoDSmallKey) || _game.Items.Has(ItemType.Hammer))) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } + + if (Available > 11) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } } if (_game.Items.Has(ItemType.PoDSmallKey, 4)) { if (_game.Items.Has(ItemType.PoDBigKey) && Available > 3) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } if (Available > 4) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } } if (_game.Items.Has(ItemType.PoDSmallKey, 3)) { if (_game.Items.Has(ItemType.PoDBigKey) && Available > 4) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } if (Available > 5) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } } if (_game.Items.Has(ItemType.PoDSmallKey, 2)) { if (_game.Items.Has(ItemType.PoDBigKey) && Available > 5) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } if (Available > 6) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } } if (_game.Items.Has(ItemType.PoDSmallKey) && Available > 11) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } if (Available > 13) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.PalaceOfDarkness].Accessibility); + } break; } @@ -2434,11 +2859,17 @@ public ItemSection(Game game, Location location, int index = 0) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Lamp]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Bow]); - itemReqs.Add(_game.Items[ItemType.PoDBigKey]); - itemReqs.Add(_game.Items[ItemType.PoDSmallKey]); + _updateOnDungeonItemShuffleChange = true; + _updateOnEnemyShuffleChange = true; + + _regionSubscriptions.Add(RegionID.PalaceOfDarkness, new Mode()); + + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Bow, new Mode()); + _itemSubscriptions.Add(ItemType.Bottle, new Mode()); + _itemSubscriptions.Add(ItemType.PoDBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); + _itemSubscriptions.Add(ItemType.PoDSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); PropertyChanged += OnRequirementChanged; @@ -2450,8 +2881,6 @@ public ItemSection(Game game, Location location, int index = 0) _bigKey = 1; _baseTotal = 6; Name = "Dungeon"; - _standardRegion = _game.Regions[RegionID.SwampPalace]; - _invertedRegion = _game.Regions[RegionID.SwampPalace]; GetAccessibility = () => { @@ -2464,14 +2893,20 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.Hammer)) { if (_game.Items.Has(ItemType.Hookshot)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.SwampPalace].Accessibility; if (Available > 2) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SwampPalace].Accessibility); + } } if (Available > 5) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SwampPalace].Accessibility); + } } break; @@ -2482,14 +2917,20 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.Hammer)) { if (_game.Items.Has(ItemType.Hookshot)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.SwampPalace].Accessibility; if (Available > 4) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SwampPalace].Accessibility); + } } if (Available > 7) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SwampPalace].Accessibility); + } } break; @@ -2502,18 +2943,27 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.Hammer)) { if (_game.Items.Has(ItemType.Hookshot)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.SwampPalace].Accessibility; if (Available > 4) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SwampPalace].Accessibility); + } } if (Available > 7) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SwampPalace].Accessibility); + } } if (Available > 8) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SwampPalace].Accessibility); + } } break; @@ -2526,24 +2976,39 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.Hammer)) { if (_game.Items.Has(ItemType.Hookshot) && _game.Items.Has(ItemType.SPBigKey)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.SwampPalace].Accessibility; if (Available > 1 && _game.Items.Has(ItemType.Hookshot)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SwampPalace].Accessibility); + } if (Available > 4 && _game.Items.Has(ItemType.SPBigKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SwampPalace].Accessibility); + } if (Available > 5) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SwampPalace].Accessibility); + } } if (Available > 8) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SwampPalace].Accessibility); + } } if (Available > 9) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SwampPalace].Accessibility); + } } break; @@ -2552,11 +3017,15 @@ public ItemSection(Game game, Location location, int index = 0) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Flippers]); - itemReqs.Add(_game.Items[ItemType.Hookshot]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.SPSmallKey]); - itemReqs.Add(_game.Items[ItemType.SPBigKey]); + _updateOnDungeonItemShuffleChange = true; + + _regionSubscriptions.Add(RegionID.SwampPalace, new Mode()); + + _itemSubscriptions.Add(ItemType.Flippers, new Mode()); + _itemSubscriptions.Add(ItemType.Hookshot, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.SPSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); + _itemSubscriptions.Add(ItemType.SPBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); PropertyChanged += OnRequirementChanged; @@ -2568,8 +3037,6 @@ public ItemSection(Game game, Location location, int index = 0) _bigKey = 1; _baseTotal = 2; Name = "Dungeon"; - _standardRegion = _game.Regions[RegionID.SkullWoods]; - _invertedRegion = _game.Regions[RegionID.SkullWoods]; GetAccessibility = () => { @@ -2580,9 +3047,10 @@ public ItemSection(Game game, Location location, int index = 0) if ((_game.Items.Has(ItemType.FireRod) || _game.Mode.EntranceShuffle.Value) && _game.Items.CanRemoveCurtains()) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.SkullWoods].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.SkullWoods].Accessibility); case DungeonItemShuffle.MapsCompassesSmallKeys: @@ -2591,17 +3059,24 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.CanRemoveCurtains()) { if (_game.Items.Has(ItemType.SWSmallKey)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.SkullWoods].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.SkullWoods].Accessibility); } if (Available > 1) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SkullWoods].Accessibility); + } } if (Available > 2) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SkullWoods].Accessibility); + } break; case DungeonItemShuffle.Keysanity: @@ -2611,27 +3086,45 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.CanRemoveCurtains()) { if (_game.Items.Has(ItemType.SWBigKey) && _game.Items.Has(ItemType.SPSmallKey)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.SkullWoods].Accessibility; if (_game.Items.Has(ItemType.SWBigKey)) - return AccessibilityLevel.SequenceBreak; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.SkullWoods].Accessibility); + } if (Available > 1) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SkullWoods].Accessibility); + } } if (Available > 1 && _game.Items.Has(ItemType.SWBigKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SkullWoods].Accessibility); + } if (Available > 2) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SkullWoods].Accessibility); + } } if (Available > 2 && _game.Items.Has(ItemType.SWBigKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SkullWoods].Accessibility); + } if (Available > 3) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.SkullWoods].Accessibility); + } break; } @@ -2639,10 +3132,14 @@ public ItemSection(Game game, Location location, int index = 0) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.FireRod]); - itemReqs.Add(_game.Items[ItemType.Sword]); - itemReqs.Add(_game.Items[ItemType.SWBigKey]); - itemReqs.Add(_game.Items[ItemType.SWSmallKey]); + _updateOnDungeonItemShuffleChange = true; + + _regionSubscriptions.Add(RegionID.SkullWoods, new Mode()); + + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.SWBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); + _itemSubscriptions.Add(ItemType.SWSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); PropertyChanged += OnRequirementChanged; @@ -2654,8 +3151,6 @@ public ItemSection(Game game, Location location, int index = 0) _bigKey = 1; _baseTotal = 4; Name = "Dungeon"; - _standardRegion = _game.Regions[RegionID.ThievesTown]; - _invertedRegion = _game.Regions[RegionID.ThievesTown]; GetAccessibility = () => { @@ -2665,30 +3160,38 @@ public ItemSection(Game game, Location location, int index = 0) case DungeonItemShuffle.MapsCompasses: if (_game.Items.Has(ItemType.Hammer)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.ThievesTown].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.ThievesTown].Accessibility); case DungeonItemShuffle.MapsCompassesSmallKeys: if (_game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.TTSmallKey)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.ThievesTown].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.ThievesTown].Accessibility); case DungeonItemShuffle.Keysanity: if (_game.Items.Has(ItemType.TTBigKey)) { if (_game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.TTSmallKey)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.ThievesTown].Accessibility; if (Available > 1) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.ThievesTown].Accessibility); + } } if (Available > 4) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.ThievesTown].Accessibility); + } break; } @@ -2696,9 +3199,13 @@ public ItemSection(Game game, Location location, int index = 0) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.TTBigKey]); - itemReqs.Add(_game.Items[ItemType.TTSmallKey]); - itemReqs.Add(_game.Items[ItemType.Hammer]); + _updateOnDungeonItemShuffleChange = true; + + _regionSubscriptions.Add(RegionID.ThievesTown, new Mode()); + + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.TTBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); + _itemSubscriptions.Add(ItemType.TTSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); PropertyChanged += OnRequirementChanged; @@ -2710,8 +3217,6 @@ public ItemSection(Game game, Location location, int index = 0) _bigKey = 1; _baseTotal = 3; Name = "Dungeon"; - _standardRegion = _game.Regions[RegionID.IcePalace]; - _invertedRegion = _game.Regions[RegionID.IcePalace]; GetAccessibility = () => { @@ -2723,9 +3228,10 @@ public ItemSection(Game game, Location location, int index = 0) { if (_game.Items.Has(ItemType.Hammer) && (_game.Items.Has(ItemType.Hookshot) || _game.Items.Has(ItemType.CaneOfSomaria))) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.IcePalace].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.IcePalace].Accessibility); } break; @@ -2736,13 +3242,17 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.Hammer)) { if (_game.Items.Has(ItemType.Hookshot) || _game.Items.Has(ItemType.CaneOfSomaria)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.IcePalace].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.IcePalace].Accessibility); } if (Available > 1) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.IcePalace].Accessibility); + } } break; @@ -2756,13 +3266,17 @@ public ItemSection(Game game, Location location, int index = 0) (_game.Items.Has(ItemType.Hookshot) && _game.Items.Has(ItemType.IPSmallKey)) || (_game.Items.Has(ItemType.CaneOfSomaria) && _game.Items.Has(ItemType.IPSmallKey)) || _game.Items.Has(ItemType.IPSmallKey, 2)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.IcePalace].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.IcePalace].Accessibility); } if (Available > 3) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.IcePalace].Accessibility); + } } break; @@ -2776,20 +3290,32 @@ public ItemSection(Game game, Location location, int index = 0) (_game.Items.Has(ItemType.Hookshot) && _game.Items.Has(ItemType.IPSmallKey)) || (_game.Items.Has(ItemType.CaneOfSomaria) && _game.Items.Has(ItemType.IPSmallKey)) || _game.Items.Has(ItemType.IPSmallKey, 2)) && _game.Items.Has(ItemType.IPBigKey)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.IcePalace].Accessibility; if (_game.Items.Has(ItemType.IPBigKey)) - return AccessibilityLevel.SequenceBreak; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.IcePalace].Accessibility); + } if (Available > 1) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.IcePalace].Accessibility); + } } if (Available > 3 && _game.Items.Has(ItemType.IPBigKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.IcePalace].Accessibility); + } if (Available > 4) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.IcePalace].Accessibility); + } } break; @@ -2798,14 +3324,18 @@ public ItemSection(Game game, Location location, int index = 0) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.FireRod]); - itemReqs.Add(_game.Items[ItemType.Bombos]); - itemReqs.Add(_game.Items[ItemType.Sword]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Hookshot]); - itemReqs.Add(_game.Items[ItemType.CaneOfSomaria]); - itemReqs.Add(_game.Items[ItemType.IPSmallKey]); - itemReqs.Add(_game.Items[ItemType.IPBigKey]); + _updateOnDungeonItemShuffleChange = true; + + _regionSubscriptions.Add(RegionID.IcePalace, new Mode()); + + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.Bombos, new Mode()); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Hookshot, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfSomaria, new Mode()); + _itemSubscriptions.Add(ItemType.IPSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); + _itemSubscriptions.Add(ItemType.IPBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); PropertyChanged += OnRequirementChanged; @@ -2817,15 +3347,12 @@ public ItemSection(Game game, Location location, int index = 0) _bigKey = 1; _baseTotal = 2; Name = "Dungeon"; - _standardRegion = _game.Regions[RegionID.MiseryMire]; - _invertedRegion = _game.Regions[RegionID.MiseryMire]; GetAccessibility = () => { switch (_game.Mode.DungeonItemShuffle.Value) { case DungeonItemShuffle.Standard: - case DungeonItemShuffle.MapsCompasses: if (_game.Items.Has(ItemType.Hookshot) || _game.Items.Has(ItemType.Boots)) { @@ -2834,17 +3361,19 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.CaneOfSomaria)) { if ((_game.Items.Has(ItemType.Hookshot) || - (_game.Items.Has(ItemType.Boots) && _game.Mode.ItemPlacement == ItemPlacement.Advanced)) && + (_game.Items.Has(ItemType.Boots) && + _game.Mode.ItemPlacement == ItemPlacement.Advanced)) && _game.Items.Has(ItemType.Lamp)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.MiseryMire].Accessibility; } } - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.MiseryMire].Accessibility); } break; - case DungeonItemShuffle.MapsCompassesSmallKeys: + case DungeonItemShuffle.MapsCompasses: if (_game.Items.Has(ItemType.Hookshot) || _game.Items.Has(ItemType.Boots)) { @@ -2853,57 +3382,116 @@ public ItemSection(Game game, Location location, int index = 0) if (_game.Items.Has(ItemType.CaneOfSomaria)) { if ((_game.Items.Has(ItemType.Hookshot) || - (_game.Items.Has(ItemType.Boots) && _game.Mode.ItemPlacement == ItemPlacement.Advanced)) && + (_game.Items.Has(ItemType.Boots) && + _game.Mode.ItemPlacement == ItemPlacement.Advanced)) && _game.Items.Has(ItemType.Lamp)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.MiseryMire].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.MiseryMire].Accessibility); } if (Available > 1) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.MiseryMire].Accessibility); + } } - if (Available > 2 && _game.Items.Has(ItemType.CaneOfSomaria)) - return AccessibilityLevel.Partial; - if (Available > 3) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.MiseryMire].Accessibility); + } } break; - case DungeonItemShuffle.Keysanity: + case DungeonItemShuffle.MapsCompassesSmallKeys: if (_game.Items.Has(ItemType.Hookshot) || _game.Items.Has(ItemType.Boots)) { if (_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod)) { - if (_game.Items.Has(ItemType.CaneOfSomaria) && _game.Items.Has(ItemType.MMBigKey)) + if (_game.Items.Has(ItemType.CaneOfSomaria)) + { + if ((_game.Items.Has(ItemType.Hookshot) || + (_game.Items.Has(ItemType.Boots) && _game.Mode.ItemPlacement == ItemPlacement.Advanced)) && + _game.Items.Has(ItemType.Lamp)) + return _game.Regions[RegionID.MiseryMire].Accessibility; + + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.MiseryMire].Accessibility); + } + + if (Available > 1) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.MiseryMire].Accessibility); + } + } + + if (Available > 2 && _game.Items.Has(ItemType.CaneOfSomaria)) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.MiseryMire].Accessibility); + } + + if (Available > 3) + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.MiseryMire].Accessibility); + } + } + + break; + case DungeonItemShuffle.Keysanity: + + if (_game.Items.Has(ItemType.Hookshot) || _game.Items.Has(ItemType.Boots)) + { + if (_game.Items.Has(ItemType.Lamp) || _game.Items.Has(ItemType.FireRod)) + { + if (_game.Items.Has(ItemType.CaneOfSomaria) && _game.Items.Has(ItemType.MMBigKey)) { if ((_game.Items.Has(ItemType.Hookshot) || (_game.Items.Has(ItemType.Boots) && _game.Mode.ItemPlacement == ItemPlacement.Advanced)) && _game.Items.Has(ItemType.Lamp)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.MiseryMire].Accessibility; - return AccessibilityLevel.SequenceBreak; + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.MiseryMire].Accessibility); } if (Available > 1 && _game.Items.Has(ItemType.MMBigKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.MiseryMire].Accessibility); + } if (Available > 2) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.MiseryMire].Accessibility); + } } if (Available > 2 && _game.Items.Has(ItemType.CaneOfSomaria) && _game.Items.Has(ItemType.MMBigKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.MiseryMire].Accessibility); + } if (Available > 3 && _game.Items.Has(ItemType.MMBigKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.MiseryMire].Accessibility); + } if (Available > 4) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.MiseryMire].Accessibility); + } } break; @@ -2912,12 +3500,17 @@ public ItemSection(Game game, Location location, int index = 0) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Hookshot]); - itemReqs.Add(_game.Items[ItemType.Boots]); - itemReqs.Add(_game.Items[ItemType.Lamp]); - itemReqs.Add(_game.Items[ItemType.FireRod]); - itemReqs.Add(_game.Items[ItemType.CaneOfSomaria]); - itemReqs.Add(_game.Items[ItemType.MMBigKey]); + _updateOnItemPlacementChange = true; + _updateOnDungeonItemShuffleChange = true; + + _regionSubscriptions.Add(RegionID.MiseryMire, new Mode()); + + _itemSubscriptions.Add(ItemType.Hookshot, new Mode()); + _itemSubscriptions.Add(ItemType.Boots, new Mode()); + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfSomaria, new Mode()); + _itemSubscriptions.Add(ItemType.MMBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); PropertyChanged += OnRequirementChanged; @@ -2929,8 +3522,6 @@ public ItemSection(Game game, Location location, int index = 0) _bigKey = 1; _baseTotal = 5; Name = "Dungeon"; - _standardRegion = _game.Regions[RegionID.TurtleRock]; - _invertedRegion = _game.Regions[RegionID.TurtleRock]; GetAccessibility = () => { @@ -2984,293 +3575,526 @@ AccessibilityLevel backAccess() return AccessibilityLevel.None; } + AccessibilityLevel back = AccessibilityLevel.None; + AccessibilityLevel backFront = AccessibilityLevel.None; + AccessibilityLevel front = AccessibilityLevel.None; + switch (_game.Mode.DungeonItemShuffle.Value) { case DungeonItemShuffle.Standard: if (_game.Items.Has(ItemType.CaneOfSomaria) && _game.Items.Has(ItemType.FireRod) && - _game.Items.Has(ItemType.Lamp) && (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Mode.WorldState == WorldState.Inverted || _game.Items.Has(ItemType.Cape) || - _game.Items.Has(ItemType.CaneOfByrna) || _game.Items.Has(ItemType.Shield, 3))) - return AccessibilityLevel.Normal; + _game.Items.Has(ItemType.Lamp) && + (_game.Mode.ItemPlacement == ItemPlacement.Advanced || + _game.Items.Has(ItemType.Cape) || _game.Items.Has(ItemType.CaneOfByrna) || + _game.Items.Has(ItemType.Shield, 3))) + return _game.Regions[RegionID.TurtleRock].Accessibility; - if (backAccess() >= AccessibilityLevel.SequenceBreak) - return AccessibilityLevel.SequenceBreak; + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)backAccess()); - if (frontAccess() >= AccessibilityLevel.SequenceBreak && _game.Items.Has(ItemType.CaneOfSomaria)) - return AccessibilityLevel.SequenceBreak; + if (_game.Items.Has(ItemType.CaneOfSomaria)) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)frontAccess()); + } + + return (AccessibilityLevel)Math.Max((byte)back, (byte)front); - break; case DungeonItemShuffle.MapsCompasses: if (_game.Items.Has(ItemType.CaneOfSomaria) && _game.Items.Has(ItemType.FireRod) && - _game.Items.Has(ItemType.Lamp) && (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Mode.WorldState == WorldState.Inverted || _game.Items.Has(ItemType.Cape) || - _game.Items.Has(ItemType.CaneOfByrna) || _game.Items.Has(ItemType.Shield, 3))) - return AccessibilityLevel.Normal; + _game.Items.Has(ItemType.Lamp) && + (_game.Mode.ItemPlacement == ItemPlacement.Advanced || + _game.Items.Has(ItemType.Cape) || _game.Items.Has(ItemType.CaneOfByrna) || + _game.Items.Has(ItemType.Shield, 3))) + return _game.Regions[RegionID.TurtleRock].Accessibility; - if (backAccess() >= AccessibilityLevel.SequenceBreak) - return AccessibilityLevel.SequenceBreak; + if (Available > 1) + { + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); + } - if (frontAccess() >= AccessibilityLevel.SequenceBreak) + if (_game.Items.Has(ItemType.CaneOfSomaria)) { - if (_game.Items.Has(ItemType.CaneOfSomaria)) + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)backAccess()); + + if (Available > 2) { - if (_game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.SequenceBreak; + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } - if (Available > 2) - return AccessibilityLevel.Partial; + if (_game.Items.Has(ItemType.FireRod)) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)frontAccess()); } + } - break; + return (AccessibilityLevel)Math.Max((byte)back, (byte)front); + case DungeonItemShuffle.MapsCompassesSmallKeys: - if (backAccess() >= AccessibilityLevel.SequenceBreak) + if (Available > 5) { - if (_game.Items.Has(ItemType.CaneOfSomaria)) + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); + } + + if (_game.Items.Has(ItemType.Hookshot)) + { + if (Available > 4) { - if (_game.Items.Has(ItemType.TRSmallKey, 2) || - (_game.Items.Has(ItemType.TRSmallKey) && frontAccess() >= AccessibilityLevel.SequenceBreak)) - { - if (_game.Items.Has(ItemType.FireRod) && (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Mode.WorldState == WorldState.Inverted || _game.Items.Has(ItemType.Cape) || - _game.Items.Has(ItemType.CaneOfByrna) || _game.Items.Has(ItemType.Shield, 3))) - return AccessibilityLevel.Normal; + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); + } - if (Available > 2) - return AccessibilityLevel.Partial; + if (_game.Items.Has(ItemType.TRSmallKey)) + { + if (Available > 3) + { + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); } + } + } + + if (_game.Items.Has(ItemType.CaneOfSomaria)) + { + if (Available > 10) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } + + if (Available > 4) + { + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); + } + + if (Available > 3) + { + backFront = (AccessibilityLevel)Math.Min(Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()), (byte)frontAccess()); + } - if (_game.Items.Has(ItemType.TRSmallKey) || frontAccess() >= AccessibilityLevel.SequenceBreak) + if (_game.Items.Has(ItemType.FireRod)) + { + if (Available > 8) { - if (Available > 1 && _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Partial; + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } - if (Available > 3) - return AccessibilityLevel.Partial; + if (Available > 1) + { + backFront = (AccessibilityLevel)Math.Min(Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()), (byte)frontAccess()); } } - if (Available > 4) - return AccessibilityLevel.Partial; - } - - if (frontAccess() >= AccessibilityLevel.SequenceBreak) - { - if (_game.Items.Has(ItemType.CaneOfSomaria)) + if (_game.Items.Has(ItemType.TRSmallKey)) { - if (_game.Items.Has(ItemType.TRSmallKey, 4)) + if (Available > 9) { - if (_game.Items.Has(ItemType.FireRod)) + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } + + if (Available > 3) + { + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); + } + + if (Available > 2) + { + backFront = (AccessibilityLevel)Math.Min(Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()), (byte)frontAccess()); + } + + if (_game.Items.Has(ItemType.FireRod)) + { + if (Available > 7) { - if (_game.Items.Has(ItemType.Lamp) && (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Mode.WorldState == WorldState.Inverted || _game.Items.Has(ItemType.Cape) || - _game.Items.Has(ItemType.CaneOfByrna) || _game.Items.Has(ItemType.Shield, 3))) - return AccessibilityLevel.Normal; + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } - return AccessibilityLevel.SequenceBreak; + if (Available > 1) + { + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); } + + backFront = (AccessibilityLevel)Math.Min(Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)backAccess()), (byte)frontAccess()); - if (Available > 2) - return AccessibilityLevel.Partial; + if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || + _game.Items.Has(ItemType.Cape) || _game.Items.Has(ItemType.CaneOfByrna) || + _game.Items.Has(ItemType.Shield, 3)) + backFront = (AccessibilityLevel)Math.Min((byte)backAccess(), (byte)frontAccess()); } + } - if (_game.Items.Has(ItemType.TRSmallKey, 3)) + if (_game.Items.Has(ItemType.TRSmallKey, 2)) + { + if (Available > 7) { - if (Available > 1 && _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Partial; + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } - if (Available > 3) - return AccessibilityLevel.Partial; + if (Available > 2) + { + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); } - if (_game.Items.Has(ItemType.TRSmallKey, 2)) + if (_game.Items.Has(ItemType.FireRod)) { - if (Available > 5 && _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Partial; + if (Available > 5) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } - if (Available > 7) - return AccessibilityLevel.Partial; + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)backAccess()); + + if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || + _game.Items.Has(ItemType.Cape) || _game.Items.Has(ItemType.CaneOfByrna) || + _game.Items.Has(ItemType.Shield, 3)) + back = backAccess(); } + } - if (_game.Items.Has(ItemType.TRSmallKey)) + if (_game.Items.Has(ItemType.TRSmallKey, 3)) + { + if (Available > 3) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } + + if (_game.Items.Has(ItemType.FireRod)) { - if (Available > 7 && _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Partial; + if (Available > 1) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } + } + } - if (Available > 9) - return AccessibilityLevel.Partial; + if (_game.Items.Has(ItemType.TRSmallKey, 4)) + { + if (Available > 2) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); } - if (Available > 8 && _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Partial; + if (_game.Items.Has(ItemType.FireRod)) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)frontAccess()); - if (Available > 10) - return AccessibilityLevel.Partial; + if ((_game.Mode.ItemPlacement == ItemPlacement.Advanced || + _game.Items.Has(ItemType.Cape) || _game.Items.Has(ItemType.CaneOfByrna) || + _game.Items.Has(ItemType.Shield, 3)) && _game.Items.Has(ItemType.Lamp)) + front = frontAccess(); + } } } - break; - case DungeonItemShuffle.Keysanity: + return (AccessibilityLevel)Math.Max(Math.Max((byte)back, (byte)front), (byte)backFront); - if (backAccess() >= AccessibilityLevel.SequenceBreak) + case DungeonItemShuffle.Keysanity: + + if (Available > 6) { - if (_game.Items.Has(ItemType.CaneOfSomaria)) + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); + } + + if (_game.Items.Has(ItemType.TRBigKey)) + { + if (Available > 5) + { + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); + } + + if (_game.Items.Has(ItemType.Hookshot)) { - if (frontAccess() >= AccessibilityLevel.SequenceBreak) + if (Available > 4) { - if (_game.Items.Has(ItemType.FireRod) && _game.Items.Has(ItemType.TRSmallKey) && - _game.Items.Has(ItemType.TRBigKey) && (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Mode.WorldState == WorldState.Inverted || _game.Items.Has(ItemType.Cape) || - _game.Items.Has(ItemType.CaneOfByrna) || _game.Items.Has(ItemType.Shield, 3))) - return AccessibilityLevel.Normal; + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); + } - if (Available > 4) - return AccessibilityLevel.Partial; + if (_game.Items.Has(ItemType.TRSmallKey)) + { + if (Available > 3) + { + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); + } + } + } + } - if (Available > 3 && _game.Items.Has(ItemType.TRBigKey)) - return AccessibilityLevel.Partial; + if (_game.Items.Has(ItemType.CaneOfSomaria)) + { + if (Available > 11) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } - if (Available > 2 && - _game.Items.Has(ItemType.TRSmallKey) && _game.Items.Has(ItemType.TRBigKey)) - return AccessibilityLevel.Partial; + if (Available > 5) + { + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); + } - if (Available > 2 && _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Partial; + if (Available > 4) + { + backFront = (AccessibilityLevel)Math.Min(Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()), (byte)frontAccess()); + } - if (Available > 1 && - _game.Items.Has(ItemType.FireRod) && _game.Items.Has(ItemType.TRBigKey)) - return AccessibilityLevel.Partial; + if (_game.Items.Has(ItemType.TRBigKey)) + { + if (Available > 4) + { + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); } - if (_game.Items.Has(ItemType.FireRod) && _game.Items.Has(ItemType.TRSmallKey, 2) && - _game.Items.Has(ItemType.TRBigKey) && (_game.Mode.ItemPlacement == ItemPlacement.Advanced || - _game.Mode.WorldState == WorldState.Inverted || _game.Items.Has(ItemType.Cape) || - _game.Items.Has(ItemType.CaneOfByrna) || _game.Items.Has(ItemType.Shield, 3))) - return AccessibilityLevel.Normal; - - if (Available > 4 && _game.Items.Has(ItemType.TRSmallKey)) - return AccessibilityLevel.Partial; - - if (Available > 4 && _game.Items.Has(ItemType.TRBigKey)) - return AccessibilityLevel.Partial; - - if (Available > 3 && - _game.Items.Has(ItemType.TRSmallKey) && _game.Items.Has(ItemType.TRBigKey)) - return AccessibilityLevel.Partial; + if (Available > 3) + { + backFront = (AccessibilityLevel)Math.Min(Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()), (byte)frontAccess()); + } + } - if (Available > 2 && - _game.Items.Has(ItemType.TRSmallKey) && _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Partial; + if (_game.Items.Has(ItemType.FireRod)) + { + if (Available > 9) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } - if (Available > 2 && - _game.Items.Has(ItemType.TRSmallKey, 2) && _game.Items.Has(ItemType.TRBigKey)) - return AccessibilityLevel.Partial; + if (Available > 2) + { + backFront = (AccessibilityLevel)Math.Min(Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()), (byte)frontAccess()); + } - if (Available > 1 && _game.Items.Has(ItemType.FireRod) && - _game.Items.Has(ItemType.TRSmallKey) && _game.Items.Has(ItemType.TRBigKey)) - return AccessibilityLevel.Partial; + if (_game.Items.Has(ItemType.TRBigKey)) + { + if (Available > 1) + { + backFront = (AccessibilityLevel)Math.Min(Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()), (byte)frontAccess()); + } + } } - if (Available > 4 && - _game.Items.Has(ItemType.TRBigKey) && _game.Items.Has(ItemType.Hookshot)) - return AccessibilityLevel.Partial; + if (_game.Items.Has(ItemType.TRSmallKey)) + { + if (Available > 10) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } - if (Available > 5) - return AccessibilityLevel.Partial; - } + if (Available > 4) + { + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); + } - if (frontAccess() >= AccessibilityLevel.SequenceBreak) - { - if (_game.Items.Has(ItemType.CaneOfSomaria)) - { - if (_game.Items.Has(ItemType.TRSmallKey, 4) && _game.Items.Has(ItemType.TRBigKey)) + if (_game.Items.Has(ItemType.TRBigKey)) { - if (_game.Items.Has(ItemType.FireRod)) + if (Available > 3) { - if (_game.Items.Has(ItemType.Lamp)) - return AccessibilityLevel.Normal; + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); + } - return AccessibilityLevel.SequenceBreak; + if (Available > 2) + { + backFront = (AccessibilityLevel)Math.Min(Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()), (byte)frontAccess()); } - + } + + if (_game.Items.Has(ItemType.FireRod)) + { + if (Available > 8) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } + if (Available > 2) - return AccessibilityLevel.Partial; + { + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); + } + + if (_game.Items.Has(ItemType.TRBigKey)) + { + if (Available > 1) + { + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); + } + + backFront = (AccessibilityLevel)Math.Min(Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)backAccess()), (byte)frontAccess()); + + if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || + _game.Items.Has(ItemType.Cape) || _game.Items.Has(ItemType.CaneOfByrna) || + _game.Items.Has(ItemType.Shield, 3)) + backFront = (AccessibilityLevel)Math.Min((byte)backAccess(), (byte)frontAccess()); + } } + } - if (_game.Items.Has(ItemType.TRSmallKey, 3) && _game.Items.Has(ItemType.TRBigKey)) + if (_game.Items.Has(ItemType.TRSmallKey, 2)) + { + if (Available > 9) { - if (Available > 1 && _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Partial; - - if (Available > 3) - return AccessibilityLevel.Partial; + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); } - if (_game.Items.Has(ItemType.TRSmallKey, 2)) + if (_game.Items.Has(ItemType.TRBigKey)) { - if (_game.Items.Has(ItemType.TRBigKey)) + if (Available > 7) { - if (Available > 5 && _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Partial; + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } - if (Available > 7) - return AccessibilityLevel.Partial; + if (Available > 2) + { + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)backAccess()); } + } - if (Available > 7 && _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Partial; + if (_game.Items.Has(ItemType.FireRod)) + { + if (Available > 7) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } - if (Available > 9) - return AccessibilityLevel.Partial; + if (_game.Items.Has(ItemType.TRBigKey)) + { + if (Available > 5) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } + + back = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)backAccess()); + + if (_game.Mode.ItemPlacement == ItemPlacement.Advanced || + _game.Items.Has(ItemType.Cape) || _game.Items.Has(ItemType.CaneOfByrna) || + _game.Items.Has(ItemType.Shield, 3)) + back = backAccess(); + } } + } - if (_game.Items.Has(ItemType.TRSmallKey)) + if (_game.Items.Has(ItemType.TRBigKey)) + { + if (_game.Items.Has(ItemType.TRSmallKey, 3)) { - if (Available > 8 && _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Partial; + if (Available > 3) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } - if (Available > 10) - return AccessibilityLevel.Partial; + if (_game.Items.Has(ItemType.FireRod)) + { + if (Available > 1) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } + } } - if (Available > 9 && _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Partial; + if (_game.Items.Has(ItemType.TRSmallKey, 4)) + { + if (Available > 2) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)frontAccess()); + } + + if (_game.Items.Has(ItemType.FireRod)) + { + front = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)frontAccess()); - if (Available > 11) - return AccessibilityLevel.Partial; + if ((_game.Mode.ItemPlacement == ItemPlacement.Advanced || + _game.Items.Has(ItemType.Cape) || _game.Items.Has(ItemType.CaneOfByrna) || + _game.Items.Has(ItemType.Shield, 3)) && _game.Items.Has(ItemType.Lamp)) + front = frontAccess(); + } + } } } - break; + return (AccessibilityLevel)Math.Max(Math.Max((byte)back, (byte)front), (byte)backFront); + } return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Sword]); - itemReqs.Add(_game.Items[ItemType.Bombos]); - itemReqs.Add(_game.Items[ItemType.BombosDungeons]); - itemReqs.Add(_game.Items[ItemType.Ether]); - itemReqs.Add(_game.Items[ItemType.EtherDungeons]); - itemReqs.Add(_game.Items[ItemType.Quake]); - itemReqs.Add(_game.Items[ItemType.QuakeDungeons]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.CaneOfSomaria]); - itemReqs.Add(_game.Items[ItemType.FireRod]); - itemReqs.Add(_game.Items[ItemType.Lamp]); - itemReqs.Add(_game.Items[ItemType.Cape]); - itemReqs.Add(_game.Items[ItemType.CaneOfByrna]); - itemReqs.Add(_game.Items[ItemType.Shield]); - itemReqs.Add(_game.Items[ItemType.TRSmallKey]); - itemReqs.Add(_game.Items[ItemType.TRBigKey]); - itemReqs.Add(_game.Items[ItemType.Hookshot]); - - _game.Regions[RegionID.DeathMountainEastTop].PropertyChanged += OnRequirementChanged; - _game.Regions[RegionID.DarkDeathMountainTop].PropertyChanged += OnRequirementChanged; + _updateOnItemPlacementChange = true; + _updateOnDungeonItemShuffleChange = true; + + _regionSubscriptions.Add(RegionID.TurtleRock, new Mode()); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode()); + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode()); + + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Sword, new Mode()); + _itemSubscriptions.Add(ItemType.Bombos, new Mode()); + _itemSubscriptions.Add(ItemType.BombosDungeons, new Mode()); + _itemSubscriptions.Add(ItemType.Ether, new Mode()); + _itemSubscriptions.Add(ItemType.EtherDungeons, new Mode()); + _itemSubscriptions.Add(ItemType.Quake, new Mode()); + _itemSubscriptions.Add(ItemType.QuakeDungeons, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfSomaria, new Mode()); + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); + _itemSubscriptions.Add(ItemType.Cape, new Mode() { ItemPlacement = ItemPlacement.Basic }); + _itemSubscriptions.Add(ItemType.CaneOfByrna, new Mode() { ItemPlacement = ItemPlacement.Basic }); + _itemSubscriptions.Add(ItemType.Shield, new Mode() { ItemPlacement = ItemPlacement.Basic }); + _itemSubscriptions.Add(ItemType.TRSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); + _itemSubscriptions.Add(ItemType.TRBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); + _itemSubscriptions.Add(ItemType.Hookshot, new Mode()); PropertyChanged += OnRequirementChanged; @@ -3282,8 +4106,6 @@ AccessibilityLevel backAccess() _bigKey = 1; _baseTotal = 19; Name = "Dungeon"; - _standardRegion = _game.Regions[RegionID.GanonsTower]; - _invertedRegion = _game.Regions[RegionID.GanonsTower]; GetAccessibility = () => { @@ -3295,7 +4117,7 @@ AccessibilityLevel backAccess() _game.Items.Has(ItemType.Boots) && _game.Items.Has(ItemType.CaneOfSomaria) && (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) && _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.GanonsTower].Accessibility; if (_game.Items.Has(ItemType.Hammer) && (_game.Items.Has(ItemType.Hookshot) || _game.Items.Has(ItemType.Boots))) @@ -3305,22 +4127,37 @@ AccessibilityLevel backAccess() if (_game.Items.Has(ItemType.CaneOfSomaria)) { if (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) - return AccessibilityLevel.SequenceBreak; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 1) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (Available > 2 && (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 5) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (Available > 5) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (_game.Items.Has(ItemType.FireRod) || _game.Items.Has(ItemType.Lamp)) @@ -3331,37 +4168,61 @@ AccessibilityLevel backAccess() { if (Available > 4 && (_game.Items.Has(ItemType.Boots) || _game.Items.Has(ItemType.Hookshot))) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 5) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (Available > 7 && (_game.Items.Has(ItemType.Boots) || _game.Items.Has(ItemType.Hookshot))) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 8) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) { if (Available > 13 && (_game.Items.Has(ItemType.Boots) || _game.Items.Has(ItemType.Hookshot))) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 14) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } } if (Available > 15 && _game.Items.Has(ItemType.CaneOfSomaria)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 16) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } break; case DungeonItemShuffle.MapsCompasses: @@ -3370,7 +4231,7 @@ AccessibilityLevel backAccess() _game.Items.Has(ItemType.Boots) && _game.Items.Has(ItemType.CaneOfSomaria) && (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) && _game.Items.Has(ItemType.FireRod)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.GanonsTower].Accessibility; if (_game.Items.Has(ItemType.Hammer) && (_game.Items.Has(ItemType.Hookshot) || _game.Items.Has(ItemType.Boots))) @@ -3380,22 +4241,37 @@ AccessibilityLevel backAccess() if (_game.Items.Has(ItemType.CaneOfSomaria)) { if (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) - return AccessibilityLevel.SequenceBreak; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 3) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (Available > 4 && (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 7) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (Available > 7) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (_game.Items.Has(ItemType.FireRod) || _game.Items.Has(ItemType.Lamp)) @@ -3406,32 +4282,53 @@ AccessibilityLevel backAccess() { if (Available > 6 && (_game.Items.Has(ItemType.Boots) || _game.Items.Has(ItemType.Hookshot))) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 7) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (Available > 10) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) { if (Available > 15 && (_game.Items.Has(ItemType.Boots) || _game.Items.Has(ItemType.Hookshot))) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 16) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } } if (Available > 17 && _game.Items.Has(ItemType.CaneOfSomaria)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 18) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } break; case DungeonItemShuffle.MapsCompassesSmallKeys: @@ -3440,7 +4337,7 @@ AccessibilityLevel backAccess() _game.Items.Has(ItemType.Boots) && _game.Items.Has(ItemType.CaneOfSomaria) && (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) && _game.Items.Has(ItemType.FireRod) && _game.Items.Has(ItemType.GTSmallKey, 2)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.GanonsTower].Accessibility; if (_game.Items.Has(ItemType.Hammer) && (_game.Items.Has(ItemType.Hookshot) || _game.Items.Has(ItemType.Boots))) @@ -3452,43 +4349,73 @@ AccessibilityLevel backAccess() if (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) { if (_game.Items.Has(ItemType.GTSmallKey)) - return AccessibilityLevel.SequenceBreak; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 1) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (Available > 4) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) { if (Available > 5 && _game.Items.Has(ItemType.GTSmallKey, 2)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 6 && _game.Items.Has(ItemType.GTSmallKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 7) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } } if (_game.Items.Has(ItemType.CaneOfSomaria)) { if (Available > 8 && _game.Items.Has(ItemType.GTSmallKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 9) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (Available > 9 && _game.Items.Has(ItemType.GTSmallKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 10) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (_game.Items.Has(ItemType.FireRod) || _game.Items.Has(ItemType.Lamp)) @@ -3499,32 +4426,53 @@ AccessibilityLevel backAccess() { if (Available > 9 && _game.Items.Has(ItemType.GTSmallKey) && (_game.Items.Has(ItemType.Boots) || _game.Items.Has(ItemType.Hookshot))) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 10) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (Available > 13) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) { if (Available > 19 && (_game.Items.Has(ItemType.Boots) || _game.Items.Has(ItemType.Hookshot))) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 20) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } } if (Available > 21 && _game.Items.Has(ItemType.CaneOfSomaria)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 22) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } break; case DungeonItemShuffle.Keysanity: @@ -3534,7 +4482,7 @@ AccessibilityLevel backAccess() (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) && _game.Items.Has(ItemType.FireRod) && _game.Items.Has(ItemType.GTSmallKey, 2) && _game.Items.Has(ItemType.GTBigKey)) - return AccessibilityLevel.Normal; + return _game.Regions[RegionID.GanonsTower].Accessibility; if (_game.Items.Has(ItemType.Hammer) && (_game.Items.Has(ItemType.Hookshot) || _game.Items.Has(ItemType.Boots))) @@ -3549,18 +4497,30 @@ AccessibilityLevel backAccess() _game.Items.Has(ItemType.GTBigKey)) { if (_game.Items.Has(ItemType.GTSmallKey)) - return AccessibilityLevel.SequenceBreak; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 1) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (Available > 4) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (Available > 5) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (_game.Items.Has(ItemType.GTBigKey)) @@ -3568,13 +4528,22 @@ AccessibilityLevel backAccess() if (_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) { if (Available > 5 && _game.Items.Has(ItemType.GTSmallKey, 2)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 6 && _game.Items.Has(ItemType.GTSmallKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 7) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } } } @@ -3583,30 +4552,54 @@ AccessibilityLevel backAccess() { if (Available > 8 && _game.Items.Has(ItemType.GTBigKey) && _game.Items.Has(ItemType.GTSmallKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 9 && _game.Items.Has(ItemType.GTSmallKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 9 && _game.Items.Has(ItemType.GTBigKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 10) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (Available > 9 && _game.Items.Has(ItemType.GTSmallKey) && _game.Items.Has(ItemType.GTBigKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 10 && _game.Items.Has(ItemType.GTSmallKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 10 && _game.Items.Has(ItemType.GTBigKey)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 11) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (_game.Items.Has(ItemType.FireRod) || _game.Items.Has(ItemType.Lamp)) @@ -3619,18 +4612,30 @@ AccessibilityLevel backAccess() { if (Available > 10 && _game.Items.Has(ItemType.GTSmallKey) && (_game.Items.Has(ItemType.Boots) || _game.Items.Has(ItemType.Hookshot))) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 11) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (Available > 13) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if (Available > 14) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } if ((_game.Items.Has(ItemType.Bow) || _game.Mode.EnemyShuffle.Value) && @@ -3638,18 +4643,30 @@ AccessibilityLevel backAccess() { if (Available > 20 && (_game.Items.Has(ItemType.Boots) || _game.Items.Has(ItemType.Hookshot))) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 21) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } } } if (Available > 22 && _game.Items.Has(ItemType.CaneOfSomaria)) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } if (Available > 23) - return AccessibilityLevel.Partial; + { + return (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.Partial, + (byte)_game.Regions[RegionID.GanonsTower].Accessibility); + } break; } @@ -3657,91 +4674,166 @@ AccessibilityLevel backAccess() return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Hookshot]); - itemReqs.Add(_game.Items[ItemType.Boots]); - itemReqs.Add(_game.Items[ItemType.CaneOfSomaria]); - itemReqs.Add(_game.Items[ItemType.Bow]); - itemReqs.Add(_game.Items[ItemType.FireRod]); - itemReqs.Add(_game.Items[ItemType.Lamp]); - itemReqs.Add(_game.Items[ItemType.GTSmallKey]); - itemReqs.Add(_game.Items[ItemType.GTBigKey]); + _updateOnDungeonItemShuffleChange = true; + _updateOnEnemyShuffleChange = true; + + _regionSubscriptions.Add(RegionID.GanonsTower, new Mode()); + + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Hookshot, new Mode()); + _itemSubscriptions.Add(ItemType.Boots, new Mode()); + _itemSubscriptions.Add(ItemType.CaneOfSomaria, new Mode()); + _itemSubscriptions.Add(ItemType.Bow, new Mode() { EnemyShuffle = false }); + _itemSubscriptions.Add(ItemType.FireRod, new Mode()); + _itemSubscriptions.Add(ItemType.Lamp, new Mode()); + _itemSubscriptions.Add(ItemType.GTSmallKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.MapsCompassesSmallKeys }); + _itemSubscriptions.Add(ItemType.GTBigKey, new Mode() { DungeonItemShuffle = DungeonItemShuffle.Keysanity }); PropertyChanged += OnRequirementChanged; break; } - Total = _baseTotal; - Available = _baseTotal; - - foreach (Item item in itemReqs) - item.PropertyChanged += OnRequirementChanged; - if (RequiredMode == null) RequiredMode = new Mode(); - if (_standardRegion != null) - _standardRegion.PropertyChanged += OnRequirementChanged; + SetTotal(); + + _game.Mode.PropertyChanged += OnModeChanged; - if (_invertedRegion != null) - _invertedRegion.PropertyChanged += OnRequirementChanged; + UpdateRegionSubscriptions(); + UpdateItemSubscriptions(); UpdateAccessibility(); } - private void SetTotal() + private void OnPropertyChanged(string propertyName) { - int newTotal = _baseTotal + - ((_game.Mode.DungeonItemShuffle.Value >= DungeonItemShuffle.MapsCompasses) ? _mapCompass : 0) + - ((_game.Mode.DungeonItemShuffle.Value >= DungeonItemShuffle.MapsCompassesSmallKeys) ? _smallKey : 0) + - ((_game.Mode.DungeonItemShuffle.Value >= DungeonItemShuffle.Keysanity) ? _bigKey : 0); - - int delta = newTotal - Total; - - Total = newTotal; - Available = Math.Max(0, Math.Min(Total, Available + delta)); + if (PropertyChanged != null) + PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); } - private void UpdateAccessibility() + private void OnModeChanged(object sender, PropertyChangedEventArgs e) { - AccessibilityLevel? regionAccessibility = null; - - if (_game.Mode.WorldState == WorldState.StandardOpen && _standardRegion != null) - regionAccessibility = _standardRegion.Accessibility; - - if (_game.Mode.WorldState == WorldState.Inverted && _invertedRegion != null) - regionAccessibility = _invertedRegion.Accessibility; - - if (regionAccessibility != null) + UpdateItemSubscriptions(); + UpdateRegionSubscriptions(); + + if (e.PropertyName == nameof(_game.Mode.ItemPlacement) && + _updateOnItemPlacementChange) + UpdateAccessibility(); + + if (e.PropertyName == nameof(_game.Mode.DungeonItemShuffle)) { - AccessibilityLevel sectionAccessibility = GetAccessibility(); - Accessibility = (AccessibilityLevel)Math.Min((byte)regionAccessibility.Value, - (byte)sectionAccessibility); + SetTotal(); + + if (_updateOnDungeonItemShuffleChange) + UpdateAccessibility(); } - else - Accessibility = GetAccessibility(); + + if (e.PropertyName == nameof(_game.Mode.WorldState)) + UpdateAccessibility(); + + if (e.PropertyName == nameof(_game.Mode.EnemyShuffle) && + _updateOnEnemyShuffleChange) + UpdateAccessibility(); + } - + private void OnRequirementChanged(object sender, PropertyChangedEventArgs e) { UpdateAccessibility(); } - private void OnModeChanged(object sender, PropertyChangedEventArgs e) + private void UpdateRegionSubscriptions() { - UpdateAccessibility(); + foreach (RegionID region in _regionSubscriptions.Keys) + { + if (_game.Mode.Validate(_regionSubscriptions[region])) + { + if (_regionIsSubscribed.ContainsKey(region)) + { + if (!_regionIsSubscribed[region]) + { + _regionIsSubscribed[region] = true; + _game.Regions[region].PropertyChanged += OnRequirementChanged; + } + } + else + { + _regionIsSubscribed.Add(region, true); + _game.Regions[region].PropertyChanged += OnRequirementChanged; + } + } + else + { + if (_regionIsSubscribed.ContainsKey(region)) + { + if (_regionIsSubscribed[region]) + { + _regionIsSubscribed[region] = false; + _game.Regions[region].PropertyChanged -= OnRequirementChanged; + } + } + else + _regionIsSubscribed.Add(region, false); + } + } + } - if (e.PropertyName == nameof(_game.Mode.DungeonItemShuffle)) - SetTotal(); + private void UpdateItemSubscriptions() + { + foreach (ItemType item in _itemSubscriptions.Keys) + { + if (_game.Mode.Validate(_itemSubscriptions[item])) + { + if (_itemIsSubscribed.ContainsKey(item)) + { + if (!_itemIsSubscribed[item]) + { + _itemIsSubscribed[item] = true; + _game.Items[item].PropertyChanged += OnRequirementChanged; + } + } + else + { + _itemIsSubscribed.Add(item, true); + _game.Items[item].PropertyChanged += OnRequirementChanged; + } + } + else + { + if (_itemIsSubscribed.ContainsKey(item)) + { + if (_itemIsSubscribed[item]) + { + _itemIsSubscribed[item] = false; + _game.Items[item].PropertyChanged -= OnRequirementChanged; + } + } + else + _itemIsSubscribed.Add(item, false); + } + } } - private void OnPropertyChanged(string propertyName) + private void SetTotal() { - if (PropertyChanged != null) - PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); + int newTotal = _baseTotal + + ((_game.Mode.DungeonItemShuffle.Value >= DungeonItemShuffle.MapsCompasses) ? _mapCompass : 0) + + ((_game.Mode.DungeonItemShuffle.Value >= DungeonItemShuffle.MapsCompassesSmallKeys) ? _smallKey : 0) + + ((_game.Mode.DungeonItemShuffle.Value >= DungeonItemShuffle.Keysanity) ? _bigKey : 0); + + int delta = newTotal - Total; + + Total = newTotal; + Available = Math.Max(0, Math.Min(Total, Available + delta)); } + private void UpdateAccessibility() + { + Accessibility = GetAccessibility(); + } + public void Clear() { do diff --git a/OpenTracker.Models/Location.cs b/OpenTracker.Models/Location.cs index 47671b97..30e06328 100644 --- a/OpenTracker.Models/Location.cs +++ b/OpenTracker.Models/Location.cs @@ -31,8 +31,6 @@ public Location(Game game, LocationID iD) int itemSections = 0; bool entranceSection = false; - List itemRequirements = new List(); - switch (iD) { case LocationID.Pedestal: diff --git a/OpenTracker.Models/MapLocation.cs b/OpenTracker.Models/MapLocation.cs index 39f13811..b0b1237a 100644 --- a/OpenTracker.Models/MapLocation.cs +++ b/OpenTracker.Models/MapLocation.cs @@ -1,5 +1,4 @@ using OpenTracker.Models.Enums; -using System.ComponentModel; namespace OpenTracker.Models { diff --git a/OpenTracker.Models/Mode.cs b/OpenTracker.Models/Mode.cs index 8f5c9935..61e10de2 100644 --- a/OpenTracker.Models/Mode.cs +++ b/OpenTracker.Models/Mode.cs @@ -122,6 +122,9 @@ private void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); + + if (propertyName == nameof(WorldState) && WorldState == Enums.WorldState.Inverted) + ItemPlacement = Enums.ItemPlacement.Advanced; } public bool Validate(Mode gameMode) diff --git a/OpenTracker.Models/OpenTracker.Models.csproj b/OpenTracker.Models/OpenTracker.Models.csproj index 7c4ae4ca..b29c3c5d 100644 --- a/OpenTracker.Models/OpenTracker.Models.csproj +++ b/OpenTracker.Models/OpenTracker.Models.csproj @@ -2,6 +2,7 @@ netcoreapp3.1 + 0.7.1 diff --git a/OpenTracker.Models/Region.cs b/OpenTracker.Models/Region.cs index 9c0d2cbe..7d8bbd03 100644 --- a/OpenTracker.Models/Region.cs +++ b/OpenTracker.Models/Region.cs @@ -8,11 +8,13 @@ namespace OpenTracker.Models public class Region : INotifyPropertyChanged { private readonly Game _game; - private readonly List _observedRegions; + private readonly Dictionary _regionSubscriptions; + private readonly Dictionary _regionIsSubscribed; + private readonly Dictionary _itemSubscriptions; + private readonly Dictionary _itemIsSubscribed; public RegionID ID { get; } - public Func GetDirectAccessibility { get; } - public Func, AccessibilityLevel> GetIndirectAccessibility { get; } + public Func, AccessibilityLevel> GetAccessibility { get; } public event PropertyChangedEventHandler PropertyChanged; @@ -49,20 +51,23 @@ public Region(Game game, RegionID iD) _game = game; ID = iD; - _game.Mode.PropertyChanged += OnModeChanged; - - List itemReqs = new List(); - _observedRegions = new List(); + _regionSubscriptions = new Dictionary(); + _regionIsSubscribed = new Dictionary(); + _itemSubscriptions = new Dictionary(); + _itemIsSubscribed = new Dictionary(); switch (ID) { case RegionID.LightWorld: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Standard and Open modes if (_game.Mode.WorldState == WorldState.StandardOpen) + { + // Access from start return AccessibilityLevel.Normal; + } // Inverted mode if (_game.Mode.WorldState == WorldState.Inverted) @@ -122,38 +127,32 @@ public Region(Game game, RegionID iD) // Default to no access return AccessibilityLevel.None; }; - GetIndirectAccessibility = (excludedRegions) => { return AccessibilityLevel.None; }; - - itemReqs.Add(_game.Items[ItemType.Aga]); - itemReqs.Add(_game.Items[ItemType.LightWorldAccess]); - itemReqs.Add(_game.Items[ItemType.DeathMountainExitAccess]); - itemReqs.Add(_game.Items[ItemType.RaceGameAccess]); - itemReqs.Add(_game.Items[ItemType.HyruleCastleSecondFloorAccess]); - itemReqs.Add(_game.Items[ItemType.DesertLeftAccess]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.GrassHouseAccess]); - itemReqs.Add(_game.Items[ItemType.WitchsHutAccess]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.DesertBackAccess]); - itemReqs.Add(_game.Items[ItemType.LakeHyliaFairyIslandAccess]); - itemReqs.Add(_game.Items[ItemType.Flippers]); - itemReqs.Add(_game.Items[ItemType.WaterfallFairyAccess]); + + _itemSubscriptions.Add(ItemType.Aga, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.LightWorldAccess, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.DeathMountainExitAccess, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.RaceGameAccess, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.HyruleCastleSecondFloorAccess, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.DesertLeftAccess, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.GrassHouseAccess, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.WitchsHutAccess, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.Hammer, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.DesertBackAccess, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.LakeHyliaFairyIslandAccess, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.Flippers, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.WaterfallFairyAccess, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.HyruleCastleSecondFloor: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access via exits in the region if (_game.Items.Has(ItemType.HyruleCastleSecondFloorAccess)) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -169,21 +168,24 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.HyruleCastleSecondFloorAccess]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DarkWorldEast, new Mode() { WorldState = WorldState.StandardOpen }); - _observedRegions.Add(RegionID.DarkWorldEast); + _itemSubscriptions.Add(ItemType.HyruleCastleSecondFloorAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); break; case RegionID.DarkWorldWest: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access via exits in the region if (_game.Items.Has(ItemType.DarkWorldWestAccess) || _game.Items.Has(ItemType.BumperCaveAccess)) return AccessibilityLevel.Normal; + List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); + newExcludedRegions.Add(ID); + // Standard and Open modes if (_game.Mode.WorldState == WorldState.StandardOpen) { @@ -197,6 +199,10 @@ public Region(Game game, RegionID iD) if ((_game.Items.Has(ItemType.Gloves) && _game.Items.Has(ItemType.Hammer)) || _game.Items.Has(ItemType.Gloves, 2)) return AccessibilityLevel.Normal; + + // Access via Dark World Witch area by hookshot + if (_game.Items.Has(ItemType.Hookshot) && !excludedRegions.Contains(RegionID.DarkWorldWitchArea)) + return _game.Regions[RegionID.DarkWorldWitchArea].GetAccessibility(newExcludedRegions); } } @@ -210,28 +216,7 @@ public Region(Game game, RegionID iD) // Access via Hammer House exit if (_game.Items.Has(ItemType.HammerHouseAccess) && _game.Items.Has(ItemType.Hammer)) return AccessibilityLevel.Normal; - } - - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { - List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); - newExcludedRegions.Add(ID); - - // Standard and Open modes - if (_game.Mode.WorldState == WorldState.StandardOpen) - { - // Access via Dark World Witch area by hookshot - if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Hookshot) && - !excludedRegions.Contains(RegionID.DarkWorldWitchArea)) - return _game.Regions[RegionID.DarkWorldWitchArea].GetAccessibility(newExcludedRegions); - } - // Inverted mode - if (_game.Mode.WorldState == WorldState.Inverted) - { AccessibilityLevel dWSouth = AccessibilityLevel.None; AccessibilityLevel dWWitch = AccessibilityLevel.None; AccessibilityLevel lightWorld = AccessibilityLevel.None; @@ -255,28 +240,31 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DarkWorldWestAccess]); - itemReqs.Add(_game.Items[ItemType.BumperCaveAccess]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.HammerHouseAccess]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Hookshot]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DarkWorldWitchArea, new Mode()); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode() { WorldState = WorldState.Inverted }); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); - _observedRegions.Add(RegionID.DarkWorldSouth); - _observedRegions.Add(RegionID.DarkWorldWitchArea); - _observedRegions.Add(RegionID.LightWorld); + _itemSubscriptions.Add(ItemType.DarkWorldWestAccess, new Mode()); + _itemSubscriptions.Add(ItemType.BumperCaveAccess, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.HammerHouseAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.Hookshot, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.DarkWorldSouth: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access via exits in the region if (_game.Items.Has(ItemType.DarkWorldSouthAccess)) return AccessibilityLevel.Normal; + List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); + newExcludedRegions.Add(ID); + // Standard and Open modes if (_game.Mode.WorldState == WorldState.StandardOpen) { @@ -284,45 +272,29 @@ public Region(Game game, RegionID iD) if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.Gloves)) return AccessibilityLevel.Normal; - } - // Inverted mode - if (_game.Mode.WorldState == WorldState.Inverted) - { - // Access is provided from the start in non-entrance shuffle - if (!_game.Mode.EntranceShuffle.Value) - return AccessibilityLevel.Normal; - } - - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { - List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); - newExcludedRegions.Add(ID); - - // Standard and Open modes - if (_game.Mode.WorldState == WorldState.StandardOpen) - { - AccessibilityLevel darkWorldWest = AccessibilityLevel.None; - AccessibilityLevel darkWorldEast = AccessibilityLevel.None; + AccessibilityLevel dWWest = AccessibilityLevel.None; + AccessibilityLevel dWEast = AccessibilityLevel.None; // Access via Dark World West if (!excludedRegions.Contains(RegionID.DarkWorldWest)) - darkWorldWest = _game.Regions[RegionID.DarkWorldWest].GetAccessibility(newExcludedRegions); + dWWest = _game.Regions[RegionID.DarkWorldWest].GetAccessibility(newExcludedRegions); // Access via Dark World East by hammer if (_game.Items.Has(ItemType.Hammer) && _game.Items.Has(ItemType.MoonPearl) && !excludedRegions.Contains(RegionID.DarkWorldEast)) - darkWorldEast = _game.Regions[RegionID.DarkWorldEast].GetAccessibility(newExcludedRegions); + dWEast = _game.Regions[RegionID.DarkWorldEast].GetAccessibility(newExcludedRegions); - return (AccessibilityLevel)Math.Max((byte)darkWorldWest, (byte)darkWorldEast); + return (AccessibilityLevel)Math.Max((byte)dWWest, (byte)dWEast); } // Inverted mode if (_game.Mode.WorldState == WorldState.Inverted) { + // Access is provided from the start in non-entrance shuffle + if (!_game.Mode.EntranceShuffle.Value) + return AccessibilityLevel.Normal; + AccessibilityLevel dWWest = AccessibilityLevel.None; AccessibilityLevel dWEast = AccessibilityLevel.None; AccessibilityLevel lightWorld = AccessibilityLevel.None; @@ -346,25 +318,28 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DarkWorldSouthAccess]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); + _regionSubscriptions.Add(RegionID.DarkWorldEast, new Mode()); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); - _observedRegions.Add(RegionID.DarkWorldWest); - _observedRegions.Add(RegionID.DarkWorldEast); - _observedRegions.Add(RegionID.LightWorld); + _itemSubscriptions.Add(ItemType.DarkWorldSouthAccess, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.DarkWorldEast: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access via exits in the region if (_game.Items.Has(ItemType.DarkWorldEastAccess)) return AccessibilityLevel.Normal; + List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); + newExcludedRegions.Add(ID); + // Standard and Open modes if (_game.Mode.WorldState == WorldState.StandardOpen) { @@ -372,28 +347,16 @@ public Region(Game game, RegionID iD) if (_game.Items.Has(ItemType.Aga)) return AccessibilityLevel.Normal; - if (_game.Items.Has(ItemType.MoonPearl) && _game.Items.Has(ItemType.Gloves) && - _game.Items.Has(ItemType.Hammer)) - return AccessibilityLevel.Normal; - } - - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { - List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); - newExcludedRegions.Add(ID); - - // Standard and Open modes - if (_game.Mode.WorldState == WorldState.StandardOpen) - { AccessibilityLevel darkWorldWitch = AccessibilityLevel.None; AccessibilityLevel darkWorldSouth = AccessibilityLevel.None; AccessibilityLevel darkWorldSouthEast = AccessibilityLevel.None; if (_game.Items.Has(ItemType.MoonPearl)) { + // Access via south of Eastern Palace portal + if (_game.Items.Has(ItemType.Gloves) && _game.Items.Has(ItemType.Hammer)) + return AccessibilityLevel.Normal; + // Access via Dark World Witch area if ((_game.Items.Has(ItemType.Gloves) || _game.Items.Has(ItemType.Hammer)) && !excludedRegions.Contains(RegionID.DarkWorldWitchArea)) @@ -431,63 +394,74 @@ public Region(Game game, RegionID iD) // Inverted mode if (_game.Mode.WorldState == WorldState.Inverted) { - AccessibilityLevel dWSouth = AccessibilityLevel.None; AccessibilityLevel dWWitch = AccessibilityLevel.None; + AccessibilityLevel dWSouth = AccessibilityLevel.None; + AccessibilityLevel dWSouthEast = AccessibilityLevel.None; AccessibilityLevel lightWorld = AccessibilityLevel.None; + // Access via Dark World Witch area by hammer or gloves + if ((_game.Items.Has(ItemType.Gloves) || _game.Items.Has(ItemType.Hammer)) + && !excludedRegions.Contains(RegionID.DarkWorldWitchArea)) + dWWitch = _game.Regions[RegionID.DarkWorldWitchArea].GetAccessibility(newExcludedRegions); + // Access via South Dark World by hammer, flippers, or fake flippers sequence break if (!excludedRegions.Contains(RegionID.DarkWorldSouth)) { if (_game.Items.Has(ItemType.Hammer) || _game.Items.Has(ItemType.Flippers)) dWSouth = _game.Regions[RegionID.DarkWorldSouth].GetAccessibility(newExcludedRegions); else + { dWSouth = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, (byte)_game.Regions[RegionID.DarkWorldSouth].GetAccessibility(newExcludedRegions)); + } } - // Access via Dark World Witch area by hammer or gloves - if ((_game.Items.Has(ItemType.Gloves) || _game.Items.Has(ItemType.Hammer)) - && !excludedRegions.Contains(RegionID.DarkWorldWitchArea)) - dWWitch = _game.Regions[RegionID.DarkWorldWitchArea].GetAccessibility(newExcludedRegions); + // Access via Southeast Dark World by flippers or fake flippers sequence break + if (!excludedRegions.Contains(RegionID.DarkWorldSouthEast)) + { + if (_game.Items.Has(ItemType.Flippers)) + dWSouthEast = _game.Regions[RegionID.DarkWorldSouthEast].GetAccessibility(newExcludedRegions); + else + { + dWSouthEast = (AccessibilityLevel)Math.Min((byte)AccessibilityLevel.SequenceBreak, + (byte)_game.Regions[RegionID.DarkWorldSouthEast].GetAccessibility(newExcludedRegions)); + } + } // Access via Light World by mirror if (_game.Items.Has(ItemType.Mirror) && !excludedRegions.Contains(RegionID.LightWorld)) lightWorld = _game.Regions[RegionID.LightWorld].GetAccessibility(newExcludedRegions); - return (AccessibilityLevel)Math.Max(Math.Max((byte)dWSouth, (byte)dWWitch), (byte)lightWorld); + return (AccessibilityLevel)Math.Max(Math.Max(Math.Max((byte)dWWitch, (byte)dWSouth), + (byte)dWSouthEast), (byte)lightWorld); } // Default to no access return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DarkWorldEastAccess]); - itemReqs.Add(_game.Items[ItemType.Aga]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Flippers]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DarkWorldWitchArea, new Mode()); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode()); + _regionSubscriptions.Add(RegionID.DarkWorldSouthEast, new Mode()); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); - _observedRegions.Add(RegionID.DarkWorldWitchArea); - _observedRegions.Add(RegionID.DarkWorldSouth); - _observedRegions.Add(RegionID.DarkWorldSouthEast); - _observedRegions.Add(RegionID.LightWorld); + _itemSubscriptions.Add(ItemType.DarkWorldEastAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Aga, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Flippers, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.DarkWorldSouthEast: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access via exits in the region if (_game.Items.Has(ItemType.DarkWorldSouthEastAccess)) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -561,29 +535,24 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DarkWorldSouthEastAccess]); - itemReqs.Add(_game.Items[ItemType.Flippers]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode()); + _regionSubscriptions.Add(RegionID.DarkWorldEast, new Mode()); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); - _observedRegions.Add(RegionID.DarkWorldSouth); - _observedRegions.Add(RegionID.DarkWorldEast); - _observedRegions.Add(RegionID.LightWorld); + _itemSubscriptions.Add(ItemType.DarkWorldSouthEastAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Flippers, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.DarkWorldWitchArea: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access via exits in the region if (_game.Items.Has(ItemType.DarkWorldWitchAreaAccess)) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -652,9 +621,16 @@ public Region(Game game, RegionID iD) } } - // Access via Light World by mirror - if (_game.Items.Has(ItemType.Mirror) && !excludedRegions.Contains(RegionID.LightWorld)) - lightWorld = _game.Regions[RegionID.LightWorld].GetAccessibility(newExcludedRegions); + if (_game.Items.Has(ItemType.Mirror)) + { + // Access via Witch's Hut area by mirror + if (_game.Items.Has(ItemType.WitchsHutAccess)) + return AccessibilityLevel.Normal; + + // Access via Light World by mirror (requires moon pearl to reach mirror area) + if (_game.Items.Has(ItemType.MoonPearl) && !excludedRegions.Contains(RegionID.LightWorld)) + lightWorld = _game.Regions[RegionID.LightWorld].GetAccessibility(newExcludedRegions); + } return (AccessibilityLevel)Math.Max(Math.Max((byte)darkWorldEast, (byte)darkWorldWest), (byte)lightWorld); @@ -664,26 +640,30 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DarkWorldWitchAreaAccess]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Flippers]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DarkWorldEast, new Mode()); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode()); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); - _observedRegions.Add(RegionID.DarkWorldEast); - _observedRegions.Add(RegionID.DarkWorldWest); - _observedRegions.Add(RegionID.LightWorld); + _itemSubscriptions.Add(ItemType.DarkWorldWitchAreaAccess, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Flippers, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.WitchsHutAccess, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.MireArea: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access via exits in the region if (_game.Items.Has(ItemType.MireAreaAccess)) return AccessibilityLevel.Normal; + List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); + newExcludedRegions.Add(ID); + // Standard and Open modes if (_game.Mode.WorldState == WorldState.StandardOpen) { @@ -692,14 +672,6 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.Normal; } - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { - List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); - newExcludedRegions.Add(ID); - // Inverted mode if (_game.Mode.WorldState == WorldState.Inverted) { @@ -714,26 +686,34 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MireAreaAccess]); - itemReqs.Add(_game.Items[ItemType.Flute]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); - _observedRegions.Add(RegionID.LightWorld); + _itemSubscriptions.Add(ItemType.MireAreaAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Flute, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.DeathMountainWestBottom: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access via exits in the region if (_game.Items.Has(ItemType.DeathMountainWestBottomAccess)) return AccessibilityLevel.Normal; + List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); + newExcludedRegions.Add(ID); + // Standard and Open modes if (_game.Mode.WorldState == WorldState.StandardOpen) { + AccessibilityLevel direct = AccessibilityLevel.None; + AccessibilityLevel dMWestTop = AccessibilityLevel.None; + AccessibilityLevel dMEastBottom = AccessibilityLevel.None; + AccessibilityLevel dDMWestBottom = AccessibilityLevel.None; + // Access via Flute drop spot if (_game.Items.Has(ItemType.Flute)) return AccessibilityLevel.Normal; @@ -746,24 +726,8 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.Normal; // Sequence Break dark room - return AccessibilityLevel.SequenceBreak; + direct = AccessibilityLevel.SequenceBreak; } - } - - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { - List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); - newExcludedRegions.Add(ID); - - // Standard and Open modes - if (_game.Mode.WorldState == WorldState.StandardOpen) - { - AccessibilityLevel dMWestTop = AccessibilityLevel.None; - AccessibilityLevel dMEastBottom = AccessibilityLevel.None; - AccessibilityLevel dDMWestBottom = AccessibilityLevel.None; // Access via West Death Mountain top if (!excludedRegions.Contains(RegionID.DeathMountainWestTop)) @@ -777,7 +741,8 @@ public Region(Game game, RegionID iD) if (_game.Items.Has(ItemType.Mirror) && !excludedRegions.Contains(RegionID.DarkDeathMountainWestBottom)) dDMWestBottom = _game.Regions[RegionID.DarkDeathMountainWestBottom].GetAccessibility(newExcludedRegions); - return (AccessibilityLevel)Math.Max(Math.Max((byte)dMWestTop, (byte)dMEastBottom), (byte)dDMWestBottom); + return (AccessibilityLevel)Math.Max(Math.Max(Math.Max((byte)direct, (byte)dMWestTop), + (byte)dMEastBottom), (byte)dDMWestBottom); } // Inverted mode @@ -807,32 +772,27 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DeathMountainWestBottomAccess]); - itemReqs.Add(_game.Items[ItemType.Flute]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Lamp]); - itemReqs.Add(_game.Items[ItemType.Hookshot]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DeathMountainWestTop, new Mode()); + _regionSubscriptions.Add(RegionID.DeathMountainEastBottom, new Mode()); + _regionSubscriptions.Add(RegionID.DarkDeathMountainWestBottom, new Mode()); - _observedRegions.Add(RegionID.DeathMountainWestTop); - _observedRegions.Add(RegionID.DeathMountainEastBottom); - _observedRegions.Add(RegionID.DarkDeathMountainWestBottom); + _itemSubscriptions.Add(ItemType.DeathMountainWestBottomAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Flute, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Lamp, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Hookshot, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.DeathMountainWestTop: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access via exits in the region if (_game.Items.Has(ItemType.DeathMountainWestTopAccess)) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -874,19 +834,19 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DeathMountainWestTopAccess]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode()); + _regionSubscriptions.Add(RegionID.DarkDeathMountainWestBottom, new Mode() { WorldState = WorldState.StandardOpen }); + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode() { WorldState = WorldState.StandardOpen }); - _observedRegions.Add(RegionID.DeathMountainEastTop); - _observedRegions.Add(RegionID.DarkDeathMountainWestBottom); - _observedRegions.Add(RegionID.DarkDeathMountainTop); + _itemSubscriptions.Add(ItemType.DeathMountainWestTopAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.DeathMountainEastBottom: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access via exits in the region if (_game.Items.Has(ItemType.DeathMountainEastTopConnectorAccess) || @@ -894,6 +854,9 @@ public Region(Game game, RegionID iD) _game.Items.Has(ItemType.SpiralCaveTopAccess)) return AccessibilityLevel.Normal; + List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); + newExcludedRegions.Add(ID); + // Standard and Open modes if (_game.Mode.WorldState == WorldState.StandardOpen) { @@ -902,19 +865,7 @@ public Region(Game game, RegionID iD) _game.Items.Has(ItemType.TurtleRockSafetyDoorAccess) && _game.Items.Has(ItemType.Mirror)) return AccessibilityLevel.Normal; - } - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { - List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); - newExcludedRegions.Add(ID); - - // Standard and Open modes - if (_game.Mode.WorldState == WorldState.StandardOpen) - { AccessibilityLevel dMEastTop = AccessibilityLevel.None; AccessibilityLevel dMWestBottom = AccessibilityLevel.None; AccessibilityLevel dDMEastBottom = AccessibilityLevel.None; @@ -961,34 +912,29 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DeathMountainEastTopConnectorAccess]); - itemReqs.Add(_game.Items[ItemType.DeathMountainEastBottomAccess]); - itemReqs.Add(_game.Items[ItemType.SpiralCaveTopAccess]); - itemReqs.Add(_game.Items[ItemType.TurtleRockTunnelAccess]); - itemReqs.Add(_game.Items[ItemType.TurtleRockSafetyDoorAccess]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.Hookshot]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode()); + _regionSubscriptions.Add(RegionID.DeathMountainWestBottom, new Mode()); + _regionSubscriptions.Add(RegionID.DarkDeathMountainEastBottom, new Mode()); - _observedRegions.Add(RegionID.DeathMountainEastTop); - _observedRegions.Add(RegionID.DeathMountainWestBottom); - _observedRegions.Add(RegionID.DarkDeathMountainEastBottom); + _itemSubscriptions.Add(ItemType.DeathMountainEastTopConnectorAccess, new Mode()); + _itemSubscriptions.Add(ItemType.DeathMountainEastBottomAccess, new Mode()); + _itemSubscriptions.Add(ItemType.SpiralCaveTopAccess, new Mode()); + _itemSubscriptions.Add(ItemType.TurtleRockTunnelAccess, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.TurtleRockSafetyDoorAccess, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Hookshot, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.DeathMountainEastTop: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access via exits in the region if (_game.Items.Has(ItemType.DeathMountainEastTopAccess)) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -1043,31 +989,26 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DeathMountainEastTopAccess]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Gloves]); + _regionSubscriptions.Add(RegionID.DeathMountainWestTop, new Mode()); + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode()); + _regionSubscriptions.Add(RegionID.DeathMountainEastBottom, new Mode()); - _observedRegions.Add(RegionID.DarkDeathMountainTop); - _observedRegions.Add(RegionID.DeathMountainWestTop); - _observedRegions.Add(RegionID.DeathMountainEastBottom); + _itemSubscriptions.Add(ItemType.DeathMountainEastTopAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Hammer, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.DarkDeathMountainTop: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access via exits in the region if (_game.Items.Has(ItemType.DarkDeathMountainFloatingIslandAccess) || _game.Items.Has(ItemType.DarkDeathMountainTopAccess)) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -1127,32 +1068,27 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DarkDeathMountainFloatingIslandAccess]); - itemReqs.Add(_game.Items[ItemType.DarkDeathMountainTopAccess]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode()); + _regionSubscriptions.Add(RegionID.DarkDeathMountainEastBottom, new Mode()); + _regionSubscriptions.Add(RegionID.DarkDeathMountainWestBottom, new Mode() { WorldState = WorldState.Inverted }); + _regionSubscriptions.Add(RegionID.DeathMountainWestTop, new Mode() { WorldState = WorldState.Inverted }); - _observedRegions.Add(RegionID.DeathMountainEastTop); - _observedRegions.Add(RegionID.DarkDeathMountainEastBottom); - _observedRegions.Add(RegionID.DarkDeathMountainWestBottom); - _observedRegions.Add(RegionID.DeathMountainWestTop); + _itemSubscriptions.Add(ItemType.DarkDeathMountainFloatingIslandAccess, new Mode()); + _itemSubscriptions.Add(ItemType.DarkDeathMountainTopAccess, new Mode()); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Hammer, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.DarkDeathMountainEastBottom: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access via exits in the region if (_game.Items.Has(ItemType.DarkDeathMountainEastBottomAccess)) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -1194,41 +1130,22 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DarkDeathMountainEastBottomAccess]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode()); + _regionSubscriptions.Add(RegionID.DeathMountainEastBottom, new Mode()); - _observedRegions.Add(RegionID.DarkDeathMountainTop); - _observedRegions.Add(RegionID.DeathMountainEastBottom); + _itemSubscriptions.Add(ItemType.DarkDeathMountainEastBottomAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.DarkDeathMountainWestBottom: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access via exits in the region if (_game.Items.Has(ItemType.DarkDeathMountainWestBottomAccess)) return AccessibilityLevel.Normal; - if (_game.Mode.WorldState == WorldState.Inverted) - { - // Access via Death Mountain Entry cave (non-entrance shuffle only) - if (!_game.Mode.EntranceShuffle.Value && _game.Items.Has(ItemType.Gloves)) - { - // Lamp required by logic - if (_game.Items.Has(ItemType.Lamp)) - return AccessibilityLevel.Normal; - - // Sequence break dark room - return AccessibilityLevel.SequenceBreak; - } - } - - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -1252,10 +1169,22 @@ public Region(Game game, RegionID iD) // Inverted mode if (_game.Mode.WorldState == WorldState.Inverted) { + AccessibilityLevel direct = AccessibilityLevel.None; AccessibilityLevel lightWorld = AccessibilityLevel.None; AccessibilityLevel dDMTop = AccessibilityLevel.None; AccessibilityLevel dMWestBottom = AccessibilityLevel.None; + // Access via Death Mountain Entry cave (non-entrance shuffle only) + if (!_game.Mode.EntranceShuffle.Value && _game.Items.Has(ItemType.Gloves)) + { + // Lamp required by logic + if (_game.Items.Has(ItemType.Lamp)) + return AccessibilityLevel.Normal; + + // Sequence break dark room + direct = AccessibilityLevel.SequenceBreak; + } + // Access via Flute drop spot if (_game.Items.Has(ItemType.Flute) && _game.Items.Has(ItemType.MoonPearl) && !excludedRegions.Contains(RegionID.LightWorld)) @@ -1269,90 +1198,80 @@ public Region(Game game, RegionID iD) if (_game.Items.Has(ItemType.Mirror) && !excludedRegions.Contains(RegionID.DeathMountainWestBottom)) dMWestBottom = _game.Regions[RegionID.DeathMountainWestBottom].GetAccessibility(newExcludedRegions); - return (AccessibilityLevel)Math.Max(Math.Max((byte)lightWorld, (byte)dDMTop), (byte)dMWestBottom); + return (AccessibilityLevel)Math.Max(Math.Max(Math.Max((byte)direct, (byte)lightWorld), + (byte)dDMTop), (byte)dMWestBottom); } // Default to no access return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.DarkDeathMountainWestBottomAccess]); - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.Lamp]); - itemReqs.Add(_game.Items[ItemType.Flute]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DeathMountainWestBottom, new Mode()); + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode()); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); - _observedRegions.Add(RegionID.DarkDeathMountainTop); - _observedRegions.Add(RegionID.DeathMountainWestBottom); - _observedRegions.Add(RegionID.LightWorld); + _itemSubscriptions.Add(ItemType.DarkDeathMountainWestBottomAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.Lamp, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.Flute, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.TurtleRockTunnel: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access via exits in the region if (_game.Items.Has(ItemType.TurtleRockTunnelAccess)) return AccessibilityLevel.Normal; - // Inverted mode - if (_game.Mode.WorldState == WorldState.Inverted) - { - if ((_game.Items.Has(ItemType.SpiralCaveTopAccess) || - _game.Items.Has(ItemType.MimicCaveAccess)) && - _game.Items.Has(ItemType.Mirror)) - return AccessibilityLevel.Normal; - } - - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); // Inverted mode if (_game.Mode.WorldState == WorldState.Inverted) { - // Access via East Death Mountain top by mirror from Spiral Cave or Mimic Cave ledges - if (_game.Items.Has(ItemType.Mirror) && !excludedRegions.Contains(RegionID.DeathMountainEastTop)) - return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; + if (_game.Items.Has(ItemType.Mirror)) + { + // Access via mirror from Spiral Cave top and Mimic Cave ledges + if (_game.Items.Has(ItemType.SpiralCaveTopAccess) || + _game.Items.Has(ItemType.MimicCaveAccess)) + return AccessibilityLevel.Normal; + + // Access via East Death Mountain top by mirror from Spiral Cave or Mimic Cave ledges + if (!excludedRegions.Contains(RegionID.DeathMountainEastTop)) + return _game.Regions[RegionID.DeathMountainEastTop].Accessibility; + } } // Default to no access return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.TurtleRockTunnelAccess]); - itemReqs.Add(_game.Items[ItemType.SpiralCaveTopAccess]); - itemReqs.Add(_game.Items[ItemType.MimicCaveAccess]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode() { WorldState = WorldState.Inverted }); - _observedRegions.Add(RegionID.DeathMountainEastTop); + _itemSubscriptions.Add(ItemType.TurtleRockTunnelAccess, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.SpiralCaveTopAccess, new Mode() { WorldState = WorldState.Inverted }); + _itemSubscriptions.Add(ItemType.MimicCaveAccess, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.HyruleCastle: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access to dungeons assumed available with entrance shuffle if (_game.Mode.EntranceShuffle.Value) return AccessibilityLevel.Normal; + List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); + newExcludedRegions.Add(ID); + // Standard and Open modes if (_game.Mode.WorldState == WorldState.StandardOpen) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { - List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); - newExcludedRegions.Add(ID); - // Inverted mode if (_game.Mode.WorldState == WorldState.Inverted) { @@ -1365,19 +1284,22 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() { WorldState = WorldState.Inverted }); - _observedRegions.Add(RegionID.LightWorld); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.Agahnim: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access to dungeons assumed available with entrance shuffle if (_game.Mode.EntranceShuffle.Value) return AccessibilityLevel.Normal; + List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); + newExcludedRegions.Add(ID); + // Standard and Open modes if (_game.Mode.WorldState == WorldState.StandardOpen) { @@ -1386,14 +1308,6 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.Normal; } - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { - List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); - newExcludedRegions.Add(ID); - // Inverted mode if (_game.Mode.WorldState == WorldState.Inverted) { @@ -1405,33 +1319,44 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Cape]); - itemReqs.Add(_game.Items[ItemType.Sword]); - itemReqs.Add(_game.Items[ItemType.Hammer]); + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode() + { + WorldState = WorldState.Inverted, + EntranceShuffle = false + }); - _observedRegions.Add(RegionID.DarkDeathMountainTop); + _itemSubscriptions.Add(ItemType.Cape, new Mode() + { + WorldState = WorldState.StandardOpen, + EntranceShuffle = false + }); + _itemSubscriptions.Add(ItemType.Sword, new Mode() + { + WorldState = WorldState.StandardOpen, + EntranceShuffle = false + }); + _itemSubscriptions.Add(ItemType.Hammer, new Mode() + { + WorldState = WorldState.StandardOpen, + EntranceShuffle = false + }); break; case RegionID.EasternPalace: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access to dungeons assumed available with entrance shuffle if (_game.Mode.EntranceShuffle.Value) return AccessibilityLevel.Normal; + List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); + newExcludedRegions.Add(ID); + // Standard and Open modes if (_game.Mode.WorldState == WorldState.StandardOpen) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { - List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); - newExcludedRegions.Add(ID); - // Inverted mode if (_game.Mode.WorldState == WorldState.Inverted) { @@ -1444,38 +1369,37 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() + { + WorldState = WorldState.Inverted, + EntranceShuffle = false + }); - _observedRegions.Add(RegionID.LightWorld); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() + { + WorldState = WorldState.Inverted, + EntranceShuffle = false + }); break; case RegionID.DesertPalace: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access to dungeons assumed available with entrance shuffle if (_game.Mode.EntranceShuffle.Value) return AccessibilityLevel.Normal; + List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); + newExcludedRegions.Add(ID); + // Standard and Open modes if (_game.Mode.WorldState == WorldState.StandardOpen) { // Access via Light World entrance by book if (_game.Items.Has(ItemType.Book)) return AccessibilityLevel.Normal; - } - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { - List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); - newExcludedRegions.Add(ID); - - // Standard and Open modes - if (_game.Mode.WorldState == WorldState.StandardOpen) - { // Access via Mire Area by Mirror if (_game.Items.Has(ItemType.Mirror)) return _game.Regions[RegionID.MireArea].GetAccessibility(newExcludedRegions); @@ -1494,27 +1418,30 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Book]); - itemReqs.Add(_game.Items[ItemType.Mirror]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() + { + WorldState = WorldState.Inverted, + EntranceShuffle = false + }); + _regionSubscriptions.Add(RegionID.MireArea, new Mode() + { + WorldState = WorldState.StandardOpen, + EntranceShuffle = false + }); - _observedRegions.Add(RegionID.MireArea); - _observedRegions.Add(RegionID.LightWorld); + _itemSubscriptions.Add(ItemType.Book, new Mode()); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { WorldState = WorldState.StandardOpen }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { WorldState = WorldState.Inverted }); break; case RegionID.TowerOfHera: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access to dungeons assumed available with entrance shuffle if (_game.Mode.EntranceShuffle.Value) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -1537,24 +1464,23 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DeathMountainWestTop, new Mode() { EntranceShuffle = false }); - _observedRegions.Add(RegionID.DeathMountainWestTop); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() + { + WorldState = WorldState.Inverted, + EntranceShuffle = false + }); break; case RegionID.PalaceOfDarkness: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access to dungeons assumed available with entrance shuffle if (_game.Mode.EntranceShuffle.Value) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -1578,24 +1504,23 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldEast, new Mode() { EntranceShuffle = false }); - _observedRegions.Add(RegionID.DarkWorldEast); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() + { + WorldState = WorldState.StandardOpen, + EntranceShuffle = false + }); break; case RegionID.SwampPalace: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access to dungeons assumed available with entrance shuffle if (_game.Mode.EntranceShuffle.Value) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -1619,26 +1544,29 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DarkWorldSouth, new Mode() + { + WorldState = WorldState.StandardOpen, + EntranceShuffle = false + }); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() + { + WorldState = WorldState.Inverted, + EntranceShuffle = false + }); - _observedRegions.Add(RegionID.DarkWorldSouth); - _observedRegions.Add(RegionID.LightWorld); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() { EntranceShuffle = false }); break; case RegionID.SkullWoods: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access to dungeons assumed available with entrance shuffle if (_game.Mode.EntranceShuffle.Value) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -1661,24 +1589,23 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode() { EntranceShuffle = false }); - _observedRegions.Add(RegionID.DarkWorldWest); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() + { + WorldState = WorldState.StandardOpen, + EntranceShuffle = false + }); break; case RegionID.ThievesTown: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access to dungeons assumed available with entrance shuffle if (_game.Mode.EntranceShuffle.Value) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -1701,14 +1628,18 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkWorldWest, new Mode() { EntranceShuffle = false }); - _observedRegions.Add(RegionID.DarkWorldWest); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() + { + WorldState = WorldState.StandardOpen, + EntranceShuffle = false + }); break; case RegionID.IcePalace: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access to dungeons assumed available with entrance shuffle if (_game.Mode.EntranceShuffle.Value) @@ -1743,26 +1674,28 @@ public Region(Game game, RegionID iD) // Default to no access return AccessibilityLevel.None; }; - GetIndirectAccessibility = (excludedRegions) => { return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.Gloves]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Flippers]); + _itemSubscriptions.Add(ItemType.Gloves, new Mode() + { + WorldState = WorldState.StandardOpen, + EntranceShuffle = false + }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() + { + WorldState = WorldState.StandardOpen, + EntranceShuffle = false + }); + _itemSubscriptions.Add(ItemType.Flippers, new Mode() { EntranceShuffle = false }); break; case RegionID.MiseryMire: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access to dungeons assumed available with entrance shuffle if (_game.Mode.EntranceShuffle.Value) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -1810,31 +1743,30 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Sword]); - itemReqs.Add(_game.Items[ItemType.Bombos]); - itemReqs.Add(_game.Items[ItemType.BombosDungeons]); - itemReqs.Add(_game.Items[ItemType.Ether]); - itemReqs.Add(_game.Items[ItemType.EtherDungeons]); - itemReqs.Add(_game.Items[ItemType.Quake]); - itemReqs.Add(_game.Items[ItemType.QuakeDungeons]); + _regionSubscriptions.Add(RegionID.MireArea, new Mode() { EntranceShuffle = false }); - _observedRegions.Add(RegionID.MireArea); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() + { + WorldState = WorldState.StandardOpen, + EntranceShuffle = false + }); + _itemSubscriptions.Add(ItemType.Sword, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.Bombos, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.BombosDungeons, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.Ether, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.EtherDungeons, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.Quake, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.QuakeDungeons, new Mode() { EntranceShuffle = false }); break; case RegionID.TurtleRock: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access to dungeons assumed available with entrance shuffle if (_game.Mode.EntranceShuffle.Value) return AccessibilityLevel.Normal; - // Default to no access - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -1884,33 +1816,45 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.MoonPearl]); - itemReqs.Add(_game.Items[ItemType.Hammer]); - itemReqs.Add(_game.Items[ItemType.Sword]); - itemReqs.Add(_game.Items[ItemType.Bombos]); - itemReqs.Add(_game.Items[ItemType.BombosDungeons]); - itemReqs.Add(_game.Items[ItemType.Ether]); - itemReqs.Add(_game.Items[ItemType.EtherDungeons]); - itemReqs.Add(_game.Items[ItemType.Quake]); - itemReqs.Add(_game.Items[ItemType.QuakeDungeons]); - itemReqs.Add(_game.Items[ItemType.Mirror]); + _regionSubscriptions.Add(RegionID.DeathMountainEastTop, new Mode() + { + WorldState = WorldState.Inverted, + EntranceShuffle = false + }); + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode() { EntranceShuffle = false }); - _observedRegions.Add(RegionID.DeathMountainEastTop); - _observedRegions.Add(RegionID.DarkDeathMountainTop); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() + { + WorldState = WorldState.StandardOpen, + EntranceShuffle = false + }); + _itemSubscriptions.Add(ItemType.Hammer, new Mode() + { + WorldState = WorldState.StandardOpen, + EntranceShuffle = false + }); + _itemSubscriptions.Add(ItemType.Sword, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.Bombos, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.BombosDungeons, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.Ether, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.EtherDungeons, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.Quake, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.QuakeDungeons, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.Mirror, new Mode() + { + WorldState = WorldState.Inverted, + EntranceShuffle = false + }); break; case RegionID.GanonsTower: - GetDirectAccessibility = () => + GetAccessibility = (excludedRegions) => { // Access to dungeons assumed available with entrance shuffle if (_game.Mode.EntranceShuffle.Value) return AccessibilityLevel.Normal; - return AccessibilityLevel.None; - }; - GetIndirectAccessibility = (excludedRegions) => - { List newExcludedRegions = excludedRegions.GetRange(0, excludedRegions.Count); newExcludedRegions.Add(ID); @@ -1936,60 +1880,126 @@ public Region(Game game, RegionID iD) return AccessibilityLevel.None; }; - itemReqs.Add(_game.Items[ItemType.TowerCrystals]); - itemReqs.Add(_game.Items[ItemType.Crystal]); - itemReqs.Add(_game.Items[ItemType.RedCrystal]); - itemReqs.Add(_game.Items[ItemType.MoonPearl]); + _regionSubscriptions.Add(RegionID.DarkDeathMountainTop, new Mode() + { + WorldState = WorldState.StandardOpen, + EntranceShuffle = false + }); + _regionSubscriptions.Add(RegionID.LightWorld, new Mode() + { + WorldState = WorldState.Inverted, + EntranceShuffle = false + }); + + _itemSubscriptions.Add(ItemType.TowerCrystals, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.Crystal, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.RedCrystal, new Mode() { EntranceShuffle = false }); + _itemSubscriptions.Add(ItemType.MoonPearl, new Mode() { EntranceShuffle = false }); - _observedRegions.Add(RegionID.DarkDeathMountainTop); - _observedRegions.Add(RegionID.LightWorld); break; } - foreach (Item itemReq in itemReqs) - itemReq.PropertyChanged += OnItemRequirementChanged; + _game.Mode.PropertyChanged += OnModeChanged; + + UpdateItemSubscriptions(); } - private void UpdateAccessibility() + private void OnPropertyChanged(string propertyName) { - DirectAccessibility = GetDirectAccessibility(); - Accessibility = (AccessibilityLevel)Math.Max((byte)DirectAccessibility, - (byte)GetIndirectAccessibility(new List())); + if (PropertyChanged != null) + PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private void OnModeChanged(object sender, PropertyChangedEventArgs e) { + UpdateRegionSubscriptions(); + UpdateItemSubscriptions(); + if (e.PropertyName == nameof(_game.Mode.WorldState) || e.PropertyName == nameof(_game.Mode.EntranceShuffle)) UpdateAccessibility(); } - private void OnItemRequirementChanged(object sender, PropertyChangedEventArgs e) + private void OnRequirementChanged(object sender, PropertyChangedEventArgs e) { UpdateAccessibility(); } - private void OnPropertyChanged(string propertyName) + private void UpdateItemSubscriptions() { - if (PropertyChanged != null) - PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); + foreach (ItemType item in _itemSubscriptions.Keys) + { + if (_game.Mode.Validate(_itemSubscriptions[item])) + { + if (_itemIsSubscribed.ContainsKey(item)) + { + if (!_itemIsSubscribed[item]) + { + _itemIsSubscribed[item] = true; + _game.Items[item].PropertyChanged += OnRequirementChanged; + } + } + else + { + _itemIsSubscribed.Add(item, true); + _game.Items[item].PropertyChanged += OnRequirementChanged; + } + } + else + { + if (_itemIsSubscribed.ContainsKey(item)) + { + if (_itemIsSubscribed[item]) + { + _itemIsSubscribed[item] = false; + _game.Items[item].PropertyChanged -= OnRequirementChanged; + } + } + else + _itemIsSubscribed.Add(item, false); + } + } } - public AccessibilityLevel GetAccessibility(List excludedRegions) + public void UpdateRegionSubscriptions() { - if (DirectAccessibility == AccessibilityLevel.Normal) - return DirectAccessibility; - - AccessibilityLevel indirectAccessibility = GetIndirectAccessibility(excludedRegions); - - return (AccessibilityLevel)Math.Max((byte)DirectAccessibility, - (byte)indirectAccessibility); + foreach (RegionID region in _regionSubscriptions.Keys) + { + if (_game.Mode.Validate(_regionSubscriptions[region])) + { + if (_regionIsSubscribed.ContainsKey(region)) + { + if (!_regionIsSubscribed[region]) + { + _regionIsSubscribed[region] = true; + _game.Regions[region].PropertyChanged += OnRequirementChanged; + } + } + else + { + _regionIsSubscribed.Add(region, true); + _game.Regions[region].PropertyChanged += OnRequirementChanged; + } + } + else + { + if (_regionIsSubscribed.ContainsKey(region)) + { + if (_regionIsSubscribed[region]) + { + _regionIsSubscribed[region] = false; + _game.Regions[region].PropertyChanged -= OnRequirementChanged; + } + } + else + _regionIsSubscribed.Add(region, false); + } + } } - public void SubscribeToRegions() + public void UpdateAccessibility() { - foreach (RegionID iD in _observedRegions) - _game.Regions[iD].PropertyChanged += OnItemRequirementChanged; + Accessibility = GetAccessibility(new List()); } } } diff --git a/OpenTracker.Setup/OpenTracker.Setup.vdproj b/OpenTracker.Setup/OpenTracker.Setup.vdproj index 308c1927..841d920a 100644 --- a/OpenTracker.Setup/OpenTracker.Setup.vdproj +++ b/OpenTracker.Setup/OpenTracker.Setup.vdproj @@ -274,15 +274,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:OpenTracker" - "ProductCode" = "8:{8560B543-CDC5-4378-A016-E7442882BFE7}" - "PackageCode" = "8:{6477EB62-4D47-47D0-A7B6-FC12ED9C33DB}" + "ProductCode" = "8:{2D8F6709-1B8C-40AC-8BF6-F5138CFB5B7B}" + "PackageCode" = "8:{4B1C3BF1-9E05-452F-9432-946482E80785}" "UpgradeCode" = "8:{C98C2121-B4C5-473A-9B86-5407FEFFE8F1}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:TRUE" - "ProductVersion" = "8:0.7.0" + "ProductVersion" = "8:0.7.1" "Manufacturer" = "8:OpenTracker" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" @@ -824,7 +824,7 @@ { "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_8BEB0D6860DB4F80B56A45FAD1BDE151" { - "SourcePath" = "8:..\\OpenTracker\\obj\\Debug\\netcoreapp3.1\\OpenTracker.exe" + "SourcePath" = "8:..\\OpenTracker\\obj\\Release\\netcoreapp3.1\\OpenTracker.exe" "TargetName" = "8:" "Tag" = "8:" "Folder" = "8:_B21EA2C01C014AC99A33B72F50C26B5D" diff --git a/OpenTracker/OpenTracker.csproj b/OpenTracker/OpenTracker.csproj index 780274d4..2e7f6b82 100644 --- a/OpenTracker/OpenTracker.csproj +++ b/OpenTracker/OpenTracker.csproj @@ -4,10 +4,10 @@ netcoreapp3.1 triforce.ico - 0.7.0 + 0.7.1 Tripp - 0.7.0.0 - 0.7.0.0 + 0.7.1.0 + 0.7.1.0 osx-x64;linux-x64;debian-x64;rhel-x64;win-x64;win-x86;win7-x64;win7-x86 diff --git a/OpenTracker/ViewModels/MainWindowVM.cs b/OpenTracker/ViewModels/MainWindowVM.cs index c21cbef9..db322caf 100644 --- a/OpenTracker/ViewModels/MainWindowVM.cs +++ b/OpenTracker/ViewModels/MainWindowVM.cs @@ -176,7 +176,7 @@ public MainWindowVM() UndoCommand = ReactiveCommand.Create(Undo, this.WhenAnyValue(x => x.CanUndo)); RedoCommand = ReactiveCommand.Create(Redo, this.WhenAnyValue(x => x.CanRedo)); ToggleDisplayAllLocationsCommand = ReactiveCommand.Create(ToggleDisplayAllLocations); - ItemPlacementCommand = ReactiveCommand.Create(SetItemPlacement); + ItemPlacementCommand = ReactiveCommand.Create(SetItemPlacement, this.WhenAnyValue(x => x.WorldStateStandardOpen)); DungeonItemShuffleCommand = ReactiveCommand.Create(SetDungeonItemShuffle); WorldStateCommand = ReactiveCommand.Create(SetWorldState); EntranceShuffleCommand = ReactiveCommand.Create(ToggleEntranceShuffle); diff --git a/OpenTracker/ViewModels/MapLocationControlVM.cs b/OpenTracker/ViewModels/MapLocationControlVM.cs index 3faec230..98daeb5a 100644 --- a/OpenTracker/ViewModels/MapLocationControlVM.cs +++ b/OpenTracker/ViewModels/MapLocationControlVM.cs @@ -102,7 +102,7 @@ public MapLocationControlVM(UndoRedoManager undoRedoManager, AppSettingsVM appSe appSettings.PropertyChanged += OnAppSettingsChanged; game.Mode.PropertyChanged += OnModeChanged; - mapLocation.Location.RequirementChanged += OnItemRequirementChanged; + mapLocation.Location.RequirementChanged += OnRequirementChanged; foreach (ISection section in mapLocation.Location.Sections) section.PropertyChanged += OnSectionChanged; @@ -342,7 +342,7 @@ private void OnModeChanged(object sender, PropertyChangedEventArgs e) SetVisibility(); } - private void OnItemRequirementChanged(object sender, EventArgs e) + private void OnRequirementChanged(object sender, EventArgs e) { SetColor(); SetVisibility();