//~ [HideInInspector] public int totalUnitCount=0;
		//~ [HideInInspector] public bool spawned=false;
		
		public SubWave Clone(){
			SubWave subWave=new SubWave();
			subWave.unit=unit;
			subWave.count=count;
			subWave.interval=interval;
			subWave.delay=delay;
			subWave.path=path;
			return subWave;
		}
		public SubWave Clone(){
			SubWave subWave=new SubWave();
			subWave.unit=unit;
			subWave.count=count;
			subWave.interval=interval;
			subWave.delay=delay;
			subWave.path=path;
			subWave.overrideHP=overrideHP;
			subWave.overrideShield=overrideShield;
			subWave.overrideMoveSpd=overrideMoveSpd;
			subWave.overrideLifeCost=overrideLifeCost;
			subWave.overrideScoreCost=overrideScoreCost;
			//subWave.overrideValue=overrideValue;
			subWave.overrideValueMin=new List<int>(overrideValueMin);
			subWave.overrideValueMax=new List<int>(overrideValueMax);
			return subWave;
		}
Esempio n. 3
0
        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();
                }
            }
        }
Esempio n. 4
0
        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;
        }
        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);
        }