summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ArchipelagoManager.cs1
-rw-r--r--GameData.cs2
-rw-r--r--GameState.cs37
-rw-r--r--GameplayPatches.cs195
-rw-r--r--Requirements.cs117
-rw-r--r--SlotSave.cs16
-rw-r--r--game_data.yaml38
7 files changed, 309 insertions, 97 deletions
diff --git a/ArchipelagoManager.cs b/ArchipelagoManager.cs index 611ef30..998e2d9 100644 --- a/ArchipelagoManager.cs +++ b/ArchipelagoManager.cs
@@ -87,6 +87,7 @@ namespace ManifoldGardenArchipelago
87 87
88 if (GameData.listenersByItem.TryGetValue(itemName, out var listeners)) 88 if (GameData.listenersByItem.TryGetValue(itemName, out var listeners))
89 { 89 {
90 //Plugin.Logger.LogInfo($"Evaluating for {itemName}");
90 GameState.EvaluateGameStateListeners(listeners); 91 GameState.EvaluateGameStateListeners(listeners);
91 } 92 }
92 } 93 }
diff --git a/GameData.cs b/GameData.cs index 9ec511e..6b5eddc 100644 --- a/GameData.cs +++ b/GameData.cs
@@ -372,6 +372,8 @@ namespace ManifoldGardenArchipelago
372 Requirement req = ParseRequirement(scenePair.Key, (Dictionary<object, object>)smokePair.Value); 372 Requirement req = ParseRequirement(scenePair.Key, (Dictionary<object, object>)smokePair.Value);
373 sceneDescription.smokeWalls[sir.index] = req; 373 sceneDescription.smokeWalls[sir.index] = req;
374 374
375 Plugin.Logger.LogInfo($"Smoke {sir} requirements: {req}");
376
375 foreach (var reqScene in req.references.scenes) 377 foreach (var reqScene in req.references.scenes)
376 { 378 {
377 GetOrAddListeners(listenersByScene, reqScene).smokeWalls[sir] = req; 379 GetOrAddListeners(listenersByScene, reqScene).smokeWalls[sir] = req;
diff --git a/GameState.cs b/GameState.cs index d3bea06..bdf5760 100644 --- a/GameState.cs +++ b/GameState.cs
@@ -112,7 +112,7 @@ namespace ManifoldGardenArchipelago
112 { 112 {
113 foreach (var location in listeners.locations) 113 foreach (var location in listeners.locations)
114 { 114 {
115 if (location.Value.Check()) 115 if (location.Value.Check() == Requirement.Decision.Yes)
116 { 116 {
117 Plugin.archipelagoManager.CheckLocation(location.Key); 117 Plugin.archipelagoManager.CheckLocation(location.Key);
118 } 118 }
@@ -120,8 +120,14 @@ namespace ManifoldGardenArchipelago
120 120
121 foreach (var door in listeners.doors) 121 foreach (var door in listeners.doors)
122 { 122 {
123 bool shouldOpen = door.Value.Check(); 123 Requirement.Decision decision = door.Value.Check();
124 Plugin.Logger.LogInfo($"{door.Key}: {door.Value} -> {shouldOpen}"); 124 if (decision == Requirement.Decision.Maybe)
125 {
126 continue;
127 }
128
129 bool shouldOpen = (decision == Requirement.Decision.Yes);
130 //Plugin.Logger.LogInfo($"{door.Key}: {door.Value} -> {shouldOpen}");
125 131
126 if (SceneManager.GetSceneByName(door.Key.scene) is Scene doorScene && doorScene.isLoaded) 132 if (SceneManager.GetSceneByName(door.Key.scene) is Scene doorScene && doorScene.isLoaded)
127 { 133 {
@@ -142,11 +148,34 @@ namespace ManifoldGardenArchipelago
142 } 148 }
143 } 149 }
144 150
151 foreach (var smokeWall in listeners.smokeWalls)
152 {
153 Requirement.Decision decision = smokeWall.Value.Check();
154 if (decision == Requirement.Decision.Maybe)
155 {
156 continue;
157 }
158
159 bool shouldOpen = (decision == Requirement.Decision.Yes);
160 //Plugin.Logger.LogInfo($"{smokeWall.Key}: {smokeWall.Value} -> {shouldOpen}");
145 161
162 if (SceneManager.GetSceneByName(smokeWall.Key.scene) is Scene smokeScene && smokeScene.isLoaded)
163 {
164 LevelSystems levelSystems = GetLevelSystems(smokeScene);
165 if (levelSystems.isActiveAndEnabled)
166 {
167 SolidStateController ldc = levelSystems.chainListeners[smokeWall.Key.index].GetComponent<SolidStateController>();
168 ldc.chains.Clear();
169
170 FieldInfo fieldInfo = typeof(SolidStateController).GetField("m_isSolid", BindingFlags.Instance | BindingFlags.NonPublic);
171 fieldInfo.SetValue(ldc, !shouldOpen);
172 }
173 }
174 }
146 175
147 foreach (var worldGrow in listeners.worldGrows) 176 foreach (var worldGrow in listeners.worldGrows)
148 { 177 {
149 if (worldGrow.Value.Check()) 178 if (worldGrow.Value.Check() == Requirement.Decision.Yes)
150 { 179 {
151 if (SceneManager.GetSceneByName(worldGrow.Key.scene) is Scene gardenScene && gardenScene.isLoaded) 180 if (SceneManager.GetSceneByName(worldGrow.Key.scene) is Scene gardenScene && gardenScene.isLoaded)
152 { 181 {
diff --git a/GameplayPatches.cs b/GameplayPatches.cs index c21bf97..3090a98 100644 --- a/GameplayPatches.cs +++ b/GameplayPatches.cs
@@ -1,5 +1,6 @@
1using HarmonyLib; 1using HarmonyLib;
2using System.Reflection; 2using System.Reflection;
3using UnityEngine;
3 4
4namespace ManifoldGardenArchipelago 5namespace ManifoldGardenArchipelago
5{ 6{
@@ -14,9 +15,16 @@ namespace ManifoldGardenArchipelago
14 { 15 {
15 if (sceneDescription.doors.TryGetValue(sir.index, out var requirement)) 16 if (sceneDescription.doors.TryGetValue(sir.index, out var requirement))
16 { 17 {
17 if (open != requirement.Check()) 18 Requirement.Decision decision = requirement.Check();
19
20 if (decision != Requirement.Decision.Maybe)
18 { 21 {
19 return false; 22 bool shouldOpen = (decision == Requirement.Decision.Yes);
23
24 if (open != shouldOpen)
25 {
26 return false;
27 }
20 } 28 }
21 } 29 }
22 } 30 }
@@ -38,15 +46,27 @@ namespace ManifoldGardenArchipelago
38 return; 46 return;
39 } 47 }
40 48
41 if (setPressed) 49 Plugin.slotSave.ActivatedButtons[sir] = setPressed;
42 { 50
43 Plugin.slotSave.ActivatedButtons.Add(sir); 51 GameState.EvaluateGameStateListeners(listeners);
44 } 52 }
45 else 53 }
54
55 [HarmonyPatch(typeof(ButtonLineActivator), "ForceButtonPressedImmediately")]
56 static class ButtonLineActivatorForceButtonPressedImmediatelyPatch
57 {
58 static void Prefix(ButtonLineActivator __instance, bool _pressed)
59 {
60 SceneItemReference sir = GameState.GetButtonSceneReference(__instance);
61 Plugin.Logger.LogInfo($"Button {sir} forced state {_pressed}");
62
63 if (!GameData.listenersByButton.TryGetValue(sir, out GameStateListeners listeners))
46 { 64 {
47 Plugin.slotSave.ActivatedButtons.Remove(sir); 65 return;
48 } 66 }
49 67
68 Plugin.slotSave.ActivatedButtons[sir] = _pressed;
69
50 GameState.EvaluateGameStateListeners(listeners); 70 GameState.EvaluateGameStateListeners(listeners);
51 } 71 }
52 } 72 }
@@ -64,14 +84,7 @@ namespace ManifoldGardenArchipelago
64 return; 84 return;
65 } 85 }
66 86
67 if (active) 87 Plugin.slotSave.ActivatedSockets[sir] = active;
68 {
69 Plugin.slotSave.ActivatedSockets.Add(sir);
70 }
71 else
72 {
73 Plugin.slotSave.ActivatedSockets.Remove(sir);
74 }
75 88
76 GameState.EvaluateGameStateListeners(listeners); 89 GameState.EvaluateGameStateListeners(listeners);
77 } 90 }
@@ -90,15 +103,46 @@ namespace ManifoldGardenArchipelago
90 return; 103 return;
91 } 104 }
92 105
93 if (setActive) 106 Plugin.slotSave.ActivatedPads[sir] = setActive;
107
108 GameState.EvaluateGameStateListeners(listeners);
109 }
110 }
111
112 [HarmonyPatch(typeof(CubeLineActivator), "ForceActivatorToTurnOnAsCorrectCubeOnSwitch")]
113 static class CubeLineActivatorForceActivatorToTurnOnAsCorrectCubeOnSwitchPatch
114 {
115 static void Prefix(CubeLineActivator __instance)
116 {
117 SceneItemReference sir = GameState.GetPadSceneReference(__instance);
118 Plugin.Logger.LogInfo($"Pad {sir} forced on");
119
120 if (!GameData.listenersByPad.TryGetValue(sir, out GameStateListeners listeners))
94 { 121 {
95 Plugin.slotSave.ActivatedPads.Add(sir); 122 return;
96 } 123 }
97 else 124
125 Plugin.slotSave.ActivatedPads[sir] = true;
126
127 GameState.EvaluateGameStateListeners(listeners);
128 }
129 }
130
131 [HarmonyPatch(typeof(CubeLineActivator), "ForceActivatorToTurnOffAsCorrectCubeNotOnSwitch")]
132 static class CubeLineActivatorForceActivatorToTurnOffAsCorrectCubeNotOnSwitchPatch
133 {
134 static void Prefix(CubeLineActivator __instance)
135 {
136 SceneItemReference sir = GameState.GetPadSceneReference(__instance);
137 Plugin.Logger.LogInfo($"Pad {sir} forced off");
138
139 if (!GameData.listenersByPad.TryGetValue(sir, out GameStateListeners listeners))
98 { 140 {
99 Plugin.slotSave.ActivatedPads.Remove(sir); 141 return;
100 } 142 }
101 143
144 Plugin.slotSave.ActivatedPads[sir] = false;
145
102 GameState.EvaluateGameStateListeners(listeners); 146 GameState.EvaluateGameStateListeners(listeners);
103 } 147 }
104 } 148 }
@@ -109,21 +153,14 @@ namespace ManifoldGardenArchipelago
109 static void Prefix(WaterDetector __instance, bool setActive) 153 static void Prefix(WaterDetector __instance, bool setActive)
110 { 154 {
111 SceneItemReference sir = GameState.GetWaterwheelSceneReference(__instance); 155 SceneItemReference sir = GameState.GetWaterwheelSceneReference(__instance);
112 Plugin.Logger.LogInfo($"Waterwheel {sir} state {setActive}"); 156 //Plugin.Logger.LogInfo($"Waterwheel {sir} state {setActive}");
113 157
114 if (!GameData.listenersByWaterwheel.TryGetValue(sir, out GameStateListeners listeners)) 158 if (!GameData.listenersByWaterwheel.TryGetValue(sir, out GameStateListeners listeners))
115 { 159 {
116 return; 160 return;
117 } 161 }
118 162
119 if (setActive) 163 Plugin.slotSave.ActivatedWaterwheels[sir] = setActive;
120 {
121 Plugin.slotSave.ActivatedWaterwheels.Add(sir);
122 }
123 else
124 {
125 Plugin.slotSave.ActivatedWaterwheels.Remove(sir);
126 }
127 164
128 GameState.EvaluateGameStateListeners(listeners); 165 GameState.EvaluateGameStateListeners(listeners);
129 } 166 }
@@ -142,14 +179,7 @@ namespace ManifoldGardenArchipelago
142 return; 179 return;
143 } 180 }
144 181
145 if (newState == SphereController.State.AtDestination) 182 Plugin.slotSave.ActivatedSpheres[sir] = (newState == SphereController.State.AtDestination);
146 {
147 Plugin.slotSave.ActivatedSpheres.Add(sir);
148 }
149 else
150 {
151 Plugin.slotSave.ActivatedSpheres.Remove(sir);
152 }
153 183
154 GameState.EvaluateGameStateListeners(listeners); 184 GameState.EvaluateGameStateListeners(listeners);
155 } 185 }
@@ -166,10 +196,22 @@ namespace ManifoldGardenArchipelago
166 { 196 {
167 if (sceneDescription.doors.TryGetValue(sir.index, out var requirement)) 197 if (sceneDescription.doors.TryGetValue(sir.index, out var requirement))
168 { 198 {
169 FieldInfo fieldInfo = typeof(LineDoorController).GetField("doorShouldOpenImmediatelyOnEnable", BindingFlags.Instance | BindingFlags.NonPublic); 199 Requirement.Decision decision = requirement.Check();
170 fieldInfo.SetValue(__instance, requirement.Check()); 200
201 if (decision != Requirement.Decision.Maybe)
202 {
203 bool shouldOpen = (decision == Requirement.Decision.Yes);
204
205 FieldInfo fieldInfo = typeof(LineDoorController).GetField("doorShouldOpenImmediatelyOnEnable", BindingFlags.Instance | BindingFlags.NonPublic);
206 fieldInfo.SetValue(__instance, shouldOpen);
207
208 FieldInfo animatorInfo = typeof(LineDoorController).GetField("m_animator", BindingFlags.Instance | BindingFlags.NonPublic);
209 Animator animator = (Animator)animatorInfo.GetValue(__instance);
210
211 AnimatorExt.PlayDoorStateThenDisable(animator, __instance.DoorOpenAnimationString, shouldOpen ? 1f : -1f, true);
171 212
172 __instance.chains.Clear(); 213 __instance.chains.Clear();
214 }
173 } 215 }
174 } 216 }
175 } 217 }
@@ -180,16 +222,32 @@ namespace ManifoldGardenArchipelago
180 { 222 {
181 static void Prefix(LineDoorController __instance) 223 static void Prefix(LineDoorController __instance)
182 { 224 {
225 //Plugin.Logger.LogInfo("LineDoorControllerOnLoadPatch entered");
183 SceneItemReference sir = GameState.GetChainListenerSceneReference(__instance); 226 SceneItemReference sir = GameState.GetChainListenerSceneReference(__instance);
227 //Plugin.Logger.LogInfo($"Got sir {sir}");
184 228
185 if (GameData.scenes.TryGetValue(sir.scene, out var sceneDescription)) 229 if (GameData.scenes.TryGetValue(sir.scene, out var sceneDescription))
186 { 230 {
231 //Plugin.Logger.LogInfo($"{sceneDescription.doors.Count} doors in scene");
187 if (sceneDescription.doors.TryGetValue(sir.index, out var requirement)) 232 if (sceneDescription.doors.TryGetValue(sir.index, out var requirement))
188 { 233 {
189 FieldInfo fieldInfo = typeof(LineDoorController).GetField("doorShouldOpenImmediatelyOnEnable", BindingFlags.Instance | BindingFlags.NonPublic); 234 //Plugin.Logger.LogInfo($"Found req {requirement}");
190 fieldInfo.SetValue(__instance, requirement.Check()); 235 Requirement.Decision decision = requirement.Check();
236
237 if (decision != Requirement.Decision.Maybe)
238 {
239 bool shouldOpen = (decision == Requirement.Decision.Yes);
240
241 FieldInfo fieldInfo = typeof(LineDoorController).GetField("doorShouldOpenImmediatelyOnEnable", BindingFlags.Instance | BindingFlags.NonPublic);
242 fieldInfo.SetValue(__instance, shouldOpen);
243
244 FieldInfo animatorInfo = typeof(LineDoorController).GetField("m_animator", BindingFlags.Instance | BindingFlags.NonPublic);
245 Animator animator = (Animator)animatorInfo.GetValue(__instance);
246
247 AnimatorExt.PlayDoorStateThenDisable(animator, __instance.DoorOpenAnimationString, shouldOpen ? 1f : -1f, true);
191 248
192 __instance.chains.Clear(); 249 __instance.chains.Clear();
250 }
193 } 251 }
194 } 252 }
195 } 253 }
@@ -204,6 +262,7 @@ namespace ManifoldGardenArchipelago
204 262
205 if (GameData.listenersByScene.TryGetValue(newLevel.levelName, out var listeners)) 263 if (GameData.listenersByScene.TryGetValue(newLevel.levelName, out var listeners))
206 { 264 {
265 Plugin.Logger.LogInfo($"Evaluating for scene {newLevel.levelName}");
207 GameState.EvaluateGameStateListeners(listeners); 266 GameState.EvaluateGameStateListeners(listeners);
208 } 267 }
209 } 268 }
@@ -227,7 +286,7 @@ namespace ManifoldGardenArchipelago
227 286
228 if (GameData.scenes.TryGetValue(sir.scene, out var sceneDescription) && 287 if (GameData.scenes.TryGetValue(sir.scene, out var sceneDescription) &&
229 sceneDescription.worldGrows.TryGetValue(sir.index, out var requirement) && 288 sceneDescription.worldGrows.TryGetValue(sir.index, out var requirement) &&
230 requirement.Check()) 289 requirement.Check() == Requirement.Decision.Yes)
231 { 290 {
232 FieldInfo fieldInfo = typeof(DarkModeCollapsedCubeWorldGrow).GetField("m_grown", BindingFlags.Instance | BindingFlags.NonPublic); 291 FieldInfo fieldInfo = typeof(DarkModeCollapsedCubeWorldGrow).GetField("m_grown", BindingFlags.Instance | BindingFlags.NonPublic);
233 fieldInfo.SetValue(__instance, true); 292 fieldInfo.SetValue(__instance, true);
@@ -235,6 +294,54 @@ namespace ManifoldGardenArchipelago
235 } 294 }
236 } 295 }
237 296
297 [HarmonyPatch(typeof(SolidStateController), nameof(SolidStateController.OnChainFillComplete))]
298 static class SolidStateControllerOnChainFillCompletePatch
299 {
300 static bool Prefix(SolidStateController __instance)
301 {
302 SceneItemReference sir = GameState.GetChainListenerSceneReference(__instance);
303
304 if (GameData.scenes.TryGetValue(sir.scene, out var sceneDescription))
305 {
306 if (sceneDescription.smokeWalls.TryGetValue(sir.index, out var requirement))
307 {
308 Requirement.Decision decision = requirement.Check();
309
310 if (decision == Requirement.Decision.No)
311 {
312 return false;
313 }
314 }
315 }
316
317 return true;
318 }
319 }
320
321 [HarmonyPatch(typeof(SolidStateController), nameof(SolidStateController.OnUnfilled))]
322 static class SolidStateControllerOnUnfilledPatch
323 {
324 static bool Prefix(SolidStateController __instance)
325 {
326 SceneItemReference sir = GameState.GetChainListenerSceneReference(__instance);
327
328 if (GameData.scenes.TryGetValue(sir.scene, out var sceneDescription))
329 {
330 if (sceneDescription.smokeWalls.TryGetValue(sir.index, out var requirement))
331 {
332 Requirement.Decision decision = requirement.Check();
333
334 if (decision == Requirement.Decision.Yes)
335 {
336 return false;
337 }
338 }
339 }
340
341 return true;
342 }
343 }
344
238 [HarmonyPatch(typeof(DarkModeCollider), nameof(DarkModeCollider.OnLevelUpdate))] 345 [HarmonyPatch(typeof(DarkModeCollider), nameof(DarkModeCollider.OnLevelUpdate))]
239 static class DarkModeColliderOnLevelUpdatePatch 346 static class DarkModeColliderOnLevelUpdatePatch
240 { 347 {
diff --git a/Requirements.cs b/Requirements.cs index 987a299..81ecf36 100644 --- a/Requirements.cs +++ b/Requirements.cs
@@ -50,9 +50,16 @@ namespace ManifoldGardenArchipelago
50 50
51 public abstract class Requirement 51 public abstract class Requirement
52 { 52 {
53 public enum Decision
54 {
55 Maybe,
56 No,
57 Yes,
58 }
59
53 public RequirementReferences references = new(); 60 public RequirementReferences references = new();
54 61
55 public abstract bool Check(); 62 public abstract Decision Check();
56 } 63 }
57 64
58 public class AndRequirement : Requirement 65 public class AndRequirement : Requirement
@@ -69,9 +76,19 @@ namespace ManifoldGardenArchipelago
69 } 76 }
70 } 77 }
71 78
72 public override bool Check() 79 public override Decision Check()
73 { 80 {
74 return _requirements.All(x => x.Check()); 81 foreach (var requirement in _requirements)
82 {
83 Decision decision = requirement.Check();
84
85 if (decision != Decision.Yes)
86 {
87 return decision;
88 }
89 }
90
91 return Decision.Yes;
75 } 92 }
76 93
77 public override string ToString() 94 public override string ToString()
@@ -94,9 +111,19 @@ namespace ManifoldGardenArchipelago
94 } 111 }
95 } 112 }
96 113
97 public override bool Check() 114 public override Decision Check()
98 { 115 {
99 return _requirements.Any(x => x.Check()); 116 foreach (var requirement in _requirements)
117 {
118 Decision decision = requirement.Check();
119
120 if (decision != Decision.No)
121 {
122 return decision;
123 }
124 }
125
126 return Decision.No;
100 } 127 }
101 128
102 public override string ToString() 129 public override string ToString()
@@ -116,9 +143,9 @@ namespace ManifoldGardenArchipelago
116 references.items.Add(itemName); 143 references.items.Add(itemName);
117 } 144 }
118 145
119 public override bool Check() 146 public override Decision Check()
120 { 147 {
121 return Plugin.archipelagoManager.HasItem(_itemName); 148 return Plugin.archipelagoManager.HasItem(_itemName) ? Decision.Yes : Decision.No;
122 } 149 }
123 150
124 public override string ToString() 151 public override string ToString()
@@ -138,9 +165,9 @@ namespace ManifoldGardenArchipelago
138 references.scenes.Add(sceneName); 165 references.scenes.Add(sceneName);
139 } 166 }
140 167
141 public override bool Check() 168 public override Decision Check()
142 { 169 {
143 return Plugin.slotSave.VisitedScenes.Contains(_sceneName); 170 return Plugin.slotSave.VisitedScenes.Contains(_sceneName) ? Decision.Yes : Decision.No;
144 } 171 }
145 172
146 public override string ToString() 173 public override string ToString()
@@ -161,9 +188,16 @@ namespace ManifoldGardenArchipelago
161 references.buttons.Add(button); 188 references.buttons.Add(button);
162 } 189 }
163 190
164 public override bool Check() 191 public override Decision Check()
165 { 192 {
166 return Plugin.slotSave.ActivatedButtons.Contains(_button); 193 if (Plugin.slotSave.ActivatedButtons.TryGetValue(_button, out bool value))
194 {
195 return value ? Decision.Yes : Decision.No;
196 }
197 else
198 {
199 return Decision.Maybe;
200 }
167 } 201 }
168 202
169 public override string ToString() 203 public override string ToString()
@@ -184,9 +218,16 @@ namespace ManifoldGardenArchipelago
184 references.sockets.Add(socket); 218 references.sockets.Add(socket);
185 } 219 }
186 220
187 public override bool Check() 221 public override Decision Check()
188 { 222 {
189 return Plugin.slotSave.ActivatedSockets.Contains(_socket); 223 if (Plugin.slotSave.ActivatedSockets.TryGetValue(_socket, out bool value))
224 {
225 return value ? Decision.Yes : Decision.No;
226 }
227 else
228 {
229 return Decision.Maybe;
230 }
190 } 231 }
191 232
192 public override string ToString() 233 public override string ToString()
@@ -207,9 +248,16 @@ namespace ManifoldGardenArchipelago
207 references.pads.Add(pad); 248 references.pads.Add(pad);
208 } 249 }
209 250
210 public override bool Check() 251 public override Decision Check()
211 { 252 {
212 return Plugin.slotSave.ActivatedPads.Contains(_pad); 253 if (Plugin.slotSave.ActivatedPads.TryGetValue(_pad, out bool value))
254 {
255 return value ? Decision.Yes : Decision.No;
256 }
257 else
258 {
259 return Decision.Maybe;
260 }
213 } 261 }
214 262
215 public override string ToString() 263 public override string ToString()
@@ -230,9 +278,16 @@ namespace ManifoldGardenArchipelago
230 references.waterwheels.Add(waterwheel); 278 references.waterwheels.Add(waterwheel);
231 } 279 }
232 280
233 public override bool Check() 281 public override Decision Check()
234 { 282 {
235 return Plugin.slotSave.ActivatedWaterwheels.Contains(_waterwheel); 283 if (Plugin.slotSave.ActivatedWaterwheels.TryGetValue(_waterwheel, out bool value))
284 {
285 return value ? Decision.Yes : Decision.No;
286 }
287 else
288 {
289 return Decision.Maybe;
290 }
236 } 291 }
237 292
238 public override string ToString() 293 public override string ToString()
@@ -253,9 +308,16 @@ namespace ManifoldGardenArchipelago
253 references.spheres.Add(sphere); 308 references.spheres.Add(sphere);
254 } 309 }
255 310
256 public override bool Check() 311 public override Decision Check()
257 { 312 {
258 return Plugin.slotSave.ActivatedSpheres.Contains(_sphere); 313 if (Plugin.slotSave.ActivatedSpheres.TryGetValue(_sphere, out bool value))
314 {
315 return value ? Decision.Yes : Decision.No;
316 }
317 else
318 {
319 return Decision.Maybe;
320 }
259 } 321 }
260 322
261 public override string ToString() 323 public override string ToString()
@@ -275,9 +337,22 @@ namespace ManifoldGardenArchipelago
275 references = requirement.references; 337 references = requirement.references;
276 } 338 }
277 339
278 public override bool Check() 340 public override Decision Check()
279 { 341 {
280 return !_requirement.Check(); 342 Decision subdec = _requirement.Check();
343
344 if (subdec == Decision.Yes)
345 {
346 return Decision.No;
347 }
348 else if (subdec == Decision.No)
349 {
350 return Decision.Yes;
351 }
352 else
353 {
354 return Decision.Maybe;
355 }
281 } 356 }
282 357
283 public override string ToString() 358 public override string ToString()
diff --git a/SlotSave.cs b/SlotSave.cs index 6261890..dfa18bc 100644 --- a/SlotSave.cs +++ b/SlotSave.cs
@@ -1,18 +1,14 @@
1using System; 1using System.Collections.Generic;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading.Tasks;
6 2
7namespace ManifoldGardenArchipelago 3namespace ManifoldGardenArchipelago
8{ 4{
9 public class SlotSave 5 public class SlotSave
10 { 6 {
11 public readonly HashSet<string> VisitedScenes = []; 7 public readonly HashSet<string> VisitedScenes = [];
12 public readonly HashSet<SceneItemReference> ActivatedButtons = []; 8 public readonly Dictionary<SceneItemReference, bool> ActivatedButtons = [];
13 public readonly HashSet<SceneItemReference> ActivatedSockets = []; 9 public readonly Dictionary<SceneItemReference, bool> ActivatedSockets = [];
14 public readonly HashSet<SceneItemReference> ActivatedPads = []; 10 public readonly Dictionary<SceneItemReference, bool> ActivatedPads = [];
15 public readonly HashSet<SceneItemReference> ActivatedWaterwheels = []; 11 public readonly Dictionary<SceneItemReference, bool> ActivatedWaterwheels = [];
16 public readonly HashSet<SceneItemReference> ActivatedSpheres = []; 12 public readonly Dictionary<SceneItemReference, bool> ActivatedSpheres = [];
17 } 13 }
18} 14}
diff --git a/game_data.yaml b/game_data.yaml index 43ccf22..a261be0 100644 --- a/game_data.yaml +++ b/game_data.yaml
@@ -274,24 +274,25 @@ World_612_BlindSpherePuzzle_Optimized:
274 scene: Hallway_W612_W057_Optimized 274 scene: Hallway_W612_W057_Optimized
275 index: 0 275 index: 0
276World_018_PastaTile_Optimized: 276World_018_PastaTile_Optimized:
277 0: 277 doors:
278 or: 278 0:
279 - button: 0 279 or:
280 - pad: 0 280 - button: 0
281 3: 281 - pad: 0
282 or: 282 3:
283 - pad: 0 283 or:
284 - sphere: 284 - pad: 0
285 scene: Hallway_W018_W003B_Optimized 285 - sphere:
286 index: 0 286 scene: Hallway_W018_W003B_Optimized
287 5: 287 index: 0
288 or: 288 5:
289 - button: 1 289 or:
290 - button: 290 - button: 1
291 - scene: Hallway_W018_W063_Optimized 291 - button:
292 index: 0 292 - scene: Hallway_W018_W063_Optimized
293 - scene: Hallway_W018_W063_Optimized 293 index: 0
294 index: 1 294 - scene: Hallway_W018_W063_Optimized
295 index: 1
295Hallway_W018_W003B_Optimized: 296Hallway_W018_W003B_Optimized:
296 locations: 297 locations:
297 Mini Sphere Puzzle Solved: 298 Mini Sphere Puzzle Solved:
@@ -559,6 +560,7 @@ World_026_Library_Optimized:
559 smoke: 560 smoke:
560 3: 561 3:
561 item: Library - Yellow Smoke Wall 562 item: Library - Yellow Smoke Wall
563 entry: World_026_Library_Optimized
562Hallway_W026_W002_Optimized: 564Hallway_W026_W002_Optimized:
563 locations: 565 locations:
564 Yellow Cube Fetch Quest Completed: 566 Yellow Cube Fetch Quest Completed: