public void LatePatch()
        {
            // Facepaint
            changeFacepaintDialogType = AccessTools.TypeByName("VFEV.Facepaint.Dialog_ChangeFacepaint");
            //setFacepaintMethod = AccessTools.Method(changeFacepaintDialogType, "SetHairstyle");
            orderedFacepaintDefsField = AccessTools.Field(changeFacepaintDialogType, "orderedFacepaintDefs");

            newFacepaintComboSync = MP.RegisterSyncField(AccessTools.Field(changeFacepaintDialogType, "newFacepaintCombo"));
            coloursTiedSync       = MP.RegisterSyncField(AccessTools.Field(changeFacepaintDialogType, "coloursTied"));
            MP.RegisterSyncMethod(changeFacepaintDialogType, "SetHairstyle");
            MP.RegisterSyncWorker <Window>(SyncDialog, changeFacepaintDialogType);

            MP.RegisterSyncMethod(typeof(VanillaFactionsVikings), nameof(SyncedTryRemoveWindow));

            MpCompat.harmony.Patch(AccessTools.Method(changeFacepaintDialogType, "DoWindowContents"),
                                   prefix: new HarmonyMethod(typeof(VanillaFactionsVikings), nameof(PreDoWindowContents)),
                                   postfix: new HarmonyMethod(typeof(VanillaFactionsVikings), nameof(PostDoWindowContents)));

            var type = AccessTools.Inner(changeFacepaintDialogType, "FacepaintCombination");

            MP.RegisterSyncWorker <object>(SyncFacepaintCombination, type);

            facepaintDefOneField    = AccessTools.Field(type, "facepaintDefOne");
            facepaintDefTwoField    = AccessTools.Field(type, "facepaintDefTwo");
            facepaintColourOneField = AccessTools.Field(type, "colourOne");
            facepaintColourTwoField = AccessTools.Field(type, "colourTwo");

            MpCompat.harmony.Patch(AccessTools.Method(typeof(WindowStack), nameof(WindowStack.TryRemove), new[] { typeof(Window), typeof(bool) }),
                                   prefix: new HarmonyMethod(typeof(VanillaFactionsVikings), nameof(PreTryRemoveWindow)));
        }
예제 #2
0
        static ExtendedOutfitProxy()
        {
            if (!MP.enabled)
            {
                return;
            }

            ProxyFields = new ISyncField[] {
                MP.RegisterSyncField(typeof(ExtendedOutfitProxy), nameof(targetWeight))
                .SetBufferChanges().PostApply(Update)
            };

            ExtendedOutfitFields = new ISyncField[] {
                MP.RegisterSyncField(typeof(ExtendedOutfit), nameof(ExtendedOutfit.targetTemperaturesOverride)),
                MP.RegisterSyncField(typeof(ExtendedOutfit), nameof(ExtendedOutfit.targetTemperatures)),
                MP.RegisterSyncField(typeof(ExtendedOutfit), nameof(ExtendedOutfit.PenaltyWornByCorpse)),
                MP.RegisterSyncField(typeof(ExtendedOutfit), nameof(ExtendedOutfit.AutoWorkPriorities)),
            };

            MP.RegisterSyncMethod(typeof(ExtendedOutfit), nameof(ExtendedOutfit.AddStatPriority));
            MP.RegisterSyncMethod(typeof(ExtendedOutfit), nameof(ExtendedOutfit.RemoveStatPriority));

            MP.RegisterSyncMethod(typeof(ExtendedOutfitProxy), nameof(SetStat));

            MP.RegisterSyncWorker <ExtendedOutfit>(ExtendedOutfitSyncer);
        }
예제 #3
0
        public AnimalTab(ModContentPack mod)
        {
            var type = AccessTools.TypeByName("AnimalTab.Command_HandlerSettings");

            commandCtor = AccessTools.Constructor(type, new[] { AccessTools.TypeByName("AnimalTab.CompHandlerSettings") });
            compField   = AccessTools.FieldRefAccess <ThingComp>(type, "comp");
            MP.RegisterSyncMethod(type, "MassSetMode").SetContext(SyncContext.MapSelected);
            MP.RegisterSyncMethod(type, "MassSetHandler").SetContext(SyncContext.MapSelected);
            MP.RegisterSyncMethod(type, "MassSetLevel").SetContext(SyncContext.MapSelected);
            MP.RegisterSyncWorker <Command_Action>(SyncHandlerSettingsCommand, type);

            type = AccessTools.TypeByName("AnimalTab.PawnColumnWorker_Handler");
            MpCompat.RegisterLambdaDelegate(type, "DoHandlerFloatMenu", 0, 1, 2);
            MpCompat.RegisterLambdaDelegate(type, "DoMassHandlerFloatMenu", 0, 1, 4);
            MpCompat.harmony.Patch(AccessTools.Method(type, nameof(PawnColumnWorker.DoHeader)),
                                   prefix: new HarmonyMethod(typeof(AnimalTab), nameof(PreDoHeader)),
                                   postfix: new HarmonyMethod(typeof(AnimalTab), nameof(StopWatch)));
            MpCompat.harmony.Patch(AccessTools.Method(type, nameof(PawnColumnWorker.DoCell)),
                                   prefix: new HarmonyMethod(typeof(AnimalTab), nameof(PreDoCell)),
                                   postfix: new HarmonyMethod(typeof(AnimalTab), nameof(StopWatch)));

            type       = compHandlerSettingsType = AccessTools.TypeByName("AnimalTab.CompHandlerSettings");
            modeField  = MP.RegisterSyncField(type, "_mode");
            levelField = MP.RegisterSyncField(type, "_level");
        }
        private static void LatePatch()
        {
            // Window_Psyker
            psykerWindowType      = AccessTools.TypeByName("Corruption.Psykers.Window_Psyker");
            psykerWindowCompField = AccessTools.Field(psykerWindowType, "comp");
            MP.RegisterSyncMethod(typeof(CorruptionPsykers), nameof(SyncedAddMinorDiscipline));

            MpCompat.harmony.Patch(AccessTools.Method(psykerWindowType, nameof(Window.DoWindowContents)),
                                   prefix: new HarmonyMethod(typeof(CorruptionPsykers), nameof(PrePsykerDoWindowContents)),
                                   postfix: new HarmonyMethod(typeof(CorruptionPsykers), nameof(PostPsykerDoWindowContents)));

            MP.RegisterSyncMethod(typeof(CorruptionPsykers), nameof(SyncedTryLearnPower));

            var psykerLearnablePowerType = AccessTools.TypeByName("Corruption.Psykers.PsykerLearnablePower");

            var type = AccessTools.TypeByName("Corruption.Psykers.CompPsyker");

            compPsykerTryLearnPowerMethod   = AccessTools.Method(type, "TryLearnPower", new Type[] { psykerLearnablePowerType });
            compPsykerAddXpMethod           = AccessTools.Method(type, "AddXP");
            compPsykerMainDisciplineField   = AccessTools.Field(type, "MainDiscipline");
            compPsykerMinorDisciplinesField = AccessTools.Field(type, "minorDisciplines");
            compPsykerXpSyncField           = MP.RegisterSyncField(type, "PsykerXP");

            type = AccessTools.TypeByName("Corruption.Psykers.PsykerDisciplineDef");
            psykerDisciplineDefAbilitiesField = AccessTools.Field(type, "abilities");

            var database = typeof(DefDatabase <>).MakeGenericType(new Type[] { type });

            getDefByShortHash = AccessTools.Method(database, "GetByShortHash");

            MpCompat.harmony.Patch(AccessTools.Method(psykerWindowType, "DrawSelectedPower"),
                                   transpiler: new HarmonyMethod(typeof(CorruptionPsykers), nameof(Transpiler)));
        }
예제 #5
0
        public CorruptionCore(ModContentPack mod)
        {
            // ITab_Pawn_Soul - checkboxes to allow praying and show prayers
            var type = AccessTools.TypeByName("Corruption.Core.Soul.ITab_Pawn_Soul");

            pawnSoulITabSoulToShowGetter = AccessTools.PropertyGetter(type, "SoulToShow");
            MP.RegisterSyncMethod(typeof(CorruptionCore), nameof(SyncFavourValue));
            MpCompat.harmony.Patch(AccessTools.Method(type, "FillTab"),
                                   prefix: new HarmonyMethod(typeof(CorruptionCore), nameof(PreFillTab)),
                                   postfix: new HarmonyMethod(typeof(CorruptionCore), nameof(PostFillTab)));

            type = AccessTools.TypeByName("Corruption.Core.Soul.CompSoul");
            compSoulFavourTrackerField = AccessTools.Field(type, "FavourTracker");
            compSoulAllowPrayingSync   = MP.RegisterSyncField(type, "PrayerTracker/AllowPraying");
            compSoulShowPrayerSync     = MP.RegisterSyncField(type, "PrayerTracker/ShowPrayer");

            setPawnPantheonDialogType      = AccessTools.TypeByName("Corruption.Core.Dialog_SetPawnPantheon");
            setPawnPantheonDialogSoulField = AccessTools.Field(setPawnPantheonDialogType, "soul");
            MP.RegisterSyncMethod(setPawnPantheonDialogType, "SelectionChanged");
            MP.RegisterSyncWorker <object>(SyncDialogSetPawnPantheon, setPawnPantheonDialogType);

            type = AccessTools.TypeByName("Corruption.Core.Soul.Soul_FavourTracker");
            soulFavourTrackerFavoursField = AccessTools.Field(type, "Favours");

            type = AccessTools.TypeByName("Corruption.Core.Soul.FavourProgress");
            favourProgressFavourValueField = AccessTools.Field(type, "favourValue");
        }
        public CommonSense(ModContentPack mod)
        {
            manualUnloadEnabledField = AccessTools.Field(AccessTools.TypeByName("CommonSense.Settings"), "gui_manual_unload");
            var type = AccessTools.TypeByName("CommonSense.CompUnloadChecker");

            MP.RegisterSyncWorker <ThingComp>(SyncComp, type);
            shouldUnloadSyncField        = MP.RegisterSyncField(AccessTools.Field(type, "ShouldUnload"));
            getCompUnlockerCheckerMethod = AccessTools.Method(type, "GetChecker");

            MpCompat.harmony.Patch(AccessTools.Method("RimWorld.ITab_Pawn_Gear:DrawThingRow"),
                                   prefix: new HarmonyMethod(typeof(CommonSense), nameof(CommonSensePatchPrefix)),
                                   postfix: new HarmonyMethod(typeof(CommonSense), nameof(CommonSensePatchPostix)));
        }
예제 #7
0
        public SimpleSidearmsCompat(ModContentPack mod)
        {
            Type type;

            {
                type = AccessTools.TypeByName("SimpleSidearms.intercepts.FloatMenuMakerMap_AddHumanLikeOrders_Postfix");

                MP.RegisterSyncDelegate(type, "<>c__DisplayClass0_0", "<AddHumanlikeOrders>b__0");
            }
            {
                type = AccessTools.TypeByName("SimpleSidearms.utilities.WeaponAssingment");

                MP.RegisterSyncMethod(type, "SetPrimary");
                MP.RegisterSyncMethod(type, "weaponSwapSpecific");
                MP.RegisterSyncMethod(type, "dropSidearm");
                MP.RegisterSyncMethod(type, "forgetSidearmMemory");
            }
            {
                type = AccessTools.TypeByName("SimpleSidearms.rimworld.GoldfishModule");

                MP.RegisterSyncMethod(type, "SetPrimaryEmpty");
                MP.RegisterSyncMethod(type, "AddSidearm");
                MP.RegisterSyncMethod(type, "DropPrimary");
                MP.RegisterSyncMethod(type, "DropSidearm");
                MP.RegisterSyncWorker <object>(SyncWorkerForGoldfishModule, type);

                GoldfishModule_PawnProperty             = AccessTools.Property(type, "Owner");
                GoldfishModule_GetGoldfishForPawnMethod = AccessTools.Method(type, "GetGoldfishForPawn");
            }
            // All the following for that tiny lock?!
            // This is an exercise of futility testing the limits of the API
            // TODO: Pester modder to encapsulate autoLockOnManualSwap in a method
            LongEventHandler.ExecuteWhenFinished(delegate {
                type = AccessTools.TypeByName("SimpleSidearms.rimworld.SwapControlsHandler");

                MP.RegisterSyncWorker <object>(SyncWorkerForSwapControlsHandler, type);

                autoLockOnManualSwapSyncField = MP.RegisterSyncField(type, "autoLockOnManualSwap");

                SwapControlsHandler_PawnProperty            = AccessTools.Property(type, "Owner");
                SwapControlsHandler_GetHandlerForPawnMethod = AccessTools.Method(type, "GetHandlerForPawn");

                type = AccessTools.TypeByName("SimpleSidearms.rimworld.Gizmo_SidearmsList");

                MpCompat.harmony.Patch(AccessTools.Method(type, "DrawLocklock"),
                                       prefix: new HarmonyMethod(typeof(SimpleSidearmsCompat), nameof(DrawLockPrefix)),
                                       postfix: new HarmonyMethod(typeof(SimpleSidearmsCompat), nameof(DrawLockPostfix)));
            });
        }
        public CommonSense(ModContentPack mod)
        {
            var type = AccessTools.TypeByName("CommonSense.CompUnloadChecker");

            // We need to make a sync worker for this Comp, as it is initialized dynamically and might not exists at the time
            MP.RegisterSyncWorker <ThingComp>(SyncComp, type);
            shouldUnloadSyncField = MP.RegisterSyncField(AccessTools.Field(type, "ShouldUnload"));
            // The GetChecker method either gets an existing, or creates a new comp
            getCompUnlockerCheckerMethod = AccessTools.Method(type, "GetChecker");

            // Watch unload bool changes
            MpCompat.harmony.Patch(AccessTools.Method("CommonSense.Utility:DrawThingRow"),
                                   prefix: new HarmonyMethod(typeof(CommonSense), nameof(CommonSensePatchPrefix)),
                                   postfix: new HarmonyMethod(typeof(CommonSense), nameof(CommonSensePatchPostix)));

            // RNG Patch
            PatchingUtilities.PatchUnityRand("CommonSense.JobGiver_Wander_TryGiveJob_CommonSensePatch:Postfix", false);
        }
예제 #9
0
        public Pharmacist(ModContentPack mod)
        {
            var type  = AccessTools.TypeByName("Pharmacist.PharmacistSettings");
            var outer = type;

            setDefaultsMethod = AccessTools.MethodDelegate <SetDefaults>(AccessTools.Method(type, "SetDefaults"));
            medicalCareField  = AccessTools.StaticFieldRefAccess <object>(AccessTools.Field(type, "medicalCare"));

            type = AccessTools.Inner(outer, "MedicalCare");
            diseaseMarginField        = MP.RegisterSyncField(type, "_diseaseMargin");
            minorWoundsThresholdField = MP.RegisterSyncField(type, "_minorWoundsThreshold");
            diseaseThresholdField     = MP.RegisterSyncField(type, "_diseaseThreshold");
            MP.RegisterSyncWorker <object>(SyncMedicalCare, type);

            type = AccessTools.TypeByName("Pharmacist.MainTabWindow_Pharmacist");
            MpCompat.RegisterLambdaDelegate(type, "DrawCareSelectors", 0, 1, 2);
            MpCompat.harmony.Patch(AccessTools.Method(type, "DrawOptions"),
                                   prefix: new HarmonyMethod(typeof(Pharmacist), nameof(PreDrawOptions)),
                                   postfix: new HarmonyMethod(typeof(Pharmacist), nameof(PostDrawOptions)));
        }
예제 #10
0
 // Token: 0x06000089 RID: 137 RVA: 0x00007314 File Offset: 0x00005514
 static MultiplayerSupport()
 {
     if (!MP.enabled)
     {
         return;
     }
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainMinor", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainSerious", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainIntense", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainExtreme", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainMinorNone", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainSeriousNone", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainIntenseNone", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetPainExtremeNone", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetMalady", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetMaladyDrug", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetMaladyDrugNone", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetMaladySet", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "ClearMaladyOne", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "ClearMaladyAll", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetUsePR", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetUseDR", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetDoPrisoners", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetDoDRPrisoners", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetShowNPR", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetShowNDR", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetUseNM", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetShowR", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetBillsHPain", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetDoIfImm", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetUseRB", null);
     MP.RegisterSyncMethod(typeof(MainTabWindow_DrugResponse), "SetUseDB", null);
     MP.RegisterSyncWorker <DRSettings>(new SyncWorkerDelegate <DRSettings>(MultiplayerSupport.SyncWriterForDRSettings), null, false, false);
     MultiplayerSupport.DRSettingsFields = new ISyncField[]
     {
         MP.RegisterSyncField(typeof(DRSettings), "DRWaitPeriod").SetBufferChanges(),
         MP.RegisterSyncField(typeof(DRSettings), "DRWaitPeriod2").SetBufferChanges(),
         MP.RegisterSyncField(typeof(DRSettings), "PainReliefWaitPeriod").SetBufferChanges()
     };
     MultiplayerSupport.harmony.Patch(AccessTools.Method(typeof(MainTabWindow_DrugResponse), "DoWindowContents", null, null), new HarmonyMethod(typeof(MultiplayerSupport), "WatchBegin", null), new HarmonyMethod(typeof(MultiplayerSupport), "WatchEnd", null), null, null);
 }
        public SRTSExpanded(ModContentPack mod)
        {
            LongEventHandler.ExecuteWhenFinished(DelayedPatch);

            // Refuel shuttle
            MP.RegisterSyncDelegate(AccessTools.TypeByName("SRTS.StartUp"), "<>c__DisplayClass24_1", "<LaunchAndBombGizmosPassthrough>b__3");

            // Bombing
            MP.RegisterSyncWorker <Pair <IntVec3, IntVec3> >(SyncIntVec3Pair, typeof(Pair <IntVec3, IntVec3>));
            var type = AccessTools.TypeByName("SRTS.CompBombFlyer");

            MP.RegisterSyncMethod(type, "TryLaunchBombRun");
            bombTypeSync = MP.RegisterSyncField(type, "bombType");

            foreach (MethodInfo method in MpCompat.MethodsByIndex(type, "<CompGetGizmosExtra>", 1, 2))
            {
                MpCompat.harmony.Patch(method,
                                       prefix: new HarmonyMethod(typeof(SRTSExpanded), nameof(PreSyncBombType)),
                                       postfix: new HarmonyMethod(typeof(SRTSExpanded), nameof(PostSyncBombType)));
            }
        }
예제 #12
0
        static Multiplayer()
        {
            if (!MP.enabled)
            {
                return;
            }

            // CompGuest
            guestFields = new [] {
                MP.RegisterSyncField(typeof(CompGuest), "guestArea_int").SetBufferChanges(),
                MP.RegisterSyncField(typeof(CompGuest), "shoppingArea_int").SetBufferChanges(),
                MP.RegisterSyncField(typeof(CompGuest), nameof(CompGuest.makeFriends)),
                MP.RegisterSyncField(typeof(CompGuest), nameof(CompGuest.entertain)),
                MP.RegisterSyncField(typeof(CompGuest), nameof(CompGuest.sentAway)),
            };

            // Hospitality_MapComponent
            mapFields = new [] {
                MP.RegisterSyncField(typeof(Hospitality_MapComponent), nameof(Hospitality_MapComponent.defaultMakeFriends)),
                MP.RegisterSyncField(typeof(Hospitality_MapComponent), nameof(Hospitality_MapComponent.defaultEntertain)),
                MP.RegisterSyncField(typeof(Hospitality_MapComponent), nameof(Hospitality_MapComponent.guestsAreWelcome)),
                MP.RegisterSyncField(typeof(Hospitality_MapComponent), nameof(Hospitality_MapComponent.defaultAreaRestriction)).SetBufferChanges(),
                MP.RegisterSyncField(typeof(Hospitality_MapComponent), nameof(Hospitality_MapComponent.defaultAreaShopping)).SetBufferChanges(),
                MP.RegisterSyncField(typeof(Hospitality_MapComponent), nameof(Hospitality_MapComponent.refuseGuestsUntilWeHaveBeds)),
            };

            // Guest ITab
            {
                MP.RegisterSyncMethod(AccessTools.Method(typeof(ITab_Pawn_Guest), nameof(ITab_Pawn_Guest.SendHome)));
                MP.RegisterSyncMethod(AccessTools.Method(typeof(GuestUtility), nameof(GuestUtility.Recruit)));
                MP.RegisterSyncMethod(AccessTools.Method(typeof(ITab_Pawn_Guest), nameof(ITab_Pawn_Guest.SetAllDefaults)));
            }

            // Beds
            {
                MP.RegisterSyncMethod(AccessTools.Method(typeof(Building_GuestBed), nameof(Building_GuestBed.Swap)));
                MP.RegisterSyncMethod(AccessTools.Method(typeof(Building_GuestBed), nameof(Building_GuestBed.AdjustFee)));
            }
        }
예제 #13
0
        public CorruptionCore(ModContentPack mod)
        {
            // ITab_Pawn_Soul - checkboxes to allow praying and show prayers
            var type = AccessTools.TypeByName("Corruption.Core.Soul.ITab_Pawn_Soul");

            pawnSoulITabSoulToShowGetter = MethodInvoker.GetHandler(AccessTools.PropertyGetter(type, "SoulToShow"));
            MP.RegisterSyncMethod(typeof(CorruptionCore), nameof(SyncFavourValue));
            MpCompat.harmony.Patch(AccessTools.Method(type, "FillTab"),
                                   prefix: new HarmonyMethod(typeof(CorruptionCore), nameof(PreFillTab)),
                                   postfix: new HarmonyMethod(typeof(CorruptionCore), nameof(PostFillTab)));

            type = AccessTools.TypeByName("Corruption.Core.Soul.CompSoul");
            compSoulFavourTrackerField = AccessTools.FieldRefAccess <object>(type, "FavourTracker");
            compSoulPrayerTrackerField = AccessTools.FieldRefAccess <object>(type, "PrayerTracker");

            type = AccessTools.TypeByName("Corruption.Core.Dialog_SetPawnPantheon");
            setPawnPantheonDialogConstructor = AccessTools.DeclaredConstructor(type);
            setPawnPantheonDialogSoulField   = AccessTools.FieldRefAccess <ThingComp>(type, "soul");
            MP.RegisterSyncMethod(type, "SelectionChanged");
            MP.RegisterSyncWorker <object>(SyncDialogSetPawnPantheon, type);

            type = AccessTools.TypeByName("Corruption.Core.Soul.Soul_FavourTracker");
            soulFavourTrackerFavoursField = AccessTools.FieldRefAccess <IList>(type, "Favours");

            type = AccessTools.TypeByName("Corruption.Core.Gods.Pawn_PrayerTracker");
            prayerTrackerCompSoulField    = AccessTools.FieldRefAccess <ThingComp>(type, "compSoul");
            prayerTrackerAllowPrayingSync = MP.RegisterSyncField(type, "AllowPraying");
            prayerTrackerShowPrayerSync   = MP.RegisterSyncField(type, "ShowPrayer");
            MP.RegisterSyncWorker <object>(SyncPawnPrayerTracker, type);
            MpCompat.harmony.Patch(AccessTools.Method(type, "AdvancePrayer"),
                                   prefix: new HarmonyMethod(typeof(CorruptionCore), nameof(PreAdvancePrayer)),
                                   postfix: new HarmonyMethod(typeof(CorruptionCore), nameof(PostAdvancePrayer)));

            type = AccessTools.TypeByName("Corruption.Core.Soul.FavourProgress");
            favourProgressFavourValueField = AccessTools.FieldRefAccess <float>(type, "favourValue");
        }
        public SimpleSidearmsCompat(ModContentPack mod)
        {
            Type type;

            // Gizmo interactions
            {
                type = AccessTools.TypeByName("PeteTimesSix.SimpleSidearms.Utilities.WeaponAssingment");

                var methods = new[] {
                    "equipSpecificWeaponTypeFromInventory",
                    "equipSpecificWeapon",
                    "dropSidearm",
                };
                foreach (string method in methods)
                {
                    MP.RegisterSyncMethod(AccessTools.Method(type, method));
                }
            }
            {
                type = AccessTools.TypeByName("SimpleSidearms.rimworld.CompSidearmMemory");

                var methods = new[] {
                    "SetWeaponAsForced",
                    "SetRangedWeaponTypeAsDefault",
                    "SetMeleeWeaponTypeAsPreferred",
                    "SetUnarmedAsForced",
                    "SetUnarmedAsPreferredMelee",
                    "UnsetForcedWeapon",
                    "UnsetRangedWeaponDefault",
                    "UnsetMeleeWeaponPreference",
                    "UnsetUnarmedAsForced",
                    "UnsetMeleeWeaponPreference",
                    "ForgetSidearmMemory",
                };
                foreach (string method in methods)
                {
                    MP.RegisterSyncMethod(AccessTools.Method(type, method));
                }

                // TODO: Suggest the author to encapsulate this, would simplify things so much
                primaryWeaponModeSyncField = MP.RegisterSyncField(AccessTools.Field(type, "primaryWeaponMode"));
            }
            // Required for primaryWeaponMode
            {
                type = AccessTools.TypeByName("SimpleSidearms.rimworld.Gizmo_SidearmsList");

                MpCompat.harmony.Patch(AccessTools.Method(type, "handleInteraction"),
                                       prefix: new HarmonyMethod(typeof(SimpleSidearmsCompat), nameof(HandleInteractionPrefix)),
                                       postfix: new HarmonyMethod(typeof(SimpleSidearmsCompat), nameof(HandleInteractionPostfix)));
            }
            {
                type = AccessTools.TypeByName("SimpleSidearms.rimworld.CompSidearmMemory");

                MpCompat.harmony.Patch(AccessTools.Method(type, "GetMemoryCompForPawn"),
                                       postfix: new HarmonyMethod(typeof(SimpleSidearmsCompat), nameof(CaptureTheMemory)));
            }
            // Used often in the Set* methods for CompSidearmMemory
            {
                type = AccessTools.TypeByName("SimpleSidearms.rimworld.ThingDefStuffDefPair");

                MP.RegisterSyncWorker <object>(SyncWorkerForThingDefStuffDefPair, type);
            }
        }
예제 #15
0
        static void LateLoad()
        {
            Type type;

            // Bed Gizmo
            {
                MP.RegisterSyncMethod(AccessTools.Method("Hospitality.Building_GuestBed:Swap"));
            }

            // Guest MainTab
            {
                MP.RegisterSyncMethod(AccessTools.Method("Hospitality.MainTab.PawnColumnWorker_AccommodationArea:SetArea"));
                MP.RegisterSyncMethod(AccessTools.Method("Hospitality.MainTab.PawnColumnWorker_ShoppingArea:SetArea"));
                MP.RegisterSyncMethod(AccessTools.Method("Hospitality.MainTab.PawnColumnWorker_Entertain:SetValue"));
                MP.RegisterSyncMethod(AccessTools.Method("Hospitality.MainTab.PawnColumnWorker_Recruit:SetValue"));
            }

            // Guest Tab
            {
                // force recruit button
                MP.RegisterSyncMethod(AccessTools.Method("Hospitality.GuestUtility:ForceRecruit"));
            }
            {
                type = AccessTools.TypeByName("Hospitality.ITab_Pawn_Guest");

                // send home button
                MP.RegisterSyncMethod(AccessTools.Method(type, "SendHome"));
            }
            {
                // field watching as Tab shows
                MpCompat.harmony.Patch(AccessTools.Method(type, "FillTabGuest"),
                                       prefix: new HarmonyMethod(typeof(HospitalityCompat), nameof(WatchPrefix)),
                                       postfix: new HarmonyMethod(typeof(HospitalityCompat), nameof(WatchPostfix))
                                       );
            }
            {
                // Individual Guest
                type = AccessTools.TypeByName("Hospitality.CompGuest");

                _chat     = MP.RegisterSyncField(type, "chat");
                _recruit  = MP.RegisterSyncField(type, "recruit");
                _arrived  = MP.RegisterSyncField(type, "arrived");
                _sentAway = MP.RegisterSyncField(type, "sentAway");

                _areaGuest = MP.RegisterSyncField(type, "guestArea_int").SetBufferChanges();
                _areaShop  = MP.RegisterSyncField(type, "shoppingArea_int").SetBufferChanges();

                GetCompMethod = AccessTools.Method("Verse.ThingWithComps:GetComp").MakeGenericMethod(type);

                MP.RegisterSyncWorker <ThingComp>(SyncWorkerForCompGuest, type);
            }
            {
                // Stops infinite recursion bug, seems to be outdated and unnecesary code in Hospitality.
                // Should report to author.
                MpCompat.harmony.Patch(AccessTools.Method("Hospitality.GenericUtility:DoAreaRestriction"),
                                       transpiler: new HarmonyMethod(typeof(HospitalityCompat), nameof(StopRecursiveCall))
                                       );
            }
            {
                // Default preferences
                type = AccessTools.TypeByName("Hospitality.Hospitality_MapComponent");

                _defMode      = MP.RegisterSyncField(type, "defaultInteractionMode");
                _defAreaGuest = MP.RegisterSyncField(type, "defaultAreaRestriction");
                _defAreaShop  = MP.RegisterSyncField(type, "defaultAreaShopping");

                GetMapCompMethod = AccessTools.Method(type, "Instance");

                MP.RegisterSyncWorker <MapComponent>(SyncWorkerForMapComp, type);
            }
        }
        // Things we don't sync as they're unfinished, and seem to not be implemented yet:
        // Dialog_StartRitual, which is created from BuildingSacrificialAltar

        public CorruptionWorship(ModContentPack mod)
        {
            // BuildingAltar
            {
                var type = AccessTools.TypeByName("Corruption.Worship.BuildingAltar");
                altarNameSyncField        = MP.RegisterSyncField(type, "RoomName");
                altarSermonTemplatesField = AccessTools.FieldRefAccess <IList>(type, "Templates");
                altarEndSermonMethod      = MethodInvoker.GetHandler(AccessTools.Method(type, "EndSermon"));
                altarTryStartSermonMethod = MethodInvoker.GetHandler(AccessTools.Method(type, "TryStartSermon"));

                // The class representing a sermon, with all the required data
                type = AccessTools.TypeByName("Corruption.Worship.SermonTemplate");
                sermonTemplateNameField = AccessTools.FieldRefAccess <string>(type, "Name");
                sermonTemplatePreferredStartTimeField  = AccessTools.FieldRefAccess <int>(type, "preferredStartTime");
                sermonTemplateSermonDurationHoursField = AccessTools.FieldRefAccess <float>(type, "SermonDurationHours");
                sermonTemplateActiveField = AccessTools.FieldRefAccess <bool>(type, "Active");

                // Dialog for renaming the altar, created from TempleCardUtility
                type = AccessTools.TypeByName("Corruption.Worship.Dialog_RenameTemple");
                MP.RegisterSyncMethod(typeof(CorruptionWorship), nameof(SyncSermonName));
                MpCompat.harmony.Patch(AccessTools.Method(type, nameof(Window.DoWindowContents)),
                                       prefix: new HarmonyMethod(typeof(CorruptionWorship), nameof(RenameTemplePrefix)),
                                       postfix: new HarmonyMethod(typeof(CorruptionWorship), nameof(RenameTemplePostfix)));

                // Dialog for renaming a specific sermon, created from TempleCardUtility
                type = AccessTools.TypeByName("Corruption.Worship.Dialog_RenameSermon");
                MpCompat.harmony.Patch(AccessTools.Method(type, "DoWindowContents"),
                                       prefix: new HarmonyMethod(typeof(CorruptionWorship), nameof(RenameSermonPrefix)),
                                       postfix: new HarmonyMethod(typeof(CorruptionWorship), nameof(RenameSermonPostfix)));

                // Dialog used for assigning a preacher, created from TempleCardUtility
                assignPreacherType        = AccessTools.TypeByName("Corruption.Worship.Dialog_AssignPreacher");
                assignPreacherAltarField  = AccessTools.FieldRefAccess <Building>(assignPreacherType, "altar");
                assignPreacherSermonField = AccessTools.FieldRefAccess <object>(assignPreacherType, "sermon");
                MP.RegisterSyncMethod(assignPreacherType, "AssignPawn");
                MP.RegisterSyncMethod(assignPreacherType, "UnassignPawn");
                MP.RegisterSyncWorker <Window>(SyncDialogAssignPreacher, assignPreacherType);

                // Dialog used for assigning a preacher, you guessed it, created from TempleCardUtility
                // This is a subclass of Dialog_AssignPreacher
                assignAssistantType = AccessTools.TypeByName("Corruption.Worship.Dialog_AssignAssistant");
                MP.RegisterSyncMethod(assignAssistantType, "AssignPawn");
                MP.RegisterSyncMethod(assignAssistantType, "UnassignPawn");
                MP.RegisterSyncWorker <Window>(SyncDialogAssignPreacher, assignAssistantType);
            }

            // MainTabWindow_Worship
            {
                // WonderWorker, does the work to execute the wonder defined in the MainTabWindow_Worship
                var wonderWorkerType           = AccessTools.TypeByName("Corruption.Worship.Wonders.WonderWorker");
                var wonderWorkerTargetableType = AccessTools.TypeByName("Corruption.Worship.Wonders.WonderWorker_Targetable");
                wonderWorkerDefField = AccessTools.FieldRefAccess <Def>(wonderWorkerType, "Def");
                wonderWorkerTargetableTargetField   = AccessTools.FieldRefAccess <TargetInfo>(wonderWorkerTargetableType, "target");
                wonderWorkerTargetableCanceledField = AccessTools.FieldRefAccess <bool>(wonderWorkerTargetableType, "cancelled");
                MP.RegisterSyncWorker <object>(SyncWonderWorker, wonderWorkerType, isImplicit: true);
                MP.RegisterSyncWorker <object>(SyncWonderTargetableWorker, wonderWorkerTargetableType, isImplicit: true);
                MP.RegisterSyncMethod(wonderWorkerTargetableType, "StartTargeting");
                MP.RegisterSyncMethod(wonderWorkerTargetableType, "CheckCancelled");

                // Sync the method for each class inheriting from TryExecuteWonder
                // If we ever want to sync the base class too, include .Concat(type) there
                // But since all it does is returning false, we'll skip it
                // We also check if it's not a subtype of WonderWorker_Targetable, as it uses TryDoEffectOnTarget method for the reward
                // (and then we pray that there's not another class doing it in a special way)
                foreach (var subtype in wonderWorkerType.AllSubclasses().Where(x => !x.IsAssignableFrom(wonderWorkerTargetableType)))
                {
                    // Include types for maximum safety
                    var method = AccessTools.Method(subtype, "TryExecuteWonder", new[] { typeof(Def), typeof(int) });
                    if (method != null)
                    {
                        MP.RegisterSyncMethod(method);
                    }
                }

                var methods = MpMethodUtil.GetLambda(wonderWorkerTargetableType, "TryExecuteWonderInt", lambdaOrdinals: new[] { 0, 1 }).ToArray();
                wonderWorkerTargetableInnerBaseField = AccessTools.FieldRefAccess <object>(methods[0].DeclaringType, "<>4__this");
                MpCompat.harmony.Patch(methods[0],
                                       prefix: new HarmonyMethod(typeof(CorruptionWorship), nameof(PreStartTargetting)));
                MpCompat.harmony.Patch(methods[1],
                                       prefix: new HarmonyMethod(typeof(CorruptionWorship), nameof(PreCheckCancelled)));

                // WonderDef, all we want is the field storing the WonderWorker for sync worker
                var type = AccessTools.TypeByName("Corruption.Worship.Wonders.WonderDef");
                wonderDefWorkerIntField = AccessTools.FieldRefAccess <object>(type, "workerInt");

                var database = typeof(DefDatabase <>).MakeGenericType(new Type[] { type });
                getDefByShortHash = MethodInvoker.GetHandler(AccessTools.Method(database, "GetByShortHash"));

                // GlobalWorshipTracker, we sync favor usage when the user decides to purchase a wonder
                type = AccessTools.TypeByName("Corruption.Worship.GlobalWorshipTracker");
                MP.RegisterSyncMethod(type, "ConsumeFavourFor");
            }

            LongEventHandler.ExecuteWhenFinished(LatePatch);
        }
예제 #17
0
        private static void LatePatch()
        {
            // Tables
            {
                var type = AccessTools.TypeByName("Gastronomy.Dining.CompCanDineAt");
                MP.RegisterSyncMethod(type, "ChangeDeco");
                MP.RegisterSyncMethod(type, "ToggleDining");
            }
            // Register menu
            {
                // ITab_Register
                var type = AccessTools.TypeByName("Gastronomy.TableTops.ITab_Register");
                hiddenSpecialThingFiltersMethod = AccessTools.Method(type, "HiddenSpecialThingFilters");
                MpCompat.harmony.Patch(
                    AccessTools.Method(type, "FillTab"),
                    prefix: new HarmonyMethod(typeof(Gastronomy), nameof(FillTabPrefix)),
                    postfix: new HarmonyMethod(typeof(Gastronomy), nameof(FillTabPostfix)));

                // Clear debt on cliking it
                MP.RegisterSyncDelegate(type, "<>c__DisplayClass18_0", "<DrawDebts>b__1").CancelIfAnyFieldNull().CancelIfNoSelectedObjects().SetContext(SyncContext.CurrentMap);

                // Sync worker for debt itself, requires SyncContext.CurrentMap
                type = AccessTools.TypeByName("Gastronomy.Restaurant.Debt");
                MP.RegisterSyncWorker <object>(SyncDebt, type);

                // RestaurantDebt, used for finding the debt
                type = AccessTools.TypeByName("Gastronomy.Restaurant.RestaurantDebt");
                restaurantDebtAllDebtsField = AccessTools.Field(type, "debts");

                // Building_CashRegister
                type = AccessTools.TypeByName("Gastronomy.TableTops.Building_CashRegister");
                restaurantControllerField = AccessTools.Field(type, "restaurant");

                // TimetableBool
                type = AccessTools.TypeByName("Gastronomy.Restaurant.Timetable.TimetableBool");
                timetableTimesField = AccessTools.Field(type, "times");

                // RestaurantMenu
                type                       = AccessTools.TypeByName("Gastronomy.Restaurant.RestaurantMenu");
                menuFilterField            = AccessTools.Field(type, "menuFilter");
                menuGlobalFilterField      = AccessTools.Field(type, "menuGlobalFilter");
                initMenuFilterMethod       = AccessTools.Method(type, "InitMenuFilter");
                initMenuGlobalFilterMethod = AccessTools.Method(type, "InitMenuGlobalFilter");
                MpCompat.harmony.Patch(
                    AccessTools.Constructor(type),
                    prefix: new HarmonyMethod(typeof(Gastronomy), nameof(RestaurantMenuConstructorPrefix)));

                // RestaurantController
                restaurantControllerType = AccessTools.TypeByName("Gastronomy.RestaurantController");
                controllerFieldsToSync   = (new[] { "openForBusiness", "allowGuests", "allowColonists", "allowPrisoners", "guestPricePercentage" }).Select(x => MP.RegisterSyncField(restaurantControllerType, x)).ToArray();
                controllerTimetableField = AccessTools.Field(restaurantControllerType, "timetableOpen");
                controllerMenuField      = AccessTools.Field(restaurantControllerType, "menu");
                controllerTimesSync      = MP.RegisterSyncField(restaurantControllerType, "timetableOpen/times").SetBufferChanges();
                controllerDebtField      = AccessTools.Field(restaurantControllerType, "debts");
            }
            // MP overrides
            {
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Multiplayer.cs#L58
                shouldSyncGetter = AccessTools.PropertyGetter(AccessTools.TypeByName("Multiplayer.Client.Multiplayer"), "ShouldSync");
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncHandlers.cs#L771
                allowCategoryHelperMethod = AccessTools.Method(AccessTools.TypeByName("Multiplayer.Client.SyncThingFilters"), "ThingFilter_AllowCategory_Helper");

                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncSerialization.cs#L33
                // We get the thingFilterTarget, and add our own filter to it
                var thingFilterTarget = AccessTools.Field(AccessTools.TypeByName("Multiplayer.Client.Sync"), "thingFilterTarget");
                var target            = thingFilterTarget.GetValue(null);

                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/Sync.cs#L1243
                // Get and call the method to add our filter
                AccessTools.Method(AccessTools.TypeByName("Multiplayer.Client.MultiTarget"), "Add", new Type[] { typeof(Type), typeof(string) })
                .Invoke(target, new object[] { restaurantControllerType, "menu/menuFilter" });

                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncHandlers.cs#L960
                MpCompat.harmony.Patch(AccessTools.PropertyGetter(AccessTools.TypeByName("Multiplayer.Client.SyncMarkers"), "ThingFilterOwner"),
                                       prefix: new HarmonyMethod(typeof(Gastronomy), nameof(ThingFilterOwnerPrefix)));

                // Set prefixes to the 3 methods that need some additional work that isn't universal to all filters
                // (See the methods for github links)
                MpCompat.harmony.Patch(AccessTools.Method(typeof(ThingFilter), nameof(ThingFilter.SetAllow), new[] { typeof(ThingCategoryDef), typeof(bool), typeof(IEnumerable <ThingDef>), typeof(IEnumerable <SpecialThingFilterDef>) }),
                                       prefix: new HarmonyMethod(typeof(Gastronomy), nameof(ThingFilter_SetAllowPrefix)));
                MpCompat.harmony.Patch(AccessTools.Method(typeof(ThingFilter), nameof(ThingFilter.SetDisallowAll)),
                                       prefix: new HarmonyMethod(typeof(Gastronomy), nameof(ThingFilter_SetDisallowAllPrefix)));
                MpCompat.harmony.Patch(AccessTools.Method(typeof(ThingFilter), nameof(ThingFilter.SetAllowAll)),
                                       prefix: new HarmonyMethod(typeof(Gastronomy), nameof(ThingFilter_SetAllowAllPrefix)));

                // Methods that we'll need to setup SyncFields/SyncMethods for MultiTarget
                var type = AccessTools.TypeByName("Multiplayer.Client.Sync");
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/Sync.cs#L801
                var methodMultiTarget = AccessTools.Method(type, "MethodMultiTarget");
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/Sync.cs#L818
                var fieldMultiTarget = AccessTools.Method(type, "FieldMultiTarget");

                // Create fields for SyncFields that will include our filter
                type = AccessTools.TypeByName("Multiplayer.Client.SyncFieldsPatches");
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncHandlers.cs#L66
                var values = (Array)fieldMultiTarget.Invoke(null, new[] { target, nameof(ThingFilter.AllowedHitPointsPercents) });
                foreach (var value in values)
                {
                    ((ISyncField)value).SetBufferChanges();
                }
                AccessTools.Field(type, "SyncThingFilterHitPoints").SetValue(null, values);
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncHandlers.cs#L69
                values = (Array)fieldMultiTarget.Invoke(null, new[] { target, nameof(ThingFilter.AllowedQualityLevels) });
                foreach (var value in values)
                {
                    ((ISyncField)value).SetBufferChanges();
                }
                AccessTools.Field(type, "SyncThingFilterQuality").SetValue(null, values);

                // Create fields for SyncMethods that will include our filter
                type = AccessTools.TypeByName("Multiplayer.Client.SyncThingFilters");
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncHandlers.cs#L658
                AccessTools.Field(type, "SyncThingFilterAllowThing").SetValue(null, methodMultiTarget.Invoke(null, new[] { target, nameof(ThingFilter.SetAllow), new SyncType[] { typeof(ThingDef), typeof(bool) } }));
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncHandlers.cs#L659
                AccessTools.Field(type, "SyncThingFilterAllowSpecial").SetValue(null, methodMultiTarget.Invoke(null, new[] { target, nameof(ThingFilter.SetAllow), new SyncType[] { typeof(SpecialThingFilterDef), typeof(bool) } }));
                // https://github.com/rwmt/Multiplayer/blob/7aac8b54727d8626ec39429b97225fc88c807ab8/Source/Client/Sync/SyncHandlers.cs#L660
                AccessTools.Field(type, "SyncThingFilterAllowStuffCategory").SetValue(null, methodMultiTarget.Invoke(null, new[] { target, nameof(ThingFilter.SetAllow), new SyncType[] { typeof(StuffCategoryDef), typeof(bool) } }));

                // Sync our helper methods
                // (See the methods for github links)
                MP.RegisterSyncMethod(typeof(Gastronomy), nameof(ThingFilter_DisallowAll_HelperRestaurant));
                MP.RegisterSyncMethod(typeof(Gastronomy), nameof(ThingFilter_AllowAll_HelperRestaurant));
                MP.RegisterSyncMethod(typeof(Gastronomy), nameof(ThingFilter_AllowCategory_HelperRestaurant));
            }
        }