Пример #1
0
    //colours and returns abialable tiles a selected unit can move to
    List <Terrain> UnitMove(Terrain Start, RPGClass Unit, GameObject[,,] Map)
    {
        //create the list I will eventually return, add the starting tile because of course a unit can go there
        List <Terrain> available = new List <Terrain> {
            Start
        };
        int movement = Unit.Stats[11].dynamicValue + 1;

        //temp. Get all the tiles surrounding the start without adjusting for movement cost or obstructions
        for (int i = 0; i < movement; i++)
        {
            for (int j = -i; j < i; j++)
            {
                int k = Mathf.Abs(j) - i;
                int a = Start.x - j;
                int b = Start.y + k;

                for (int doTwice = 0; doTwice < 2; doTwice++)
                {
                    if (a >= 0 && a < Map.GetLength(0) && b >= 0 && b < Map.GetLength(1))
                    {
                        //Terrain t = Map[a, b, 0].GetComponent<Terrain>();

                        //if (!available.Contains(t) && t.Tag != Terrain.tileTag.Wall && aStarPathfinding(Start, t, Unit, Map) )
                        //{
                        //    available.Add(Map[a, b, 0].GetComponent<Terrain>());
                        //}
                    }

                    if (doTwice == 0)
                    {
                        k = -Mathf.Abs(j) + i;
                        a = Start.x + j;
                        b = Start.y + k;
                    }
                }
            }
        }


        return(available);

        /*
         * List<int> coordinates = new List<int> { };
         *
         * int x = Location.x;
         * int y = Location.y;
         * GameObject aUI;
         * maxRange++;
         *
         * //for unit movement, minrange will always equal 0 since a unit can always at least travel to the tile they are on
         * for (int i = minRange; i < maxRange; i++)
         * {
         *  for (int j = -i; j < i; j++)
         *  {
         *      //this algorithm does not acount for varying costs of moving across a tile or tiles that can not be crossed
         *      int k = Mathf.Abs(j) - i;
         *      aUI = Instantiate(AttackUI, new Vector3(x - j, y + k), transform.rotation);
         *      aUI.GetComponent<DestroyOnBoolNotReset>().flagChecked = true;
         *
         *      k = ((x - j) * 1000) + (y + k);
         *      coordinates.Add(k);
         *
         *
         *      k = -Mathf.Abs(j) + i;
         *      aUI = Instantiate(AttackUI, new Vector3(x + j, y + k), transform.rotation);
         *      aUI.GetComponent<DestroyOnBoolNotReset>().flagChecked = true;
         *
         *      k = ((x - j) * 1000) + (y + k);
         *      coordinates.Add(k);
         *  }
         * }
         *
         * return coordinates;
         */
    }
Пример #2
0
    //find the shortest path to every tile in range
    protected Terrain[] DijkstraPath(Terrain Start, RPGClass Unit, GameObject[,,] map)
    {
        List <Terrain> visited = new List <Terrain> {
            Start
        };                                                      //this list contains the tiles that form the shortest path
        List <Terrain> unvisited = new List <Terrain> {
        };                                                      //this list contains the tiles being considered to add to the closed list

        int     move       = Unit.Stats[11].dynamicValue;
        Terrain mostRecent = Start;
        Terrain temp;

        Start.H = 0;

        do
        {
            //Add adjacent tiles to the list
            for (int i = 0; i < 4; i++)
            {
                temp = null;
                switch (i)
                {
                case 0: if (mostRecent.x + 1 < map.GetLength(0))
                    {
                        temp = map[mostRecent.x + 1, mostRecent.y, 0].GetComponent <Terrain>();
                    }
                    break;                                                                                                                              //right tile

                case 1: if (mostRecent.x - 1 >= 0)
                    {
                        temp = map[mostRecent.x - 1, mostRecent.y, 0].GetComponent <Terrain>();
                    }
                    break;                                                                                                                              //left tile

                case 2: if (mostRecent.y + 1 < map.GetLength(1))
                    {
                        temp = map[mostRecent.x, mostRecent.y + 1, 0].GetComponent <Terrain>();
                    }
                    break;                                                                                                                              //above tile

                case 3: if (mostRecent.y - 1 >= 0)
                    {
                        temp = map[mostRecent.x, mostRecent.y - 1, 0].GetComponent <Terrain>();
                    }
                    break;                                                                                                                              //below tile
                }
                //if an existing tile was found
                if (temp != null)
                {
                    temp.F = Unit.AdjustTileMovementCost(temp);

                    //ignore the tile if i have already visited it, or it is a wall, or there is not enough movement to pay for it
                    if (!visited.Contains(temp) && temp.Type != Terrain.Tile.Wall && mostRecent.H + temp.F <= move)
                    {
                        //if the checked tile is already on the unvisited list, check to see if this new path is shorter
                        if (unvisited.Contains(temp))
                        {
                            if (mostRecent.H + temp.F < temp.H)
                            {
                                temp.H = mostRecent.H + temp.F; temp.parent = mostRecent;
                            }
                        }
                        else                                     //otherwise, add it to the unvisited list
                        {
                            unvisited.Add(temp);                 //add to unvisited
                            temp.H      = mostRecent.H + temp.F; //update H for future comparison
                            temp.parent = mostRecent;            //update parent so a path can be formed as needed
                        }
                    }
                }   //temp check
            }       //for loop


            //sort list (lazily) so that the first result has the smallest H value
            for (int i = 1; i < unvisited.Count; i++)
            {
                if (unvisited[i].H < unvisited[0].H)
                {
                    temp         = unvisited[0];
                    unvisited[0] = unvisited[i];
                    unvisited[i] = temp;
                }
            }

            visited.Add(unvisited[0]);             //add the unvisted tile with the smallest F value to the visited list
            unvisited.Remove(unvisited[0]);        //remove the added tile from the unvisited list
            mostRecent = visited.Last <Terrain>(); //update the mostrecent tile
        } while (unvisited.Count > 0);             //if the cost of moving becomes greater than the avaialable movement, stop looping

        //reset the h values for future pathfindings... parent should not be reset so that it can be used in future.
        for (int i = 0; i < visited.Count; i++)
        {
            visited[i].H = Mathf.Infinity;
        }

        return(visited.ToArray());
    }
Пример #3
0
    //A little state machine to handle different actions depending on what is being done with the selected unit
    private void StateMachine(RPGClass Unit)
    {
        switch (Unit.CurrentState)
        {
        case Character._State.Selected:
            //Put up some indicators for movement, current pathm and attackable tiles
            Path = UpdateCurrentPath(LevelMap[Cursor.x, Cursor.y], Unit, Path, AvailableTilesForTravel);

            DisplayIndicator(Indicators[1], AvailableTilesForTravel);
            DisplayIndicator(Indicators[0], Path);
            DisplayIndicator(Indicators[2], RedTiles);

            //If the player wants to confirm movement, move the unit to the last tile on the path
            if (inputs.CheckSelectDown())
            {
                RPGClass temp = Cursor.GetUnitAtCursorPosition();
                if (temp == null || temp == SelectedUnit)
                {
                    Unit.CurrentState = Character._State.SelectingAction;

                    Unit.x = Path[Path.Length - 1].x; Unit.y = Path[Path.Length - 1].y;
                    AvailableTilesForAttack = GetRangeAtPoint(Unit.CombatParameters.EquipedWeapon, Path[Path.Length - 1], LevelMap);

                    SoundPlayer.clip = SelectNoise; SoundPlayer.Play();
                }
            }

            //If the player wants to cancel the selection, deselect the unit
            if (inputs.CheckCancelDown())
            {
                DeselectUnit(Character._State.Idle);
                SoundPlayer.clip = CancelNoise; SoundPlayer.Play();
            }

            break;

        case Character._State.SelectingAction:
            //Put up some indicators for what is in range
            DisplayIndicator(Indicators[2], AvailableTilesForAttack);


            //If the player wants to confirm an action
            if (inputs.CheckSelectDown())
            {
                RPGClass TempUnit = Cursor.GetUnitAtCursorPosition();

                if (TempUnit != null)
                {
                    //If the player clicks the selected unit they will begin waiting
                    if (TempUnit == Unit)
                    {
                        DeselectUnit(Character._State.Waiting); SoundPlayer.clip = SelectNoise; SoundPlayer.Play();
                    }

                    //If the player clicks an enemy unit, combat will begin
                    else if (!TempUnit.CompareTag(SelectedUnit.tag) && PathContains(LevelMap[TempUnit.x, TempUnit.y], AvailableTilesForAttack))
                    {
                        SelectedUnit.CurrentState = Character._State.InCombat;

                        //Set up the combat Manager with new stats
                        CombatManager cManager = gameObject.GetComponent <CombatManager>();
                        cManager.InitializeCombatParameters(Unit, TempUnit, LevelMap[Unit.x, Unit.y], LevelMap[TempUnit.x, TempUnit.y]);
                        //cManager.StartCombat();
                        SoundPlayer.clip = SelectNoise; SoundPlayer.Play();
                    }
                }
            }


            //If the player wants to cancel their move and put the unit back at the starting tile
            if (inputs.CheckCancelDown())
            {
                Unit.x = Path[0].x; Unit.y = Path[0].y;
                SetSelectedUnit(Unit, LevelMap);        //If I don't recalculate all of the pathfinding, the game crashes
                SoundPlayer.clip = CancelNoise; SoundPlayer.Play();
            }

            break;

        case Character._State.InCombat:
            getCombatInfo menu = FindObjectOfType <getCombatInfo>();
            CombatManager cMan = GetComponent <CombatManager>();

            RPGClass tempUnit;
            if (Unit != cMan.LeftSide.Unit)
            {
                tempUnit = cMan.LeftSide.Unit;
            }
            else
            {
                tempUnit = cMan.RightSide.Unit;
            }
            DisplayIndicator(Indicators[2], LevelMap[tempUnit.x, tempUnit.y]);

            //End combat after it has been run all the way
            if (!cMan.SimulateCombat)
            {
                if (menu.transform.parent.name == menu.DisabledView.name)
                {
                    DeselectUnit(Character._State.Waiting);
                }                                                   //Unit.CurrentState = Character._State.Waiting; }

                //on submit action, start combat (only while not already in combat)
                if (inputs.CheckSelectDown())
                {
                    cMan.StartCombat(); SoundPlayer.clip = SelectNoise; SoundPlayer.Play();
                }

                //on cancel action, go back 1 state
                if (inputs.CheckCancelDown())
                {
                    Unit.CurrentState = Character._State.SelectingAction; menu.CloseMenu(); SoundPlayer.clip = CancelNoise; SoundPlayer.Play();
                }
            }

            break;

        default:
            //If the selected unit gets put in an unintended state, deselect them and make them wait
            print("Defaulted. Previous State: " + Unit.CurrentState.ToString());
            DeselectUnit(Character._State.Waiting);
            break;
        }
    }
Пример #4
0
        public CombatStats(RPGClass Unit, Weapons Weapon)
        {
            //Set up stuff from parameters
            UnitReference = Unit;
            EquipedWeapon = Weapon;

            //Rip stats from unit
            Health        = Unit.Stats[(int)Stat.HitPoints].dynamicValue;
            Stress        = Unit.Stats[(int)Stat.StressPoints].dynamicValue;
            Defense       = Unit.Stats[(int)Stat.Defense].dynamicValue;
            Resistance    = Unit.Stats[(int)Stat.Resistance].dynamicValue;
            CriticalDodge = Unit.Stats[(int)Stat.Luck].dynamicValue;

            if (EquipedWeapon == null)
            {
                DamageType  = Weapons.Damage.Physical;
                HitChance   = CritChance = Attack = 0;
                AttackSpeed = Unit.Stats[(int)Stat.Speed].dynamicValue;
                Dodge       = (AttackSpeed * 2) + Unit.Stats[(int)Stat.Luck].dynamicValue;
            }
            else
            {
                DamageType = Weapon.DamageType;

                //Calculate Hit and Crit Chance
                HitChance  = (Unit.Stats[(int)Stat.Skill].dynamicValue * 2) + (Unit.Stats[(int)Stat.Luck].dynamicValue / 2) + Weapon.HitChance;
                CritChance = (Unit.Stats[(int)Stat.Skill].dynamicValue * 2) + (Unit.Stats[(int)Stat.Luck].dynamicValue / 4) + Weapon.CritChance;

                //Calculate Damage, Physical attacks use strength while magical attacks use magic
                if (DamageType == Weapons.Damage.Physical)
                {
                    Attack = Unit.Stats[(int)Stat.Strength].dynamicValue + Weapon.Might;
                }
                else if (DamageType == Weapons.Damage.Magical)
                {
                    Attack = Unit.Stats[(int)Stat.Magic].dynamicValue + Weapon.Might;
                }
                else
                {
                    Attack = 0;
                }

                //If a weapon is too heavy, give a penalty to speed. Otherwise, just use speed
                if (Unit.Stats[(int)Stat.Bulk].dynamicValue < Weapon.Weight)
                {
                    AttackSpeed = Unit.Stats[(int)Stat.Speed].dynamicValue + (Unit.Stats[(int)Stat.Bulk].dynamicValue - Weapon.Weight);
                }
                else
                {
                    AttackSpeed = Unit.Stats[(int)Stat.Speed].dynamicValue;
                }

                //Determine Dodge based off of the (potentially) modified speed stat
                Dodge = (AttackSpeed * 2) + Unit.Stats[(int)Stat.Luck].dynamicValue;

                //Determine Weapon Bonuses, Reward some combination of extra damage or hit damage
                //Check Weapon type first as different bonuses are rewarded to different weapons. Then Check weapon rank, higher rank = better bonus
                Weapons.Rank CharacterWeaponRank = Unit.WeaponStats[(int)Weapon.WeaponCategory].WeaponRank;
                switch (Weapon.WeaponCategory)
                {
                case (Weapons.WeaponType.Sword):
                case (Weapons.WeaponType.Staff):
                    switch (CharacterWeaponRank)
                    {
                    case (Weapons.Rank.C): Attack += 1; break;

                    case (Weapons.Rank.B): Attack += 2; break;

                    case (Weapons.Rank.A):
                    case (Weapons.Rank.S): Attack += 3; break;
                    }
                    break;

                case (Weapons.WeaponType.Lance):
                case (Weapons.WeaponType.Bow):
                case (Weapons.WeaponType.Arcane):
                case (Weapons.WeaponType.Divine):
                case (Weapons.WeaponType.Occult):
                    switch (CharacterWeaponRank)
                    {
                    case (Weapons.Rank.C): Attack += 1; break;

                    case (Weapons.Rank.B): Attack += 1; HitChance += 5; break;

                    case (Weapons.Rank.A):
                    case (Weapons.Rank.S): Attack += 2; HitChance += 5; break;
                    }
                    break;

                case (Weapons.WeaponType.Axe):
                    switch (CharacterWeaponRank)
                    {
                    case (Weapons.Rank.C): HitChance += 5; break;

                    case (Weapons.Rank.B): HitChance += 10; break;

                    case (Weapons.Rank.A):
                    case (Weapons.Rank.S): HitChance += 15; break;
                    }
                    break;
                }
            }
        }
Пример #5
0
    //Updates the path a unit will travel
    Terrain[] UpdateCurrentPath(Terrain NewTile, RPGClass Unit, Terrain[] CurrentPath, Terrain[] AvailableTiles)
    {
        //If the unit passed doesn't exsist, return a null
        if (Unit == null)
        {
            return(null);
        }
        //Check if the new tile is a tile that could be traveled to
        if (!PathContains(NewTile, AvailableTiles))
        {
            return(CurrentPath);
        }
        //Check if tile is the last tile on the path
        else if (NewTile == CurrentPath[CurrentPath.Length - 1])
        {
            return(CurrentPath);
        }
        //Check if the new tile is already on the current path
        else if (PathContains(NewTile, CurrentPath))
        {
            return(ShortenPath(NewTile, CurrentPath));
        }
        //Check if the new tile is adjacent to the last tile on the path
        else if (AdjacentTiles(NewTile, CurrentPath[CurrentPath.Length - 1]))
        {
            //Calculate the movement cost needed to add the tile
            int MoveCost = Unit.AdjustTileMovementCost(NewTile);
            for (int i = 1; i < CurrentPath.Length; i++)
            {
                MoveCost += Unit.AdjustTileMovementCost(CurrentPath[i]);
            }

            //Add the tile if it there is enough movement for it
            if (MoveCost <= Unit.Stats[(int)RPGClass.Stat.Move].dynamicValue)
            {
                Terrain[] NewPath = new Terrain[CurrentPath.Length + 1];

                for (int j = 0; j < CurrentPath.Length; j++)
                {
                    NewPath[j] = CurrentPath[j];
                }
                NewPath[CurrentPath.Length] = NewTile;

                return(NewPath);
            }
            //if there is not enough movement to pay for the tile, return a new shorter path
            else
            {
                return(ShortenPath(NewTile, CurrentPath[0]));
            }
        }
        //If all other checks fail, return the shortest path
        else
        {
            //print("all checks failed");
            Terrain[] temp = ShortenPath(NewTile, CurrentPath[0]);

            if (temp == null)
            {
                return(CurrentPath);
            }
            else
            {
                return(temp);
            }
        }
    }