示例#1
0
        public bool isSpellTargetViable(int spellId, [NotNull] DefaultEntityActorStateContainer actorState)
        {
            if (actorState == null)
            {
                throw new ArgumentNullException(nameof(actorState));
            }
            if (spellId <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(spellId));
            }

            SpellDefinitionDataModel definition = SpellDataCollection.GetSpellDefinition(spellId);

            foreach (var effect in SpellDataCollection.GetEffectsForSpell(spellId))
            {
                ISpellEffectTargetValidator effectTargetValidator = ValidatorFactory.Create(effect);

                //One effect's targets failed given the context. So this fails.
                if (!effectTargetValidator.ValidateTargetContext(definition, effect, actorState))
                {
                    return(false);
                }
            }

            return(true);
        }
示例#2
0
        protected override void HandleEvent(ActionBarButtonStateChangedEventArgs args)
        {
            //TODO: Check actionbar index and handle multiple rows.
            if (ActionBarRow.ContainsKey(args.Index))
            {
                IUIActionBarButton barButton = ActionBarRow[args.Index];

                if (args.ActionType == ActionBarIndexType.Empty)
                {
                    barButton.SetElementActive(false);
                }
                else
                {
                    barButton.SetElementActive(true);

                    //TODO: Refactor for spell/item
                    if (args.ActionType == ActionBarIndexType.Spell)
                    {
                        //TODO: Abstract the icon content loading
                        //TODO: Don't assume we have the content icon. Throw/log better exception
                        SpellDefinitionDataModel definition = SpellDataCollection.GetSpellDefinition(args.ActionId);
                        ContentIconInstanceModel icon       = ContentIconCollection[definition.SpellIconId];

                        ProjectVersionStage.AssertAlpha();
                        //TODO: Load async
                        Texture2D iconTexture = Resources.Load <Texture2D>(Path.Combine("Icon", Path.GetFileNameWithoutExtension(icon.IconPathName)));
                        barButton.ActionBarImageIcon.SetSpriteTexture(iconTexture);
                    }
                    else
                    {
                        throw new InvalidOperationException($"TODO: Implement empty/item action bar support");
                    }
                }
            }
        }
示例#3
0
        protected override bool ValidateTargeting(SpellDefinitionDataModel spellDefinition, SpellEffectDefinitionDataModel spellEffect, DefaultEntityActorStateContainer actorState)
        {
            if (spellDefinition == null)
            {
                throw new ArgumentNullException(nameof(spellDefinition));
            }
            if (spellEffect == null)
            {
                throw new ArgumentNullException(nameof(spellEffect));
            }
            if (actorState == null)
            {
                throw new ArgumentNullException(nameof(actorState));
            }

            NetworkEntityGuid guid = GetEntityTarget(actorState);

            //Does the entity exist, small window of time between valid cast start and now where entity can despawn
            //so minor chance it doesn't exist anymore.
            if (!KnownEntitySet.isEntityKnown(guid))
            {
                return(false);
            }

            //TODO: We shouldn't assume they are enemies just because they aren't use. We need a system for hostility masking for entities
            return(guid != NetworkEntityGuid.Empty && guid.EntityType == EntityType.Creature && guid != actorState.EntityGuid);
        }
示例#4
0
 protected override bool ValidateTargeting(SpellDefinitionDataModel spellDefinition, SpellEffectDefinitionDataModel spellEffect, DefaultEntityActorStateContainer actorState)
 {
     //Ally targeting is always valid. Even if targeting an enemy
     //This is because we'll just cast it on ourselves if we're
     //targeting an enemy.
     return(true);
 }
示例#5
0
        public BarCastingState(bool isSpellCasting, [CanBeNull][NotNull] SpellDefinitionDataModel spellDefinition, long startTimeStamp)
        {
            if (startTimeStamp < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(startTimeStamp));
            }

            this.isSpellCasting = isSpellCasting;
            SpellDefinition     = spellDefinition ?? throw new ArgumentNullException(nameof(spellDefinition));
            StartTimeStamp      = startTimeStamp;
        }
示例#6
0
        public ApplySpellEffectMessage Create([NotNull] SpellEffectApplicationMessageCreationContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            SpellDefinitionDataModel       spellDefinition  = SpellDataCollection.GetSpellDefinition(context.SpellId);
            SpellEffectDefinitionDataModel effectDefinition = SpellDataCollection.GetSpellEffectDefinition(spellDefinition.GetSpellEffectId(context.EffectIndex));

            return(new ApplySpellEffectMessage(context.ApplicationSource, spellDefinition, effectDefinition));
        }
示例#7
0
        public ApplySpellEffectMessage([NotNull] NetworkEntityGuid sourceCaster, [NotNull] SpellDefinitionDataModel spell, [NotNull] SpellEffectDefinitionDataModel spellEffect)
        {
            SourceCaster = sourceCaster ?? throw new ArgumentNullException(nameof(sourceCaster));
            Spell        = spell ?? throw new ArgumentNullException(nameof(spell));
            SpellEffect  = spellEffect ?? throw new ArgumentNullException(nameof(spellEffect));

            //TODO: Expand this to validate additional effects.
            if (spell.SpellEffectIdOne != SpellEffect.SpellEffectId)
            {
                throw new InvalidOperationException($"Cannot apply spell effect for Spell: {spell.SpellId} with Effect: {spellEffect.SpellEffectId} because the spell is not linked to that effect.");
            }
        }
示例#8
0
        public bool AddSpellDefinition([NotNull] SpellDefinitionDataModel spellData)
        {
            if (spellData == null)
            {
                throw new ArgumentNullException(nameof(spellData));
            }

            if (ContainsSpellDefinition(spellData.SpellId))
            {
                return(false);
            }

            SpellMap.Add(spellData.SpellId, spellData);
            return(true);
        }
示例#9
0
        public PendingSpellCastData Create([NotNull] PendingSpellCastCreationContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            ICancelable pendingSpellCastCancelable = new Cancelable(ActorScheduler);
            SpellDefinitionDataModel definition    = SpellDataCollection.GetSpellDefinition(context.SpellId);

            //We need to compute a timespan for the pending cast from the definition casting time.
            TimeSpan castTimeSpan       = definition.CastTime == 0 ? TimeSpan.Zero : TimeSpan.FromMilliseconds(definition.CastTime);
            long     startCastTime      = TimeService.CurrentLocalTime;
            long     expectedFinishTime = startCastTime + castTimeSpan.Ticks;

            return(new PendingSpellCastData(startCastTime, expectedFinishTime, context.SpellId, pendingSpellCastCancelable, castTimeSpan, context.CurrentTarget));
        }
示例#10
0
        public bool ValidateTargetContext([NotNull] SpellDefinitionDataModel spellDefinition, [NotNull] SpellEffectDefinitionDataModel spellEffect, [NotNull] DefaultEntityActorStateContainer actorState)
        {
            if (spellDefinition == null)
            {
                throw new ArgumentNullException(nameof(spellDefinition));
            }
            if (spellEffect == null)
            {
                throw new ArgumentNullException(nameof(spellEffect));
            }
            if (actorState == null)
            {
                throw new ArgumentNullException(nameof(actorState));
            }

            //We don't validate effect targeting matching the validators effect targeting
            //because a validator may have MULTIPLE targeting handling.

            return(ValidateTargeting(spellDefinition, spellEffect, actorState));
        }
示例#11
0
        public void DispatchSpellCast([NotNull] IPendingSpellCastData pendingSpellCast, DefaultEntityActorStateContainer casterData)
        {
            if (pendingSpellCast == null)
            {
                throw new ArgumentNullException(nameof(pendingSpellCast));
            }

            if (!SpellDataCollection.ContainsSpellDefinition(pendingSpellCast.SpellId))
            {
                throw new InvalidOperationException($"Tried to cast Spell: {pendingSpellCast.SpellId} but no definition exists.");
            }

            IActorRef casterActorReference           = ActorReferenceMappable.RetrieveEntity(casterData.EntityGuid);
            SpellDefinitionDataModel spellDefinition = SpellDataCollection.GetSpellDefinition(pendingSpellCast.SpellId);

            //Each spell can have N effects with individual unique targeting attributes.
            //So we need to handle each spell effect seperately, compute their effects/targets
            //and send an effect application message to the involved actors.
            foreach (SpellEffectIndex effectIndex in spellDefinition.EnumerateSpellEffects())
            {
                SpellEffectDefinitionDataModel effectDefinition = SpellDataCollection.GetSpellEffectDefinition(spellDefinition.GetSpellEffectId(effectIndex));

                SpellEffectTargetContext targetContext = EffectTargetSelectorFactory
                                                         .Create(effectDefinition)
                                                         .CalculateTargets(spellDefinition, effectDefinition, casterData, pendingSpellCast);

                ApplySpellEffectMessage spellEffectApplicationMessage = SpellEffectApplicationMessageFactory.Create(new SpellEffectApplicationMessageCreationContext(casterData.EntityGuid, pendingSpellCast.SpellId, effectIndex));

                //For each actor target in the target context
                //we need to send the spell application message for handling
                foreach (var target in targetContext.SpellEffectTargets)
                {
                    if (Logger.IsDebugEnabled)
                    {
                        Logger.Debug($"Entity: {casterData.EntityGuid} casted spell with effect that targets Target: {target.Path.Name}");
                    }

                    target.Tell(spellEffectApplicationMessage, casterActorReference);
                }
            }
        }
示例#12
0
        public override SpellEffectTargetContext CalculateTargets([NotNull] SpellDefinitionDataModel spellDefinition, [NotNull] SpellEffectDefinitionDataModel spellEffect, [NotNull] DefaultEntityActorStateContainer actorState, [NotNull] IPendingSpellCastData pendingSpellCast)
        {
            if (spellDefinition == null)
            {
                throw new ArgumentNullException(nameof(spellDefinition));
            }
            if (spellEffect == null)
            {
                throw new ArgumentNullException(nameof(spellEffect));
            }
            if (actorState == null)
            {
                throw new ArgumentNullException(nameof(actorState));
            }
            if (pendingSpellCast == null)
            {
                throw new ArgumentNullException(nameof(pendingSpellCast));
            }

            return(new SpellEffectTargetContext(ComputeAllyTargets(pendingSpellCast, actorState)));
        }
示例#13
0
        protected override void OnEventFired(object source, SpellCastingStateChangedEventArgs args)
        {
            if (Logger.IsInfoEnabled)
            {
                Logger.Info($"Player started casting Spell: {args.CastingSpellId}");
            }

            //Spell casting stopped. Disable the bar.
            if (!args.isCasting)
            {
                CastingBar.SetElementActive(false);
                CastingBar.CastingBarFillable.FillAmount = 0;
                CastingState = new BarCastingState(false);
            }
            else
            {
                SpellDefinitionDataModel spellDefinition = SpellDataCollection.GetSpellDefinition(args.CastingSpellId);
                CastingState = new BarCastingState(true, spellDefinition, args.CastingStartTimeStamp);
                CastingBar.CastingBarSpellNameText.Text = spellDefinition.SpellName;
                CastingBar.SetElementActive(true);
            }
        }
示例#14
0
 public abstract SpellEffectTargetContext CalculateTargets(SpellDefinitionDataModel spellDefinition, SpellEffectDefinitionDataModel spellEffect, DefaultEntityActorStateContainer actorState, IPendingSpellCastData pendingSpellCast);
示例#15
0
 /// <summary>
 /// Parameters are never null.
 /// </summary>
 /// <param name="spellDefinition"></param>
 /// <param name="spellEffect"></param>
 /// <param name="actorState"></param>
 /// <returns></returns>
 protected abstract bool ValidateTargeting(SpellDefinitionDataModel spellDefinition, SpellEffectDefinitionDataModel spellEffect, DefaultEntityActorStateContainer actorState);