예제 #1
0
        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);
                }
            }
        }
예제 #2
0
 public static void SetProcValue(ProcChainMask chain, string ProcName, bool value)
 {
     if (ProcChainLinker.ContainsKey(chain))
     {
         ProcChainLinker[chain].ChangeProcState(ProcName, value);
     }
 }
예제 #3
0
 public MsgHealTargetAndSelf(HealthComponent target, HealthComponent self, float amount, ProcChainMask pcm)
 {
     _target        = target;
     _self          = self;
     _adjustedCount = amount;
     _pcm           = pcm;
 }
예제 #4
0
        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);
        }
예제 #5
0
 public static void AddLink(ProcChainMask chain, ModProc modproc)
 {
     if (!ProcChainLinker.ContainsKey(chain))
     {
         ProcChainLinker.Add(chain, modproc);
     }
 }
예제 #6
0
        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);
        }
예제 #7
0
 public static void RemoveLink(ProcChainMask chain)
 {
     if (ProcChainLinker.ContainsKey(chain))
     {
         ProcChainLinker.Remove(chain);
     }
 }
예제 #8
0
            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();
            }
예제 #9
0
        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);
        }
예제 #10
0
 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);
 }
예제 #11
0
파일: Hooks.cs 프로젝트: 6len/game-mods
        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);
        }
예제 #12
0
 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);
         }
     };
 }
예제 #13
0
        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);
        }
예제 #14
0
        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);
            }
        }
예제 #15
0
        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);
                }
            }
        }
예제 #16
0
        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);
                }
            }
        }
예제 #17
0
        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);
        }
예제 #18
0
            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;
            }
예제 #19
0
        /// <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);
            }
        }
예제 #20
0
        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;
            };
        }
예제 #22
0
 public static bool GetProcValue(this ProcChainMask procMask, string ProcName)
 {
     return(ModProcManager.GetProcValue(procMask, ProcName));
 }
예제 #23
0
 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;
 }
예제 #24
0
 public static void Write(this NetworkWriter writer, ProcChainMask procChainMask)
 {
     writer.Write(procChainMask.mask);
 }
예제 #25
0
 public static bool GetProcValue(this ProcChainMask procMask, ProcType Proc)
 {
     return(ModProcManager.GetProcValue(procMask, Proc.ToString()));
 }
예제 #26
0
 public static void LinkToManager(this ProcChainMask procMask)
 {
     ModProcManager.AddLink(procMask, new ModProc());
 }
예제 #27
0
 public static void UnlinkToManager(this ProcChainMask procMask)
 {
     ModProcManager.RemoveLink(procMask);
 }
예제 #28
0
        public override bool Condition(GlobalEventManager globalEventManager, DamageInfo damageInfo, GameObject victim, int count)
        {
            ProcChainMask procChainMask = damageInfo.procChainMask;

            return(damageInfo.crit);
        }
예제 #29
0
        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);
        }
예제 #30
0
        public override bool Condition(GlobalEventManager globalEventManager, DamageInfo damageInfo, GameObject victim, int count)
        {
            ProcChainMask procChainMask = damageInfo.procChainMask;

            return(damageInfo.crit && procChainMask.GetProcValue(ProcType.HealOnCrit));
        }