Skip to content

Commit 81b206b

Browse files
Merge pull request #666 from TheTrackerCouncil/ap-fixes
Archipelago Fixes
2 parents 65676ef + 19635cc commit 81b206b

File tree

23 files changed

+1262
-16
lines changed

23 files changed

+1262
-16
lines changed

src/TrackerCouncil.Smz3.Abstractions/ITrackerGameStateService.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,10 @@ public interface ITrackerGameStateService
109109
public void UpdateLastMarkedLocations(List<Location> locations);
110110

111111
public void ClearLastViewedObject(float confidence);
112+
113+
public void UpdateGanonsTowerRequirement(int crystalAmount, bool autoTracked);
114+
115+
public void UpdateGanonRequirement(int crystalAmount, bool autoTracked);
116+
117+
public void UpdateTourianRequirement(int bossAmount, bool autoTracked);
112118
}

src/TrackerCouncil.Smz3.Data/Configuration/ConfigFiles/ResponseConfig.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,27 @@ public class ResponseConfig : IMergeable<ResponseConfig>, IConfigFile<ResponseCo
627627
/// </summary>
628628
public SchrodingersString? LongSpeechResponse { get; init; }
629629

630+
/// <summary>
631+
/// Gets the phrases for when the player has updated the number of crystals required
632+
/// to get into GT
633+
/// <c>{0}</c> is a placeholder for the number of crystals required
634+
/// </summary>
635+
public SchrodingersString? UpdatedGanonsTowerCrystalRequirement { get; init; }
636+
637+
/// <summary>
638+
/// Gets the phrases for when the player has updated the number of crystals required
639+
/// to defeat Ganon
640+
/// <c>{0}</c> is a placeholder for the number of crystals required
641+
/// </summary>
642+
public SchrodingersString? UpdatedGanonCrystalRequirement { get; init; }
643+
644+
/// <summary>
645+
/// Gets the phrases for when the player has updated the number of bosses required
646+
/// to enter Tourian
647+
/// <c>{0}</c> is a placeholder for the number of bosses required
648+
/// </summary>
649+
public SchrodingersString? UpdatedTourianBossRequirement { get; init; }
650+
630651
/// <summary>
631652
/// Gets a dictionary that contains the phrases to respond with when no
632653
/// voice commands have been issued after a certain period of time, as

src/TrackerCouncil.Smz3.Data/Services/TrackerStateService.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ public TrackerState CreateTrackerState(List<World> worlds)
161161
hintStates.Add(hintState);
162162
}
163163

164+
var localWorld = worlds.First(x => x.IsLocalWorld);
165+
164166
return new TrackerState()
165167
{
166168
LocationStates = locationStates,
@@ -169,10 +171,16 @@ public TrackerState CreateTrackerState(List<World> worlds)
169171
BossStates = bossStates,
170172
RewardStates = rewardStates,
171173
PrerequisiteStates = prereqStates,
172-
LocalWorldId = worlds.First(x => x.IsLocalWorld).Id,
174+
LocalWorldId = localWorld.Id,
173175
Hints = hintStates,
174176
StartDateTime = DateTimeOffset.Now,
175177
UpdatedDateTime = DateTimeOffset.Now,
178+
GanonsTowerCrystalCount = localWorld.Config.GanonsTowerCrystalCount,
179+
MarkedGanonsTowerCrystalCount = localWorld.LegacyWorld == null ? localWorld.Config.GanonsTowerCrystalCount : null,
180+
GanonCrystalCount = localWorld.Config.GanonCrystalCount,
181+
MarkedGanonCrystalCount = localWorld.LegacyWorld == null ? localWorld.Config.GanonCrystalCount : null,
182+
TourianBossCount = localWorld.Config.TourianBossCount,
183+
MarkedTourianBossCount = localWorld.LegacyWorld == null ? localWorld.Config.TourianBossCount : null,
176184
};
177185
}
178186

src/TrackerCouncil.Smz3.Data/TrackerCouncil.Smz3.Data.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
<ItemGroup>
2525
<PackageReference Include="Avalonia" Version="11.0.11" />
26-
<PackageReference Include="MattEqualsCoder.DynamicForms.Core" Version="1.0.2" />
26+
<PackageReference Include="MattEqualsCoder.DynamicForms.Core" Version="1.2.0" />
2727
<PackageReference Include="MattEqualsCoder.GitHubReleaseChecker" Version="1.1.2" />
2828
<PackageReference Include="MattEqualsCoder.MSURandomizer.Library" Version="3.0.1" />
2929
<PackageReference Include="NAudio.Wasapi" Version="2.2.1" />

src/TrackerCouncil.Smz3.Data/WorldData/Regions/SuperMetroid/Crateria/WestCrateria.cs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
24
using TrackerCouncil.Smz3.Shared;
35
using TrackerCouncil.Smz3.Data.Configuration.ConfigTypes;
46
using TrackerCouncil.Smz3.Data.Options;
@@ -30,6 +32,10 @@ public WestCrateria(World world, Config config, IMetadataService? metadata, Trac
3032

3133
public TerminatorRoom Terminator { get; }
3234

35+
public Accessibility MotherBrainAccessibility { get; private set; }
36+
37+
public event EventHandler? UpdatedMotherBrainAccessibility;
38+
3339
public override bool CanEnter(Progression items, bool requireRewards)
3440
{
3541
return Logic.CanDestroyBombWalls(items) || Logic.CanParlorSpeedBoost(items);
@@ -107,4 +113,48 @@ public TerminatorRoom(WestCrateria region, IMetadataService? metadata, TrackerSt
107113
};
108114
}
109115
}
116+
117+
public void UpdateMotherBrainAccessibility(Progression progression)
118+
{
119+
Accessibility NewAccessibility;
120+
121+
var tourianBossRequirement = World.State?.TourianBossCount == null
122+
? Config.TourianBossCount
123+
: World.State?.MarkedTourianBossCount ?? 4;
124+
125+
if (World.Bosses.First(x => x.Type == BossType.MotherBrain).Defeated)
126+
{
127+
NewAccessibility = Accessibility.Cleared;
128+
}
129+
else if (World.LegacyWorld == null)
130+
{
131+
var canAccessStatueRoom = Terminator.Locations.First().IsAvailable(progression) &&
132+
(!World.Config.MetroidKeysanity || World.Config.SkipTourianBossDoor ||
133+
progression.CardCrateriaBoss);
134+
135+
var canEnterTourian = World.GoldenBosses.Count(x => x.Defeated) >= tourianBossRequirement;
136+
137+
NewAccessibility = canAccessStatueRoom && canEnterTourian
138+
? Accessibility.Available
139+
: Accessibility.OutOfLogic;
140+
}
141+
else
142+
{
143+
var canAccessStatueRoom = World.LegacyWorld.IsLocationAccessible((int)LocationId.CrateriaTerminator, progression.LegacyProgression) &&
144+
(!World.Config.MetroidKeysanity || World.Config.SkipTourianBossDoor ||
145+
progression.CardCrateriaBoss);
146+
147+
var canEnterTourian = World.GoldenBosses.Count(x => x.Defeated) >= tourianBossRequirement;
148+
149+
NewAccessibility = canAccessStatueRoom && canEnterTourian
150+
? Accessibility.Available
151+
: Accessibility.OutOfLogic;
152+
}
153+
154+
if (NewAccessibility != MotherBrainAccessibility)
155+
{
156+
MotherBrainAccessibility = NewAccessibility;
157+
UpdatedMotherBrainAccessibility?.Invoke(this, EventArgs.Empty);
158+
}
159+
}
110160
}

src/TrackerCouncil.Smz3.Data/WorldData/Regions/Zelda/DarkWorld/DarkWorldNorthEast.cs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
24
using TrackerCouncil.Smz3.Shared;
35
using TrackerCouncil.Smz3.Data.Configuration.ConfigTypes;
46
using TrackerCouncil.Smz3.Data.Options;
@@ -49,6 +51,10 @@ public DarkWorldNorthEast(World world, Config config, IMetadataService? metadata
4951

5052
public PyramidFairyChamber PyramidFairy { get; }
5153

54+
public Accessibility GanonAccessibility { get; private set; }
55+
56+
public event EventHandler? UpdatedGanonAccessibility;
57+
5258
public override bool CanEnter(Progression items, bool requireRewards)
5359
{
5460
return Logic.CheckAgahnim(items, World, requireRewards) ||
@@ -60,6 +66,62 @@ public override bool CanEnter(Progression items, bool requireRewards)
6066
);
6167
}
6268

69+
public void UpdateGanonAccessibility(Progression progression, Progression assumedKeyProgression)
70+
{
71+
Accessibility NewAccessibility;
72+
73+
var ganonCrystalRequirement = World.State?.GanonCrystalCount == null
74+
? Config.GanonCrystalCount
75+
: World.State?.MarkedGanonCrystalCount ?? 7;
76+
77+
if (World.Bosses.First(x => x.Type == BossType.Ganon).Defeated)
78+
{
79+
NewAccessibility = Accessibility.Cleared;
80+
}
81+
else if (World.LegacyWorld == null)
82+
{
83+
var canAccessPyramid = Pyramid.IsAvailable(progression);
84+
85+
var canClimbGt = World.GanonsTower.CanBeatBoss(progression, true) ||
86+
(!World.Config.ZeldaKeysanity &&
87+
World.GanonsTower.Locations.All(x => x.IsAvailable(assumedKeyProgression)) &&
88+
World.GanonsTower.CanBeatBoss(assumedKeyProgression, true));
89+
90+
var isPyramidOpen = World.Config.OpenPyramid || canClimbGt;
91+
var canHurtGanon = progression.CrystalCount >= ganonCrystalRequirement && progression.MasterSword &&
92+
(progression.Lamp || progression.FireRod);
93+
94+
NewAccessibility = canAccessPyramid && isPyramidOpen && canHurtGanon
95+
? Accessibility.Available
96+
: Accessibility.OutOfLogic;
97+
}
98+
else
99+
{
100+
var canAccessPyramid = World.LegacyWorld.IsLocationAccessible((int)LocationId.Pyramid, progression.LegacyProgression);
101+
102+
var canClimbGt =
103+
World.LegacyWorld.IsLocationAccessible((int)LocationId.GanonsTowerMoldormChest,
104+
progression.LegacyProgression) || (!World.Config.ZeldaKeysanity &&
105+
World.GanonsTower.Locations.All(x =>
106+
World.LegacyWorld.IsLocationAccessible((int)x.Id,
107+
assumedKeyProgression.LegacyProgression)));
108+
109+
var isPyramidOpen = World.Config.OpenPyramid || canClimbGt;
110+
var canHurtGanon = progression.CrystalCount >= ganonCrystalRequirement && progression.MasterSword &&
111+
(progression.Lamp || progression.FireRod);
112+
113+
NewAccessibility = canAccessPyramid && isPyramidOpen && canHurtGanon
114+
? Accessibility.Available
115+
: Accessibility.OutOfLogic;
116+
}
117+
118+
if (NewAccessibility != GanonAccessibility)
119+
{
120+
GanonAccessibility = NewAccessibility;
121+
UpdatedGanonAccessibility?.Invoke(this, EventArgs.Empty);
122+
}
123+
}
124+
63125
public class PyramidFairyChamber : Room
64126
{
65127
public PyramidFairyChamber(Region region, IMetadataService? metadata, TrackerState? trackerState)

src/TrackerCouncil.Smz3.Data/WorldData/Regions/Zelda/GanonsTower.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,13 @@ public GanonsTower(World world, Config config, IMetadataService? metadata, Track
171171

172172
public override bool CanEnter(Progression items, bool requireRewards)
173173
{
174+
var gtCrystalRequirement = World.State?.GanonsTowerCrystalCount == null
175+
? Config.GanonsTowerCrystalCount
176+
: World.State?.MarkedGanonsTowerCrystalCount ?? 7;
177+
174178
var smBosses = new[] { BossType.Kraid, BossType.Phantoon, BossType.Draygon, BossType.Ridley };
175179
var canEnterDDMEast = World.DarkWorldDeathMountainEast.CanEnter(items, requireRewards);
176-
var haveEnoughCrystals = items.CrystalCount >= Config.GanonsTowerCrystalCount;
180+
var haveEnoughCrystals = items.CrystalCount >= gtCrystalRequirement;
177181
var gtOpenBeforeGanon = Config.GanonsTowerCrystalCount < Config.GanonCrystalCount;
178182
var canBeatMetroid = World.CanDefeatBossCount(items, requireRewards, smBosses) >= Config.TourianBossCount;
179183
return World.Logic.CanNavigateDarkWorld(items) && canEnterDDMEast && haveEnoughCrystals && (gtOpenBeforeGanon || canBeatMetroid);

src/TrackerCouncil.Smz3.Data/WorldData/World.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public World(Config config, string player, int id, string guid, bool isLocalWorl
116116

117117
LegacyWorld = new LegacyWorld(legacyConfig, Player, Id, Guid);
118118

119-
UpdateLegacyWorld();
119+
UpdateLegacyWorld(trackerState);
120120
}
121121
}
122122

@@ -323,7 +323,7 @@ private void SetBottles(Random rnd)
323323
}
324324
}
325325

326-
public void UpdateLegacyWorld()
326+
public void UpdateLegacyWorld(TrackerState? trackerState)
327327
{
328328
if (LegacyWorld == null)
329329
{
@@ -354,9 +354,9 @@ public void UpdateLegacyWorld()
354354
GetLegacyRewardType(InnerMaridia),
355355
GetLegacyRewardType(LowerNorfairEast),
356356
],
357-
TowerCrystals = Config.GanonsTowerCrystalCount,
358-
GanonCrystals = Config.GanonCrystalCount,
359-
TourianBossTokens = Config.TourianBossCount
357+
TowerCrystals = trackerState?.MarkedGanonsTowerCrystalCount ?? 7,
358+
GanonCrystals = trackerState?.MarkedGanonCrystalCount ?? 7,
359+
TourianBossTokens = trackerState?.MarkedGanonsTowerCrystalCount ?? 4
360360
};
361361

362362
LegacyWorld.Setup(worldState);

src/TrackerCouncil.Smz3.Data/maps.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,6 +1733,8 @@
17331733
{
17341734
"Name": "Dark World North East",
17351735
"TypeName": "TrackerCouncil.Smz3.Data.WorldData.Regions.Zelda.DarkWorld.DarkWorldNorthEast",
1736+
"BossX": 998,
1737+
"BossY": 815,
17361738
"Rooms": [
17371739
{
17381740
"Name": "Catfish",
@@ -2277,6 +2279,8 @@
22772279
{
22782280
"Name": "West Crateria",
22792281
"TypeName": "TrackerCouncil.Smz3.Data.WorldData.Regions.SuperMetroid.Crateria.WestCrateria",
2282+
"BossX": 453,
2283+
"BossY": 358,
22802284
"Rooms": [
22812285
{
22822286
"Name": "Energy Tank, Gauntlet",

0 commit comments

Comments
 (0)