using System.Collections; using System.Collections.Generic; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace TBTK{ [ExecuteInEditMode] public class UnitManager : MonoBehaviour { public List allUnitList=new List(); public static List GetAllUnitList(){ if(TurnControl.IsUnitPerTurn()) return instance.allUnitList; else{ instance.allUnitList=new List(); for(int i=0; i factionList=new List(); public static List GetFactionList(){ return instance.factionList; } public static Faction GetFaction(int idx){ return instance.factionList[idx]; } private bool hasAIInGame=false; public Unit selectedUnit; public static Unit GetSelectedUnit(){ return instance.selectedUnit; } public static Faction GetSelectedFaction(){ if(GetSelectedUnit()==null) return null; for(int i=0; i=0) instance.NewFactionDeployment(); instance._Init(); } public void _Init(){ //~ selectIndicator=GridManager.IsHexGrid() ? selectIndicatorHex : selectIndicatorSq ; //~ selectIndicator.localScale*=GridManager.GetNodeSize(); //~ if(GridManager.IsHexGrid()) selectIndicatorSq.gameObject.SetActive(false); //~ if(GridManager.IsSquareGrid()) selectIndicatorHex.gameObject.SetActive(false); } public void Start(){ if(!Application.isPlaying && instance==null) instance=this; } public void NewFactionDeployment(){ deployingUnitIdx=0; int deployFacID=instance.factionList[deployingFacIdx].factionID; List deploymentNodeList=GridManager.GetDeploymentNode(deployFacID); GridIndicator.ShowDeployment(deploymentNodeList); //~ List addOnList=new List(); //~ for(int i=0; i neighbours=deploymentNodeList[i].GetNeighbourList(true); //~ for(int n=0; n deploymentNodeList=GridManager.GetDeploymentNode(instance.factionList[instance.deployingFacIdx].factionID); for(int i=0; i0; } public static bool DeployUnit(Node node, int idx=0){ return instance._DeployUnit(node, idx); } public bool _DeployUnit(Node node, int idx=0){ if(node.deployFacID!=factionList[deployingFacIdx].factionID) return false; if(node.unit!=null){ if(node.unit.GetFacID()!=deployingFacIdx) return false; factionList[deployingFacIdx].unitList.Remove(node.unit); factionList[deployingFacIdx].deployingList.Add(node.unit); node.unit.transform.position=new Vector3(0, 99999, 0); node.unit=null; //PrevUnitToDeploy(); } else{ if(!node.walkable || node.obstacleT!=null) return false; if(factionList[deployingFacIdx].deployingList.Count==0) return false; node.unit=factionList[deployingFacIdx].deployingList[idx]; node.unit.transform.position=node.GetPos(); if(!Unit.enableRotation) node.unit.transform.rotation=Quaternion.identity; else node.unit.transform.rotation=Quaternion.Euler(0, factionList[deployingFacIdx].direction, 0); node.unit.node=node; factionList[deployingFacIdx].unitList.Add(node.unit); factionList[deployingFacIdx].deployingList.RemoveAt(idx); if(factionList[deployingFacIdx].unitList.Count<=1) deployingUnitIdx=0; } return true; } public static int EndDeployment(){ GridIndicator.HideDeployment(); instance.deployingFacIdx=instance._RequireManualDeployment(instance.deployingFacIdx+1); if(instance.deployingFacIdx>=0) instance.NewFactionDeployment(); return instance.deployingFacIdx; } public static bool RequireManualDeployment(){ return instance._RequireManualDeployment()>=0; } public int _RequireManualDeployment(int offset=0){ if(!GameControl.EnableUnitDeployment()) return -1; //if(unitDeployed) return -1; for(int i=0+offset; i0) return i; } return -1; } public int deployingFacIdx=-1; public int deployingUnitIdx=-1; public static bool DeployingUnit(){ return instance.deployingFacIdx>=0; } public static int GetDeployingFacIdx(){ return instance.deployingFacIdx; } public static int GetDeployingUnitIdx(){ return instance.deployingUnitIdx; } public static void SetDeployingUnitIdx(int idx){ instance.deployingUnitIdx=idx; } //~ public static void NextUnitToDeploy(){ //~ instance.deployingUnitIdx+=1; //~ if(instance.deployingUnitIdx>=instance.factionList[deployingFacIdx].deployingList.Count) instance.deployingUnitIdx=0; //~ } //~ public static void PrevUnitToDeploy(){ //~ instance.deployingUnitIdx-=1; //~ if(instance.deployingUnitIdx<0) instance.deployingUnitIdx=instance.factionList[deployingFacIdx].deployingList.Count-1; //~ } //private bool unitDeployed=false; //public static bool UnitDeployed(){ return instance.unitDeployed; } public void DeployAllUnit(){ //unitDeployed=true; for(int i=0; i=instance.allUnitList.Count; } else if(TurnControl.IsFactionPerTurn()){ return turnIdx>=instance.factionList.Count; } return false; } public static void EndTurn_UnitPerTurn(int turnIdx){ //if(turnIdx>=instance.allUnitList.Count) turnIdx=0; if(instance.allUnitList[turnIdx]==null || instance.allUnitList[turnIdx].hp<=0){ //in case the unit is destroy by dot or other effect TurnControl.EndTurn(); return; } instance.allUnitList[turnIdx].NewTurn(); if(instance.allUnitList[turnIdx].playableUnit){ TBSelectUnit(instance.allUnitList[turnIdx]); for(int i=0; i=instance.factionList.Count) turnIdx=0; instance.factionList[turnIdx].NewTurn(); if(instance.factionList[turnIdx].playableFaction){ TBSelectUnit(instance.factionList[turnIdx].unitList[0]); TBTK.OnSelectFaction(instance.factionList[turnIdx]); } else{ AI.MoveFaction(instance.factionList[turnIdx]); } //return turnIdx; } //~ private bool aiToMoveNext=false; //~ private unit unitToMoveNext=false; //~ public static Unit NextUnitToMove; //~ public static void MoveAI(int turnIdx){ //~ aiToMoveNext=false; //~ if(TurnControl.IsUnitPerTurn()){ //~ AI.MoveUnit(instance.allUnitList[turnIdx]); //~ } //~ else if(TurnControl.IsFactionPerTurn()){ //~ AI.MoveFaction(instance.factionList[turnIdx]); //~ } //~ } //to iterate unit ability and effect CD public static IEnumerator EndTurn_IterateCD(){ for(int i=0; i=TurnControl.GetUnitLimit()) TBSelectUnit(instance.selectedUnit); else TBSelectUnit(instance.factionList[instance.currentFacID].GetNextUnitInTurn()); } } public static void TBSelectUnit(Unit unit){ instance._SelectUnit(unit); } //by non UI-user event public static void SelectUnit(Unit unit){ if(!TurnControl.CanSwitchUnit(unit)) return; instance._SelectUnit(unit); } public void _SelectUnit(Unit unit){ selectedUnit=unit; if(unit!=null && unit.playableUnit){ //selectIndicator.position=selectedUnit.GetPos(); currentFacID=instance.selectedUnit.GetFacID(); factionList[currentFacID].UpdateTurnIdx(selectedUnit); GridManager.SelectUnit(unit); GridIndicator.SetSelect(unit.node); GridIndicator.ShowMovable(GridManager.GetWalkableList()); GridIndicator.ShowHostile(GridManager.GetAttackableList()); selectedUnit.AudioPlaySelect(); } else{ GridIndicator.HideAll(); GridIndicator.SetSelect(null); //else selectIndicator.position=new Vector3(0, 9999, 0); } TBTK.OnSelectUnit(unit); } public static List SortUnitListByPriority(List list){ List newList=new List(); while(list.Count>0){ int highestIdx=0; float highestVal=0; for(int i=0; ihighestVal || turnPriority==highestVal && Random.value<0.5f){ highestVal=turnPriority; highestIdx=i; } } newList.Add(list[highestIdx]); list.RemoveAt(highestIdx); } return newList; } private IEnumerator SelectedUnitDestroyed(){ while(GameControl.ActionInProgress() || AI.ActionInProgress()) yield return null; if(TurnControl.IsFactionPerTurn()) SelectNextUnit(); else if(TurnControl.IsUnitPerTurn()) GameControl.EndTurn(); } public static void UnitDestroyed(Unit unit){ instance._UnitDestroyed(unit); } public void _UnitDestroyed(Unit unit){ if(selectedUnit==unit){ StartCoroutine(SelectedUnitDestroyed()); //~ Debug.Log("selected unit is destroyed"); //~ if(TurnControl.IsFactionPerTurn()) SelectNextUnit(); //~ else if(TurnControl.IsUnitPerTurn()) GameControl.EndTurn(); //if(TurnControl.IsUnitPerTurn()) } if(TurnControl.IsUnitPerTurn()){ if(allUnitList.IndexOf(unit)<=TurnControl.GetTurn()) TurnControl.RevertTurn(); allUnitList.Remove(unit); } TBTK.OnUnitDestroyed(unit); bool factionCleared=factionList[unit.GetBaseFacID()].RemoveUnit(unit); if(unit.tempFacID>=0) factionCleared|=factionList[unit.tempFacID].RemoveUnit(unit); if(!factionCleared) return; int facWithUnitCount=0; int facIdxWithUnit=-1; for(int i=0; i0){ facIdxWithUnit=i; facWithUnitCount+=1; } } if(facWithUnitCount<=1) GameControl.GameOver(factionList[facIdxWithUnit]); } public static void GameOver(){ for(int i=0; i GetAllHostileUnits(int facID){ List list=new List(); for(int i=0; i GetAllUnits(){ if(TurnControl.IsUnitPerTurn()) return instance.allUnitList; List list=new List(); for(int i=0; iunit.GetTurnPriority()) continue; instance.allUnitList.Insert(i, unit); break; } if(GetSelectedUnit().GetTurnPriority() unitPIDList){ foreach(Faction fac in instance.factionList){ if(!fac.playableFaction) continue; foreach(Unit unit in fac.unitList){ if(unitPIDList!=null && !unitPIDList.Contains(unit.prefabID)) continue; unit.AddAbility(abilityPID); } } } public static void AddFacSwitchUnit(Unit unit){ for(int i=0; i(); unit.node=node; node.unit=unit; return unit; } //for gizmo public static Color GetFacColor(int idx){ if(instance==null) instance=(UnitManager)FindObjectOfType(typeof(UnitManager)); return idx cachedFactionList=new List(); public static void ClearCache(){ cachedFactionList.Clear(); } public static void CacheFaction(int factionID, List unitList, bool postBattle=false){ List unitInfoList=new List(); for(int i=0; i=0){ cachedFactionList[index].unitList=unitList; cachedFactionList[index].cachedUnitInfoList=unitInfoList; } else{ Faction fac=new Faction(); fac.factionID=factionID; fac.unitList=unitList; fac.cachedUnitInfoList=unitInfoList; cachedFactionList.Add(fac); } } public static int CheckCachedFaction(int factionID){ for(int i=0; i GetCachedUnitList(int index){ return ((index>=0 && cachedFactionList.Count>index) ? cachedFactionList[index].unitList : new List() ); } public static List GetCachedUnitInfoList(int index){ return ((index>=0 && cachedFactionList.Count>index) ? cachedFactionList[index].cachedUnitInfoList : new List() ); } } public class CachedUnitInfo{ //public float hp; public CachedUnitInfo(Unit unit){ //hp=unit.hp; } } [System.Serializable] public class Faction{ //[HideInInspector] public int factionID=0; [HideInInspector] public int factionIdx=-1; public string name="Faction"; public Color color; //not used in runtime public float direction; public int turnIdx; //indicate which unit in the faction is being selected right now, used in FactionPerTurn only public void UpdateTurnIdx(Unit unit){ turnIdx=unitList.IndexOf(unit); } [HideInInspector] public int movedUnitCount=0; //not in used public bool playableFaction=true; public List unitList=new List(); public List cachedUnitInfoList=new List(); public List startingUnitList=new List(); public List deployingList=new List(); public List spawnGroupList=new List(); public bool loadFromData; public bool saveToData; public bool saveLoadedUnitOnly; //public int cachedFacID=0; //the factionID as assigned in editor [HideInInspector] //for grid regeneration public List deploymentPointList=new List(); public void CacheUnit_PostGame(){ //called by the faction instance in a game when the game is over if(!saveToData) return; if(!saveLoadedUnitOnly){ UnitManager.CacheFaction(factionID, unitList, false); return; } List newList=new List(); for(int i=0; i=0){ startingUnitList=UnitManager.GetCachedUnitList(index); cachedUnitInfoList=UnitManager.GetCachedUnitInfoList(index); loadedFromCache=true; } } for(int i=0; i()); if(loadedFromCache){ deployingList[deployingList.Count-1].loadedFromCache=true; //deployingList[deployingList.Count-1].hp=cachedUnitInfoList[i].hp; } unitObj.transform.parent=UnitManager.GetInstance().transform; } for(int i=0; i{ 0, 1 }; for(int i=0; i nodeList=GridManager.GetDeploymentNode(factionID); int count=deployingList.Count; for(int i=0; i abilityIDList=new List(); public List abilityList=new List(); //runtime attribute public Ability GetAbility(int idx){ return abilityList[idx]; } public Ability._AbilityStatus SelectAbility(int idx){ Ability._AbilityStatus abilityStatus=abilityList[idx].IsAvailable(); if(abilityStatus!=Ability._AbilityStatus.Ready) return abilityStatus; //~ int usable=abilityList[idx].IsAvailable(); //~ if(usable!=0) return usable; if(!abilityList[idx].requireTarget){ UseAbility(idx, null); } else{ AbilityManager.AbilityTargetModeFac(this, abilityList[idx]); } return 0; } public void UseAbility(int idx, Node target){ GameControl.FactionUseAbility(this, abilityList[idx], target); //StartCoroutine(_UseAbility(abilityList[idx], target)); } public IEnumerator UseAbilityRoutine(Ability ability, Node target){ Debug.Log("UseAbilityRoutine "+target); ability.Activate(); //ap-=ability.apCost; //~ yield return CRoutine.Get().StartCoroutine(AbilityHit(ability, target)); yield return CRoutine.Get().StartCoroutine(ability.HitTarget(target)); } //~ public IEnumerator AbilityHit(Ability ability, Node target){ //~ ability.HitTarget(target); //~ } } [System.Serializable] public class SpawnGroup{ public int ID; public int countMin=5; public int countMax=5; public List unitList=new List(); public List unitCountMinList=new List(); public List unitCountMaxList=new List(); [HideInInspector] //for grid regeneration public List spawnPointList=new List(); public void Spawn(Faction fac){ //use a dummy list so the original list wont get altered if this is run in EditMode List cloneUnitList=new List( unitList ); List cloneMinList=new List( unitCountMinList ); List cloneMaxList=new List( unitCountMaxList ); List spawnedUnitList=new List(); List nodeList=GridManager.GetSpawnGroup(fac.factionID, ID); int limit=(int)Mathf.Min(nodeList.Count, Rand.Range(countMin, countMax)); int currentCount=0; //loop through the unitlist, place the limited amount of them while(nodeList.Count>0 && currentCount0 && cloneUnitList.Count>0){ int unitIdx=Rand.Range(0, cloneUnitList.Count); int nodeIdx=Rand.Range(0, nodeList.Count); spawnedUnitList.Add(UnitManager.PlaceUnit(cloneUnitList[unitIdx].gameObject, nodeList[nodeIdx], fac.direction)); nodeList.RemoveAt(nodeIdx); currentCount+=1; cloneMaxList[unitIdx]-=1; if(cloneMaxList[unitIdx]<=0){ cloneUnitList.RemoveAt(unitIdx); cloneMaxList.RemoveAt(unitIdx); continue; } } for(int i=0; i