Example #1
0
        // Recursive algorithm that paints the tiles the character may move to. BLUE
        public void PaintPath(BattleTile current, int row, int col, int moves)
        {
            // Limits path range based on number of moves taken
            if (moves < 0)
            {
                return;
            }

            // Maximum range in the grid from anywhere in the grid.
            // Without this limit, the algorithm would continue to run needlessly
            if (moves > 9)
            {
                moves = 9;
            }

            // If the current tile is passed, paint it red so characters can skip turn.
            if (row == 0 && col == 0)
            {
                Grid[current.Column][current.Row].Highlight = "Blue";
            }

            // Updates the new position
            current.Row    += row;
            current.Column += col;

            // Tries to continue the path on all directions
            PaintPath(new BattleTile(current), 1, 0, moves - 1);
            PaintPath(new BattleTile(current), 0, 1, moves - 1);
            PaintPath(new BattleTile(current), -1, 0, moves - 1);
            PaintPath(new BattleTile(current), 0, -1, moves - 1);

            // Ensures path is within bounds
            if (current.Row >= 0 && current.Row < Grid[0].Count && current.Column >= 0 && current.Column < Grid.Count)
            {
                // Cannot pass by monsters but may pass by tiles and characters
                if (Grid[current.Column][current.Row].Type == "Monster")
                {
                    return;
                }

                //Mark path
                if (Grid[current.Column][current.Row].Type == "Tile")
                {
                    Grid[current.Column][current.Row].Highlight = "Blue";
                }
            }
        }
Example #2
0
        // Recursive algorithm that paints the grid in red to indicate range to attack.
        // Exclusively used by Characters to indicate their range.
        public void PaintWarPath(BattleTile current, int row, int col, int range)
        {
            // Limits path range based on number of moves taken
            if (range < 0)
            {
                return;
            }

            // Maximum range in the grid from anywhere in the grid.
            // Without this limit, the algorithm would continue to run needlessly
            if (range > 9)
            {
                range = 9;
            }

            // If the current tile is passed, paint it red so characters can skip turn.
            if (row == 0 && col == 0)
            {
                Grid[current.Column][current.Row].Highlight = "Red";
            }

            // Updates the new position
            current.Row    += row;
            current.Column += col;

            // Tries to continue the path on all directions
            PaintWarPath(new BattleTile(current), 1, 0, range - 1);
            PaintWarPath(new BattleTile(current), 0, 1, range - 1);
            PaintWarPath(new BattleTile(current), -1, 0, range - 1);
            PaintWarPath(new BattleTile(current), 0, -1, range - 1);

            // Ensures path is within bounds
            if (current.Row >= 0 && current.Row < Grid[0].Count && current.Column >= 0 && current.Column < Grid.Count)
            {
                // No friendly fire
                if (Grid[current.Column][current.Row].Type == "Character")
                {
                    return;
                }

                // Mark empty tiles to skip attack and Monsters to direct attack.
                if (Grid[current.Column][current.Row].Type == "Tile" || Grid[current.Column][current.Row].Type == "Monster")
                {
                    Grid[current.Column][current.Row].Highlight = "Red";
                }
            }
        }
Example #3
0
        // Algorithm that tries to move the monster closer to the target.
        public BattleTile MoveCloser(BattleTile target, BattleTile current)
        {
            TargetList = new List <BattleTile>();
            BattleTile newLocation = new BattleTile(current);

            MoveCloser(target, new BattleTile(current), 0, 0, current.GetMove());
            foreach (BattleTile t in TargetList)
            {
                // Manhattand Distance is used to select the closest tile to the target whether or not it is within range.
                if (ManhattanDistance(t.Row, t.Column, target.Row, target.Column) < ManhattanDistance(newLocation.Row, newLocation.Column, target.Row, target.Column))
                {
                    newLocation = t;
                }
            }

            // Returns the new monster location closest to the target. Might be the current location in which case the monster did not move.
            return(Grid[newLocation.Column][newLocation.Row]);
        }
Example #4
0
 // Constructor to make a new instance of a tile
 public BattleTile(BattleTile bt)
 {
     Type = bt.Type;
     if (bt.Type == "Monster")
     {
         Enemy = bt.Enemy;
     }
     if (bt.Type == "Character")
     {
         Hero = bt.Hero;
     }
     Row       = bt.Row;
     Column    = bt.Column;
     Highlight = bt.Highlight;
     Image     = bt.Image;
     Life      = bt.Life;
     Name      = bt.Name;
     Settings();
 }
Example #5
0
        // Recursive algorithm for pathfinding.
        public void MoveCloser(BattleTile target, BattleTile current, int row, int col, int moves)
        {
            // Limits path range based on number of moves taken
            if (moves < 0)
            {
                return;
            }

            // Moves to the next avaialable tile
            current.Row    += row;
            current.Column += col;
            MoveCloser(target, new BattleTile(current), 1, 0, moves - 1);
            MoveCloser(target, new BattleTile(current), 0, 1, moves - 1);
            MoveCloser(target, new BattleTile(current), -1, 0, moves - 1);
            MoveCloser(target, new BattleTile(current), 0, -1, moves - 1);

            // Adds the target to the taget list for comparison after the recursion.
            if (current.Row >= 0 && current.Row < Grid[0].Count && current.Column >= 0 && current.Column < Grid.Count && Grid[current.Column][current.Row].Type == "Tile")
            {
                TargetList.Add(Grid[current.Column][current.Row]);
            }
        }
Example #6
0
        // Generates a turnlist by grabbing all monsters and characters in the grid then arranging them by speed.
        public List <BattleTile> ComputeTurnList()
        {
            // Visit every tile in the Grid to identify all potential fighters
            List <BattleTile> turnList = new List <BattleTile>();

            for (int i = 0; i < Grid.Count; i++)
            {
                for (int j = 0; j < Grid[i].Count; j++)
                {
                    // If this tile is a fighter
                    BattleTile tempTile = Grid[i][j];
                    if (tempTile.Type != "Tile")
                    {
                        // Identify where in the turnlist this fighter will be inserted.
                        bool insterted = false;
                        for (var k = 0; k < turnList.Count && !insterted; k++)
                        {
                            // If the fighter from the grid is faster than the current fighter in the turnlist, insert the fighter
                            if (tempTile.GetSpeed() > turnList[k].GetSpeed())
                            {
                                insterted = true;
                                turnList.Insert(k, tempTile);
                            }
                            // If the fighter from the grid is of equal speed as the fighter in the turnlist, compare levels
                            else if (tempTile.GetSpeed() == turnList[k].GetSpeed())
                            {
                                // If the fighter from the grid is of a higher level than the current fighter in the turnlist, insert the fighter
                                if (tempTile.GetLevel() > turnList[k].GetLevel())
                                {
                                    insterted = true;
                                    turnList.Insert(k, tempTile);
                                }
                                // If the fighter from the grid is of equal speed as the fighter in the turnlist, compare experience
                                else if (tempTile.GetLevel() == turnList[k].GetLevel())
                                {
                                    // If the fighter from the grid is of a higher experience than the current fighter in the turnlist, insert the fighter
                                    // Experience for characters is their current XP and the experience for monsters is their current ExpToGive.
                                    if (tempTile.GetExperience() > turnList[k].GetExperience())
                                    {
                                        insterted = true;
                                        turnList.Insert(k, tempTile);
                                    }
                                    // If the fighter from the grid is of equal speed as the fighter in the turnlist, compare type
                                    else if (tempTile.GetExperience() == turnList[k].GetExperience())
                                    {
                                        // If the fighter from the grid is a Character and the current fighter in the turnlist is a Monster, insert the fighter
                                        if (tempTile.Type == "Character" && turnList[k].Type == "Monster")
                                        {
                                            insterted = true;
                                            turnList.Insert(k, tempTile);
                                        }
                                        // If the fighter from the grid is of equal type as the fighter in the turnlist, compare name
                                        else if (tempTile.Type == turnList[k].Type)
                                        {
                                            // If the fighter from the grid does not have the same name as the current fighter in the turnlist, check alphabetical order
                                            if (tempTile.Name != turnList[k].Name)
                                            {
                                                List <string> judge = new List <string>
                                                {
                                                    tempTile.Name,
                                                    turnList[k].Name
                                                };
                                                judge.Sort();

                                                // If the fighter from the grid is first based on alphabetical order for both names, insert the fighter
                                                if (tempTile.Name == judge[0])
                                                {
                                                    insterted = true;
                                                    turnList.Insert(k, tempTile);
                                                }
                                                // If the fighter from the grid is second based on alphabetical order for both names, check the next fighter.
                                            }
                                            // If they are equal then check the next fighter because this fighter came first in the list order.
                                        }
                                    }
                                }
                            }
                        }

                        // If the fighter is the slowest among the fighters in the turnlist
                        if (!insterted)
                        {
                            // Insert the fighter to the end of the list.
                            turnList.Add(tempTile);
                        }
                    }
                }
            }
            return(turnList);
        }
Example #7
0
        // AI for a Monster to make an attack.
        // Includes identifying the closest character
        // Moving closer to the character. Teleporting more like
        // Then attacking the target if within range.
        public string EnemyTakeTurn(int row, int column)
        {
            // Find target in the grid
            BattleTile target = new BattleTile();

            for (int i = 0; i < Grid.Count; i++)
            {
                for (int j = 0; j < Grid[i].Count; j++)
                {
                    // If a Character occupies the current grid access to determine if it is closer than current target.
                    if (Grid[i][j].Type == "Character")
                    {
                        // If the current target is just a tile or empty then assign the new target.
                        if (target.Type == "Tile")
                        {
                            target = Grid[i][j];
                        }
                        else
                        {
                            // If the current target and locations are both Characters, use ManhattanDistance to determine the closest one.
                            if (ManhattanDistance(target.Row, target.Column, row, column) > ManhattanDistance(j, i, row, column))
                            {
                                target = Grid[i][j];
                            }
                        }
                    }
                }
            }

            string battleText = "";
            // Move to target in the grid
            BattleTile current     = new BattleTile(Grid[column][row]);
            BattleTile newLocation = new BattleTile(MoveCloser(target, current));

            Grid[column][row] = new BattleTile(row, column);
            current.Row       = newLocation.Row;
            current.Column    = newLocation.Column;
            Grid[newLocation.Column][newLocation.Row] = current;

            // Cannot move any closer to the target so the Monster stays put
            if (row == newLocation.Row && column == newLocation.Column)
            {
                battleText += current.Name + " does not move.\n";
            }

            // Has successfully moved closer to the target.
            else
            {
                battleText += current.Name + " moves to Row " + newLocation.Row + " and Column " + newLocation.Column + ".\n";
            }

            // Try to attack target.
            if (ManhattanDistance(target.Row, target.Column, newLocation.Row, newLocation.Column) <= current.GetRange())
            {
                // Damage is attempted against the Character target.
                int    damage = target.DealtDamage(current);
                string status = target.DamageStatus;

                // Monster misses the attack.
                if (status == "Miss")
                {
                    battleText += current.Name + " misses attack against " + target.Name + ".\n";
                }

                // Monster hits the target.
                else if (status == "Hit")
                {
                    battleText += current.Name + " deals " + damage + " damage to " + target.Name + ".\n";
                }

                // Monster critically misses.
                else if (status == "Critical Miss")
                {
                    battleText  += current.Name + " CRITICALLY misses attack against " + target.Name + ".\n";
                    DamageStatus = "Critical Miss";

                    // Monster Criticaly hits.
                }
                else if (status == "Critical Hit")
                {
                    battleText  += current.Name + " deals " + damage + " CRITICAL damage to " + target.Name + ".\n";
                    DamageStatus = "Critical Hit";
                }
                target.DamageStatus = "";

                // If the target dies
                if (target.GetHealthCurr() <= 0)
                {
                    // Automatically resurect if the MostlyDead option is turned on.
                    if (BattleSystemViewModel.Instance.MostlyDead && target.MostlyDead)
                    {
                        target.MostlyDead      = false;
                        battleText            += "Miracle Max pops out of a drainage pipe steps on " + target.Name + " and brings him back to life.\n";
                        target.Hero.HealthCurr = target.Hero.Health;
                        target.Life            = "life" + (int)(((double)(target.Hero.HealthCurr + 1) / (double)(target.Hero.Health + 1)) * 10) + ".png";
                    }

                    // Otherwise the character dies and the state is saved.
                    else
                    {
                        battleText += target.Name + " dies from the damage.\n";
                        Grid[target.Column][target.Row] = new BattleTile(target.Row, target.Column);
                        recentlyDeceased = target;
                    }
                }
            }

            // Monster is not within range of its target.
            else
            {
                battleText += current.Name + " does not attack. \n";
            }

            // Returns the messages saved during combat.
            return(battleText);
        }
Example #8
0
        // Damage dealing function that works with either monster or character
        public int DealtDamage(BattleTile attacker)
        {
            BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Damage Calculation Begins"));
            // Roll 20 for attack type.
            Random rng  = new Random();
            int    roll = 1 + rng.Next(20);

            BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Rolled: " + roll));

            // Applies to hit Rule
            if (ToHit > 0)
            {
                roll = ToHit;
                BattleSystemViewModel.Instance.AddTxt(new StringWrapper("ToHit Applied: " + ToHit));
            }

            // Applies Miss at roll/ToHit 1 Rule
            if (Miss1 && roll == 1)
            {
                BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Missed"));
                DamageStatus = "Miss";
                return(0);
                // Applies Critical Miss at 1 rule
            }
            else if (CriticalMiss1 && roll == 1)
            {
                DamageStatus = "Critical Miss";
                BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Critical Miss"));
                return(0);
            }

            // Applies Hit at roll/ToHit 20 Rule
            bool hit           = false;
            bool criticalHit   = false;
            bool focusedAttack = false;

            if (Hit20 && roll == 20)
            {
                BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Hit20"));
                DamageStatus = "Hit";
                hit          = true;

                // Applies critical hit rule at 20
            }
            else if (Critical20 && roll == 20)
            {
                BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Critical Hit"));
                DamageStatus = "Critical Hit";
                criticalHit  = true;

                // Applies focused attack rule
            }
            else if (BattleSystemViewModel.Instance.FocusedAttack && BattleSystemViewModel.Instance.UseFocusedAttack)
            {
                if (attacker.Type == "Character" && attacker.Hero.UnequipAllItems().Count > 0)
                {
                    BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Focused Attack Applied"));
                    DamageStatus  = "Focused Attack";
                    FocusedAttack = true;
                }
            }

            BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Attacker Attack: " + attacker.GetAttack()));
            BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Attacker Level: " + attacker.GetLevel()));
            BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Target Defense: " + GetDefense()));
            BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Target Level: " + GetLevel()));
            // Hit Designation
            if (roll + attacker.GetLevel() + attacker.GetAttack() > GetDefense() + GetLevel() || hit || criticalHit || focusedAttack)
            {
                int damage = 0;
                BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Hit Success"));
                // Level Damage
                int lvlDamage = (int)(attacker.GetLevel() * .25) + 1;
                BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Level Damage: " + lvlDamage));
                BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Weapon Damage: " + attacker.GetDamage()));
                // Applies Disable RNG Rule
                if (DisableRNG)
                {
                    damage = attacker.GetDamage() + lvlDamage + attacker.GetAttack();
                    BattleSystemViewModel.Instance.AddTxt(new StringWrapper("RNG Disabled damage: " + damage));
                }

                // RNG enabled rule
                else
                {
                    Random weaponDamage = new Random();
                    damage = (1 + weaponDamage.Next(attacker.GetDamage() + attacker.GetAttack())) + lvlDamage;
                    BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Resulting Damage: " + damage));
                }

                // Critical hit doubles the damage dealt
                if (criticalHit)
                {
                    damage = 2 * damage;
                    BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Critical Applied damage: " + damage));
                }

                // Focused attack deals 10 times the damage dealt
                if (focusedAttack)
                {
                    damage = 10 * damage;
                    BattleSystemViewModel.Instance.AddTxt(new StringWrapper("Focus Attack Applied damage: " + damage));
                }

                // Update life bar of this Combatant
                UpdateLifeBar(damage);

                BattleSystemViewModel.Instance.AddTxt(new StringWrapper("End Damage"));
                // Return damage delt for recording
                return(damage);
            }
            // Missed
            return(0);
        }