示例#1
0
    public Summoned getNearestMinion(Vector3 point)
    {
        // make sure all summons in the list are valid
        summons.RemoveAll(x => x == null);

        // return if there are no summons
        if (summons.Count <= 0)
        {
            return(null);
        }

        // initialise the nearest as the first
        Summoned nearestSummon     = summons[0];
        float    nearestSquareDist = Maths.squareDistance(point, summons[0].transform.position);

        // try to find the nearest one
        float squareDist = 0;

        for (int i = 1; i < summons.Count; i++)
        {
            squareDist = Maths.squareDistance(point, summons[i].transform.position);
            if (squareDist < nearestSquareDist)
            {
                nearestSquareDist = squareDist;
                nearestSummon     = summons[i];
            }
        }

        // return the nearest one found
        return(nearestSummon);
    }
示例#2
0
 public void AddSummon(Summoned summon)
 {
     summons.Add(summon);
     if (newSummonEvent != null)
     {
         newSummonEvent.Invoke(summon);
     }
 }
示例#3
0
    public void onNewSummon(Summoned summon)
    {
        // subscribe to the death events of skeletal minions
        if (summon && summon.references && summon.references.thisAbility)
        {
            if (summon.references.thisAbility == ability || summon.references.thisAbility == summonWarrior || summon.references.thisAbility == summonMage ||
                summon.references.thisAbility == summonArcher || summon.references.thisAbility == summonWarlord || summon.references.thisAbility == summonBrawler)
            {
                Dying dying = summon.GetComponent <Dying>();
                if (!dying)
                {
                    Debug.LogError(summon.name + " does not have a Dying component yet, fix this script please"); return;
                }

                dying.deathEvent += OnSkeletonDeath;
            }
        }
    }
    // Use this for initialization
    public override void onCreation()
    {
        bool success = false;

        CreationReferences references = GetComponent <CreationReferences>();

        if (!references || !references.creator)
        {
            if (destroyIfFailedToMove)
            {
                SelfDestroyer dest = Comp <SelfDestroyer> .GetOrAdd(gameObject);

                dest.failedAbility = true;
                dest.die();
            }
            return;
        }

        SummonTracker tracker = references.creator.GetComponent <SummonTracker>();

        if (!tracker)
        {
            if (destroyIfFailedToMove)
            {
                SelfDestroyer dest = Comp <SelfDestroyer> .GetOrAdd(gameObject);

                dest.failedAbility = true;
                dest.die();
            }
            return;
        }

        // find a lit of summon
        List <Summoned> summons = new List <Summoned>();

        foreach (Summoned summoned in tracker.summons)
        {
            if (summoned)
            {
                summons.Add(summoned);
            }
        }
        // remove inactive objects from the list
        for (int i = summons.Count - 1; i >= 0; i--)
        {
            if (!summons[i].gameObject.activeSelf)
            {
                summons.Remove(summons[i]);
            }
        }
        // remove dying objects from the list
        if (requiredLifeState == lifeState.alive)
        {
            for (int i = summons.Count - 1; i >= 0; i--)
            {
                if (summons[i].GetComponent <Dying>() != null)
                {
                    if (summons[i].GetComponent <StateController>().currentState == summons[i].GetComponent <StateController>().dying)
                    {
                        summons.Remove(summons[i]);
                    }
                }
            }
        }
        // or remove living objects from the list
        else if (requiredLifeState == lifeState.dead)
        {
            for (int i = summons.Count - 1; i >= 0; i--)
            {
                if (summons[i].GetComponent <Dying>() != null)
                {
                    if (summons[i].GetComponent <StateController>().currentState != summons[i].GetComponent <StateController>().dying)
                    {
                        summons.Remove(summons[i]);
                    }
                }
                else
                {
                    summons.Remove(summons[i]);
                }
            }
        }
        if (summons.Count == 0)
        {
            if (destroyIfFailedToMove)
            {
                SelfDestroyer dest = Comp <SelfDestroyer> .GetOrAdd(gameObject);

                dest.failedAbility = true;
                dest.die();
            }
            return;
        }
        else
        {
            // find the nearest summon
            Summoned nearest  = summons[0];
            float    distance = Vector3.Distance(transform.position, nearest.transform.position);
            foreach (Summoned summon in summons)
            {
                if (Vector3.Distance(transform.position, summon.transform.position) < distance)
                {
                    nearest  = summon;
                    distance = Vector3.Distance(transform.position, summon.transform.position);
                }
            }

            // move to the summon's location
            transform.position = nearest.transform.position;
            // change to the summon's rotation
            transform.rotation = nearest.transform.rotation;

            success = true;

            if (kill)
            {
                Dying dying = nearest.GetComponent <Dying>();

                if (dying)
                {
                    if (eraseCorpse)
                    {
                        dying.setDelays(0.01f, 0.02f);
                    }

                    dying.myHealth.HealthDamage(dying.myHealth.maxHealth * 200);
                }
            }
        }
        if (destroyIfFailedToMove && success == false)
        {
            SelfDestroyer dest = Comp <SelfDestroyer> .GetOrAdd(gameObject);

            dest.failedAbility = true;
            dest.die();
        }
    }
    public void Summon()
    {
        for (int i = 0; i < numberToSummon; i++)
        {
            // get a reference to this objects creation references
            CreationReferences myReferences = GetComponent <CreationReferences>();

            // remove previous summons if necessary
            if (limitNumber && myReferences && attachCreationReferences && entity.GetComponent <Prefabs>())
            {
                abilitiesThatCountForLimit.Add(myReferences.thisAbility);
                List <GameObject> existingSummons = new List <GameObject>();
                foreach (Summoned summoned in Summoned.all)
                {
                    if (abilitiesThatCountForLimit.Contains(summoned.references.thisAbility))
                    {
                        if (summoned.references.creator = myReferences.creator)
                        {
                            existingSummons.Add(summoned.gameObject);
                        }
                    }
                }

                // components for removing summons
                SelfDestroyer selfDestroyer = null;
                Dying         dying         = null;

                while (existingSummons.Count >= limit)
                {
                    GameObject SummonToKill = getLowestPriority(existingSummons);
                    existingSummons.Remove(SummonToKill);

                    selfDestroyer = SummonToKill.GetComponent <SelfDestroyer>();
                    dying         = SummonToKill.GetComponent <Dying>();

                    // death events
                    if (dying && dying.getController())
                    {
                        dying.unsummoned = true;
                        dying.die();
                    }

                    // self destroyer events
                    if (selfDestroyer)
                    {
                        selfDestroyer.die();
                    }

                    // if neither exist, resort to destroying the game object
                    if (!dying && !selfDestroyer)
                    {
                        Destroy(SummonToKill);
                    }
                }
            }

            // decide the position
            Vector3 pos = displacement;
            if (distance > 0)
            {
                float angle = Random.Range(0, Mathf.PI * 2);
                pos = new Vector3(distance * Mathf.Cos(angle), displacement.y, distance * Mathf.Sin(angle));
            }

            pos = transform.position + pos;
            pos = new Vector3(pos.x, getY(pos), pos.z);

            // create the entity
            GameObject summon = Instantiate(entity, pos, Quaternion.Euler(0, 0, 0));

            // adapt the entity
            foreach (EntityAdapter adapter in GetComponents <EntityAdapter>())
            {
                summon = adapter.adapt(summon);
            }

            // attach creation references if necessary, if not then update them
            CreationReferences references = null;
            if (attachCreationReferences && myReferences != null)
            {
                if (!summon.GetComponent <CreationReferences>())
                {
                    references = summon.AddComponent <CreationReferences>();
                }
                else
                {
                    references = summon.GetComponent <CreationReferences>();
                }
                references.creator     = myReferences.creator;
                references.thisAbility = myReferences.thisAbility;
            }

            // add a summoned component
            Summoned summonedComponent = summon.AddComponent <Summoned>();
            summonedComponent.singeCardForAllMinions = singeCardForAllMinions;

            // initialise the summoned component
            summonedComponent.references = references;
            summonedComponent.initialise();

            //adds recent events tracker
            summon.AddComponent <CharacterStatusTracker>();

            // get a reference to the minion's stats
            BaseStats stats = summon.GetComponent <BaseStats>();

            // give it damage bonuses based on a tagged stats holder
            if (GetComponent <TaggedStatsHolder>() && stats)
            {
                TaggedStatsHolder holder = GetComponent <TaggedStatsHolder>();
                foreach (TaggedStatsHolder.TaggableStat ts in holder.taggedStats)
                {
                    List <Tags.AbilityTags> newTagList = new List <Tags.AbilityTags>();
                    newTagList.AddRange(ts.tagList);
                    if (newTagList.Contains(Tags.AbilityTags.Minion))
                    {
                        newTagList.Remove(Tags.AbilityTags.Minion);

                        stats.ChangeStatModifier(ts.property, ts.addedValue, BaseStats.ModType.ADDED, newTagList);
                        stats.ChangeStatModifier(ts.property, ts.increasedValue, BaseStats.ModType.INCREASED, newTagList);
                        foreach (float value in ts.moreValues)
                        {
                            stats.ChangeStatModifier(ts.property, value, BaseStats.ModType.MORE, newTagList);
                        }
                        foreach (float value in ts.quotientValues)
                        {
                            stats.ChangeStatModifier(ts.property, value, BaseStats.ModType.QUOTIENT, newTagList);
                        }
                    }
                }
            }

            // make it follow the creator if necessary
            if (followsCreator)
            {
                if (GetComponent <CreationReferences>())
                {
                    // if no follow ranges have been defined then use the defaults
                    if (followRangesAndPriorities.Count <= 0)
                    {
                        summon.AddComponent <Following>().leader = myReferences.creator;
                    }
                    // otherwise create follow states for each entry in the list
                    Following following;
                    foreach (FollowRangeAndPriority frar in followRangesAndPriorities)
                    {
                        following        = summon.AddComponent <Following>();
                        following.leader = myReferences.creator;
                        following.startFollowingRange = frar.range;
                        following.priority            = frar.priority;
                    }
                }
            }

            // make it move away from the creator when close if necessary
            if (movesAwayFromSummonerWhenClose)
            {
                if (myReferences)
                {
                    summon.AddComponent <MovingAwayFromSummoner>().summoner = myReferences.creator;
                }
            }

            // if necessary limit the duration by adding a destroy after duration component
            if (limitDuration)
            {
                // use a self destroyer if it has ones, otherwise use the dying state
                if (summon.GetComponent <SelfDestroyer>())
                {
                    DestroyAfterDuration destroyer = summon.AddComponent <DestroyAfterDuration>();
                    destroyer.duration = duration;
                }
                else
                {
                    DieAfterDelay destroyer = null;
                    if (!summon.GetComponent <DieAfterDelay>())
                    {
                        destroyer = summon.AddComponent <DieAfterDelay>();
                        destroyer.timeUntilDeath = duration;
                    }
                    // if there is already a destroy after duration component, lower the duration if this component's duration is lower than the one already there
                    else
                    {
                        destroyer = summon.GetComponent <DieAfterDelay>();
                        destroyer.timeUntilDeath = Mathf.Min(destroyer.timeUntilDeath, duration);
                    }
                    // make the destroyer unsummon rather than kill
                    if (destroyer)
                    {
                        destroyer.countsAsUnsummoned = true;
                    }
                }
            }

            // pass on alignment if necessary, may require an alignment manager to be added to the entity
            if (passOnAlignment && GetComponent <AlignmentManager>())
            {
                AlignmentManager alignmentManager = null;
                if (!summon.GetComponent <AlignmentManager>())
                {
                    alignmentManager = summon.AddComponent <AlignmentManager>();
                }
                else
                {
                    alignmentManager = summon.GetComponent <AlignmentManager>();
                }
                alignmentManager.alignment = GetComponent <AlignmentManager>().alignment;
            }

            // give the entity a custom name if necessary, may require a display information component to be added to the entity
            if (giveCustomName && customNames.Count > 0)
            {
                DisplayInformation displayInformation = null;
                if (!summon.GetComponent <DisplayInformation>())
                {
                    displayInformation = summon.AddComponent <DisplayInformation>();
                }
                else
                {
                    displayInformation = summon.GetComponent <DisplayInformation>();
                }
                int nameIndex = Random.Range(0, customNames.Count);
                displayInformation.displayName = customNames[nameIndex];
            }

            // add stats
            if (statList != null && statList.Count > 0)
            {
                if (stats)
                {
                    foreach (TaggedStatsHolder.TaggableStat stat in statList)
                    {
                        stats.addStat(stat);
                    }
                    stats.UpdateStats();
                    stats.myHealth.currentHealth = stats.myHealth.maxHealth;
                }
            }

            // give the entity a custom tag if necessary
            if (giveCustomTag)
            {
                summon.tag = customTag;
            }

            if (stats)
            {
                stats.UpdateStats();
                if (stats.myHealth)
                {
                    stats.myHealth.currentHealth = stats.myHealth.maxHealth;
                }
            }

            // pass on this summon information to a summonChangeTracker
            SummonChangeTracker sct = summon.AddComponent <SummonChangeTracker>();
            sct.statList.AddRange(statList);
            sct.limitDuration = limitDuration;

            sct.followsCreator            = followsCreator;
            sct.followRangesAndPriorities = new List <FollowRangeAndPriority>();
            sct.followRangesAndPriorities.AddRange(followRangesAndPriorities);

            sct.limitDuration = limitDuration;
            sct.duration      = duration;
        }
    }
示例#6
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);
    }
示例#7
0
 protected virtual void OnSummoned()
 {
     Summoned?.Invoke(this);
 }
示例#8
0
    public void Start()
    {
        CreationReferences references = GetComponent <CreationReferences>();

        if (references && references.creator)
        {
            SummonTracker summonTracker = references.creator.GetComponent <SummonTracker>();
            if (summonTracker)
            {
                List <Summoned> minionsToUse   = new List <Summoned>();
                List <Summoned> creatorMinions = summonTracker.summons;
                if (creatorMinions.Count > 0)
                {
                    // select minions
                    if (minionsToUseAbility == MinionUseType.Nearest)
                    {
                        Summoned selected         = creatorMinions[0];
                        float    selectedDistance = Vector3.Distance(transform.position, creatorMinions[0].transform.position);
                        float    distance         = 0;
                        foreach (Summoned minion in creatorMinions)
                        {
                            distance = Vector3.Distance(transform.position, minion.transform.position);
                            if (distance < selectedDistance && (!requiresCanUseMovementAbilities || minion.GetComponent <CanUseMovementAbilities>()))
                            {
                                selectedDistance = distance;
                                selected         = minion;
                            }
                        }
                        if (!requiresCanUseMovementAbilities || selected.GetComponent <CanUseMovementAbilities>())
                        {
                            minionsToUse.Add(selected);
                        }
                    }
                    else if (minionsToUseAbility == MinionUseType.Random)
                    {
                        int      attempts = 0;
                        Summoned selected = null;
                        while (attempts < 20)
                        {
                            selected = creatorMinions[Random.Range(0, creatorMinions.Count)];
                            if (!requiresCanUseMovementAbilities || selected.GetComponent <CanUseMovementAbilities>())
                            {
                                attempts = 100000;
                                minionsToUse.Add(selected);
                            }
                        }
                    }
                    else if (minionsToUseAbility == MinionUseType.All)
                    {
                        if (!requiresCanUseMovementAbilities)
                        {
                            minionsToUse.AddRange(creatorMinions);
                        }
                        else
                        {
                            foreach (Summoned minion in creatorMinions)
                            {
                                if (minion.GetComponent <CanUseMovementAbilities>())
                                {
                                    minionsToUse.Add(minion);
                                }
                            }
                        }
                    }
                    // make the minions use the ability
                    Vector3      targetPostion = GetComponent <LocationDetector>().targetLocation;
                    UsingAbility ua            = null;
                    foreach (Summoned minion in minionsToUse)
                    {
                        ua = minion.GetComponent <UsingAbility>();
                        if (ua)
                        {
                            ua.UseAbility(ability, targetPostion, false, false);
                            ua.transform.LookAt(targetPostion);
                        }
                    }
                }
            }
        }
    }