using System; using Core.Economy; using Core.Health; using Core.Utilities; using JetBrains.Annotations; using TowerDefense.Economy; using TowerDefense.Towers.Data; using TowerDefense.Towers.Placement; using TowerDefense.UI.HUD; using UnityEngine; namespace TowerDefense.Level { /// /// The level manager - handles the level states and tracks the player's currency /// [RequireComponent(typeof(WaveManager))] public class LevelManager : Singleton { protected static readonly int MAX_TOWER = 5; /// /// The configured level intro. If this is null the LevelManager will fall through to the gameplay state (i.e. SpawningEnemies) /// public LevelIntro intro; /// /// The tower library for this level /// public TowerLibrary towerLibrary; /// /// 怪物重生的特效. /// public GameObject agentRegenPrefab; /// /// The currency that the player starts with /// public int startingCurrency; /// /// 自身所在的PlacementArea和对方所有的PlaceArea. /// public TowerPlacementGrid selfPlacementArea; public TowerPlacementGrid oppoPlacementArea; /// /// The controller for gaining currency /// public CurrencyGainer currencyGainer; /// /// Configuration for if the player gains currency even in pre-build phase /// [Header("Setting this will allow currency gain during the Intro and Pre-Build phase")] public bool alwaysGainCurrency; /// /// The home bases that the player must defend /// public PlayerHomeBase[] homeBases; /// /// 对手盘的HomeBase,如果死亡,则胜利发生. /// public PlayerHomeBase[] opponentHomeBases; public Collider[] environmentColliders; /// /// 全局的JSON数据初始化. /// protected JsonDataInit mJsonData; /// /// The attached wave manager /// public WaveManager waveManager { get; protected set; } /// /// Number of enemies currently in the level /// public int numberOfEnemies { get; protected set; } /// /// The current state of the level /// public LevelState levelState { get; protected set; } /// /// The currency controller /// public Currency currency { get; protected set; } /// /// Number of home bases left /// public int numberOfHomeBasesLeft { get; protected set; } /// /// 对手盘的HomeBase数据. /// public int oppoNumOfHomeBaseLeft { get; protected set; } /// /// Starting number of home bases /// public int numberOfHomeBases { get; protected set; } /// /// 对手盘的homeBase数目 /// public int oppoNumOfHomeBases { get; protected set; } /// /// 每一个Tower对应的AttributeID. /// protected int[] towerAttributeID = new int[5]; protected int[] towerLevel = new int[5]; /// /// An accessor for the home bases /// public PlayerHomeBase[] playerHomeBases { get { return homeBases; } } /// /// 设置每一条兵线对应的AttID /// /// /// public void SetTowerAttID( int waveline,int id,int lvl ) { towerAttributeID[waveline] = id; towerLevel[waveline] = lvl; //if( lvl>=1 ) UpdateWaveSpawn(waveline, id); } public int GetTowerAttID( int waveline) { return towerAttributeID[waveline]; } public int GetTowerLevel( int waveline) { return towerLevel[waveline]; } /// /// 重设当前的Currency数据 /// /// public void ResetCurrency( int curnum) { int curChg = curnum - currency.currentCurrency; currency.AddCurrency(curChg); } /// /// 更新刷怪时间 /// /// /// protected void UpdateWaveSpawn(int gridx, int attid) { OpponentMgr.instance.m_WaveManager.UpdateWaveSpawnTime(gridx, attid); } /// /// If the game is over /// public bool isGameOver { get { return (levelState == LevelState.Win) || (levelState == LevelState.Lose); } } /// /// Fired when all the waves are done and there are no more enemies left /// public event Action levelCompleted; /// /// Fired when all of the home bases are destroyed /// public event Action levelFailed; /// /// Fired when the level state is changed - first parameter is the old state, second parameter is the new state /// public event Action levelStateChanged; /// /// Fired when the number of enemies has changed /// public event Action numberOfEnemiesChanged; /// /// Event for home base being destroyed /// public event Action homeBaseDestroyed; /// /// Increments the number of enemies. Called on Agent spawn /// public virtual void IncrementNumberOfEnemies() { numberOfEnemies++; SafelyCallNumberOfEnemiesChanged(); } /// /// Returns the sum of all HomeBases' health /// public float GetAllHomeBasesHealth() { float health = 0.0f; foreach (PlayerHomeBase homebase in homeBases) { health += homebase.configuration.currentHealth; } return health; } /// /// 开启对应索引的兵线。 /// /// /// public bool startWaveLine(int waveline,bool opponent,int attid ) { if (opponent) { waveManager.startWaveLine(waveline, attid); } else { OpponentMgr.instance.startWaveLine(waveline,attid); } return true; } /// /// 停止某一条兵线的出兵. /// /// public void stopWaveLine( int waveLine,bool opponent ) { if( opponent ) OpponentMgr.instance.stopWaveLine(waveLine); else waveManager.stopWaveLine(waveLine); return; } /// /// Decrements the number of enemies. Called on Agent death /// public virtual void DecrementNumberOfEnemies() { numberOfEnemies--; SafelyCallNumberOfEnemiesChanged(); if (numberOfEnemies < 0) { Debug.LogError("[LEVEL] There should never be a negative number of enemies. Something broke!"); numberOfEnemies = 0; } if (numberOfEnemies == 0 && levelState == LevelState.AllEnemiesSpawned) { ChangeLevelState(LevelState.Win); } } /// /// Completes building phase, setting state to spawn enemies /// public virtual void BuildingCompleted() { ChangeLevelState(LevelState.SpawningEnemies); this.selfPlacementArea.startCoinGenMode(); this.oppoPlacementArea.startCoinGenMode(); } public void TestLoadJsonData() { //mJsonData.LoadGlobalJsonData(); } /// /// Caches the attached wave manager and subscribes to the spawning completed event /// Sets the level state to intro and ensures that the number of enemies is set to 0 /// protected override void Awake() { base.Awake(); for( int ti = 0;ti(); waveManager.spawningCompleted += OnSpawningCompleted; // Does not use the change state function as we don't need to broadcast the event for this default value levelState = LevelState.Intro; numberOfEnemies = 0; // Ensure currency change listener is assigned currency = new Currency(startingCurrency); currencyGainer.Initialize(currency); // 设置对手数据 // OpponentMgr.instance.startingCurrency = startingCurrency; // If there's an intro use it, otherwise fall through to gameplay if (intro != null) { intro.introCompleted += IntroCompleted; } else { IntroCompleted(); } // Iterate through home bases and subscribe numberOfHomeBases = homeBases.Length; numberOfHomeBasesLeft = numberOfHomeBases; for (int i = 0; i < numberOfHomeBases; i++) { homeBases[i].homebaseIdx = i; homeBases[i].died += OnHomeBaseDestroyed; } // 处理对手盘的HomeBase数据 oppoNumOfHomeBases = opponentHomeBases.Length; oppoNumOfHomeBaseLeft = oppoNumOfHomeBases; for( int ti = 0;ti /// Updates the currency gain controller /// protected virtual void Update() { if (alwaysGainCurrency || (!alwaysGainCurrency && levelState != LevelState.Building && levelState != LevelState.Intro)) { currencyGainer.Tick(Time.deltaTime); } } /// /// Unsubscribes from events /// protected override void OnDestroy() { base.OnDestroy(); if (waveManager != null) { waveManager.spawningCompleted -= OnSpawningCompleted; } if (intro != null) { intro.introCompleted -= IntroCompleted; } // Iterate through home bases and unsubscribe for (int i = 0; i < numberOfHomeBases; i++) { homeBases[i].died -= OnHomeBaseDestroyed; } for( int ti = 0;ti /// Fired when Intro is completed or immediately, if no intro is specified /// protected virtual void IntroCompleted() { ChangeLevelState(LevelState.Building); } /// /// Fired when the WaveManager has finished spawning enemies /// protected virtual void OnSpawningCompleted() { ChangeLevelState(LevelState.AllEnemiesSpawned); } /// /// Changes the state and broadcasts the event /// /// The new state to transitioned to protected virtual void ChangeLevelState(LevelState newState) { // If the state hasn't changed then return if (levelState == newState) { return; } LevelState oldState = levelState; levelState = newState; if (levelStateChanged != null) { levelStateChanged(oldState, newState); } switch (newState) { case LevelState.SpawningEnemies: waveManager.StartWaves(); break; case LevelState.AllEnemiesSpawned: // Win immediately if all enemies are already dead if (numberOfEnemies == 0) { ChangeLevelState(LevelState.Win); } break; case LevelState.Lose: SafelyCallLevelFailed(); break; case LevelState.Win: SafelyCallLevelCompleted(); break; } } /// /// Fired when a home base is destroyed /// protected virtual void OnHomeBaseDestroyed(DamageableBehaviour homeBase) { // Decrement the number of home bases numberOfHomeBasesLeft--; // Call the destroyed event if (homeBaseDestroyed != null) { homeBaseDestroyed(); } // If there are no home bases left and the level is not over then set the level to lost if ((numberOfHomeBasesLeft < 3) && !isGameOver) { ChangeLevelState(LevelState.Lose); } } /// /// 对手盘的HomeBase被破坏掉的接口 /// /// protected void OnOppoHomeBaseDestroyed(DamageableBehaviour homeBase) { // Decrement the number of home bases this.oppoNumOfHomeBaseLeft --; // Call the destroyed event if (homeBaseDestroyed != null) { homeBaseDestroyed(); } // If there are no home bases left and the level is not over then set the level to lost if ((oppoNumOfHomeBaseLeft < 3 ) && !isGameOver) { ChangeLevelState( LevelState.Win ); } } /// /// Calls the event /// protected virtual void SafelyCallLevelCompleted() { if (levelCompleted != null) { levelCompleted(); } } /// /// Calls the event /// protected virtual void SafelyCallNumberOfEnemiesChanged() { if (numberOfEnemiesChanged != null) { numberOfEnemiesChanged(numberOfEnemies); } } /// /// Calls the event /// protected virtual void SafelyCallLevelFailed() { if (levelFailed != null) { levelFailed(); } } } }