Пример #1
0
 /// <summary>
 /// Apply the action's item to the given target.
 /// </summary>
 /// <returns>True if there was any effect on the target.</returns>
 private bool ApplyItem(Combatant itemTarget)
 {
     StatisticsValue effectStatistics = CalculateItemDamage(combatant, item);
     if (item.IsOffensive)
     {
         // calculate the defense
         Int32Range defenseRange = itemTarget.Character.MagicDefenseRange +
             itemTarget.Statistics.MagicalDefense;
         Int32 defense = defenseRange.GenerateValue(Session.Random);
         // subtract the defense
         effectStatistics -= new StatisticsValue(defense,
             defense, defense, defense, defense, defense);
         // make sure that this only contains damage
         effectStatistics.ApplyMinimum(new StatisticsValue());
         // damage the target
         itemTarget.Damage(effectStatistics, item.TargetDuration);
     }
     else
     {
         // make sure taht this only contains healing
         effectStatistics.ApplyMinimum(new StatisticsValue());
         // heal the target
         itemTarget.Heal(effectStatistics, item.TargetDuration);
     }
     return !effectStatistics.IsZero;
 }
Пример #2
0
        /// <summary>
        /// Constructs a new CombatAction object.
        /// </summary>
        /// <param name="combatant">The combatant performing the action.</param>
        public CombatAction(Combatant combatant)
        {
            // check the parameter
            if (combatant == null)
            {
                throw new ArgumentNullException("combatant");
            }

            // assign the parameter
            this.combatant = combatant;

            Reset();
        }
Пример #3
0
        /// <summary>
        /// Constructs a new SpellCombatAction object.
        /// </summary>
        /// <param name="character">The combatant performing the action.</param>
        public SpellCombatAction(Combatant combatant, Spell spell)
            : base(combatant)
        {
            // check the parameter
            if (spell == null)
            {
                throw new ArgumentNullException("spell");
            }

            // assign the parameter
            this.spell = spell;
            this.adjacentTargets = this.spell.AdjacentTargets;
        }
Пример #4
0
        /// <summary>
        /// Constructs a new ItemCombatAction object.
        /// </summary>
        /// <param name="character">The combatant performing the action.</param>
        public ItemCombatAction(Combatant combatant, Item item)
            : base(combatant)
        {
            // check the parameter
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            if ((item.Usage & Item.ItemUsage.Combat) == 0)
            {
                throw new ArgumentException("Combat items must have Combat usage.");
            }

            // assign the parameter
            this.item = item;
            this.adjacentTargets = this.item.AdjacentTargets;
        }
Пример #5
0
        /// <summary>
        /// Set the primary and any secondary targets.
        /// </summary>
        /// <param name="primaryTarget">The desired primary target.</param>
        /// <param name="adjacentTargets">
        /// The number of simultaneous, adjacent targets affected by this spell.
        /// </param>
        private void SetTargets(Combatant primaryTarget, int adjacentTargets)
        {
            // set the primary target
            this.primaryTargetedCombatant = primaryTarget;

            // set any secondary targets
            this.secondaryTargetedCombatants.Clear();
            if ((primaryTarget != null) && (adjacentTargets > 0))
            {
                // find out which side is targeted
                bool isPlayerTarget = primaryTarget is CombatantPlayer;
                // find the index
                int primaryTargetIndex = 0;
                if (isPlayerTarget)
                {
                    primaryTargetIndex = players.FindIndex(
                        delegate(CombatantPlayer player)
                        {
                            return (player == primaryTarget);
                        });
                }
                else
                {
                    primaryTargetIndex = monsters.FindIndex(
                        delegate(CombatantMonster monster)
                        {
                            return (monster == primaryTarget);
                        });
                }
                // add the surrounding indices
                for (int i = 1; i <= adjacentTargets; i++)
                {
                    int leftIndex = primaryTargetIndex - i;
                    if (leftIndex >= 0)
                    {
                        secondaryTargetedCombatants.Add(
                            isPlayerTarget ? players[leftIndex] as Combatant : 
                                monsters[leftIndex] as Combatant);
                    }
                    int rightIndex = primaryTargetIndex + i;
                    if (rightIndex < (isPlayerTarget ? players.Count : monsters.Count))
                    {
                        secondaryTargetedCombatants.Add(
                            isPlayerTarget ? players[rightIndex] as Combatant :
                            monsters[rightIndex] as Combatant);
                    }
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Starts a new combat stage.  Called right after the stage changes.
        /// </summary>
        /// <remarks>The stage never changes into NotStarted.</remarks>
        protected override void StartStage()
        {
            switch (stage)
            {
            case CombatActionStage.Preparing:     // called from Start()
            {
                // play the animations
                combatant.CombatSprite.PlayAnimation("SpellCast");
                spellSpritePosition = Combatant.Position;
                spell.SpellSprite.PlayAnimation("Creation");
                // remove the magic points
                Combatant.PayCostForSpell(spell);
            }
            break;

            case CombatActionStage.Advancing:
            {
                // play the animations
                spell.SpellSprite.PlayAnimation("Traveling");
                // calculate the projectile destination
                projectileDirection = Target.Position -
                                      Combatant.OriginalPosition;
                totalProjectileDistance = projectileDirection.Length();
                projectileDirection.Normalize();
                projectileDistanceCovered = 0f;
                // determine if the projectile is flipped
                if (Target.Position.X > Combatant.Position.X)
                {
                    projectileSpriteEffect = SpriteEffects.FlipHorizontally;
                }
                else
                {
                    projectileSpriteEffect = SpriteEffects.None;
                }
            }
            break;

            case CombatActionStage.Executing:
            {
                // play the animation
                spell.SpellSprite.PlayAnimation("Impact");
                // apply the spell effect to the primary target
                bool damagedAnyone = ApplySpell(Target);
                // apply the spell to the secondary targets
                foreach (Combatant targetCombatant in
                         CombatEngine.SecondaryTargetedCombatants)
                {
                    // skip dead or dying targets
                    if (targetCombatant.IsDeadOrDying)
                    {
                        continue;
                    }
                    // apply the spell
                    damagedAnyone |= ApplySpell(targetCombatant);
                }
                // play the impact sound effect
                if (damagedAnyone)
                {
                    AudioManager.PlayCue(spell.ImpactCueName);
                    if (spell.Overlay != null)
                    {
                        spell.Overlay.PlayAnimation(0);
                        spell.Overlay.ResetAnimation();
                    }
                }
            }
            break;

            case CombatActionStage.Returning:
                // play the animation
                combatant.CombatSprite.PlayAnimation("Idle");
                break;

            case CombatActionStage.Finishing:
                // play the animation
                combatant.CombatSprite.PlayAnimation("Idle");
                break;

            case CombatActionStage.Complete:
                // play the animation
                combatant.CombatSprite.PlayAnimation("Idle");
                // make sure that the overlay has stopped
                spell.Overlay.StopAnimation();
                break;
            }
        }
Пример #7
0
 /// <summary>
 /// Constructs a new DefendCombatAction object.
 /// </summary>
 /// <param name="character">The character performing the action.</param>
 public DefendCombatAction(Combatant combatant)
     : base(combatant)
 {
 }
Пример #8
0
        /// <summary>
        /// Calculate the spell damage done by the given combatant and spell.
        /// </summary>
        public static StatisticsValue CalculateSpellDamage(Combatant combatant, 
            Spell spell)
        {
            // check the parameters
            if (combatant == null)
            {
                throw new ArgumentNullException("combatant");
            }
            if (spell == null)
            {
                throw new ArgumentNullException("spell");
            }

            // get the magical offense from the character's class, gear, and bonuses
            // -- note that this includes stat buffs
            int magicalOffense = combatant.Statistics.MagicalOffense;

            // add the magical offense to the spell
            StatisticsValue damage = 
                spell.TargetEffectRange.GenerateValue(Session.Random);
            damage.HealthPoints += (damage.HealthPoints != 0) ? magicalOffense : 0;
            damage.MagicPoints += (damage.MagicPoints != 0) ? magicalOffense : 0;
            damage.PhysicalOffense += (damage.PhysicalOffense != 0) ? magicalOffense : 0;
            damage.PhysicalDefense += (damage.PhysicalDefense != 0) ? magicalOffense : 0;
            damage.MagicalOffense += (damage.MagicalOffense != 0) ? magicalOffense : 0;
            damage.MagicalDefense += (damage.MagicalDefense != 0) ? magicalOffense : 0;

            // add in the spell damage
            return damage;
        }
Пример #9
0
 /// <summary>
 /// Constructs a new MeleeCombatAction object.
 /// </summary>
 /// <param name="character">The character performing the action.</param>
 public MeleeCombatAction(Combatant combatant)
     : base(combatant)
 {
 }
Пример #10
0
 /// <summary>
 /// Constructs a new MeleeCombatAction object.
 /// </summary>
 /// <param name="character">The character performing the action.</param>
 public MeleeCombatAction(Combatant combatant)
     : base(combatant)
 {
 }
Пример #11
0
        /// <summary>
        /// Calculate the item damage done by the given combatant and item.
        /// </summary>
        public static StatisticsValue CalculateItemDamage(Combatant combatant,
            Item item)
        {
            // check the parameters
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            // generate a new effect value - no stats are involved for items
            return item.TargetEffectRange.GenerateValue(Session.Random);
        }
Пример #12
0
        /// <summary>
        /// Start the given player's combat turn.
        /// </summary>
        private void BeginPlayerTurn(CombatantPlayer player)
        {
            // check the parameter
            if (player == null)
            {
                throw new ArgumentNullException("player");
            }

            // set the highlight sprite
            highlightedCombatant = player;
            primaryTargetedCombatant = null;
            secondaryTargetedCombatants.Clear();

            Session.Hud.ActionText = "Choose an Action";
        }
Пример #13
0
        /// <summary>
        /// Update the combat engine for this frame.
        /// </summary>
        private void UpdateCombatEngine(GameTime gameTime)
        {
            // check for the end of combat
            if (ArePlayersDefeated)
            {
                EndCombat(CombatEndingState.Loss);
                return;
            }
            else if (AreMonstersDefeated)
            {
                EndCombat(CombatEndingState.Victory);
                return;
            }

            // update the target selections
            if ((highlightedCombatant != null) &&
                (highlightedCombatant.CombatAction != null))
            {
                SetTargets(highlightedCombatant.CombatAction.Target,
                    highlightedCombatant.CombatAction.AdjacentTargets);
            }

            //update active battle timers
            foreach (CombatantPlayer player in players)
            {
                if (player.AC > 5000 && player.readyForQueue)
                {
                    player.AC = 5000;

                    //add player if hes not already there
                    if (!selectionQueue.Contains(player))
                    {
                        selectionQueue.Enqueue(player);
                        player.readyForQueue = false;
                    }
                }
                else if(!player.IsDeadOrDying)
                    player.AC += gameTime.ElapsedGameTime.Milliseconds;

            }

            foreach (CombatantMonster monster in monsters)
            {
                if (monster.AC > 4000 && monster.readyForQueue)
                {
                    monster.AC = 4000;

                    //add player if hes not already there
                    if (!actionQueue.Contains(monster))
                    {
                        actionQueue.Enqueue(monster);
                        monster.readyForQueue = false;
                    }
                }
                else if(!monster.IsDeadOrDying)
                    monster.AC += gameTime.ElapsedGameTime.Milliseconds;
            }

            //show action menu if player's turn is ready
            if (selectionQueue.Count > 0 && !selectionQueueLocked)
            {
                if (currentSelector == null)
                {
                    isPlayersTurn = true;
                    currentSelector = selectionQueue.Peek();
                    currentSelector.IsTurnTaken = false;
                    BeginPlayerTurn((CombatantPlayer)selectionQueue.Peek());
                    selectionQueue.Dequeue();
                    selectionQueueLocked = true;
                }
            }

            //resolve actions
            bool removeAction = false;

            //remove dead people in the front of the queue
            while(actionQueue.Count > 0 && actionQueue.Peek().IsDeadOrDying)
                actionQueue.Dequeue();

            if (actionQueue.Count > 0 )
            {
                //unlock queue after current combatant finishes its action.
                if(currentCombatant != null)
                    if(currentCombatant.CombatAction == null)
                        actionQueueLocked = false;
                    else if(currentCombatant.CombatAction.Stage == CombatAction.CombatActionStage.NotStarted)
                        actionQueueLocked = false;

                if (actionQueue.Peek().GetType() == typeof(CombatantPlayer) && !actionQueueLocked)
                {
                    //execute player action
                    actionQueue.Peek().CombatAction.Start();

                    currentCombatant = actionQueue.Peek();
                    removeAction = true;
                }

                if (actionQueue.Peek().GetType() == typeof(CombatantMonster) && !actionQueueLocked)
                {
                    //execute monster action
                    BeginMonsterTurn((CombatantMonster)actionQueue.Peek() );

                    currentCombatant = actionQueue.Peek();
                    removeAction = true;
                }

                if (removeAction)
                {
                    actionQueue.Dequeue();
                    actionQueueLocked = true;
                }
            }

            // update the delay
            UpdateDelay(gameTime.ElapsedGameTime.Milliseconds);

            // UpdateDelay might cause combat to end due to a successful escape,
            // which will set the singleton to null.
            if (singleton == null)
            {
                return;
            }

            // update the players
            foreach (CombatantPlayer player in players)
            {
                player.Update(gameTime);
            }

            // update the monsters
            foreach (CombatantMonster monster in monsters)
            {
                monster.Update(gameTime);
            }

            // check for completion of the highlighted combatant
            if ((delayType == DelayType.NoDelay) &&
                (highlightedCombatant != null) && highlightedCombatant.IsTurnTaken)
            {
                delayType = DelayType.EndCharacterTurn;
            }

            // handle any player input
            HandleInput();
        }
Пример #14
0
        /// <summary>
        /// Handle player input that affects the combat engine.
        /// </summary>
        private void HandleInput()
        {
            // only accept input during the players' turn
            // -- exit game, etc. is handled by GameplayScreen
            if (!IsPlayersTurn || IsPlayersTurnComplete ||
                (highlightedCombatant == null))
            {
                return;
            }

            #if DEBUG
            // cheat key
            if (InputManager.IsGamePadRightShoulderTriggered() ||
                InputManager.IsKeyTriggered(Keys.W))
            {
                EndCombat(CombatEndingState.Victory);
                return;
            }
            #endif
            // handle input while choosing an action
            if (highlightedCombatant.CombatAction != null)
            {
                // skip if its turn is over or the action is already going
                if (highlightedCombatant.IsTurnTaken ||
                    (highlightedCombatant.CombatAction.Stage !=
                     CombatAction.CombatActionStage.NotStarted))
                {
                    return;
                }

                // back out of the action
                if (InputManager.IsActionTriggered(InputManager.Action.Back))
                {
                    highlightedCombatant.CombatAction = null;
                    SetTargets(null, 0);
                    return;
                }

                // start the action
                if (InputManager.IsActionTriggered(InputManager.Action.Ok))
                {
                    actionQueue.Enqueue(highlightedCombatant);
                    currentSelector = null;

                    highlightedCombatant.IsTurnTaken = true;
                    highlightedCombatant = null;
                    primaryTargetedCombatant = null;
                    secondaryTargetedCombatants.Clear();

                    isPlayersTurn = false;
                    selectionQueueLocked = false;

                    return;
                }

                // go to the next target
                if (InputManager.IsActionTriggered(InputManager.Action.TargetUp))
                {
                    // cycle through monsters or party members
                    if (highlightedCombatant.CombatAction.IsOffensive)
                    {
                        // find the index of the current target
                        int newIndex = monsters.FindIndex(
                            delegate(CombatantMonster monster)
                            {
                                return (primaryTargetedCombatant == monster);
                            });
                        // find the next living target
                        do
                        {
                            newIndex = (newIndex + 1) % monsters.Count;
                        }
                        while (monsters[newIndex].IsDeadOrDying);
                        // set the new target
                        highlightedCombatant.CombatAction.Target = monsters[newIndex];
                    }
                    else
                    {
                        // find the index of the current target
                        int newIndex = players.FindIndex(
                            delegate(CombatantPlayer player)
                            {
                                return (primaryTargetedCombatant == player);
                            });
                        // find the next active, living target
                        do
                        {
                            newIndex = (newIndex + 1) % players.Count;
                        }
                        while (players[newIndex].IsDeadOrDying);
                        // set the new target
                        highlightedCombatant.CombatAction.Target = players[newIndex];
                    }
                    return;
                }
                // go to the previous target
                else if (InputManager.IsActionTriggered(InputManager.Action.TargetDown))
                {
                    // cycle through monsters or party members
                    if (highlightedCombatant.CombatAction.IsOffensive)
                    {
                        // find the index of the current target
                        int newIndex = monsters.FindIndex(
                            delegate(CombatantMonster monster)
                            {
                                return (primaryTargetedCombatant == monster);
                            });
                        // find the previous active, living target
                        do
                        {
                            newIndex--;
                            while (newIndex < 0)
                            {
                                newIndex += monsters.Count;
                            }
                        }
                        while (monsters[newIndex].IsDeadOrDying);
                        // set the new target
                        highlightedCombatant.CombatAction.Target = monsters[newIndex];
                    }
                    else
                    {
                        // find the index of the current target
                        int newIndex = players.FindIndex(
                            delegate(CombatantPlayer player)
                            {
                                return (primaryTargetedCombatant == player);
                            });
                        // find the previous living target
                        do
                        {
                            newIndex--;
                            while (newIndex < 0)
                            {
                                newIndex += players.Count;
                            }
                        }
                        while (players[newIndex].IsDeadOrDying);
                        // set the new target
                        highlightedCombatant.CombatAction.Target = players[newIndex];
                    }
                    return;
                }
            }
            else // choosing which character will act
            {
                // move to the previous living character
                if (InputManager.IsActionTriggered(
                    InputManager.Action.ActiveCharacterLeft))
                {
                    int newHighlightedPlayer = highlightedPlayer;
                    do
                    {
                        newHighlightedPlayer--;
                        while (newHighlightedPlayer < 0)
                        {
                            newHighlightedPlayer += players.Count;
                        }
                    }
                    while (players[newHighlightedPlayer].IsDeadOrDying ||
                            players[newHighlightedPlayer].IsTurnTaken);
                    if (newHighlightedPlayer != highlightedPlayer)
                    {
                        highlightedPlayer = newHighlightedPlayer;
                        BeginPlayerTurn(players[highlightedPlayer]);
                    }
                    return;
                }
                // move to the next living character
                else if (InputManager.IsActionTriggered(
                    InputManager.Action.ActiveCharacterRight))
                {
                    int newHighlightedPlayer = highlightedPlayer;
                    do
                    {
                        newHighlightedPlayer =
                            (newHighlightedPlayer + 1) % players.Count;
                    }
                    while (players[newHighlightedPlayer].IsDeadOrDying ||
                            players[newHighlightedPlayer].IsTurnTaken);
                    if (newHighlightedPlayer != highlightedPlayer)
                    {
                        highlightedPlayer = newHighlightedPlayer;
                        BeginPlayerTurn(players[highlightedPlayer]);
                    }
                    return;
                }
                Session.Hud.UpdateActionsMenu();
            }
        }
Пример #15
0
        /// <summary>
        /// Start the given player's combat turn.
        /// </summary>
        private void BeginMonsterTurn(CombatantMonster monster)
        {
            // if it's null, find a random living monster who has yet to take their turn
            if (monster == null)
            {
                // don't bother if all monsters have finished
                if (IsMonstersTurnComplete)
                {
                    return;
                }
                // pick random living monsters who haven't taken their turn
                do
                {
                    monster = monsters[Session.Random.Next(monsters.Count)];
                }
                while (monster.IsTurnTaken || monster.IsDeadOrDying);
            }

            // set the highlight sprite
            highlightedCombatant = monster;
            primaryTargetedCombatant = null;
            secondaryTargetedCombatants.Clear();

            // choose the action immediate
            monster.CombatAction = monster.ArtificialIntelligence.ChooseAction();
        }
 /// <summary>
 /// Constructs a new DefendCombatAction object.
 /// </summary>
 /// <param name="character">The character performing the action.</param>
 public DefendCombatAction(Combatant combatant)
     : base(combatant)
 {
 }