private void AddWaterShader(ILContext il)
        {
            ILCursor c = new ILCursor(il);

            //back target
            c.TryGotoNext(n => n.MatchLdfld <Main>("backWaterTarget"));

            c.TryGotoNext(n => n.MatchCallvirt <SpriteBatch>("Draw"));
            c.Index++;
            ILLabel label = il.DefineLabel(c.Next);

            c.TryGotoPrev(n => n.MatchLdfld <Main>("backWaterTarget"));
            c.Index -= 2;
            c.EmitDelegate <Action>(NewDrawBack);
            c.Emit(OpCodes.Br, label);

            //front target
            c.TryGotoNext(n => n.MatchLdsfld <Main>("waterTarget"));

            c.TryGotoNext(n => n.MatchCallvirt <SpriteBatch>("Draw"));
            c.Index++;
            ILLabel label2 = il.DefineLabel(c.Next);

            c.TryGotoPrev(n => n.MatchLdsfld <Main>("waterTarget"));
            c.Index--;
            c.EmitDelegate <Action>(NewDraw);
            c.Emit(OpCodes.Br, label2);
        }
        public static void Level_Render(ILContext il)
        {
            ILCursor c;

            new ILCursor(il).FindNext(out ILCursor[] found,
                                      i => i.MatchLdfld(typeof(Pathfinder), "DebugRenderEnabled"),
                                      i => i.MatchCall(typeof(Draw), "get_SpriteBatch"),
                                      i => i.MatchLdarg(0),
                                      i => i.MatchLdarg(0),
                                      i => i.MatchLdarg(0)
                                      );

            // Place labels at and after pathfinder rendering code
            ILLabel render     = il.DefineLabel();
            ILLabel skipRender = il.DefineLabel();

            c = found[1];
            c.MarkLabel(render);
            c = found[4];
            c.MarkLabel(skipRender);

            // || the value of DebugRenderEnabled with Debug rendering being enabled, && with seekers being present.
            c = found[0];
            c.Index++;
            c.Emit(OpCodes.Brtrue_S, render.Target);
            c.Emit(OpCodes.Call, typeof(GameplayRendererExt).GetMethod("get_RenderDebug"));
            c.Emit(OpCodes.Brfalse_S, skipRender.Target);
            c.Emit(OpCodes.Ldarg_0);
            c.Emit(OpCodes.Callvirt, typeof(Scene).GetMethod("get_Tracker"));
            MethodInfo GetEntity = typeof(Tracker).GetMethod("GetEntity");

            c.Emit(OpCodes.Callvirt, GetEntity.MakeGenericMethod(new Type[] { typeof(Seeker) }));
        }
Esempio n. 3
0
        /// <summary>MASSIVE thanks to Starlight River for the base of this IL edit.</summary>
        private static void AddWaterShader(ILContext il)
        {
            var c = new ILCursor(il);

            c.TryGotoNext(n => n.MatchLdfld <Main>("backWaterTarget"));            //Back target

            c.TryGotoNext(n => n.MatchCallvirt <SpriteBatch>("Draw"));
            c.Index++;
            ILLabel label = il.DefineLabel(c.Next);

            c.TryGotoPrev(n => n.MatchLdfld <Main>("backWaterTarget"));
            c.Emit(OpCodes.Pop);
            c.Emit(OpCodes.Pop);
            c.Emit(OpCodes.Ldc_I4_0);             //Push 0 because this is the back
            c.EmitDelegate <Action <bool> >(NewDraw);
            c.Emit(OpCodes.Br, label);

            c.TryGotoNext(n => n.MatchLdsfld <Main>("waterTarget"));            //Front target

            c.TryGotoNext(n => n.MatchCallvirt <SpriteBatch>("Draw"));
            c.Index++;
            ILLabel label2 = il.DefineLabel(c.Next);

            c.TryGotoPrev(n => n.MatchLdsfld <Main>("waterTarget"));
            c.Emit(OpCodes.Pop);
            c.Emit(OpCodes.Ldc_I4_1);             //Push 1 since this is the front
            c.EmitDelegate <Action <bool> >(NewDraw);
            c.Emit(OpCodes.Br, label2);
        }
Esempio n. 4
0
        private static void GameplayRenderer_Render(ILContext il)
        {
            ILCursor c;

            // Mark the instr after RenderExcept.
            ILLabel lblAfterEntities = il.DefineLabel();

            c = new ILCursor(il).Goto(0);
            c.GotoNext(
                i => i.MatchCallvirt(typeof(EntityList), "RenderExcept")
                );
            c.Index++;
            c.MarkLabel(lblAfterEntities);

            // Branch after calling Begin.
            c = new ILCursor(il).Goto(0);
            // GotoNext skips c.Next
            if (!c.Next.MatchCall(typeof(GameplayRenderer), "Begin"))
            {
                c.GotoNext(i => i.MatchCall(typeof(GameplayRenderer), "Begin"));
            }

            c.Index++;
            c.EmitDelegate <Func <bool> >(() => Settings.SimplifiedGraphics && Settings.HideGameplay);
            // c.Emit(OpCodes.Call, typeof(CelesteTASModule).GetMethod("get_Settings"));
            // c.Emit(OpCodes.Callvirt, typeof(CelesteTASModuleSettings).GetMethod("get_HideGameplay"));
            c.Emit(OpCodes.Brtrue, lblAfterEntities);
        }
Esempio n. 5
0
        private static void ILItemOnRightClick(ILContext il)
        {
            ILCursor cursor = new ILCursor(il);
            ILLabel  label  = il.DefineLabel();

            if (!cursor.TryGotoNext(i => i.MatchBr(out label), i => i.MatchLdarg(0), i => i.MatchLdarg(2),
                                    i => i.MatchLdelemRef(), i => i.MatchCall(out _)))
            {
                return;
            }

            cursor.Index++;
            cursor.MoveAfterLabels();
            cursor.Emit(Ldarg_0);
            cursor.Emit(Ldarg_2);
            cursor.Emit(Ldloc_0);
            cursor.EmitDelegate <Func <Item[], int, Player, bool> >((item, slot, player) =>
            {
                if (Main.mouseRight && Main.mouseRightRelease && Main.mouseItem.modItem is ItemOnRightClick modItem)
                {
                    if (modItem.CanRightClick(item[slot], false))
                    {
                        Main.mouseItem.Consume();
                        modItem.RightClick(ref item[slot], player, false);
                        Main.mouseRightRelease = false;
                        Recipe.FindRecipes();
                    }
                    return(true);
                }
                return(false);
            });
            cursor.Emit(Brtrue, label);
        }
Esempio n. 6
0
        private void AddProfessionalMode(ILContext il)
        {
            ILCursor c = new ILCursor(il);
            ILLabel  ifStatementEnd = null;

            var a = typeof(Main).GetField(nameof(Main.menuMode));

            if (!c.TryGotoNext(i => i.MatchLdsfld(a),
                               i => i.MatchLdcI4(-7),
                               i => i.MatchBneUn(out ifStatementEnd)))
            {
                Logger.Info("SpectraMod failed to patch DrawMenu");
                return;
            }
            if (ifStatementEnd == null)
            {
                Logger.Info("SpectraMod's DrawMenu patch's label is null");
                return;
            }

            ILLabel reeee = il.DefineLabel();

            int start = c.Index;

            c.GotoLabel(ifStatementEnd);
            int end = c.Index;

            c.Goto(start);

            c.Emit(OpCodes.Br, reeee);
            c.Goto(end);
            c.MarkLabel(reeee);

            var focus        = typeof(Main).GetField("focusMenu", BindingFlags.NonPublic | BindingFlags.Instance);
            var selectedmenu = typeof(Main).GetField("selectedMenu", BindingFlags.NonPublic | BindingFlags.Instance);

            // pushing fields by reference to the delegate (except this)
            c.Emit(OpCodes.Ldarg_0);                                            // this
            c.Emit(OpCodes.Ldarg_0);                                            // this
            c.Emit(OpCodes.Ldflda, focus);                                      // focusmenu
            c.Emit(OpCodes.Ldarg_0);                                            // this
            c.Emit(OpCodes.Ldflda, selectedmenu);                               // selectedmenu
            c.Emit(OpCodes.Ldloca, 5);                                          // num2
            c.Emit(OpCodes.Ldloca, 7);                                          // num4
            c.Emit(OpCodes.Ldloca, 19);                                         // array4
            c.Emit(OpCodes.Ldloca, 21);                                         // array6
            c.Emit(OpCodes.Ldloca, 26);                                         // array9
            c.Emit(OpCodes.Ldloca, 16);                                         // array
            c.Emit(OpCodes.Ldloca, 8);                                          // num5
            c.Emit(OpCodes.Ldloca, 25);                                         // flag5

            c.Emit(OpCodes.Call, ((modifyingdelegate)ProfessionalMenu).Method); // now we call E V E R Y T H I N G that was inside that if statement manually, rip
        }
        private void HookTakeUnityPotion(ILContext il)
        {
            ILCursor cursor = new ILCursor(il);

            // if (portableWormholePlayer.hasPortableWormhole) return;
            cursor.Emit(Ldarg_0);
            cursor.EmitDelegate(PortableWormholeDelegate);

            ILLabel label = il.DefineLabel();

            cursor.Emit(Brfalse, label);
            cursor.Emit(Ret);
            cursor.MarkLabel(label);
        }
Esempio n. 8
0
        //The following 3 things are used for an IL edit that disables the vanilla painting handled in Player.PlaceThing
        private void HookPlaceThing(ILContext il)
        {
            var c = new ILCursor(il);

            var label = il.DefineLabel();

            c.Emit(Ldarg_0);
            c.Emit(OpCodes.Call, ((shouldInterruptPlaceThingDelegate)shouldInterruptPlaceThing).Method);
            c.Emit(Brfalse_S, label);

            c.Emit(Ret);

            c.MarkLabel(label);
        }
Esempio n. 9
0
        /*
         * Some useful ModdersToolkit REPL snippets for testing patches (need `using Terraria.ID;`):
         *
         * int CorruptGrass = 0;
         * for (int i = 0; i < Main.maxTilesX; i++) {
         *      for (int j = 0; j < Main.maxTilesY; j++) {
         *              Tile tile = Main.tile[i, j];
         *              if (tile.type == TileID.Crimstone)
         *                      Crimstone++;
         *              if (tile.type == TileID.Pearlstone)
         *                      Pearlstone++;
         *              if (tile.type == TileID.Ebonstone)
         *                      Ebonstone++;
         *              if (tile.type == TileID.Grass)
         *                      Grass++;
         *              if (tile.type == TileID.FleshGrass)
         *                      FleshGrass++;
         *              if (tile.type == TileID.HallowedGrass)
         *                      HallowedGrass++;
         *              if (tile.type == TileID.CorruptGrass)
         *                      CorruptGrass++;
         *      }
         * }
         * Main.NewText("Totals: ");
         * Main.NewText("Ebonstone: " + Ebonstone);
         * Main.NewText("Pearlstone: " + Pearlstone);
         * Main.NewText("Crimstone: " + Crimstone);
         * Main.NewText("Grass: " + Grass);
         * Main.NewText("FleshGrass: " + FleshGrass);
         * Main.NewText("HallowedGrass: " + HallowedGrass);
         * Main.NewText("CorruptGrass: " + CorruptGrass);
         *
         * //for (int i = 0; i < Main.maxTilesX; i++) {
         * //    for (int j = 0; j < Main.maxTilesY; j++) {
         * //		Tile tile = Main.tile[i, j];
         * //		if (tile.type == TileID.Crimstone)
         * //			tile.type = TileID.Stone;
         * //		if (tile.type == TileID.Pearlstone)
         * //			tile.type = TileID.Stone;
         * //		if (tile.type == TileID.Ebonstone)
         * //			tile.type = TileID.Stone;
         * //	}
         * //}
         */
        private void WorldGen_hardUpdateWorld(ILContext il)
        {
            // Prevents Tile Spread
            // Modifies this code:
            //if (NPC.downedPlantBoss && WorldGen.genRand.Next(2) != 0) {
            //	return;
            //+ if(DisableCorruptionSpread.CorruptionSpreadDisabled)
            //+     return;
            //if (type == 23 || type == 25 || type == 32 || type == 112 || type == 163 || type == 400 || type == 398) {

            var c = new ILCursor(il);

            if (!c.TryGotoNext(i => i.MatchLdsfld <NPC>(nameof(NPC.downedPlantBoss))))
            {
                return;                                            // Patch unable to be applied
            }
            if (!c.TryGotoNext(MoveType.After, i => i.MatchRet())) // instead of: c.Index++; // Move after ret
            {
                return;
            }

            c.MoveAfterLabels();             // Simplifies the logic, as we don't have to point the original label to our instruction. Affects current cursor index, not a persistent setting.
            c.EmitDelegate <Func <bool> >(() => {
                return(DisableCorruptionSpreadModWorld.CorruptionSpreadDisabled);
            });
            var postSkipCheckLabel = il.DefineLabel();

            c.Emit(Brfalse, postSkipCheckLabel);
            c.Emit(Ret);
            c.MarkLabel(postSkipCheckLabel);

            // These 2 original approaches are a bit unreliable and ugly.
            //var originalLabel = c.IncomingLabels.First(); // unreliable on Debug. ldc.i4.s 23 might be only reliable one.

            //c.Emit(Ldsfld, typeof(DisableCorruptionSpreadModWorld).GetField(nameof(DisableCorruptionSpreadModWorld.CorruptionSpreadDisabled)));
            //c.Index--;
            //c.MarkLabel(originalLabel);
            //c.Index++;

            //int index = c.Index;
            //var result = c.EmitDelegate<Func<bool>>(() => {
            //	return DisableCorruptionSpreadModWorld.CorruptionSpreadDisabled;
            //});
            //originalLabel.Target = c.Instrs[index];

            patchSuccessTileSpread = true;
        }
        private void OnHitEnemyAddCustomBuff(ILContext il)
        {
            var     c     = new ILCursor(il);
            ILLabel label = il.DefineLabel();

            Mono.Cecil.FieldReference fr1;
            c.GotoNext(
                x => x.MatchLdarg(2),
                x => x.MatchCallvirt <GameObject>("GetComponent"),
                x => x.MatchStloc(out victimBodyIndex));

            c.GotoNext(
                x => x.MatchLdloc(victimBodyIndex),
                x => x.MatchLdcI4(26),
                x => x.MatchLdcR4(2)
                );

            c.Emit(OpCodes.Ldarg_1); //Arg1 = DamageInfo
            c.Emit(OpCodes.Ldarg_2); //Arg2 = VictimGameObj
            c.EmitDelegate <Func <DamageInfo, GameObject, bool> >((damageInfo, victimGameObject) =>
            {
                if (ModIsActive)
                {
                    var attackerBody = damageInfo.attacker.GetComponent <CharacterBody>();
                    var victimBody   = victimGameObject.GetComponent <CharacterBody>();

                    var attackerChronobaubleCount = attackerBody.inventory.GetItemCount(ItemIndex.SlowOnHit);
                    var victimCurrentBuffCount    = victimBody.GetBuffCount(CustomChronobaubleBuffIndex);
                    var maximumBuffCount          = DebuffStacksPerItemStack.Value * attackerChronobaubleCount;

                    if (victimCurrentBuffCount < maximumBuffCount)
                    {
                        float debuffDuration = DebuffDuration.Value + IncreasedDebuffDurationPerStack.Value * (attackerChronobaubleCount - 1);
                        victimBody.AddTimedBuff(CustomChronobaubleBuffIndex, debuffDuration);
                    }
                    return(false);
                }
                else
                {
                    return(true);
                }
            });
            c.Emit(OpCodes.Brfalse, label); //If delegate returns false, break and do not add buff
            c.GotoNext(x => x.MatchLdloc(0));
            c.MarkLabel(label);
        }
Esempio n. 11
0
        public static void HasAmmo(ILContext il)
        {
            ILCursor cursor = new ILCursor(il);

            cursor.Emit(Ldarg_0);
            cursor.Emit(Ldarg_1);
            cursor.EmitDelegate <Func <Player, Item, bool> >((player, item) => {
                EndlessAmmoPlayer modPlayer = player.GetModPlayer <EndlessAmmoPlayer>();
                return(modPlayer.GetItemForEndlessAmmoType(item.useAmmo).type > ItemID.None);
            });

            ILLabel label = il.DefineLabel();

            cursor.Emit(Brfalse, label);
            cursor.Emit(Ldc_I4_1);
            cursor.Emit(Ret);
            cursor.MarkLabel(label);
        }
Esempio n. 12
0
        private void SwapLavaDrawEffects(ILContext il)
        {
            var c = new ILCursor(il);

            c.TryGotoNext(n => n.MatchLdsfld <Dust>("lavaBubbles"));
            c.Index += 3;

            var savedIndex = c.Index;

            c.TryGotoNext(n => n.MatchLdloc(4)); //I know this looks bad but this is reliable enough. Local 4 is ptr2 in source
            var label = il.DefineLabel(c.Next);

            c.Index = savedIndex;
            c.Emit(OpCodes.Ldloc, 66); //num25, x coordinate iteration variable
            c.Emit(OpCodes.Ldloc, 67); //num26, y coordinate iteration variable
            c.EmitDelegate <Func <int, int, bool> >(SwapLava);
            c.Emit(OpCodes.Brtrue, label);
        }
Esempio n. 13
0
        private void ILGoldenLockBox(ILContext il)
        {
            ILCursor cursor = new ILCursor(il);

            if (!cursor.TryGotoNext(MoveType.After, i => i.MatchLdcI4(ItemID.GoldenKey), i => i.MatchLdcI4(0),
                                    i => i.MatchCallvirt(typeof(Player).GetMethod(nameof(Player.ConsumeItem)))))
            {
                return;
            }

            ILLabel label = il.DefineLabel();

            cursor.Emit(Brtrue_S, label);
            cursor.Emit(Ldloc_0);
            cursor.EmitDelegate <Func <Player, bool> >(player => player.HasItem(ItemType <MasterKey>()));
            cursor.Index++;
            cursor.MarkLabel(label);
        }
Esempio n. 14
0
        private void HookAdjustButton(ILContext il)
        {
            var c = new ILCursor(il).Goto(0);

            if (!c.TryGotoNext(i => i.MatchLdcI4(NPCID.TaxCollector)))
            {
                return;
            }
            if (!c.TryGotoNext(i => i.Match(Bne_Un)))
            {
                return;
            }

            c.Index++;
            ILLabel label = il.DefineLabel();

            c.EmitDelegate <Func <bool> >(() => TaxWorld.serverConfig.AddCustomDialog);
            c.Emit(Brfalse_S, label);
            c.EmitDelegate <Func <string> >(() => Language.GetTextValue("Mods.BetterTaxes.Status.Status"));
            c.Emit(Stloc_S, (byte)10);
            c.MarkLabel(label);
        }
        private void PlayCustomSound(ILContext il)
        {
            ILCursor c = new ILCursor(il);

            while (c.TryGotoNext(n => n.MatchCall <Main>("PlaySound")))                //swap every sound call
            {
                var branchTarget = il.DefineLabel(c.Next.Next);                        //so we can skip to after the vanilla sound call later

                c.Index -= 5;                                                          //back up 5 instructions to just under where the soundID is pushed

                c.Emit(OpCodes.Ldarg_0);                                               //load item array
                c.Emit(OpCodes.Ldarg_2);                                               //load index
                c.Emit(OpCodes.Ldelem_Ref);                                            //push item ref

                c.EmitDelegate <Func <int, Item, SoundEffectInstance> >(PlayNewSound); //play the custom sound if applicable
                c.Emit(OpCodes.Br, branchTarget);                                      //move past sound call

                //load a sound ID back onto the stack since mac / linux check both paths even if its an unconditional branch ()
                c.Emit(OpCodes.Ldc_I4_0);     //putting a 0 but the actual value does not matter

                c.Index += 7;                 //so we wont keep patching the same call lol
            }
        }
Esempio n. 16
0
        private void NPC_getNewNPCName(ILContext il)
        {
            ILCursor c = new ILCursor(il);

            try {
                System.Reflection.MethodInfo method = typeof(KeepNames).GetMethod(nameof(getSavedName));

                ILLabel label = il.DefineLabel();
                c.Emit(Ldarg_0);
                c.Emit(OpCodes.Call, method);
                c.Emit(Stloc_0);
                c.Emit(Ldloc_0);
                c.Emit(Brfalse_S, label);
                c.Emit(Ldloc_0);
                c.Emit(Ret);

                c.MarkLabel(label);
                _patchedGame = true;
            } catch (System.Exception e) {
                Logger.Error($"{e.Message} - {e.StackTrace}");
                _patchedGame = false;
            }
        }
        private void ApplyTwice(ILContext il) //this is horrid.
        {
            var c = new ILCursor(il);

            c.TryGotoNext(i => i.MatchStfld <Item>("crit"), i => i.MatchLdloc(2), i => i.MatchLdcI4(84));
            c.Index++;

            ILLabel label = il.DefineLabel(c.Next); //for when we need to skip later

            c.TryGotoPrev(i => i.MatchLdarg(0), i => i.MatchLdarg(0), i => i.MatchLdfld <Item>("damage"));

            c.Emit(OpCodes.Ldarg_0); //emits the values of the prefixes decided by vanilla, and the item instance
            c.Emit(OpCodes.Ldloc, 3);
            c.Emit(OpCodes.Ldloc, 5);
            c.Emit(OpCodes.Ldloc, 8);
            c.Emit(OpCodes.Ldloc, 4);
            c.Emit(OpCodes.Ldloc, 6);
            c.Emit(OpCodes.Ldloc, 7);
            c.Emit(OpCodes.Ldloc, 9);

            c.EmitDelegate <Func <Item, float, float, float, float, float, float, int, bool> >(ApplyTwiceBody); //funny!

            c.Emit(OpCodes.Brtrue, label);                                                                      //skip vanilla stat setting if we do our own!
        }
Esempio n. 18
0
        public static void PickAmmo(ILContext il)
        {
            ILLabel UseNormalAmmoLabel  = il.DefineLabel();
            ILLabel UseEndlessAmmoLabel = il.DefineLabel();
            ILLabel CanShootLabel       = il.DefineLabel();

            // Item item = new Item();
            // bool flag = false;
            ILCursor cursor = new ILCursor(il);

            if (!cursor.TryGotoNext(i => i.MatchLdcI4(0) && i.Next.MatchStloc(1)))
            {
                throw new Exception("Could not locate flag = false");
            }

            cursor.Index += 2;

            // bool useEndlessAmmoFirst = Delegate(this);
            cursor.Emit(Ldarg_0);             // Player player
            cursor.EmitDelegate <Func <Player, bool> >((player) => {
                EndlessAmmoPlayer modPlayer = player.GetModPlayer <EndlessAmmoPlayer>();
                return(modPlayer.useEndlessAmmoFirst);
            });

            cursor.Emit(Stloc_2);

            // if (useEndlessAmmoFirst == false) goto USE_NORMAL_AMMO;
            cursor.Emit(Ldloc_2);
            cursor.Emit(Brfalse, UseNormalAmmoLabel);

            // USE_ENDLESS_AMMO:
            cursor.MarkLabel(UseEndlessAmmoLabel);

            // item = Delegate(this, sItem);
            cursor.Emit(Ldarg_0);             // Player player
            cursor.Emit(Ldarg_1);             // Item weapon
            cursor.EmitDelegate <Func <Player, Item, Item> >((player, weapon) => {
                EndlessAmmoPlayer modPlayer = player.GetModPlayer <EndlessAmmoPlayer>();
                Item playerAmmo             = modPlayer.GetItemForEndlessAmmoType(weapon.useAmmo);
                return(playerAmmo);
            });
            cursor.Emit(Stloc_0);

            ILLabel IfItemIsAirLabel = il.DefineLabel();

            // if (item.type == 0) goto ITEM_IS_AIR;
            cursor.Emit(Ldloc_0);
            cursor.Emit(Ldfld, typeof(Item).GetField(nameof(Item.type)));
            cursor.Emit(Brfalse, IfItemIsAirLabel);
            // canShoot = true;
            cursor.Emit(Ldarg, 4);
            cursor.Emit(Ldc_I4_1);
            cursor.Emit(Stind_I1);
            // dontConsume = true;
            cursor.Emit(Ldc_I4_1);
            cursor.Emit(Starg, 7);

            // goto CAN_SHOOT;
            cursor.Emit(Br, CanShootLabel);

            // ITEM_IS_AIR:
            cursor.MarkLabel(IfItemIsAirLabel);

            // if (useEndlessAmmoFirst == false) goto CAN_SHOOT;
            cursor.Emit(Ldloc_2);
            cursor.Emit(Brfalse, CanShootLabel);

            // USE_NORMAL_AMMO:
            cursor.MarkLabel(UseNormalAmmoLabel);

            // ..
            if (!cursor.TryGotoNext(i => i.MatchLdarg(4) && i.Next.MatchLdindU1()))
            {
                throw new Exception("Could not locate canShoot == false conditional.");
            }

            // if (useEndlessAmmoFirst) goto CAN_SHOOT;
            ILLabel SkipAheadLabel = il.DefineLabel();

            cursor.Emit(Ldloc_2);
            cursor.Emit(Brtrue, CanShootLabel);

            // if (item.type == 0) goto USE_ENDLESS_AMMO;
            cursor.Emit(Ldloc_0);
            cursor.Emit(Ldfld, typeof(Item).GetField(nameof(Item.type)));
            cursor.Emit(Brfalse, UseEndlessAmmoLabel);

            // CAN_SHOOT:
            cursor.MarkLabel(CanShootLabel);

            // if (!canShoot) return;
            // ...
        }
Esempio n. 19
0
        public void HookAdjustAngler(ILContext il)
        {
            var c = new ILCursor(il).Goto(0);

            // we force reset the angler quest if not on a server
            if (!c.TryGotoNext(i => i.MatchLdsfld(typeof(Main).GetField(nameof(Main.anglerWhoFinishedToday)))))
            {
                throw new Exception("Can't patch force reset");
            }
            if (!c.TryGotoNext(i => i.MatchCall(typeof(Lang).GetMethod(nameof(Lang.AnglerQuestChat)))))
            {
                throw new Exception("Can't patch force reset");
            }
            ILLabel label = il.DefineLabel();

            c.Emit(Brtrue_S, label);
            c.Emit(Ldloc_S, (byte)50);
            c.Index += 2;
            c.MarkLabel(label);
            if (!c.TryGotoNext(i => i.MatchCall(typeof(AchievementsHelper).GetMethod(nameof(AchievementsHelper.HandleAnglerService)))))
            {
                throw new Exception("Can't patch force reset");
            }
            c.Emit(Call, typeof(NoFishTimer).GetMethod(nameof(NoFishTimer.AnglerQuestSwap)));
            c.EmitDelegate <Action>(() => {
                if (!NoFishWorld.serverConfig.DisableAnglerTimer)
                {
                    Main.npcChatText = Lang.AnglerQuestChat(true);
                }
                else if (Main.netMode != 1)
                {
                    Main.npcChatText = Lang.AnglerQuestChat();
                }
            });

            // add reroll button
            c.Goto(0);
            if (!c.TryGotoNext(i => i.MatchLdcI4(NPCID.Angler)))
            {
                throw new Exception("Can't patch reroll button");
            }
            if (!c.TryGotoNext(i => i.MatchLdcI4(NPCID.Angler)))
            {
                throw new Exception("Can't patch reroll button");
            }
            c.Index += 2;

            label = il.DefineLabel();
            c.EmitDelegate <Func <bool> >(() => NoFishWorld.serverConfig.RerollPrice > 0);
            c.Emit(Brfalse_S, label);

            c.EmitDelegate <Func <string> >(() =>
            {
                int num13    = 0, num14 = 0, num15 = 0, num16 = 0;
                int num17    = NoFishWorld.serverConfig.RerollPrice;
                string text2 = "";

                if (num17 >= 1000000)
                {
                    num13  = num17 / 1000000;
                    num17 -= num13 * 1000000;
                }
                if (num17 >= 10000)
                {
                    num14  = num17 / 10000;
                    num17 -= num14 * 10000;
                }
                if (num17 >= 100)
                {
                    num15  = num17 / 100;
                    num17 -= num15 * 100;
                }
                if (num17 >= 1)
                {
                    num16 = num17;
                }

                if (num13 > 0)
                {
                    object obj5 = text2;
                    text2       = string.Concat(new object[]
                    {
                        obj5,
                        num13,
                        " ",
                        Language.GetText("LegacyInterface.15").Value,
                        " "
                    });
                }
                if (num14 > 0)
                {
                    object obj6 = text2;
                    text2       = string.Concat(new object[]
                    {
                        obj6,
                        num14,
                        " ",
                        Language.GetText("LegacyInterface.16").Value,
                        " "
                    });
                }
                if (num15 > 0)
                {
                    object obj7 = text2;
                    text2       = string.Concat(new object[]
                    {
                        obj7,
                        num15,
                        " ",
                        Language.GetText("LegacyInterface.17").Value,
                        " "
                    });
                }
                if (num16 > 0)
                {
                    object obj8 = text2;
                    text2       = string.Concat(new object[]
                    {
                        obj8,
                        num16,
                        " ",
                        Language.GetText("LegacyInterface.18").Value,
                        " "
                    });
                }

                text2 = text2.Substring(0, text2.Length - 1);
                return(Language.GetTextValue("Mods.NoFishTimer.Dialog.Reroll") + " (" + text2 + ")");
            });
            c.Emit(Stloc_S, (byte)10);

            c.EmitDelegate <Func <Color> >(() =>
            {
                int num13 = 0, num14 = 0, num15 = 0, num16 = 0;
                int num17 = NoFishWorld.serverConfig.RerollPrice;

                if (num17 >= 1000000)
                {
                    num13  = num17 / 1000000;
                    num17 -= num13 * 1000000;
                }
                if (num17 >= 10000)
                {
                    num14  = num17 / 10000;
                    num17 -= num14 * 10000;
                }
                if (num17 >= 100)
                {
                    num15  = num17 / 100;
                    num17 -= num15 * 100;
                }
                if (num17 >= 1)
                {
                    num16 = num17;
                }

                float num18 = Main.mouseTextColor / 255f;
                if (num13 > 0)
                {
                    return(new Color((byte)(220f * num18), (byte)(220f * num18), (byte)(198f * num18), Main.mouseTextColor));
                }
                else if (num14 > 0)
                {
                    return(new Color((byte)(224f * num18), (byte)(201f * num18), (byte)(92f * num18), Main.mouseTextColor));
                }
                else if (num15 > 0)
                {
                    return(new Color((byte)(181f * num18), (byte)(192f * num18), (byte)(193f * num18), Main.mouseTextColor));
                }
                return(new Color((byte)(246f * num18), (byte)(138f * num18), (byte)(96f * num18), Main.mouseTextColor));
            });
            c.Emit(Stloc_S, (byte)2);

            c.MarkLabel(label);
        }