diff options
| -rw-r--r-- | ArchipelagoManager.cs | 1 | ||||
| -rw-r--r-- | GameData.cs | 51 | ||||
| -rw-r--r-- | GameState.cs | 46 | ||||
| -rw-r--r-- | GameplayPatches.cs | 48 | ||||
| -rw-r--r-- | game_data.yaml | 31 |
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 |
| 77 | World_001_Optimized: | 77 | World_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 | ||
| 88 | World_044_CubicSpaceDivision_Optimized: | 98 | World_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: | |||
| 437 | Hallway_W018_W063_Optimized: | 447 | Hallway_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 |
| 771 | World_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 | ||
