// Called before start protected void Awake() { // These will have to be set multiple times [allies only] SetReferences(); // These will only need to be set once, since they are attached to this game object _sprRendRef = this.GetComponent <SpriteRenderer>(); if (_sprRendRef == null) { Debug.Log("Could not find SpriteRenderer attached to " + this.name); } _anime = this.GetComponent <Animator>(); if (_anime == null) { Debug.Log("Could not find Animator attached to " + this.name); } _maRef = this.GetComponent <MoveAttack>(); if (_maRef == null) { Debug.Log("Could not find MoveAttack attached to " + this.name); } _statsRef = this.GetComponent <Stats>(); if (_statsRef == null) { Debug.Log("Could not find Stats attached to " + this.name); } }
/// <summary> /// When the last character in the room leaves, un trigger the room /// </summary> /// <param name="collision"></param> private void OnTriggerExit2D(Collider2D collision) { // If we collide with something that has a MoveAttack script attached, remove it from characters currently in the room MoveAttack mARef = collision.GetComponent <MoveAttack>(); if (mARef == null) { return; } // If it was an ally if (mARef.WhatAmI == CharacterType.Ally) { _alliesInRoom.Remove(mARef); // If it was the last ally and that ally dead if (_alliesInRoom.Count == 0 && mARef.GetComponent <Health>().CurHP == 0) { CalmRoom(mARef); } } // If it was an enemy and the room is active else if (mARef.WhatAmI == CharacterType.Enemy && mARef.gameObject.activeInHierarchy) { _enemiesInRoom.Remove(mARef); // If it was the last enemy if (_enemiesInRoom.Count == 0) { _clear = true; } } }
/// <summary> /// Finds if there is an enemy in range and gives its gridPositon, if there's not, it returns an invalid gridPosition /// </summary> /// <returns>Returns a Vector2Int on the grid if it finds an enemy, otherwise returns a Vector2Int off the grid</returns> private Vector2Int FindDesiredAttackNodePos() { // If there is an "ally" character in range, we want that node // Test if the ally is in range // Iterate over each ally for (int i = 0; i < _alliesMA.Count; ++i) { MoveAttack ally = _alliesMA[i]; // Make sure the enemy exists if (ally == null) { _alliesMA.RemoveAt(i); --i; continue; } // Get that ally's node Node allyNode = _mAContRef.GetNodeByWorldPosition(ally.transform.position); // If that ally's node is in this enemy's move tiles, they are in range, so that is the node we want to reach if (_currentEnemy.AttackTiles.Contains(allyNode)) { //Debug.Log("Found ally to attack at " + allyGridPos); return(allyNode.Position); } } //Debug.Log("No ally in range"); // If there is no ally in range, we don't want to attack anything with a character on it, so we return a position not on the grid return(new Vector2Int(_mAContRef.GridTopLeft.x - 1, 0)); }
// Called before start protected void Awake() { // These references are attached to this game object, so they will only need to be set once _mARef = this.GetComponent <MoveAttack>(); if (_mARef == null) { if (this.name != "DeadAllyStats") { Debug.Log("Could not find MoveAttack attached to " + this.name); } } else { _mARef.MoveRange = _speed; } _hpRef = this.GetComponent <Health>(); if (_hpRef == null) { if (this.name != "DeadAllyStats") { Debug.Log("Could not find Health attached to " + this.name); } } else { _hpRef.MaxHP = _vitality; _hpRef.CurHP = _hpRef.MaxHP; } }
// Called 0th // Set references to itself private void Awake() { _mARef = this.GetComponent <MoveAttack>(); if (_mARef == null) { Debug.Log("WARNING - There was no MoveAttack script attached to " + this.name); } GameObject gameContObj = GameObject.FindWithTag("GameController"); if (gameContObj == null) { Debug.Log("WARNING - No GameObject with the tag GameController was found"); } _skillHoldRef = gameContObj.GetComponent <SkillHolder>(); if (_skillHoldRef == null) { Debug.Log("WARNING - There was no SkillHolder script attached to " + gameContObj.name); } // Initialize the list of skills _availableSkills = new List <Skill>(); // Subscribe to the procedural gen event ProceduralGenerationController.OnFinishGenerationNoParam += Initialize; }
/// <summary> /// Attempts to do whatever action this enemy does. /// Called after the character finishes moving. /// Uses the character's skill on an enemy in range. /// </summary> override protected void AttemptAction() { // Recalculate the enemy's move and attack tiles. // We really only want their attack tiles, but those are based on the move tiles // Which are currently out of place since they are what the MARef.CalculateAllTiles(); Vector2Int nodeToAttack = new Vector2Int(int.MaxValue, int.MaxValue); // Try to find an ally in range //Debug.Log("These are " + this.name + " at " + this.transform.position + " potential attack tiles: "); foreach (Node atkNode in MARef.AttackTiles) { //Debug.Log(atkNode.Position); MoveAttack potAlly = MAContRef.GetCharacterMAByNode(atkNode); // If we found an ally at that tile if (potAlly != null && potAlly.WhatAmI == CharacterType.Ally) { //Debug.Log("Attacking ^ That tile"); nodeToAttack = atkNode.Position; break; } } // If there is no node to attack, just end the attack if (nodeToAttack.x == int.MaxValue && nodeToAttack.y == int.MaxValue) { MARef.EndAttack(); } // If there is a node being attacked, start the attack else { MARef.StartAttack(nodeToAttack); } }
/// <summary> /// Creates the visual tiles for each character /// </summary> private void InitialCreateVisuals() { // For each character create the visual tiles // based on their starting moveRange and attackRange. // Also initializes each character // Do this for each ally foreach (Transform allyTrans in _allyParent) { MoveAttack mARef = allyTrans.GetComponent <MoveAttack>(); if (mARef == null) { Debug.Log(allyTrans.name + " does not have a MoveAttack script attached to it"); } else { // Create the visual tiles ahead of time CreateVisualTiles(mARef); } } // Do this for each enemy foreach (Transform enemyTrans in _enemyParent) { MoveAttack mARef = enemyTrans.GetComponent <MoveAttack>(); if (mARef == null) { Debug.Log(enemyTrans.name + " does not have a MoveAttack script attached to it"); } else { // Create the visual tiles ahead of time CreateVisualTiles(mARef); } } }
// Start is called before the first frame update private void Start() { // Initialize the list _allies = new List <GameObject>(); // Get the initial allies foreach (Transform character in _tempAllyParent) { // Try to pull a move attack script off the character, they should have one MoveAttack charMARef = character.GetComponent <MoveAttack>(); // See if the character is an ally, if they aren't we just want to test the next character if (charMARef == null || charMARef.WhatAmI != CharacterType.Ally) { continue; } // Add the ally to the list _allies.Add(character.gameObject); } //Debug.Log("Finished initializing allies"); // Initialize the starting floors stuff // Initialize the floor difficulty to 3 _nextFloorDiff = 4; _nextFloorNum = 1; _shouldHaveCamfire = _nextFloorNum % _floorsUntilFire == 0; // Start the first floor's generation StartGeneration(); }
/// <summary> /// Refinds all the allies. Resets the enemy index to 0. /// Removes dead enemies from the list. Sets during enemy turn to false /// </summary> private void FindCharacters() { _alliesMA = new List <MoveAttack>(); _enemyIndex = 0; // Iterate over each ally to add them to the list foreach (Transform allyTrans in _allyParent) { MoveAttack mA = allyTrans.GetComponent <MoveAttack>(); if (mA == null) { Debug.Log("There was no MoveAttack attached to " + allyTrans.name); continue; } _alliesMA.Add(mA); } // Bring out your dead *rings bell* Bring out your dead // We have to go over the enemies list and remove any dead enemies for (int i = 0; i < _enemiesMA.Count; ++i) { // If we find a dead enemy, get rid of them if (_enemiesMA[i] == null) { _enemiesMA.RemoveAt(i); // We also need to decrement i so that the list does not stop prematurely since the list now shrank by 1 --i; } } _duringEnemyTurn = false; }
/// <summary> /// Has the current enemy move and then increments it so that the next time this is called, the next enemy will move /// </summary> private IEnumerator NextEnemy() { // So that the this enemy can't start until the previous one is done while (_duringEnemyTurn) { yield return(null); } _duringEnemyTurn = true; if (_enemyIndex < _enemiesMA.Count) { // Try to get the current enemy we should move _currentEnemy = _enemiesMA[_enemyIndex]; // If the enemy does not exist, do not try to move it if (_currentEnemy != null) { // Call the begin single enemy event if (OnBeginSingleEnemy != null) { OnBeginSingleEnemy(_currentEnemy); } //Debug.Log("Begin " + _currentEnemy.name + "'s turn"); // See if the current enemy will be active Node enemyNode = _mAContRef.GetNodeByWorldPosition(_currentEnemy.transform.position); for (int i = 0; i < _alliesMA.Count; ++i) { MoveAttack ally = _alliesMA[i]; // Make sure the enemy exists if (ally == null) { _alliesMA.RemoveAt(i); --i; continue; } Node allyNode = _mAContRef.GetNodeByWorldPosition(ally.transform.position); if (Mathf.Abs(enemyNode.Position.x - allyNode.Position.x) + Mathf.Abs(enemyNode.Position.y - allyNode.Position.y) <= _aggroRange) { break; } } } // Have the current enemy take their turn // Now called from the CamFollow OnFinishEnemyPan event //TakeSingleTurn(); } else { //Debug.Log("All enemies done"); if (OnEnemyTurnEnd != null) { OnEnemyTurnEnd(); } } _duringEnemyTurn = false; yield return(null); }
/// <summary> /// Updates the value of the side health bar /// </summary> private IEnumerator UpdateSideHealth() { // Add the ongoing action MoveAttack.AddOngoingAction(); // Get the target amount to work towards float targetAm = ((float)CurHP) / MaxHP; // If we are lower than the current amount while (_sideSlider.value < targetAm) { _sideSlider.value += Time.deltaTime * _healthBarSpeed; yield return(null); } // If we are higher than the current amount while (_sideSlider.value > targetAm) { _sideSlider.value -= Time.deltaTime * _healthBarSpeed; yield return(null); } // Just set it to what it is supposed to be _sideSlider.value = targetAm; // Remove the ongoing action MoveAttack.RemoveOngoingAction(); yield return(null); }
/// <summary> /// Finds the closest ally to the current enemy /// </summary> /// <returns>Returns the node that the closest ally is on [0]. Also returns the closest node to attack that ally from [1]</returns> private Node[] FindAllyOutOfRange() { // Get the node the current enemy is at Node startNode = _mAContRef.GetNodeByWorldPosition(_currentEnemy.transform.position); // Find the allies, and see if they are more than maxDepth grid units away anyway // If they are, we just return null Node closestAllyNode = null; // The node of the closest ally // The closest allies distance from the currentEnemy int closestAllyDist = int.MaxValue; // The closest ally in terms of Node.F int closestF = int.MaxValue; // Closest node to attack the closest ally from Node closestAttackNode = null; for (int i = 0; i < _alliesMA.Count; ++i) { MoveAttack curAlly = _alliesMA[i]; // Make sure the current ally exists if (curAlly == null) { continue; } Node curAllyNode = _mAContRef.GetNodeByWorldPosition(curAlly.transform.position); int curAllyDist = Mathf.Abs(startNode.Position.x - curAllyNode.Position.x) + Mathf.Abs(startNode.Position.y - curAllyNode.Position.y); // Quick check if ally is close to this enemy and is closer than the current closest ally if (curAllyDist <= _aggroRange && curAllyDist < closestAllyDist) { // Check to make sure the enemy has a place to stand to attack and that the enemy can reach that node // // Get the nodes the enemy can attack the ally from List <Node> allyAttackNodes = _mAContRef.GetNodesDistFromNode(curAllyNode, _currentEnemy.AttackRange); // Iterate over each of the nodes the enemy could potentially stand at to attack for (int j = 0; j < allyAttackNodes.Count; ++j) { // See if the node exists and there is no character there if (allyAttackNodes[j] != null && allyAttackNodes[j].Occupying == CharacterType.None) { // See if there is a path to there for enemies if (_mAContRef.Pathing(startNode, allyAttackNodes[j], CharacterType.Enemy)) { // See if the F value is lower if (closestF > startNode.F) { closestF = startNode.F; _mAContRef.ResetPathing(); closestAllyNode = curAllyNode; closestAllyDist = curAllyDist; closestAttackNode = allyAttackNodes[j]; } } } } } } Node[] rtnList = { closestAllyNode, closestAttackNode }; // Returns null if the closestAlly node was not found return(rtnList); }
/// <summary> /// Called from Procedural Generation after everything is created. /// Gets the allies and enemies from the character parent /// </summary> /// <param name="charPar">Parent of all characters</param> public void Initiasdalize(Transform charPar) { // Set the transform of the character parent charParent = charPar; // Get the scripts on the characters allyMARefs = new List <MoveAttack>(); enemyMARefs = new List <MoveAttack>(); foreach (Transform child in charParent) { MoveAttack mARef = child.GetComponent <MoveAttack>(); if (mARef == null) { Debug.Log("Could not find MoveAttack attached to " + child.name); continue; } if (mARef.WhatAmI == CharacterType.Ally) { allyMARefs.Add(mARef); } else if (mARef.WhatAmI == CharacterType.Enemy) { enemyMARefs.Add(mARef); } else { Debug.Log(child.name + " is having an identity crisis"); } scriptsToTurnOff.Add(mARef); } }
/// <summary> /// Calls UpdateSkillButtons with the most recently selected character. /// Refreshes the skill buttons to reflect any changes /// </summary> private void RefreshSkillButtons() { // Get the current selected allies skill controller MoveAttack charMA = _mAGUIContRef.RecentCharSelectedMA; UpdateSkillButtons(charMA); // Also refresh the skill pop out menu RefreshSkillDetails(); }
public Bishop() { this.HitPoints = 1; this._MoveBehavior.MoveType = MoveBehavior.MoveTypes.Diagonal; var attackBehavior = new MoveAttack(this._MoveBehavior); attackBehavior.Damage = 1; this._AttackBehavior = attackBehavior; }
public Queen() { this.HitPoints = 1; this._MoveBehavior.MoveType = MoveBehavior.MoveTypes.Diagonal | MoveBehavior.MoveTypes.Linear; var attackBehavior = new MoveAttack(this._MoveBehavior); attackBehavior.Damage = 1; this._AttackBehavior = attackBehavior; }
/// <summary> /// Turns off all the visual tiles /// </summary> /// <param name="mARef">Reference to the MoveAttack script attached to the character whose visuals we are turning off</param> public void TurnOffVisuals(MoveAttack mARef) { // Iterate over all the tiles and turn them off foreach (Transform tileParent in mARef.RangeVisualParent.transform) { foreach (Transform tileTrans in tileParent) { tileTrans.gameObject.SetActive(false); } } }
public SoldierA() { this.HitPoints = 5; this._MoveBehavior.MoveType = MoveBehavior.MoveTypes.Standard; this.MoveDistance = 2; var attackBehavior = new MoveAttack(this._MoveBehavior); attackBehavior.Damage = 1; this._AttackBehavior = attackBehavior; }
public PansyC() { this.HitPoints = 1; this._MoveBehavior.MoveType = MoveBehavior.MoveTypes.Standard; this.MoveDistance = 3; var attackBehavior = new MoveAttack(this._MoveBehavior); attackBehavior.Damage = 1; this._AttackBehavior = attackBehavior; }
/// <summary> /// Swaps the skill of the current selected player /// Called by the skill swap button. /// </summary> public void SwapSelectedPlayerSkill() { // Get the current selected allies skill controller MoveAttack charMA = _mAGUIRef.RecentCharSelectedMA; if (charMA != null) { // Get a refrence to the currently selected ally's skill controller AllySkillController curAllySkillCont = charMA.GetComponent <AllySkillController>(); // Swap the equipped skill curAllySkillCont.SwapSkill(); } }
/// <summary> /// Called when the last ally in a room dies. Turns off the room /// </summary> /// <param name="allyWhoExited">The enemy who just exited the room (died)</param> private void CalmRoom(MoveAttack allyWhoExited) { Debug.Log("Calming the room"); // We want to turn the room off _currentLightIntensity = 0f; // Change the intensity of this room this.BeginChangeIntensity(); // Update lighting of the adjacent rooms foreach (Room adjRoom in _adjacentRooms) { adjRoom.BeginChangeIntensity(); } }
/// <summary> /// When this object collides with the player for the first time, we trigger the room. Also adds characters to what is currently in the room /// </summary> /// <param name="collision">The collider2d of the object that was collided with</param> private void OnTriggerEnter2D(Collider2D collision) { // Try to get the movement script from what we collided with, and tests if it exists MoveAttack mARef = collision.GetComponent <MoveAttack>(); if (mARef == null) { return; } // If we collide with an enemy if (mARef.WhatAmI == CharacterType.Enemy) { // If they aren't already a part of the room's enemies, add them to it if (!_enemiesInRoom.Contains(mARef)) { _clear = false; _enemiesInRoom.Add(mARef); } // Also, if their room isn't active hide them (transition is used to test if it is the beginning of the game or not, since we don't // want an enemy to disappear when they walk between rooms, for which transition will always be true if (!_isRoomActive && mARef.Transition == false) { mARef.gameObject.SetActive(false); } } // If we collide with a player else if (mARef.WhatAmI == CharacterType.Ally) { // Add them to the allies in room // Make sure they are not already in the list if (!_alliesInRoom.Contains(mARef)) { _alliesInRoom.Add(mARef); } // Turn on the room TriggerRoom(mARef); // If we haven't activated the enemies in the room yet, do that if (!_isRoomActive) { _isRoomActive = true; // Call the room activate event if (OnRoomActivate != null) { OnRoomActivate(_enemiesInRoom); } } } }
/// <summary> /// Turns the visuals of the character off and no longer selects them /// </summary> private void Deselect() { if (_charSelected != null) { _mAContRef.TurnOffVisuals(_charSelected); _charSelected.MyStats.DisplayStats(false); _charSelected = null; } // Call the character selected event if (OnCharacterDeselect != null) { OnCharacterDeselect(null); } }
public override Attack GetCopy(Unit o) { MoveAttack nca; nca = new MoveAttack(attackId, arrowId, isActiveState, armyId, o, keyFieldId, isKeyFieldTaken, targetId, arrowPosition); foreach (int i in activatesAttacks) { nca.AddActivatedAttackId(i); } foreach (int i in deactivatesAttacks) { nca.AddDeactivatedAttackId(i); } return((Attack)nca); }
// End Grid Functions // Visual Tile Functions /// <summary> /// Creates the visual tiles for when a character is clicked on /// </summary> /// <param name="mARef">Reference to the character whose visual tiles will be created</param> public void CreateVisualTiles(MoveAttack mARef) { // Make sure it exists if (mARef != null) { if (mARef.RangeVisualParent == null) { InitializeVisualTiles(mARef); } } else { Debug.Log(mARef.name + " has no MoveAttack script attached to it"); } }
/// <summary> /// Updates the skill skill buttons to reflect the selected character's skills /// </summary> private void UpdateSkillButtons(MoveAttack selChara) { // Get the current character's available skills List <Skill> availSkills = new List <Skill>(); if (selChara != null) { availSkills = selChara.GetComponent <CharacterSkills>().GetAvailableSkills(); } // Determine how many skills they have int amountSkills = availSkills.Count; if (amountSkills > _sideSkillObjs.Count) { Debug.LogError("The character has too many skills. Or there are too few side skill objects"); amountSkills = _sideSkillObjs.Count; } // Turn on only as many side skills as needed for (int i = 0; i < amountSkills; ++i) { _sideSkillObjs[i].SetActive(true); _sideSkillIcons[i].sprite = SkillHolder.GetSkillImage(availSkills[i].GetSkillNum()); if (availSkills[i].GetCooldownTimer() > 0) { _skillCoolTexts[i].text = availSkills[i].GetCooldownTimer().ToString(); } else { _skillCoolTexts[i].text = ""; } // If the skill is the active one, make it have the active color if (availSkills[i] == selChara.SkillRef) { _sideSkillIcons[i].color = _activeCol; } else { _sideSkillIcons[i].color = _inactiveCol; } } // Turn off the uneeded ones for (int i = amountSkills; i < _sideSkillObjs.Count; ++i) { _sideSkillObjs[i].SetActive(false); } }
// Use this for initialization void Start() { spriteRenderer = gameObject.GetComponentInChildren <SpriteRenderer> (); shadow = gameObject.GetComponentInChildren <MeshRenderer>(); gc = GameController.Instance; rb = GetComponent <Rigidbody> (); maxHealth = health; Reset(); Hide(); //STATE MACHINE INITIALISATION fsm = new FSM(); idle = new Idle(); move = new Move(); attack = new Attack(); moveAttack = new MoveAttack(); //idle: moveVec.sqrMagnitude == 0 && shootVec.sqrMagnitude == 0 //move: moveVec.sqrMagnitude != 0 && shootVec.sqrMagnitude == 0 //attack: moveVec.sqrMagnitude == 0 && shootVec.sqrMagnitude != 0 //moveattack: moveVec.sqrMagnitude != 0 && shootVec.sqrMagnitude != 0 idle.AddTransition(new Transition(move, () => moveVec.sqrMagnitude != 0 && shootVec.sqrMagnitude == 0)); idle.AddTransition(new Transition(attack, () => moveVec.sqrMagnitude == 0 && shootVec.sqrMagnitude != 0)); idle.AddTransition(new Transition(moveAttack, () => moveVec.sqrMagnitude != 0 && shootVec.sqrMagnitude != 0)); move.AddTransition(new Transition(idle, () => moveVec.sqrMagnitude == 0 && shootVec.sqrMagnitude == 0)); move.AddTransition(new Transition(attack, () => moveVec.sqrMagnitude == 0 && shootVec.sqrMagnitude != 0)); move.AddTransition(new Transition(moveAttack, () => moveVec.sqrMagnitude != 0 && shootVec.sqrMagnitude != 0)); //attack not moving attack.AddTransition(new Transition(move, () => moveVec.sqrMagnitude != 0 && shootVec.sqrMagnitude == 0 && !CurrentWeaponScript.shootDelaying)); attack.AddTransition(new Transition(idle, () => moveVec.sqrMagnitude == 0 && shootVec.sqrMagnitude == 0 && !CurrentWeaponScript.shootDelaying)); attack.AddTransition(new Transition(moveAttack, () => moveVec.sqrMagnitude != 0 && shootVec.sqrMagnitude != 0)); //attack while moving moveAttack.AddTransition(new Transition(move, () => moveVec.sqrMagnitude != 0 && shootVec.sqrMagnitude == 0 && !CurrentWeaponScript.shootDelaying)); moveAttack.AddTransition(new Transition(idle, () => moveVec.sqrMagnitude == 0 && shootVec.sqrMagnitude == 0 && !CurrentWeaponScript.shootDelaying)); moveAttack.AddTransition(new Transition(attack, () => moveVec.sqrMagnitude == 0 && shootVec.sqrMagnitude != 0)); fsm.AddState(idle); fsm.AddState(move); fsm.AddState(attack); fsm.Init(idle, Directions.Unspecified, Directions.Unspecified); }
/// <summary> /// Returns a room, that is not this room, that contains the given ally /// </summary> /// <param name="ally">The ally coming from the room we will return</param> /// <returns>Room adjacent to this room where ally came from</returns> private Room GetAdjacentRoomByAlly(MoveAttack ally) { // Iterate over the adjacent rooms until we get the room this ally is in foreach (Room adjRoom in _adjacentRooms) { if (adjRoom._alliesInRoom.Contains(ally)) { return(adjRoom); } } // If we don't find it, something went wrong, or the game just started if (ally.Transition) { Debug.Log("Could not find adjacent room with " + ally.name + " in it"); } return(null); }
// Gets character selected using the event and changes allyIndex to match the character selected character private void CharacterToHeal(MoveAttack charMA) { if (charMA.WhatAmI == CharacterType.Ally && _isHolding == true) { // reduces the charges PersistantController.SetPotCharges(PersistantController.GetPotCharges() - 1); _allyToHeal = charMA.GetComponent <AllyHealth>(); if (_allyToHeal == null) { Debug.LogError("No AllyHealth attached to " + _allyToHeal.name); } HealCharacter(); _isHolding = false; } }
/// <summary> /// Tries to start moving the selected character to the node that was just selected /// or tries to go to hit the enemy at the selected node /// </summary> /// <param name="selNode">The node that was just selected</param> /// <returns>Returns true if the character will do an action, false if they just got deselected</returns> private bool AttemptMoveOrAttackOrInteract(Node selNode) { MoveAttack charAtNode = _mAContRef.GetCharacterMAByNode(selNode); // If the current character can move there if (_charSelected.MoveTiles.Contains(selNode) && selNode.Occupying == CharacterType.None) { // We want the user to be able to select after moving, so // when the ally finishes moving, return control MoveAttack.OnCharacterFinishedMoving += ReturnControlAfterMove; // Start moving the ally Node startNode = _mAContRef.GetNodeByWorldPosition(_charSelected.transform.position); DoMove(startNode, selNode); return(true); } // If the current character can attack there (and wants to attack), and there is an (active) enemy there. // Then we want the current character to walk to the closest node to there and attack else if (_charSelected.AttackTiles.Contains(selNode) && !_charSelected.TargetFriendly && charAtNode != null && charAtNode.WhatAmI == CharacterType.Enemy && charAtNode.gameObject.activeInHierarchy) { AttemptMoveAndAttack(selNode); return(true); } // If the current character can heal/buff there (and wants to), and there is an ally there. // Then we want the current character to walk to the closest node to there and heal/buff else if (_charSelected.AttackTiles.Contains(selNode) && _charSelected.TargetFriendly && charAtNode != null && charAtNode.WhatAmI == CharacterType.Ally && charAtNode != _charSelected) { AttemptMoveAndAttack(selNode); return(true); } // If the current character can interact there, and there is an interactable thing there else if (_charSelected.InteractTiles.Contains(selNode) && selNode.Occupying == CharacterType.Interactable) { AttemptMoveAndInteract(selNode); return(true); } // If none of the above, just deselect them else { Deselect(); return(false); } }