/**<summary>Patches coin glowing when moving.</summary>*/ private static void Patch_Dust_UpdateDust() { string functionName = "Terraria.Dust.UpdateDust"; var updateDust = IL.GetMethodDefinition(Dust, "UpdateDust", 0); var onCoinGlow = ModDefinition.Import(IL.GetMethodDefinition(CoinReplacer, "OnCoinGlow")); var checks = new IL.OperandCheck[] { IL.VarCheck(LocOpCodes.Ldloc), IL.CheckField(OpCodes.Ldfld, "Dust::type"), IL.Check(OpCodes.Ldc_I4, (int)244), IL.Check(OpCodes.Blt), IL.VarCheck(LocOpCodes.Ldloc), IL.CheckField(OpCodes.Ldfld, "Dust::type"), IL.Check(OpCodes.Ldc_I4, (int)247), IL.Check(OpCodes.Bgt) }; int start = IL.ScanForInstructionPatternEnd(updateDust, checks); CheckFailedToFindStart(start, 0, functionName); var dust = IL.ScanForVariablePattern(updateDust, checks); CheckFailedToFindVariable(dust, "dust", functionName); int end = IL.ScanForInstructionPatternEnd(updateDust, start, IL.CheckMethod(OpCodes.Call, "Lighting::AddLight") ); CheckFailedToFindEnd(end, 0, functionName); IL.MethodReplaceRange(updateDust, start, end, Instruction.Create(OpCodes.Ldloc_S, dust), Instruction.Create(OpCodes.Call, onCoinGlow) ); }
/**<summary>Patches coin pickup text.</summary>*/ private static void Patch_ItemText_NewText() { string functionName = "Terraria.ItemText.NewText"; var newText = IL.GetMethodDefinition(ItemText, "NewText", 4); var onCoinPickupText = ModDefinition.Import(IL.GetMethodDefinition(CoinReplacer, "OnCoinPickupText")); var onCoinPickupText2 = ModDefinition.Import(IL.GetMethodDefinition(CoinReplacer, "OnCoinPickupText2")); var checks = new IL.OperandCheck[] { IL.Check(LocOpCodes.Ldloc), IL.Check(OpCodes.Brfalse), IL.CheckField(OpCodes.Ldsfld, "Main::itemText"), IL.VarCheck(LocOpCodes.Ldloc), IL.Check(OpCodes.Ldelem_Ref), IL.CheckField(OpCodes.Ldfld, "ItemText::coinText"), IL.Check(OpCodes.Brfalse) }; int start = IL.ScanForNthInstructionPatternEnd(newText, 1, checks); CheckFailedToFindStart(start, 0, functionName); var i = IL.ScanForNthVariablePattern(newText, 1, checks); CheckFailedToFindVariable(i, "i", functionName); var vector = IL.ScanForVariablePattern(newText, start, IL.CheckField(OpCodes.Ldsfld, "Main::fontMouseText"), IL.Check(LocOpCodes.Ldloc), IL.CheckMethod(OpCodes.Callvirt, "DynamicSpriteFont::MeasureString"), IL.VarCheck(LocOpCodes.Stloc) ); CheckFailedToFindVariable(vector, "vector", functionName); int end = IL.ScanForInstructionPatternEnd(newText, start, IL.Check(OpCodes.Ldc_I4, (int)246), IL.Check(OpCodes.Ldc_I4, (int)138), IL.Check(OpCodes.Ldc_I4_S, (sbyte)96), IL.Check(OpCodes.Newobj), IL.Check(OpCodes.Stfld) ); CheckFailedToFindEnd(end, 0, functionName); IL.MethodReplaceRange(newText, start, end, Instruction.Create(OpCodes.Ldarg_0), Instruction.Create(OpCodes.Ldloc_S, i), Instruction.Create(OpCodes.Call, onCoinPickupText), Instruction.Create(OpCodes.Stloc_S, vector) ); checks = new IL.OperandCheck[] { IL.CheckField(OpCodes.Ldsfld, "Main::itemText"), IL.VarCheck(LocOpCodes.Ldloc), IL.Check(OpCodes.Ldelem_Ref), IL.CheckField(OpCodes.Ldfld, "ItemText::coinText"), IL.Check(OpCodes.Brfalse) }; start = IL.ScanForInstructionPatternEnd(newText, end + 5, checks); CheckFailedToFindStart(start, 1, functionName); var num2 = IL.ScanForVariablePattern(newText, end + 5, checks); CheckFailedToFindVariable(num2, "num2", functionName); end = IL.ScanForInstructionPatternEnd(newText, start, IL.Check(OpCodes.Ldc_I4, (int)246), IL.Check(OpCodes.Ldc_I4, (int)138), IL.Check(OpCodes.Ldc_I4_S, (sbyte)96), IL.Check(OpCodes.Newobj), IL.Check(OpCodes.Stfld) ); CheckFailedToFindEnd(end, 1, functionName); IL.MethodReplaceRange(newText, start, end, Instruction.Create(OpCodes.Ldarg_0), Instruction.Create(OpCodes.Ldloc_S, num2), Instruction.Create(OpCodes.Call, onCoinPickupText2) ); }
/**<summary>Patches store buy and sell price text.</summary>*/ private static void Patch_Main_MouseText_DrawItemTooltip() { string functionName = "Terraria.Main.MouseText_DrawItemTooltip"; var mouseText_DrawItemTooltip = IL.GetMethodDefinition(Main, "MouseText_DrawItemTooltip", 4); var onNPCShopPrice = ModDefinition.Import(IL.GetMethodDefinition(CoinReplacer, "OnNPCShopPrice")); var storeValue = IL.ScanForVariablePattern(mouseText_DrawItemTooltip, IL.CheckField(OpCodes.Ldsfld, "Main::npcShop"), IL.Check(OpCodes.Ldc_I4_0), IL.Check(OpCodes.Ble), IL.CheckField(OpCodes.Ldsfld, "Main::HoverItem"), IL.CheckMethod(OpCodes.Callvirt, "Item::GetStoreValue"), IL.VarCheck(LocOpCodes.Stloc) ); CheckFailedToFindVariable(storeValue, "storeValue", functionName); int start = IL.ScanForInstructionPatternEnd(mouseText_DrawItemTooltip, IL.Check(OpCodes.Ldsfld), IL.CheckMethod(OpCodes.Callvirt, "Item::GetStoreValue"), IL.Check(OpCodes.Ldc_I4_0), IL.Check(OpCodes.Ble) ); CheckFailedToFindStart(start, 0, functionName); var array = IL.ScanForVariablePattern(mouseText_DrawItemTooltip, start, IL.CheckField(OpCodes.Ldsfld, "Main::HoverItem"), IL.CheckField(OpCodes.Ldfld, "Item::buy"), IL.Check(OpCodes.Brtrue_S), IL.VarCheck(LocOpCodes.Ldloc), IL.Check(LocOpCodes.Ldloc), IL.CheckField(OpCodes.Ldsfld, "Lang::tip") ); CheckFailedToFindVariable(array, "array", functionName); var num4 = IL.ScanForVariablePattern(mouseText_DrawItemTooltip, start, IL.CheckField(OpCodes.Ldsfld, "Main::HoverItem"), IL.CheckField(OpCodes.Ldfld, "Item::buy"), IL.Check(OpCodes.Brtrue_S), IL.Check(LocOpCodes.Ldloc), IL.VarCheck(LocOpCodes.Ldloc), IL.CheckField(OpCodes.Ldsfld, "Lang::tip") ); CheckFailedToFindVariable(num4, "num4", functionName); var array4 = IL.ScanForVariablePattern(mouseText_DrawItemTooltip, start, IL.VarCheck(LocOpCodes.Ldloc), IL.Check(LocOpCodes.Ldloc, num4), IL.Check(OpCodes.Ldstr, "Price"), IL.Check(OpCodes.Stelem_Ref) ); if (IsTMod) { CheckFailedToFindVariable(array4, "array4", functionName); } var checks = new IL.OperandCheck[] { IL.VarCheck(LocOpCodes.Ldloca), IL.Check(OpCodes.Ldc_R4, 246f), IL.Check(LocOpCodes.Ldloc), IL.Check(OpCodes.Mul), IL.Check(OpCodes.Conv_U1), IL.Check(OpCodes.Ldc_R4, 138f), IL.Check(LocOpCodes.Ldloc), IL.Check(OpCodes.Mul), IL.Check(OpCodes.Conv_U1), IL.Check(OpCodes.Ldc_R4, 96f), IL.Check(LocOpCodes.Ldloc), IL.Check(OpCodes.Mul), IL.Check(OpCodes.Conv_U1), IL.Check(LocOpCodes.Ldloc), IL.CheckMethod(OpCodes.Call, "Color::.ctor") }; var color = IL.ScanForVariablePattern(mouseText_DrawItemTooltip, start, checks); CheckFailedToFindVariable(color, "color", functionName); int end = IL.ScanForInstructionPatternEnd(mouseText_DrawItemTooltip, start, checks); CheckFailedToFindEnd(end, 0, functionName); start = IL.MethodReplaceRange(mouseText_DrawItemTooltip, start, end, Instruction.Create(OpCodes.Ldloc_S, color), Instruction.Create(OpCodes.Ldloc_S, num4), Instruction.Create(OpCodes.Ldloc_S, array), Instruction.Create(OpCodes.Ldloc_S, storeValue), Instruction.Create(OpCodes.Call, onNPCShopPrice), Instruction.Create(OpCodes.Stloc_S, color) ); if (IsTMod) { start = IL.MethodInsert(mouseText_DrawItemTooltip, start, Instruction.Create(OpCodes.Ldloc_S, array4), Instruction.Create(OpCodes.Ldloc_S, num4), Instruction.Create(OpCodes.Ldstr, "Price"), Instruction.Create(OpCodes.Stelem_Ref) ); } IL.MethodInsert(mouseText_DrawItemTooltip, start, Instruction.Create(OpCodes.Ldloc_S, num4), Instruction.Create(OpCodes.Ldc_I4_1), Instruction.Create(OpCodes.Add), Instruction.Create(OpCodes.Stloc_S, num4) ); }
//-------------------------------- #region Patchers /**<summary>Patches reforge cost text.</summary>*/ private static void Patch_Main_DrawInventory() { string functionName = "Terraria.Main.DrawInventory"; var drawInventory = IL.GetMethodDefinition(Main, "DrawInventory", 0); var onReforgeCost = ModDefinition.Import(IL.GetMethodDefinition(CoinReplacer, "OnReforgeCost")); var checks = new IL.OperandCheck[] { IL.CheckField(OpCodes.Ldsfld, "Main::reforgeItem"), IL.CheckField(OpCodes.Ldfld, "Item::type"), IL.Check(OpCodes.Ldc_I4_0), IL.Check(OpCodes.Ble), IL.CheckSkipIndefinite(), // TMod fix IL.CheckField(OpCodes.Ldsfld, "Main::reforgeItem"), IL.CheckField(OpCodes.Ldfld, "Item::value"), IL.VarCheck(LocOpCodes.Stloc), IL.CheckSkipIndefinite(), IL.CheckField(OpCodes.Ldsfld, "Main::player"), IL.CheckField(OpCodes.Ldsfld, "Main::myPlayer"), IL.Check(OpCodes.Ldelem_Ref), IL.CheckField(OpCodes.Ldfld, "Player::discount"), IL.Check(OpCodes.Brfalse_S), IL.CheckSkipIndefinite(), IL.VarCheck(LocOpCodes.Stloc), IL.Check(OpCodes.Ldstr, ""), IL.Check(LocOpCodes.Stloc) }; int start = IL.ScanForInstructionPatternEnd(drawInventory, checks); CheckFailedToFindStart(start, 0, functionName); var num60 = IL.ScanForVariablePattern(drawInventory, checks); CheckFailedToFindVariable(num60, "num60", functionName); var text3 = IL.ScanForVariablePattern(drawInventory, start - 2, IL.Check(OpCodes.Ldstr, ""), IL.VarCheck(LocOpCodes.Stloc) ); CheckFailedToFindVariable(text3, "text3", functionName); int end = IL.ScanForInstructionPattern(drawInventory, start, IL.CheckField(OpCodes.Ldsfld, "Main::spriteBatch"), IL.Check(LocOpCodes.Ldloc), IL.Check(OpCodes.Ldc_I4, 130), IL.Check(OpCodes.Add), IL.Check(OpCodes.Conv_R4), IL.Check(OpCodes.Ldarg_0), IL.CheckField(OpCodes.Ldfld, "Main::invBottom"), IL.Check(OpCodes.Conv_R4), IL.Check(OpCodes.Ldc_I4_1), IL.CheckMethod(OpCodes.Call, "ItemSlot::DrawSavings") ); CheckFailedToFindEnd(end, 0, functionName); IL.MethodReplaceRange(drawInventory, start, end, Instruction.Create(OpCodes.Ldloc_S, num60), Instruction.Create(OpCodes.Call, onReforgeCost), Instruction.Create(OpCodes.Stloc_S, text3) ); }