Example #1
0
    public override GameObject Mutate(GameObject abilityObject, Vector3 location, Vector3 targetLocation)
    {
        // work out whether a corpse has been consumed to empower the skeleton
        bool corpseConsumed = false;

        if (corpseStatList != null && corpseStatList.Count > 0 && health && health.alignmentManager && health.alignmentManager.alignment != null)
        {
            float closestDistance = float.MaxValue;
            Dying closestDying    = null;
            float distance        = 0f;

            // check all corpses to find the closest
            foreach (Dying dying in Dying.all)
            {
                // check that the entity is dying and is an enemy
                if (dying.isDying() && dying.myHealth && dying.myHealth.alignmentManager && health.alignmentManager.alignment.foes.Contains(dying.myHealth.alignmentManager.alignment))
                {
                    // find the distance
                    distance = Maths.manhattanDistance(dying.transform.position, targetLocation);
                    // don't consume very distant corpses
                    if (distance <= 8f)
                    {
                        // if a closest one hasn't been found yet this is the closest
                        if (closestDying == null)
                        {
                            closestDying    = dying;
                            closestDistance = distance;
                        }
                        // otherwise compare distances
                        else
                        {
                            if (distance < closestDistance)
                            {
                                closestDying    = dying;
                                closestDistance = distance;
                            }
                        }
                    }
                }
            }

            // consume the closest corpse
            if (closestDying)
            {
                closestDying.setDelays(0f, 0f);
                corpseConsumed = true;
            }
        }

        // self stat buffs on corpse consumption
        if (corpseConsumed)
        {
            TaggedBuff newBuff;
            for (int i = 0; i < corpseSelfBuffStatList.Count; i++)
            {
                newBuff      = new TaggedBuff();
                newBuff.stat = new TaggedStatsHolder.TaggableStat(corpseSelfBuffStatList[i]);
                newBuff.remainingDuration = 4f;
                newBuff.name = "skeleton corpse buff " + newBuff.stat.property;
                if (newBuff.stat.tagList != null)
                {
                    foreach (Tags.AbilityTags tag in newBuff.stat.tagList)
                    {
                        newBuff.name += " " + tag;
                    }
                }
                statBuffs.addTaggedBuff(newBuff);
            }
        }

        // control the weights of each minion type
        CreateRandomAbilityObjectOnDeath randomSummoner = abilityObject.GetComponent <CreateRandomAbilityObjectOnDeath>();

        randomSummoner.possibleAbilities.Clear();
        randomSummoner.weights.Clear();
        if (!cannotSummonWarriors)
        {
            randomSummoner.possibleAbilities.Add(summonWarrior);
            // add extra weight if there are no warriors
            if (summonTracker.numberOfMinions(summonWarrior) <= 0)
            {
                randomSummoner.weights.Add(4);
            }
            else
            {
                randomSummoner.weights.Add(1);
            }
        }
        if (!cannotSummonMages)
        {
            randomSummoner.possibleAbilities.Add(summonMage);
            randomSummoner.weights.Add(1);
        }
        if (canSummonArchers)
        {
            randomSummoner.possibleAbilities.Add(summonArcher);
            randomSummoner.weights.Add(1);
        }
        if (canSummonWarlords)
        {
            randomSummoner.possibleAbilities.Add(summonWarlord);
            randomSummoner.weights.Add(0.45f);
        }
        if (cannotSummonWarriors && cannotSummonMages && !canSummonArchers && !canSummonWarlords)
        {
            randomSummoner.possibleAbilities.Add(summonBrawler);
            randomSummoner.weights.Add(1);
        }

        // skeleton warrior
        if (!cannotSummonWarriors)
        {
            SummonSkeletonWarriorMutator warrior = abilityObject.AddComponent <SummonSkeletonWarriorMutator>();
            warrior.statList.AddRange(statList);
            warrior.usesDeathSlash = usesDeathSlash;
            warrior.increasedDeathSlashCooldownRecovery = increasedDeathSlashCooldownRecovery;
            warrior.additionalDuration  = additionalDuration;
            warrior.additionalSkeletons = additionalSkeletons;
            warrior.limitDuration       = limitDuration;
            if (corpseConsumed)
            {
                warrior.tempStats.AddRange(corpseStatList);
            }
        }

        // skeleton mage
        if (!cannotSummonMages)
        {
            SummonSkeletonMageMutator mage = abilityObject.AddComponent <SummonSkeletonMageMutator>();
            mage.statList.AddRange(statList);
            mage.usesNecroticMortar = usesNecroticMortar;
            mage.increasedNecroticMortarCooldownRecovery = increasedNecroticMortarCooldownRecovery;
            mage.additionalDuration  = additionalDuration;
            mage.additionalSkeletons = additionalSkeletons;
            mage.limitDuration       = limitDuration;
            if (corpseConsumed)
            {
                mage.tempStats.AddRange(corpseStatList);
            }
        }

        // skeleton archer
        if (canSummonArchers)
        {
            SummonSkeletonArcherMutator archer = abilityObject.AddComponent <SummonSkeletonArcherMutator>();
            archer.statList.AddRange(statList);
            archer.usesPoisonArrow = usesPoisonArrow;
            archer.increasedPoisonArrowCooldownSpeed = increasedPoisonArrowCooldownSpeed;
            archer.increasedPoisonArrowCooldown      = increasedPoisonArrowCooldown;
            archer.poisonArrowPierces         = poisonArrowPierces;
            archer.poisonArrowInaccurate      = poisonArrowInaccurate;
            archer.poisonArrowIncreasedDamage = poisonArrowIncreasedDamage;
            archer.poisonArrowDelayedAttacks  = poisonArrowDelayedAttacks;
            archer.usesMultishot = usesMultishot;
            archer.increasedMultishotCooldownSpeed = increasedMultishotCooldownSpeed;
            archer.additionalDuration  = additionalDuration;
            archer.additionalSkeletons = additionalSkeletons;
            archer.limitDuration       = limitDuration;
            if (corpseConsumed)
            {
                archer.tempStats.AddRange(corpseStatList);
            }
        }

        // skeleton warlord
        if (canSummonWarlords)
        {
            SummonSkeletonWarlordMutator warlord = abilityObject.AddComponent <SummonSkeletonWarlordMutator>();
            warlord.statList.AddRange(statList);
            warlordStatList.AddRange(warlordStatList);
            warlord.usesInspire = usesInspire;
            warlord.increasedInspireCooldownRecovery = increasedInspireCooldownRecovery;
            warlord.additionalDuration  = additionalDuration;
            warlord.additionalSkeletons = additionalWarlords;
            warlord.limitDuration       = limitDuration;
            if (corpseConsumed)
            {
                warlord.tempStats.AddRange(corpseStatList);
            }
        }

        // skeleton brawler
        if (cannotSummonWarriors && cannotSummonMages && !canSummonArchers && !canSummonWarlords)
        {
            SummonSkeletonBrawlerMutator brawler = abilityObject.AddComponent <SummonSkeletonBrawlerMutator>();
            brawler.statList.AddRange(statList);
            brawler.additionalDuration  = additionalDuration;
            brawler.additionalSkeletons = additionalSkeletons;
            brawler.limitDuration       = limitDuration;
            if (corpseConsumed)
            {
                brawler.tempStats.AddRange(corpseStatList);
            }
        }

        return(abilityObject);
    }
Example #2
0
    public override GameObject Mutate(GameObject abilityObject, Vector3 location, Vector3 targetLocation)
    {
        // Leech on cast buff
        if (statBuffs)
        {
            statBuffs.addBuff(4f, Tags.Properties.PercentLifeLeech, 0, physLeechOnCast, null, null, physTag, "marrow shards phys leech on cast buff");
            if (tracker && tracker.numberOfMinions() == 2)
            {
                statBuffs.addBuff(2f, Tags.Properties.CriticalChance, 0, critChanceOnCast, null, null, physTag, "marrow shards phys leech on cast buff");
            }
        }

        if (createsSplintersAtEnd)
        {
            // nova trigger(s)
            CreateAbilityObjectOnDeath component = abilityObject.AddComponent <CreateAbilityObjectOnDeath>();
            component.abilityToInstantiate = Ability.getAbility(AbilityID.boneNova);
            component.failsIfFailedAbility = true;
            component.offset       = boneNovaOffset;
            component.aimingMethod = CreateAbilityObjectOnDeath.AimingMethod.TravelDirection;

            // nova mutator
            BoneNovaMutator mutator = abilityObject.AddComponent <BoneNovaMutator>();
            mutator.increasedSpeed      = nova_increasedSpeed;
            mutator.pierces             = true;
            mutator.increasedDamage     = nova_increasedDamage;
            mutator.increasedStunChance = nova_increasedStunChance;
            mutator.bleedChance         = nova_bleedChance;
            mutator.addedCritChance     = nova_addedCritChance;
            mutator.addedCritMultiplier = nova_addedCritMultiplier;
            mutator.cone                      = true;
            mutator.randomAngles              = true;
            mutator.noVFX                     = true;
            mutator.dontAttach                = true;
            mutator.dontMoveToTarget          = true;
            mutator.moreDamageAgainstBleeding = nova_moreDamageAgainstBleeding;
        }

        if (returnHealthChance != 0 && returnHealthChance > (Random.Range(0f, 1f)))
        {
            CreateResourceReturnAbilityObjectOnEnemyHit component = abilityObject.AddComponent <CreateResourceReturnAbilityObjectOnEnemyHit>();
            component.abilityObject = Ability.getAbility(AbilityID.bloodReturn);
            component.health        = healthReturned;
            if (manaReturnChance != 0 && manaReturnChance > (Random.Range(0f, 1f)))
            {
                component.mana = manaReturned;
            }
        }

        if (increasedHealthCost != 0)
        {
            DamageCreatorOnCreation component = abilityObject.GetComponent <DamageCreatorOnCreation>();
            if (component)
            {
                component.flatDamage *= (1 + increasedHealthCost);
                component.percentCurrentHealthTaken *= (1 + increasedHealthCost);
            }
        }

        if (doesntPierce)
        {
            Comp <Pierce> .GetOrAdd(abilityObject).objectsToPierce = 0;

            abilityObject.AddComponent <DestroyOnFailingToPierceEnemy>();
        }

        if (endsAtTargetPoint)
        {
            if (!abilityObject.GetComponent <LocationDetector>())
            {
                abilityObject.AddComponent <LocationDetector>();
            }
            DestroyAfterDurationAfterReachingTargetLocation component = abilityObject.AddComponent <DestroyAfterDurationAfterReachingTargetLocation>();
            component.duration = 0f;
        }

        if (increasedDuration != 0)
        {
            DestroyAfterDuration dad = abilityObject.GetComponent <DestroyAfterDuration>();
            dad.duration *= 1 + increasedDuration;
        }

        if (addedCritChance != 0)
        {
            foreach (DamageStatsHolder damage in abilityObject.GetComponents <DamageStatsHolder>())
            {
                damage.baseDamageStats.critChance += addedCritChance;
            }
        }

        if (addedCritMultiplier != 0)
        {
            foreach (DamageStatsHolder damage in abilityObject.GetComponents <DamageStatsHolder>())
            {
                damage.baseDamageStats.critMultiplier += addedCritMultiplier;
            }
        }

        if (moreDamageAgainstBleeding != 0)
        {
            // create the conditional
            DamageConditionalEffect    conditionalEffect = new DamageConditionalEffect();
            HasStatusEffectConditional conditional       = new HasStatusEffectConditional();
            conditional.statusEffect      = StatusEffectID.Bleed;
            conditionalEffect.conditional = conditional;
            conditionalEffect.effect      = new DamageEffectMoreDamage(moreDamageAgainstBleeding);
            // add the conditional to all damage stats holders
            foreach (DamageStatsHolder holder in abilityObject.GetComponents <DamageStatsHolder>())
            {
                holder.baseDamageStats.conditionalEffects.Add(conditionalEffect);
            }
        }

        if (chanceToBleed > 0)
        {
            ChanceToApplyStatusOnEnemyHit newComponent = abilityObject.AddComponent <ChanceToApplyStatusOnEnemyHit>();
            newComponent.statusEffect = StatusEffectList.getEffect(StatusEffectID.Bleed);
            newComponent.chance       = chanceToBleed;
        }

        if (chanceToShredArmour > 0)
        {
            ChanceToApplyStatusOnEnemyHit newComponent = abilityObject.AddComponent <ChanceToApplyStatusOnEnemyHit>();
            newComponent.statusEffect = StatusEffectList.getEffect(StatusEffectID.ArmourShred);
            newComponent.chance       = chanceToShredArmour;
        }

        if (increasedStunChance != 0)
        {
            foreach (DamageStatsHolder holder in abilityObject.GetComponents <DamageStatsHolder>())
            {
                holder.baseDamageStats.increasedStunChance += increasedStunChance;
            }
        }

        // increase damage based on the number of minions
        float realIncreasedDamage = increasedDamage;

        if (increasedDamagePerMinion != 0)
        {
            if (tracker && tracker.summons != null)
            {
                realIncreasedDamage += increasedDamagePerMinion * tracker.summons.Count;
            }
        }

        // more damage if you only have one minion
        if (increasedDamageWithOneMinion != 0)
        {
            if (tracker && tracker.numberOfMinions() == 1)
            {
                realIncreasedDamage += increasedDamageWithOneMinion;
            }
        }

        if (increasedDamageFromMinionDrain != 0 && tracker && tracker.summons != null && tracker.summons.Count > 0)
        {
            // choose a minion to drain
            BaseHealth minionHealth = tracker.summons[Random.Range(0, tracker.summons.Count - 1)].GetComponent <BaseHealth>();

            if (minionHealth)
            {
                // gain extra damage
                realIncreasedDamage += increasedDamageFromMinionDrain;
                // create a death vfx
                Instantiate(spiritEscapePrefab).transform.position = minionHealth.transform.position + spiritEscapeOffset;
                // kill the minion
                minionHealth.HealthDamage(minionHealth.currentHealth + 1);
            }
        }

        // increase damage
        if (realIncreasedDamage != 0 || moreDamage != 0)
        {
            foreach (DamageStatsHolder holder in abilityObject.GetComponents <DamageStatsHolder>())
            {
                holder.increaseAllDamage(realIncreasedDamage);
                if (moreDamage != 0)
                {
                    holder.increaseAllDamage(moreDamage);
                }
            }
        }

        if (damagesMinions)
        {
            DamageEnemyOnHit deoh = abilityObject.GetComponent <DamageEnemyOnHit>();
            if (deoh)
            {
                DamageCreatorMinionOnHit component = abilityObject.AddComponent <DamageCreatorMinionOnHit>();
                component.baseDamageStats = deoh.baseDamageStats;

                if (doesntPierce)
                {
                    abilityObject.GetComponent <DestroyOnFailingToPierceEnemy>().alsoDestroyOnFailingToPierceCreatorMinion();
                }
            }
        }

        return(abilityObject);
    }
Example #3
0
    public override GameObject Mutate(GameObject abilityObject, Vector3 location, Vector3 targetLocation)
    {
        // DoT on cast buff
        if (statBuffs)
        {
            statBuffs.addBuff(4f, Tags.Properties.Damage, 0, increasedDotDamageOnCast, null, null, dotTag, "sacrifice dot on cast bug");
        }

        if (boneNovaChance > 0 && (!mana || mana.currentMana > 0) && (boneNovaChance >= 1 || boneNovaChance > (Random.Range(0f, 1f))))
        {
            // nova trigger
            CreateAbilityObjectOnDeath component = abilityObject.AddComponent <CreateAbilityObjectOnDeath>();
            component.abilityToInstantiate = Ability.getAbility(AbilityID.boneNova);
            component.failsIfFailedAbility = true;
            component.offset = boneNovaOffset;

            // nova mutator
            BoneNovaMutator mutator = abilityObject.AddComponent <BoneNovaMutator>();
            mutator.increasedSpeed      = nova_increasedSpeed;
            mutator.pierces             = nova_pierces;
            mutator.increasedDamage     = nova_increasedDamage;
            mutator.increasedStunChance = nova_increasedStunChance;
            mutator.bleedChance         = nova_bleedChance;
            mutator.addedCritChance     = nova_addedCritChance;
            mutator.addedCritMultiplier = nova_addedCritMultiplier;
            mutator.cone                      = false;
            mutator.dontAttach                = true;
            mutator.dontMoveToTarget          = true;
            mutator.randomAngles              = false;
            mutator.noVFX                     = true;
            mutator.moreDamageAgainstBleeding = nova_moreDamageAgainstBleeding;
        }

        if (bloodWraithChance > 0 && (bloodWraithChance >= 1 || bloodWraithChance > Random.Range(0f, 1f)))
        {
            // wraith trigger
            CreateAbilityObjectOnDeath component = abilityObject.AddComponent <CreateAbilityObjectOnDeath>();
            component.abilityToInstantiate = Ability.getAbility(AbilityID.summonBloodWraith);
            component.failsIfFailedAbility = true;

            // wraith mutator
            BloodWraithMutator mutator = abilityObject.AddComponent <BloodWraithMutator>();
            mutator.statList.AddRange(bloodWraithStats);
            mutator.increasedSize = increasedBloodWraithSize;
        }

        if (moreDamageAgainstBleeding != 0)
        {
            // create the conditional
            DamageConditionalEffect    conditionalEffect = new DamageConditionalEffect();
            HasStatusEffectConditional conditional       = new HasStatusEffectConditional();
            conditional.statusEffect      = StatusEffectID.Bleed;
            conditionalEffect.conditional = conditional;
            conditionalEffect.effect      = new DamageEffectMoreDamage(moreDamageAgainstBleeding);
            // add the conditional to all damage stats holders
            foreach (DamageStatsHolder holder in abilityObject.GetComponents <DamageStatsHolder>())
            {
                holder.baseDamageStats.conditionalEffects.Add(conditionalEffect);
            }
        }

        // increase radius
        float totalIncreasedArea = increasedArea;

        if (increasedArea != 0 || increasedAreaWith3OrMoreMinions != 0)
        {
            // calculate total increased area
            if (increasedAreaWith3OrMoreMinions != 0 && tracker && tracker.summons != null && tracker.summons.Count >= 3)
            {
                totalIncreasedArea += increasedAreaWith3OrMoreMinions;
            }

            // calculate increased radius
            float increasedRadius = Mathf.Sqrt(totalIncreasedArea + 1) - 1;;

            // apply increased radius
            if (increasedRadius != 0)
            {
                foreach (CreateOnDeath cod in abilityObject.GetComponents <CreateOnDeath>())
                {
                    cod.increasedRadius = increasedRadius;
                    cod.increasedHeight = increasedRadius;
                }
                foreach (SphereCollider col in abilityObject.GetComponents <SphereCollider>())
                {
                    col.radius *= (1 + increasedRadius);
                }
                foreach (CapsuleCollider col in abilityObject.GetComponents <CapsuleCollider>())
                {
                    col.radius *= (1 + increasedRadius);
                    col.height *= (1 + increasedRadius);
                }
            }
        }



        if (chanceToIgnite > 0)
        {
            ChanceToApplyStatusOnEnemyHit newComponent = abilityObject.AddComponent <ChanceToApplyStatusOnEnemyHit>();
            newComponent.statusEffect = StatusEffectList.getEffect(StatusEffectID.Ignite);
            newComponent.chance       = chanceToIgnite;
        }

        if (addedFireDamage > 0)
        {
            foreach (DamageStatsHolder holder in abilityObject.GetComponents <DamageStatsHolder>())
            {
                holder.addBaseDamage(DamageType.FIRE, addedFireDamage);
            }
        }

        if (increasedStunChance != 0)
        {
            foreach (DamageStatsHolder holder in abilityObject.GetComponents <DamageStatsHolder>())
            {
                holder.baseDamageStats.increasedStunChance += increasedStunChance;
            }
        }

        // increase damage based on the number of minions
        float realIncreasedDamage = increasedDamage;

        if (increasedDamagePerMinion != 0)
        {
            if (tracker && tracker.summons != null)
            {
                realIncreasedDamage += increasedDamagePerMinion * tracker.summons.Count;
            }
        }

        // increased damage if the minion has more health
        if (increasedDamageIfDetonatedMinionHasMoreHealth != 0 && tracker)
        {
            // get the likely target
            Summoned targetMinion = tracker.getNearestMinion(targetLocation);
            if (targetMinion)
            {
                // check if it has more health
                BaseHealth minionHealth = targetMinion.getBaseHealth();
                if (minionHealth && baseStats && baseStats.myHealth && minionHealth.currentHealth > baseStats.myHealth.currentHealth)
                {
                    realIncreasedDamage += increasedDamageIfDetonatedMinionHasMoreHealth;
                }
            }
        }

        // more damage if you only have one minion
        if (increasedDamageWithOneMinion != 0)
        {
            if (tracker && tracker.numberOfMinions() == 1)
            {
                realIncreasedDamage += increasedDamageWithOneMinion;
            }
        }

        // increase damage
        if (realIncreasedDamage != 0)
        {
            foreach (DamageStatsHolder holder in abilityObject.GetComponents <DamageStatsHolder>())
            {
                holder.increaseAllDamage(realIncreasedDamage);
            }
        }

        // chaining (mutator needs to be updated)
        if (chainsBetweenMinions)
        {
            CreateAbilityObjectOnNewAllyHit component = abilityObject.AddComponent <CreateAbilityObjectOnNewAllyHit>();
            component.abilityToInstantiate  = Ability.getAbility(AbilityID.sacrifice);
            component.onlyHitCreatorMinions = true;
            component.aimTowardsHit         = true;

            SacrificeMutator mutator = abilityObject.AddComponent <SacrificeMutator>();
            mutator.nova_increasedSpeed            = nova_increasedSpeed;
            mutator.nova_pierces                   = nova_pierces;
            mutator.nova_increasedDamage           = nova_increasedDamage;
            mutator.nova_increasedStunChance       = nova_increasedStunChance;
            mutator.nova_bleedChance               = nova_bleedChance;
            mutator.nova_addedCritChance           = nova_addedCritChance;
            mutator.nova_addedCritMultiplier       = nova_addedCritMultiplier;
            mutator.nova_moreDamageAgainstBleeding = nova_moreDamageAgainstBleeding;

            mutator.boneNovaChance = boneNovaChance;

            mutator.moreDamageAgainstBleeding = moreDamageAgainstBleeding;

            mutator.increasedStunChance = increasedStunChance;

            mutator.chanceToIgnite  = chanceToIgnite;
            mutator.addedFireDamage = addedFireDamage;

            mutator.bloodWraithChance = bloodWraithChance;
            mutator.bloodWraithStats  = new List <TaggedStatsHolder.TaggableStat>();
            mutator.bloodWraithStats.AddRange(bloodWraithStats);
            mutator.increasedBloodWraithSize = increasedBloodWraithSize;

            mutator.chainsBetweenMinions = true;

            // snap shot the damage increase and area increase
            mutator.increasedDamage = realIncreasedDamage;
            mutator.increasedArea   = totalIncreasedArea;
        }

        return(abilityObject);
    }