コード例 #1
0
    // Use this for initialization
    void Start()
    {
        mutatorManager      = GetComponent <AbilityMutatorManager>();
        myAlignmentManager  = GetComponent <AlignmentManager>();
        myTaggedStatsHolder = GetComponent <TaggedStatsHolder>();

        myCreationReferences = GetComponent <CreationReferences>();
        myHitDetector        = GetComponent <HitDetector>();
    }
    public void Apply(GameObject hitObject)
    {
        GameObject        effect              = Instantiate(statusEffect.effectObject, hitObject.transform);
        StatusDamage      statusDamage        = effect.GetComponent <StatusDamage>();
        TaggedStatsHolder myTaggedStatsHolder = GetComponent <TaggedStatsHolder>();
        ProtectionClass   protection          = hitObject.GetComponent <ProtectionClass>();

        if (protection)
        {
            if (statusDamage && myTaggedStatsHolder)
            {
                TaggedStatsHolder taggedStatsHolder = effect.AddComponent <TaggedStatsHolder>();
                taggedStatsHolder.simpleStats.AddRange(myTaggedStatsHolder.simpleStats);
                taggedStatsHolder.taggedStats.AddRange(myTaggedStatsHolder.taggedStats);

                // apply DoT damage
                foreach (TaggedStatsHolder.TaggableStat taggableStat in taggedStatsHolder.taggedStats)
                {
                    if (taggableStat.tagList.Contains(Tags.AbilityTags.DoT))
                    {
                        taggableStat.tagList.Remove(Tags.AbilityTags.DoT);
                    }
                }
                // build damage stats if necessary
                foreach (DamageStatsHolder holder in effect.GetComponents <DamageStatsHolder>())
                {
                    holder.damageStats = DamageStats.buildDamageStats(holder, taggedStatsHolder);
                }
            }
            // add creation reference
            CreationReferences myReferences = GetComponent <CreationReferences>();
            if (myReferences)
            {
                CreationReferences references = effect.AddComponent <CreationReferences>();
                references.creator     = myReferences.creator;
                references.thisAbility = myReferences.thisAbility;
            }
            // add alignment
            AlignmentManager myAlignmentManager = GetComponent <AlignmentManager>();
            if (myAlignmentManager)
            {
                AlignmentManager alignmentManager = effect.AddComponent <AlignmentManager>();
                alignmentManager.alignment = myAlignmentManager.alignment;
            }
            // apply shock effect
            if (statusEffect.effectID == 13)
            {
                TaggedStatsHolder tsh = GetComponent <TaggedStatsHolder>();
                if (tsh)
                {
                    float      shockEffect = tsh.GetStatValue(Tags.Properties.IncreasedShockEffect);
                    BuffParent pb          = effect.GetComponent <BuffParent>();
                    if (shockEffect != 0 && pb)
                    {
                        foreach (TaggedStatsHolder.TaggableStat stat in pb.taggedStats)
                        {
                            stat.addedValue     *= (1 + shockEffect);
                            stat.increasedValue *= (1 + shockEffect);
                        }
                    }
                }
            }
            // apply
            protection.effectControl.AddEffect(effect, effect.GetComponent <StatusEffect>());
        }
    }
コード例 #3
0
    public GameObject constructAbilityObject(Ability ability, Vector3 location, Vector3 targetLocation, GameObject overridePrefab = null, bool InheritSharedHitDetector = true)
    {
        // create the ability object
        GameObject abilityObject = null;

        if (overridePrefab == null)
        {
            // if there is no override prefab instantiate the ability's ability prefab
            abilityObject = Instantiate(ability.abilityPrefab, location, Quaternion.Euler(targetLocation - location));
        }
        else // othewise instrantiate the override prefab
        {
            abilityObject = Instantiate(overridePrefab, location, Quaternion.Euler(targetLocation - location));
        }

        // apply the relevant mutator if this entity has one
        if (mutatorManager)
        {
            mutators = mutatorManager.getMutators(ability);
            if (mutators != null)
            {
                foreach (AbilityMutator mutator in mutators)
                {
                    abilityObject = mutator.Mutate(abilityObject, location, targetLocation);
                    if (mutator.changeLocation)
                    {
                        targetLocation = mutator.newLocation;
                    }
                    if (mutator.changeTargetLocation)
                    {
                        targetLocation = mutator.newTargetLocation;
                    }
                }
            }
        }

        // move the ability object if necessary
        foreach (DefineStartLocation defineStartLocation in abilityObject.GetComponents <DefineStartLocation>())
        {
            if (defineStartLocation.active)
            {
                defineStartLocation.setLocation(location, targetLocation);
                // the direction from the cast point needs to be maintained
                if (defineStartLocation.maintainDirectionFromCastPoint())
                {
                    targetLocation = abilityObject.transform.position + targetLocation - location;
                }
            }
        }


        // initialise a location detector if necessary
        LocationDetector locationDetector = abilityObject.GetComponent <LocationDetector>();

        if (locationDetector)
        {
            locationDetector.startLocation  = abilityObject.transform.position;
            locationDetector.targetLocation = targetLocation;
        }

        // rotate the ability object
        abilityObject.transform.LookAt(targetLocation);

        // give the ability object its alignment
        AlignmentManager abilityAlignmentManager = abilityObject.GetComponent <AlignmentManager>();

        if (!abilityAlignmentManager)
        {
            abilityAlignmentManager = abilityObject.AddComponent <AlignmentManager>();
        }
        abilityAlignmentManager.alignment = myAlignmentManager.alignment;

        // give the ability object its creation references
        CreationReferences abilityCreationReferences = abilityObject.GetComponent <CreationReferences>();

        if (!abilityCreationReferences)
        {
            abilityCreationReferences = abilityObject.AddComponent <CreationReferences>();
        }
        abilityCreationReferences.thisAbility         = ability;
        abilityCreationReferences.locationCreatedFrom = location;
        // if this an ability object then the creator is this objects creator, otherwise the creator is this object
        if (myCreationReferences && GetComponent <AbilityObjectIndicator>())
        {
            abilityCreationReferences.creator = myCreationReferences.creator;
        }
        else
        {
            abilityCreationReferences.creator = gameObject;
        }

        // check whether there should be a shared hit detector
        HitDetector abilityHitDetector = abilityObject.GetComponent <HitDetector>();

        if (abilityHitDetector)
        {
            SharedHitDetector sharedHitDetector = null;
            if (myHitDetector && myHitDetector.sharedHitDetector && InheritSharedHitDetector)
            {
                sharedHitDetector = myHitDetector.sharedHitDetector;
            }
            // create a shared hit detector
            else if (ability.sharedHitDetector)
            {
                GameObject newGameObject = new GameObject();
                sharedHitDetector = newGameObject.AddComponent <SharedHitDetector>();
                sharedHitDetector.gameObject.AddComponent <SelfDestroyer>();
                sharedHitDetector.name = abilityObject.name + "'s shared hit detector";
            }
            if (sharedHitDetector != null && !abilityHitDetector.cannotHaveSharedhitDetector)
            {
                abilityHitDetector.sharedHitDetector = sharedHitDetector;
            }
        }

        // build the damage stats for each damage stats holder
        foreach (DamageStatsHolder damageStatsHolder in abilityObject.GetComponents <DamageStatsHolder>())
        {
            damageStatsHolder.damageStats = DamageStats.buildDamageStats(damageStatsHolder, GetComponent <TaggedStatsHolder>());
        }

        // attach any on hit status appliers if this ability deals damage on hit
        if (myTaggedStatsHolder && abilityObject.GetComponent <DamageEnemyOnHit>() && !abilityObject.GetComponent <CannotApplyAdditionalStatuses>())
        {
            ChanceToApplyStatusOnEnemyHit applier;
            float poisonChance = myTaggedStatsHolder.GetStatValue(Tags.Properties.PoisonChance, ability.useTags);
            if (poisonChance > 0)
            {
                applier = abilityObject.AddComponent <ChanceToApplyStatusOnEnemyHit>();
                applier.statusEffect             = StatusEffectList.getEffect(StatusEffectID.Poison);
                applier.chance                   = poisonChance;
                applier.canApplyToSameEnemyAgain = false;
            }
            float igniteChance = myTaggedStatsHolder.GetStatValue(Tags.Properties.IgniteChance, ability.useTags);
            if (igniteChance > 0)
            {
                applier = abilityObject.AddComponent <ChanceToApplyStatusOnEnemyHit>();
                applier.statusEffect             = StatusEffectList.getEffect(StatusEffectID.Ignite);
                applier.chance                   = igniteChance;
                applier.canApplyToSameEnemyAgain = false;
            }
            float chillChance = myTaggedStatsHolder.GetStatValue(Tags.Properties.ChillChance, ability.useTags);
            if (chillChance > 0)
            {
                applier = abilityObject.AddComponent <ChanceToApplyStatusOnEnemyHit>();
                applier.statusEffect             = StatusEffectList.getEffect(StatusEffectID.Chill);
                applier.chance                   = chillChance;
                applier.canApplyToSameEnemyAgain = false;
            }
            float slowChance = myTaggedStatsHolder.GetStatValue(Tags.Properties.SlowChance, ability.useTags);
            if (slowChance > 0)
            {
                applier = abilityObject.AddComponent <ChanceToApplyStatusOnEnemyHit>();
                applier.statusEffect             = StatusEffectList.getEffect(StatusEffectID.Slow);
                applier.chance                   = slowChance;
                applier.canApplyToSameEnemyAgain = false;
            }
            float blindChance = myTaggedStatsHolder.GetStatValue(Tags.Properties.BlindChance, ability.useTags);
            if (blindChance > 0)
            {
                applier = abilityObject.AddComponent <ChanceToApplyStatusOnEnemyHit>();
                applier.statusEffect             = StatusEffectList.getEffect(StatusEffectID.Blind);
                applier.chance                   = blindChance;
                applier.canApplyToSameEnemyAgain = false;
            }

            float bleedChance = myTaggedStatsHolder.GetStatValue(Tags.Properties.BleedChance, ability.useTags);
            if (bleedChance > 0)
            {
                applier = abilityObject.AddComponent <ChanceToApplyStatusOnEnemyHit>();
                applier.statusEffect             = StatusEffectList.getEffect(StatusEffectID.Bleed);
                applier.chance                   = bleedChance;
                applier.canApplyToSameEnemyAgain = false;
            }
            float shockChance = myTaggedStatsHolder.GetStatValue(Tags.Properties.ShockChance, ability.useTags);
            if (shockChance > 0)
            {
                applier = abilityObject.AddComponent <ChanceToApplyStatusOnEnemyHit>();
                applier.statusEffect             = StatusEffectList.getEffect(StatusEffectID.Shock);
                applier.chance                   = shockChance;
                applier.canApplyToSameEnemyAgain = false;
            }
        }


        // if the ability has an ability object constructor give it a tagged stats holder with your tagged stats
        if (myTaggedStatsHolder && abilityObject.GetComponent <RequiresTaggedStats>())
        {
            TaggedStatsHolder holder = abilityObject.GetComponent <TaggedStatsHolder>();
            if (holder == null)
            {
                holder = abilityObject.AddComponent <TaggedStatsHolder>();
            }
            holder.simpleStats.AddRange(myTaggedStatsHolder.simpleStats);
            holder.taggedStats.AddRange(myTaggedStatsHolder.taggedStats);
        }

        // set the direction if there is an ability mover
        if (abilityObject.GetComponent <AbilityMover>())
        {
            abilityObject.GetComponent <AbilityMover>().positionDelta = Vector3.Normalize(targetLocation - location);
            // if the ability object defines its own start direction then let it
            if (abilityObject.GetComponent <DefineStartDirection>())
            {
                abilityObject.GetComponent <DefineStartDirection>().setDirection();
            }
        }

        // run any on creation methods
        foreach (OnCreation component in abilityObject.GetComponents <OnCreation>())
        {
            if (component.runOnCreation)
            {
                component.onCreation();
            }
        }

        // invoke the event
        if (abilityObjectCreatedEvent != null)
        {
            abilityObjectCreatedEvent.Invoke(ability, abilityObject);
        }

        return(abilityObject);
    }
コード例 #4
0
    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;
        }
    }