public Wave Clone(){
			Wave wave=new Wave();
			wave.duration=duration;
			wave.scoreGain=scoreGain;
			
			for(int i=0; i<subWaveList.Count; i++) wave.subWaveList.Add(subWaveList[i].Clone());
			for(int i=0; i<rscGainList.Count; i++) wave.rscGainList.Add(rscGainList[i]);
			
			return wave;
		}
        IEnumerator SpawnSubWave(SubWave subWave, Wave parentWave)
        {
            yield return new WaitForSeconds(subWave.delay);

            PathTD path=defaultPath;
            if(subWave.path!=null) path=subWave.path;

            Vector3 pos=path.GetSpawnPoint().position;
            Quaternion rot=path.GetSpawnPoint().rotation;

            int spawnCount=0;

            while(spawnCount<subWave.count){
                GameObject obj=ObjectPoolManager.Spawn(subWave.unit, pos, rot);
                //GameObject obj=(GameObject)Instantiate(subWave.unit, pos, rot);
                UnitCreep unit=obj.GetComponent<UnitCreep>();

                if(subWave.overrideHP>0) unit.defaultHP=subWave.overrideHP;
                if(subWave.overrideShield>0) unit.defaultShield=subWave.overrideShield;
                if(subWave.overrideMoveSpd>0) unit.moveSpeed=subWave.overrideMoveSpd;

                unit.Init(path, totalSpawnCount, parentWave.waveID);

                totalSpawnCount+=1;
                activeUnitCount+=1;

                parentWave.activeUnitCount+=1;

                spawnCount+=1;
                if(spawnCount==subWave.count) break;

                yield return new WaitForSeconds(subWave.interval);
            }

            parentWave.subWaveSpawnedCount+=1;
            if(parentWave.subWaveSpawnedCount==parentWave.subWaveList.Count){
                parentWave.spawned=true;
                spawning=false;
                Debug.Log("wave "+(parentWave.waveID+1)+" has done spawning");

                yield return new WaitForSeconds(0.5f);

                if(currentWaveID<=waveList.Count-2){
                    //for UI to show spawn button again
                    if(spawnMode==_SpawnMode.Continous && allowSkip && onEnableSpawnE!=null) onEnableSpawnE();
                    if(spawnMode==_SpawnMode.WaveCleared && allowSkip && onEnableSpawnE!=null) onEnableSpawnE();
                }
            }
        }
		void PreviewSubWave(Wave wave, float startX, float startY, float spaceX, float width, float spaceY, float height){
			startY-=5;
			for(int i=0; i<wave.subWaveList.Count; i++){
				SubWave subWave=wave.subWaveList[i];
				startX+=70;
				
				int unitID=-1;
				for(int n=0; n<creepList.Count; n++){ if(subWave.unit==creepList[n].gameObject) unitID=n;	}
				
				if(unitID>=0 && creepList[unitID].iconSprite!=null){
					//cont=new GUIContent(creepList[unitID].icon);
					//EditorGUI.LabelField(new Rect(startX, startY, 30, 30), cont);
					EditorUtilities.DrawSprite(new Rect(startX, startY, 30, 30), creepList[unitID].iconSprite, false, false);
					EditorGUI.LabelField(new Rect(startX+33, startY+7, 30, 30), "x"+subWave.count);
				}
			}
		}
		Vector2 SubWaveConfigurator(Wave wave, float startX, float startY, float spaceX, float width, float spaceY, float height){
			float cachedY=startY;
			
			startX+=5;
			
			float width2=width*.6f;
			
			for(int i=0; i<wave.subWaveList.Count; i++){
				SubWave subWave=wave.subWaveList[i];
				
				float cachedX=startX;
				
				GUI.Box(new Rect(startX-5, startY+spaceY-5, spaceX+width2+10, 8*spaceY+47), "");
				
				int unitID=-1;
				for(int n=0; n<creepList.Count; n++){ if(subWave.unit==creepList[n].gameObject) unitID=n;	}
			
				Sprite icon=unitID==-1 ? null : creepList[unitID].iconSprite;
				EditorUtilities.DrawSprite(new Rect(startX, startY+spaceY, 30, 30), icon);
				
				cont=new GUIContent("Creep Prefab:", "The creep prefab to be spawned");
				EditorGUI.LabelField(new Rect(startX+32, startY+=spaceY-2, width, height), cont);
				unitID=EditorGUI.Popup(new Rect(startX+32, startY+=spaceY-5, width+20, height), unitID, creepNameList);
				if(unitID>=0) subWave.unit=creepList[unitID].gameObject;
				
				//subWave.unit=DrawCreepSelect(startX, startY+=spaceY, subWave.unit); startY+=14;
				
				
				startX=cachedX;
				
								cont=new GUIContent("Number of Unit:", "Number of unit to be spawned");
								EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
								subWave.count=EditorGUI.IntField(new Rect(startX+spaceX, startY, width2, height), subWave.count);
				
								cont=new GUIContent("Start Delay:", "Time delay before the first creep of this subwave start spawn");
								EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
								subWave.delay=EditorGUI.FloatField(new Rect(startX+spaceX, startY, width2, height), subWave.delay);
								
								cont=new GUIContent("Spawn Interval:", "The time interval in second between each single individual spawned");
								EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
								subWave.interval=EditorGUI.FloatField(new Rect(startX+spaceX, startY, width2, height), subWave.interval);
								
								cont=new GUIContent("Alternate Path:", "The path to use for this subwave, if it's different from the default path. Optional and can be left blank");
								EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
								subWave.path=(PathTD)EditorGUI.ObjectField(new Rect(startX+spaceX, startY, width2, height), subWave.path, typeof(PathTD), true);
				
				
				EditorGUI.LabelField(new Rect(startX, startY+=spaceY+5, width, height), "Override:");
				
						GUI.color=new Color(.5f, .5f, .5f, 1f);
						if(subWave.overrideHP>=0) GUI.color=Color.white;
				
								cont=new GUIContent(" - HP:", "Override the value of default HP set in CreepEditor. Only valid if value is set to >0");
								EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
								subWave.overrideHP=EditorGUI.FloatField(new Rect(startX+spaceX, startY, width2, height), subWave.overrideHP);
								
						GUI.color=new Color(.5f, .5f, .5f, 1f);
						if(subWave.overrideShield>=0) GUI.color=Color.white;
								
								cont=new GUIContent(" - Shield:", "Override the value of default shield set in CreepEditor. Only valid if value is set to >0");
								EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
								subWave.overrideShield=EditorGUI.FloatField(new Rect(startX+spaceX, startY, width2, height), subWave.overrideShield);
								
						GUI.color=new Color(.5f, .5f, .5f, 1f);
						if(subWave.overrideMoveSpd>=0) GUI.color=Color.white;
								
								cont=new GUIContent(" - Move Speed:", "Override the value of default MoveSpeed set in CreepEditor. Only valid if value is set to >0");
								EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
								subWave.overrideMoveSpd=EditorGUI.FloatField(new Rect(startX+spaceX, startY, width2, height), subWave.overrideMoveSpd);
								
				GUI.color=Color.white;
							
				
				if(i<wave.subWaveList.Count-1) startY=cachedY;
				startX+=spaceX+width*0.85f;
				
				if(contentWidth<startX) contentWidth=startX;
			}
			return new Vector2(startX, startY+3);
		}
        public Wave Generate(int waveID)
        {
            if(pathList.Count==0){
                Debug.Log("no path at all");
                return null;
            }

            Wave wave=new Wave();
            wave.waveID=waveID;

            waveID+=1;

            int _subWaveCount=Mathf.Max(1, (int)subWaveCount.GetValueAtWave(waveID));
            int totalUnitCount=(int)unitCount.GetValueAtWave(waveID);

            _subWaveCount=Mathf.Min(totalUnitCount, _subWaveCount);

            //filter thru all the units, only use the one that meets the wave requirement (>minWave)
            List<ProceduralUnitSetting> availableUnitList=new List<ProceduralUnitSetting>();
            int nearestAvailableID=0; 	float currentNearestValue=Mathf.Infinity;
            for(int i=0; i<unitSettingList.Count; i++){
                if(unitSettingList[i].minWave<=waveID) availableUnitList.Add(unitSettingList[i]);
                //while we are at it, check which unit has the lowest wave requirement, just in case
                if(availableUnitList.Count==0 && unitSettingList[i].minWave<currentNearestValue){
                    currentNearestValue=unitSettingList[i].minWave;
                    nearestAvailableID=i;
                }
            }
            //if no unit available, simply uses the one with lowest requirement
            if(availableUnitList.Count==0) availableUnitList.Add(unitSettingList[nearestAvailableID]);

            //we are going to just iterate thru the pathlist and assign them to each subwave.
            //So here we introduce an offset so it doesnt always start from the first path in the list
            int startingPathID=Random.Range(0, pathList.Count);

            for(int i=0; i<_subWaveCount; i++){
                SubWave subWave=new SubWave();

                int unitID=Random.Range(0, availableUnitList.Count);
                ProceduralUnitSetting unitSetting=availableUnitList[unitID];

                subWave.unit=unitSetting.unit.gameObject;

                subWave.overrideHP=unitSetting.HP.GetValueAtWave(waveID);
                subWave.overrideShield=unitSetting.shield.GetValueAtWave(waveID);
                subWave.overrideMoveSpd=unitSetting.speed.GetValueAtWave(waveID);

                //limit the minimum interval to 0.25f
                subWave.interval=Mathf.Max(0.25f, unitSetting.interval.GetValueAtWave(waveID));

                //iterate through the path, randomly skip one
                int pathID=startingPathID+(Random.Range(0f, 1f)>0.75f ? 1 : 0);
                while(pathID>=pathList.Count) pathID-=pathList.Count;
                subWave.path=pathList[pathID];

                subWave.delay=i*Random.Range(2f, 3f);

                wave.subWaveList.Add(subWave);
            }

            //fill up the unit count
            int remainingUnitCount=totalUnitCount;
            while(remainingUnitCount>0){
                for(int i=0; i<_subWaveCount; i++){
                    if(wave.subWaveList[i].count==0){
                        wave.subWaveList[i].count=1;
                        remainingUnitCount-=1;
                    }
                    else{
                        int rand=Random.Range(0, 3);
                        rand=Mathf.Min(rand, remainingUnitCount);
                        wave.subWaveList[i].count+=rand;
                        remainingUnitCount-=rand;
                    }
                }
            }

            wave.duration=wave.CalculateSpawnDuration();

            //get the slowest moving unit and the longest path so we know which subwave is going to take the longest to finish
            float longestDuration=0;
            for(int i=0; i<_subWaveCount; i++){
                float pathDist=wave.subWaveList[i].path.GetPathDistance();
                float moveSpeed=wave.subWaveList[i].overrideMoveSpd;
                float duration=pathDist/moveSpeed;
                if(duration>longestDuration) longestDuration=duration;
            }
            //add the longest to the existing duration
            wave.duration+=longestDuration*Random.Range(0.5f, 0.8f);

            for(int i=0; i<rscSettingList.Count; i++){
                wave.rscGainList.Add((int)rscSettingList[i].GetValueAtWave(waveID));
            }

            return wave;
        }
Beispiel #6
0
        public void UpdateWavePath(Wave oldWave)
        {
            if (pathList.Count == 0)
              {
            Debug.Log("no path at all");
            return;
              }

              int startingPathID = Random.Range(0, pathList.Count);

              for (int i = 0; i < oldWave.subWaveList.Count; i++)
              {
            //iterate through the path, randomly skip one
            int pathID = startingPathID + (Random.Range(0f, 1f) > 0.75f ? 1 : 0);
            while (pathID >= pathList.Count) pathID -= pathList.Count;
            oldWave.subWaveList[i].path = pathList[pathID];
              }
        }
Beispiel #7
0
        IEnumerator SpawnSubWave(SubWave subWave, Wave parentWave)
        {
            if (subWave.unit == null)
            {
                Debug.LogWarning("No creep prefab has been assigned to sub-wave", this);
                yield break;
            }

            yield return(new WaitForSeconds(subWave.delay));

            PathTD path = defaultPath;

            if (subWave.path != null)
            {
                path = subWave.path;
            }

            Vector3    pos = path.GetSpawnPoint();
            Quaternion rot = path.GetSpawnDirection();

            int spawnCount = 0;

            if (subWave.unitC == null)
            {
                subWave.unitC = subWave.unit.GetComponent <UnitCreep>();
            }

            while (spawnCount < subWave.count)
            {
                if (subWave.unit == null)
                {
                    Debug.LogWarning("no creep has been assigned to subwave", this);
                    break;
                }

                GameObject obj  = ObjectPoolManager.Spawn(subWave.unit, pos, rot);
                UnitCreep  unit = obj.GetComponent <UnitCreep>();

                if (subWave.overrideHP > 0)
                {
                    unit.defaultHP = subWave.overrideHP;
                }
                else
                {
                    unit.defaultHP = subWave.unitC.defaultHP;
                }

                if (subWave.overrideShield > 0)
                {
                    unit.defaultShield = subWave.overrideShield;
                }
                else
                {
                    unit.defaultShield = subWave.unitC.defaultShield;
                }

                if (subWave.overrideMoveSpd > 0)
                {
                    unit.moveSpeed = subWave.overrideMoveSpd;
                }
                else
                {
                    unit.moveSpeed = subWave.unitC.moveSpeed;
                }

                unit.Init(path, totalSpawnCount, parentWave.waveID);

                totalSpawnCount += 1;
                activeUnitCount += 1;

                parentWave.activeUnitCount += 1;

                spawnCount += 1;
                if (spawnCount == subWave.count)
                {
                    break;
                }

                yield return(new WaitForSeconds(subWave.interval));
            }

            parentWave.subWaveSpawnedCount += 1;
            if (parentWave.subWaveSpawnedCount == parentWave.subWaveList.Count)
            {
                parentWave.spawned = true;
                spawning           = false;
                Debug.Log("wave " + (parentWave.waveID + 1) + " has done spawning");

                yield return(new WaitForSeconds(0.5f));

                if (currentWaveID <= waveList.Count - 2 || spawnLimit == _SpawnLimit.Infinite)
                {
                    if ((spawnMode == _SpawnMode.WaveCleared || spawnMode == _SpawnMode.Continous) && allowSkip)
                    {
                        TDTK.OnEnableSpawn();
                    }
                }
            }
        }
Beispiel #8
0
        void OnUnitCleared(UnitCreep creep)
        {
            if (GameControl.IsGameOver())
            {
                return;
            }

            int waveID = creep.waveID;

            activeUnitCount -= 1;

            Wave wave = null;

            if (spawnLimit == _SpawnLimit.Finite)
            {
                wave = waveList[waveID];
            }
            else if (spawnLimit == _SpawnLimit.Infinite)
            {
                for (int i = 0; i < waveList.Count; i++)
                {
                    if (waveList[i].waveID == waveID)
                    {
                        wave = waveList[i];
                        break;
                    }
                }

                if (wave == null)
                {
                    Debug.Log("error!");
                    return;
                }
            }


            wave.activeUnitCount -= 1;
            if (wave.spawned && wave.activeUnitCount == 0)
            {
                wave.cleared      = true;
                waveClearedCount += 1;

                TDTK.OnWaveCleared(waveID);
                Debug.Log("wave" + (waveID + 1) + " is cleared");

                ResourceManager.GainResource(wave.rscGainList, PerkManager.GetRscWaveCleared());
                GameControl.GainLife(wave.lifeGain + PerkManager.GetLifeWaveClearedModifier());
                AbilityManager.GainEnergy(wave.energyGain + (int)PerkManager.GetEnergyWaveClearedModifier());

                if (spawnLimit == _SpawnLimit.Infinite)
                {
                    waveList.Remove(wave);
                }

                if (IsAllWaveCleared())
                {
                    GameControl.GameOver(true);                         //pass true to signify level won
                }
                else
                {
                    if (spawnMode == _SpawnMode.Round)
                    {
                        TDTK.OnEnableSpawn();                                                // && onEnableSpawnE!=null) onEnableSpawnE();
                    }
                }
            }


            if (!IsAllWaveCleared() && activeUnitCount == 0 && !spawning)
            {
                if (spawnMode == _SpawnMode.WaveCleared)
                {
                    SpawnWaveFinite();
                }
            }
        }
Beispiel #9
0
        private float DrawSubWave(float startX, float startY, Wave wave)
        {
            float cachedY = startY;   spaceX -= 20;

            for (int i = 0; i < wave.subWaveList.Count; i++)
            {
                SubWave subWave = wave.subWaveList[i];

                startY = cachedY;

                GUI.Box(new Rect(startX, startY, subWaveBoxWidth, subWaveBoxHeight), "");

                startX += 5; startY += 5;

                if (subWave.unit != null && subWave.unitC == null)
                {
                    subWave.unitC = subWave.unit.GetComponent <UnitCreep>();
                }
                if (subWave.unitC != null && subWave.unit != subWave.unitC.gameObject)
                {
                    subWave.unit = subWave.unitC.gameObject;
                }

                Sprite icon = subWave.unitC == null ? null : subWave.unitC.iconSprite;
                TDEditor.DrawSprite(new Rect(startX, startY, 30, 30), icon);

                int index = subWave.unitC != null?TDEditor.GetCreepIndex(subWave.unitC.prefabID) : 0;

                cont = new GUIContent("Creep Prefab:", "The creep prefab to be spawned");
                EditorGUI.LabelField(new Rect(startX + 32, startY, width, height), cont);
                index = EditorGUI.Popup(new Rect(startX + 32, startY + spaceY - 4, width, height), index, creepLabel);
                if (index > 0)
                {
                    subWave.unitC = creepDB.creepList[index - 1];
                }
                else
                {
                    subWave.unitC = null;
                }

                startY += 35;

                cont = new GUIContent("Number of Unit:", "Number of unit to be spawned");
                EditorGUI.LabelField(new Rect(startX, startY, width, height), cont);
                subWave.count = EditorGUI.IntField(new Rect(startX + spaceX, startY, widthS, height), subWave.count);

                cont = new GUIContent("Start Delay:", "Time delay before the first creep of this subwave start spawn");
                EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont);
                subWave.delay = EditorGUI.FloatField(new Rect(startX + spaceX, startY, widthS, height), subWave.delay);

                cont = new GUIContent("Spawn Interval:", "The time interval in second between each single individual spawned");
                EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont);
                subWave.interval = EditorGUI.FloatField(new Rect(startX + spaceX, startY, widthS, height), subWave.interval);

                cont = new GUIContent("Alternate Path:", "The path to use for this subwave, if it's different from the default path. Optional and can be left blank");
                EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont);
                subWave.path = (PathTD)EditorGUI.ObjectField(new Rect(startX + spaceX, startY, widthS + 40, height), subWave.path, typeof(PathTD), true);

                startY += 5;

                EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), "Override:");

                GUI.color = subWave.overrideHP >= 0 ? Color.white : Color.grey;
                cont      = new GUIContent(" - HP:", "Override the value of default HP set in CreepEditor. Only valid if value is set to >0");
                EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont);
                subWave.overrideHP = EditorGUI.FloatField(new Rect(startX + spaceX, startY, widthS, height), subWave.overrideHP);

                GUI.color = subWave.overrideShield >= 0 ? Color.white : Color.grey;
                cont      = new GUIContent(" - Shield:", "Override the value of default shield set in CreepEditor. Only valid if value is set to >0");
                EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont);
                subWave.overrideShield = EditorGUI.FloatField(new Rect(startX + spaceX, startY, widthS, height), subWave.overrideShield);

                GUI.color = subWave.overrideMoveSpd >= 0 ? Color.white : Color.grey;
                cont      = new GUIContent(" - Move Speed:", "Override the value of default MoveSpeed set in CreepEditor. Only valid if value is set to >0");
                EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont);
                subWave.overrideMoveSpd = EditorGUI.FloatField(new Rect(startX + spaceX, startY, widthS, height), subWave.overrideMoveSpd);

                GUI.color = Color.white;

                startX += subWaveBoxWidth + 10;

                subWaveBoxHeight = startY + spaceY + 5 - cachedY;
            }

            spaceX += 20;

            return(cachedY + subWaveBoxHeight);
        }
Beispiel #10
0
        private float DrawSpawnInfo(float startX, float startY)
        {
            maxSubWaveSize = 1;

            while (waveFoldList.Count < instance.waveList.Count)
            {
                waveFoldList.Add(true);
            }
            while (waveFoldList.Count > instance.waveList.Count)
            {
                waveFoldList.RemoveAt(waveFoldList.Count - 1);
            }

            startY += 5;

            for (int i = 0; i < instance.waveList.Count; i++)
            {
                Wave wave = instance.waveList[i];

                if (deleteID == i)
                {
                    if (GUI.Button(new Rect(startX, startY, 60, 20), "Cancel"))
                    {
                        deleteID = -1;
                    }

                    GUI.color = Color.red;
                    if (GUI.Button(new Rect(startX + 65, startY, 20, 20), "X"))
                    {
                        instance.waveList.RemoveAt(i);  i -= 1;
                        deleteID = -1;
                    }
                    GUI.color = Color.white;
                }
                else
                {
                    cont = new GUIContent("X", "Delete wave");
                    if (GUI.Button(new Rect(startX, startY, 20, 20), cont))
                    {
                        deleteID = i;
                    }
                }


                float offsetX = deleteID == i ? 60 : 0;
                waveFoldList[i] = EditorGUI.Foldout(new Rect(startX + 25 + offsetX, startY + 3, width, height), waveFoldList[i], "wave " + i, foldoutStyle);
                if (!waveFoldList[i])                   //preview
                {
                    DrawSubWavePreview(startX + 120, startY - 5, wave);
                }
                else                                                            //details
                {
                    startX += 25;     startY += 3;

                    cont = new GUIContent("SubWave Size: " + wave.subWaveList.Count, "Number of sub waves in the level");
                    EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont);
                    if (GUI.Button(new Rect(startX + spaceX, startY, widthS, height), "-1"))
                    {
                        if (wave.subWaveList.Count > 1)
                        {
                            wave.subWaveList.RemoveAt(wave.subWaveList.Count - 1);
                        }
                    }
                    if (GUI.Button(new Rect(startX + spaceX + 50, startY, widthS, height), "+1"))
                    {
                        wave.subWaveList.Add(new SubWave());
                    }


                    startY = DrawSubWave(startX, startY + spaceY + 5, wave) + 8;


                    cont = new GUIContent("Time To Next Wave: ", "Time until next wave");
                    EditorGUI.LabelField(new Rect(startX, startY, width, height), cont);
                    if (instance.spawnMode == SpawnManager._SpawnMode.Continous)
                    {
                        wave.duration = EditorGUI.FloatField(new Rect(startX + spaceX, startY, widthS, height), wave.duration);
                    }
                    else
                    {
                        EditorGUI.LabelField(new Rect(startX + spaceX, startY, widthS, height), "-");
                    }


                    float reqDuration = wave.CalculateSpawnDuration();
                    EditorGUI.LabelField(new Rect(startX + spaceX + 50, startY, 500, height), "(Time to spawn all units: " + reqDuration.ToString("f1") + "s)");


                    cont = new GUIContent("Resource Gain:", "The amount of resource player will gain when surviving the wave");
                    EditorGUI.LabelField(new Rect(startX, startY += spaceY + 5, width, height), cont);

                    if (wave.rscGainList.Count < rscDB.rscList.Count)
                    {
                        wave.rscGainList.Add(0);
                    }
                    if (wave.rscGainList.Count > rscDB.rscList.Count)
                    {
                        wave.rscGainList.RemoveAt(wave.rscGainList.Count - 1);
                    }

                    float cachedX = startX;   startX += spaceX;
                    for (int n = 0; n < rscDB.rscList.Count; n++)
                    {
                        TDEditor.DrawSprite(new Rect(startX, startY - 2, 20, 20), rscDB.rscList[n].icon);
                        wave.rscGainList[n] = EditorGUI.IntField(new Rect(startX + 20, startY, widthS, height - 2), wave.rscGainList[n]);
                        startX += 75;
                    }
                    startX = cachedX;

                    cont = new GUIContent("Life Gained: ", "The amount of life player will gain when surviving the wave");
                    EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont);
                    wave.lifeGain = EditorGUI.IntField(new Rect(startX + spaceX, startY, widthS, height), wave.lifeGain);

                    cont = new GUIContent("Energy Gained: ", "The amount of energy (for abilities) player will gain when surviving the wave");
                    EditorGUI.LabelField(new Rect(startX, startY += spaceY, width, height), cont);
                    wave.energyGain = EditorGUI.IntField(new Rect(startX + spaceX, startY, widthS, height), wave.energyGain);

                    startX -= 25;
                }

                startY += spaceY * 2;
            }

            return(startY);
        }
        void OnGUI()
        {
            if(window==null) Init();
            if(instance==null){
                EditorGUI.LabelField(new Rect(5, 5, 350, 18), "No SpawnManager in current scene");
                GetSpawnManager();
                return;
            }

            if(creepList.Count!=creepNameList.Length) ResetCreepNameList();

            if(instance.spawnLimit==SpawnManager._SpawnLimit.Finite && !instance.procedurallyGenerateWave){
                if(GUI.Button(new Rect(window.position.width-130, 5, 125, 25), configureAutoGen ? "Wave List" : "Configuration")){
                    configureAutoGen=!configureAutoGen;
                }

                if(!configureAutoGen){
                    GUI.color=new Color(0, 1, 1, 1);
                    cont=new GUIContent("Auto Generate", "Procedurally generate all the waves\nCAUTION: overwirte all existing wave!");
                    if(GUI.Button(new Rect(window.position.width-130, 35, 125, 25), cont)){
                        for(int i=0; i<instance.waveList.Count; i++) instance.waveList[i]=instance.waveGenerator.Generate(i);
                    }
                    GUI.color=Color.white;
                }
            }

            if(GUI.Button(new Rect(window.position.width-130, 90, 125, 25), "Creep Editor")){
                UnitCreepEditorWindow.Init();
            }

            float startX=5;
            float startY=5;

            int spawnMode=(int)instance.spawnMode;
            cont=new GUIContent("Spawn Mode:", "Spawn mode in this level");
            EditorGUI.LabelField(new Rect(startX, startY, width, height), cont);
            cont=new GUIContent("", "");
            contList=new GUIContent[spawnModeLabel.Length];
            for(int i=0; i<contList.Length; i++) contList[i]=new GUIContent(spawnModeLabel[i], spawnModeTooltip[i]);
            spawnMode = EditorGUI.Popup(new Rect(startX+spaceX, startY, width, 15), cont, spawnMode, contList);
            instance.spawnMode=(SpawnManager._SpawnMode)spawnMode;

            if(instance.spawnMode!=SpawnManager._SpawnMode.Round){
                cont=new GUIContent("Allow Skip:", "Allow player to skip ahead and spawn the next wave");
                EditorGUI.LabelField(new Rect(startX+spaceX+width+20, startY, width, height), cont);
                instance.allowSkip=GUI.Toggle(new Rect(startX+spaceX+width+90, startY, 15, 15), instance.allowSkip, "");
            }

            int spawnLimit=(int)instance.spawnLimit;
            cont=new GUIContent("Spawn Count:", "Spawn count in this level. Infinite (endless mode) must use procedural wave generation");
            EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
            cont=new GUIContent("", "");
            contList=new GUIContent[spawnLimitLabel.Length];
            for(int i=0; i<contList.Length; i++) contList[i]=new GUIContent(spawnLimitLabel[i], spawnLimitTooltip[i]);
            spawnLimit = EditorGUI.Popup(new Rect(startX+spaceX, startY, width, 15), cont, spawnLimit, contList);
            instance.spawnLimit=(SpawnManager._SpawnLimit)spawnLimit;

            cont=new GUIContent("Auto Start: ", "Check to have the spawning start on a fixed timer. Rather than waiting for player initiation");
            EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width+50, height), cont);
            instance.autoStart=EditorGUI.Toggle(new Rect(startX+spaceX, startY, width, height), instance.autoStart);

            if(instance.autoStart){
                cont=new GUIContent("Timer: ", "The duration to wait in second before the spawning start");
                EditorGUI.LabelField(new Rect(startX+spaceX+30, startY, width+50, height), cont);
                instance.autoStartDelay=EditorGUI.FloatField(new Rect(startX+spaceX+70, startY, width-70, height), instance.autoStartDelay);
            }

            if(instance.spawnLimit==SpawnManager._SpawnLimit.Finite){
                cont=new GUIContent("Auto Generate", "Check to have the SpawnManager automatically generate the wave in runtime as opposed to using preset data");
                EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width+50, height), cont);
                instance.procedurallyGenerateWave=EditorGUI.Toggle(new Rect(startX+spaceX, startY, width, height), instance.procedurallyGenerateWave);

                cont=new GUIContent("Default Path:", "The primary path to be used. Every creep will follow this path unless an alternate path is specified in a sub-wave");
                EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, height), cont);
                instance.defaultPath=(PathTD)EditorGUI.ObjectField(new Rect(startX+spaceX, startY, width, 15), instance.defaultPath, typeof(PathTD), true);

                cont=new GUIContent("Waves Size: "+instance.waveList.Count, "Number of waves in the level");
                EditorGUI.LabelField(new Rect(startX, startY+=spaceY, width, 15), cont);
                if(GUI.Button(new Rect(startX+spaceX, startY-1, 40, 15), "-1")){
                    if(instance.waveList.Count>1){
                        instance.waveList.RemoveAt(instance.waveList.Count-1);
                        waveFoldList.RemoveAt(waveFoldList.Count-1);
                    }
                }
                if(GUI.Button(new Rect(startX+spaceX+50, startY-1, 40, 15), "+1")){
                    if(instance.waveList.Count>0) instance.waveList.Add(instance.waveList[instance.waveList.Count-1].Clone());
                    else{
                        Wave wave=new Wave();
                        SubWave subWave=new SubWave();
                        wave.subWaveList.Add(subWave);
                        List<Rsc> rscList=EditorDBManager.GetRscList();
                        wave.rscGainList=new List<int>();
                        for(int i=0; i<rscList.Count; i++) wave.rscGainList.Add(0);
                        instance.waveList.Add(wave);
                    }
                    waveFoldList.Add(true);
                }
            }
            else configureAutoGen=false;

            if(instance.spawnLimit==SpawnManager._SpawnLimit.Infinite || configureAutoGen){
                EditorGUI.LabelField(new Rect(startX, startY+30, 400, height), "Procedural Wave Generation Parameters");
                startY+=10;
            }

            startY+=35;
            float waveConfigStartY=startY;

            Rect visibleRect=new Rect(startX, startY, window.position.width-10, window.position.height-startY-5);
            Rect contentRect=new Rect(startX, startY, contentWidth-25, contentHeight);

            contentWidth=0;
                GUI.color=new Color(.8f, .8f, .8f, 1f);
                GUI.Box(visibleRect, "");
                GUI.color=Color.white;

            scrollPos = GUI.BeginScrollView(visibleRect, scrollPos, contentRect);

                startX+=5;
                startY+=10;

                float cachedX=startX;
                Vector2 v2=Vector2.zero;

                if(instance.spawnLimit==SpawnManager._SpawnLimit.Infinite || configureAutoGen || instance.procedurallyGenerateWave){
                    v2=WaveGeneratorSetting(startX+5, startY);
                }
                else{
                    v2=WaveConfigurator(startX, startY);
                }

                startX=cachedX;
                startY=v2.y;

            GUI.EndScrollView();

            contentHeight=startY-waveConfigStartY;

            if(GUI.changed) EditorUtility.SetDirty(instance);
        }
        public Wave Generate(int waveID)
        {
            if (pathList.Count == 0)
            {
                Debug.Log("no path at all");
                return(null);
            }

            Wave wave = new Wave();

            wave.waveID = waveID;

            waveID += 1;

            int _subWaveCount  = Mathf.Max(1, (int)subWaveCount.GetValueAtWave(waveID));
            int totalUnitCount = (int)unitCount.GetValueAtWave(waveID);

            _subWaveCount = Mathf.Min(totalUnitCount, _subWaveCount);

            //filter thru all the units, only use the one that meets the wave requirement (>minWave)
            List <ProceduralUnitSetting> availableUnitList = new List <ProceduralUnitSetting>();
            int nearestAvailableID = 0; float currentNearestValue = Mathf.Infinity;

            for (int i = 0; i < unitSettingList.Count; i++)
            {
                if (!unitSettingList[i].enabled)
                {
                    continue;
                }
                if (unitSettingList[i].minWave <= waveID)
                {
                    availableUnitList.Add(unitSettingList[i]);
                }
                //while we are at it, check which unit has the lowest wave requirement, just in case
                if (availableUnitList.Count == 0 && unitSettingList[i].minWave < currentNearestValue)
                {
                    currentNearestValue = unitSettingList[i].minWave;
                    nearestAvailableID  = i;
                }
            }
            //if no unit available, simply uses the one with lowest requirement
            if (availableUnitList.Count == 0)
            {
                availableUnitList.Add(unitSettingList[nearestAvailableID]);
            }

            //we are going to just iterate thru the pathlist and assign them to each subwave.
            //So here we introduce an offset so it doesnt always start from the first path in the list
            int startingPathID = Random.Range(0, pathList.Count);


            for (int i = 0; i < _subWaveCount; i++)
            {
                SubWave subWave = new SubWave();

                int unitID = Random.Range(0, availableUnitList.Count);
                ProceduralUnitSetting unitSetting = availableUnitList[unitID];

                subWave.unit = unitSetting.unit.gameObject;

                subWave.overrideHP = unitSetting.HP.GetValueAtWave(waveID);

                //limit the minimum interval to 0.25f
                subWave.interval = Mathf.Max(0.25f, unitSetting.interval.GetValueAtWave(waveID));

                //iterate through the path, randomly skip one
                int pathID = startingPathID + (Random.Range(0f, 1f) > 0.75f ? 1 : 0);
                while (pathID >= pathList.Count)
                {
                    pathID -= pathList.Count;
                }
                subWave.path = pathList[pathID];

                subWave.delay = i * Random.Range(2f, 3f);

                wave.subWaveList.Add(subWave);
            }

            //fill up the unit count
            int remainingUnitCount = totalUnitCount;

            while (remainingUnitCount > 0)
            {
                for (int i = 0; i < _subWaveCount; i++)
                {
                    if (wave.subWaveList[i].count == 0)
                    {
                        wave.subWaveList[i].count = 1;
                        remainingUnitCount       -= 1;
                    }
                    else
                    {
                        int rand = Random.Range(0, 3);
                        rand = Mathf.Min(rand, remainingUnitCount);
                        wave.subWaveList[i].count += rand;
                        remainingUnitCount        -= rand;
                    }
                }
            }

            wave.duration = wave.CalculateSpawnDuration();
            wave.rscGain  = (int)rscSetting.GetValueAtWave(waveID);

            return(wave);
        }