private static void ProcMissile(int stack, CharacterBody attackerBody, CharacterMaster attackerMaster, TeamIndex attackerTeamIndex, ProcChainMask procChainMask, GameObject victim, DamageInfo damageInfo) { if (stack > 0) { GameObject gameObject = attackerBody.gameObject; InputBankTest component = gameObject.GetComponent <InputBankTest>(); Vector3 position = component ? component.aimOrigin : gameObject.transform.position; Vector3 vector = component ? component.aimDirection : gameObject.transform.forward; Vector3 up = Vector3.up; if (Util.CheckRoll(10f * GNCProtoRocketConfig.GNCProtoRocketProcChance.Value, attackerMaster)) { float damageCoefficient = 2f * (float)stack; float damage = Util.OnHitProcDamage(damageInfo.damage, attackerBody.damage, damageCoefficient); ProcChainMask procChainMask2 = procChainMask; procChainMask2.AddProc(ProcType.Missile); FireProjectileInfo fireProjectileInfo = new FireProjectileInfo { projectilePrefab = GlobalEventManager.instance.daggerPrefab, position = position, rotation = Util.QuaternionSafeLookRotation(Vector3.up + Random.insideUnitSphere * 0.1f), procChainMask = procChainMask2, target = victim, owner = gameObject, damage = damage, crit = damageInfo.crit, force = 200f, damageColorIndex = DamageColorIndex.Item }; ProjectileManager.instance.FireProjectile(fireProjectileInfo); } } }
public static void SetProcValue(ProcChainMask chain, string ProcName, bool value) { if (ProcChainLinker.ContainsKey(chain)) { ProcChainLinker[chain].ChangeProcState(ProcName, value); } }
public MsgHealTargetAndSelf(HealthComponent target, HealthComponent self, float amount, ProcChainMask pcm) { _target = target; _self = self; _adjustedCount = amount; _pcm = pcm; }
private void ProcMissile(int mNum, CharacterBody attackerBody, ProcChainMask procChainMask, GameObject victim, DamageInfo damageInfo, int stack) { GameObject gameObject = attackerBody.gameObject; InputBankTest component = gameObject.GetComponent <InputBankTest>(); Vector3 position = component ? component.aimOrigin : gameObject.transform.position; float dmgCoef = dmgCoefficient + (dmgStack * stack); float damage = Util.OnHitProcDamage(damageInfo.damage, attackerBody.damage, dmgCoef); ProcChainMask procChainMask2 = procChainMask; procChainMask2.AddProc(ProcType.Missile); FireProjectileInfo fireProjectileInfo = new FireProjectileInfo { projectilePrefab = GlobalEventManager.instance.missilePrefab, position = position, rotation = Util.QuaternionSafeLookRotation(DetermineFacing(mNum)), procChainMask = procChainMask2, target = victim, owner = gameObject, damage = damage, crit = damageInfo.crit, force = 200f, damageColorIndex = DamageColorIndex.Item }; ProjectileManager.instance.FireProjectile(fireProjectileInfo); }
public static void AddLink(ProcChainMask chain, ModProc modproc) { if (!ProcChainLinker.ContainsKey(chain)) { ProcChainLinker.Add(chain, modproc); } }
private void ProcMissile(CharacterBody attackerBody, ProcChainMask procChainMask, float damage, bool crit, int stack) { GameObject gameObject = attackerBody.gameObject; InputBankTest component = gameObject.GetComponent <InputBankTest>(); Vector3 position = component ? component.aimOrigin : gameObject.transform.position; float dmgCoef = missileDamage + (missileStackDamage * (stack - 1)); damage *= dmgCoef; ProcChainMask procChainMask2 = procChainMask; procChainMask2.AddProc(ProcType.Missile); FireProjectileInfo fireProjectileInfo = new FireProjectileInfo { projectilePrefab = GlobalEventManager.instance.missilePrefab, position = position, rotation = Util.QuaternionSafeLookRotation(Vector3.up), procChainMask = procChainMask2, owner = gameObject, damage = damage, crit = crit, force = 200f, damageColorIndex = DamageColorIndex.Item }; ProjectileManager.instance.FireProjectile(fireProjectileInfo); }
public static void RemoveLink(ProcChainMask chain) { if (ProcChainLinker.ContainsKey(chain)) { ProcChainLinker.Remove(chain); } }
public void Deserialize(NetworkReader reader) { var tgto = reader.ReadGameObject(); if (!tgto) { TinkersSatchelPlugin._logger.LogError("Received MsgHealTargetAndSelf for nonexistent target object"); return; } if (!tgto.TryGetComponent <HealthComponent>(out _target)) { TinkersSatchelPlugin._logger.LogError("Received MsgHealTargetAndSelf for target object with no HealthComponent"); return; } var selfo = reader.ReadGameObject(); if (!selfo) { TinkersSatchelPlugin._logger.LogWarning("Received MsgHealTargetAndSelf for nonexistent self object"); _self = null; } else if (!selfo.TryGetComponent <HealthComponent>(out _self)) { TinkersSatchelPlugin._logger.LogWarning("Received MsgHealTargetAndSelf for self object with no HealthComponent"); _self = null; } _adjustedCount = reader.ReadSingle(); _pcm = reader.ReadProcChainMask(); }
private void GlobalEventManager_OnHitEnemy(On.RoR2.GlobalEventManager.orig_OnHitEnemy orig, GlobalEventManager self, DamageInfo damageInfo, UnityEngine.GameObject victim) { GameObject attacker = damageInfo.attacker; if (self && attacker) { var attackerBody = attacker.GetComponent <CharacterBody>(); var victimBody = victim.GetComponent <CharacterBody>(); int thalCount = GetCount(attackerBody); if (thalCount > 0) { bool flag = (damageInfo.damageType & DamageType.PoisonOnHit) > DamageType.Generic; if ((thalCount > 0 || flag) && (flag || Util.CheckRoll((procChance + (stackChance * (thalCount - 1)))))) { ProcChainMask procChainMask = damageInfo.procChainMask; procChainMask.AddProc(ProcType.BleedOnHit); var dotInfo = new InflictDotInfo() { attackerObject = attacker, victimObject = victim, dotIndex = poisonDot, duration = duration, damageMultiplier = dmgCoefficient }; DotController.InflictDot(ref dotInfo); } } } orig(self, damageInfo, victim); }
public static bool GetProcValue(ProcChainMask chain, string ProcName) { if (ProcChainLinker.ContainsKey(chain)) { if (ProcChainLinker[chain].ProcList.ContainsKey(ProcName)) { return(ProcChainLinker[chain].ProcList[ProcName]); } } return(false); }
private static void PoisonOnHit_OnHit(On.RoR2.GlobalEventManager.orig_OnHitEnemy orig, GlobalEventManager gem, DamageInfo damageInfo, [NotNull] GameObject victim) { try { if (damageInfo.procCoefficient == 0f || damageInfo.rejected) { return; } if (!NetworkServer.active) { return; } CharacterBody component = damageInfo.attacker.GetComponent <CharacterBody>(); CharacterBody characterBody = victim ? victim.GetComponent <CharacterBody>() : null; if (component) { CharacterMaster master = component.master; if (master) { Inventory inventory = master.inventory; TeamComponent component2 = component.GetComponent <TeamComponent>(); TeamIndex teamIndex = component2 ? component2.teamIndex : TeamIndex.Neutral; Vector3 aimOrigin = component.aimOrigin; int itemCount2 = inventory.GetItemCount(GNCItemSuite.PoisonOnHitItemIndex); int itemCount3 = inventory.GetItemCount(GNCItemSuite.BlightOnHitItemIndex); if ((itemCount2 > 0) && (Util.CheckRoll(5f * (float)itemCount2 * damageInfo.procCoefficient, master))) { ProcChainMask procChainMask2 = damageInfo.procChainMask; procChainMask2.AddProc(ProcType.BleedOnHit); DotController.InflictDot(victim, damageInfo.attacker, DotController.DotIndex.Poison, 10f * damageInfo.procCoefficient, 1f); } if ((itemCount3 > 0) && (Util.CheckRoll(10f * (float)itemCount3 * damageInfo.procCoefficient, master))) { ProcChainMask procChainMask2 = damageInfo.procChainMask; procChainMask2.AddProc(ProcType.BleedOnHit); DotController.InflictDot(victim, damageInfo.attacker, DotController.DotIndex.Blight, 10f * damageInfo.procCoefficient, 1f); } } } } catch { } orig(gem, damageInfo, victim); }
public static void ArmsRaceItemHook() { On.RoR2.GlobalEventManager.OnHitEnemy += (orig, self, damage, victim) => { if (damage.attacker) { CharacterBody Attacker = damage.attacker.GetComponent <CharacterBody>(); CharacterMaster AttackerMaster = Attacker.master; if (Attacker.name.ToLower().Contains("drone") || Attacker.name.ToLower().Contains("turret")) { if (!damage.procChainMask.HasProc(ProcType.Missile)) { var inventory = AttackerMaster.minionOwnership.ownerMaster.inventory; int itemCount = inventory.GetItemCount(ArmsRaceItemIndex); if (itemCount > 0) { GameObject gameObject = Attacker.gameObject; InputBankTest component = gameObject.GetComponent <InputBankTest>(); Vector3 position = component ? component.aimOrigin : gameObject.transform.position; Vector3 vector = component ? component.aimDirection : gameObject.transform.forward; Vector3 up = Vector3.up; if (Util.CheckRoll(15f, AttackerMaster)) { float damageCoefficient = 3f * itemCount; float dealdamage = Util.OnHitProcDamage(damage.damage, Attacker.damage, damageCoefficient); ProcChainMask procChainMask2 = damage.procChainMask; procChainMask2.AddProc(ProcType.Missile); FireProjectileInfo fireProjectileInfo = new FireProjectileInfo { projectilePrefab = GlobalEventManager.instance.missilePrefab, position = position, rotation = Util.QuaternionSafeLookRotation(up), procChainMask = procChainMask2, target = victim, owner = gameObject, damage = dealdamage, crit = damage.crit, force = 200f, damageColorIndex = DamageColorIndex.Item }; ProjectileManager.instance.FireProjectile(fireProjectileInfo); } } } } orig(self, damage, victim); } }; }
private void SuperMissileICBMLaunch(Vector3 position, CharacterBody attacker, ProcChainMask procChainMask, GameObject victim, float missileDamage, bool isCrit, GameObject projectilePrefab, DamageColorIndex damageColorIndex) { Vector3 initialDirection = Vector3.up + UnityEngine.Random.insideUnitSphere * 0.1f; float force = 200f; bool addMissileProc = true; int num1 = characterBody.inventory?.GetItemCount(DLC1Content.Items.MoreMissile) ?? 0; float num2 = Mathf.Max(1f, (1 + 0.5f * (num1 - 1))); InputBankTest component = inputBank; ProcChainMask procChainMask1 = procChainMask; if (addMissileProc) { procChainMask1.AddProc(ProcType.Missile); } FireProjectileInfo fireProjectileInfo = new FireProjectileInfo() { projectilePrefab = projectilePrefab, position = position, rotation = Util.QuaternionSafeLookRotation(gunRay.direction), procChainMask = procChainMask1, target = victim, owner = attacker.gameObject, damage = missileDamage * num2, crit = isCrit, force = force, damageColorIndex = damageColorIndex }; ProjectileManager.instance.FireProjectile(fireProjectileInfo); if (num1 <= 0) { return; } Vector3 axis = component ? component.aimDirection : attacker.transform.position; FireProjectileInfo fireProjectileInfo1 = fireProjectileInfo; fireProjectileInfo1.rotation = Util.QuaternionSafeLookRotation(Quaternion.AngleAxis(45f, axis) * initialDirection); fireProjectileInfo1.projectilePrefab = sMissileExtraMissiles; fireProjectileInfo1.damage = Modules.StaticValues.missileDamageCoefficient * damageStat; FireProjectileInfo fireProjectileInfo2 = fireProjectileInfo; fireProjectileInfo2.rotation = Util.QuaternionSafeLookRotation(Quaternion.AngleAxis(-45f, axis) * initialDirection); fireProjectileInfo2.projectilePrefab = sMissileExtraMissiles; fireProjectileInfo2.damage = Modules.StaticValues.missileDamageCoefficient * damageStat; ProjectileManager.instance.FireProjectile(fireProjectileInfo1); ProjectileManager.instance.FireProjectile(fireProjectileInfo2); }
private void LaunchMortar(CharacterBody attackerBody, ProcChainMask procChainMask, GameObject victim, DamageInfo damageInfo, int stack) { GameObject gameObject = attackerBody.gameObject; InputBankTest component = gameObject.GetComponent <InputBankTest>(); Vector3 position = component ? component.aimOrigin : gameObject.transform.position; float dmgCoef = dmgCoefficient + (dmgStack * stack); float damage = Util.OnHitProcDamage(damageInfo.damage, attackerBody.damage, dmgCoef); ProcChainMask procChainMask2 = procChainMask; procChainMask2.AddProc(ProcType.Missile); FireProjectileInfo fireProjectileInfo = new FireProjectileInfo { projectilePrefab = mortarPrefab, position = position, procChainMask = procChainMask2, target = victim, owner = gameObject, damage = damage, crit = damageInfo.crit, force = 500f, damageColorIndex = DamageColorIndex.Item, speedOverride = -1f, damageTypeOverride = DamageType.AOE }; int times = (int)(1 + stackAmount * stack); for (int t = 0; t < times; t++) { Vector3 direction; if (fixedAim) { direction = gameObject.transform.forward; } else { direction = component ? component.aimDirection : gameObject.transform.forward; } direction = direction.normalized + new Vector3(0f, launchAngle, 0f); direction += new Vector3(Random.Range(-inaccuracyRate, inaccuracyRate), Random.Range(-inaccuracyRate, inaccuracyRate), Random.Range(-inaccuracyRate, inaccuracyRate)); fireProjectileInfo.rotation = Util.QuaternionSafeLookRotation(direction); ProjectileManager.instance.FireProjectile(fireProjectileInfo); } }
public override void Effect(GlobalEventManager globalEventManager, DamageInfo damageInfo, GameObject victim, int itemCount) { CharacterBody body = damageInfo.attacker.GetComponent <CharacterBody>(); CharacterBody Attacker = damageInfo.attacker.GetComponent <CharacterBody>(); Inventory inventory = body.master.inventory; if (itemCount > 0) { HealthComponent AttackerHealthComponent = Attacker.GetComponent <HealthComponent>(); if (AttackerHealthComponent) { ProcChainMask procChainMask = damageInfo.procChainMask; procChainMask.SetProcValue(ProcType.HealOnHit, true); double num = AttackerHealthComponent.Heal(itemCount * damageInfo.procCoefficient, procChainMask, true); } } }
public override void Effect(GlobalEventManager globalEventManager, DamageInfo damageInfo, GameObject victim, int itemCount) { float procCoefficient = damageInfo.procCoefficient; CharacterBody body = damageInfo.attacker.GetComponent <CharacterBody>(); ProcChainMask procChainMask = damageInfo.procChainMask; Inventory inventory = body.master.inventory; procChainMask.SetProcValue(ProcType.HealOnCrit, true); if (itemCount > 0 && body.healthComponent) { int ProcHealthSoundId = (int)Util.PlaySound("Play_item_proc_crit_heal", body.gameObject); if (NetworkServer.active) { double HealResult = body.healthComponent.Heal((float)(4f + itemCount * 4f) * procCoefficient, procChainMask, true); } } }
private void LaunchMortar(CharacterBody attackerBody, ProcChainMask procChainMask, float damage, bool crit, int stack) { GameObject gameObject = attackerBody.gameObject; InputBankTest component = gameObject.GetComponent <InputBankTest>(); Vector3 position = component ? component.aimOrigin : gameObject.transform.position; Vector3 direction; if (MortarTube.instance.fixedAim) { direction = gameObject.transform.forward; } else { direction = component ? component.aimDirection : gameObject.transform.forward; } direction = direction.normalized + new Vector3(0f, MortarTube.instance.launchAngle, 0f); float inaccuracyRate = MortarTube.instance.inaccuracyRate; direction += new Vector3(Random.Range(-inaccuracyRate, inaccuracyRate), Random.Range(-inaccuracyRate, inaccuracyRate), Random.Range(-inaccuracyRate, inaccuracyRate)); float dmgCoef = mortarDamage + (mortarStackDamage * (stack - 1)); damage *= dmgCoef; ProcChainMask procChainMask2 = procChainMask; procChainMask2.AddProc(ProcType.Missile); FireProjectileInfo fireProjectileInfo = new FireProjectileInfo { projectilePrefab = MortarTube.mortarPrefab, position = position, procChainMask = procChainMask2, owner = gameObject, damage = damage, crit = crit, force = 500f, damageColorIndex = DamageColorIndex.Item, speedOverride = -1f, damageTypeOverride = DamageType.AOE, rotation = Util.QuaternionSafeLookRotation(direction) }; ProjectileManager.instance.FireProjectile(fireProjectileInfo); }
public static void ThalliumItemHook() { On.RoR2.GlobalEventManager.OnHitEnemy += (orig, self, damage, victim) => { if (damage.attacker) { CharacterBody Attacker = damage.attacker.GetComponent <CharacterBody>(); CharacterMaster AttackerMaster = Attacker.master; CharacterBody VictimBody = victim ? victim.GetComponent <CharacterBody>() : null; if (Attacker && AttackerMaster) { int itemcount = Attacker.inventory.GetItemCount(ThalliumItemIndex); if ((itemcount > 0) && (Util.CheckRoll(10f * damage.procCoefficient, AttackerMaster))) { ProcChainMask procChainMask = damage.procChainMask; procChainMask.AddProc(ProcType.BleedOnHit); DotController.InflictDot(victim, damage.attacker, DotController.DotIndex.Blight, 3f * damage.procCoefficient, 3.33f * itemcount); VictimBody.AddTimedBuff(ThalliumDebuff, 3f * damage.procCoefficient); } } } orig(self, damage, victim); }; void ThalliumILHook(ILContext il) { var c = new ILCursor(il); c.GotoNext(x => x.MatchCallvirt <CharacterBody>("set_moveSpeed")); c.Emit(OpCodes.Ldarg_0); c.EmitDelegate <Func <CharacterBody, float> >((cb) => { if (cb.HasBuff(ThalliumDebuff)) { return(0.5f); } return(1.0f); }); c.Emit(OpCodes.Mul); } IL.RoR2.CharacterBody.RecalculateStats += ThalliumILHook; }
/// <summary> /// Used to trigger Arms Race effect in launching artillery. /// </summary> /// <param name="body">The drone's body</param> /// <param name="damage">Damage to be computed against the coefficients of Arms Race projectiles</param> /// <param name="crit">Determines if this should be a critical hit</param> /// <param name="procChainMask">The proc chain mask</param> public void TriggerArtillery(CharacterBody body, float damage, bool crit, ProcChainMask procChainMask = default) { if (damage <= 0 || !body || !body.master || !body.master.minionOwnership || !body.master.minionOwnership.ownerMaster || procChainMask.HasProc(ProcType.Missile)) { return; } int itemCount = GetCount(body.master.minionOwnership.ownerMaster); if (itemCount <= 0) { return; } if (Util.CheckRoll(ProcComputation(mortarProcChance, itemCount), body.master)) { LaunchMortar(body, procChainMask, damage, crit, itemCount); } if (Util.CheckRoll(ProcComputation(missileProcChance, itemCount), body.master)) { ProcMissile(body, procChainMask, damage, crit, itemCount); } }
private static void LeechHook() { On.RoR2.EquipmentSlot.PerformEquipmentAction += (orig, self, equipmentIndex) => { if (equipmentIndex == MassiveLeechIndex) { if (self.characterBody) { self.characterBody.AddTimedBuff(MassiveLeechbuff, 10f); return(true); } } return(orig(self, equipmentIndex)); }; On.RoR2.GlobalEventManager.OnHitEnemy += (orig, self, damage, victim) => { if (damage.attacker) { CharacterBody Attacker = damage.attacker.GetComponent <CharacterBody>(); CharacterMaster AttackerMaster = Attacker.master; if (Attacker && AttackerMaster) { if (Attacker.HasBuff(MassiveLeechbuff)) { ProcChainMask procChainMask = damage.procChainMask; HealthComponent component = Attacker.GetComponent <HealthComponent>(); procChainMask.AddProc(ProcType.HealOnHit); float heal = Attacker.level + 10f; component.Heal(heal * damage.procCoefficient, procChainMask, true); } } } orig(self, damage, victim); }; }
public void Awake() { //Scale the stacks of corpseblooms to provide % HP / s increase per stack, and -%Reserve per stack IL.RoR2.HealthComponent.Heal += (il) => { //Increase the amount of reserve consumed to heal per second #region Benefit var c = new ILCursor(il); c.GotoNext( x => x.MatchLdfld <HealthComponent>("repeatHealComponent"), x => x.MatchLdcR4(0.1f) ); //match: this.repeatHealComponent.healthFractionToRestorePerSecond = 0.1f / (float)this.repeatHealCount; line 197 //Becomes this.repeatHealComponent.healthFractionToRestorePerSecond = 0.1f * (float)this.repeatHealCount; c.Index += 5; c.Remove(); c.Emit(OpCodes.Mul); #endregion #region Disadvantage //remove multiplicative scaling (amount*increaseHealingCount*repeatHealingCount) #region healingMultiplier c.GotoNext( x => x.MatchLdcI4(1), x => x.MatchLdarg(0), x => x.MatchLdfld <HealthComponent>("repeatHealCount"), x => x.MatchAdd() ); //match this.repeatHealComponent.AddReserve(amount * (float)(1 + this.repeatHealCount), this.fullHealth); line 198 //Replace with this.repeatHealComponent.AddReserve(amount * (float)(1), this.fullHealth); c.Index += 1; c.RemoveRange(3); #endregion //decrease the total health reserve that is restored #region modifyMaxReserve c.GotoNext( x => x.MatchMul(), x => x.MatchLdarg(0), x => x.MatchCallvirt <HealthComponent>("get_fullHealth") ); //Match this.repeatHealComponent.AddReserve(amount * (float)(1), this.fullHealth); line 198 //Replace with this.repeatHealComponent.AddReserve(amount * (float)(1), (this.fullHealth * 1.0f + (float)this.increaseHealingCount) / this.repeatHealCount); c.Index += 3; c.Emit(OpCodes.Ldc_R4, 1f); c.Emit(OpCodes.Ldarg_0); c.Emit(OpCodes.Ldfld, typeof(HealthComponent).GetField("increaseHealingCount", BindingFlags.Instance | BindingFlags.NonPublic)); c.Emit(OpCodes.Conv_R4); c.Emit(OpCodes.Add); c.Emit(OpCodes.Mul); c.Emit(OpCodes.Ldarg_0); c.Emit(OpCodes.Ldfld, typeof(HealthComponent).GetField("repeatHealCount", BindingFlags.Instance | BindingFlags.NonPublic)); c.Emit(OpCodes.Conv_R4); c.Emit(OpCodes.Div); c.Emit(OpCodes.Ldarg_0); //Update each CorpseBloom owner's FullHealthReserve value and store in corpseReserve c.EmitDelegate <Func <float, HealthComponent, float> >((fhp, hc) => { if (hc.body != null) { if (LocalUserManager.GetFirstLocalUser().cachedBody != null) { if (hc.body.Equals(LocalUserManager.GetFirstLocalUser().cachedBody)) { reserveMax = fhp; } } if (playerReserves.ContainsKey(hc.body.netId)) { playerReserves[hc.body.netId].maxReserve = fhp; } else { playerReserves.Add(hc.body.netId, new CorpseReserve()); playerReserves[hc.body.netId].maxReserve = fhp; } } return(fhp); }); #endregion //cut multiplicative healing, only gets applied to reserves, and not to health restored #region multiplicativeHealing c.GotoNext( x => x.MatchRet(), x => x.MatchLdarg(1) ); c.Index += 2; //Debug.Log(c.ToString()); c.Emit(OpCodes.Ldarg_1); c.Emit(OpCodes.Ldarg_3); c.Emit(OpCodes.Ldarg_0); c.Emit(OpCodes.Ldfld, typeof(HealthComponent).GetField("increaseHealingCount", BindingFlags.Instance | BindingFlags.NonPublic)); c.Emit(OpCodes.Ldarg_0); c.Emit(OpCodes.Ldfld, typeof(HealthComponent).GetFieldCached("repeatHealComponent")); //I'm not sure why, but we can properly existance check the private subtype RepeatHealComponent when its cast as a HealthComponent c.EmitDelegate <Func <float, bool, int, HealthComponent, float> > ((amnt, rgn, incHealingCount, repHealComponent) => { if (rgn && repHealComponent) //If nonRegen flag is set, and the client has a repeatHealComponent, and the procChain has type.RepeatHeal (ommited due to code prior to delegate returning if has procType.) { amnt /= 1f + (float)incHealingCount; return(amnt); //return the modified amount. } return(amnt); //otherwise we do nothing here. }); c.Emit(OpCodes.Starg_S, (byte)1); #endregion #endregion }; //Build reserve while fullHP, do not consume. Update currentReserve IL.RoR2.HealthComponent.RepeatHealComponent.FixedUpdate += (il) => { var c = new ILCursor(il); ILLabel lab = il.DefineLabel(); #region updateCurrentReserveHP c.GotoNext( x => x.MatchLdarg(0), x => x.MatchLdfld("RoR2.HealthComponent/RepeatHealComponent", "timer"), x => x.MatchLdcR4(0f) ); //match if (this.timer <= 0f) line 1226 //push reserve & HealthComponent onto stack & emitDelegate c.Emit(OpCodes.Ldarg_0); c.Emit(OpCodes.Ldfld, typeof(HealthComponent).GetNestedType("RepeatHealComponent", BindingFlags.Instance | BindingFlags.NonPublic).GetFieldCached("reserve")); c.Emit(OpCodes.Ldarg_0); c.Emit(OpCodes.Ldfld, typeof(HealthComponent).GetNestedType("RepeatHealComponent", BindingFlags.Instance | BindingFlags.NonPublic).GetFieldCached("healthComponent")); //Update each CorpseBloom owner's CurrentReserve value c.EmitDelegate <Action <float, HealthComponent> > ((curHP, hc) => { if (hc.body != null) { if (LocalUserManager.GetFirstLocalUser().cachedBody != null) { if (LocalUserManager.GetFirstLocalUser().cachedBody.Equals(hc.body)) { currentReserve = curHP; } } if (playerReserves.ContainsKey(hc.body.netId)) { playerReserves[hc.body.netId].currentReserve = curHP; } else { playerReserves.Add(hc.body.netId, new CorpseReserve(curHP)); } } }); #endregion #region DontConsume c.GotoNext( //match the timer and loading of 0f onto the stack, increment 4 instuctions to palce ourselves here: if(this.timer > 0f<here>) x => x.MatchLdarg(0), x => x.MatchLdfld("RoR2.HealthComponent/RepeatHealComponent", "reserve"), x => x.MatchLdcR4(0f) ); //Match if (this.timer <= 0f) line 1228 //add condition if(healthComponent.health < healthComponent.get_FullHealth) { //Old non-malechite logic //c.Index += 4; //c.Emit(OpCodes.Ldarg_0); //c.Emit(OpCodes.Ldfld, typeof(HealthComponent).GetNestedType("RepeatHealComponent", BindingFlags.Instance | BindingFlags.NonPublic).GetFieldCached("healthComponent")); //c.Emit(OpCodes.Ldfld, typeof(HealthComponent).GetFieldCached("health")); //c.Emit(OpCodes.Ldarg_0); //load (this) onto the stack //c.Emit(OpCodes.Ldfld, typeof(HealthComponent).GetNestedType("RepeatHealComponent", BindingFlags.Instance | BindingFlags.NonPublic).GetFieldCached("healthComponent")); //c.Emit(OpCodes.Call, typeof(HealthComponent).GetMethod("get_fullHealth")); //c.Emit(OpCodes.Bge_Un_S, lab); //branch to return if health > fullhealth //Remove unwanted instructions and setup the stack for our delegate. c.Index += 2; c.RemoveRange(2); c.Emit(OpCodes.Ldarg_0); c.Emit(OpCodes.Ldfld, typeof(HealthComponent).GetNestedType("RepeatHealComponent", BindingFlags.Instance | BindingFlags.NonPublic).GetFieldCached("healthComponent")); c.Emit(OpCodes.Ldarg_0); c.Emit(OpCodes.Ldfld, typeof(HealthComponent).GetNestedType("RepeatHealComponent", BindingFlags.Instance | BindingFlags.NonPublic).GetFieldCached("healthComponent")); c.Emit(OpCodes.Ldfld, typeof(HealthComponent).GetFieldCached("health")); c.Emit(OpCodes.Ldarg_0); //load (this) onto the stack c.Emit(OpCodes.Ldfld, typeof(HealthComponent).GetNestedTypeCached("RepeatHealComponent").GetFieldCached("healthComponent")); c.Emit(OpCodes.Call, typeof(HealthComponent).GetMethod("get_fullHealth")); c.EmitDelegate <Func <float, HealthComponent, float, float, bool> >((reserve, hc, health, fullhp) => { if (reserve > 0f && health < fullhp && !hc.body.HasBuff(BuffIndex.HealingDisabled)) { return(true); } return(false); }); //Mark return address c.Emit(OpCodes.Brfalse, lab); c.GotoNext( x => x.MatchRet() ); c.MarkLabel(lab); #endregion }; //Add regen over time to health reserve IL.RoR2.HealthComponent.ServerFixedUpdate += (il) => { var c = new ILCursor(il); //Logger.LogInfo(il.ToString()); //GoTo: this.regenAccumulator -= num; c.GotoNext( x => x.MatchLdfld <HealthComponent>("regenAccumulator"), x => x.MatchLdloc(0), x => x.MatchSub(), x => x.MatchStfld <HealthComponent>("regenAccumulator") ); //Match this.regenAccumulator -= num; line 802 //emitDelgate c.Index += 4; //NextLine c.RemoveRange(8); c.Emit(OpCodes.Ldarg_0); c.Emit(OpCodes.Ldloc_0); c.EmitDelegate <Action <HealthComponent, float> >((hc, num) => { ProcChainMask procChainMask = default(ProcChainMask); if (hc.body.inventory && hc.body.inventory.GetItemCount(ItemIndex.RepeatHeal) > 0) //Check if we have a CorpseBloom { hc.Heal(num, procChainMask, true); //Add regen to reserve. } else { hc.Heal(num, procChainMask, false); //Add regen to health } }); }; //Add reserveUI to HealthBar On.RoR2.UI.HUD.Start += (self, orig) => { self(orig); initializeReserveUI(); reserveRect.transform.SetParent(orig.healthBar.transform, false); hpBar = orig.healthBar; }; }
public static bool GetProcValue(this ProcChainMask procMask, string ProcName) { return(ModProcManager.GetProcValue(procMask, ProcName)); }
private void MissileUtils_FireMissile_MyKingdomForAStruct(On.RoR2.MissileUtils.orig_FireMissile_Vector3_CharacterBody_ProcChainMask_GameObject_float_bool_GameObject_DamageColorIndex_Vector3_float_bool orig, Vector3 position, CharacterBody attackerBody, ProcChainMask procChainMask, GameObject victim, float missileDamage, bool isCrit, GameObject projectilePrefab, DamageColorIndex damageColorIndex, Vector3 initialDirection, float force, bool addMissileProc) { ignoreMugs = true; orig(position, attackerBody, procChainMask, victim, missileDamage, isCrit, projectilePrefab, damageColorIndex, initialDirection, force, addMissileProc); ignoreMugs = false; }
public static void Write(this NetworkWriter writer, ProcChainMask procChainMask) { writer.Write(procChainMask.mask); }
public static bool GetProcValue(this ProcChainMask procMask, ProcType Proc) { return(ModProcManager.GetProcValue(procMask, Proc.ToString())); }
public static void LinkToManager(this ProcChainMask procMask) { ModProcManager.AddLink(procMask, new ModProc()); }
public static void UnlinkToManager(this ProcChainMask procMask) { ModProcManager.RemoveLink(procMask); }
public override bool Condition(GlobalEventManager globalEventManager, DamageInfo damageInfo, GameObject victim, int count) { ProcChainMask procChainMask = damageInfo.procChainMask; return(damageInfo.crit); }
static void ProcMissile(int stack, CharacterBody attackerBody, CharacterMaster attackerMaster, TeamIndex attackerTeamIndex, ProcChainMask procChainMask, GameObject victim, DamageInfo damageInfo) { if (stack <= 0) { return; } GameObject AttackerGO = attackerBody.gameObject; InputBankTest AttackerBankTest = AttackerGO.GetComponent <InputBankTest>(); Vector3 position = AttackerBankTest ? AttackerBankTest.aimOrigin : GlobalEventManager.instance.transform.position; Vector3 vector3 = AttackerBankTest ? AttackerBankTest.aimDirection : GlobalEventManager.instance.transform.forward; Vector3 up = Vector3.up; if (!Util.CheckRoll(10f * damageInfo.procCoefficient, attackerMaster)) { return; } GameObject MissileGO = UnityEngine.Object.Instantiate <GameObject>(GlobalEventManager.instance.missilePrefab, position, Util.QuaternionSafeLookRotation(up + UnityEngine.Random.insideUnitSphere * 0.0f)); ProjectileController MissileControler = MissileGO.GetComponent <ProjectileController>(); MissileControler.Networkowner = AttackerGO.gameObject; MissileControler.procChainMask = procChainMask; MissileControler.procChainMask.AddProc(ProcType.Missile); MissileGO.GetComponent <TeamFilter>().teamIndex = attackerTeamIndex; MissileGO.GetComponent <MissileController>().target = victim.transform; float damageCoefficient = 3f * (float)stack; float num = Util.OnHitProcDamage(damageInfo.damage, attackerBody.damage, damageCoefficient); ProjectileDamage MissileDamage = MissileGO.GetComponent <ProjectileDamage>(); MissileDamage.damage = num; MissileDamage.crit = damageInfo.crit; MissileDamage.force = 200f; MissileDamage.damageColorIndex = DamageColorIndex.Item; NetworkServer.Spawn(MissileGO); }
public override bool Condition(GlobalEventManager globalEventManager, DamageInfo damageInfo, GameObject victim, int count) { ProcChainMask procChainMask = damageInfo.procChainMask; return(damageInfo.crit && procChainMask.GetProcValue(ProcType.HealOnCrit)); }