public VEE(ModContentPack mod) { var methodsForAll = new[] { "VEE.DummySpaceBattle:Tick", "VEE.HeddifComp_MightJoin:CompPostTick", "VEE.Shuttle:Tick", // These 4 methods initialize System.Random, but don't use them in any way whatsoever. //"VEE.PurpleEvents.GlobalWarming:ChangeBiomes", //"VEE.PurpleEvents.GlobalWarming:ChangeTileTemp", //"VEE.PurpleEvents.IceAge:ChangeBiomes", //"VEE.PurpleEvents.IceAge:ChangeTileTemp", "VEE.PurpleEvents.PsychicBloom:Init", "VEE.RegularEvents.ApparelPod:TryExecuteWorker", "VEE.RegularEvents.CaravanAnimalWI:GenerateGroup", "VEE.RegularEvents.Drought:HarmPlant", "VEE.RegularEvents.HuntingParty:TryExecuteWorker", "VEE.RegularEvents.MeteoriteShower:TryExecuteWorker", "VEE.RegularEvents.SpaceBattle:GameConditionTick", // This method was having issues with transpiling no matter what I did, skipping it until it can be fixed "VEE.RegularEvents.WeaponPod:TryExecuteWorker", }; PatchingUtilities.PatchSystemRand(methodsForAll, false); // This method only calls other methods that use RNG calls PatchingUtilities.PatchPushPopRand("VEE.RegularEvents.EarthQuake:TryExecuteWorker"); // Only patch System.Random out, as this methods is only called by other ones PatchingUtilities.PatchSystemRand("VEE.RegularEvents.EarthQuake:DamageInRadius", false); }
public VanillaIdeologyMemes(ModContentPack mod) { // RNG { var methods = new[] { // Commented out the ones that use seeded random, as they should be fine // If not, then uncommenting those lines should fix it "VanillaMemesExpanded.CompAbilityHarvestBodyParts:Apply", //"VanillaMemesExpanded.VanillaMemesExpanded_GameConditionManager_RegisterCondition_Patch:SendRandomMood", //"VanillaMemesExpanded.VanillaMemesExpanded_GameCondition_Aurora_Init_Patch:SendRandomMood", //"VanillaMemesExpanded.RitualOutcomeEffectWorker_DivineStars:Apply", "VanillaMemesExpanded.RitualOutcomeEffectWorker_SlaveEmancipation:Apply", "VanillaMemesExpanded.RitualOutcomeEffectWorker_ViolentConversion:Apply", }; PatchingUtilities.PatchSystemRand(methods, false); } // Gizmos { var type = AccessTools.TypeByName("VanillaMemesExpanded.CompDeconstructJunk"); MP.RegisterSyncMethod(type, "SetObjectForDeconstruction"); MP.RegisterSyncMethod(type, "CancelObjectForDeconstruction"); } }
public VEE(ModContentPack mod) { var methodsForAll = new[] { "VEE.HeddifComp_MightJoin:CompPostTick", "VEE.HuntingParty:TryExecuteWorker", // These 4 methods initialize System.Random, but don't use them in any way whatsoever. //"VEE.PurpleEvents.GlobalWarming:ChangeBiomes", //"VEE.PurpleEvents.GlobalWarming:ChangeTileTemp", //"VEE.PurpleEvents.IceAge:ChangeBiomes", //"VEE.PurpleEvents.IceAge:ChangeTileTemp", "VEE.PurpleEvents.PsychicBloom:Init", "VEE.RegularEvents.ApparelPod:TryExecuteWorker", "VEE.RegularEvents.CaravanAnimalWI:GenerateGroup", "VEE.RegularEvents.MeteoriteShower:TryExecuteWorker", "VEE.RegularEvents.WeaponPod:TryExecuteWorker", }; PatchingUtilities.PatchSystemRand(methodsForAll, false); // This method only calls other methods that use RNG calls PatchingUtilities.PatchPushPopRand("VEE.RegularEvents.EarthQuake:TryExecuteWorker"); // Only patch System.Random out, as this methods is only called by other ones PatchingUtilities.PatchSystemRand("VEE.RegularEvents.EarthQuake:DamageInRadius", false); // Unity RNG PatchingUtilities.PatchUnityRand("VEE.Shuttle:Tick"); LongEventHandler.ExecuteWhenFinished(LatePatch); }
public AlphaBehavioursAndEvents(ModContentPack mod) { //RNG Fix { var rngFixConstructors = new[] { "AlphaBehavioursAndEvents.CompAnimalProduct", "AlphaBehavioursAndEvents.CompExploder", "AlphaBehavioursAndEvents.CompGasProducer", "AlphaBehavioursAndEvents.CompInitialHediff", "AlphaBehavioursAndEvents.Gas_Ocular", "AlphaBehavioursAndEvents.Hediff_Crushing", //"NewAlphaAnimalSubproducts.CompAnimalProduct ", // System.Random initialized, but not used }; PatchingUtilities.PatchSystemRandCtor(rngFixConstructors, false); var rngFixMethods = new[] //System.Random fixes { "AlphaBehavioursAndEvents.CompGasProducer:CompTick", "AlphaBehavioursAndEvents.CompAnimalProduct:InformGathered", "AlphaBehavioursAndEvents.CompInitialHediff:CompTickRare", "AlphaBehavioursAndEvents.Gas_Ocular:Tick", "AlphaBehavioursAndEvents.Hediff_Crushing:RandomFilthGenerator", "AlphaBehavioursAndEvents.CompExploder:wickInitializer", }; PatchingUtilities.PatchPushPopRand(rngFixMethods); PatchingUtilities.PatchSystemRand("AlphaBehavioursAndEvents.DamageWorker_ExtraInfecter:ApplySpecialEffectsToPart"); } }
public AlphaMemes(ModContentPack mod) { PatchingUtilities.PatchSystemRand("AlphaMemes.AlphaMemes_DamageWorker_AddInjury_Apply_Patch:SendHistoryIfMelee", false); // The following method is seeded, so it should be fine // If not, then patching it as well should fix it //"AlphaMemes.GameComponent_RandomMood:GameComponentTick", }
public RunandGun(ModContentPack mod) { Type type = AccessTools.TypeByName("RunAndGun.Harmony.Pawn_DraftController_GetGizmos_Patch"); MP.RegisterSyncDelegate(type, "<>c__DisplayClass0_0", "<Postfix>b__1"); PatchingUtilities.PatchSystemRand("RunAndGun.Harmony.MentalStateHandler_TryStartMentalState:shouldRunAndGun", false); }
public VanillaPlantsMorePlants(ModContentPack mod) { PatchingUtilities.PatchSystemRand("VanillaPlantsExpandedMorePlants.Plant_SowsAdjacent:SpawnSetup", false); PatchingUtilities.PatchSystemRand("VanillaPlantsExpandedMorePlants.Plant_TransformOnMaturity:TickLong", false); MpCompat.RegisterLambdaMethod("VanillaPlantsExpandedMorePlants.Zone_GrowingAquatic", "GetGizmos", 1, 3); MpCompat.RegisterLambdaMethod("VanillaPlantsExpandedMorePlants.Zone_GrowingSandy", "GetGizmos", 1, 3); }
public WitcherMonsterHunt(ModContentPack mod) { var methods = new[] { "WMHAnimalBehaviours.DamageWorker_ExtraInfecter:ApplySpecialEffectsToPart", "WMHAnimalBehaviours.IncidentWorker_MonsterEncounter:TryExecuteWorker", }; PatchingUtilities.PatchSystemRand(methods, false); }
public VanillaFactionsVikings(ModContentPack mod) { LongEventHandler.ExecuteWhenFinished(LatePatch); // Debug stuff var type = AccessTools.TypeByName("VFEV.Apiary"); MpCompat.RegisterSyncMethodsByIndex(type, "<GetGizmos>", 0, 1).Do(m => m.SetDebugOnly()); // This method seems unused... But I guess it's better to be safe than sorry. PatchingUtilities.PatchSystemRand(AccessTools.Method(type, "ResetTend"), false); }
public VanillaFurnitureExpanded(ModContentPack mod) { var methods = new[] { "AOMoreFurniture.JobDriver_PlayComputerIndustrial:WatchTickAction", "AOMoreFurniture.JobDriver_PlayComputerModern:WatchTickAction", "AOMoreFurniture.JobDriver_PlayArcadeSounds:WatchTickAction", "AOMoreFurniture.JobDriver_PlayPunchingBag:WatchTickAction", }; PatchingUtilities.PatchSystemRand(methods, false); }
public WhatTheHack(ModContentPack mod) { var methods = new[] { AccessTools.Method(AccessTools.TypeByName("WhatTheHack.Harmony.IncidentWorker_Raid_TryExecuteWorker"), "SpawnHackedMechanoids"), AccessTools.Method(AccessTools.TypeByName("WhatTheHack.Harmony.Pawn_JobTracker_DetermineNextJob"), "HackedPoorlyEvent"), AccessTools.Method(AccessTools.TypeByName("WhatTheHack.Harmony.Thing_ButcherProducts"), "GenerateExtraButcherProducts"), AccessTools.Method(AccessTools.TypeByName("WhatTheHack.Needs.Need_Maintenance"), "MaybeUnhackMechanoid"), AccessTools.Method(AccessTools.TypeByName("WhatTheHack.Recipes.Recipe_Hacking"), "CheckHackingFail"), }; PatchingUtilities.PatchSystemRand(methods, false); }
public FertileFieldsCompat(ModContentPack mod) { { // RNG PatchingUtilities.PatchSystemRand("RFF_Code.Building_CompostBin:PlaceProduct"); } Type type = GrowZoneManagerType = AccessTools.TypeByName("RFF_Code.GrowZoneManager"); MP.RegisterSyncMethod(type, "ToggleReturnToSoil"); MP.RegisterSyncMethod(type, "ToggleDesignateReplacements"); MP.RegisterSyncWorker <MapComponent>(SyncWorkerForGrowZoneManager, type); }
public AlphaBehavioursAndEvents(ModContentPack mod) { //RNG Fix { var rngFixMethods = new[] { //System.Random fixes "AlphaBehavioursAndEvents.CompGasProducer:CompTick", "AlphaBehavioursAndEvents.CompAnimalProduct:InformGathered", "AlphaBehavioursAndEvents.CompInitialHediff:CompTickRare", "AlphaBehavioursAndEvents.Gas_Ocular:Tick", "AlphaBehavioursAndEvents.Hediff_Crushing:RandomFilthGenerator", }; PatchingUtilities.PatchSystemRand(rngFixMethods); } }
private static void LatePatch() { var types = new[] { "VSEWW.MapComponent_Winston:SetNextNormalRaidInfo", "VSEWW.MapComponent_Winston:SetNextBossRaidInfo", "VSEWW.NextRaidInfo:WavePawns", "VSEWW.NextRaidInfo:ChooseAndApplyModifier", }; PatchingUtilities.PatchSystemRand(types, false); var type = AccessTools.TypeByName("VSEWW.MapComponent_Winston"); MP.RegisterSyncMethod(type, "ExecuteRaid"); }
public VanillaFactionsVikings(ModContentPack mod) { LongEventHandler.ExecuteWhenFinished(LatePatch); // Debug commands, other stuff var type = AccessTools.TypeByName("VFEV.Building_MeadBarrel"); MpCompat.RegisterSyncMethodByIndex(type, "<GetGizmos>", 0).SetDebugOnly(); type = AccessTools.TypeByName("VFEV.Apiary"); foreach (var gizmo in MpCompat.RegisterSyncMethodsByIndex(type, "<GetGizmos>", 0, 1)) { gizmo.SetDebugOnly(); } // This method seems unused... But I guess it's better to be safe than sorry. PatchingUtilities.PatchSystemRand(AccessTools.Method(type, "ResetTend"), false); }
public AlphaBiomes(ModContentPack mod) { var type = AccessTools.TypeByName("AlphaBiomes.Command_SetStoneType"); buildingField = AccessTools.FieldRefAccess <Building>(type, "building"); // SyncWorker needed as the <ProcessInput> methods require syncing of the `building` field MP.RegisterSyncWorker <Command>(SyncSetStoneType, type, shouldConstruct: true); MpCompat.RegisterLambdaMethod(type, "ProcessInput", Enumerable.Range(0, 6).ToArray()); var rngFixMethods = new[] { "AlphaBiomes.CompGasProducer:CompTick", "AlphaBiomes.TarSprayer:SteamSprayerTick", "AlphaBiomes.GameCondition_AcidRain:DoCellSteadyEffects", }; PatchingUtilities.PatchSystemRand(AccessTools.Constructor(AccessTools.TypeByName("AlphaBiomes.CompGasProducer")), false); PatchingUtilities.PatchPushPopRand(rngFixMethods); }
public VanillaFishingExpanded(ModContentPack mod) { // RNG fix { PatchingUtilities.PatchSystemRand(AccessTools.Method("VCE_Fishing.JobDriver_Fish:SelectFishToCatch")); } // Gizmo (select fish size to catch) { commandType = AccessTools.TypeByName("VCE_Fishing.Command_SetFishList"); mapField = AccessTools.Field(commandType, "map"); fishingZoneField = AccessTools.Field(commandType, "zone"); MP.RegisterSyncMethod(commandType, "<ProcessInput>b__4_0"); MP.RegisterSyncMethod(commandType, "<ProcessInput>b__4_1"); MP.RegisterSyncMethod(commandType, "<ProcessInput>b__4_2"); MP.RegisterSyncWorker <Command>(SyncFishingZoneChange, commandType, shouldConstruct: false); } }
public MoreArchotechGarbage(ModContentPack mod) { // RNG Fix { var rngTypes = new[] { "RimWorld.CompSpawnerH", "RimWorld.CompSpawnerResearch", "RimWorld.CompSpawnerResearchMK2", "RimWorld.JoinOrRaidTameOrManhunter", "RimWorld.MechhSummon", "RimWorld.MechhSummonNoRoyalty", }; foreach (var type in rngTypes) { PatchingUtilities.PatchSystemRand($"{type}:RandomNumber"); } } // Gizmo Fix { // Mech cluster (0), raid (2), ship part (4) var type = AccessTools.TypeByName("RimWorld.MechhSummon"); MpCompat.RegisterLambdaDelegate(type, "GetGizmos", Array.Empty <string>(), 0, 2); MpCompat.RegisterLambdaMethod(type, "GetGizmos", 4); // Raid (0), ship part (2) type = AccessTools.TypeByName("RimWorld.MechhSummonNoRoyalty"); MpCompat.RegisterLambdaDelegate(type, "GetGizmos", Array.Empty <string>(), 0); MpCompat.RegisterLambdaMethod(type, "GetGizmos", 2); // Summon meteorite MpCompat.RegisterLambdaDelegate("RimWorld.PodSummoner", "GetGizmos", Array.Empty <string>(), 0); // Dev mode gizmos MpCompat.RegisterLambdaMethod("RimWorld.CompSpawnerH", "CompGetGizmosExtra", 0).SetDebugOnly(); MpCompat.RegisterLambdaMethod("RimWorld.CompSpawnerResearch", "CompGetGizmosExtra", 0).SetDebugOnly(); MpCompat.RegisterLambdaMethod("RimWorld.CompSpawnerResearchMK2", "CompGetGizmosExtra", 0).SetDebugOnly(); } }
public VanillaAnimalsCaves(ModContentPack mod) { // RNG { var methods = new[] { "VAECaves.Building_SpiderEggs:Tick", "VAECaves.DamageWorker_TwoArmSlam:Apply", "VAECaves.IncidentWorker_Hulk:CanFireNowSub", "VAECaves.JobDriver_CreateEggs:<MakeNewToils>b__1_0", }; PatchingUtilities.PatchSystemRand(methods, false); PatchingUtilities.PatchSystemRandCtor("VAECaves.Hediff_WallBreaker", false); } // Gizmos { MpCompat.RegisterLambdaMethod("VAECaves.Building_Cocoon", "GetGizmos", 0); MpCompat.RegisterLambdaMethod("VAECaves.CompConditionalSpawner", "CompGetGizmosExtra", 0).SetDebugOnly(); } }
public EccentricTechFusionPower(ModContentPack mod) { // RNG { var type = AccessTools.TypeByName("EccentricPower.CompFusionGenerator"); PatchingUtilities.PatchSystemRand(AccessTools.Method(type, "generateNewFailurePoints"), false); PatchingUtilities.PatchSystemRand(AccessTools.Method(type, "doEmergencyVentFireDamage"), true); } // Gizmos { var type = AccessTools.TypeByName("EccentricPower.CompFusionGenerator"); MP.RegisterSyncMethod(type, "SetDesiredOutputLevel"); MP.RegisterSyncMethod(type, "setPowerMode"); MP.RegisterSyncMethod(type, "StartIgnitionCycle"); MP.RegisterSyncMethod(type, "StartShutdownCycle"); MP.RegisterSyncMethod(type, "StartEmergencyVent"); MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", Enumerable.Range(3, 5).ToArray()).SetDebugOnly(); // 3 to 7 } LongEventHandler.ExecuteWhenFinished(LatePatch); }
public VanillaFactionsInsectoid(ModContentPack mod) { // Gizmos { // These two methods aren't patched, but supposedly the teleporter isn't included in the mod right now due to being bugged // Working on them could be problematic, as it seems that they reimplement (or at least used to reimplement) vanilla caravan forming screen completely from scratch // VFEI.Comps.ItemComps.CompArchotechTeleporter // VFEI.Comps.ItemComps.CompCustomTransporter var type = AccessTools.TypeByName("InsectoidBioengineering.Building_BioengineeringIncubator"); MpCompat.RegisterSyncMethodsByIndex(type, "<GetGizmos>", 0, 1, 2, 3); // Keep an eye on this in the future, seems like something the devs might combine into a single class at some point foreach (var geneNumber in new[] { "First", "Second", "Third" }) { type = AccessTools.TypeByName($"InsectoidBioengineering.Command_Set{geneNumber}GenomeList"); MP.RegisterSyncWorker <Command>(SyncSetGenomeCommand, type, shouldConstruct: true); MP.RegisterSyncMethod(AccessTools.Method(type, $"TryInsert{geneNumber}Genome")); } } // RNG { var constructors = new[] { "InsectoidBioengineering.Building_BioengineeringIncubator", //"VFEI.CompFilthProducer", }; PatchingUtilities.PatchSystemRandCtor(constructors, false); var methods = new[] { "VFEI.CompTargetEffect_Tame:RandomNumber", }; PatchingUtilities.PatchSystemRand(methods); } }
public VanillaExpandedFramework(ModContentPack mod) { // ItemProcessor { var type = AccessTools.TypeByName("ItemProcessor.Building_ItemProcessor"); // _1, _5 and _7 are used to check if gizmo should be enabled, so we don't sync them MpCompat.RegisterLambdaMethod(type, "GetGizmos", 0, 2, 3, 4, 6, 8, 9, 10); type = AccessTools.TypeByName("ItemProcessor.Command_SetQualityList"); MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true); MpCompat.RegisterLambdaMethod(type, "ProcessInput", Enumerable.Range(0, 8).ToArray()); type = AccessTools.TypeByName("ItemProcessor.Command_SetOutputList"); MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true); MP.RegisterSyncMethod(type, "TryConfigureIngredientsByOutput"); // Keep an eye on this in the future, seems like something the devs could combine into a single class at some point foreach (var ingredientNumber in new[] { "First", "Second", "Third", "Fourth" }) { type = AccessTools.TypeByName($"ItemProcessor.Command_Set{ingredientNumber}ItemList"); MP.RegisterSyncWorker <Command>(SyncSetIngredientCommand, type, shouldConstruct: true); MP.RegisterSyncMethod(type, $"TryInsert{ingredientNumber}Thing"); MpCompat.RegisterLambdaMethod(type, "ProcessInput", 0); } } // Vanilla Cooking Expanded { // AddHediff desyncs with Arbiter, but seems fine without it PatchingUtilities.PatchPushPopRand("VanillaCookingExpanded.Thought_Hediff:MoodOffset"); } // VFE Core { MpCompat.RegisterLambdaMethod("VFECore.CompPawnDependsOn", "CompGetGizmosExtra", 0).SetDebugOnly(); learnedAbilitiesField = AccessTools.Field(AccessTools.TypeByName("VFECore.Abilities.CompAbilities"), "learnedAbilities"); MP.RegisterSyncWorker <ITargetingSource>(SyncVEFAbility, AccessTools.TypeByName("VFECore.Abilities.Ability")); } // Vanilla Furniture Expanded { MpCompat.RegisterLambdaMethod("VanillaFurnitureExpanded.CompConfigurableSpawner", "CompGetGizmosExtra", 0).SetDebugOnly(); var type = AccessTools.TypeByName("VanillaFurnitureExpanded.Command_SetItemsToSpawn"); MpCompat.RegisterLambdaDelegate(type, "ProcessInput", 1); MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true); MpCompat.RegisterLambdaMethod("VanillaFurnitureExpanded.CompRockSpawner", "CompGetGizmosExtra", 0); type = AccessTools.TypeByName("VanillaFurnitureExpanded.Command_SetStoneType"); setStoneBuildingField = AccessTools.Field(type, "building"); MpCompat.RegisterLambdaMethod(type, "ProcessInput", 0); MP.RegisterSyncWorker <Command>(SyncSetStoneTypeCommand, type, shouldConstruct: true); MpCompat.RegisterLambdaDelegate(type, "ProcessInput", 1); type = AccessTools.TypeByName("VanillaFurnitureExpanded.CompRandomBuildingGraphic"); MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", 0); } // Vanilla Faction Mechanoids { var type = AccessTools.TypeByName("VFE.Mechanoids.CompMachineChargingStation"); MpCompat.RegisterLambdaDelegate(type, "CompGetGizmosExtra", 1, 6).SetContext(SyncContext.MapSelected); MpCompat.RegisterLambdaDelegate(type, "CompGetGizmosExtra", 4); } // AnimalBehaviours { // RNG PatchingUtilities.PatchSystemRand("AnimalBehaviours.DamageWorker_ExtraInfecter:ApplySpecialEffectsToPart", false); var rngFixConstructors = new[] { "AnimalBehaviours.CompAnimalProduct", "AnimalBehaviours.CompFilthProducer", "AnimalBehaviours.CompGasProducer", "AnimalBehaviours.CompInitialHediff", "AnimalBehaviours.DeathActionWorker_DropOnDeath", }; PatchingUtilities.PatchSystemRandCtor(rngFixConstructors, false); // Gizmos var type = AccessTools.TypeByName("AnimalBehaviours.CompDestroyThisItem"); MP.RegisterSyncMethod(type, "SetObjectForDestruction"); MP.RegisterSyncMethod(type, "CancelObjectForDestruction"); } // MVCF (Multi Verb Combat Framework) { var type = AccessTools.TypeByName("MVCF.WorldComponent_MVCF"); mvcfGetWorldCompMethod = AccessTools.Method(type, "GetComp"); mvcfAllManagersListField = AccessTools.Field(type, "allManagers"); mvcfManagersTableField = AccessTools.Field(type, "managers"); MP.RegisterSyncMethod(typeof(VanillaExpandedFramework), nameof(SyncedInitVerbManager)); MpCompat.harmony.Patch(AccessTools.Method(type, "GetManagerFor"), prefix: new HarmonyMethod(typeof(VanillaExpandedFramework), nameof(GetManagerForPrefix))); type = AccessTools.TypeByName("MVCF.VerbManager"); MP.RegisterSyncWorker <object>(SyncVerbManager, type, isImplicit: true); mvcfVerbManagerCtor = AccessTools.Constructor(type); mvcfInitializeManagerMethod = AccessTools.Method(type, "Initialize"); mvcfPawnGetter = AccessTools.PropertyGetter(type, "Pawn"); mvcfVerbsField = AccessTools.Field(type, "verbs"); var weakReferenceType = typeof(System.WeakReference <>).MakeGenericType(new[] { type }); weakReferenceCtor = AccessTools.FirstConstructor(weakReferenceType, ctor => ctor.GetParameters().Count() == 1); var conditionalWeakTableType = typeof(System.Runtime.CompilerServices.ConditionalWeakTable <,>).MakeGenericType(new[] { typeof(Pawn), type }); conditionalWeakTableAddMethod = AccessTools.Method(conditionalWeakTableType, "Add"); conditionalWeakTableTryGetValueMethod = AccessTools.Method(conditionalWeakTableType, "TryGetValue"); type = AccessTools.TypeByName("MVCF.ManagedVerb"); mvcfManagerVerbManagerField = AccessTools.Field(type, "man"); MP.RegisterSyncWorker <object>(SyncManagedVerb, type, isImplicit: true); // Seems like selecting the Thing that holds the verb inits some stuff, so we need to set the context MP.RegisterSyncMethod(type, "Toggle"); type = AccessTools.TypeByName("MVCF.Harmony.Gizmos"); MpCompat.RegisterLambdaDelegate(type, "GetGizmos_Postfix", 1); // Fire at will MpCompat.RegisterLambdaDelegate(type, "GetAttackGizmos_Postfix", 4); // Interrupt Attack MpCompat.RegisterLambdaDelegate(type, "Pawn_GetGizmos_Postfix", 0); // Also interrupt Attack } // Explosive Trails Effect { // RNG PatchingUtilities.PatchPushPopRand("ExplosiveTrailsEffect.SmokeThrowher:ThrowSmokeTrail"); } // KCSG (Custom Structure Generation) { // RNG var methods = new[] { "KCSG.SymbolResolver_AddFields:Resolve", "KCSG.SymbolResolver_Settlement:GenerateRooms", }; PatchingUtilities.PatchSystemRand(methods, false); } }
public static void LatePatch() => PatchingUtilities.PatchSystemRand("VEE.RegularEvents.SpaceBattle:GameConditionTick", false);
public VanillaBrewingExpanded(ModContentPack mod) { PatchingUtilities.PatchSystemRand("VanillaBrewingExpanded.Plant_AutoProduce:TickLong"); PatchingUtilities.PatchSystemRandCtor("VanillaBrewingExpanded.Hediff_ConsumedCocktail"); }
public AndroidTiers(ModContentPack mod) { // RNG { var methods = new[] { "MOARANDROIDS.CompHeatSensitive:PostSpawnSetup", "MOARANDROIDS.CompHeatSensitive:CheckTemperature", "MOARANDROIDS.StartingPawnUtility_Patch+NewGeneratedStartingPawn_Patch:Listener", "MOARANDROIDS.AndroidFactionDialogOverride:Postfix", "MOARANDROIDS.MultiplePawnRacesAtStart:Postfix", "MOARANDROIDS.Recipe_MemoryCorruptionChance:RandomCorruption", "MOARANDROIDS.Recipe_AndroidRewireSurgery:RandomCorruption", "MOARANDROIDS.Recipe_RemoveSentience:RandomCorruption", "MOARANDROIDS.Recipe_RerollTraits:RandomCorruption", "MOARANDROIDS.StockGenerator_SlaveAndroids+<GenerateThings>d__0:MoveNext", }; PatchingUtilities.PatchSystemRand(methods, false); } // Gizmos { var type = AccessTools.TypeByName("MOARANDROIDS.CompAndroidState"); MpCompat.RegisterLambdaDelegate(type, "CompGetGizmosExtra", 0, 2, 4, 5, 7, 10, 11, 12, 14); type = AccessTools.TypeByName("MOARANDROIDS.CompAutoDoor"); MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", 0, 1); type = AccessTools.TypeByName("MOARANDROIDS.CompRemotelyControlledTurret"); MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", 0); // Really ugly... We can't sync the pawns directly here, as they're inaccessible - the ThingComp is holding them inside // however, it does not implement IThingHolder or whatever it's supposed to in cases like those // so we do a lot of workarounds to not rely on the pawn sync worker type = compSkyCloudCoreType = AccessTools.TypeByName("MOARANDROIDS.CompSkyCloudCore"); skyCloudCoreStoredMindsField = AccessTools.FieldRefAccess <List <Pawn> >(type, "storedMinds"); MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", 6, 10, 11, 12, 13, 26, 27); var methods = MpMethodUtil.GetLambda(type, "CompGetGizmosExtra", MethodType.Normal, null, 4, 16, 24); foreach (var method in methods) { MP.RegisterSyncMethod(method); MP.RegisterSyncWorker <object>(SyncInnerClassWithPawn, method.DeclaringType, shouldConstruct: true); } var methodsArray = MpMethodUtil.GetLambda(type, "CompGetGizmosExtra", MethodType.Normal, null, 6, 11, 27).ToArray(); skyCloudCoreGetGizmos6 = MethodInvoker.GetHandler(methodsArray[0]); skyCloudCoreGetGizmos11 = MethodInvoker.GetHandler(methodsArray[1]); skyCloudCoreGetGizmos27 = MethodInvoker.GetHandler(methodsArray[2]); MP.RegisterSyncMethod(typeof(AndroidTiers), nameof(SyncedGetGizmos6)); MP.RegisterSyncMethod(typeof(AndroidTiers), nameof(SyncedGetGizmos11)); MP.RegisterSyncMethod(typeof(AndroidTiers), nameof(SyncedGetGizmos27)); MpCompat.harmony.Patch(methodsArray[0], prefix: new HarmonyMethod(typeof(AndroidTiers), nameof(PreCompGetGizmos6))); MpCompat.harmony.Patch(methodsArray[1], prefix: new HarmonyMethod(typeof(AndroidTiers), nameof(PreCompGetGizmos11))); MpCompat.harmony.Patch(methodsArray[2], prefix: new HarmonyMethod(typeof(AndroidTiers), nameof(PreCompGetGizmos27))); type = AccessTools.TypeByName("MOARANDROIDS.CompSkyMind"); MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", 1, 3); type = compSurrogateOwnerType = AccessTools.TypeByName("MOARANDROIDS.CompSurrogateOwner"); surrogateOwnerSkyCloudHostField = AccessTools.FieldRefAccess <Thing>(type, "skyCloudHost"); MpCompat.RegisterLambdaDelegate(type, "CompGetGizmosExtra", 1, 3, 5, 9, 10, 13, 16, 19, 23); type = AccessTools.TypeByName("MOARANDROIDS.CPaths"); MpCompat.RegisterLambdaDelegate(type, "QEE_BuildingPawnVatGrower_GetGizmosPostfix", 2, 5, 8); // CompComputer - all gizmos end up using a designator to pick a target, so we sync the designator } // Designators { var type = AccessTools.TypeByName("MOARANDROIDS.Designator_SurrogateToHack"); surrogateToHackConstructor = AccessTools.Constructor(type, new[] { typeof(int) }); surrogateToHackPosField = AccessTools.FieldRefAccess <IntVec3>(type, "pos"); surrogateToHackTargetField = AccessTools.FieldRefAccess <Pawn>(type, "target"); surrogateToHackMapField = AccessTools.FieldRefAccess <Map>(type, "cmap"); surrogateToHackHackTypeField = AccessTools.FieldRefAccess <int>(type, "hackType"); MP.RegisterSyncWorker <Designator>(SyncSurrogateToHackDesignator, type); type = AccessTools.TypeByName("MOARANDROIDS.Designator_AndroidToControl"); androidToControlConstructor = AccessTools.Constructor(type, new[] { typeof(Pawn), typeof(bool) }); androidToControlPawnField = AccessTools.FieldRefAccess <Pawn>(type, "controller"); androidToControlFromSkyCloudField = AccessTools.FieldRefAccess <bool>(type, "fromSkyCloud"); androidToControlKindOfTargetField = AccessTools.FieldRefAccess <int>(type, "kindOfTarget"); androidToControlPosField = AccessTools.FieldRefAccess <IntVec3>(type, "pos"); androidToControlTargetField = AccessTools.FieldRefAccess <Thing>(type, "target"); androidToControlMapField = AccessTools.FieldRefAccess <Map>(type, "cmap"); MP.RegisterSyncWorker <Designator>(SyncAndroidToControlDesignator, type); MP.RegisterSyncMethod(typeof(AndroidTiers), nameof(SyncedConnectToSkyMind)); MpCompat.harmony.Patch(AccessTools.Method(type, "CanDesignateThing"), transpiler: new HarmonyMethod(typeof(AndroidTiers), nameof(ReplaceConnectToSkyMind))); } // Dialogs { var type = AccessTools.TypeByName("MOARANDROIDS.Dialog_SkillUp"); skillUpDialogConstructor = AccessTools.Constructor(type, new[] { typeof(Pawn), typeof(bool) }); skillUpGetNbPointsWantedToBuyMethod = MethodInvoker.GetHandler(AccessTools.Method(type, "getNbPointsWantedToBuy")); skillUpAndroidField = AccessTools.FieldRefAccess <Pawn>(type, "android"); skillUpSkillDefListField = AccessTools.FieldRefAccess <List <SkillDef> >(type, "sd"); skillUpPointsField = AccessTools.FieldRefAccess <List <int> >(type, "points"); skillUpPassionsStateField = AccessTools.FieldRefAccess <List <int> >(type, "points"); skillUpPointsNeededPerSkillField = AccessTools.FieldRefAccess <int>(type, "pointsNeededPerSkill"); skillUppointsNeededToIncreasePassionField = AccessTools.FieldRefAccess <int>(type, "pointsNeededToIncreasePassion"); MP.RegisterSyncMethod(typeof(AndroidTiers), nameof(SyncedSkillUpDialogAccept)); MP.RegisterSyncWorker <Window>(SyncSkillUpDialog, type); MpCompat.harmony.Patch(AccessTools.Method(type, "DoWindowContents"), transpiler: new HarmonyMethod(typeof(AndroidTiers), nameof(ReplaceButton))); type = AccessTools.TypeByName("MOARANDROIDS.Utils"); gcAttpCompField = AccessTools.StaticFieldRefAccess <GameComponent>(AccessTools.Field(type, "GCATPP")); type = AccessTools.TypeByName("MOARANDROIDS.GC_ATPP"); gameComponentDecSkillPointsMethod = MethodInvoker.GetHandler(AccessTools.Method(type, "decSkillPoints")); gameComponentConnectUserMethod = MethodInvoker.GetHandler(AccessTools.Method(type, "connectUser")); gameComponentConnectedThingField = AccessTools.FieldRefAccess <HashSet <Thing> >(type, "connectedThing"); gameComponentNbSlotField = AccessTools.FieldRefAccess <int>(type, "nbSlot"); } // Choice letters { var type = AccessTools.TypeByName("Multiplayer.Client.Patches.CloseDialogsForExpiredLetters"); // We should probably add this to the API the next time we update it var rejectMethods = (Dictionary <Type, MethodInfo>)AccessTools.Field(type, "rejectMethods").GetValue(null); var typeNames = new[] { "MOARANDROIDS.ChoiceLetter_RansomDemand", "MOARANDROIDS.ChoiceLetter_RansomwareDemand", }; foreach (var typeName in typeNames) { type = AccessTools.TypeByName(typeName); rejectMethods.Add(type, AccessTools.Method(typeof(ChoiceLetter), nameof(ChoiceLetter.Option_Reject))); // Generic reject option var method = MpMethodUtil.GetLambda(type, "Choices", MethodType.Getter, lambdaOrdinal: 0); MP.RegisterSyncMethod(method); } } }
public VanillaPowerExpanded(ModContentPack mod) { Type type; // Gizmos // Debug fill/empty { type = AccessTools.TypeByName("GasNetwork.CompGasStorage"); // Both these methods are calling (basically) the same method, // but that method also has other callers that don't need syncing MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", 0, 1).SetDebugOnly(); } // Order to or cancel plugging the hole (method names shared by both types) { var types = new[] { "VanillaPowerExpanded.Building_ChemfuelPond", "VanillaPowerExpanded.Building_GasGeyser", }; foreach (var typeName in types) { type = AccessTools.TypeByName(typeName); MP.RegisterSyncMethod(type, "SetHoleForPlugging"); MP.RegisterSyncMethod(type, "CancelHoleForPlugging"); } } // Violence generator { type = AccessTools.TypeByName("VanillaPowerExpanded.CompSoulsPowerPlant"); MpCompat.RegisterLambdaMethod(type, "CompGetGizmosExtra", 1); // Toggle on/off } // RNG Fix { // Patch GasNetwork.MapComponent_WindDirection ctor PatchingUtilities.PatchSystemRand(AccessTools.Constructor(AccessTools.TypeByName("GasNetwork.MapComponent_WindDirection"), new Type[] { typeof(Map) }), false); var methods = new[] { "VanillaPowerExpanded.Building_SmallBattery:Tick", "VanillaPowerExpanded.Building_SmallBattery:PostApplyDamage", "VanillaPowerExpanded.WeatherEvent_CustomLightningStrike:FireEvent", "VanillaPowerExpanded.MapComponentExtender:doMapSpawns", "VanillaPowerExpanded.CompPlantHarmRadiusIfBroken:CompTick", // HarmRandomPlantInRadius is only called by CompPlantHarmRadiusIfBroken:CompTick, no need for patching // CompPowerPlantNuclear:AffectCell is only calling a seeded random "VanillaPowerExpanded.IntermittentGasSprayer:SteamSprayerTick", // IntermittentGasSprayer - NewBaseAirPuff is only called by ThrowAirPuffUp which is called by SteamSprayerTick, no need for patching // Building_GasGeyser:StartSpray is assigned to IntermittentGasSprayer:startSprayCallback, which is called from SteamSprayerTick "GasNetwork.GasNet:GasNetTick", "GasNetwork.MapComponent_WindDirection:MapGenerated", // PipeNetGrid pushes and pops all Rand calls, no need to patch // CompPowerAdvancedWater:RebuildCache is only calling a seeded random }; // These methods are loading resources in their .ctor, must be patched later var methodsForLater = new[] { "VanillaPowerExpanded.CompPowerAdvancedWater:PostSpawnSetup", "VanillaPowerExpanded.CompPowerAdvancedWind:PostSpawnSetup", }; PatchingUtilities.PatchPushPopRand(methods); LongEventHandler.ExecuteWhenFinished(() => PatchingUtilities.PatchPushPopRand(methodsForLater)); // Wind map comp windDirectionField = AccessTools.FieldRefAccess <float>(AccessTools.TypeByName("GasNetwork.MapComponent_WindDirection"), "windDirection"); MpCompat.harmony.Patch(AccessTools.Method("GasNetwork.MapComponent_WindDirection:MapComponentTick"), prefix: new HarmonyMethod(typeof(VanillaPowerExpanded), nameof(ReplaceWindMapComponentTick))); // GasNet utilities MpCompat.harmony.Patch(AccessTools.Method("GasNetwork.Utilities:HashOffsetTicks"), prefix: new HarmonyMethod(typeof(VanillaPowerExpanded), nameof(ReplaceHashOffsetTicks))); } }
public WhatTheHack(ModContentPack mod) { thingsById = (Dictionary <int, Thing>)AccessTools.Field(AccessTools.TypeByName("Multiplayer.Client.ThingsById"), "thingsById").GetValue(null); // Setup { // Base mod class var type = AccessTools.TypeByName("WhatTheHack.Base"); MpCompat.harmony.Patch(AccessTools.Method(type, "WorldLoaded"), postfix: new HarmonyMethod(typeof(WhatTheHack), nameof(PostWorldLoaded))); // ExtendedDataStorage class type = AccessTools.TypeByName("WhatTheHack.Storage.ExtendedDataStorage"); pawnStorageDictionary = AccessTools.FieldRefAccess <IDictionary>(type, "_store"); getExtendedDataForPawnMethod = MethodInvoker.GetHandler(AccessTools.Method(type, "GetExtendedDataFor", new[] { typeof(Pawn) })); // ExtendedPawnData class, needs to be synced for some sync methods type = AccessTools.TypeByName("WhatTheHack.Storage.ExtendedPawnData"); MP.RegisterSyncWorker <object>(SyncExtendedPawnData, type); } // RNG { var methods = new[] { AccessTools.Method(AccessTools.TypeByName("WhatTheHack.Harmony.IncidentWorker_Raid_TryExecuteWorker"), "SpawnHackedMechanoids"), AccessTools.Method(AccessTools.TypeByName("WhatTheHack.Harmony.Pawn_JobTracker_DetermineNextJob"), "HackedPoorlyEvent"), AccessTools.Method(AccessTools.TypeByName("WhatTheHack.Harmony.Thing_ButcherProducts+<GenerateExtraButcherProducts>d__1"), "MoveNext"), AccessTools.Method(AccessTools.TypeByName("WhatTheHack.Needs.Need_Maintenance"), "MaybeUnhackMechanoid"), AccessTools.Method(AccessTools.TypeByName("WhatTheHack.Recipes.Recipe_Hacking"), "CheckHackingFail"), }; PatchingUtilities.PatchSystemRand(methods, false); } // Gizmos { // Activate the beacon to boost rogue AI MP.RegisterSyncMethod(AccessTools.Method("WhatTheHack.Buildings.Building_MechanoidBeacon:StartupHibernatingParts")); // Mechanoid platform (bed) // Toggle regenerate missing parts (1), toggle repair (3) MpCompat.RegisterLambdaMethod("WhatTheHack.Buildings.Building_MechanoidPlatform", "GetGizmos", 1, 3); // Rogue AI, it's got a bit of functions var type = AccessTools.TypeByName("WhatTheHack.Buildings.Building_RogueAI"); // Methods MpCompat.RegisterLambdaMethod(type, "GetTalkGibberishGizmo", 0); MpCompat.RegisterLambdaMethod(type, "GetManagePowerNetworkGizmo", 1); MpCompat.RegisterLambdaMethod(type, "GetControlTurretAvtivateGizmo", 0); MpCompat.RegisterLambdaMethod(type, "GetControlMechanoidActivateGizmo", 0); MpCompat.RegisterLambdaMethod(type, "GetHackingAvtivateGizmo", 0); // Delegates MpCompat.RegisterLambdaDelegate(type, "GetControlMechanoidCancelGizmo", 0); MpCompat.RegisterLambdaDelegate(type, "GetControlTurretCancelGizmo", 0); MpCompat.RegisterLambdaDelegate(type, "GetHackingCancelGizmo", 0); // Gizmo for hacked mechanoids, setting min value for maintenance type = AccessTools.TypeByName("WhatTheHack.Command_SetMaintenanceThreshold"); maintenanceNeedField = AccessTools.FieldRefAccess <Need>(type, "maintenanceNeed"); MpCompat.RegisterLambdaMethod(type, "ProcessInput", 1); MP.RegisterSyncWorker <Command>(SyncCommand_SetMaintenanceThreshold, type, shouldConstruct: true); // Gizmo for hacked mechanoids, setting min value for power type = AccessTools.TypeByName("WhatTheHack.Command_SetWorkThreshold"); powerNeedField = AccessTools.FieldRefAccess <Need>(type, "powerNeed"); MpCompat.RegisterLambdaMethod(type, "ProcessInput", 1); MP.RegisterSyncWorker <Command>(SyncCommand_SetWorkThreshold, type, shouldConstruct: true); // type = AccessTools.TypeByName("WhatTheHack.Harmony.Pawn_GetGizmos"); MpCompat.RegisterLambdaDelegate(type, "CreateGizmo_SearchAndDestroy", 1); MpCompat.RegisterLambdaDelegate(type, "CreateGizmo_AutoRecharge", 1); MpCompat.RegisterLambdaDelegate(type, "CreateGizmo_Work", 1); MpCompat.RegisterLambdaDelegate(type, "CreateGizmo_SelfDestruct", 0); MpCompat.RegisterLambdaDelegate(type, "CreateGizmo_SelfRepair", 0); MpCompat.RegisterLambdaDelegate(type, "CreateGizmo_Repair", 0); MpCompat.RegisterLambdaDelegate(type, "CreateGizmo_EquipBelt", 0); MpCompat.RegisterLambdaDelegate(type, "CreateGizmo_Overdrive", 0); type = AccessTools.TypeByName("WhatTheHack.RemoteController"); MpCompat.RegisterLambdaDelegate(type, "GetRemoteControlDeActivateGizmo", 0); MpCompat.RegisterLambdaDelegate(type, "GetRemoteControlActivateGizmo", 0); type = AccessTools.TypeByName("WhatTheHack.Harmony.CompLongRangeMineralScanner_CompGetGizmosExtra"); MpCompat.RegisterLambdaDelegate(type, "AddMechPartsOption", 1).SetContext(SyncContext.MapSelected); } }
public GeneticRimCompat(ModContentPack mod) { Type type; // Several Gizmos { type = AccessTools.TypeByName("DraftingPatcher.Pawn_GetGizmos_Patch"); string[] methods = { "<AddGizmo>b__0", "<AddGizmo>b__1", "<AddGizmo>b__10", "<AddGizmo>b__11", "<AddGizmo>b__12", "<AddGizmo>b__13", "<AddGizmo>b__14", "<AddGizmo>b__15", "<AddGizmo>b__16", "<AddGizmo>b__17", "<AddGizmo>b__3", "<AddGizmo>b__5", "<AddGizmo>b__7", "<AddGizmo>b__8", "<AddGizmo>b__9", }; foreach (string method in methods) { MP.RegisterSyncDelegate(type, "<>c__DisplayClass0_0", method); } } // ArchotechShip startup { MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.ArchotechUtility:StartupHibernatingParts")); MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.ArchotechCountdown:InitiateCountdown")); } { type = AccessTools.TypeByName("NewMachinery.ArchotechCountdown"); string[] methods = { "InitiateCountdown", "CancelCountdown", "CountdownEnded" }; foreach (string method in methods) { MP.RegisterSyncMethod(AccessTools.Method(type, method)); } } // Genepod { type = AccessTools.TypeByName("NewMachinery.Building_NewGenePod"); MP.RegisterSyncMethod(type, "<GetGizmos>b__20_0"); MP.RegisterSyncMethod(type, "<GetGizmos>b__20_1"); } // Commands { MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.Command_SetGene2List:ProcessInput")); MP.RegisterSyncMethod(AccessTools.Method("NewMachinery.Command_SetGeneList:ProcessInput")); } // RNG patching { string[] methodsWithRand = { "NewHatcher.CompHatcherRandomizer:Hatch", "NewHatcher.CompIncubator:Hatch", "NewHatcher.CompRecombinator:Hatch", "NewHatcher.CompRecombinator:RecombinateAgain", "NewHatcher.CompRecombinatorSerum:Hatch", }; PatchingUtilities.PatchSystemRand(methodsWithRand); } }
public VanillaExpandedFramework(ModContentPack mod) { // ItemProcessor { var type = AccessTools.TypeByName("ItemProcessor.Building_ItemProcessor"); // _1, _5 and _7 are used to check if gizmo should be enabled, so we don't sync them MpCompat.RegisterSyncMethodsByIndex(type, "<GetGizmos>", 0, 2, 3, 4, 6, 8, 9, 10); type = AccessTools.TypeByName("ItemProcessor.Command_SetQualityList"); MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true); MpCompat.RegisterSyncMethodsByIndex(type, "<ProcessInput>", Enumerable.Range(0, 8).ToArray()); type = AccessTools.TypeByName("ItemProcessor.Command_SetOutputList"); MP.RegisterSyncWorker <Command>(SyncCommandWithBuilding, type, shouldConstruct: true); MP.RegisterSyncMethod(type, "TryConfigureIngredientsByOutput"); // Keep an eye on this in the future, seems like something the devs could combine into a single class at some point foreach (var ingredientNumber in new[] { "First", "Second", "Third", "Fourth" }) { type = AccessTools.TypeByName($"ItemProcessor.Command_Set{ingredientNumber}ItemList"); MP.RegisterSyncWorker <Command>(SyncSetIngredientCommand, type, shouldConstruct: true); MP.RegisterSyncMethod(type, $"TryInsert{ingredientNumber}Thing"); MpCompat.RegisterSyncMethodsByIndex(type, "<ProcessInput>", 0); } } // Vanilla Cooking Expanded { // AddHediff desyncs with Arbiter, but seems fine without it PatchingUtilities.PatchPushPopRand("VanillaCookingExpanded.Thought_Hediff:MoodOffset"); } // VFE Core { var type = AccessTools.TypeByName("VFECore.CompPawnDependsOn"); MpCompat.RegisterSyncMethodByIndex(type, "<CompGetGizmosExtra>", 0).SetDebugOnly(); } // Vanilla Furniture Expanded { var type = AccessTools.TypeByName("VanillaFurnitureExpanded.CompConfigurableSpawner"); MpCompat.RegisterSyncMethodByIndex(type, "<CompGetGizmosExtra>", 0).SetDebugOnly(); type = AccessTools.TypeByName("VanillaFurnitureExpanded.Command_SetItemsToSpawn"); MP.RegisterSyncDelegate(type, "<>c__DisplayClass2_0", "<ProcessInput>b__1"); type = AccessTools.TypeByName("VanillaFurnitureExpanded.CompRockSpawner"); MpCompat.RegisterSyncMethodByIndex(type, "<CompGetGizmosExtra>", 0); type = AccessTools.TypeByName("VanillaFurnitureExpanded.Command_SetStoneType"); setStoneBuildingField = AccessTools.Field(type, "building"); MpCompat.RegisterSyncMethodByIndex(type, "<ProcessInput>", 0); MP.RegisterSyncWorker <Command>(SyncSetStoneTypeCommand, type, shouldConstruct: true); MP.RegisterSyncDelegate(type, "<>c__DisplayClass2_0", "<ProcessInput>b__1"); } // Vanilla Faction Mechanoids { var type = AccessTools.TypeByName("VFE.Mechanoids.CompMachineChargingStation"); MP.RegisterSyncDelegate(type, "<>c", "<CompGetGizmosExtra>b__21_1", Array.Empty <string>()).SetContext(SyncContext.MapSelected); MP.RegisterSyncDelegate(type, "<>c", "<CompGetGizmosExtra>b__21_6", Array.Empty <string>()).SetContext(SyncContext.MapSelected); MP.RegisterSyncDelegate(type, "<>c__DisplayClass21_0", "<CompGetGizmosExtra>b__4"); } // AnimalBehaviours { // RNG PatchingUtilities.PatchSystemRand("AnimalBehaviours.DamageWorker_ExtraInfecter:ApplySpecialEffectsToPart", false); PatchingUtilities.PatchSystemRandCtor(new[] { "AnimalBehaviours.CompAnimalProduct", "AnimalBehaviours.CompGasProducer" }, false); // Gizmos // Might not work, as I could not find a mod that uses this to test this var type = AccessTools.TypeByName("AnimalBehaviours.CompDestroyThisItem"); MP.RegisterSyncMethod(type, "SetObjectForDestruction"); MP.RegisterSyncMethod(type, "CancelObjectForDestruction"); } // MVCF (Multi Verb Combat Framework) { var type = AccessTools.TypeByName("MVCF.WorldComponent_MVCF"); mvcfGetWorldCompMethod = AccessTools.Method(type, "GetComp"); mvcfAllManagersListField = AccessTools.Field(type, "allManagers"); mvcfManagersTableField = AccessTools.Field(type, "managers"); MP.RegisterSyncMethod(typeof(VanillaExpandedFramework), nameof(SyncedInitVerbManager)); MpCompat.harmony.Patch(AccessTools.Method(type, "GetManagerFor"), prefix: new HarmonyMethod(typeof(VanillaExpandedFramework), nameof(GetManagerForPrefix))); type = AccessTools.TypeByName("MVCF.VerbManager"); MP.RegisterSyncWorker <object>(SyncVerbManager, type, isImplicit: true); mvcfVerbManagerCtor = AccessTools.Constructor(type); mvcfInitializeManagerMethod = AccessTools.Method(type, "Initialize"); mvcfPawnGetter = AccessTools.PropertyGetter(type, "Pawn"); mvcfVerbsField = AccessTools.Field(type, "verbs"); var weakReferenceType = typeof(System.WeakReference <>).MakeGenericType(new[] { type }); weakReferenceCtor = AccessTools.FirstConstructor(weakReferenceType, ctor => ctor.GetParameters().Count() == 1); var conditionalWeakTableType = typeof(System.Runtime.CompilerServices.ConditionalWeakTable <,>).MakeGenericType(new[] { typeof(Pawn), type }); conditionalWeakTableAddMethod = AccessTools.Method(conditionalWeakTableType, "Add"); conditionalWeakTableTryGetValueMethod = AccessTools.Method(conditionalWeakTableType, "TryGetValue"); type = AccessTools.TypeByName("MVCF.ManagedVerb"); mvcfManagerVerbManagerField = AccessTools.Field(type, "man"); MP.RegisterSyncWorker <object>(SyncManagedVerb, type, isImplicit: true); // Seems like selecting the Thing that holds the verb inits some stuff, so we need to set the context MP.RegisterSyncMethod(type, "Toggle"); type = AccessTools.TypeByName("MVCF.Harmony.Gizmos"); MP.RegisterSyncDelegate(type, "<>c__DisplayClass5_0", "<GetGizmos_Postfix>b__1"); // Fire at will MP.RegisterSyncDelegate(type, "<>c__DisplayClass6_0", "<GetAttackGizmos_Postfix>b__4"); // Interrupt Attack MP.RegisterSyncDelegate(type, "<>c__DisplayClass7_0", "<Pawn_GetGizmos_Postfix>b__0"); // Also interrupt Attack } }