static public void Postfix(RuleSummonUnit __instance)
            {
                var context = __instance.Context;

                context = ShadowSpells.extractMainContext(context, context?.MaybeCaster);
                if (context == null)
                {
                    return;
                }

                var spell_reality = ShadowSpells.getSpellReality(context);
                var rounds        = __instance.Duration + __instance.BonusDuration;

                if (spell_reality == 20)
                {
                    __instance.SummonedUnit.Descriptor.AddBuff(ShadowSpells.shadow20_buff, __instance.Context, new TimeSpan?(rounds.Seconds));
                }
                else if (spell_reality == 60)
                {
                    __instance.SummonedUnit.Descriptor.AddBuff(ShadowSpells.shadow60_buff, __instance.Context, new TimeSpan?(rounds.Seconds));
                }
                else if (spell_reality == 80)
                {
                    __instance.SummonedUnit.Descriptor.AddBuff(ShadowSpells.shadow80_buff, __instance.Context, new TimeSpan?(rounds.Seconds));
                }
            }
            static public bool Prefix(ContextActionKnockdownTarget __instance)
            {
                var context = ElementsContext.GetData <MechanicsContext.Data>()?.Context;

                if (context == null)
                {
                    return(true);
                }
                if (context?.AssociatedBlueprint is BlueprintBuff)
                {
                    return(true);
                }

                var unit = ElementsContext.GetData <MechanicsContext.Data>()?.CurrentTarget?.Unit;

                if (unit == null)
                {
                    return(true);
                }
                context = ShadowSpells.extractMainContext(context, context?.MaybeCaster);
                if (context == null)
                {
                    return(true);
                }
                if (!unit.Ensure <UnitPartDisbelief>().attemptedDisbelief(context))
                {
                    if (unit.Descriptor.State.HasCondition(UnitCondition.TrueSeeing))
                    {
                        unit.Ensure <UnitPartDisbelief>().register(context, true);
                    }
                    else
                    {
                        unit.Ensure <UnitPartDisbelief>().register(context, ShadowSpells.makeDisbeliefSave(context, unit));
                    }
                }

                if (unit.Ensure <UnitPartDisbelief>().disbelieved(context))
                {
                    int illusion_reality = ShadowSpells.getSpellReality(context);
                    int result           = RulebookEvent.Dice.D(new DiceFormula(1, DiceType.D100));
                    if (illusion_reality > 0 && result > illusion_reality)
                    {
                        Common.AddBattleLogMessage(unit.CharacterName + " avoids " + context.SourceAbility.Name
                                                   + $" effect due to disbelief (rolled {result} vs {illusion_reality}%)");
                        return(false);
                    }
                }

                return(true);
            }
            static public bool Prefix(RuleHealDamage __instance, RulebookEventContext context)
            {
                if (__instance.Target == null)
                {
                    return(true);
                }

                var context2 = __instance.Reason.Context;

                if (context2?.AssociatedBlueprint != null && context2.AssociatedBlueprint is BlueprintBuff)
                {//do not apply shadow twice
                    return(true);
                }
                context2 = ShadowSpells.extractMainContext(context2, __instance.Initiator);
                if (context2 == null)
                {
                    return(true);
                }

                if (!__instance.Target.Ensure <UnitPartDisbelief>().attemptedDisbelief(context2))
                {
                    if (__instance.Target.Descriptor.State.HasCondition(UnitCondition.TrueSeeing))
                    {
                        __instance.Target.Ensure <UnitPartDisbelief>().register(context2, true);
                    }
                    else
                    {
                        __instance.Target.Ensure <UnitPartDisbelief>().register(context2, ShadowSpells.makeDisbeliefSave(context2, __instance.Target));
                    }
                }

                if (__instance.Target.Ensure <UnitPartDisbelief>().disbelieved(context2))
                {
                    int illusion_reality = ShadowSpells.getSpellReality(context2);

                    if (illusion_reality > 0)
                    {
                        __instance.Modifier = new float?((__instance.Modifier.HasValue ? __instance.Modifier.GetValueOrDefault() : 1f) * 0.01f * illusion_reality);
                        Common.AddBattleLogMessage(__instance.Target.CharacterName + " reduces healing from "
                                                   + context2.SourceAbility.Name + " to " + illusion_reality.ToString() + "% due to disbelief");
                    }
                }
                return(true);
            }
            static public bool Prefix(AreaEffectPit __instance, MechanicsContext context, AreaEffectEntityData areaEffect, UnitEntityData unit)
            {
                var source_context = context?.SourceAbilityContext;
                var context2       = ShadowSpells.extractMainContext(source_context, source_context?.MaybeCaster);

                if (context2 == null)
                {
                    return(true);
                }

                if (!unit.Ensure <UnitPartDisbelief>().attemptedDisbelief(context2))
                {
                    if (unit.Descriptor.State.HasCondition(UnitCondition.TrueSeeing))
                    {
                        unit.Ensure <UnitPartDisbelief>().register(context2, true);
                    }
                    else
                    {
                        unit.Ensure <UnitPartDisbelief>().register(context2, ShadowSpells.makeDisbeliefSave(context2, unit));
                    }
                }

                if (unit.Ensure <UnitPartDisbelief>().disbelieved(context2))
                {
                    int illusion_reality = ShadowSpells.getSpellReality(context2);
                    int result           = RulebookEvent.Dice.D(new DiceFormula(1, DiceType.D100));
                    if (illusion_reality > 0 && result > illusion_reality)
                    {
                        Common.AddBattleLogMessage(unit.CharacterName + " avoids " + context2.SourceAbility.Name
                                                   + $" effect due to disbelief (rolled {result} vs {illusion_reality}%)");
                        return(false);
                    }
                }

                return(true);
            }
            static public bool Prefix(RuleApplyBuff __instance, RulebookEventContext context)
            {
                if (__instance.Blueprint?.GetComponent <IgnoreShadowReality>() != null)
                {
                    return(true);
                }
                var rule_summon = Rulebook.CurrentContext.AllEvents.LastOfType <RuleSummonUnit>();

                if (rule_summon != null)
                {//do not interrupt summon buffs
                    return(true);
                }

                var context2 = __instance.Reason.Context;
                //there are also actions after summon that should not be affected
                //we need to check if we are still inside SpawnMonsterComponent
                var summon_context = __instance.Initiator.Buffs?.GetBuff(Game.Instance.BlueprintRoot.SystemMechanics.SummonedUnitBuff)?.MaybeContext?.ParentContext;

                if (summon_context == context2)
                {
                    return(true);
                }

                if (context2?.AssociatedBlueprint != null && context2.AssociatedBlueprint is BlueprintBuff)
                {//do not apply shadow twice
                    return(true);
                }

                context2 = ShadowSpells.extractMainContext(context2, context2?.MaybeCaster);
                if (context2 == null)
                {
                    return(true);
                }

                if (__instance.Initiator == null)
                {
                    return(true);
                }

                if (!__instance.Initiator.Ensure <UnitPartDisbelief>().attemptedDisbelief(context2))
                {
                    if (__instance.Initiator.Descriptor.State.HasCondition(UnitCondition.TrueSeeing))
                    {
                        __instance.Initiator.Ensure <UnitPartDisbelief>().register(context2, true);
                    }
                    else
                    {
                        __instance.Initiator.Ensure <UnitPartDisbelief>().register(context2, ShadowSpells.makeDisbeliefSave(context2, __instance.Initiator));
                    }
                }

                if (__instance.Initiator.Ensure <UnitPartDisbelief>().disbelieved(context2))
                {
                    int illusion_reality = ShadowSpells.getSpellReality(context2);
                    int result           = RulebookEvent.Dice.D(new DiceFormula(1, DiceType.D100));
                    if (illusion_reality > 0 && result > illusion_reality)
                    {
                        __instance.CanApply = false;
                        Common.AddBattleLogMessage(__instance.Initiator.CharacterName + " avoids " + context2.SourceAbility.Name
                                                   + $" effect due to disbelief (rolled {result} vs {illusion_reality}%)");
                        return(false);
                    }
                }

                return(true);
            }