private void BossGroup_DropRewards(MonoMod.Cil.ILContext il) { ILCursor c = new ILCursor(il); c.GotoNext( x => x.MatchStloc(5), x => x.MatchLdcI4(0), x => x.MatchStloc(6) ); c.Index += 2; c.Emit(OpCodes.Ldarg_0); //self c.Emit(OpCodes.Ldloc_2); //PickupIndex c.Emit(OpCodes.Ldloc, 4); //vector c.Emit(OpCodes.Ldloc, 5); //rotation c.Emit(OpCodes.Ldloc, 3); //scaledRewardCount c.EmitDelegate <Func <int, BossGroup, PickupIndex, Vector3, Quaternion, int, int> >((val, self, pickupIndex, vector, rotation, scaledRewardCount) => { if (self && !self.GetComponent <DelayedBossRewards>()) { var component = self.gameObject.AddComponent <DelayedBossRewards>(); component.rng = self.rng; component.num = scaledRewardCount; component.pickupIndex = pickupIndex; component.bossDrops = self.bossDrops; component.bossDropChance = self.bossDropChance; component.dropPosition = self.dropPosition; component.vector = vector; component.rotation = rotation; } return(int.MaxValue); //Prevent vanilla code from being run }); }
private void RemoveTransitionWaits(MonoMod.Cil.ILContext il) { ILCursor c = new ILCursor(il).Goto(0); while (c.TryGotoNext( i => i.OpCode == OpCodes.Ldc_R4, i => i.OpCode == OpCodes.Newobj && i.MatchNewobj <WaitForSeconds>() )) { if ((float)c.Instrs[c.Index].Operand == .4f) { c.Remove(); c.Emit(OpCodes.Ldc_R4, 0f); c.Index += 2; } else if ((float)c.Instrs[c.Index].Operand == .165f) { c.Remove(); c.Emit(OpCodes.Ldc_R4, 0f); c.Index += 2; } else if ((float)c.Instrs[c.Index].Operand == .25f || (float)c.Instrs[c.Index].Operand == .33f) { c.Index += 2; } } }
private void NPC_MechSpawn(MonoMod.Cil.ILContext il) { var c = new ILCursor(il); if (!c.TryGotoNext(i => i.MatchLdcI4(3))) { return; // Patch unable to be applied } c.Index++; c.EmitDelegate <Func <int, int> >((nearLimit) => { return((int)(nearLimit * mechTweakerConfig.NPCLimitMultiplier)); }); c.GotoNext(i => i.MatchLdcI4(6)); c.Index++; c.EmitDelegate <Func <int, int> >((farLimit) => { return((int)(farLimit * mechTweakerConfig.NPCLimitMultiplier)); }); c.GotoNext(i => i.MatchLdcI4(10)); c.Index++; c.EmitDelegate <Func <int, int> >((totalLimit) => { return((int)(totalLimit * mechTweakerConfig.NPCLimitMultiplier)); }); }
private void DotController_AddDot(MonoMod.Cil.ILContext il) { ILCursor c = new ILCursor(il); ILLabel[] labels = new ILLabel[3]; c.GotoNext(MoveType.After, x => x.MatchSwitch(out labels)); if (labels.Length < 3 || labels[2] == null) { return; } c.GotoLabel(labels[2], MoveType.Before); c.GotoNext(MoveType.After, x => x.MatchLdarg(0)); var index1 = c.Index + 1; ILLabel label = labels[0]; c.GotoNext(MoveType.Before, x => x.MatchBr(out label)); //var index1 = c.Index - 4; if (label == labels[0]) { return; } c.GotoLabel(label, MoveType.After); c.GotoNext(MoveType.After, x => x.MatchBlt(out _)); c.Index += 0; Int32 dist = c.Index - index1; c.Index = index1; c.RemoveRange(dist); c.Emit(OpCodes.Ldloc, 5); c.EmitDelegate <Action <HealthComponent, object> >((victim, stack) => { if (stack == null) { return; } var stackTemp = Convert.ChangeType(stack, dotStack); var dotDefTemp = Convert.ChangeType(dotStack_dotDef.GetValue(stackTemp), dotDef); Single damage = (Single)dotStack_damage.GetValue(stackTemp); Single baseDamage = damage / (Single)dotDef_damageCoefficient.GetValue(dotDefTemp); var flatPortion = baseDamage * baseDamageMult; var maxHpPortion = Mathf.Min(victim.fullCombinedHealth * percentHealthMult, flatPortion * percentRatioCap); dotStack_damage.SetValue(stackTemp, (object)((maxHpPortion + flatPortion) * (Single)dotDef_interval.GetValue(dotDefTemp))); dotStack_damageType.SetValue(stackTemp, (object)(DamageType.NonLethal)); }); }
//void Update() //{ // if(isAnimating) // { // foreach(MultiShop shop in MultiShop.instances) // { // AnimateShop(shop); // } // } //} // Sadly can't get the animation to work on client with Multi Shops for some reason. Chests work, but even their movement is very stuttery on the client ¯\_(ツ)_/¯ I don't know anything about unity //private void AnimateShop(MultiShop shop) //{ // if (shop.multiShopController.gameObject.transform.position == shop.endPosition) // { // isAnimating = false; // } // else // { // shop.multiShopController.gameObject.transform.position = Vector3.MoveTowards(shop.multiShopController.gameObject.transform.position, shop.endPosition, MultiShop.movementSpeed * Time.deltaTime); // foreach (PurchaseInteraction terminal in shop.terminalPurchaseInteractions) // { // terminal.gameObject.transform.position = Vector3.MoveTowards(terminal.gameObject.transform.position, new Vector3(terminal.gameObject.transform.position.x, shop.endPosition.y + MultiShop.terminalOffset, terminal.gameObject.transform.position.z), MultiShop.movementSpeed * Time.deltaTime); // } // } //} private void MultiShopController_Start(MonoMod.Cil.ILContext il) { ILCursor c = new ILCursor(il); c.GotoNext( x => x.MatchLdarg(0), x => x.MatchLdfld <MultiShopController>("baseCost") ); c.Index -= 2; c.RemoveRange(6); }
private void CharacterBody_RecalculateStats(MonoMod.Cil.ILContext il) { var c = new ILCursor(il); c.GotoNext(x => x.MatchLdloc(17)); c.GotoNext(x => x.MatchLdloc(17)); c.Index--; c.Index--; c.RemoveRange(2); c.Emit(OpCodes.Ldc_R4, EnergyDrinkBoost.Value); c.Emit(OpCodes.Ldc_R4, EnergyDrinkCoefficient.Value); }
private void BulletAttack_DefaultHitCallback(MonoMod.Cil.ILContext il) { var c = new ILCursor(il); c.GotoNext( x => x.MatchLdcR4(0.5f), //I know this could be more robust but for now this works... x => x.MatchLdcR4(60f), x => x.MatchLdcR4(25f) ); c.Index++; c.RemoveRange(2); c.Emit(OpCodes.Ldc_R4, FallOffEndDistance.Value); c.Emit(OpCodes.Ldc_R4, FallOffStartDistance.Value); }
private void WeeklyRun_ClientSubmitLeaderboardScore(MonoMod.Cil.ILContext il) { ILCursor c = new ILCursor(il); c.GotoNext(MoveType.After, x => x.MatchCall <String>(nameof(String.IsNullOrEmpty))); c.Emit(OpCodes.Ldarg_1); c.Emit(OpCodes.Ldarg_0); c.EmitDelegate <Func <RunReport, WeeklyRun, Boolean> >((report, run) => { SaveFile(report, run); return(true); }); c.Emit(OpCodes.Or); c.GotoNext(MoveType.After, x => x.MatchCall <UnityEngine.Object>("op_Implicit")); c.EmitDelegate <Func <Boolean> >(() => !RoR2Application.isModded); c.Emit(OpCodes.And); }
private void Skills_RaiseSkill(MonoMod.Cil.ILContext il) { ILCursor c = new ILCursor(il); c.GotoNext(MoveType.After, zz => zz.MatchConstrained(out _), zz => zz.MatchCallOrCallvirt <System.Object>("ToString"), zz => zz.MatchCallOrCallvirt <System.String>("ToLower") ); c.EmitDelegate <Func <string, string> >((string skillID) => { var asd = Enum.TryParse <global::Skills.SkillType>(skillID, out var result); if (asd && Skills.ContainsKey(result)) { Jotunn.Logger.LogDebug($"Fixing Enum.ToString on {skillID}, match found: {Skills[result].Name}"); return(Skills[result].Name); } return(skillID); }); }
private static void RecalculateStats_Il(MonoMod.Cil.ILContext il) => new ILCursor(il) .GotoNext(MoveType.After, x => x.MatchLdarg(0), x => x.MatchCallOrCallvirt(out _), x => x.MatchLdcI4((Int32)ItemIndex.InvadingDoppelganger), x => x.MatchCallOrCallvirt(out _), x => x.MatchStloc(out dopLoc) ).GotoNext(MoveType.After, x => x.MatchLdloc(dopLoc), x => x.MatchLdcI4(0), x => x.MatchBle(out _), x => x.MatchLdloc(out _), x => x.MatchLdcR4(out _) ).CallDel_ <Func <Single, Single> >(CalcDoppelHealthMult) .GotoNext(MoveType.Before, x => x.MatchCallOrCallvirt(typeof(CharacterBody).GetProperty("maxHealth", BF.Public | BF.NonPublic | BF.Instance).GetSetMethod(true))) .LdArg_(0) .CallDel_ <Func <Single, CharacterBody, Single> >(IncreaseHealthIfMonster) .GotoNext(MoveType.After, x => x.MatchLdloc(dopLoc), x => x.MatchLdcI4(0), x => x.MatchBle(out _), x => x.MatchLdloc(out _), x => x.MatchLdcR4(out _) ).CallDel_ <Func <Single, Single> >(CalcDoppelDmgMult);
private void MeteorWave_GetNextMeteor(MonoMod.Cil.ILContext il) { var c = new ILCursor(il); c.GotoNext( x => x.MatchLdarg(0), x => x.MatchLdfld(out FieldReference fr1), x => x.MatchLdarg(0), x => x.MatchLdfld(out FieldReference fr2), x => x.MatchLdelemRef() ); c.GotoNext(x => x.MatchStloc(0)); c.EmitDelegate <Func <CharacterBody, CharacterBody> >((cb) => { if (PlayerToBePunished != null && PlayerToBePunished.healthComponent.alive) { return(PlayerToBePunished); } else { return(null); } }); }
private static void FindColor_Il(MonoMod.Cil.ILContext il) => new ILCursor(il) .GotoNext(MoveType.AfterLabel, x => x.MatchLdcI4((Int32)DamageColorIndex.Count)) .Remove() .LdSFld_(fieldRef);
internal ILLabel(ILContext context, Instruction target) : this(context) { Target = target; }
internal ILLabel(ILContext context) { Context = context; Context._Labels.Add(this); }