summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2025-02-23 16:42:22 -0500
committerStar Rauchenberger <fefferburbia@gmail.com>2025-02-23 16:42:22 -0500
commit42bc500a77f4b29d952058aede6abfaf91bd74c8 (patch)
treebfcdf83f9ec863f807fc9df48c0326ba56402a8e
parentf5b0daa0279ce4ed272b007ac4324e848ad4b03d (diff)
downloadmanifold-garden-archipelago-42bc500a77f4b29d952058aede6abfaf91bd74c8.tar.gz
manifold-garden-archipelago-42bc500a77f4b29d952058aede6abfaf91bd74c8.tar.bz2
manifold-garden-archipelago-42bc500a77f4b29d952058aede6abfaf91bd74c8.zip
Add support for lasers
The three lasers in Blue are item locked, and the laser in Akshardham requires you to have planted all other god cubes in order to activate.
-rw-r--r--ArchipelagoManager.cs1
-rw-r--r--GameData.cs51
-rw-r--r--GameState.cs46
-rw-r--r--GameplayPatches.cs48
-rw-r--r--game_data.yaml31
5 files changed, 175 insertions, 2 deletions
diff --git a/ArchipelagoManager.cs b/ArchipelagoManager.cs index 998e2d9..5e1d867 100644 --- a/ArchipelagoManager.cs +++ b/ArchipelagoManager.cs
@@ -29,6 +29,7 @@ namespace ManifoldGardenArchipelago
29 } 29 }
30 catch (Exception ex) 30 catch (Exception ex)
31 { 31 {
32 Plugin.Logger.LogError(ex.GetBaseException().Message);
32 return new LoginFailure(ex.GetBaseException().Message); 33 return new LoginFailure(ex.GetBaseException().Message);
33 } 34 }
34 35
diff --git a/GameData.cs b/GameData.cs index 6b5eddc..f8adb17 100644 --- a/GameData.cs +++ b/GameData.cs
@@ -27,6 +27,7 @@ namespace ManifoldGardenArchipelago
27 public readonly Dictionary<int, Requirement> doors = []; 27 public readonly Dictionary<int, Requirement> doors = [];
28 public readonly Dictionary<int, Requirement> smokeWalls = []; 28 public readonly Dictionary<int, Requirement> smokeWalls = [];
29 public readonly Dictionary<int, Requirement> worldGrows = []; 29 public readonly Dictionary<int, Requirement> worldGrows = [];
30 public readonly Dictionary<int, Requirement> lasers = [];
30 } 31 }
31 32
32 public class GameStateListeners 33 public class GameStateListeners
@@ -35,6 +36,7 @@ namespace ManifoldGardenArchipelago
35 public readonly Dictionary<SceneItemReference, Requirement> doors = []; 36 public readonly Dictionary<SceneItemReference, Requirement> doors = [];
36 public readonly Dictionary<SceneItemReference, Requirement> smokeWalls = []; 37 public readonly Dictionary<SceneItemReference, Requirement> smokeWalls = [];
37 public readonly Dictionary<SceneItemReference, Requirement> worldGrows = []; 38 public readonly Dictionary<SceneItemReference, Requirement> worldGrows = [];
39 public readonly Dictionary<SceneItemReference, Requirement> lasers = [];
38 } 40 }
39 41
40 public static class GameData 42 public static class GameData
@@ -419,6 +421,8 @@ namespace ManifoldGardenArchipelago
419 Requirement req = ParseRequirement(scenePair.Key, (Dictionary<object, object>)worldPair.Value); 421 Requirement req = ParseRequirement(scenePair.Key, (Dictionary<object, object>)worldPair.Value);
420 sceneDescription.worldGrows[sir.index] = req; 422 sceneDescription.worldGrows[sir.index] = req;
421 423
424 Plugin.Logger.LogInfo($"World {sir} requirements: {req}");
425
422 foreach (var reqScene in req.references.scenes) 426 foreach (var reqScene in req.references.scenes)
423 { 427 {
424 GetOrAddListeners(listenersByScene, reqScene).worldGrows[sir] = req; 428 GetOrAddListeners(listenersByScene, reqScene).worldGrows[sir] = req;
@@ -456,6 +460,53 @@ namespace ManifoldGardenArchipelago
456 } 460 }
457 } 461 }
458 462
463 if (sceneDetails.ContainsKey("lasers"))
464 {
465 foreach (var laserPair in (Dictionary<object, object>)sceneDetails["lasers"])
466 {
467 SceneItemReference sir = new(scenePair.Key, int.Parse((string)laserPair.Key));
468 Requirement req = ParseRequirement(scenePair.Key, (Dictionary<object, object>)laserPair.Value);
469 sceneDescription.lasers[sir.index] = req;
470
471 Plugin.Logger.LogInfo($"Laser {sir} requirements: {req}");
472
473 foreach (var reqScene in req.references.scenes)
474 {
475 GetOrAddListeners(listenersByScene, reqScene).lasers[sir] = req;
476 }
477
478 foreach (var button in req.references.buttons)
479 {
480 GetOrAddListeners(listenersByButton, button).lasers[sir] = req;
481 }
482
483 foreach (var socket in req.references.sockets)
484 {
485 GetOrAddListeners(listenersBySocket, socket).lasers[sir] = req;
486 }
487
488 foreach (var pad in req.references.pads)
489 {
490 GetOrAddListeners(listenersByPad, pad).lasers[sir] = req;
491 }
492
493 foreach (var waterwheel in req.references.waterwheels)
494 {
495 GetOrAddListeners(listenersByWaterwheel, waterwheel).lasers[sir] = req;
496 }
497
498 foreach (var sphere in req.references.spheres)
499 {
500 GetOrAddListeners(listenersBySphere, sphere).lasers[sir] = req;
501 }
502
503 foreach (var item in req.references.items)
504 {
505 GetOrAddListeners(listenersByItem, item).lasers[sir] = req;
506 }
507 }
508 }
509
459 scenes[scenePair.Key] = sceneDescription; 510 scenes[scenePair.Key] = sceneDescription;
460 } 511 }
461 } 512 }
diff --git a/GameState.cs b/GameState.cs index bdf5760..9280eb3 100644 --- a/GameState.cs +++ b/GameState.cs
@@ -33,6 +33,21 @@ namespace ManifoldGardenArchipelago
33 throw new Exception("Shouldn't happen"); 33 throw new Exception("Shouldn't happen");
34 } 34 }
35 35
36 public static SceneItemReference GetGameplayComponentSceneReference(Component component)
37 {
38 LevelSystems levelSystem = GetLevelSystems(component);
39
40 for (int i = 0; i < levelSystem.gameplayComponentsInLevel.Count(); i++)
41 {
42 if (levelSystem.gameplayComponentsInLevel[i] == component)
43 {
44 return new(component.gameObject.scene.name, i);
45 }
46 }
47
48 throw new Exception("Shouldn't happen");
49 }
50
36 public static SceneItemReference GetButtonSceneReference(ButtonLineActivator arg) 51 public static SceneItemReference GetButtonSceneReference(ButtonLineActivator arg)
37 { 52 {
38 LevelSystems levelSystem = GetLevelSystems(arg); 53 LevelSystems levelSystem = GetLevelSystems(arg);
@@ -191,6 +206,37 @@ namespace ManifoldGardenArchipelago
191 } 206 }
192 } 207 }
193 } 208 }
209
210 foreach (var laser in listeners.lasers)
211 {
212 Requirement.Decision decision = laser.Value.Check();
213 if (decision == Requirement.Decision.Maybe)
214 {
215 continue;
216 }
217
218 bool shouldOpen = (decision == Requirement.Decision.Yes);
219
220 if (SceneManager.GetSceneByName(laser.Key.scene) is Scene laserScene && laserScene.isLoaded)
221 {
222 LevelSystems levelSystems = GetLevelSystems(laserScene);
223 if (levelSystems.isActiveAndEnabled)
224 {
225 DarkModeCageController ldc = levelSystems.gameplayComponentsInLevel[laser.Key.index].GetComponent<DarkModeCageController>();
226
227 if (shouldOpen)
228 {
229 MethodInfo methodInfo = typeof(DarkModeCageController).GetMethod("OpenLaserSource", BindingFlags.Instance | BindingFlags.NonPublic);
230 methodInfo.Invoke(ldc, [false]);
231 }
232 else
233 {
234 MethodInfo methodInfo = typeof(DarkModeCageController).GetMethod("CloseLaserSource", BindingFlags.Instance | BindingFlags.NonPublic);
235 methodInfo.Invoke(ldc, [false]);
236 }
237 }
238 }
239 }
194 } 240 }
195 } 241 }
196} 242}
diff --git a/GameplayPatches.cs b/GameplayPatches.cs index bdcbcae..37a671d 100644 --- a/GameplayPatches.cs +++ b/GameplayPatches.cs
@@ -389,4 +389,52 @@ namespace ManifoldGardenArchipelago
389 return false; 389 return false;
390 } 390 }
391 } 391 }
392
393 [HarmonyPatch(typeof(DarkModeCageController), "StartFilling")]
394 static class DarkModeCageControllerStartFillingPatch
395 {
396 static bool Prefix(DarkModeCageController __instance)
397 {
398 SceneItemReference sir = GameState.GetGameplayComponentSceneReference(__instance);
399
400 if (GameData.scenes.TryGetValue(sir.scene, out var sceneDescription))
401 {
402 if (sceneDescription.lasers.TryGetValue(sir.index, out var requirement))
403 {
404 Requirement.Decision decision = requirement.Check();
405
406 if (decision == Requirement.Decision.No)
407 {
408 return false;
409 }
410 }
411 }
412
413 return true;
414 }
415 }
416
417 [HarmonyPatch(typeof(DarkModeCageController), "StartUnfilling")]
418 static class DarkModeCageControllerStartUnfillingPatch
419 {
420 static bool Prefix(DarkModeCageController __instance)
421 {
422 SceneItemReference sir = GameState.GetGameplayComponentSceneReference(__instance);
423
424 if (GameData.scenes.TryGetValue(sir.scene, out var sceneDescription))
425 {
426 if (sceneDescription.lasers.TryGetValue(sir.index, out var requirement))
427 {
428 Requirement.Decision decision = requirement.Check();
429
430 if (decision == Requirement.Decision.Yes)
431 {
432 return false;
433 }
434 }
435 }
436
437 return true;
438 }
439 }
392} 440}
diff --git a/game_data.yaml b/game_data.yaml index 891b169..fe5d99a 100644 --- a/game_data.yaml +++ b/game_data.yaml
@@ -75,7 +75,6 @@ Hallway_W062_W063_Optimized:
75 scene: World_063_TowerX_Optimized 75 scene: World_063_TowerX_Optimized
76 index: 0 76 index: 0
77World_001_Optimized: 77World_001_Optimized:
78 # lasers are called DarkModeCageControllers; will handle them separately bc most worlds don't item-lock them
79 locations: 78 locations:
80 Blue - Red Laser Activated: 79 Blue - Red Laser Activated:
81 socket: 5 80 socket: 5
@@ -85,6 +84,17 @@ World_001_Optimized:
85 socket: 3 84 socket: 3
86 Blue - Tree Purified: 85 Blue - Tree Purified:
87 entry: AudioVisual_001_Optimized 86 entry: AudioVisual_001_Optimized
87 lasers:
88 # These are gameplayComponentsInLevel indicies
89 127:
90 item: Blue - Green Laser
91 socket: 3
92 133:
93 item: Blue - Yellow Laser
94 socket: 4
95 149:
96 item: Blue - Red Laser
97 socket: 5
88World_044_CubicSpaceDivision_Optimized: 98World_044_CubicSpaceDivision_Optimized:
89 locations: 99 locations:
90 Blue God Cube Planted: 100 Blue God Cube Planted:
@@ -437,7 +447,7 @@ Hallway_W073_W018_Optimized:
437Hallway_W018_W063_Optimized: 447Hallway_W018_W063_Optimized:
438 doors: 448 doors:
439 0: 449 0:
440 - button: [0, 1] 450 button: [0, 1]
441 1: 451 1:
442 item: Orange Secret Path 452 item: Orange Secret Path
443 or: 453 or:
@@ -758,3 +768,20 @@ World_806_Optimized:
758 locations: 768 locations:
759 Rainbow - Second Water Tetromino Puzzle Solved: 769 Rainbow - Second Water Tetromino Puzzle Solved:
760 waterwheel: 0 770 waterwheel: 0
771World_071_AkshardhamTemple_Optimized:
772 lasers:
773 49:
774 waterwheel: 0
775 socket:
776 - scene: World_044_CubicSpaceDivision_Optimized
777 index: 0
778 - scene: World_044_CubicSpaceDivision_Optimized
779 index: 1
780 - scene: World_044_CubicSpaceDivision_Optimized
781 index: 2
782 - scene: World_044_CubicSpaceDivision_Optimized
783 index: 3
784 - scene: World_044_CubicSpaceDivision_Optimized
785 index: 4
786 - scene: World_044_CubicSpaceDivision_Optimized
787 index: 5