using System; using UnityEngine; using System.Collections; using System.Collections.Generic; using System.Linq; public class Squad : Unit { #region class members public float TimeBetweenAttacks = 0.5f; public string TeamTag; /// /// List of non attackable units. /// public List Humans; /// /// List of attackable units. /// public List Soldiers; private bool _playerInRange; private Squad _enemySquad; private float _timer; private float _squadMaxHealth; /// /// The tag to assign for each soldiers in the squad /// //protected String SquadTag; private int _numberOfAliveSoldiers; #endregion #region Unity functions // Use this for initialization void Start () { Humans = new List(); Soldiers = new List(); InitializeSquad(); InitializeDefaultTagAndLayer(); CurrentHP = ComputeRemainingHP(); // Debug.Log("Current Zomb HP " + CurrentHP); Attack = ComputeAttackDamage(); _numberOfAliveSoldiers = ComputeNumberOfAliveSoldiers(); _enemySquad = null; _timer = 0f; } // Update is called once per frame void Update () { CurrentHP = ComputeRemainingHP(); _squadMaxHealth = ComputeTotalHP(); HealthImage.fillAmount = (CurrentHP / _squadMaxHealth); _numberOfAliveSoldiers = ComputeNumberOfAliveSoldiers(); _timer += Time.deltaTime; if (_timer >= TimeBetweenAttacks && _playerInRange && !IsDead) { AttackEnemySquad(_enemySquad); } // TODO execute movement command // TODO Check if all the units are dead // if yes destroy if (_numberOfAliveSoldiers > 0) return; // first release all humans ... AbandonUnits(Humans.Count); IsDead = true; } void OnTriggerEnter(Collider collider) { if (IsDead) return; var unitComponent = collider.GetComponent(); if (unitComponent == null) return; // check if the unit is not a friendly one if (this.Tag == unitComponent.Tag) return; if (unitComponent.Tag.Equals(TagLayerManager.Human)) { if (unitComponent.IsCaptured) { return; } else { CaptureHuman(unitComponent); } } else // we know that it's an enemy { if (unitComponent.IsDead) return; _playerInRange = true; _enemySquad = collider.GetComponent(); } } void OnTriggerExit(Collider collider) { if (collider.gameObject.tag == Tag || collider.gameObject.tag == TagLayerManager.Human) return; _playerInRange = false; this.gameObject.GetComponent().PlayAttackAnimation(false); _enemySquad = null; } #endregion #region squad related functions public int ComputeNumberOfAliveSoldiers() { // LINQ + Resharper FTW!!!!! return Soldiers.Count(soldier => !soldier.IsDead); } /// /// Assign the corresponding squad tag to each soldiers. /// protected void InitializeSquad() { if (Soldiers.Count == 0) { this.Soldiers.Add(this.gameObject.GetComponent()); } } private void InitializeDefaultTagAndLayer() { try { if (this.TeamTag.Length == 0) { this.Tag = TagLayerManager.VampirePlayer; this.Layer = TagLayerManager.VampireLayerIndex; } else { if (Tag.Equals(TagLayerManager.VampirePlayer)) { this.Tag = TagLayerManager.VampirePlayer; // set the tag to player 1 this.Layer = TagLayerManager.VampireLayerIndex; } else { this.Tag = TagLayerManager.ZombiePlayer; // set the tag to player 2 this.Layer = TagLayerManager.ZombieLayerIndex; } } } catch (IndexOutOfRangeException ex) { Debug.LogError("Please set a vampire Tag, check the Tag & layers in the inspector!\n" + ex); } // set the tag and the layer of the gameObject to vampire if (this.gameObject.tag != Tag) { this.gameObject.tag = Tag; } if (this.gameObject.layer != Layer) { this.gameObject.layer = Layer; } } /// /// Add the human unit in the humans unit list. /// /// the human unit to add in the human unit list void AddHuman(Unit humanUnit) { Humans.Add(humanUnit); } /// /// Add the human unit in the abandoned unit list. /// /// the soldier unit to add in the soldier unit list void AddSoldier(Squad soldierUnit) { soldierUnit.IsCaptured = false; Soldiers.Add(soldierUnit); } /// /// Dispose of a human unit and heal all the soldiers with a percentage depending /// of the number of remaining soldiers. /// /// The human to dispose public void HealSquad(Unit humanUnit) { var percentageOfHpToHeal = ( humanUnit.CurrentHP / Soldiers.Count ); foreach (var soldier in Soldiers) { soldier.CurrentHP += soldier.CurrentHP * ( 1 + percentageOfHpToHeal ); } humanUnit.GetComponent().PlayFetchedAnimation(); // dispose of the human unit RemoveHuman(humanUnit); } /// /// Abandon a specified amount of units. /// /// The number of units to abandon public void AbandonUnits(int nbUnits) { if (nbUnits <= Humans.Count) { for (var i = 0; i < nbUnits; i++) { // retrieve the human at the specified index var humanUnit = Humans.ElementAt(i); // reassign the human attributes humanUnit.Tag = TagLayerManager.Human; humanUnit.Layer = TagLayerManager.HumanLayerIndex; humanUnit.gameObject.GetComponent().useGravity = true; // add the human to the abandoned Unit list humanUnit.IsCaptured = false; Debug.Log(string.Format("{0} has abandoned the unit {1}", this.gameObject.name, humanUnit.gameObject.name)); // remove the human from the humandUnit that was added to the abandoned unit list RemoveHuman(humanUnit); } } else { Debug.LogError("Exceeded the maximum numbers of units in the humans list!"); } } /// /// Remove the selected soldier from the unit list. /// /// the corresponding soldier that we want to remove void RemoveSoldier(Squad soldierUnit) { Soldiers.Remove(soldierUnit); } /// /// Remove the selected human from the human list. /// /// the corresponding human that we want to remove void RemoveHuman(Unit humanUnit) { Humans.Remove(humanUnit); } /// /// Transform the human to the corresponding type of the squad. /// /// the number of humans to transform public void TransformHuman(int nbHumans) { if (nbHumans <= Humans.Count) { for (var i = 0; i < nbHumans; i++) { // retrieve the human at the specified index var humanUnit = Humans.ElementAt(i); // remove the human from the human list RemoveHuman(humanUnit); // set the human tag to the same as the squad humanUnit.Tag = Tag; AddSoldier(humanUnit as Squad); } } else { Debug.LogError("Exceeded the maximum number of humans in the humans list!"); } } public void ReceiveDamage(float amountOfDamage) { // apply the damage to the first soldier in the list foreach (var soldier in Soldiers) { //soldier.CurrentHP -= amountOfDamage; soldier.TakeDamage(amountOfDamage); Debug.Log(string.Format("{0} received {1} damage!", soldier.name, amountOfDamage)); Debug.Log(string.Format("{0} remaining hp : {1}", soldier.name, soldier.CurrentHP)); } } protected void CaptureHuman(Unit unit) { // set the position of the squad as a target, so that // the unit would always follow the squad leader unit.TargetDestination = this.transform; // specify that the unit is captured to that the captured animation plays at the next update. unit.IsCaptured = true; // add the caught human in the caught list. AddHuman(unit); Debug.Log(string.Format("{0} joined the squad of : {1} ", unit.gameObject.name, transform.gameObject.name)); } protected void AttackEnemySquad(Squad targettedEnemySquad) { _timer = 0f; if (targettedEnemySquad.CurrentHP > 0) { foreach (var soldier in Soldiers) { soldier.GetComponent().PlayAttackAnimation(true); } targettedEnemySquad.ReceiveDamage(ComputeAttackDamage()); Debug.Log(string.Format("{0} Attacked the enemy : {1} ", this.gameObject.name, targettedEnemySquad.gameObject.name)); } else { foreach (var soldier in Soldiers) { soldier.GetComponent().PlayAttackAnimation(false); } } } /// /// Compute to attack damage depending of the numbers of soldiers in the squad. /// /// the damage to apply to each enemy soldiers units protected float ComputeAttackDamage() { // LINQ + Resharper FTW!!!!! var sumOfAttack = Soldiers.Sum(soldier => soldier.Attack); return ( 1 + (sumOfAttack / Soldiers.Count)); } protected float ComputeRemainingHP() { var sumOfHp = Soldiers.Sum(x => x.CurrentHP); return sumOfHp; } protected float ComputeTotalHP() { var sumOfHp = Soldiers.Sum(x => x.MaxHealth); return sumOfHp; } #endregion #region squad accessors and mutators #endregion }