public void Copy(AIUnit original) { this.currentState = original.currentState; this.splitFactor = original.splitFactor; this.mergeFactor = original.mergeFactor; this.attackCooldownFactor = original.attackCooldownFactor; this.attackFactor = original.attackFactor; this.unitManager = original.unitManager; this.currentHealth = original.currentHealth; this.maxHealth = original.maxHealth; this.splitCounter = original.splitCounter; this.minimapCameraRect = original.minimapCameraRect; this.teamFaction = original.teamFaction; this.SetTeamColor(original.teamColorValue); AILineOfSight myLOS = this.GetComponentInChildren <AILineOfSight>(); AILineOfSight originalLOS = original.GetComponentInChildren <AILineOfSight>(); AIAttackRange myAR = this.GetComponentInChildren <AIAttackRange>(); AIAttackRange originalAR = original.GetComponentInChildren <AIAttackRange>(); myLOS.teamFaction = originalLOS.teamFaction; myAR.teamFaction = originalAR.teamFaction; }
//Actual update tick public void Tick() { if (this.unitCount <= 0) { //Defeat. No more AI units on the map. Debug.Log("AI Player is defeated."); this.hasLostTheGame = true; this.startAIFlag = false; return; } switch (this.currentFiniteState) { case FSMState.Wait: if (this.selectedUnits.Count > 0) { this.selectedUnits.Clear(); } if (this.unitCount == 1) { //Usually at the start of the game, or when the AI player is on the brink of defeat. Transform child = this.unitContainer.transform.GetChild(this.unitContainer.transform.childCount - 1); AIUnit unit = child.GetComponent <AIUnit>(); AILineOfSight lineOfSight = child.GetComponentInChildren <AILineOfSight>(); AIAttackRange attackRange = child.GetComponentInChildren <AIAttackRange>(); //TODO: Refer to an attribute manager for AI units on what attributes are required. unit.teamFaction = this.teamFaction; lineOfSight.teamFaction = this.teamFaction; attackRange.teamFaction = this.teamFaction; //Always select the unit before doing other AI state machines. this.spawnList.Add(unit); this.currentFiniteState = FSMState.Split; break; } int scoutUnitCount = 0; int splitUnitCount = 0; int mergeUnitCount = 0; foreach (Transform child in this.unitContainer.transform) { if (splitUnitCount > 0) { splitPercentage = splitRatio / splitUnitCount; } else { splitPercentage = splitRatio / 1f; } if (mergeUnitCount > 0) { mergePercentage = mergeRatio / mergeUnitCount; } else { mergePercentage = mergeRatio / 1f; } if (scoutUnitCount > 0) { scoutPercentage = scoutRatio / scoutUnitCount; } else { scoutPercentage = scoutRatio / 1f; } if (this.splitPercentage > this.mergePercentage && this.splitPercentage > this.scoutPercentage) { this.spawnList.Add(child.GetComponent <AIUnit>()); splitUnitCount++; } else if (this.splitPercentage > this.mergePercentage && this.splitPercentage < this.scoutPercentage) { this.selectedUnits.Add(child.GetComponent <AIUnit>()); scoutUnitCount++; } else if (this.splitPercentage < this.mergePercentage && this.splitPercentage > this.scoutPercentage) { this.mergeList.Add(child.GetComponent <AIUnit>()); mergeUnitCount++; } else if (this.splitPercentage < this.mergePercentage && this.splitPercentage < this.scoutPercentage) { if (this.mergePercentage > this.scoutPercentage) { this.mergeList.Add(child.GetComponent <AIUnit>()); mergeUnitCount++; } else { this.selectedUnits.Add(child.GetComponent <AIUnit>()); scoutUnitCount++; } } } this.currentFiniteState = FSMState.Merge; break; case FSMState.Split: if (this.spawnList.Count > 0) { foreach (AIUnit unit in this.spawnList) { if (unit != null && unit.currentState != State.Split) { if (this.unitCount < this.maxUnitCount) { GameObject splitObject = SplitUnit(unit); if (splitObject != null) { this.splitGroupList.Add(new SplitGroup(unit.gameObject, splitObject)); } } else { break; } } } this.spawnList.Clear(); } this.currentFiniteState = FSMState.Wait; break; case FSMState.Scout: Debug.Log("AI player is ready to scout."); if (this.selectedUnits.Count > 0) { for (int i = 0; i < this.selectedUnits.Count; i++) { if (this.selectedUnits[i] != null) { this.selectedUnits[i].SetScoutFlag(); } else { this.selectedUnits.RemoveAt(i); } } this.selectedUnits.Clear(); } if (this.spawnList.Count > 0) { this.currentFiniteState = FSMState.Split; } else { this.currentFiniteState = FSMState.Wait; } break; case FSMState.Merge: if (this.mergeList.Count > 0) { if (this.mergeList.Count > 1) { AIUnit owner = null; AIUnit merge = null; List <AIUnit> removeList = new List <AIUnit>(); for (int i = 0; i < this.mergeList.Count - 1; i++) { if (this.mergeList[i] != null && !removeList.Contains(this.mergeList[i])) { owner = this.mergeList[i]; if (owner.CheckMergeFlag()) { for (int j = i + 1; j < this.mergeList.Count; j++) { merge = this.mergeList[j]; if (merge != null && !removeList.Contains(merge) && !owner.Equals(merge) && owner.level == merge.level) { //TODO: Once unit attribute manager is implemented for the AI player, change the 2f to the actual scaling factor. if (merge.CheckMergeFlag()) { owner.SetMergeFlag(); merge.SetMergeFlag(); this.mergeGroupList.Add(new MergeGroup(owner.gameObject, merge.gameObject, 1.5f)); //ScaleFactor is done here. removeList.Add(owner); removeList.Add(merge); break; } else { continue; } } } } } } removeList.Clear(); } this.mergeList.Clear(); } this.currentFiniteState = FSMState.Scout; break; } foreach (Transform child in this.unitContainer.transform) { if (child != null) { AIUnit unit = child.GetComponent <AIUnit>(); if (unit != null) { unit.Tick(); } } } }
public void Start() { bool initialStateFlag = false; if (this.unitManager != null) { AIAttributeManager aiAttributeManager = this.unitManager.aiAttributeManager; if (aiAttributeManager.tiers != null) { TierUpgrade firstTier = aiAttributeManager.tiers[0]; this.maxHealth = (int)(firstTier.health); this.currentHealth = this.maxHealth; this.attackFactor = firstTier.attack; this.attackCooldownFactor = firstTier.attackCooldown; this.speedFactor = firstTier.speed; this.splitFactor = firstTier.split; this.mergeFactor = firstTier.merge; initialStateFlag = true; } } this.currentState = State.Idle; this.level = 1; this.previousLevel = 1; this.isSplitting = false; this.splitCounter = 0f; this.mergeCounter = 0f; this.attackCooldownCounter = 1f; this.recoveryCounter = 1f; if (!initialStateFlag) { this.speedFactor = 1f; if (this.attackFactor == 0f) { this.attackFactor = 1f; } if (this.splitFactor == 0f) { this.splitFactor = 1f; } if (this.mergeFactor == 0f) { this.mergeFactor = 1f; } if (this.attackCooldownFactor == 0f) { this.attackCooldownFactor = 1f; } this.currentHealth = this.maxHealth; } if (this.lineOfSight == null) { this.lineOfSight = this.GetComponentInChildren <AILineOfSight>(); if (this.lineOfSight == null) { Debug.LogError("Cannot find Line of Sight component for the AI unit."); } } if (this.attackRange == null) { this.attackRange = this.GetComponentInChildren <AIAttackRange>(); if (this.attackRange == null) { Debug.LogError("Cannot find Attack Range component for the AI unit."); } } this.agent = this.GetComponent <NavMeshAgent>(); if (this.agent != null) { this.agent.stoppingDistance = 1.5f; if (!initialStateFlag) { this.agent.speed = this.speedFactor; } } GameObject minimapObject = GameObject.FindGameObjectWithTag("Minimap"); if (minimapObject != null) { Camera camera = minimapObject.GetComponent <Camera>(); this.minimapCameraRect = camera.rect; } else { minimapObject = GameObject.FindGameObjectWithTag("Menu"); if (minimapObject != null) { Image image = minimapObject.GetComponent <Image>(); this.minimapCameraRect = image.rectTransform.rect; } } }