//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); } }
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 }
//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); }