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) })); }
/// <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); }
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); }
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); }
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); }
//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); }
/* * 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); }
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); }
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); }
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); }
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 } }
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! }
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; // ... }
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); }