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); }
public SpellCastResult ValidateSpellCast(DefaultEntityActorStateContainer actorState, int spellId) { if (!TargetValidator.isSpellTargetViable(spellId, actorState)) { return(SpellCastResult.SPELL_FAILED_BAD_TARGETS); } return(SpellCastResult.SPELL_FAILED_SUCCESS); }
protected NetworkEntityGuid GetEntityTarget([NotNull] DefaultEntityActorStateContainer state) { if (state == null) { throw new ArgumentNullException(nameof(state)); } return(state.EntityData.GetEntityGuidValue(EntityObjectField.UNIT_FIELD_TARGET));; }
public SpellCastResult ValidateSpellCast(DefaultEntityActorStateContainer state, int spellId) { if (!MovementGeneratorMappable.RetrieveEntity(state.EntityGuid).isFinished) { return(SpellCastResult.SPELL_FAILED_MOVING); } return(SpellCastResult.SPELL_FAILED_SUCCESS); }
public SpellEffectTargetCreationContext(int spellId, SpellEffectIndex effectIndex, [NotNull] DefaultEntityActorStateContainer actorState) { if (spellId <= 0) { throw new ArgumentOutOfRangeException(nameof(spellId)); } SpellId = spellId; EffectIndex = effectIndex; ActorState = actorState ?? throw new ArgumentNullException(nameof(actorState)); }
public SpellCastResult ValidateSpellCast(DefaultEntityActorStateContainer state, int spellId) { if (PendingSpellCastMappable.ContainsKey(state.EntityGuid)) { PendingSpellCastData pendingCast = PendingSpellCastMappable.RetrieveEntity(state.EntityGuid); if (!pendingCast.IsSpellcastFinished(TimeService.CurrentLocalTime)) { return(SpellCastResult.SPELL_FAILED_SPELL_IN_PROGRESS); } } return(SpellCastResult.SPELL_FAILED_SUCCESS); }
public SpellCastResult ValidateSpellCast(DefaultEntityActorStateContainer actorState, int spellId) { foreach (var validator in Validators) { SpellCastResult result = validator.ValidateSpellCast(actorState, spellId); //If not successful we failed and no longer need to validate. We know something is wrong. if (result != SpellCastResult.SPELL_FAILED_SUCCESS) { return(result); } } return(SpellCastResult.SPELL_FAILED_SUCCESS); }
public SpellCastResult ValidateSpellCast([NotNull] DefaultEntityActorStateContainer actorState, int spellId) { if (actorState == null) { throw new ArgumentNullException(nameof(actorState)); } int level = actorState.EntityData.GetFieldValue <int>(BaseObjectField.UNIT_FIELD_LEVEL); //TODO: Support correct entity class type. //If it's a player and we don't know the spell. if (actorState.EntityGuid.EntityType == EntityType.Player && !LearnedSpells.IsSpellKnown(spellId, EntityPlayerClassType.Mage, level)) { return(SpellCastResult.SPELL_FAILED_NOT_KNOWN); } return(SpellCastResult.SPELL_FAILED_SUCCESS); }
public abstract SpellEffectTargetContext CalculateTargets(SpellDefinitionDataModel spellDefinition, SpellEffectDefinitionDataModel spellEffect, DefaultEntityActorStateContainer actorState, IPendingSpellCastData pendingSpellCast);
public IEnumerable <IActorRef> ComputeAllyTargets([NotNull] IPendingSpellCastData pendingSpellData, [NotNull] DefaultEntityActorStateContainer actorState) { if (pendingSpellData == null) { throw new ArgumentNullException(nameof(pendingSpellData)); } if (actorState == null) { throw new ArgumentNullException(nameof(actorState)); } //TODO: Handle hostility calculation. Right now it just only supports player targeting, and opts to self target if targeting a creature. yield return(pendingSpellData.SnapshotEntityTarget.EntityType == EntityType.Player ? ActorReferenceMappable.RetrieveEntity(pendingSpellData.SnapshotEntityTarget) : ActorReferenceMappable.RetrieveEntity(actorState.EntityGuid)); }
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))); }
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); }
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); }
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); } } }
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)); }
/// <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);