static VEF_ReflectionData() { if (VEF_ModCompatibilityCheck.enabled_rooloDualWield) { MB_TryGetOffHandEquipment = AccessTools.Method(type: GenTypes.GetTypeInAnyAssemblyNew("DualWield.Ext_Pawn_EquipmentTracker", "DualWield"), name: "TryGetOffHandEquipment"); } }
static HarmonyPatches() { //HarmonyInstance.DEBUG = true; RenameEverything.HarmonyInstance.PatchAll(); // RPG Style Inventory if (ModCompatibilityCheck.RPGStyleInventory) { // Apply the same transpiler used on ITab_Pawn_Gear.DrawThingRow to RPG_GearTab's DrawThingRow var rpgGearTab = GenTypes.GetTypeInAnyAssemblyNew("Sandy_Detailed_RPG_Inventory.Sandy_Detailed_RPG_GearTab", "Sandy_Detailed_RPG_Inventory"); if (rpgGearTab != null) { RenameEverything.HarmonyInstance.Patch(AccessTools.Method(rpgGearTab, "DrawThingRow"), transpiler: new HarmonyMethod(typeof(Patch_ITab_Pawn_Gear.Patch_DrawThingRow), "Transpiler")); } else { Log.Error("Could not find type Sandy_Detailed_RPG_Inventory.Sandy_Detailed_RPG_GearTab in RPG Style Inventory"); } } // Infused if (ModCompatibilityCheck.Infused) { var infusedThingLabelPatch = GenTypes.GetTypeInAnyAssemblyNew("Infused.GenMapUI_DrawThingLabel_Patch", "Infused"); if (infusedThingLabelPatch != null) { RenameEverything.HarmonyInstance.Patch(AccessTools.Method(infusedThingLabelPatch, "Postfix"), transpiler: new HarmonyMethod(typeof(Patch_Infused_GenMapUI_DrawThingLabel_Patch.ManualPatch_Postfix), "Transpiler")); } else { Log.Error("Could not find type Infused.GenMapUI_DrawThingLabel_Patch in Infused"); } } }
static HarmonyPatches() { HarmonyInstance h = HarmonyInstance.Create("XeoNovaDan.SurvivalTools"); //HarmonyInstance.DEBUG = true; // Automatic patches h.PatchAll(Assembly.GetExecutingAssembly()); // Manual patches // Plants that obstruct construction zones var postfixHandleBlockingThingJob = new HarmonyMethod(patchType, nameof(Postfix_HandleBlockingThingJob)); h.Patch(AccessTools.Method(typeof(GenConstruct), nameof(GenConstruct.HandleBlockingThingJob)), postfix: postfixHandleBlockingThingJob); h.Patch(AccessTools.Method(typeof(RoofUtility), nameof(RoofUtility.HandleBlockingThingJob)), postfix: postfixHandleBlockingThingJob); // Mining JobDriver - ResetTicksToPickHit var transpileResetTicksToPickHit = new HarmonyMethod(patchType, nameof(Transpile_JobDriver_Mine_ResetTicksToPickHit)); h.Patch(AccessTools.Method(typeof(JobDriver_Mine), "ResetTicksToPickHit"), transpiler: transpileResetTicksToPickHit); // Thanks Mehni! if (!ModCompatibilityCheck.OtherInventoryModsActive) { h.Patch(AccessTools.Method(typeof(FloatMenuMakerMap), "AddHumanlikeOrders"), transpiler: new HarmonyMethod(patchType, nameof(Transpile_FloatMenuMakerMad_AddHumanlikeOrders))); } // erdelf never fails to impress :) #region JobDriver Boilerplate h.Patch(typeof(RimWorld.JobDriver_PlantWork).GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Instance).First(). GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Instance).First().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance). MaxBy(mi => mi.GetMethodBody()?.GetILAsByteArray().Length ?? -1), transpiler: new HarmonyMethod(patchType, nameof(Transpile_JobDriver_PlantWork_MakeNewToils))); var transpileMineMakeNewToils = new HarmonyMethod(patchType, nameof(Transpile_JobDriver_Mine_MakeNewToils)); h.Patch(typeof(JobDriver_Mine).GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Instance).First(). GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Instance).First().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance). MaxBy(mi => mi.GetMethodBody()?.GetILAsByteArray().Length ?? -1), transpiler: transpileMineMakeNewToils); h.Patch(typeof(JobDriver_ConstructFinishFrame).GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Instance).First(). GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Instance).First().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance). MaxBy(mi => mi.GetMethodBody()?.GetILAsByteArray().Length ?? -1), transpiler: new HarmonyMethod(patchType, nameof(Transpile_JobDriver_ConstructFinishFrame_MakeNewToils))); h.Patch(typeof(JobDriver_Repair).GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Instance).First(). GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Instance).First().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance). MaxBy(mi => mi.GetMethodBody()?.GetILAsByteArray().Length ?? -1), transpiler: new HarmonyMethod(patchType, nameof(Transpile_JobDriver_Repair_MakeNewToils))); h.Patch(AccessTools.Method(typeof(JobDriver_Deconstruct), "TickAction"), new HarmonyMethod(patchType, nameof(Prefix_JobDriver_Deconstruct_TickAction))); h.Patch(typeof(JobDriver_AffectRoof).GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Instance).First(). GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Instance).First().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance). MaxBy(mi => mi.GetMethodBody()?.GetILAsByteArray().Length ?? -1), transpiler: new HarmonyMethod(patchType, nameof(Transpile_JobDriver_AffectRoof_MakeNewToils))); #endregion // Fluffy Breakdowns if (ModCompatibilityCheck.FluffyBreakdowns) { var maintenanceDriver = GenTypes.GetTypeInAnyAssemblyNew("Fluffy_Breakdowns.JobDriver_Maintenance", null); if (maintenanceDriver != null && typeof(JobDriver).IsAssignableFrom(maintenanceDriver)) { h.Patch(maintenanceDriver.GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Instance).MinBy(x => x.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).Count()) .GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).MaxBy(mi => mi.GetMethodBody()?.GetILAsByteArray().Length ?? -1), transpiler: new HarmonyMethod(patchType, nameof(Transpile_JobDriver_Maintenance_MakeNewToils))); } else { Log.Error("Survival Tools - Could not find Fluffy_Breakdowns.JobDriver_Maintenance type to patch"); } } // Quarry if (ModCompatibilityCheck.Quarry) { var quarryDriver = GenTypes.GetTypeInAnyAssemblyNew("Quarry.JobDriver_MineQuarry", null); if (quarryDriver != null && typeof(JobDriver).IsAssignableFrom(quarryDriver)) { h.Patch(AccessTools.Method(quarryDriver, "Mine"), postfix: new HarmonyMethod(patchType, nameof(Postfix_JobDriver_MineQuarry_Mine))); h.Patch(AccessTools.Method(quarryDriver, "ResetTicksToPickHit"), transpiler: new HarmonyMethod(patchType, nameof(Transpile_JobDriver_MineQuarry_ResetTicksToPickHit))); } else { Log.Error("Survival Tools - Could not find Quarry.JobDriver_MineQuarry type to patch"); } } // Turret Extensions if (ModCompatibilityCheck.TurretExtensions) { var turretExtensionsDriver = GenTypes.GetTypeInAnyAssemblyNew("TurretExtensions.JobDriver_UpgradeTurret", null); if (turretExtensionsDriver != null && typeof(JobDriver).IsAssignableFrom(turretExtensionsDriver)) { h.Patch(AccessTools.Method(turretExtensionsDriver, "Upgrade"), postfix: new HarmonyMethod(patchType, nameof(Postfix_JobDriver_UpgradeTurret_Upgrade))); } else { Log.Error("Survival Tools - Could not find TurretExtensions.JobDriver_UpgradeTurret type to patch"); } } // Combat Extended if (ModCompatibilityCheck.CombatExtended) { // Prevent tools from incorrectly being removed based on loadout var combatExtendedHoldTrackerExcessThingClass = GenTypes.GetTypeInAnyAssemblyNew("CombatExtended.Utility_HoldTracker", null); if (combatExtendedHoldTrackerExcessThingClass != null) { h.Patch(AccessTools.Method(combatExtendedHoldTrackerExcessThingClass, "GetExcessThing"), postfix: new HarmonyMethod(patchType, nameof(Postfix_CombatExtended_Utility_HoldTracker_GetExcessThing))); } else { Log.Error("Survival Tools - Could not find CombatExtended.Utility_HoldTracker type to patch"); } // Prevent pawns from picking up excess tools with Combat Extended's CompInventory var combatExtendedCompInventory = GenTypes.GetTypeInAnyAssemblyNew("CombatExtended.CompInventory", null); if (combatExtendedCompInventory != null) { h.Patch(AccessTools.Method(combatExtendedCompInventory, "CanFitInInventory"), postfix: new HarmonyMethod(patchType, nameof(Postfix_CombatExtended_CompInventory_CanFitInInventory))); } else { Log.Error("Survival Tools - Could not find CombatExtended.CompInventory type to patch"); } } // Prison Labor if (ModCompatibilityCheck.PrisonLabor) { // Fix pickaxe degradation and use correct mining speed stat var prisonLabourMineJobDriver = GenTypes.GetTypeInAnyAssemblyNew("PrisonLabor.JobDriver_Mine_Tweak", null); if (prisonLabourMineJobDriver != null) { h.Patch(AccessTools.Method(prisonLabourMineJobDriver, "ResetTicksToPickHit"), transpiler: transpileResetTicksToPickHit); h.Patch(prisonLabourMineJobDriver.GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Instance).Last() .GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).MaxBy(mi => mi.GetMethodBody()?.GetILAsByteArray().Length ?? -1), transpiler: transpileMineMakeNewToils); } } }
static HarmonyPatches() { // Harmony Setup and Debug Log.Message("VEF :: Performing Hamrony Patches"); HarmonyInstance.DEBUG = false; HarmonyInstance harmony = HarmonyInstance.Create(id: "com.framework.expansion.verb"); // Harmony Patches required for Core operation. harmony.Patch(original: AccessTools.Method(type: typeof(Alert_BrawlerHasRangedWeapon), name: nameof(Alert_BrawlerHasRangedWeapon.GetReport)), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(Alert_BrawlerHasRangedWeapon_GetReportPostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(AttackTargetsCache), name: nameof(AttackTargetsCache.GetPotentialTargetsFor)), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(AttackTargetsCache_GetPotentialTargetsForPostfix))); harmony.Patch(original: AccessTools.Constructor(type: typeof(BattleLogEntry_RangedFire), parameters: new Type[] { typeof(Thing), typeof(Thing), typeof(ThingDef), typeof(ThingDef), typeof(bool) }), prefix: new HarmonyMethod(type: patchType, name: nameof(BattleLogEntry_WeaponDefGrammarPrefix)), postfix: null); harmony.Patch(original: AccessTools.Constructor(type: typeof(BattleLogEntry_RangedImpact), parameters: new Type[] { typeof(Thing), typeof(Thing), typeof(Thing), typeof(ThingDef), typeof(ThingDef), typeof(ThingDef) }), prefix: new HarmonyMethod(type: patchType, name: nameof(BattleLogEntry_WeaponDefGrammarPrefix)), postfix: null); harmony.Patch(original: AccessTools.Method(type: typeof(Command_VerbTarget), name: nameof(Command_VerbTarget.ProcessInput)), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(Command_VerbTarget_ProcessInputPostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(Command_VerbTarget), name: nameof(Command_VerbTarget.GizmoUpdateOnMouseover)), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(Command_VerbTarget_GizmoUpdateOnMousoverPostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(Explosion), name: "AffectCell"), prefix: new HarmonyMethod(type: patchType, name: nameof(Explsoion_AffectCellPrefix)), postfix: null); harmony.Patch(original: AccessTools.Method(type: typeof(FloatMenuUtility), name: nameof(FloatMenuUtility.GetAttackAction)), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(FloatMenuUtility_GetAttackActionPostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(HealthCardUtility), name: "GenerateSurgeryOption"), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(HealthCardUtility_GenerateSurgeryOptionPostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(HediffSet), name: "CalculateBleedRate"), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(HediffSet_CalculateBleedRatePostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(JobDriver_Wait), name: "CheckForAutoAttack"), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(JobDriver_Wait_CheckForAutoAttackPostfix))); harmony.Patch(original: AccessTools.Property(type: typeof(Pawn), name: nameof(Pawn.HealthScale)).GetGetMethod(true), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(Pawn_GetHealthScalePostfix))); if (!VEF_ModCompatibilityCheck.enabled_CombatExtended) { harmony.Patch(original: AccessTools.Method(type: typeof(Pawn), name: nameof(Pawn.TryGetAttackVerb)), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(Pawn_TryGetAttackVerbPostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(PawnAttackGizmoUtility), name: "GetSquadAttackGizmo"), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(PawnAttackGizmoUtility_GetSquadAttackGizmoPostfix))); } harmony.Patch(original: VEF_ReflectionData.MB_Pawn_DraftController_GetGizmo(), prefix: null, postfix: null, transpiler: new HarmonyMethod(type: patchType, name: nameof(Pawn_DraftController_GetGizmosTranspiler))); harmony.Patch(original: AccessTools.Method(type: typeof(Pawn_HealthTracker), name: nameof(Pawn_HealthTracker.PreApplyDamage)), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(Pawn_HealthTracker_PreApplyDamagePostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(SmokepopBelt), name: nameof(SmokepopBelt.CheckPreAbsorbDamage)), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(SmokepopBelt_CheckPreAbsorbDamagePostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(Targeter), name: "GetTargetingVerb"), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(Targeter_GetTargetingVerbPostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(Targeter), name: nameof(Targeter.TargeterUpdate)), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(Targeter_TargeterUpdatePostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(ThoughtWorker_IsCarryingRangedWeapon), name: "CurrentStateInternal"), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(ThoughtWorker_IsCarryingRangedWeapon_CurrentStateInternalPostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(Verb_ShootOneUse), name: "SelfConsume"), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(Verb_ShootOneUse_SelfConsumePostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(Verb_Spawn), name: "TryCastShot"), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(Verb_Spawn_TryCastShotPostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(VerbProperties), name: nameof(VerbProperties.GetDamageFactorFor), parameters: new Type[] { typeof(Tool), typeof(Pawn), typeof(HediffComp_VerbGiver) }), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(VerbProperties_GetDamageFactorForPostfix)), transpiler: new HarmonyMethod(type: patchType, name: nameof(VerbProperties_GetDamageFactorForTranspiler))); harmony.Patch(original: AccessTools.Method(type: typeof(VerbUtility), name: nameof(VerbUtility.AllowAdjacentShot)), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(VerbUtility_AllowAdjacentShotPostfix))); // UpdateHediffSetPostfix (instrcucts HediffSets on pawn to update when a hediff changed) harmony.Patch(original: AccessTools.Method(type: typeof(HediffSet), name: nameof(HediffSet.DirtyCache)), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(UpdateHediffSetPostfix))); // UpdateRangedVerbPostfix (forces update to ranged verbs when a change to a possible verb source is detected) harmony.Patch(original: AccessTools.Method(type: typeof(HediffSet), name: nameof(HediffSet.DirtyCache)), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(UpdateRangedVerbsPostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(Pawn_EquipmentTracker), name: nameof(Pawn_EquipmentTracker.Notify_EquipmentAdded)), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(UpdateRangedVerbsPostfix))); harmony.Patch(original: AccessTools.Method(type: typeof(Pawn_EquipmentTracker), name: nameof(Pawn_EquipmentTracker.Notify_EquipmentRemoved)), prefix: null, postfix: new HarmonyMethod(type: patchType, name: nameof(UpdateRangedVerbsPostfix))); // Harmony Patches for Mod Compatibility // Dual Wield if (VEF_ModCompatibilityCheck.enabled_rooloDualWield) { try { ((Action)(() => { harmony.Patch(original: AccessTools.Method(type: typeof(DualWield.Ext_Verb), name: nameof(DualWield.Ext_Verb.OffhandTryStartCastOn)), prefix: new HarmonyMethod(type: patchType, name: nameof(DualWield_Ext_Verb_OffhandTryStartCastOn)), postfix: null); }))(); } catch (TypeLoadException ex) { } } // Range Animal Framework if (VEF_ModCompatibilityCheck.enabled_RangeAnimalFramework) { try { ((Action)(() => { harmony.Patch(original: AccessTools.Method(type: GenTypes.GetTypeInAnyAssemblyNew("AnimalRangeAttack.ARA_FightAI_Patch", "AnimalRangeAttack"), name: "Prefix"), prefix: null, postfix: null, transpiler: new HarmonyMethod(type: patchType, name: nameof(PrefixSlayerTranspiler))); harmony.Patch(original: AccessTools.Method(type: GenTypes.GetTypeInAnyAssemblyNew("AnimalRangeAttack.ARA__ManHunter_Patch", "AnimalRangeAttack"), name: "Prefix"), prefix: null, postfix: null, transpiler: new HarmonyMethod(type: patchType, name: nameof(PrefixSlayerTranspiler))); harmony.Patch(original: AccessTools.Method(type: GenTypes.GetTypeInAnyAssemblyNew("AnimalRangeAttack.ARA__VerbCheck_Patch", "AnimalRangeAttack"), name: "Prefix"), prefix: null, postfix: null, transpiler: new HarmonyMethod(type: patchType, name: nameof(PrefixSlayerTranspiler))); }))(); } catch (TypeLoadException ex) { } } }
static VEF_ModCompatibilityCheck() { if (ModsConfig.ActiveModsInLoadOrder.Any(m => m.Name == "Range Animal Framework") || GenTypes.GetTypeInAnyAssemblyNew("AnimalRangeAttack.AnimalRangeAttack_Init", "AnimalRangeAttack") != null) { enabled_RangeAnimalFramework = true; } if (ModsConfig.ActiveModsInLoadOrder.Any(m => m.Name == "Smokepop Defense Framework") || GenTypes.GetTypeInAnyAssemblyNew("SmokepopCompFramework.SCF_Harmony", "SmokepopCompFramework") != null) { enabled_SmokepopDefenseFramework = true; } if (ModsConfig.ActiveModsInLoadOrder.Any(m => m.Name == "Variable Health Framework") || GenTypes.GetTypeInAnyAssemblyNew("VariableHealthFramework.VHF_Harmony", "VariableHealthFramework") != null) { enabled_VariableHealthFramework = true; } }
static ReflectedMethods() { // Convert DualWield.Ext_Pawn_EquipmentTracker.TryGetOffHandEquipment to a delegate if (ModCompatibilityCheck.DualWield) { TryGetOffHandEquipment = (FuncOut <Pawn_EquipmentTracker, ThingWithComps, bool>)Delegate.CreateDelegate(typeof(FuncOut <Pawn_EquipmentTracker, ThingWithComps, bool>), AccessTools.Method(GenTypes.GetTypeInAnyAssemblyNew("DualWield.Ext_Pawn_EquipmentTracker", "DualWield"), "TryGetOffHandEquipment")); } }