/// <summary> /// Generates a randomized value based on <see cref="effect"/> base value /// and random component. /// </summary> /// <param name="effect">The spell effect.</param> /// <returns>Random value depending on base points and dice roll.</returns> protected int RollEffectValue([NotNull] SpellEffectDefinitionDataModel effect) { if (effect == null) { throw new ArgumentNullException(nameof(effect)); } return(RandomGenerator.Value.Next(effect.EffectBasePoints, effect.EffectBasePoints + 1 + effect.EffectPointsDiceRange)); //+1 is due to exclusive. }
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."); } }
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)); }
public bool AddSpellEffectDefinition([NotNull] SpellEffectDefinitionDataModel spellEffectData) { if (spellEffectData == null) { throw new ArgumentNullException(nameof(spellEffectData)); } if (ContainsSpellEffectDefinition(spellEffectData.SpellEffectId)) { return(false); } SpellEffectMap.Add(spellEffectData.SpellEffectId, spellEffectData); return(true); }
public ISpellEffectTargetValidator Create([NotNull] SpellEffectDefinitionDataModel context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } long computedKeyValue = SpellEffectTargetingStrategyAttribute.ComputeKey(context.EffectTargetingType, context.AdditionalEffectTargetingType); if (ValidatorMap.ContainsKey(computedKeyValue)) { return(ValidatorMap[computedKeyValue]); } else { throw new KeyNotFoundException($"Key {computedKeyValue} for Effect target validator: {context.SpellEffectId} with TargetType: {context.EffectTargetingType}:{context.AdditionalEffectTargetingType} not found."); } }
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 abstract SpellEffectTargetContext CalculateTargets(SpellDefinitionDataModel spellDefinition, SpellEffectDefinitionDataModel spellEffect, DefaultEntityActorStateContainer actorState, IPendingSpellCastData pendingSpellCast);
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 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);