예제 #1
0
    //execute move/attack for a single unit
    IEnumerator _MoveUnit(UnitTB unit)
    {
        //make sure no event is taking place
        while (GameControlTB.IsActionInProgress())
        {
            yield return(null);
        }

        if (!unit.IsStunned())
        {
            /*
             * DateTime timeS;
             * DateTime timeE;
             * TimeSpan timeSpan;
             * timeS=System.DateTime.Now;
             */

            Tile destinationTile = null;
            if (aIStance == _AIStance.Trigger)
            {
                if (unit.triggered)
                {
                    destinationTile = Analyse(unit);
                }
            }
            else
            {
                destinationTile = Analyse(unit);
            }

            //if there's target in current tile, just attack it
            if (destinationTile == unit.occupiedTile)
            {
                if (destinationTile.AIHostileList.Count != 0)
                {
                    //unit.Attack(destinationTile.AIHostileList[UnityEngine.Random.Range(0, destinationTile.AIHostileList.Count)]);
                    //unit will simply attack instead of move
                    if (!unit.MoveAttack(unit.occupiedTile))
                    {
                        NoActionForUnit(unit);
                    }
                }
                else
                {
                    unitInAction = false;
                }
                yield break;
            }

            if (destinationTile != null)
            {
                if (GameControlTB.EnableFogOfWar())
                {
                    bool visibleToPlayer = CheckEncounterOnPath(unit.occupiedTile, destinationTile);
                    if (visibleToPlayer)
                    {
                        if (!unit.MoveAttack(destinationTile))
                        {
                            NoActionForUnit(unit);
                        }
                    }
                    else
                    {
                        if (destinationTile.AIHostileList.Count == 0)
                        {
                            MoveUnitToTileInstant(unit, destinationTile);
                            unit.CompleteAllAction();
                        }
                        else
                        {
                            if (!unit.MoveAttack(destinationTile))
                            {
                                NoActionForUnit(unit);
                            }
                        }
                    }
                }
                else
                {
                    if (!unit.MoveAttack(destinationTile))
                    {
                        NoActionForUnit(unit);
                    }
                }
            }
            else
            {
                //no action is available for the unit, simply registred it as moved
                NoActionForUnit(unit);
            }

            /*
             * timeE=System.DateTime.Now;
             * timeSpan=timeE-timeS;
             * Debug.Log( "Time:"+timeSpan.TotalMilliseconds);
             */
        }
        else
        {
            NoActionForUnit(unit);
        }
    }
예제 #2
0
    void OnGUI()
    {
        //if(!battleStarted) return;
                #if customGui
        GUI.skin = Resources.Load("Skins/Fantasy-Colorable") as GUISkin;
                #endif

        DrawOverlay();

        List <UnitTB> unitList = UnitControl.GetAllUnit();

        int length = 40;
        int height = 3;

        for (int i = 0; i < unitList.Count; i++)
        {
            UnitTB unit = unitList[i];

            if (GameControlTB.EnableFogOfWar())
            {
                if (!unit.IsVisibleToPlayer())
                {
                    continue;
                }
            }



#if hoverInfo
            Camera  cam       = CameraControl.GetActiveCamera();
            Vector3 screenPos = cam.WorldToScreenPoint(unitList[i].thisT.position);
            screenPos.y = Screen.height - screenPos.y;

            int startPosX = (int)(screenPos.x - length / 2 + 7);
            int startPosY = (int)screenPos.y + 5;

            float hpRatio = (float)unit.HP / (float)unit.GetFullHP() * length;
            float apRatio = (float)unit.AP / (float)unit.GetFullAP() * length;


            GUIStyle style = new GUIStyle();
            style.fontStyle = FontStyle.Bold;

            style.fontSize = 20;



            style.fontSize = 20;      style.normal.textColor = UI.colorH;       style.alignment = TextAnchor.UpperCenter;
            GUI.Label(new Rect(startPosX - x_offset, startPosY + y_offset, 90, 90), "\n HP:" + unit.HP + "/" + unit.GetFullHP() + "\n AP:" + unit.AP + "/" + unit.GetFullAP(), style);


            GUI.color = Color.white;
            //draw the hp and AP
            //GUI.Box(new Rect(startPosX, startPosY-20, 200, 200), UI.texBar);
#else
            Camera  cam       = CameraControl.GetActiveCamera();
            Vector3 screenPos = cam.WorldToScreenPoint(unitList[i].thisT.position);
            screenPos.y = Screen.height - screenPos.y;

            int startPosX = (int)(screenPos.x - length / 2 + 7);
            int startPosY = (int)screenPos.y + 5;

            float hpRatio = (float)unit.HP / (float)unit.GetFullHP() * length;
            float apRatio = (float)unit.AP / (float)unit.GetFullAP() * length;

            GUI.color = new Color(.5f, .5f, .5f, 1);
            GUI.DrawTexture(new Rect(startPosX - 1, startPosY - 1, length + 2, 2 * height + 2), UI.texBar);
            GUI.color = Color.green;
            //TODO: Add the numbers for AP and HP here, we have startpos X and Y, and other values
            //are calculated elsewhere
            GUI.DrawTexture(new Rect(startPosX, startPosY, hpRatio, height), UI.texBar);
            //GUI.Label(new Rect(screenPos.x, screenPos.y, 500, 500), "5555");
            GUI.color = new Color(0f, 1f, 1f, 1);
            GUI.DrawTexture(new Rect(startPosX, startPosY + height, apRatio, height), UI.texBar);
            Texture fIcon = UnitControl.GetFactionIcon(unitList[i].factionID);
            if (fIcon != null)
            {
                fIcon = UI.texBar;
            }

            GUI.color = Color.white;
            GUI.DrawTexture(new Rect(startPosX - 15, startPosY - 5, 15, 15), UI.texBar);


            GUI.color = UnitControl.GetFactionColor(unit.factionID);
            GUI.DrawTexture(new Rect(startPosX - 14, startPosY - 4, 13, 13), UI.texBar);

            GUI.color = Color.white;
#endif
        }

        if (tileHovered != null)
        {
            DrawHoverInfo();
        }
        ///Draw text box with selected unit health and AP
                #if ibox
        /*
         *
         * void ShowTooltip(UnitAbility ability){
         * GUIStyle style=new GUIStyle();
         * style.fontStyle=FontStyle.Bold;
         *
         * int width=500;
         * int height=160;
         *
         *
         * for(int i=0; i<3; i++) GUI.Box(new Rect(Screen.width/2-width/2, Screen.height-230, width, height), "");
         *
         * style.fontSize=20;	style.normal.textColor=UI.colorH;	style.alignment=TextAnchor.UpperCenter;
         * GUI.Label(new Rect(Screen.width/2-width/2, Screen.height-220, width, height), ability.name, style);
         *
         * style.fontSize=16;	style.normal.textColor=UI.colorH;	style.alignment=TextAnchor.UpperRight;
         * GUI.Label(new Rect(Screen.width/2-width/2-5, Screen.height-220, width, height), ability.cost+"AP", style);
         *
         * style.fontSize=16;	style.normal.textColor=UI.colorN;	style.alignment=TextAnchor.UpperCenter;	style.wordWrap=true;
         * GUI.Label(new Rect(Screen.width/2-width/2, Screen.height-190, width, height), ability.desp, style);
         *
         * GUI.color=Color.white;
         * }
         * */

        if (UnitControl.selectedUnit != null)         //only perform this calculation once every second
        //get the selected unit
        {
            UnitTB selectedUnit = UnitControl.selectedUnit;
            string name         = selectedUnit.unitName;


            Camera  cam       = CameraControl.GetActiveCamera();
            Vector3 screenPos = cam.WorldToScreenPoint(UnitControl.selectedUnit.thisT.position);
            screenPos.y = Screen.height - screenPos.y;

            int startPosX = (int)(screenPos.x - length / 2 + 7);
            int startPosY = (int)screenPos.y + 5;



            styleA.fontSize = 20;



            styleA.fontSize = 20;     styleA.normal.textColor = UI.colorH;      styleA.alignment = TextAnchor.UpperCenter;


            GUI.Box(new Rect(startPosX - x_offset - 25, startPosY + y_offset, 140, 140), "");

            GUI.Label(new Rect(startPosX - x_offset - 25, startPosY + y_offset, 140, 140), "\n HP:" + UnitControl.selectedUnit.HP + "/" + UnitControl.selectedUnit.GetFullHP() + "\n AP:" + UnitControl.selectedUnit.AP + "/" + UnitControl.selectedUnit.GetFullAP() + "\n Moves:" + UnitControl.selectedUnit.moveRemain + "\n Attacks:" + UnitControl.selectedUnit.attackRemain, styleA);


            GUI.color = Color.white;


            GUIStyle style = new GUIStyle();
            style.fontStyle = FontStyle.Bold;

            int w = w_width;
            int h = w_height;

            style.fontSize = 20;

            style.fontSize = 20;      style.normal.textColor = UI.colorH;       style.alignment = TextAnchor.UpperCenter;
#if window
            //Color c = GUI.color;
            //GUI.color = Color.red;
            //windowRect0 = GUI.Window(0,windowRect0,DoMyWindow, "Green Window");
            //GUI.color = c;

                        #if devIbox
            GUI.Box(new Rect(Screen.width / 2 - 750 / 2, -80, 750, h), "");
            GUI.Label(new Rect(Screen.width / 2 - w / 2, 0, w, h), name + " HP:" + selectedUnit.HP + " AP:" + selectedUnit.AP + " Remaining Moves:" + selectedUnit.moveRemain + " Remaining Attacks: " + selectedUnit.attackRemain, style);
#endif
#if mo
            if (timeSinceCheck > .25)
            {
                //TODO: This method is not efficient, change it later
                //get the unit position
                //get the gameObject first
                GameObject g = selectedUnit.thisObj;
                //get the camera
                Camera  c         = GameObject.Find("MainCamera").GetComponent <Camera>();
                Vector3 screenPos = camera.WorldToScreenPoint(g.transform.position);

                Debug.Log(screenPos.x + " : " + screenPos.y);
                //put a simplified version of the ibox at the unit position
                GUI.Box(new Rect(screenPos.x, screenPos.y, 100, 30), "");
                GUI.Label(new Rect(screenPos.x, screenPos.y, 100, 30), " HP:" + selectedUnit.HP + " AP:" + selectedUnit.AP, style);
            }
#endif

            //print unit information
            //GUI.Label(new Rect(Screen.width/2-250, 0, 500, 20), name+" HP:"+selectedUnit.HP+" AP:"+selectedUnit.AP+" Remaining Moves:"+selectedUnit.moveRemain +" Remaining Attacks: " +selectedUnit.attackRemain);
            if (lastCheck >= waitTime)
            {
                lastCheck = 0;
                idleUnits = totalUnits;
                //get idle units
                //get an array of their units
                p_units = UnitControl.GetAllUnitsOfFaction(p_factionId);
                //loop through the array
                foreach (UnitTB unit in p_units)
                {
                    if (unit.AreAllActionsCompleted())
                    {
                        /*GameObject g = unit.thisObj;
                         * Renderer r = g.renderer;
                         * r.material.color = Color.grey;*/
                        idleUnits--;
                    }
                    else if (false)                     //TODO: if the unit has no more moves, cannot use an ability, and cannot attack anyone

                    {
                    }
                    //if a unit has moves left, or attacks left, increment idle units
                }
            }
            else
            {
                lastCheck += Time.deltaTime;
            }
            //print idle information
            if (idleUnits == 0)
            {
                //TODO: change coords to put it right above next turn button
                //GUI.Label(new Rect(Screen.width/2-w/2, 25, w, h), "All units have exhausted their moves, hit the next turn.", style);
                //only toggle glow once per turn
                if (!messageSent)
                {
                    BroadcastMessage("toggleGlow");
                    messageSent = true;
                }
                //GUI.Label (new Rect(Screen.width/2-250, 15, 500, 20), "All units have exhausted their moves, hit the next turn.");
            }
            else
            {
                BroadcastMessage("turnoffGlow");
                GUI.Label(new Rect(Screen.width - 100, Screen.height - 65 - 20, 60, 60), idleUnits + "/" + totalUnits + " idle units", style);

                //GUI.Label (new Rect(Screen.width/2-250, 15, 500, 20),idleUnits + "/"+ totalUnits + " units still have available actions.");
            }
#else
            GUI.Box(new Rect(Screen.width / 2 - 750 / 2, -80, 750, h), "");
            GUI.Label(new Rect(Screen.width / 2 - w / 2, 0, w, h), name + " HP:" + selectedUnit.HP + " AP:" + selectedUnit.AP + " Remaining Moves:" + selectedUnit.moveRemain + " Remaining Attacks: " + selectedUnit.attackRemain, style);

            //print unit information
            //GUI.Label(new Rect(Screen.width/2-250, 0, 500, 20), name+" HP:"+selectedUnit.HP+" AP:"+selectedUnit.AP+" Remaining Moves:"+selectedUnit.moveRemain +" Remaining Attacks: " +selectedUnit.attackRemain);
            if (lastCheck >= waitTime)
            {
                lastCheck = 0;
                idleUnits = totalUnits;
                //get idle units
                //get an array of their units
                p_units = UnitControl.GetAllUnitsOfFaction(p_factionId);
                //loop through the array
                foreach (UnitTB unit in p_units)
                {
                    if (unit.AreAllActionsCompleted())
                    {
                        idleUnits--;
                    }
                    else if (false)                     //TODO: if the unit has no more moves, cannot use an ability, and cannot attack anyone

                    {
                    }
                    //if a unit has moves left, or attacks left, increment idle units
                }
            }
            else
            {
                lastCheck += Time.deltaTime;
            }
            //print idle information
            if (idleUnits == 0)
            {
                GUI.Label(new Rect(Screen.width / 2 - w / 2, 25, w, h), "All units have exhausted their moves, hit the next turn.", style);
                //GUI.Label (new Rect(Screen.width/2-250, 15, 500, 20), "All units have exhausted their moves, hit the next turn.");
            }
            else
            {
                GUI.Label(new Rect(Screen.width / 2 - w / 2, 25, w, h), idleUnits + "/" + totalUnits + " units still have available actions.", style);

                //GUI.Label (new Rect(Screen.width/2-250, 15, 500, 20),idleUnits + "/"+ totalUnits + " units still have available actions.");
            }
#endif
        }
                #endif
    }
예제 #3
0
    //LOS and fog of war is not considered
    //that has already been built into various function called on UnitControl and GridManager
    public Tile Analyse(UnitTB unit)
    {
        //analyse current tile first
        List <UnitTB> currentHostilesList;

        if (!GameControlTB.EnableFogOfWar())
        {
            currentHostilesList = UnitControl.GetHostileInRangeFromTile(unit.occupiedTile, unit);
        }
        else
        {
            currentHostilesList = UnitControl.GetVisibleHostileInRangeFromTile(unit.occupiedTile, unit);
        }
        unit.occupiedTile.AIHostileList = currentHostilesList;

        if (GameControlTB.EnableCover())
        {
            if (currentHostilesList.Count != 0)
            {
                int count = 0;
                for (int n = 0; n < currentHostilesList.Count; n++)
                {
                    if ((int)unit.occupiedTile.GetCoverType(currentHostilesList[n].thisT.position) > 0)
                    {
                        count += 1;
                    }
                }
                if (count == currentHostilesList.Count)
                {
                    return(unit.occupiedTile);
                }
            }
        }
        else
        {
            if (currentHostilesList.Count != 0)
            {
                return(unit.occupiedTile);
            }
        }


        //get all possible target
        List <UnitTB> allHostiles = new List <UnitTB>();

        if (GameControlTB.EnableFogOfWar())
        {
            allHostiles = UnitControl.GetAllHostileWithinFactionSight(unit.factionID);
        }
        else
        {
            allHostiles = UnitControl.GetAllHostile(unit.factionID);
        }


        //if there's no potential target at all
        if (allHostiles.Count == 0)
        {
            if (unit.attackerList.Count > 0)
            {
                return(unit.attackerList[0].unit.occupiedTile);
            }
            else
            {
                //if stance is set to passive, stay put
                if (aIStance == _AIStance.Passive)
                {
                    return(unit.occupiedTile);
                }
            }
        }

        //get all walkable
        List <Tile> walkableTiles = GridManager.GetWalkableTilesWithinRange(unit.occupiedTile, unit.GetMoveRange());

        //get tiles with target in range from the walkables
        List <Tile> offensiveTiles = new List <Tile>();

        for (int i = 0; i < walkableTiles.Count; i++)
        {
            walkableTiles[i].AIHostileList = new List <UnitTB>();
            bool          visibleOnly  = GameControlTB.EnableFogOfWar();
            List <UnitTB> hostilesList = UnitControl.GetHostileInRangeFromTile(walkableTiles[i], unit, visibleOnly);
            walkableTiles[i].AIHostileList = hostilesList;
            if (hostilesList.Count > 0)
            {
                offensiveTiles.Add(walkableTiles[i]);
            }
        }

        //cross search any walkables with any tiles with target
        List <Tile> offensiveWalkableTiles = new List <Tile>();

        for (int i = 0; i < offensiveTiles.Count; i++)
        {
            if (walkableTiles.Contains(offensiveTiles[i]))
            {
                offensiveWalkableTiles.Add(offensiveTiles[i]);
            }
        }

        //if the game uses cover
        if (GameControlTB.EnableCover())
        {
            //calculating general direction of enemy, to know which direction to take cover from
            //Vector3 hostileAveragePos=Vector3.zero;
            //for(int i=0; i<allHostiles.Count; i++){
            //	hostileAveragePos+=allHostiles[i].occupiedTile.pos;
            //}
            //hostileAveragePos/=allHostiles.Count;


            //get offensive tile with cover from all hostile
            List <Tile> offensiveTilesWithAllCover     = new List <Tile>();
            List <Tile> offensiveTilesWithPartialCover = new List <Tile>();
            for (int i = 0; i < offensiveWalkableTiles.Count; i++)
            {
                Tile tile  = offensiveWalkableTiles[i];
                int  count = 0;
                for (int n = 0; n < tile.AIHostileList.Count; n++)
                {
                    if ((int)tile.GetCoverType(tile.AIHostileList[n].thisT.position) > 0)
                    {
                        count += 1;
                    }
                }
                if (count == tile.AIHostileList.Count)
                {
                    offensiveTilesWithAllCover.Add(tile);
                }
                else if (count > 0)
                {
                    offensiveTilesWithPartialCover.Add(tile);
                }
            }

            if (offensiveTilesWithAllCover.Count > 0)
            {
                int rand = UnityEngine.Random.Range(0, offensiveTilesWithAllCover.Count);
                return(offensiveTilesWithAllCover[rand]);
            }
            else if (offensiveTilesWithAllCover.Count > 0)
            {
                int rand = UnityEngine.Random.Range(0, offensiveTilesWithPartialCover.Count);
                return(offensiveTilesWithPartialCover[rand]);
            }


            //get any tile with possible cover from the walkables
            List <Tile> walkableTilesWithCover = new List <Tile>();
            for (int i = 0; i < walkableTiles.Count; i++)
            {
                if (walkableTiles[i].GotCover())
                {
                    walkableTilesWithCover.Add(walkableTiles[i]);
                }
            }

            //cross-search offense and walkable tile with cover
            //to get tiles which offer cover and the unit can attack from
            List <Tile> offensiveTilesWithCover = new List <Tile>();
            for (int i = 0; i < offensiveTiles.Count; i++)
            {
                if (walkableTilesWithCover.Contains(offensiveTiles[i]))
                {
                    offensiveTilesWithCover.Add(offensiveTiles[i]);
                }
            }

            //if there's any tile that offer cover and target at the same time, use the tile
            if (offensiveTilesWithCover.Count > 0)
            {
                int rand = UnityEngine.Random.Range(0, offensiveTilesWithCover.Count);
                return(offensiveTilesWithCover[rand]);
            }

            //if there's no tile that offer cover and target at the same time
            //just use any walkable tile with cover instead
            if (walkableTilesWithCover.Count > 0)
            {
                int rand = UnityEngine.Random.Range(0, walkableTilesWithCover.Count);
                return(walkableTilesWithCover[rand]);
            }
        }

        //if cover system is not used, or there's no cover in any walkable tiles
        //if there's walkable that the unit can attack from, uses that
        if (offensiveWalkableTiles.Count > 0)
        {
            int rand = UnityEngine.Random.Range(0, offensiveWalkableTiles.Count);
            return(offensiveWalkableTiles[rand]);
        }

        //check if the unit has been attacked, if yes, retaliate
        UnitTB attacker = unit.GetNearestAttacker();

        if (attacker != null)
        {
            return(attacker.occupiedTile);
        }


        //no hostile unit within range
        if (aIStance == _AIStance.Active || aIStance == _AIStance.Trigger)
        {
            //no hostile detected at all, just move randomly
            if (allHostiles.Count == 0)
            {
                if (walkableTiles.Count > 0)
                {
                    int rand = UnityEngine.Random.Range(0, walkableTiles.Count);
                    return(walkableTiles[rand]);
                }
            }
            //get the nearest target and move towards it
            else
            {
                int nearest   = 999999999;
                int nearestID = 0;
                for (int i = 0; i < allHostiles.Count; i++)
                {
                    int dist = GridManager.Distance(unit.occupiedTile, allHostiles[i].occupiedTile);
                    if (dist < nearest)
                    {
                        nearest   = dist;
                        nearestID = i;
                    }
                }
                return(allHostiles[nearestID].occupiedTile);
            }
        }

        return(null);
    }