Exemple #1
0
        public Turn Run(float deltaTime)
        {
            var turn = new Turn() { TimeIndex = timeIndex };

            RunTriggers();

            RunActors(deltaTime, turn);

            RunProjectiles(deltaTime, turn);

            timeIndex++;

            return turn;
        }
Exemple #2
0
        private void RunProjectiles(float deltaTime, Turn turn)
        {
            foreach (var projectile in Projectiles.Where(x => x.IsAlive))
            {
                RunProjectile(deltaTime, turn, projectile);
            }

            Projectiles.RemoveAll(x => !x.IsAlive);
        }
Exemple #3
0
        private bool UseOrder(Turn turn, Actor actor, Order order)
        {
            var ability = order.Ability;

            if (!ability.Cooldown.IsReady)
                return false;

            if (ability.DamageType == DamageTypes.SingleTarget)
            {
                var abilityTarget = order.TargetActor;

                if (abilityTarget != null && abilityTarget.IsAlive)
                {
                    if (ability.TargettingType == TargettingTypes.Hostile && actor.Faction == abilityTarget.Faction)
                        return false;

                    if (ability.TargettingType == TargettingTypes.Friendly && actor.Faction != abilityTarget.Faction)
                        return false;

                    if (order.GetTargetLocation().DistanceFrom(actor).In(ability.Range + actor.Radius + abilityTarget.Radius))
                    {
                        actor.CurrentOrder = order;
                        actor.CastingProgress = new Cooldown(ability.Duration);
                        actor.CastingProgress.Incur();
                        if (ability.IsChanneled)
                        {
                            actor.ChannelProgress = new Cooldown(1.0f);
                            actor.ChannelProgress.Incur();
                        }

                        return true;
                    }
                }
            }
            else if (ability.DamageType == DamageTypes.PointBlankArea)
            {
                    actor.CurrentOrder = order;
                    actor.CastingProgress = new Cooldown(ability.Duration);
                    actor.CastingProgress.Incur();
                    if (ability.IsChanneled)
                    {
                        actor.ChannelProgress = new Cooldown(1.0f);
                        actor.ChannelProgress.Incur();
                    }

                    return true;
            }
            else if (ability.DamageType == DamageTypes.Cleave)
            {
                var primaryTarget = order.TargetActor;

                if (primaryTarget != null && primaryTarget.IsAlive)
                {
                    if (ability.TargettingType == TargettingTypes.Hostile && actor.Faction == primaryTarget.Faction)
                        return false;

                    if (ability.TargettingType == TargettingTypes.Friendly && actor.Faction != primaryTarget.Faction)
                        return false;

                    if (order.GetTargetLocation().DistanceFrom(actor).In(ability.Range + actor.Radius + order.GetTargetRadius()))
                    {
                        actor.CurrentOrder = order;
                        actor.CastingProgress = new Cooldown(ability.Duration);
                        actor.CastingProgress.Incur();
                        if (ability.IsChanneled)
                        {
                            actor.ChannelProgress = new Cooldown(1.0f);
                            actor.ChannelProgress.Incur();
                        }

                        return true;
                    }
                }
            }
            else if (ability.DamageType == DamageTypes.Location)
            {
                if (order.GetTargetLocation().DistanceFrom(actor).In(ability.Range + actor.Radius))
                {
                    actor.CurrentOrder = order;
                    actor.CastingProgress = new Cooldown(ability.Duration);
                    actor.CastingProgress.Incur();
                    if (ability.IsChanneled)
                    {
                        actor.ChannelProgress = new Cooldown(1.0f);
                        actor.ChannelProgress.Incur();
                    }

                    return true;
                }
            }

            return false;
        }
Exemple #4
0
 private void RunActors(float deltaTime, Turn turn)
 {
     foreach (var actor in Actors)
     {
         RunActor(deltaTime, turn, actor);
     }
 }
Exemple #5
0
        private void RunProjectile(float deltaTime, Turn turn, Projectile projectile)
        {
            MoveProjectile(deltaTime, projectile);

            if (projectile.Target.DistanceFrom(projectile.Position) < 0.75f)
            {
                var actor = projectile.Owner;
                var ability = projectile.Ability;
                var abilityTarget = projectile.Target;

                ApplyAbilityOutcome(turn, actor, ability, abilityTarget);

                projectile.IsAlive = false;
            }
        }
Exemple #6
0
        private void RunActor(float deltaTime, Turn turn, Actor actor)
        {
            // Aggro radius threat list calculations
            foreach (var other in Actors.Where(ba => ba.IsAlive))
            {
                var aggroRadius = 10f; // TODO: Remove hard coded aggro radius
                if (actor.DistanceFrom(other) < aggroRadius)
                    actor.ThreatList.Add(other);
            }

            // Drop dead actors from threat lists
            actor.ThreatList.RemoveAll(t => !t.Actor.IsAlive);

            // Drop dead targets from order lists
            actor.Orders.RemoveAll(o => o.HasExpired());

            while (actor.Targets.Any() && !actor.Targets.Peek().IsAlive)
                actor.Targets.Dequeue();

            // TODO: Remove hard coded mana regen
            actor.CurrentMana += 1f * deltaTime;
            // TODO: Remove hard coded energy regen
            actor.CurrentEnergy += 10f * deltaTime;

            CoolAbilities(deltaTime, actor);
            RunActorAuras(deltaTime, turn, actor);

            if (actor.IsAlive)
            {
                if (!actor.PlayerControlled)
                    actor.Orders.Clear();

                if (!actor.Orders.Any() && actor.CurrentOrder == null)
                    actor.FillOrderQueue();

                actor.SelectTarget(Actors.Where(x => x != actor));
                actor.PickDestination();

                if (actor.CastingProgress != null)
                {
                    RunAbilityCast(deltaTime, turn, actor);
                }
                else if (actor.Destination != null)
                {
                    actor.Move(deltaTime, Actors.Where(x => x.IsAlive && x != actor));
                }
                else
                {
                    if (actor.Orders.Any())
                    {
                        var order = actor.Orders.First();

                        if (UseOrder(turn, actor, order))
                        {
                            actor.Orders.Remove(order);
                        }
                    }
                }
            }
            else
            {
                actor.BaseAnimationState = BaseAnimationState.Dead;
            }

            if (actor.IsAlive && actor.CurrentHealth <= 0f)
            {
                KillActor(turn, actor);
            }
        }
Exemple #7
0
        private void RunActorAuras(float deltaTime, Turn turn, Actor actor)
        {
            var damageDone = 0f;

            foreach (var aura in actor.Auras)
            {
                aura.Cooldown.Cool(deltaTime);
                aura.Duration -= deltaTime;

                if (aura.Cooldown.IsReady)
                {
                    var combatTable = new CombatTable(new Random(), aura.Owner.CurrentStatistics, actor.CurrentStatistics);
                    var roll = combatTable.Roll();
                    var damage = aura.Damage.CalculateDamage(aura.Owner, actor);
                    var healing = aura.Healing.CalculateHealing(aura.Owner, actor);
                    if (roll.IsCrit)
                    {
                        damage *= 2;
                        healing *= 2;
                    }

                    if (damage > 0)
                    {
                        damageDone += damage;
                        Event.Raise(new ActorTookDamage { Source = aura.Owner, Target = actor, Damage = damage, IsCrit = roll.IsCrit });
                        turn.Events.Add(new OldEvent(EventTypes.AuraDamage) { Actor = aura.Owner, Target = actor, Damage = damage });
                        actor.CurrentHealth -= damage;
                    }
                    if (healing > 0)
                    {
                        Event.Raise(new ActorWasHealed { Source = aura.Owner, Target = actor, Healing = healing, IsCrit = roll.IsCrit });
                        turn.Events.Add(new OldEvent(EventTypes.AuraHealing) { Actor = aura.Owner, Target = actor, Healing = healing });
                        actor.CurrentHealth += healing;
                    }
                    aura.Cooldown.Incur();
                }
            }

            if (damageDone > 0)
                actor.Auras.RemoveAll(x => x.BreaksOnDamage);

            actor.Auras.ForEach(aura =>
            {
                if (aura.Duration <= 0f)
                {
                    turn.Events.Add(new OldEvent(EventTypes.AuraExpired) { Actor = actor, Target = actor });
                }
            });

            actor.Auras.RemoveAll(aura => aura.Duration <= 0f);
        }
Exemple #8
0
        private void KillActor(Turn turn, Actor actor)
        {
            actor.IsAlive = false;
            actor.Targets.Clear();
            actor.Auras.Clear();
            turn.Events.Add(new OldEvent(EventTypes.ActorDeath)
            {
                Actor = actor
            });

            foreach (var actorWithDeadTarget in Actors.Where(x => x.PlayerControlled))
            {
                while (actorWithDeadTarget.Targets.Any() && !actorWithDeadTarget.Targets.Peek().IsAlive)
                    actorWithDeadTarget.Targets.Dequeue();
            }
        }
Exemple #9
0
        private void RunAbilityCast(float deltaTime, Turn turn, Actor actor)
        {
            actor.CastingProgress.Cool(deltaTime);

            if (actor.ChannelProgress != null)
            {
                actor.ChannelProgress.Cool(deltaTime);

                if (actor.ChannelProgress.IsReady)
                {
                    ApplyChannelAbility(turn, actor, actor.CurrentOrder);
                }
            }
            else
            {
                if (actor.CastingProgress.IsReady)
                {
                    ApplyCastAbility(turn, actor, actor.CurrentOrder);
                }
            }
        }
Exemple #10
0
        private void ApplySingleTargetAbility(Turn turn, Actor actor, Ability ability, Actor abilityTarget)
        {
            if (ability.SpawnsProjectile != null)
            {
                SpawnProjectile(actor, abilityTarget, ability);
            }
            else
            {
                ApplyAbilityOutcome(turn, actor, ability, abilityTarget);
            }

            ability.Cooldown.Incur();
        }
Exemple #11
0
        private void ApplyPointBlankAreaAbility(Turn turn, Actor actor, Ability ability)
        {
            foreach (var target in Actors.Where(x => x.IsAlive))
            {
                if (ValidPointBlankAreaTarget(actor, target, ability))
                {
                    ApplyAbilityOutcome(turn, actor, ability, target);
                }
            }

            foreach (var animation in ability.Animations)
            {
                // TODO: This wont work if the same animation triggers on the same frame
                animation.Position = actor.Position;
                animation.Scale = ability.Area;
                GraphicEffects.Enqueue(animation);
            }

            ability.Cooldown.Incur();
        }
Exemple #12
0
        private void ApplyCleaveAbility(Turn turn, Actor actor, Ability ability, Actor primaryTarget)
        {
            foreach (var secondaryTarget in Actors.Where(x => x.IsAlive))
            {
                if ((secondaryTarget.DistanceFrom(primaryTarget) - primaryTarget.Radius - secondaryTarget.Radius) > ability.Area)
                    continue;

                if (secondaryTarget.Faction == actor.Faction && ability.TargettingType == TargettingTypes.Hostile)
                    continue;

                if (secondaryTarget.Faction != actor.Faction && ability.TargettingType == TargettingTypes.Friendly)
                    continue;

                if (ability.SpawnsProjectile != null)
                {
                    SpawnProjectile(actor, secondaryTarget, ability);
                }
                else
                {
                    ApplyAbilityOutcome(turn, actor, ability, secondaryTarget);
                }

                ability.Cooldown.Incur();
            }
        }
Exemple #13
0
        private void ApplyChannelAbility(Turn turn, Actor actor, Order order)
        {
            if (order.Ability.DamageType == DamageTypes.SingleTarget)
            {
                var abilityTarget = order.TargetActor;

                if (abilityTarget != null && abilityTarget.IsAlive)
                {
                    if (abilityTarget.DistanceFrom(actor).In(order.Ability.Range + actor.Radius + abilityTarget.Radius))
                        ApplySingleTargetAbility(turn, actor, order.Ability, abilityTarget);
                }
            }
            else if (order.Ability.DamageType == DamageTypes.PointBlankArea)
            {
                ApplyPointBlankAreaAbility(turn, actor, order.Ability);
            }
            else if (order.Ability.DamageType == DamageTypes.Cleave)
            {
                var primaryTarget = order.TargetActor;

                if (primaryTarget != null && primaryTarget.IsAlive)
                {
                    if (primaryTarget.DistanceFrom(actor).In(order.Ability.Range + actor.Radius + primaryTarget.Radius))
                        ApplyCleaveAbility(turn, actor, order.Ability, primaryTarget);
                }
            }
            else if (order.Ability.DamageType == DamageTypes.Location)
            {
                ApplyLocationAbility(turn, actor, order.Ability, order.TargetLocation.Value);
            }

            if (actor.CastingProgress.IsReady)
            {
                actor.CurrentOrder = null;
                actor.CastingProgress = null;
                actor.ChannelProgress = null;
            }
            else
            {
                actor.ChannelProgress.Incur();
            }
        }
Exemple #14
0
        private void ApplyAbilityOutcome(Turn turn, Actor actor, Ability ability, Actor target)
        {
            var combatTable = new CombatTable(random, actor.CurrentStatistics, target.CurrentStatistics, ability);
            var combatOutcome = combatTable.Roll();

            var abilityDamage = ability.Damage.CalculateDamage(actor, target);
            var abilityHealing = ability.Healing.CalculateHealing(actor, target);

            var damage = 0f;
            var damage2 = 0f;
            var healing = 0f;
            var blocked = 0f;

            if (combatOutcome.IsMiss)
                Event.Raise(new ActorMissed { Source = actor, Target = target });

            if (combatOutcome.IsDodge)
                Event.Raise(new ActorDodged { Source = actor, Target = target });

            if (combatOutcome.IsHit)
            {
                damage = abilityDamage;
                healing = abilityHealing;
            }

            if (combatOutcome.IsCrit)
            {
                damage = damage * 2f;
                healing = healing * 2f;
            }

            if (combatOutcome.IsBlock)
            {
                blocked = Math.Min(damage, actor.CurrentStatistics.For<Armor>().Rating * 0.1f);
                damage -= blocked;
                Event.Raise(new ActorBlocked { Source = actor, Target = target });
            }

            actor.CurrentMana -= ability.ManaCost;
            actor.CurrentEnergy -= ability.EnergyCost;

            if (damage > 0)
            {
                target.CurrentHealth -= (damage);
                Event.Raise(new ActorTookDamage { Source = actor, Target = target, Damage = damage, IsCrit = combatOutcome.IsCrit });

                actor.Auras.RemoveAll(x => x.BreaksOnDamage);
            }

            if (healing > 0)
            {
                target.CurrentHealth += (healing);
                Event.Raise(new ActorWasHealed { Source = actor, Target = target, Healing = healing, IsCrit = combatOutcome.IsCrit });
            }

            // Calculate damage threat
            target.ThreatList.Increase(actor, (int)(damage * ability.ThreatModifier));

            // Calculate healing threat for all enemies who knows the healer exists
            foreach (var enemyActor in Actors.Where(a => a.Faction != actor.Faction && a.ThreatList.Exists(healedActor => healedActor.Actor == target)))
            {
                enemyActor.ThreatList.Increase(actor, (int)(healing * 0.05f));
            }

            // Apply auras
            foreach (var aura in ability.AurasApplied)
            {
                target.Auras.Add(new Aura { Owner = actor, Cooldown = aura.Cooldown, Damage = aura.Damage, Healing = aura.Healing, Duration = aura.Duration, Name = aura.Name, Statistics = aura.Statistics, BreaksOnDamage = aura.BreaksOnDamage });
            }

            turn.Events.Add(new OldEvent(EventTypes.Ability)
            {
                Actor = actor,
                Target = target,
                Damage = damage,
                Damage2 = damage2,
                Healing = healing,
                Blocked = blocked,
                Ability = ability,
                CombatOutcome = combatOutcome
            });
        }