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; }
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]; } }
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(); } } } }
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(); } } }
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); }
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); }