Esempio n. 1
0
        private static void modDeathSound(ILContext il)
        {
            ILCursor       cursor    = new ILCursor(il);
            FieldReference refToThis = HookHelper.FindReferenceToThisInCoroutine(cursor);

            if (cursor.TryGotoNext(MoveType.After, instr => instr.MatchLdstr("event:/new_content/char/madeline/death_golden")))
            {
                Logger.Log("CollabUtils2/StrawberryHooks", $"Modding golden death sound at {cursor.Index} in IL for PlayerDeadBody.DeathRoutine");

                // we want to replace the vanilla death sound with the silver berry one if carrying a silver berry.
                cursor.Emit(OpCodes.Ldarg_0);
                cursor.Emit(OpCodes.Ldfld, refToThis);
                cursor.EmitDelegate <Func <string, PlayerDeadBody, string> >((orig, self) => {
                    DynData <PlayerDeadBody> data = new DynData <PlayerDeadBody>(self);
                    bool hasSilver     = data.Get <bool>("hasSilver");
                    bool hasSpeedBerry = data.Get <bool>("hasSpeedBerry");
                    if (hasSilver && hasSpeedBerry)
                    {
                        return("event:/SC2020_silverTimedBerry_death");
                    }
                    if (hasSilver)
                    {
                        return("event:/SC2020_silverBerry_death");
                    }
                    if (hasSpeedBerry)
                    {
                        return("event:/SC2020_timedBerry_death");
                    }
                    return(orig);
                });
            }
        }
Esempio n. 2
0
        private static void modStrawberrySound(ILContext il)
        {
            ILCursor       cursor    = new ILCursor(il);
            FieldReference refToThis = HookHelper.FindReferenceToThisInCoroutine(cursor);

            if (cursor.TryGotoNext(MoveType.After, instr => instr.MatchLdstr("event:/game/general/strawberry_get")))
            {
                Logger.Log("CollabUtils2/StrawberryHooks", $"Modding golden sound at {cursor.Index} in IL for Strawberry.CollectRoutine");

                // we want to replace the vanilla collect sound with the silver berry one if the current berry is a silver one.
                cursor.Emit(OpCodes.Ldarg_0);
                cursor.Emit(OpCodes.Ldfld, refToThis);
                cursor.EmitDelegate <Func <string, Strawberry, string> >((orig, self) => {
                    if (self is SilverBerry)
                    {
                        return("event:/SC2020_silverBerry_get");
                    }
                    if (self is RainbowBerry)
                    {
                        return("event:/SC2020_rainbowBerry_get");
                    }
                    if (self is SpeedBerry)
                    {
                        return("event:/SC2020_timedBerry_get");
                    }
                    return(orig);
                });
            }
        }
        private static void modDoorRoutine(ILContext il)
        {
            ILCursor cursor = new ILCursor(il);

            FieldReference refToThis = HookHelper.FindReferenceToThisInCoroutine(cursor);

            // find the "player is on the left side of the door" check
            // FNA version
            bool hookPointFound = cursor.TryGotoNext(MoveType.After,
                                                     instr => instr.MatchLdarg(0),
                                                     instr => instr.OpCode == OpCodes.Ldfld && (instr.Operand as FieldReference).Name.Contains("player"),
                                                     instr => instr.MatchCallvirt <Entity>("get_X"),
                                                     instr => instr.MatchLdarg(0),
                                                     instr => instr.OpCode == OpCodes.Ldfld && (instr.Operand as FieldReference).Name == "<>4__this",
                                                     instr => instr.MatchCallvirt <Entity>("get_X"));

            if (!hookPointFound)
            {
                cursor.Index = 0;

                // XNA version
                hookPointFound = cursor.TryGotoNext(MoveType.After,
                                                    instr => instr.OpCode == OpCodes.Ldloc_S,
                                                    instr => instr.MatchCallvirt <Entity>("get_X"),
                                                    instr => instr.OpCode == OpCodes.Ldloc_1,
                                                    instr => instr.MatchCallvirt <Entity>("get_X"));
            }

            if (hookPointFound)
            {
                Logger.Log("CollabUtils2/MiniHeartDoor", $"Making mini heart door approachable from both sides at {cursor.Index} in IL for HeartGemDoor.Routine");
                cursor.Index--;
                cursor.Emit(OpCodes.Dup);
                cursor.Index++;
                cursor.EmitDelegate <Func <HeartGemDoor, float, float> >((self, orig) => {
                    if (self is MiniHeartDoor door)
                    {
                        // actually check the Y poition of the player instead.
                        Player player = self.Scene.Tracker.GetEntity <Player>();
                        if (door.ForceTrigger || (player != null && player.Center.Y > door.Y - door.height && player.Center.Y < door.Y + door.height))
                        {
                            // player has same height as door => ok (return MaxValue so that the door is further right than the player)
                            return(float.MaxValue);
                        }
                        else
                        {
                            // player has not same height as door => ko (return MinValue so that the door is further left than the player)
                            return(float.MinValue);
                        }
                    }
                    return(orig);
                });
            }

            cursor.Index = 0;

            if (refToThis != null && cursor.TryGotoNext(MoveType.After, instr => instr.MatchLdcR4(80f)))
            {
                Logger.Log("CollabUtils2/MiniHeartDoor", $"Making mini heart door open on command at {cursor.Index} in IL for HeartGemDoor.Routine");

                cursor.Emit(OpCodes.Ldarg_0);
                cursor.Emit(OpCodes.Ldfld, refToThis);
                cursor.EmitDelegate <Func <float, HeartGemDoor, float> >((orig, self) => {
                    if (self is MiniHeartDoor door && door.ForceTrigger)
                    {
                        // force trigger the door by replacing the approach distance by... basically positive infinity.
                        return(float.MaxValue);
                    }
                    return(orig);
                });
            }

            // add a patch at the place where the vanilla opened_heartgem_door_[heartcount] gets set.
            if (refToThis != null && cursor.TryGotoNext(MoveType.After, instr => instr.MatchLdstr("opened_heartgem_door_")))
            {
                Logger.Log("CollabUtils2/MiniHeartDoor", $"Making mini heart door save its session flag at {cursor.Index} in IL for HeartGemDoor.Routine");

                cursor.Emit(OpCodes.Ldarg_0);
                cursor.Emit(OpCodes.Ldfld, refToThis);
                cursor.EmitDelegate <Action <HeartGemDoor> >(self => {
                    if (self is MiniHeartDoor door)
                    {
                        // mini heart doors use their own flags, that allow better differenciation between themselves by using entity ID.
                        (door.Scene as Level).Session.SetFlag("opened_mini_heart_door_" + door.entityID, true);
                    }
                });
            }
        }