From 20f503adf5ded1044d0d8670a51407fff13756fb Mon Sep 17 00:00:00 2001 From: Angus Fan <33101170+Angus-Fan@users.noreply.github.com> Date: Tue, 3 Dec 2019 00:16:27 -0500 Subject: [PATCH] scripts that are used in the project --- ClickableTileScript.cs | 27 + Node.cs | 23 + Tile.cs | 33 ++ UnitScript.cs | 355 +++++++++++++ battleManagerScript.cs | 189 +++++++ camShakeScript.cs | 36 ++ gameManagerScript.cs | 794 ++++++++++++++++++++++++++++ gameSceneManager.cs | 48 ++ tileMapScript.cs | 1125 ++++++++++++++++++++++++++++++++++++++++ 9 files changed, 2630 insertions(+) create mode 100644 ClickableTileScript.cs create mode 100644 Node.cs create mode 100644 Tile.cs create mode 100644 UnitScript.cs create mode 100644 battleManagerScript.cs create mode 100644 camShakeScript.cs create mode 100644 gameManagerScript.cs create mode 100644 gameSceneManager.cs create mode 100644 tileMapScript.cs diff --git a/ClickableTileScript.cs b/ClickableTileScript.cs new file mode 100644 index 0000000..5a43e1f --- /dev/null +++ b/ClickableTileScript.cs @@ -0,0 +1,27 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class ClickableTileScript : MonoBehaviour +{ + //The x and y co-ordinate of the tile + public int tileX; + public int tileY; + //The unit on the tile + public GameObject unitOnTile; + public tileMapScript map; + + + /* + * This was used in Quill18Create'sTutorial, I no longer use this portion + private void OnMouseDown() + { + + Debug.Log("tile has been clicked"); + if (map.selectedUnit != null) + { + map.generatePathTo(tileX, tileY); + } + + }*/ +} diff --git a/Node.cs b/Node.cs new file mode 100644 index 0000000..36d77e1 --- /dev/null +++ b/Node.cs @@ -0,0 +1,23 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class Node { + + public List neighbours; + public int x; + public int y; + //Edges + public Node() + { + neighbours = new List(); + } + + public float DistanceTo(Node n) + { + return Vector2.Distance(new Vector2(x, y), new Vector2(n.x, n.y)); + } + + + +} diff --git a/Tile.cs b/Tile.cs new file mode 100644 index 0000000..340fb6e --- /dev/null +++ b/Tile.cs @@ -0,0 +1,33 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +[System.Serializable] +public class Tile +{ + + public string name; + public GameObject tileVisualPrefab; + public GameObject unitOnTile; + public float movementCost = 1; + public bool isWalkable=true; + + /* + private int x; + private int y; + + + + + public Tile( int xLocation, int yLocation) + { + x = xLocation; + y = yLocation; + } + + public void setCoords(int xLocation, int yLocation) + { + x = xLocation; + y = yLocation; + } + */ +} diff --git a/UnitScript.cs b/UnitScript.cs new file mode 100644 index 0000000..dbd8002 --- /dev/null +++ b/UnitScript.cs @@ -0,0 +1,355 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using TMPro; +using UnityEngine.UI; + +public class UnitScript : MonoBehaviour +{ + public int teamNum; + public int x; + public int y; + + //This is a low tier idea, don't use it + public bool coroutineRunning; + + //Meta defining play here + public Queue movementQueue; + public Queue combatQueue; + //This global variable is used to increase the units movementSpeed when travelling on the board + public float visualMovementSpeed = .15f; + + //Animator + public Animator animator; + + + public GameObject tileBeingOccupied; + + public GameObject damagedParticle; + //UnitStats + public string unitName; + public int moveSpeed = 2; + public int attackRange = 1; + public int attackDamage = 1; + public int maxHealthPoints = 5; + public int currentHealthPoints; + public Sprite unitSprite; + + [Header("UI Elements")] + //Unity UI References + public Canvas healthBarCanvas; + public TMP_Text hitPointsText; + public Image healthBar; + + public Canvas damagePopupCanvas; + public TMP_Text damagePopupText; + public Image damageBackdrop; + + + //This may change in the future if 2d sprites are used instead + //public Material unitMaterial; + //public Material unitWaitMaterial; + + public tileMapScript map; + + //Location for positional update + public Transform startPoint; + public Transform endPoint; + public float moveSpeedTime = 1f; + + //3D Model or 2D Sprite variables to check which version to use + //Make sure only one of them are enabled in the inspector + //public GameObject holder3D; + public GameObject holder2D; + // Total distance between the markers. + private float journeyLength; + + //Boolean to startTravelling + public bool unitInMovement; + + + //Enum for unit states + public enum movementStates + { + Unselected, + Selected, + Moved, + Wait + } + public movementStates unitMoveState; + + //Pathfinding + + public List path = null; + + //Path for moving unit's transform + public List pathForMovement = null; + public bool completedMovement = false; + + private void Awake() + { + + animator = holder2D.GetComponent(); + movementQueue = new Queue(); + combatQueue = new Queue(); + + + x = (int)transform.position.x; + y = (int)transform.position.z; + unitMoveState = movementStates.Unselected; + currentHealthPoints = maxHealthPoints; + hitPointsText.SetText(currentHealthPoints.ToString()); + + + } + + public void LateUpdate() + { + healthBarCanvas.transform.forward = Camera.main.transform.forward; + //damagePopupCanvas.transform.forward = Camera.main.transform.forward; + holder2D.transform.forward = Camera.main.transform.forward; + } + + public void MoveNextTile() + { + if (path.Count == 0) + { + return; + } + else + { + StartCoroutine(moveOverSeconds(transform.gameObject, path[path.Count - 1])); + } + + } + + + public void moveAgain() + { + + path = null; + setMovementState(0); + completedMovement = false; + gameObject.GetComponentInChildren().color = Color.white; + setIdleAnimation(); + //gameObject.GetComponentInChildren().material = unitMaterial; + } + public movementStates getMovementStateEnum(int i) + { + if (i == 0) + { + return movementStates.Unselected; + } + else if (i == 1) + { + return movementStates.Selected; + } + else if (i == 2) + { + return movementStates.Moved; + } + else if (i == 3) + { + return movementStates.Wait; + } + return movementStates.Unselected; + + } + public void setMovementState(int i) + { + if (i == 0) + { + unitMoveState = movementStates.Unselected; + } + else if (i == 1) + { + unitMoveState = movementStates.Selected; + } + else if (i == 2) + { + unitMoveState = movementStates.Moved; + } + else if (i == 3) + { + unitMoveState = movementStates.Wait; + } + + + } + public void updateHealthUI() + { + healthBar.fillAmount = (float)currentHealthPoints / maxHealthPoints; + hitPointsText.SetText(currentHealthPoints.ToString()); + } + public void dealDamage(int x) + { + currentHealthPoints = currentHealthPoints - x; + updateHealthUI(); + } + public void wait() + { + + gameObject.GetComponentInChildren().color = Color.gray; + //gameObject.GetComponentInChildren().material = unitWaitMaterial; + } + public void changeHealthBarColour(int i) + { + if (i == 0) + { + healthBar.color = Color.blue; + } + else if (i == 1) + { + + healthBar.color = Color.red; + } + } + public void unitDie() + { + if (holder2D.activeSelf) + { + StartCoroutine(fadeOut()); + StartCoroutine(checkIfRoutinesRunning()); + + } + + //Destroy(gameObject,2f); + /* + Renderer rend = GetComponentInChildren(); + Color c = rend.material.color; + c.a = 0f; + rend.material.color = c; + StartCoroutine(fadeOut(rend));*/ + + } + public IEnumerator checkIfRoutinesRunning() + { + while (combatQueue.Count>0) + { + + yield return new WaitForEndOfFrame(); + } + + Destroy(gameObject); + + } + public IEnumerator fadeOut() + { + + combatQueue.Enqueue(1); + //setDieAnimation(); + //yield return new WaitForSeconds(animator.GetCurrentAnimatorStateInfo(0).length); + Renderer rend = GetComponentInChildren(); + + for (float f = 1f; f >= .05; f -= 0.01f) + { + Color c = rend.material.color; + c.a = f; + rend.material.color = c; + yield return new WaitForEndOfFrame(); + } + combatQueue.Dequeue(); + + + } + public IEnumerator moveOverSeconds(GameObject objectToMove,Node endNode) + { + movementQueue.Enqueue(1); + + //remove first thing on path because, its the tile we are standing on + + path.RemoveAt(0); + while (path.Count != 0) + { + + Vector3 endPos = map.tileCoordToWorldCoord(path[0].x, path[0].y); + objectToMove.transform.position = Vector3.Lerp(transform.position, endPos, visualMovementSpeed); + if ((transform.position - endPos).sqrMagnitude < 0.001) + { + + path.RemoveAt(0); + + } + yield return new WaitForEndOfFrame(); + } + visualMovementSpeed = 0.15f; + transform.position = map.tileCoordToWorldCoord(endNode.x, endNode.y); + + x = endNode.x; + y = endNode.y; + tileBeingOccupied.GetComponent().unitOnTile = null; + tileBeingOccupied = map.tilesOnMap[x, y]; + movementQueue.Dequeue(); + + } + + + + public IEnumerator displayDamageEnum(int damageTaken) + { + + combatQueue.Enqueue(1); + + damagePopupText.SetText(damageTaken.ToString()); + damagePopupCanvas.enabled = true; + for (float f = 1f; f >=-0.01f; f -= 0.01f) + { + + Color backDrop = damageBackdrop.GetComponent().color; + Color damageValue = damagePopupText.color; + + backDrop.a = f; + damageValue.a = f; + damageBackdrop.GetComponent().color = backDrop; + damagePopupText.color = damageValue; + yield return new WaitForEndOfFrame(); + } + + //damagePopup.enabled = false; + combatQueue.Dequeue(); + + } + public void resetPath() + { + path = null; + completedMovement = false; + } + public void displayDamage(int damageTaken) + { + damagePopupCanvas.enabled = true; + damagePopupText.SetText(damageTaken.ToString()); + } + public void disableDisplayDamage() + { + damagePopupCanvas.enabled = false; + } + + public void setSelectedAnimation() + { + + animator.SetTrigger("toSelected"); + } + public void setIdleAnimation() + { + animator.SetTrigger("toIdle"); + } + public void setWalkingAnimation() + { + animator.SetTrigger("toWalking"); + } + + public void setAttackAnimation() + { + animator.SetTrigger("toAttacking"); + } + public void setWaitIdleAnimation() + { + + animator.SetTrigger("toIdleWait"); + } + + public void setDieAnimation() + { + animator.SetTrigger("dieTrigger"); + } +} diff --git a/battleManagerScript.cs b/battleManagerScript.cs new file mode 100644 index 0000000..f29d765 --- /dev/null +++ b/battleManagerScript.cs @@ -0,0 +1,189 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class battleManagerScript : MonoBehaviour +{ + //This script is for the battle system that this game uses + //The following variables are public for easy setting in the inspector + //They can be set to private if you can pull them into the inspector + public camShakeScript CSS; + public gameManagerScript GMS; + //This is used to check if the battle has been finished + private bool battleStatus; + + //In: two 'unit' game Objects the initiator is the unit that initiated the attack and the recipient is the receiver + //Out: void - units take damage or are destroyed if the hp threshold is <= + //Desc: This is usually called by another script which has access to the two units and then just sets the units as parameters for the function + + public void battle(GameObject initiator, GameObject recipient) + { + battleStatus = true; + var initiatorUnit = initiator.GetComponent(); + var recipientUnit = recipient.GetComponent(); + int initiatorAtt = initiatorUnit.attackDamage; + int recipientAtt = recipientUnit.attackDamage; + //If the two units have the same attackRange then they can trade + if (initiatorUnit.attackRange == recipientUnit.attackRange) + { + GameObject tempParticle = Instantiate( recipientUnit.GetComponent().damagedParticle,recipient.transform.position, recipient.transform.rotation); + Destroy(tempParticle, 2f); + recipientUnit.dealDamage(initiatorAtt); + if (checkIfDead(recipient)) + { + //Set to null then remove, if the gameObject is destroyed before its removed it will not check properly + //This leads to the game not actually ending because the check to see if any units remains happens before the object + //is removed from the parent, so we need to parent to null before we destroy the gameObject. + recipient.transform.parent = null; + recipientUnit.unitDie(); + battleStatus = false; + GMS.checkIfUnitsRemain(initiator, recipient); + return; + } + + + initiatorUnit.dealDamage(recipientAtt); + if (checkIfDead(initiator)) + { + initiator.transform.parent = null; + initiatorUnit.unitDie(); + battleStatus = false; + GMS.checkIfUnitsRemain(initiator, recipient); + return; + + } + } + //if the units don't have the same attack range, like a swordsman vs an archer; the recipient cannot strike back + else + { + GameObject tempParticle = Instantiate(recipientUnit.GetComponent().damagedParticle, recipient.transform.position, recipient.transform.rotation); + Destroy(tempParticle, 2f); + + recipientUnit.dealDamage(initiatorAtt); + if (checkIfDead(recipient)) + { + recipient.transform.parent = null; + recipientUnit.unitDie(); + battleStatus = false; + GMS.checkIfUnitsRemain(initiator, recipient); + + return; + } + } + + battleStatus = false; + + } + + //In: gameObject to check + //Out: boolean - true if unit is dead, false otherwise + //Desc: the health of the gameObject is checked (must be 'unit') or it'll break + public bool checkIfDead(GameObject unitToCheck) + { + if (unitToCheck.GetComponent().currentHealthPoints <= 0) + { + return true; + } + return false; + } + + //In: gameObject to destroy + //Out: void + //Desc: the gameObject in the parameter is destroyed + public void destroyObject(GameObject unitToDestroy) + { + Destroy(unitToDestroy); + } + + //In: two unit gameObjects the attacker and the receiver + //Out: this plays the animations for the battle + //Desc: this function calls all the functions for the battle + public IEnumerator attack(GameObject unit, GameObject enemy) + { + battleStatus = true; + float elapsedTime = 0; + Vector3 startingPos = unit.transform.position; + Vector3 endingPos = enemy.transform.position; + unit.GetComponent().setWalkingAnimation(); + while (elapsedTime < .25f) + { + + unit.transform.position = Vector3.Lerp(startingPos, startingPos+((((endingPos - startingPos) / (endingPos - startingPos).magnitude)).normalized*.5f), (elapsedTime / .25f)); + elapsedTime += Time.deltaTime; + + yield return new WaitForEndOfFrame(); + } + + + + while (battleStatus) + { + + StartCoroutine(CSS.camShake(.2f,unit.GetComponent().attackDamage,getDirection(unit,enemy))); + if(unit.GetComponent().attackRange == enemy.GetComponent().attackRange && enemy.GetComponent().currentHealthPoints - unit.GetComponent().attackDamage > 0) + { + StartCoroutine(unit.GetComponent().displayDamageEnum(enemy.GetComponent().attackDamage)); + StartCoroutine(enemy.GetComponent().displayDamageEnum(unit.GetComponent().attackDamage)); + } + + else + { + StartCoroutine(enemy.GetComponent().displayDamageEnum(unit.GetComponent().attackDamage)); + } + + //unit.GetComponent().displayDamage(enemy.GetComponent().attackDamage); + //enemy.GetComponent().displayDamage(unit.GetComponent().attackDamage); + + battle(unit, enemy); + + yield return new WaitForEndOfFrame(); + } + + if (unit != null) + { + StartCoroutine(returnAfterAttack(unit, startingPos)); + + } + + + + + //unit.GetComponent().wait(); + + } + + //In: unit that is returning to its position, the endPoint vector to return to + //Out: The unit returns back to its location + //Desc: the gameObject in the parameter is returned to the endPoint + public IEnumerator returnAfterAttack(GameObject unit, Vector3 endPoint) { + float elapsedTime = 0; + + + while (elapsedTime < .30f) + { + unit.transform.position = Vector3.Lerp(unit.transform.position, endPoint, (elapsedTime / .25f)); + elapsedTime += Time.deltaTime; + yield return new WaitForEndOfFrame(); + } + + unit.GetComponent().setWaitIdleAnimation(); + unit.GetComponent().wait(); + + + } + + //In: two 'unit' gameObjects + //Out: vector3 the direction that the unit needs to moveTowards + //Desc: the vector3 which the unit needs to moveTowards is returned by this function + public Vector3 getDirection(GameObject unit, GameObject enemy) + { + Vector3 startingPos = unit.transform.position; + Vector3 endingPos = enemy.transform.position; + return (((endingPos - startingPos) / (endingPos - startingPos).magnitude)).normalized; + } + + + + + +} diff --git a/camShakeScript.cs b/camShakeScript.cs new file mode 100644 index 0000000..3c91543 --- /dev/null +++ b/camShakeScript.cs @@ -0,0 +1,36 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class camShakeScript : MonoBehaviour +{ + + public IEnumerator camShake(float duration,float camShakeStrength,Vector3 direction) + { + float updatedShakeStrength = camShakeStrength; + if (camShakeStrength > 10) + { + camShakeStrength = 10; + } + Vector3 originalPos = transform.position; + Vector3 endPoint = new Vector3(direction.x, 0, direction.z)*(camShakeStrength/2); + + float timePassed = 0f; + while (timePassed < duration) + { + + float xPos = Random.Range(-.1f, .1f)*camShakeStrength; + float zPos = Random.Range(-.1f, .1f)*camShakeStrength; + Vector3 newPos = new Vector3(transform.position.x + xPos, transform.position.y, transform.position.z + zPos); + //Vector3 newPos = endPoint + originalPos; + transform.position = Vector3.Lerp(transform.position,newPos,0.15f); + timePassed += Time.deltaTime; + yield return new WaitForEndOfFrame(); + + } + + + + + } +} diff --git a/gameManagerScript.cs b/gameManagerScript.cs new file mode 100644 index 0000000..63fa585 --- /dev/null +++ b/gameManagerScript.cs @@ -0,0 +1,794 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using TMPro; + +public class gameManagerScript : MonoBehaviour +{ + + //A lot of the UI does not need to be public, they just are currently if you need to make quick changes in the inspector + //Changing them to private will not break anything, but you will need to re-enable them to show in the inspector + [Header("UI GameObjects")] + public TMP_Text currentTeamUI; + public Canvas displayWinnerUI; + + public TMP_Text UIunitCurrentHealth; + public TMP_Text UIunitAttackDamage; + public TMP_Text UIunitAttackRange; + public TMP_Text UIunitMoveSpeed; + public TMP_Text UIunitName; + public UnityEngine.UI.Image UIunitSprite; + + public Canvas UIunitCanvas; + public GameObject playerPhaseBlock; + private Animator playerPhaseAnim; + private TMP_Text playerPhaseText; + + //Raycast for the update for unitHover info + private Ray ray; + private RaycastHit hit; + + /// The number of teams is hard coded as 2, if there are changes in the future a few of the + /// functions in this class need to be altered as well to update this change. + + public int numberOfTeams = 2; + public int currentTeam; + public GameObject unitsOnBoard; + + public GameObject team1; + public GameObject team2; + + public GameObject unitBeingDisplayed; + public GameObject tileBeingDisplayed; + public bool displayingUnitInfo; + + public tileMapScript TMS; + + //Cursor Info for tileMapScript + public int cursorX; + public int cursorY; + //currentTileBeingMousedOver + public int selectedXTile; + public int selectedYTile; + + //Variables for unitPotentialMovementRoute + List currentPathForUnitRoute; + List unitPathToCursor; + + public bool unitPathExists; + + public Material UIunitRoute; + public Material UIunitRouteCurve; + public Material UIunitRouteArrow; + public Material UICursor; + + public int routeToX; + public int routeToY; + + //This game object is to record the location of the 2 count path when it is reset to 0 this is used to remember what tile to disable + public GameObject quadThatIsOneAwayFromUnit; + + + public void Start() + { + currentTeam = 0; + setCurrentTeamUI(); + teamHealthbarColorUpdate(); + displayingUnitInfo = false; + playerPhaseAnim = playerPhaseBlock.GetComponent(); + playerPhaseText = playerPhaseBlock.GetComponentInChildren(); + unitPathToCursor = new List(); + unitPathExists = false; + + TMS = GetComponent(); + + + } + //2019/10/17 there is a small blink between disable and re-enable for path, its a bit jarring, try to fix it later + public void Update() + { + //Always trying to see where the mouse is pointing + ray = Camera.main.ScreenPointToRay(Input.mousePosition); + if (Physics.Raycast(ray, out hit)) + { + //Update cursorLocation and unit appearing in the topLeft + cursorUIUpdate(); + unitUIUpdate(); + //If the unit is selected we want to highlight the current path with the UI + if (TMS.selectedUnit != null && TMS.selectedUnit.GetComponent().getMovementStateEnum(1) == TMS.selectedUnit.GetComponent().unitMoveState) + { + //Check to see if the cursor is in range, we cant show movement outside of range so there is no point if its outside + if (TMS.selectedUnitMoveRange.Contains(TMS.graph[cursorX, cursorY])) + { + //Generate new path to cursor try to limit this to once per new cursor location or else its too many calculations + + + + if (cursorX != TMS.selectedUnit.GetComponent().x || cursorY != TMS.selectedUnit.GetComponent().y) + { + if (!unitPathExists&&TMS.selectedUnit.GetComponent().movementQueue.Count==0) + { + + unitPathToCursor = generateCursorRouteTo(cursorX, cursorY); + + routeToX = cursorX; + routeToY = cursorY; + + if (unitPathToCursor.Count != 0) + { + + for(int i = 0; i < unitPathToCursor.Count; i++) + { + int nodeX = unitPathToCursor[i].x; + int nodeY = unitPathToCursor[i].y; + + if (i == 0) + { + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().material = UICursor; + } + else if (i!=0 && (i+1)!=unitPathToCursor.Count) + { + //This is used to set the indicator for tiles excluding the first/last tile + setCorrectRouteWithInputAndOutput(nodeX, nodeY,i); + } + else if (i == unitPathToCursor.Count-1) + { + //This is used to set the indicator for the final tile; + setCorrectRouteFinalTile(nodeX, nodeY, i); + } + + TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY].GetComponent().enabled = true; + + } + + } + unitPathExists = true; + + } + + else if (routeToX != cursorX || routeToY != cursorY) + { + + if (unitPathToCursor.Count != 0) + { + for (int i = 0; i < unitPathToCursor.Count; i++) + { + int nodeX = unitPathToCursor[i].x; + int nodeY = unitPathToCursor[i].y; + + TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY].GetComponent().enabled = false; + } + } + + unitPathExists = false; + } + } + else if(cursorX == TMS.selectedUnit.GetComponent().x && cursorY == TMS.selectedUnit.GetComponent().y) + { + + TMS.disableUnitUIRoute(); + unitPathExists = false; + } + + } + } + + } + + } + //In: + //Out: void + //Desc: sets the current player Text in the UI + public void setCurrentTeamUI() + { + currentTeamUI.SetText("Current Player is : Player " + (currentTeam+1).ToString()); + } + + //In: + //Out: void + //Desc: increments the current team + public void switchCurrentPlayer() + { + resetUnitsMovements(returnTeam(currentTeam)); + currentTeam++; + if (currentTeam == numberOfTeams) + { + currentTeam = 0; + } + + } + + //In: int i, the index for each team + //Out: gameObject team + //Desc: return the gameObject of the requested team + public GameObject returnTeam(int i) + { + GameObject teamToReturn = null; + if (i == 0) + { + teamToReturn = team1; + } + else if (i == 1) + { + teamToReturn = team2; + } + return teamToReturn; + } + + //In: gameObject team - used to reset (re-enable) all the unit movements + //Out: void + //Desc: re-enables movement for all units on the team + public void resetUnitsMovements(GameObject teamToReset) + { + foreach (Transform unit in teamToReset.transform) + { + unit.GetComponent().moveAgain(); + } + } + + //In: + //Out: void + //Desc: ends the turn and plays the animation + public void endTurn() + { + + if (TMS.selectedUnit == null) + { + switchCurrentPlayer(); + if (currentTeam == 1) + { + playerPhaseAnim.SetTrigger("slideLeftTrigger"); + playerPhaseText.SetText("Player 2 Phase"); + } + else if (currentTeam == 0) + { + playerPhaseAnim.SetTrigger("slideRightTrigger"); + playerPhaseText.SetText("Player 1 Phase"); + } + teamHealthbarColorUpdate(); + setCurrentTeamUI(); + } + } + + //In: attacking unit and receiving unit + //Out: void + //Desc: checks to see if units remain on a team + public void checkIfUnitsRemain(GameObject unit, GameObject enemy) + { + // Debug.Log(team1.transform.childCount); + // Debug.Log(team2.transform.childCount); + StartCoroutine(checkIfUnitsRemainCoroutine(unit,enemy)); + } + + + //In: + //Out: void + //Desc: updates the cursor for the UI + public void cursorUIUpdate() + { + //If we are mousing over a tile, highlight it + if (hit.transform.CompareTag("Tile")) + { + if (tileBeingDisplayed == null) + { + selectedXTile = hit.transform.gameObject.GetComponent().tileX; + selectedYTile = hit.transform.gameObject.GetComponent().tileY; + cursorX = selectedXTile; + cursorY = selectedYTile; + TMS.quadOnMapCursor[selectedXTile, selectedYTile].GetComponent().enabled = true; + tileBeingDisplayed = hit.transform.gameObject; + + } + else if (tileBeingDisplayed != hit.transform.gameObject) + { + selectedXTile = tileBeingDisplayed.GetComponent().tileX; + selectedYTile = tileBeingDisplayed.GetComponent().tileY; + TMS.quadOnMapCursor[selectedXTile, selectedYTile].GetComponent().enabled = false; + + selectedXTile = hit.transform.gameObject.GetComponent().tileX; + selectedYTile = hit.transform.gameObject.GetComponent().tileY; + cursorX = selectedXTile; + cursorY = selectedYTile; + TMS.quadOnMapCursor[selectedXTile, selectedYTile].GetComponent().enabled = true; + tileBeingDisplayed = hit.transform.gameObject; + + } + + } + //If we are mousing over a unit, highlight the tile that the unit is occupying + else if (hit.transform.CompareTag("Unit")) + { + if (tileBeingDisplayed == null) + { + selectedXTile = hit.transform.parent.gameObject.GetComponent().x; + selectedYTile = hit.transform.parent.gameObject.GetComponent().y; + cursorX = selectedXTile; + cursorY = selectedYTile; + TMS.quadOnMapCursor[selectedXTile, selectedYTile].GetComponent().enabled = true; + tileBeingDisplayed = hit.transform.parent.gameObject.GetComponent().tileBeingOccupied; + + } + else if (tileBeingDisplayed != hit.transform.gameObject) + { + if (hit.transform.parent.gameObject.GetComponent().movementQueue.Count == 0) + { + selectedXTile = tileBeingDisplayed.GetComponent().tileX; + selectedYTile = tileBeingDisplayed.GetComponent().tileY; + TMS.quadOnMapCursor[selectedXTile, selectedYTile].GetComponent().enabled = false; + + selectedXTile = hit.transform.parent.gameObject.GetComponent().x; + selectedYTile = hit.transform.parent.gameObject.GetComponent().y; + cursorX = selectedXTile; + cursorY = selectedYTile; + TMS.quadOnMapCursor[selectedXTile, selectedYTile].GetComponent().enabled = true; + tileBeingDisplayed = hit.transform.parent.GetComponent().tileBeingOccupied; + + } + + } + } + //We aren't pointing at anything no cursor. + else + { + TMS.quadOnMapCursor[selectedXTile, selectedYTile].GetComponent().enabled = false; + } + } + + + //In: + //Out: void + //Desc: the unit that is being highlighted will have its stats in the UI + public void unitUIUpdate() + { + if (!displayingUnitInfo) + { + if (hit.transform.CompareTag("Unit")) + { + UIunitCanvas.enabled = true; + displayingUnitInfo = true; + unitBeingDisplayed = hit.transform.parent.gameObject; + var highlightedUnitScript = hit.transform.parent.gameObject.GetComponent(); + + UIunitCurrentHealth.SetText(highlightedUnitScript.currentHealthPoints.ToString()); + UIunitAttackDamage.SetText(highlightedUnitScript.attackDamage.ToString()); + UIunitAttackRange.SetText(highlightedUnitScript.attackRange.ToString()); + UIunitMoveSpeed.SetText(highlightedUnitScript.moveSpeed.ToString()); + UIunitName.SetText(highlightedUnitScript.unitName); + UIunitSprite.sprite = highlightedUnitScript.unitSprite; + + } + else if (hit.transform.CompareTag("Tile")) + { + if (hit.transform.GetComponent().unitOnTile != null) + { + unitBeingDisplayed = hit.transform.GetComponent().unitOnTile; + + UIunitCanvas.enabled = true; + displayingUnitInfo = true; + var highlightedUnitScript = unitBeingDisplayed.GetComponent(); + + UIunitCurrentHealth.SetText(highlightedUnitScript.currentHealthPoints.ToString()); + UIunitAttackDamage.SetText(highlightedUnitScript.attackDamage.ToString()); + UIunitAttackRange.SetText(highlightedUnitScript.attackRange.ToString()); + UIunitMoveSpeed.SetText(highlightedUnitScript.moveSpeed.ToString()); + UIunitName.SetText(highlightedUnitScript.unitName); + UIunitSprite.sprite = highlightedUnitScript.unitSprite; + + } + } + } + else if (hit.transform.gameObject.CompareTag("Tile")) + { + if (hit.transform.GetComponent().unitOnTile == null) + { + UIunitCanvas.enabled = false; + displayingUnitInfo = false; + } + else if (hit.transform.GetComponent().unitOnTile != unitBeingDisplayed) + { + UIunitCanvas.enabled = false; + displayingUnitInfo = false; + } + } + else if (hit.transform.gameObject.CompareTag("Unit")) + { + if (hit.transform.parent.gameObject != unitBeingDisplayed) + { + UIunitCanvas.enabled = false; + displayingUnitInfo = false; + } + } + } + + //In: + //Out: void + //Desc: When the current team is active, the healthbars are blue, and the other team is red + public void teamHealthbarColorUpdate() + { + for(int i = 0; i < numberOfTeams; i++) + { + GameObject team = returnTeam(i); + if(team == returnTeam(currentTeam)) + { + foreach (Transform unit in team.transform) + { + unit.GetComponent().changeHealthBarColour(0); + } + } + else + { + foreach (Transform unit in team.transform) + { + unit.GetComponent().changeHealthBarColour(1); + } + } + } + + + } + //In: x and y location to go to + //Out: list of nodes to traverse + //Desc: generate the cursor route to a position x , y + public List generateCursorRouteTo(int x, int y) + { + + if (TMS.selectedUnit.GetComponent().x == x && TMS.selectedUnit.GetComponent().y == y) + { + Debug.Log("clicked the same tile that the unit is standing on"); + currentPathForUnitRoute = new List(); + + + return currentPathForUnitRoute; + } + if (TMS.unitCanEnterTile(x, y) == false) + { + //cant move into something so we can probably just return + //cant set this endpoint as our goal + + return null; + } + + //TMS.selectedUnit.GetComponent().path = null; + currentPathForUnitRoute = null; + //from wiki dijkstra's + Dictionary dist = new Dictionary(); + Dictionary prev = new Dictionary(); + Node source = TMS.graph[TMS.selectedUnit.GetComponent().x, TMS.selectedUnit.GetComponent().y]; + Node target = TMS.graph[x, y]; + dist[source] = 0; + prev[source] = null; + //Unchecked nodes + List unvisited = new List(); + + //Initialize + foreach (Node n in TMS.graph) + { + + //Initialize to infite distance as we don't know the answer + //Also some places are infinity + if (n != source) + { + dist[n] = Mathf.Infinity; + prev[n] = null; + } + unvisited.Add(n); + } + //if there is a node in the unvisited list lets check it + while (unvisited.Count > 0) + { + //u will be the unvisited node with the shortest distance + Node u = null; + foreach (Node possibleU in unvisited) + { + if (u == null || dist[possibleU] < dist[u]) + { + u = possibleU; + } + } + + + if (u == target) + { + break; + } + + unvisited.Remove(u); + + foreach (Node n in u.neighbours) + { + + //float alt = dist[u] + u.DistanceTo(n); + float alt = dist[u] + TMS.costToEnterTile(n.x, n.y); + if (alt < dist[n]) + { + dist[n] = alt; + prev[n] = u; + } + } + } + //if were here we found shortest path, or no path exists + if (prev[target] == null) + { + //No route; + return null; + } + currentPathForUnitRoute = new List(); + Node curr = target; + //Step through the current path and add it to the chain + while (curr != null) + { + currentPathForUnitRoute.Add(curr); + curr = prev[curr]; + } + //Now currPath is from target to our source, we need to reverse it from source to target. + currentPathForUnitRoute.Reverse(); + + return currentPathForUnitRoute; + + + + + } + + //In: gameObject quad + //Out: void + //Desc: reset its rotation + public void resetQuad(GameObject quadToReset) + { + quadToReset.GetComponent().material = UICursor; + quadToReset.transform.eulerAngles = new Vector3(90, 0, 0); + + } + + //In: Vector2 cursorPos the location we change, Vector3 the rotation that we will rotate the quad + //Out: void + //Desc: the quad is rotated approriately + public void UIunitRouteArrowDisplay(Vector2 cursorPos,Vector3 arrowRotationVector) + { + GameObject quadToManipulate = TMS.quadOnMapForUnitMovementDisplay[(int)cursorPos.x, (int)cursorPos.y]; + quadToManipulate.transform.eulerAngles = arrowRotationVector; + quadToManipulate.GetComponent().material = UIunitRouteArrow; + quadToManipulate.GetComponent().enabled = true; + } + + //In: two gameObjects current vector and the next one in the list + //Out: vector which is the direction between the two inputs + //Desc: the direction from current to the next vector is returned + public Vector2 directionBetween(Vector2 currentVector, Vector2 nextVector) + { + + + Vector2 vectorDirection = (nextVector - currentVector).normalized; + + if (vectorDirection == Vector2.right) + { + return Vector2.right; + } + else if (vectorDirection == Vector2.left) + { + return Vector2.left; + } + else if (vectorDirection == Vector2.up) + { + return Vector2.up; + } + else if (vectorDirection == Vector2.down) + { + return Vector2.down; + } + else + { + Vector2 vectorToReturn = new Vector2(); + return vectorToReturn; + } + } + + //In: two nodes that are being checked and int i is the position in the path ie i=0 is the first thing in the list + //Out: void + //Desc: orients the quads to display proper information + public void setCorrectRouteWithInputAndOutput(int nodeX,int nodeY,int i) + { + Vector2 previousTile = new Vector2(unitPathToCursor[i - 1].x + 1, unitPathToCursor[i - 1].y + 1); + Vector2 currentTile = new Vector2(unitPathToCursor[i].x + 1, unitPathToCursor[i].y + 1); + Vector2 nextTile = new Vector2(unitPathToCursor[i + 1].x + 1, unitPathToCursor[i + 1].y + 1); + + Vector2 backToCurrentVector = directionBetween(previousTile, currentTile); + Vector2 currentToFrontVector = directionBetween(currentTile, nextTile); + + + //Right (UP/DOWN/RIGHT) + if (backToCurrentVector == Vector2.right && currentToFrontVector == Vector2.right) + { + //Debug.Log("[IN[R]]->[Out[R]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 270); + quadToUpdate.GetComponent().material = UIunitRoute; + quadToUpdate.GetComponent().enabled = true; + } + else if (backToCurrentVector == Vector2.right && currentToFrontVector == Vector2.up) + { + //Debug.Log("[IN[R]]->[Out[UP]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 180); + quadToUpdate.GetComponent().material = UIunitRouteCurve; + quadToUpdate.GetComponent().enabled = true; + + } + else if (backToCurrentVector == Vector2.right && currentToFrontVector == Vector2.down) + { + //Debug.Log("[IN[R]]->[Out[DOWN]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 270); + quadToUpdate.GetComponent().material = UIunitRouteCurve; + quadToUpdate.GetComponent().enabled = true; + } + //Left (UP/DOWN/LEFT) + else if (backToCurrentVector == Vector2.left && currentToFrontVector == Vector2.left) + { + //Debug.Log("[IN[L]]->[Out[L]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 90); + quadToUpdate.GetComponent().material = UIunitRoute; + quadToUpdate.GetComponent().enabled = true; + } + else if (backToCurrentVector == Vector2.left && currentToFrontVector == Vector2.up) + { + //Debug.Log("[IN[L]]->[Out[UP]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 90); + quadToUpdate.GetComponent().material = UIunitRouteCurve; + quadToUpdate.GetComponent().enabled = true; + } + else if (backToCurrentVector == Vector2.left && currentToFrontVector == Vector2.down) + { + //Debug.Log("[IN[L]]->[Out[DOWN]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 0); + quadToUpdate.GetComponent().material = UIunitRouteCurve; + quadToUpdate.GetComponent().enabled = true; + } + //UP (UP/RIGHT/LEFT) + else if (backToCurrentVector == Vector2.up && currentToFrontVector == Vector2.up) + { + //Debug.Log("[IN[UP]]->[Out[UP]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 0); + quadToUpdate.GetComponent().material = UIunitRoute; + quadToUpdate.GetComponent().enabled = true; + } + else if (backToCurrentVector == Vector2.up && currentToFrontVector == Vector2.right) + { + //Debug.Log("[IN[UP]]->[Out[R]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 0); + quadToUpdate.GetComponent().material = UIunitRouteCurve; + quadToUpdate.GetComponent().enabled = true; + } + else if (backToCurrentVector == Vector2.up && currentToFrontVector == Vector2.left) + { + //Debug.Log("[IN[UP]]->[Out[L]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 270); + quadToUpdate.GetComponent().material = UIunitRouteCurve; + quadToUpdate.GetComponent().enabled = true; + } + //DOWN (DOWN/RIGHT/LEFT) + else if (backToCurrentVector == Vector2.down && currentToFrontVector == Vector2.down) + { + //Debug.Log("[IN[DOWN]]->[Out[DOWN]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 0); + quadToUpdate.GetComponent().material = UIunitRoute; + quadToUpdate.GetComponent().enabled = true; + } + else if (backToCurrentVector == Vector2.down && currentToFrontVector == Vector2.right) + { + //Debug.Log("[IN[DOWN]]->[Out[R]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 90); + quadToUpdate.GetComponent().material = UIunitRouteCurve; + quadToUpdate.GetComponent().enabled = true; + + } + else if (backToCurrentVector == Vector2.down && currentToFrontVector == Vector2.left) + { + //Debug.Log("[IN[DOWN]]->[Out[L]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 180); + quadToUpdate.GetComponent().material = UIunitRouteCurve; + quadToUpdate.GetComponent().enabled = true; + } + } + + //In: two nodes that are being checked and int i is the position in the path ie i=0 is the first thing in the list + //Out: void + //Desc: orients the quad for the final node in list to display proper information + public void setCorrectRouteFinalTile(int nodeX,int nodeY,int i) + { + Vector2 previousTile = new Vector2(unitPathToCursor[i - 1].x + 1, unitPathToCursor[i - 1].y + 1); + Vector2 currentTile = new Vector2(unitPathToCursor[i].x + 1, unitPathToCursor[i].y + 1); + Vector2 backToCurrentVector = directionBetween(previousTile, currentTile); + + if (backToCurrentVector == Vector2.right) + { + //Debug.Log("[IN[R]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 270); + quadToUpdate.GetComponent().material = UIunitRouteArrow; + quadToUpdate.GetComponent().enabled = true; + } + else if (backToCurrentVector == Vector2.left) + { + //Debug.Log("[IN[L]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 90); + quadToUpdate.GetComponent().material = UIunitRouteArrow; + quadToUpdate.GetComponent().enabled = true; + + } + else if (backToCurrentVector == Vector2.up) + { + //Debug.Log("[IN[U]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 0); + quadToUpdate.GetComponent().material = UIunitRouteArrow; + quadToUpdate.GetComponent().enabled = true; + } + else if (backToCurrentVector == Vector2.down) + { + //Debug.Log("[IN[D]]"); + GameObject quadToUpdate = TMS.quadOnMapForUnitMovementDisplay[nodeX, nodeY]; + quadToUpdate.GetComponent().rotation = Quaternion.Euler(90, 0, 180); + quadToUpdate.GetComponent().material = UIunitRouteArrow; + quadToUpdate.GetComponent().enabled = true; + } + } + + //In: two units that last fought + //Out: void + //Desc: waits until all the animations and stuff are finished before calling the game + public IEnumerator checkIfUnitsRemainCoroutine(GameObject unit, GameObject enemy) + { + while (unit.GetComponent().combatQueue.Count != 0) + { + yield return new WaitForEndOfFrame(); + } + + while (enemy.GetComponent().combatQueue.Count != 0) + { + yield return new WaitForEndOfFrame(); + } + if (team1.transform.childCount == 0) + { + displayWinnerUI.enabled = true; + displayWinnerUI.GetComponentInChildren().SetText("Player 2 has won!"); + + + } + else if (team2.transform.childCount == 0) + { + displayWinnerUI.enabled = true; + displayWinnerUI.GetComponentInChildren().SetText("Player 1 has won!"); + + + } + + + } + + + //In: + //Out: void + //Desc: set the player winning + + public void win() + { + displayWinnerUI.enabled = true; + displayWinnerUI.GetComponentInChildren().SetText("Winner!"); + + } + + + +} diff --git a/gameSceneManager.cs b/gameSceneManager.cs new file mode 100644 index 0000000..d79d0a5 --- /dev/null +++ b/gameSceneManager.cs @@ -0,0 +1,48 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.SceneManagement; + +public class gameSceneManager : MonoBehaviour +{ + //This was just used to load menu stuff properly and change scenes + + public Canvas mainCanvas; + public Canvas helpCanvas; + public Canvas helpCanvas2; + // Start is called before the first frame update + public void loadMainMenu() + { + SceneManager.LoadScene(0); + } + + public void loadLevelOne() + { + SceneManager.LoadScene(1); + } + + public void loadHelpCanvas() + { + mainCanvas.enabled = false; + helpCanvas.enabled = true; + } + + public void loadHelpCanvasBack() + { + helpCanvas2.enabled = false; + helpCanvas.enabled = true; + } + + public void loadHelpCanvas2() + { + helpCanvas.enabled = false; + helpCanvas2.enabled = true; + } + + public void loadMainCanvas() + { + mainCanvas.enabled = true; + helpCanvas.enabled = false; + helpCanvas2.enabled = false; + } +} diff --git a/tileMapScript.cs b/tileMapScript.cs new file mode 100644 index 0000000..c7c757e --- /dev/null +++ b/tileMapScript.cs @@ -0,0 +1,1125 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class tileMapScript : MonoBehaviour +{ + //Reference holders for the other two scripts that are currently running + //alongside this script + [Header("Manager Scripts")] + public battleManagerScript BMS; + public gameManagerScript GMS; + + //List of tiles that are used to generate the map + //Try chaging tilesTypes to enum later + [Header("Tiles")] + public Tile[] tileTypes; + public int[,] tiles; + + //This is used when the game starts and there are pre-existing units + //It uses this variable to check if there are any units and then maps them to the proper tiles + [Header("Units on the board")] + public GameObject unitsOnBoard; + + //This 2d array is the list of tile gameObjects on the board + public GameObject[,] tilesOnMap; + + //This 2d array is the list of quadUI gameObjects on the board + public GameObject[,] quadOnMap; + public GameObject[,] quadOnMapForUnitMovementDisplay; + public GameObject[,] quadOnMapCursor; + + //public is only to set them in the inspector, if you change these to private then you will + //need to re-enable them in the inspector + //Game object that is used to overlay onto the tiles to show possible movement + public GameObject mapUI; + //Game object that is used to highlight the mouse location + public GameObject mapCursorUI; + //Game object that is used to highlight the path the unit is taking + public GameObject mapUnitMovementUI; + + //Nodes along the path of shortest path from the pathfinding + public List currentPath = null; + + //Node graph for pathfinding purposes + public Node[,] graph; + + //containers (parent gameObjects) for the UI tiles + [Header("Containers")] + public GameObject tileContainer; + public GameObject UIQuadPotentialMovesContainer; + public GameObject UIQuadCursorContainer; + public GameObject UIUnitMovementPathContainer; + + + //Set in the inspector, might change this otherwise. + //This is the map size (please put positive numbers it probably wont work well with negative numbers) + [Header("Board Size")] + public int mapSizeX; + public int mapSizeY; + + //In the update() function mouse down raycast sets this unit + [Header("Selected Unit Info")] + public GameObject selectedUnit; + //These two are set in the highlightUnitRange() function + //They are used for other things as well, mainly to check for movement, or finalize function + public HashSet selectedUnitTotalRange; + public HashSet selectedUnitMoveRange; + + public bool unitSelected = false; + + public int unitSelectedPreviousX; + public int unitSelectedPreviousY; + + public GameObject previousOccupiedTile; + + + //public AudioSource selectedSound; + //public AudioSource unselectedSound; + //public area to set the material for the quad material for UI purposes + [Header("Materials")] + public Material greenUIMat; + public Material redUIMat; + public Material blueUIMat; + private void Start() + { + //Get the battlemanager running + //BMS = GetComponent(); + //GMS = GetComponent(); + //Generate the map info that will be used + generateMapInfo(); + //Generate pathfinding graph + generatePathFindingGraph(); + //With the generated info this function will read the info and produce the map + generateMapVisuals(); + //Check if there are any pre-existing units on the board + setIfTileIsOccupied(); + + + } + + private void Update() + { + + //If input is left mouse down then select the unit + if (Input.GetMouseButtonDown(0)) + { + if (selectedUnit == null) + { + //mouseClickToSelectUnit(); + mouseClickToSelectUnitV2(); + + } + //After a unit has been selected then if we get a mouse click, we need to check if the unit has entered the selection state (1) 'Selected' + //Move the unit + else if (selectedUnit.GetComponent().unitMoveState == selectedUnit.GetComponent().getMovementStateEnum(1) && selectedUnit.GetComponent().movementQueue.Count == 0) + { + + + if ( selectTileToMoveTo()) + { + //selectedSound.Play(); + Debug.Log("movement path has been located"); + unitSelectedPreviousX = selectedUnit.GetComponent().x; + unitSelectedPreviousY = selectedUnit.GetComponent().y; + previousOccupiedTile = selectedUnit.GetComponent().tileBeingOccupied; + selectedUnit.GetComponent().setWalkingAnimation(); + moveUnit(); + + StartCoroutine(moveUnitAndFinalize()); + //The moveUnit function calls a function on the unitScriptm when the movement is completed the finalization is called from that script. + + + } + + } + //Finalize the movement + else if(selectedUnit.GetComponent().unitMoveState == selectedUnit.GetComponent().getMovementStateEnum(2)) + { + finalizeOption(); + } + + } + //Unselect unit with the right click + if (Input.GetMouseButtonDown(1)) + { + if (selectedUnit != null) + { + if (selectedUnit.GetComponent().movementQueue.Count == 0 && selectedUnit.GetComponent().combatQueue.Count==0) + { + if (selectedUnit.GetComponent().unitMoveState != selectedUnit.GetComponent().getMovementStateEnum(3)) + { + //unselectedSound.Play(); + selectedUnit.GetComponent().setIdleAnimation(); + deselectUnit(); + } + } + else if (selectedUnit.GetComponent().movementQueue.Count == 1) + { + selectedUnit.GetComponent().visualMovementSpeed = 0.5f; + } + } + } + + + } + + //This is from quill18Create's tutorial + //You can find it by searching for grid based movement on youtube, he goes into explaining how everything works + //The map layouts a bit different + //all this does is set the tiles[x,y] to the corresponding tile + public void generateMapInfo() + { + tiles = new int[mapSizeX, mapSizeY]; + for (int x = 0; x < mapSizeX; x++) + { + for (int y = 0; y < mapSizeY; y++) + { + tiles[x, y] = 0; + } + } + tiles[2, 7] = 2; + tiles[3, 7] = 2; + + tiles[6, 7] = 2; + tiles[7, 7] = 2; + + tiles[2, 2] = 2; + tiles[3, 2] = 2; + + tiles[6, 2] = 2; + tiles[7, 2] = 2; + + tiles[0, 3] = 3; + tiles[1, 3] = 3; + tiles[0, 2] = 3; + tiles[1, 2] = 3; + + tiles[0, 6] = 3; + tiles[1, 6] = 3; + tiles[2, 6] = 3; + tiles[0, 7] = 3; + tiles[1, 7] = 3; + + tiles[2, 3] = 3; + tiles[0, 4] = 1; + tiles[0, 5] = 1; + tiles[1, 4] = 1; + tiles[1, 5] = 1; + tiles[2, 4] = 3; + tiles[2, 5] = 3; + + tiles[4, 4] = 1; + tiles[5, 4] = 1; + tiles[4, 5] = 1; + tiles[5, 5] = 1; + + tiles[7, 3] = 3; + tiles[8, 3] = 3; + tiles[9, 3] = 3; + tiles[8, 2] = 3; + tiles[9, 2] = 3; + tiles[7, 4] = 3; + tiles[7, 5] = 3; + tiles[7, 6] = 3; + tiles[8, 6] = 3; + tiles[9, 6] = 3; + tiles[8, 7] = 3; + tiles[9, 7] = 3; + tiles[8, 4] = 1; + tiles[8, 5] = 1; + tiles[9, 4] = 1; + tiles[9, 5] = 1; + + + } + //Creates the graph for the pathfinding, it sets up the neighbours + //This is also from Quill18Create's tutorial + public void generatePathFindingGraph() + { + graph = new Node[mapSizeX, mapSizeY]; + + //initialize graph + for (int x = 0; x < mapSizeX; x++) + { + for (int y = 0; y < mapSizeY; y++) + { + graph[x, y] = new Node(); + graph[x, y].x = x; + graph[x, y].y = y; + } + } + //calculate neighbours + for (int x = 0; x < mapSizeX; x++) + { + for (int y = 0; y < mapSizeY; y++) + { + //X is not 0, then we can add left (x - 1) + if (x > 0) + { + graph[x, y].neighbours.Add(graph[x - 1, y]); + } + //X is not mapSizeX - 1, then we can add right (x + 1) + if (x < mapSizeX-1) + { + graph[x, y].neighbours.Add(graph[x + 1, y]); + } + //Y is not 0, then we can add downwards (y - 1 ) + if (y > 0) + { + graph[x, y].neighbours.Add(graph[x, y - 1]); + } + //Y is not mapSizeY -1, then we can add upwards (y + 1) + if (y < mapSizeY - 1) + { + graph[x, y].neighbours.Add(graph[x, y + 1]); + } + + + } + } + } + + + //In: + //Out: void + //Desc: This instantiates all the information for the map, the UI Quads and the map tiles + public void generateMapVisuals() + { + //generate list of actual tileGameObjects + tilesOnMap = new GameObject[mapSizeX, mapSizeY]; + quadOnMap = new GameObject[mapSizeX, mapSizeY]; + quadOnMapForUnitMovementDisplay = new GameObject[mapSizeX, mapSizeY]; + quadOnMapCursor = new GameObject[mapSizeX, mapSizeY]; + int index; + for (int x = 0; x < mapSizeX; x++) + { + for (int y = 0; y < mapSizeY; y++) + { + index = tiles[x, y]; + GameObject newTile = Instantiate(tileTypes[index].tileVisualPrefab, new Vector3(x, 0, y), Quaternion.identity); + newTile.GetComponent().tileX = x; + newTile.GetComponent().tileY = y; + newTile.GetComponent().map = this; + newTile.transform.SetParent(tileContainer.transform); + tilesOnMap[x, y] = newTile; + + + GameObject gridUI = Instantiate(mapUI, new Vector3(x, 0.501f, y),Quaternion.Euler(90f,0,0)); + gridUI.transform.SetParent(UIQuadPotentialMovesContainer.transform); + quadOnMap[x, y] = gridUI; + + GameObject gridUIForPathfindingDisplay = Instantiate(mapUnitMovementUI, new Vector3(x, 0.502f, y), Quaternion.Euler(90f, 0, 0)); + gridUIForPathfindingDisplay.transform.SetParent(UIUnitMovementPathContainer.transform); + quadOnMapForUnitMovementDisplay[x, y] = gridUIForPathfindingDisplay; + + GameObject gridUICursor = Instantiate(mapCursorUI, new Vector3(x, 0.503f, y), Quaternion.Euler(90f, 0, 0)); + gridUICursor.transform.SetParent(UIQuadCursorContainer.transform); + quadOnMapCursor[x, y] = gridUICursor; + + } + } + } + + //Moves the unit + public void moveUnit() + { + if (selectedUnit != null) + { + selectedUnit.GetComponent().MoveNextTile(); + } + } + + //In: the x and y of a tile + //Out: vector 3 of the tile in world space, theyre .75f off of zero + //Desc: returns a vector 3 of the tile in world space, theyre .75f off of zero + public Vector3 tileCoordToWorldCoord(int x, int y) + { + return new Vector3(x, 0.75f, y); + } + + + + //In: + //Out: void + //Desc: sets the tile as occupied, if a unit is on the tile + public void setIfTileIsOccupied() + { + foreach (Transform team in unitsOnBoard.transform) + { + //Debug.Log("Set if Tile is Occupied is Called"); + foreach (Transform unitOnTeam in team) { + int unitX = unitOnTeam.GetComponent().x; + int unitY = unitOnTeam.GetComponent().y; + unitOnTeam.GetComponent().tileBeingOccupied = tilesOnMap[unitX, unitY]; + tilesOnMap[unitX, unitY].GetComponent().unitOnTile = unitOnTeam.gameObject; + } + + } + } + //In: x and y position of the tile to move to + //Out: void + //Desc: generates the path for the selected unit + //Think this one is also partially from Quill18Create's tutorial + public void generatePathTo(int x, int y) + { + + if (selectedUnit.GetComponent().x == x && selectedUnit.GetComponent().y == y){ + Debug.Log("clicked the same tile that the unit is standing on"); + currentPath = new List(); + selectedUnit.GetComponent().path = currentPath; + + return; + } + if (unitCanEnterTile(x, y) == false) + { + //cant move into something so we can probably just return + //cant set this endpoint as our goal + + return; + } + + selectedUnit.GetComponent().path = null; + currentPath = null; + //from wiki dijkstra's + Dictionary dist = new Dictionary(); + Dictionary prev = new Dictionary(); + Node source = graph[selectedUnit.GetComponent().x, selectedUnit.GetComponent().y]; + Node target = graph[x, y]; + dist[source] = 0; + prev[source] = null; + //Unchecked nodes + List unvisited = new List(); + + //Initialize + foreach (Node n in graph) + { + + //Initialize to infite distance as we don't know the answer + //Also some places are infinity + if (n != source) + { + dist[n] = Mathf.Infinity; + prev[n] = null; + } + unvisited.Add(n); + } + //if there is a node in the unvisited list lets check it + while (unvisited.Count > 0) + { + //u will be the unvisited node with the shortest distance + Node u = null; + foreach (Node possibleU in unvisited) + { + if (u == null || dist[possibleU] < dist[u]) + { + u = possibleU; + } + } + + + if (u == target) + { + break; + } + + unvisited.Remove(u); + + foreach (Node n in u.neighbours) + { + + //float alt = dist[u] + u.DistanceTo(n); + float alt = dist[u] + costToEnterTile(n.x, n.y); + if (alt < dist[n]) + { + dist[n] = alt; + prev[n] = u; + } + } + } + //if were here we found shortest path, or no path exists + if (prev[target] == null) + { + //No route; + return; + } + currentPath = new List(); + Node curr = target; + //Step through the current path and add it to the chain + while (curr != null) + { + currentPath.Add(curr); + curr = prev[curr]; + } + //Now currPath is from target to our source, we need to reverse it from source to target. + currentPath.Reverse(); + + selectedUnit.GetComponent().path = currentPath; + + + + + } + + //In: tile's x and y position + //Out: cost that is requiredd to enter the tile + //Desc: checks the cost of the tile for a unit to enter + public float costToEnterTile(int x, int y) + { + + if (unitCanEnterTile(x, y) == false) + { + return Mathf.Infinity; + + } + + //Gotta do the math here + Tile t = tileTypes[tiles[x, y]]; + float dist = t.movementCost; + + return dist; + } + + //change this when we add movement types + //In: tile's x and y position + //Out: true or false if the unit can enter the tile that was entered + //Desc: if the tile is not occupied by another team's unit, then you can walk through and if the tile is walkable + public bool unitCanEnterTile(int x, int y) + { + if (tilesOnMap[x, y].GetComponent().unitOnTile != null) + { + if (tilesOnMap[x, y].GetComponent().unitOnTile.GetComponent().teamNum != selectedUnit.GetComponent().teamNum) + { + return false; + } + } + return tileTypes[tiles[x, y]].isWalkable; + } + + + //In: + //Out: void + //Desc: uses a raycast to see where the mouse is pointing, this is used to select units + public void mouseClickToSelectUnit() + { + GameObject tempSelectedUnit; + + RaycastHit hit; + Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); + + + + if (Physics.Raycast(ray, out hit)) + { + + + //Debug.Log(hit.transform.tag); + if (unitSelected == false) + { + + if (hit.transform.gameObject.CompareTag("Tile")) + { + if (hit.transform.GetComponent().unitOnTile != null) + { + + + tempSelectedUnit = hit.transform.GetComponent().unitOnTile; + if (tempSelectedUnit.GetComponent().unitMoveState == tempSelectedUnit.GetComponent().getMovementStateEnum(0) + && tempSelectedUnit.GetComponent().teamNum == GMS.currentTeam + ) + { + disableHighlightUnitRange(); + selectedUnit = tempSelectedUnit; + selectedUnit.GetComponent().map = this; + selectedUnit.GetComponent().setMovementState(1); + unitSelected = true; + + highlightUnitRange(); + } + } + } + + else if (hit.transform.parent != null && hit.transform.parent.gameObject.CompareTag("Unit")) + { + + tempSelectedUnit = hit.transform.parent.gameObject; + if (tempSelectedUnit.GetComponent().unitMoveState == tempSelectedUnit.GetComponent().getMovementStateEnum(0) + && tempSelectedUnit.GetComponent().teamNum == GMS.currentTeam + ) + { + + disableHighlightUnitRange(); + selectedUnit = tempSelectedUnit; + selectedUnit.GetComponent().setMovementState(1); + //These were here before I don't think they do anything the unit location is set beforehand + //selectedUnit.GetComponent().x = (int)selectedUnit.transform.position.x; + // selectedUnit.GetComponent().y = (int)selectedUnit.transform.position.z; + selectedUnit.GetComponent().map = this; + unitSelected = true; + + highlightUnitRange(); + } + } + } + + } + } + + + + //In: + //Out: void + //Desc: finalizes the movement, sets the tile the unit moved to as occupied, etc + public void finalizeMovementPosition() + { + tilesOnMap[selectedUnit.GetComponent().x, selectedUnit.GetComponent().y].GetComponent().unitOnTile = selectedUnit; + //After a unit has been moved we will set the unitMoveState to (2) the 'Moved' state + + + selectedUnit.GetComponent().setMovementState(2); + + highlightUnitAttackOptionsFromPosition(); + highlightTileUnitIsOccupying(); + } + + + + //In: + //Out: void + //Desc: selects a unit based on the cursor from the other script + public void mouseClickToSelectUnitV2() + { + + if (unitSelected == false && GMS.tileBeingDisplayed!=null) + { + + if (GMS.tileBeingDisplayed.GetComponent().unitOnTile != null) + { + GameObject tempSelectedUnit = GMS.tileBeingDisplayed.GetComponent().unitOnTile; + if (tempSelectedUnit.GetComponent().unitMoveState == tempSelectedUnit.GetComponent().getMovementStateEnum(0) + && tempSelectedUnit.GetComponent().teamNum == GMS.currentTeam + ) + { + disableHighlightUnitRange(); + //selectedSound.Play(); + selectedUnit = tempSelectedUnit; + selectedUnit.GetComponent().map = this; + selectedUnit.GetComponent().setMovementState(1); + selectedUnit.GetComponent().setSelectedAnimation(); + unitSelected = true; + highlightUnitRange(); + + } + } + } + +} + //In: + //Out: void + //Desc: finalizes the player's option, wait or attack + public void finalizeOption() + { + + RaycastHit hit; + Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); + HashSet attackableTiles = getUnitAttackOptionsFromPosition(); + + if (Physics.Raycast(ray, out hit)) + { + + //This portion is to ensure that the tile has been clicked + //If the tile has been clicked then we need to check if there is a unit on it + if (hit.transform.gameObject.CompareTag("Tile")) + { + if (hit.transform.GetComponent().unitOnTile != null) + { + GameObject unitOnTile = hit.transform.GetComponent().unitOnTile; + int unitX = unitOnTile.GetComponent().x; + int unitY = unitOnTile.GetComponent().y; + + if (unitOnTile == selectedUnit) + { + disableHighlightUnitRange(); + Debug.Log("ITS THE SAME UNIT JUST WAIT"); + selectedUnit.GetComponent().wait(); + selectedUnit.GetComponent().setWaitIdleAnimation(); + selectedUnit.GetComponent().setMovementState(3); + deselectUnit(); + + + } + else if (unitOnTile.GetComponent().teamNum != selectedUnit.GetComponent().teamNum && attackableTiles.Contains(graph[unitX,unitY])) + { + if (unitOnTile.GetComponent().currentHealthPoints > 0) + { + Debug.Log("We clicked an enemy that should be attacked"); + Debug.Log(selectedUnit.GetComponent().currentHealthPoints); + StartCoroutine(BMS.attack(selectedUnit, unitOnTile)); + + + StartCoroutine(deselectAfterMovements(selectedUnit, unitOnTile)); + } + } + } + } + else if (hit.transform.parent != null && hit.transform.parent.gameObject.CompareTag("Unit")) + { + GameObject unitClicked = hit.transform.parent.gameObject; + int unitX = unitClicked.GetComponent().x; + int unitY = unitClicked.GetComponent().y; + + if (unitClicked == selectedUnit) + { + disableHighlightUnitRange(); + Debug.Log("ITS THE SAME UNIT JUST WAIT"); + selectedUnit.GetComponent().wait(); + selectedUnit.GetComponent().setWaitIdleAnimation(); + selectedUnit.GetComponent().setMovementState(3); + deselectUnit(); + + } + else if (unitClicked.GetComponent().teamNum != selectedUnit.GetComponent().teamNum && attackableTiles.Contains(graph[unitX, unitY])) + { + if (unitClicked.GetComponent().currentHealthPoints > 0) + { + + Debug.Log("We clicked an enemy that should be attacked"); + Debug.Log("Add Code to Attack enemy"); + //selectedUnit.GetComponent().setAttackAnimation(); + StartCoroutine(BMS.attack(selectedUnit, unitClicked)); + + // selectedUnit.GetComponent().wait(); + //Check if soemone has won + //GMS.checkIfUnitsRemain(); + StartCoroutine(deselectAfterMovements(selectedUnit, unitClicked)); + } + } + + } + } + +} + + //In: + //Out: void + //Desc: de-selects the unit + public void deselectUnit() + { + + if (selectedUnit != null) + { + if (selectedUnit.GetComponent().unitMoveState == selectedUnit.GetComponent().getMovementStateEnum(1)) + { + disableHighlightUnitRange(); + disableUnitUIRoute(); + selectedUnit.GetComponent().setMovementState(0); + + + selectedUnit = null; + unitSelected = false; + } + else if (selectedUnit.GetComponent().unitMoveState == selectedUnit.GetComponent().getMovementStateEnum(3) ) + { + disableHighlightUnitRange(); + disableUnitUIRoute(); + unitSelected = false; + selectedUnit = null; + } + else + { + disableHighlightUnitRange(); + disableUnitUIRoute(); + tilesOnMap[selectedUnit.GetComponent().x, selectedUnit.GetComponent().y].GetComponent().unitOnTile = null; + tilesOnMap[unitSelectedPreviousX, unitSelectedPreviousY].GetComponent().unitOnTile = selectedUnit; + + selectedUnit.GetComponent().x = unitSelectedPreviousX; + selectedUnit.GetComponent().y = unitSelectedPreviousY; + selectedUnit.GetComponent().tileBeingOccupied = previousOccupiedTile; + selectedUnit.transform.position = tileCoordToWorldCoord(unitSelectedPreviousX, unitSelectedPreviousY); + selectedUnit.GetComponent().setMovementState(0); + selectedUnit = null; + unitSelected = false; + } + } + } + + + //In: + //Out: void + //Desc: highlights the units range options (this is the portion shown in the video) + public void highlightUnitRange() + { + + + HashSet finalMovementHighlight = new HashSet(); + HashSet totalAttackableTiles = new HashSet(); + HashSet finalEnemyUnitsInMovementRange = new HashSet(); + + int attRange = selectedUnit.GetComponent().attackRange; + int moveSpeed = selectedUnit.GetComponent().moveSpeed; + + + Node unitInitialNode = graph[selectedUnit.GetComponent().x, selectedUnit.GetComponent().y]; + finalMovementHighlight = getUnitMovementOptions(); + totalAttackableTiles = getUnitTotalAttackableTiles(finalMovementHighlight, attRange, unitInitialNode); + //Debug.Log("There are this many available tiles for the unit: "+finalMovementHighlight.Count); + + foreach (Node n in totalAttackableTiles) + { + + if (tilesOnMap[n.x, n.y].GetComponent().unitOnTile != null) + { + GameObject unitOnCurrentlySelectedTile = tilesOnMap[n.x, n.y].GetComponent().unitOnTile; + if (unitOnCurrentlySelectedTile.GetComponent().teamNum != selectedUnit.GetComponent().teamNum) + { + finalEnemyUnitsInMovementRange.Add(n); + } + } + } + + + highlightEnemiesInRange(totalAttackableTiles); + //highlightEnemiesInRange(finalEnemyUnitsInMovementRange); + highlightMovementRange(finalMovementHighlight); + //Debug.Log(finalMovementHighlight.Count); + selectedUnitMoveRange = finalMovementHighlight; + + //This final bit sets the selected Units tiles, which can be accessible in other functions + //Probably bad practice, but I'll need to get things to work for now (2019-09-30) + selectedUnitTotalRange = getUnitTotalRange(finalMovementHighlight, totalAttackableTiles); + //Debug.Log(unionTiles.Count); + + //Debug.Log("exiting the while loop"); + //This will for each loop will highlight the movement range of the units + + + } + + + //In: + //Out: void + //Desc: disables the quads that are being used to highlight position + public void disableUnitUIRoute() + { + foreach(GameObject quad in quadOnMapForUnitMovementDisplay) + { + if (quad.GetComponent().enabled == true) + { + + quad.GetComponent().enabled = false; + } + } + } + + //In: + //Out: HashSet of the tiles that can be reached by unit + //Desc: returns the hashSet of nodes that the unit can reach from its position + public HashSet getUnitMovementOptions() + { + float[,] cost = new float[mapSizeX, mapSizeY]; + HashSet UIHighlight = new HashSet(); + HashSet tempUIHighlight = new HashSet(); + HashSet finalMovementHighlight = new HashSet(); + int moveSpeed = selectedUnit.GetComponent().moveSpeed; + Node unitInitialNode = graph[selectedUnit.GetComponent().x, selectedUnit.GetComponent().y]; + + ///Set-up the initial costs for the neighbouring nodes + finalMovementHighlight.Add(unitInitialNode); + foreach (Node n in unitInitialNode.neighbours) + { + cost[n.x, n.y] = costToEnterTile(n.x, n.y); + //Debug.Log(cost[n.x, n.y]); + if (moveSpeed - cost[n.x, n.y] >= 0) + { + UIHighlight.Add(n); + } + } + + finalMovementHighlight.UnionWith(UIHighlight); + + while (UIHighlight.Count != 0) + { + foreach (Node n in UIHighlight) + { + foreach (Node neighbour in n.neighbours) + { + if (!finalMovementHighlight.Contains(neighbour)) + { + cost[neighbour.x, neighbour.y] = costToEnterTile(neighbour.x, neighbour.y) + cost[n.x, n.y]; + //Debug.Log(cost[neighbour.x, neighbour.y]); + if (moveSpeed - cost[neighbour.x, neighbour.y] >= 0) + { + //Debug.Log(cost[neighbour.x, neighbour.y]); + tempUIHighlight.Add(neighbour); + } + } + } + + } + + UIHighlight = tempUIHighlight; + finalMovementHighlight.UnionWith(UIHighlight); + tempUIHighlight = new HashSet(); + + } + Debug.Log("The total amount of movable spaces for this unit is: " + finalMovementHighlight.Count); + Debug.Log("We have used the function to calculate it this time"); + return finalMovementHighlight; + } + + //In: finalMovement highlight and totalAttackabletiles + //Out: a hashSet of nodes that are the combination of the two inputs + //Desc: returns the unioned hashSet + public HashSet getUnitTotalRange(HashSet finalMovementHighlight, HashSet totalAttackableTiles) + { + HashSet unionTiles = new HashSet(); + unionTiles.UnionWith(finalMovementHighlight); + //unionTiles.UnionWith(finalEnemyUnitsInMovementRange); + unionTiles.UnionWith(totalAttackableTiles); + return unionTiles; + } + //In: finalMovement highlight, the attack range of the unit, and the initial node that the unit was standing on + //Out: hashSet Node of the total attackable tiles for the unit + //Desc: returns a set of nodes that represent the unit's total attackable tiles + public HashSet getUnitTotalAttackableTiles(HashSet finalMovementHighlight, int attRange, Node unitInitialNode) + { + HashSet tempNeighbourHash = new HashSet(); + HashSet neighbourHash = new HashSet(); + HashSet seenNodes = new HashSet(); + HashSet totalAttackableTiles = new HashSet(); + foreach (Node n in finalMovementHighlight) + { + neighbourHash = new HashSet(); + neighbourHash.Add(n); + for (int i = 0; i < attRange; i++) + { + foreach (Node t in neighbourHash) + { + foreach (Node tn in t.neighbours) + { + tempNeighbourHash.Add(tn); + } + } + + neighbourHash = tempNeighbourHash; + tempNeighbourHash = new HashSet(); + if (i < attRange - 1) + { + seenNodes.UnionWith(neighbourHash); + } + + } + neighbourHash.ExceptWith(seenNodes); + seenNodes = new HashSet(); + totalAttackableTiles.UnionWith(neighbourHash); + } + totalAttackableTiles.Remove(unitInitialNode); + + //Debug.Log("The unit node has this many attack options" + totalAttackableTiles.Count); + return (totalAttackableTiles); + } + + + //In: + //Out: hashSet of nodes get all the attackable tiles from the current position + //Desc: returns a set of nodes that are all the attackable tiles from the units current position + public HashSet getUnitAttackOptionsFromPosition() + { + HashSet tempNeighbourHash = new HashSet(); + HashSet neighbourHash = new HashSet(); + HashSet seenNodes = new HashSet(); + Node initialNode = graph[selectedUnit.GetComponent().x, selectedUnit.GetComponent().y]; + int attRange = selectedUnit.GetComponent().attackRange; + + + neighbourHash = new HashSet(); + neighbourHash.Add(initialNode); + for (int i = 0; i < attRange; i++) + { + foreach (Node t in neighbourHash) + { + foreach (Node tn in t.neighbours) + { + tempNeighbourHash.Add(tn); + } + } + neighbourHash = tempNeighbourHash; + tempNeighbourHash = new HashSet(); + if (i < attRange - 1) + { + seenNodes.UnionWith(neighbourHash); + } + } + neighbourHash.ExceptWith(seenNodes); + neighbourHash.Remove(initialNode); + return neighbourHash; + } + + //In: + //Out: hashSet node that the unit is currently occupying + //Desc: returns a set of nodes of the tile that the unit is occupying + public HashSet getTileUnitIsOccupying() + { + + int x = selectedUnit.GetComponent().x; + int y = selectedUnit.GetComponent().y; + HashSet singleTile = new HashSet(); + singleTile.Add(graph[x, y]); + return singleTile; + + } + + //In: + //Out: void + //Desc: highlights the selected unit's options + public void highlightTileUnitIsOccupying() + { + if (selectedUnit != null) + { + highlightMovementRange(getTileUnitIsOccupying()); + } + } + + //In: + //Out: void + //Desc: highlights the selected unit's attackOptions from its position + public void highlightUnitAttackOptionsFromPosition() + { + if (selectedUnit != null) + { + highlightEnemiesInRange(getUnitAttackOptionsFromPosition()); + } + } + + //In: Hash set of the available nodes that the unit can range + //Out: void - it changes the quadUI property in the gameworld to visualize the selected unit's movement + //Desc: This function highlights the selected unit's movement range + public void highlightMovementRange(HashSet movementToHighlight) + { + foreach (Node n in movementToHighlight) + { + quadOnMap[n.x, n.y].GetComponent().material = blueUIMat; + quadOnMap[n.x, n.y].GetComponent().enabled = true; + } + } + + + + //In: Hash set of the enemies in range of the selected Unit + //Out: void - it changes the quadUI property in the gameworld to visualize an enemy + //Desc: This function highlights the enemies in range once they have been added to a hashSet + public void highlightEnemiesInRange(HashSet enemiesToHighlight) + { + foreach (Node n in enemiesToHighlight) + { + quadOnMap[n.x, n.y].GetComponent().material = redUIMat; + quadOnMap[n.x, n.y].GetComponent().enabled = true; + } + } + + + //In: + //Out: void + //Desc: disables the highlight + public void disableHighlightUnitRange() + { + foreach(GameObject quad in quadOnMap) + { + if(quad.GetComponent().enabled == true) + { + quad.GetComponent().enabled = false; + } + } + } + + //In: + //Out: void + //Desc: moves the unit then finalizes the movement + public IEnumerator moveUnitAndFinalize() + { + disableHighlightUnitRange(); + disableUnitUIRoute(); + while (selectedUnit.GetComponent().movementQueue.Count != 0) + { + yield return new WaitForEndOfFrame(); + } + finalizeMovementPosition(); + selectedUnit.GetComponent().setSelectedAnimation(); + } + + + //In: both units engaged in a battle + //Out: + //Desc: deselects the selected unit after the action has been taken + public IEnumerator deselectAfterMovements(GameObject unit, GameObject enemy) + { + //selectedSound.Play(); + selectedUnit.GetComponent().setMovementState(3); + disableHighlightUnitRange(); + disableUnitUIRoute(); + //If i dont have this wait for seconds the while loops get passed as the coroutine has not started from the other script + //Adding a delay here to ensure that it all works smoothly. (probably not the best idea) + yield return new WaitForSeconds(.25f); + while (unit.GetComponent().combatQueue.Count > 0) + { + yield return new WaitForEndOfFrame(); + } + while (enemy.GetComponent().combatQueue.Count > 0) + { + yield return new WaitForEndOfFrame(); + + } + Debug.Log("All animations done playing"); + + deselectUnit(); + + + } + + //In: + //Out: true if there is a tile that was clicked that the unit can move to, false otherwise + //Desc: checks if the tile that was clicked is move-able for the selected unit + public bool selectTileToMoveTo() + { + RaycastHit hit; + Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); + if (Physics.Raycast(ray, out hit)) + { + + if (hit.transform.gameObject.CompareTag("Tile")){ + + int clickedTileX = hit.transform.GetComponent().tileX; + int clickedTileY = hit.transform.GetComponent().tileY; + Node nodeToCheck = graph[clickedTileX, clickedTileY]; + //var unitScript = selectedUnit.GetComponent(); + + if (selectedUnitMoveRange.Contains(nodeToCheck)) { + if ((hit.transform.gameObject.GetComponent().unitOnTile == null || hit.transform.gameObject.GetComponent().unitOnTile == selectedUnit) && (selectedUnitMoveRange.Contains(nodeToCheck))) + { + Debug.Log("We have finally selected the tile to move to"); + generatePathTo(clickedTileX, clickedTileY); + return true; + } + } + } + else if (hit.transform.gameObject.CompareTag("Unit")) + { + + if (hit.transform.parent.GetComponent().teamNum != selectedUnit.GetComponent().teamNum) + { + Debug.Log("Clicked an Enemy"); + } + else if(hit.transform.parent.gameObject == selectedUnit) + { + + generatePathTo(selectedUnit.GetComponent().x, selectedUnit.GetComponent().y); + return true; + } + } + + } + return false; + } + + +}