From f6bf7b8576a6c2a7d89d463b4998c44324d6d370 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Wed, 22 May 2024 13:57:28 -0400 Subject: More stuff! Big keys are now locations. Health cicadas work now, both as locations and items. The two checks in the Street now also give their vanilla items. --- AnodyneArchipelago/ArchipelagoManager.cs | 11 ++- AnodyneArchipelago/ArchipelagoTreasure.cs | 22 +++++- AnodyneArchipelago/Locations.cs | 4 ++ AnodyneArchipelago/Plugin.cs | 108 ++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 4 deletions(-) diff --git a/AnodyneArchipelago/ArchipelagoManager.cs b/AnodyneArchipelago/ArchipelagoManager.cs index 4ffa3af..4ceb68a 100644 --- a/AnodyneArchipelago/ArchipelagoManager.cs +++ b/AnodyneArchipelago/ArchipelagoManager.cs @@ -131,7 +131,8 @@ namespace AnodyneArchipelago string mapName = GetMapNameForDungeon(dungeonName); GlobalState.inventory.AddMapKey(mapName, 1); - } else if (itemName == "Green Key") + } + else if (itemName == "Green Key") { GlobalState.inventory.BigKeyStatus[0] = true; } @@ -142,10 +143,16 @@ namespace AnodyneArchipelago else if (itemName == "Red Key") { GlobalState.inventory.BigKeyStatus[1] = true; - } else if (itemName == "Jump Shoes") + } + else if (itemName == "Jump Shoes") { GlobalState.inventory.CanJump = true; } + else if (itemName == "Health Cicada") + { + GlobalState.MAX_HEALTH += 1; + GlobalState.CUR_HEALTH = GlobalState.MAX_HEALTH; + } } } } diff --git a/AnodyneArchipelago/ArchipelagoTreasure.cs b/AnodyneArchipelago/ArchipelagoTreasure.cs index 6d000e8..b3812f2 100644 --- a/AnodyneArchipelago/ArchipelagoTreasure.cs +++ b/AnodyneArchipelago/ArchipelagoTreasure.cs @@ -1,4 +1,6 @@ -using AnodyneSharp.Entities.Gadget.Treasures; +using AnodyneSharp.Entities; +using AnodyneSharp.Entities.Gadget.Treasures; +using AnodyneSharp.Registry; using Microsoft.Xna.Framework; namespace AnodyneArchipelago @@ -14,7 +16,23 @@ namespace AnodyneArchipelago public override void GetTreasure() { - base.GetTreasure(); + if (_location == "Street - Broom Chest") + { + BroomTreasure broomTreasure = new("broom-icon", this.Position, BroomType.Normal); + broomTreasure.GetTreasure(); + GlobalState.SpawnEntity(broomTreasure); + } + else if (_location == "Street - Key Chest") + { + KeyTreasure keyTreasure = new(this.Position); + keyTreasure.GetTreasure(); + GlobalState.SpawnEntity(keyTreasure); + } + else + { + base.GetTreasure(); + } + ArchipelagoManager.SendLocation(_location); } } diff --git a/AnodyneArchipelago/Locations.cs b/AnodyneArchipelago/Locations.cs index 46e2471..a1a54b2 100644 --- a/AnodyneArchipelago/Locations.cs +++ b/AnodyneArchipelago/Locations.cs @@ -8,10 +8,14 @@ namespace AnodyneArchipelago { public static Dictionary LocationsByGuid = new() { + {new Guid("1525ead8-4d92-a815-873a-4dc04037d973"), "Street - Broom Chest" }, + {new Guid("3307aa58-ccf1-fb0d-1450-5af0a0c458f7"), "Street - Key Chest" }, + {new Guid("1bcddffb-5f98-4787-3a81-d1ce8fdeca29"), "Overworld - Near Gate Chest" }, {new Guid("40de36cf-9238-f8b0-7a57-c6c8ca465cc2"), "Temple of the Seeing One - Entrance Chest" }, {new Guid("621c284f-cbd0-74c3-f51b-2a9fdde8d4d7"), "Temple of the Seeing One - Rock-Surrounded Chest" }, {new Guid("401939a4-41ba-e07e-3ba2-dc22513dcc5c"), "Temple of the Seeing One - Dark Room Chest" }, {new Guid("88d0a7b8-eeab-c45f-324e-f1c7885c41ce"), "Temple of the Seeing One - Shieldy Room Chest" }, + {new Guid("c481ee20-662e-6b02-b010-676ab339fc2d"), "Temple of the Seeing One - Health Cicada" }, {new Guid("0bce5346-48a2-47f9-89cb-3f59d9d0b7d2"), "Temple of the Seeing One - Boss Chest" }, {new Guid("d41f2750-e3c7-bbb4-d650-fafc190ebd32"), "Temple of the Seeing One - After Statue Left Chest" }, {new Guid("3167924e-5d52-1cd6-d6f4-b8e0e328215b"), "Temple of the Seeing One - After Statue Right Chest" }, diff --git a/AnodyneArchipelago/Plugin.cs b/AnodyneArchipelago/Plugin.cs index f49ba35..d40da7c 100644 --- a/AnodyneArchipelago/Plugin.cs +++ b/AnodyneArchipelago/Plugin.cs @@ -2,11 +2,16 @@ using AnodyneSharp.Entities; using AnodyneSharp.Entities.Gadget; using AnodyneSharp.Entities.Gadget.Treasures; +using AnodyneSharp.Entities.Interactive; +using AnodyneSharp.Registry; +using AnodyneSharp.Utilities; using BepInEx; using BepInEx.NET.Common; using HarmonyLib; using HarmonyLib.Tools; using System; +using System.Collections; +using System.Collections.Generic; using System.Reflection; namespace AnodyneArchipelago @@ -85,4 +90,107 @@ namespace AnodyneArchipelago return true; } } + + [HarmonyPatch(typeof(Big_Key), nameof(Big_Key.PlayerInteraction))] + class BigKeyTouchPatch + { + // We basically just rewrite this method, because we need to get rid of the part that adds the key to the inventory. + static bool Prefix(Big_Key __instance, ref bool __result) + { + Type keyType = typeof(Big_Key); + FieldInfo presetField = keyType.GetField("_preset", BindingFlags.NonPublic | BindingFlags.Instance); + EntityPreset preset = presetField.GetValue(__instance) as EntityPreset; + + MethodInfo statesMethod = keyType.GetMethod("States", BindingFlags.NonPublic | BindingFlags.Instance); + + preset.Alive = false; + __instance.Solid = false; + GlobalState.StartCutscene = (System.Collections.Generic.IEnumerator)statesMethod.Invoke(__instance, new object[] { }); + __result = true; + return false; + } + } + + [HarmonyPatch(typeof(Big_Key), "States")] + class BigKeyStatesPatch + { + static void Postfix(Big_Key __instance) + { + Type keyType = typeof(Big_Key); + FieldInfo presetField = keyType.GetField("_preset", BindingFlags.NonPublic | BindingFlags.Instance); + EntityPreset preset = presetField.GetValue(__instance) as EntityPreset; + + if (preset.Frame == 0) + { + ArchipelagoManager.SendLocation("Temple of the Seeing One - Green Key"); + } else if (preset.Frame == 1) + { + ArchipelagoManager.SendLocation("Red Grotto - Red Key"); + } else if (preset.Frame == 2) + { + ArchipelagoManager.SendLocation("Mountain Cavern - Blue Key"); + } + } + } + + [HarmonyPatch(typeof(HealthCicadaSentinel), nameof(HealthCicadaSentinel.Collided))] + class HealthCicadaInteractPatch + { + static void Prefix(TreasureChest __instance) + { + Type hcsType = typeof(HealthCicadaSentinel); + FieldInfo childField = hcsType.GetField("_child", BindingFlags.NonPublic | BindingFlags.Instance); + HealthCicada healthCicada = (HealthCicada)childField.GetValue(__instance); + + Type cicadaType = typeof(HealthCicada); + FieldInfo presetField = cicadaType.GetField("_preset", BindingFlags.NonPublic | BindingFlags.Instance); + EntityPreset preset = presetField.GetValue(healthCicada) as EntityPreset; + Plugin.Instance.Log.LogInfo($"Touched cicada: {preset.EntityID.ToString()}"); + } + } + + [HarmonyPatch(typeof(HealthCicada), nameof(HealthCicada.Update))] + class HealthCicadaUpdatePatch + { + static void Postfix(HealthCicada __instance) + { + Type cicadaType = typeof(HealthCicada); + FieldInfo chirpField = cicadaType.GetField("_chirp", BindingFlags.NonPublic | BindingFlags.Instance); + FieldInfo sentinelField = cicadaType.GetField("_sentinel", BindingFlags.NonPublic | BindingFlags.Instance); + + HealthCicadaSentinel sentinel = (HealthCicadaSentinel)sentinelField.GetValue(__instance); + Type hcsType = typeof(HealthCicadaSentinel); + FieldInfo flyDistanceField = hcsType.GetField("_flyDistance", BindingFlags.NonPublic | BindingFlags.Instance); + float flyDistance = (float)flyDistanceField.GetValue(sentinel); + + if (__instance.visible && !(bool)chirpField.GetValue(__instance) && flyDistance > 0) + { + flyDistanceField.SetValue(sentinel, 0f); + + FieldInfo stateField = cicadaType.GetField("_state", BindingFlags.NonPublic | BindingFlags.Instance); + stateField.SetValue(__instance, StateLogic(__instance)); + } + } + + static IEnumerator StateLogic(HealthCicada healthCicada) + { + Type cicadaType = typeof(HealthCicada); + FieldInfo presetField = cicadaType.GetField("_preset", BindingFlags.NonPublic | BindingFlags.Instance); + EntityPreset preset = presetField.GetValue(healthCicada) as EntityPreset; + + while (!MathUtilities.MoveTo(ref healthCicada.opacity, 0.0f, 0.6f)) + yield return "FadingOut"; + preset.Alive = false; + + FieldInfo sentinelField = cicadaType.GetField("_sentinel", BindingFlags.NonPublic | BindingFlags.Instance); + HealthCicadaSentinel sentinel = (HealthCicadaSentinel)sentinelField.GetValue(healthCicada); + + sentinel.exists = false; + + if (Locations.LocationsByGuid.ContainsKey(preset.EntityID)) + { + ArchipelagoManager.SendLocation(Locations.LocationsByGuid[preset.EntityID]); + } + } + } } -- cgit 1.4.1