RitualAttachableOutcomeEffectDef onlyPositiveOutcomes - Error Creating Ritual

Started by mikeejimbo, August 01, 2021, 04:51:09 PM

Previous topic - Next topic

mikeejimbo

So I found that you can flip that flag and run a RitualAttachableOutcomeEffect on any outcome, which is handy for giving an attachable effect a bad effect on a bad outcome. It was all working just fine when I loaded my game to test it out - the effects I was giving it on bad outcomes triggered on bad outcomes and the alternate effects for good outcomes on good outcomes.

However, when I tried to create a new game with a ritual and attach it to that, I get a crash with the following stack trace:

Root level exception in OnGUI(): System.NullReferenceException: Object reference not set to an instance of an object
  at Verse.ActiveTip.get_FinalText () [0x00044] in <f429400e900f434099af71800afbc07e>:0
  at Verse.ActiveTip.get_TipRect () [0x00000] in <f429400e900f434099af71800afbc07e>:0
  at Verse.TooltipHandler.CalculateInitialTipPosition (System.Collections.Generic.List`1[T] drawingTips) [0x00017] in <f429400e900f434099af71800afbc07e>:0
  at Verse.TooltipHandler.DrawActiveTips () [0x0008b] in <f429400e900f434099af71800afbc07e>:0
  at Verse.TooltipHandler.DoTooltipGUI () [0x00000] in <f429400e900f434099af71800afbc07e>:0
  at (wrapper dynamic-method) Verse.UIRoot.Verse.UIRoot.UIRootOnGUI_Patch1(Verse.UIRoot)
  at Verse.UIRoot_Entry.UIRootOnGUI () [0x00000] in <f429400e900f434099af71800afbc07e>:0
  at (wrapper dynamic-method) Verse.Root.Verse.Root.OnGUI_Patch1(Verse.Root)
(Filename: C:\buildslave\unity\build\Runtime/Export/Debug/Debug.bindings.h Line: 39)


Removing the onlyPositiveOutcomes flag from the XML def resolves the issue, but of course means my outcome will only run on positive outcomes (since it's true by default).

Can anyone think of any workarounds? One idea I had was to allow the player to specify the actual value of this in a modExtension of the RitulAttachableOutcomeEffectDef and then sometime after the Ideology is created, run through the DefDatabase to set the flag properly. That feels like kind of a hack, and besides, I'm not sure when/how I'd run that.

This is for a mod I've got on Steam right now, but I'm still working on: https://steamcommunity.com/sharedfiles/filedetails/?id=2561617361

The source code is included, so feel free to poke around.

mikeejimbo

I got it working by using a HarmonyPatch Prefix on ApplyAttachableOutcome to check the modExtensions of the RitualAttachableEffectDef's onlyPositiveOutcomes flag and update the RitualAttachableEffectDef's flag.

    [HarmonyPatch(typeof(RitualOutcomeEffectWorker_FromQuality))]
    [HarmonyPatch("ApplyAttachableOutcome")]
    public static class Patch_RitualOutcomeEffectWorker_FromQuality
    {
        public static void Prefix(Dictionary<Pawn, int> totalPresence, LordJob_Ritual jobRitual, OutcomeChance outcomeChance,  string extraLetterText, ref LookTargets letterLookTargets)
        {
            RitualAttachableOutcomeEffectDef_TP_Custom customRitualAttachableOutcomeEffect = jobRitual.Ritual.attachableOutcomeEffect.GetModExtension<RitualAttachableOutcomeEffectDef_TP_Custom>();
            if(customRitualAttachableOutcomeEffect != null)
            {
                jobRitual.Ritual.attachableOutcomeEffect.onlyPositiveOutcomes = customRitualAttachableOutcomeEffect.onlyPositiveOutcomes;
            }

            return;
        }
    }


But it still feels like a hack, and this is the only thing I'm using Harmony for so far so it seems like overkill. It also has the weird effect of the "Upon any positive outcome" when creating it being a lie.

RawCode

check DoPlayLoad for loading routine, mod class constructed before this, you can inject here or play with StaticConstructorOnStartup flag

mikeejimbo

Quote from: RawCode on August 02, 2021, 12:08:17 AM
check DoPlayLoad for loading routine, mod class constructed before this, you can inject here or play with StaticConstructorOnStartup flag

Sweet, thank you! That's exactly what I was looking for.