using System; using SlugBase.Features; using static SlugBase.Features.FeatureTypes; using MonoMod.Cil; using Mono.Cecil.Cil; namespace JilloSlug.Features; internal static class ImmuneToDartMaggotsFeature { public static readonly PlayerFeature ImmuneToDartMaggots = PlayerBool("jillo/immune_to_dart_maggots"); public static void AddHooks() { IL.DartMaggot.Update += DartMaggot_Update; } private static bool DartMaggotCanStun(DartMaggot maggot) { if (maggot.stuckInChunk.owner is Player && ImmuneToDartMaggots.TryGet(maggot.stuckInChunk.owner as Player, out var immune) && immune) { return false; // skip } return true; // proceed as normal } private static void ILInsertHandleDartMaggotStun(ILCursor c, ILLabel skipLabel) { c.Emit(OpCodes.Ldarg_0); c.EmitDelegate>(maggot => { return DartMaggotCanStun(maggot); }); c.Emit(OpCodes.Brfalse, skipLabel); } private static void DartMaggot_Update(ILContext il) { ILCursor c = new ILCursor(il); // matching for `stuckInChunk.owner is Creature && ...` c.GotoNext(MoveType.After, i => i.MatchLdarg(0), i => i.MatchLdfld("stuckInChunk"), i => i.MatchCallOrCallvirt("get_owner"), i => i.MatchIsinst(), i => i.Match(OpCodes.Brfalse_S) ); // last instruction will be a brfalse.s; capture the label it goes to ILLabel skipLabel = c.Prev.Operand as ILLabel; // we're now ready to write another condition ILInsertHandleDartMaggotStun(c, skipLabel); // comments will be unrepeated; same functionality // matching for `stuckInChunk.owner is Player && ...` c.GotoNext(MoveType.After, i => i.MatchLdarg(0), i => i.MatchLdfld("stuckInChunk"), i => i.MatchCallOrCallvirt("get_owner"), i => i.MatchIsinst(), i => i.Match(OpCodes.Brfalse_S) ); skipLabel = c.Prev.Operand as ILLabel; ILInsertHandleDartMaggotStun(c, skipLabel); // matching for `stuckInChunk.owner is Creature` c.GotoNext(MoveType.After, i => i.MatchLdarg(0), i => i.MatchLdfld("stuckInChunk"), i => i.MatchCallOrCallvirt("get_owner"), i => i.MatchIsinst(), i => i.Match(OpCodes.Brfalse) // watch out! this one isn't _S ); skipLabel = c.Prev.Operand as ILLabel; ILInsertHandleDartMaggotStun(c, skipLabel); } }