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