static IEnumerable <CodeInstruction> Transpiler_ShowCreateCharacter(IEnumerable <CodeInstruction> instructions) { var Sequence = new PatchTargetInstructionSet(new List <PatchTargetInstruction> { new PatchTargetInstruction(OpCodes.Call, CreateCharacter_BuildLibraryManagement) }); bool patched = false; foreach (var instruction in instructions) { if (!patched && Sequence.IsMatchComplete(instruction)) { instruction.operand = QudUX_BuildLibraryScreen_Show; patched = true; } yield return(instruction); } if (patched) { PatchHelpers.LogPatchResult("CreateCharacter", "Patched successfully." /* Revamps the Build Library text UI. */); } else { PatchHelpers.LogPatchResult("CreateCharacter", "Failed. This patch may not be compatible with the current game version. " + "The revamped Build Library text UI will not be used."); } }
static IEnumerable <CodeInstruction> Transpiler_Move1(IEnumerable <CodeInstruction> instructions) { var Sequence = new PatchTargetInstructionSet(new List <PatchTargetInstruction> { new PatchTargetInstruction(OpCodes.Ldstr, "You cannot go that way."), new PatchTargetInstruction(OpCodes.Call, MessageQueue_AddPlayerMessage, 2) }); bool patched = false; foreach (var instruction in instructions) { yield return(instruction); if (!patched && Sequence.IsMatchComplete(instruction)) { yield return(new CodeInstruction(OpCodes.Ldstr, "{{w|Can't go that way!}},{{w|Nothing there!}}")); yield return(new CodeInstruction(OpCodes.Call, ParticleTextMaker_EmitFromPlayer)); patched = true; } } ReportPatchStatus(patched); }
static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { var Sequence = new PatchTargetInstructionSet(new List <PatchTargetInstruction> { new PatchTargetInstruction(OpCodes.Ldstr, "Starting game!") }); bool patched = false; foreach (var instruction in instructions) { if (!patched && Sequence.IsMatchComplete(instruction)) { yield return(new CodeInstruction(OpCodes.Call, Events_EmbarkEvent)); yield return(new CodeInstruction(OpCodes.Call, Events_OnLoadAlwaysEvent)); patched = true; } yield return(instruction); } if (patched) { PatchHelpers.LogPatchResult("XRLCore.NewGame", "Patched successfully." /* Enables an event framework that other QudUX features rely on. */); } else { PatchHelpers.LogPatchResult("XRLCore.NewGame", "Failed. This patch may not be compatible with the current game version. " + "Custom tiles chosen during character creation won't be properly applied at game start, " + "and certain other event-based QudUX features might not work as expected."); } }
static IEnumerable <CodeInstruction> Transpiler_Move2(IEnumerable <CodeInstruction> instructions) { var Sequence1 = new PatchTargetInstructionSet(new List <PatchTargetInstruction> { new PatchTargetInstruction(OpCodes.Callvirt, Cell_HasBridge), new PatchTargetInstruction(OpCodes.Callvirt, GameObject_IsDangerousOpenLiquidVolume, 80), new PatchTargetInstruction(OpCodes.Ldstr, ", dangerous-looking ", 30), new PatchTargetInstruction(OpCodes.Ldloc_S, 8), new PatchTargetInstruction(OpCodes.Callvirt, GameObject_get_ShortDisplayName, 0), new PatchTargetInstruction(OpCodes.Stfld, XRLCore_MoveConfirmDirection, 40) }); var Sequence2 = new PatchTargetInstructionSet(new List <PatchTargetInstruction> { new PatchTargetInstruction(OpCodes.Callvirt, Cell_GetDangerousOpenLiquidVolume), new PatchTargetInstruction(OpCodes.Ldfld, XRLCore_MoveConfirmDirection, 6), new PatchTargetInstruction(OpCodes.Ldstr, "Are you sure you want to move into ", 56), new PatchTargetInstruction(OpCodes.Ldloc_S, 4), new PatchTargetInstruction(OpCodes.Callvirt, GameObject_get_the, 14), new PatchTargetInstruction(OpCodes.Stfld, XRLCore_MoveConfirmDirection, 21) }); int seq = 1; bool patched = false; foreach (var instruction in instructions) { yield return(instruction); if (seq == 1) { if (Sequence1.IsMatchComplete(instruction)) { yield return(new CodeInstruction(OpCodes.Ldloc_S, Sequence1.MatchedInstructions[3].operand)); yield return(new CodeInstruction(OpCodes.Ldc_I4_1)); yield return(new CodeInstruction(OpCodes.Call, ParticleTextMaker_EmitFromPlayerIfLiquid)); seq++; } } else if (!patched && Sequence2.IsMatchComplete(instruction)) { yield return(new CodeInstruction(OpCodes.Ldloc_S, Sequence2.MatchedInstructions[3].operand)); yield return(new CodeInstruction(OpCodes.Ldc_I4_0)); yield return(new CodeInstruction(OpCodes.Call, ParticleTextMaker_EmitFromPlayerIfLiquid)); patched = true; } } ReportPatchStatus(patched); }
static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { var Sequence1 = new PatchTargetInstructionSet(new List <PatchTargetInstruction> { new PatchTargetInstruction(OpCodes.Ldstr, " ]}}"), new PatchTargetInstruction(OpCodes.Callvirt, ScreenBuffer_Write, 2), new PatchTargetInstruction(OpCodes.Pop, 0) }); bool patched = false; foreach (var instruction in instructions) { yield return(instruction); if (!patched && Sequence1.IsMatchComplete(instruction)) { //draw conversation speaker's tile and temporarily suppress any Unity prefab animations beneath it yield return(new CodeInstruction(OpCodes.Ldsfld, ConversationUI__ScreenBuffer)); //_ScreenBuffer yield return(new CodeInstruction(OpCodes.Ldarg_1)); //Speaker yield return(new CodeInstruction(OpCodes.Call, ConversationUIExtender_DrawConversationSpeakerTile)); patched = true; } } if (patched) { PatchHelpers.LogPatchResult("ConversationUI", "Patched successfully." /* Adds the speaker's sprite to the title bar of conversation windows. */); } else { PatchHelpers.LogPatchResult("ConversationUI", "Failed. This patch may not be compatible with the current game version. " + "Sprites won't be added to the title bar of conversation windows."); } }
static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { var Sequence = new PatchTargetInstructionSet(new List <PatchTargetInstruction> { new PatchTargetInstruction(OpCodes.Ldstr, "The way is blocked by "), new PatchTargetInstruction(OpCodes.Call, IComponent_GameObject_AddPlayerMessage, 11) }); bool patched = false; foreach (var instruction in instructions) { yield return(instruction); if (!patched && Sequence.IsMatchComplete(instruction)) { yield return(new CodeInstruction(OpCodes.Ldarg_0)); yield return(new CodeInstruction(OpCodes.Callvirt, IPart_get_ParentObject)); yield return(new CodeInstruction(OpCodes.Call, ParticleTextMaker_EmitFromPlayerIfBarrierInDifferentZone)); patched = true; } } if (patched) { PatchHelpers.LogPatchResult("Physics.HandleEvent", "Patched successfully." /* Adds option to show particle text messages when movement to connected zone is prevented. */); } else { PatchHelpers.LogPatchResult("Physics.HandleEvent", "Failed. This patch may not be compatible with the current game version. " + "Some particle text effects may not be shown when movement is prevented."); } }
static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions, ILGenerator generator) { var Sequence1 = new PatchTargetInstructionSet(new List <PatchTargetInstruction> { new PatchTargetInstruction(OpCodes.Ldc_I4_S, (object)62), new PatchTargetInstruction(OpCodes.Ldc_I4_S, (object)24, 0), new PatchTargetInstruction(OpCodes.Callvirt, 0), //ScreenBuffer.Goto new PatchTargetInstruction(OpCodes.Pop, 0), new PatchTargetInstruction(OpCodes.Ldsfld, 0), new PatchTargetInstruction(LoadHighScoreDeleteCommandString, 0), new PatchTargetInstruction(OpCodes.Ldc_I4_1, 0), new PatchTargetInstruction(OpCodes.Callvirt, ScreenBuffer_Write, 0), new PatchTargetInstruction(OpCodes.Pop, 0), }); var Sequence2 = new PatchTargetInstructionSet(new List <PatchTargetInstruction> { new PatchTargetInstruction(OpCodes.Ldsfld), //continues immediately after the previous sequence new PatchTargetInstruction(OpCodes.Ldsfld, 0), new PatchTargetInstruction(OpCodes.Ldnull, 0), new PatchTargetInstruction(OpCodes.Ldc_I4_1, 0), new PatchTargetInstruction(OpCodes.Callvirt, TextConsole_DrawBuffer, 0) }); var Sequence3 = new PatchTargetInstructionSet(new List <PatchTargetInstruction> { new PatchTargetInstruction(IsStoreLocalInstruction), new PatchTargetInstruction(IsLoadLocalInstruction, 0), new PatchTargetInstruction(OpCodes.Ldc_I4_S, (object)98, 0) }); int seq = 1; bool patched = false; foreach (var instruction in instructions) { if (seq == 1) { if (Sequence1.IsMatchComplete(instruction)) { yield return(new CodeInstruction(OpCodes.Ldc_I4_S, 58)); yield return(new CodeInstruction(OpCodes.Ldc_I4_S, 23)); yield return(Sequence1.MatchedInstructions[2].Clone()); yield return(new CodeInstruction(OpCodes.Ldstr, "&Y[&WTab&y - Detailed Stats&Y]")); yield return(Sequence1.MatchedInstructions[6].Clone()); yield return(Sequence1.MatchedInstructions[7].Clone()); seq++; } } else if (seq == 2) { if (Sequence2.IsMatchComplete(instruction)) { seq++; } } else if (!patched && seq == 3) { if (Sequence3.IsMatchComplete(instruction)) { //here we are essentially adding: // if (keys == Keys.Tab) // { // EnhancedScoreboardExtender.ShowGameStatsScreen(); // Console.DrawBuffer(Buffer, null, bSkipIfOverlay: true); // } yield return(new CodeInstruction(OpCodes.Ldc_I4_S, 9)); //Keys.Tab Label newLabel = generator.DefineLabel(); yield return(new CodeInstruction(OpCodes.Bne_Un_S, newLabel)); yield return(new CodeInstruction(OpCodes.Call, EnhancedScoreboardExtender_ShowGameStatsScreen)); //redraw the buffer over the screen we made yield return(Sequence2.MatchedInstructions[0].Clone()); yield return(Sequence2.MatchedInstructions[1].Clone()); yield return(Sequence2.MatchedInstructions[2].Clone()); yield return(Sequence2.MatchedInstructions[3].Clone()); yield return(Sequence2.MatchedInstructions[4].Clone()); CodeInstruction markedLoadLocal = Sequence3.MatchedInstructions[1].Clone(); markedLoadLocal.labels.Add(newLabel); yield return(markedLoadLocal); patched = true; } } yield return(instruction); } if (patched) { PatchHelpers.LogPatchResult("Scores", "Patched successfully." /* Adds an option to open a detailed game stats menu from the High Scores console UI. */); } else { PatchHelpers.LogPatchResult("Scores", "Failed. This patch may not be compatible with the current game version. " + "The High Scores text UI won't have an option to open detailed stats."); } }
static IEnumerable <CodeInstruction> Transpiler_GenerateCharacter(IEnumerable <CodeInstruction> instructions, ILGenerator generator) { var Sequence1 = new PatchTargetInstructionSet(new List <PatchTargetInstruction> { new PatchTargetInstruction(OpCodes.Ldstr, "StartingPet"), new PatchTargetInstruction(OpCodes.Callvirt, List_GameObjectBlueprint_get_Count, 1), new PatchTargetInstruction(OpCodes.Ldsfld, CreateCharacter__Console, 35), new PatchTargetInstruction(OpCodes.Ldarg_0, 0), new PatchTargetInstruction(OpCodes.Ldnull, 0), new PatchTargetInstruction(OpCodes.Ldc_I4_0, 0), new PatchTargetInstruction(OpCodes.Callvirt, TextConsole_DrawBuffer, 0) }); var Sequence2 = new PatchTargetInstructionSet(new List <PatchTargetInstruction> { new PatchTargetInstruction(OpCodes.Ldc_I4_S, (object)84), new PatchTargetInstruction(OpCodes.Bne_Un_S, 0), new PatchTargetInstruction(OpCodes.Ldstr, "HEY! Try my Caves of Qud character build.\n", 0), new PatchTargetInstruction(IsLoadLocalInstruction, 5), new PatchTargetInstruction(OpCodes.Ldc_I4_S, (object)83) }); int seq = 1; bool patched = false; foreach (var instruction in instructions) { if (seq == 1) { if (Sequence1.IsMatchComplete(instruction)) { yield return(Sequence1.MatchedInstructions[3].Clone()); yield return(new CodeInstruction(OpCodes.Call, CreateCharacterExtender_WriteCharCreateSpriteOptionText)); seq++; } } else if (!patched && seq == 2) { if (Sequence2.IsMatchComplete(instruction)) { //here we are essentially adding: // if (keys == Keys.M) // { // CreateCharacterExtender.PickCharacterTile(); // _Console.DrawBuffer(SB); // } yield return(new CodeInstruction(OpCodes.Ldc_I4_S, 77)); //Keys.M Label newLabel = generator.DefineLabel(); yield return(new CodeInstruction(OpCodes.Bne_Un_S, newLabel)); yield return(new CodeInstruction(OpCodes.Ldsfld, CreateCharacter_Template)); yield return(new CodeInstruction(OpCodes.Call, CreateCharacterExtender_PickCharacterTile)); //redraw the buffer over the screen we made yield return(Sequence1.MatchedInstructions[2].Clone()); yield return(Sequence1.MatchedInstructions[3].Clone()); yield return(Sequence1.MatchedInstructions[4].Clone()); yield return(Sequence1.MatchedInstructions[5].Clone()); yield return(Sequence1.MatchedInstructions[6].Clone()); CodeInstruction markedLoadLocal = Sequence2.MatchedInstructions[3].Clone(); markedLoadLocal.labels.Add(newLabel); yield return(markedLoadLocal); patched = true; } } yield return(instruction); } if (patched) { PatchHelpers.LogPatchResult("GenerateCharacter", "Patched successfully." /* Adds a menu for choosing your character sprite during character creation. */); } else { PatchHelpers.LogPatchResult("GenerateCharacter", "Failed. This patch may not be compatible with the current game version. " + "The character sprite customization menu won't be available during character creation."); } }
static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { var Sequence1 = new PatchTargetInstructionSet(new List <PatchTargetInstruction> { new PatchTargetInstruction(OpCodes.Ldstr, "CmdWalk"), new PatchTargetInstruction(OpCodes.Ldstr, " | {{hotkey|", 8), new PatchTargetInstruction(OpCodes.Ldsfld, Look_Buffer, 30), new PatchTargetInstruction(OpCodes.Ldloc_S, 0), new PatchTargetInstruction(OpCodes.Ldloc_S, 1), new PatchTargetInstruction(OpCodes.Callvirt, ScreenBuffer_WriteAt, 1), new PatchTargetInstruction(OpCodes.Pop, 0), new PatchTargetInstruction(OpCodes.Ldloc_S, 0), new PatchTargetInstruction(OpCodes.Brfalse, 0), new PatchTargetInstruction(OpCodes.Ldloc_S, 0), new PatchTargetInstruction(OpCodes.Brfalse, 0) }); var Sequence2 = new PatchTargetInstructionSet(new List <PatchTargetInstruction> { new PatchTargetInstruction(OpCodes.Ldloc_S), new PatchTargetInstruction(OpCodes.Ldc_I4_S, (object)101, 0), new PatchTargetInstruction(OpCodes.Beq_S, 0), new PatchTargetInstruction(OpCodes.Ldloc_S, 0), new PatchTargetInstruction(OpCodes.Ldc_I4_S, (object)27, 0), new PatchTargetInstruction(OpCodes.Bne_Un_S, 0), new PatchTargetInstruction(OpCodes.Ldc_I4_1, 0), new PatchTargetInstruction(OpCodes.Stloc_1, 0), new PatchTargetInstruction(OpCodes.Ldloc_S, 0) }); int seq = 1; bool patched = false; foreach (var instruction in instructions) { if (seq == 1) { if (Sequence1.IsMatchComplete(instruction)) { yield return(instruction); yield return(Sequence1.MatchedInstructions[2].Clone()); //load ScreenBuffer yield return(Sequence1.MatchedInstructions[7].Clone()); //load target GameObject yield return(Sequence1.MatchedInstructions[4].Clone()); //load Look UI hotkey string yield return(new CodeInstruction(OpCodes.Call, LookExtender_AddMarkLegendaryOptionToLooker)); seq++; continue; } } else if (!patched) { if (Sequence2.IsMatchComplete(instruction)) { CodeInstruction replacementInstruction = instruction.Clone(); instruction.opcode = Sequence2.MatchedInstructions[0].opcode; instruction.operand = Sequence2.MatchedInstructions[0].operand; yield return(instruction); //load pressed key onto stack (with existing label) yield return(Sequence1.MatchedInstructions[7].Clone()); //load target GameObject yield return(new CodeInstruction(OpCodes.Ldloc_1)); //load flag on the stack yield return(new CodeInstruction(OpCodes.Call, LookExtender_CheckKeyPress)); //call our method, which puts a bool on stack yield return(new CodeInstruction(OpCodes.Stloc_1)); //store bool into flag yield return(replacementInstruction); //return original instruction (without label) patched = true; continue; } } yield return(instruction); } if (patched) { PatchHelpers.LogPatchResult("Look", "Patched successfully." /* Adds option to mark legendary creature locations in the journal from the Look UI. */); } else { PatchHelpers.LogPatchResult("Look", "Failed. This patch may not be compatible with the current game version. " + "The option to mark legendary creature locations in journal won't be available from the Look UI."); } }