using System;
|
using Core.Economy;
|
using Core.Health;
|
using Core.Utilities;
|
using TowerDefense.Economy;
|
using TowerDefense.Towers.Data;
|
using TowerDefense.Towers.Placement;
|
using UnityEngine;
|
using UnityEngine.UI;
|
using KTGMGemClient;
|
using System.Collections;
|
using System.Collections.Generic;
|
using TowerDefense.Nodes;
|
using TowerDefense.UI.HUD;
|
|
namespace TowerDefense.Level
|
{
|
/// <summary>
|
/// The level manager - handles the level states and tracks the player's currency
|
/// PVE(无尽模式)关卡管理器
|
/// </summary>
|
[RequireComponent(typeof(EndlessWaveManager))]
|
public class EndlessLevelManager : Singleton<EndlessLevelManager>
|
{
|
/// <summary>
|
/// 当前的关卡等级
|
/// </summary>
|
public int CurrentLevel { get; set; } = 1;
|
|
protected static readonly int MAX_TOWER = 5;
|
|
/// <summary>
|
/// The tower library for level
|
/// </summary>
|
public TowerLibrary TowerLibrary;
|
|
/// <summary>
|
/// The currency that the player starts with
|
/// </summary>
|
public int StartingCurrency;
|
|
/// <summary>
|
/// 自身所在的PlacementArea
|
/// </summary>
|
public TowerPlacementGridEndless SelfPlacementArea;
|
|
/// <summary>
|
/// The controller for gaining currency
|
/// </summary>
|
public CurrencyGainer CurrencyGainer;
|
|
/// <summary>
|
/// Configuration for if the player gains currency even in pre-build phase
|
/// </summary>
|
[Header("Setting will allow currency gain during the Intro and Pre-Build phase")]
|
public bool alwaysGainCurrency;
|
|
/// <summary>
|
/// The home bases that the player must defend
|
/// </summary>
|
public PlayerHomeBase[] HomeBases;
|
|
/// <summary>
|
/// The attached wave manager
|
/// </summary>
|
public EndlessWaveManager WaveManager { get; protected set; }
|
|
/// <summary>
|
/// Number of enemies currently in the level
|
/// </summary>
|
public int NumberOfEnemies { get; protected set; }
|
|
/// <summary>
|
/// The current state of the level
|
/// </summary>
|
public LevelState EndlessLeveltate { get; protected set; }
|
|
/// <summary>
|
/// The currency controller
|
/// </summary>
|
public Currency Currency { get; protected set; }
|
|
/// <summary>
|
/// Number of home bases left
|
/// </summary>
|
public int NumberOfHomeBasesLeft { get; protected set; }
|
|
/// <summary>
|
/// Starting number of home bases
|
/// </summary>
|
public int NumberOfHomeBases { get; protected set; }
|
|
/// <summary>
|
/// 每一个Tower对应的AttributeID.
|
/// </summary>
|
protected int[] towerAttributeID = new int[5];
|
|
protected int[] towerLevel = new int[5];
|
|
/// <summary>
|
/// An accessor for the home bases
|
/// </summary>
|
public PlayerHomeBase[] playerHomeBases
|
{
|
get { return HomeBases; }
|
}
|
|
/// <summary>
|
/// Fired when all the waves are done and there are no more enemies left
|
/// </summary>
|
public event Action LevelCompleted;
|
|
/// <summary>
|
/// Fired when the level state is changed - first parameter is the old state, second parameter is the new state
|
/// </summary>
|
public event Action<LevelState, LevelState> LevelStateChanged;
|
|
/// <summary>
|
/// Fired when the number of enemies has changed
|
/// </summary>
|
public event Action<int> numberOfEnemiesChanged;
|
|
public event Action<int> DecrementEnemies;
|
|
/// <summary>
|
/// Event for home base being destroyed
|
/// </summary>
|
public event Action homeBaseDestroyed;
|
|
/// <summary>
|
/// 当前关卡的所有波次是否全部完成
|
/// </summary>
|
private bool IsAllWaveCompleted;
|
|
/// <summary>
|
/// 基地起点集合
|
/// </summary>
|
public List<Node> StartingNodeList;
|
|
/// <summary>
|
/// 已经完成的关卡数量
|
/// </summary>
|
public int CompletedLevels { get; protected set; }
|
|
/// <summary>
|
/// 选择buff需要通过的关卡数量,也就是,通过每通过几关然后开始选buff
|
/// </summary>
|
/// <value></value>
|
public int SelectBuffNeddLevels { get; set; }
|
// cx test
|
// public int SelectBuffNeddLevels { get; set; } = 2;
|
|
/// <summary>
|
/// buff是否选择完成
|
/// </summary>
|
private bool isBuffSelectCompleted = true;
|
|
/// <summary>
|
/// 新手第一关是否完成
|
/// </summary>
|
private bool isFirstLevelCompleted = false;
|
|
private bool isStopSecondWaveCompleted = false;
|
|
/// <summary>
|
/// 切换基地
|
/// </summary>
|
/// <param name="index">列索引</param>
|
public Node SwitchHomeBase(int index)
|
{
|
EndlessSwitchHomeBase switchHomeBase = StartingNodeList[index].GetComponent<EndlessSwitchHomeBase>();
|
return switchHomeBase.SwitchHomeBase();
|
}
|
|
/// <summary>
|
/// 设置每一条兵线对应的AttID
|
/// </summary>
|
/// <param name="waveline"></param>
|
/// <param name="id"></param>
|
public void SetTowerAttID(int waveline, int id, int lvl)
|
{
|
towerAttributeID[waveline] = id;
|
towerLevel[waveline] = lvl;
|
}
|
|
/// <summary>
|
/// 重设当前的Currency数据
|
/// </summary>
|
/// <param name="curnum"></param>
|
public void ResetCurrency(int curnum)
|
{
|
int curChg = curnum - Currency.currentCurrency;
|
Currency.AddCurrency(curChg);
|
}
|
|
/// <summary>
|
/// If the game is over
|
/// </summary>
|
public bool isGameOver
|
{
|
get { return EndlessLeveltate == LevelState.Win || EndlessLeveltate == LevelState.Lose; }
|
}
|
|
/// <summary>
|
/// Increments the number of enemies. Called on Agent spawn
|
/// </summary>
|
public virtual void IncrementNumberOfEnemies()
|
{
|
NumberOfEnemies++;
|
SafelyCallNumberOfEnemiesChanged();
|
}
|
|
/// <summary>
|
/// Returns the sum of all HomeBases' health
|
/// </summary>
|
public float GetAllHomeBasesHealth()
|
{
|
float health = 0.0f;
|
foreach (PlayerHomeBase homebase in HomeBases)
|
{
|
health += homebase.configuration.currentHealth;
|
}
|
return health;
|
}
|
|
/// <summary>
|
/// Decrements the number of enemies. Called on Agent death
|
/// </summary>
|
public virtual void DecrementNumberOfEnemies()
|
{
|
NumberOfEnemies--;
|
CallDecrementEnemies();
|
SafelyCallNumberOfEnemiesChanged();
|
if (NumberOfEnemies < 0)
|
{
|
Debug.LogError("[LEVEL] There should never be a negative number of enemies. Something broke!");
|
NumberOfEnemies = 0;
|
}
|
|
if (NumberOfEnemies == 0 && EndlessLeveltate == LevelState.AllEnemiesSpawned)
|
{
|
ChangeLevelState(LevelState.Win);
|
}
|
}
|
|
/// <summary>
|
/// 开始关卡
|
/// </summary>
|
public virtual void StartLevel()
|
{
|
ChangeLevelState(LevelState.SpawningEnemies);
|
SelfPlacementArea.startCoinGenMode();
|
}
|
|
/// <summary>
|
/// 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
|
/// </summary>
|
protected override void Awake()
|
{
|
base.Awake();
|
|
for (int i = 0; i < MAX_TOWER; ++i)
|
{
|
towerAttributeID[i] = 0;
|
}
|
|
WaveManager = GetComponent<EndlessWaveManager>();
|
WaveManager.AllWaveCompleted += AllWaveCompleted;
|
|
// Does not use the change state function as we don't need to broadcast the event for default value
|
EndlessLeveltate = LevelState.Intro;
|
NumberOfEnemies = 0;
|
|
// Ensure currency change listener is assigned
|
Currency = new Currency(StartingCurrency);
|
CurrencyGainer.Initialize(Currency);
|
|
// Iterate through home bases and subscribe
|
NumberOfHomeBases = HomeBases.Length;
|
NumberOfHomeBasesLeft = NumberOfHomeBases;
|
|
for (int i = 0; i < NumberOfHomeBases; i++)
|
{
|
HomeBases[i].homebaseIdx = i % MAX_TOWER;
|
HomeBases[i].died += OnHomeBaseDestroyed;
|
}
|
}
|
|
private void Start()
|
{
|
EndlessBuffSelect.instance.BuffSelectCompleted += OnBuffSelectCompleted;
|
EndlessGameUI.instance.GameOverEvent += SafelyCallLevelCompleted;
|
}
|
|
/// <summary>
|
/// Updates the currency gain controller
|
/// </summary>
|
protected virtual void Update()
|
{
|
if (alwaysGainCurrency || !alwaysGainCurrency && EndlessLeveltate != LevelState.Building && EndlessLeveltate != LevelState.Intro)
|
{
|
CurrencyGainer.Tick(Time.deltaTime);
|
}
|
|
if (!isBuffSelectCompleted)
|
{
|
isBuffSelectCompleted = true;
|
WaveManager.StartWaves(CurrentLevel);
|
EndlessUIStart.instance.Restart();
|
}
|
|
// 本关卡所有波次全部生成完成 && 敌人全部被清理了,然后就去尝试进入下一关
|
if (EndlessLeveltate == LevelState.SpawningEnemies && IsAllWaveCompleted && NumberOfEnemies == 0)
|
{
|
// 新手的话,第一关完了暂停
|
if (!GameConfig.IsNewbie || GameConfig.IsNewbieGuideCompleted)
|
{
|
if (!UpdateLevel())
|
ChangeLevelState(LevelState.AllEnemiesSpawned);
|
}
|
else if (!isFirstLevelCompleted)
|
{
|
isFirstLevelCompleted = true;
|
EndlessUIStart.instance.Pause();
|
// 第一关的怪全部被杀光
|
EventCenter.Ins.BroadCast((int)KTGMGemClient.EventType.KillDone);
|
}
|
}
|
}
|
|
/// <summary>
|
/// Unsubscribes from events
|
/// </summary>
|
protected override void OnDestroy()
|
{
|
base.OnDestroy();
|
|
if (WaveManager != null)
|
WaveManager.AllWaveCompleted -= AllWaveCompleted;
|
|
// Iterate through home bases and unsubscribe
|
for (int i = 0; i < NumberOfHomeBases; i++)
|
{
|
HomeBases[i].died -= OnHomeBaseDestroyed;
|
}
|
}
|
|
/// <summary>
|
/// Fired when the WaveManager has finished spawning enemies
|
/// </summary>
|
protected virtual void AllWaveCompleted()
|
{
|
IsAllWaveCompleted = true;
|
}
|
|
/// <summary>
|
/// 更新关卡
|
/// </summary>
|
private bool UpdateLevel()
|
{
|
++CurrentLevel;
|
IsAllWaveCompleted = false;
|
|
// 所有关卡全部结束
|
if (CurrentLevel > EndlessPortData.MaxLevel)
|
return false;
|
|
StartCoroutine(DelayToNextLevel());
|
|
return true;
|
}
|
|
/// <summary>
|
/// 新手更新关卡
|
/// </summary>
|
public void NewbieUpdateLevel()
|
{
|
++CurrentLevel;
|
IsAllWaveCompleted = false;
|
EndlessUIStart.instance.Restart();
|
WaveManager.StartWaves(CurrentLevel);
|
}
|
|
/// <summary>
|
/// 延迟进入下一关
|
/// </summary>
|
/// <returns></returns>
|
private IEnumerator DelayToNextLevel()
|
{
|
yield return new WaitForSeconds(5f);
|
BeginLevel();
|
}
|
|
/// <summary>
|
/// 开始关卡,需要处理选择buff
|
/// </summary>
|
private void BeginLevel()
|
{
|
if (EndlessGameUI.instance.state == EndlessGameUI.State.GameOver) return;
|
|
if (!GameConfig.IsNewbie)
|
ShowSelectBuffUI();
|
else
|
{
|
EndlessUIStart.instance.Restart();
|
WaveManager.StartWaves(CurrentLevel);
|
}
|
}
|
|
/// <summary>
|
/// 显示选择buff界面
|
/// </summary>
|
private void ShowSelectBuffUI()
|
{
|
// 需要随机一个buff列表出来,然后简单刷新一下界面
|
List<EndlessBuffConfig> list = EndlessBuffData.GetRandomBuffList();
|
|
if (list.Count == 0)
|
{
|
isBuffSelectCompleted = false;
|
return;
|
}
|
|
EndlessUIStart.instance.Pause();
|
EndlessBuffSelect.instance.Refresh(list);
|
EndlessBuffSelect.instance.ShowBuffUI();
|
}
|
|
/// <summary>
|
/// buff选择完成
|
/// </summary>
|
/// <param name="index"></param>
|
public void OnBuffSelectCompleted(int index)
|
{
|
isBuffSelectCompleted = false;
|
EndlessBuffManager.instance.AddBuff(EndlessBuffData.GetBuffByIndex(index));
|
}
|
|
/// <summary>
|
/// Changes the state and broadcasts the event
|
/// </summary>
|
/// <param name="newState">The new state to transitioned to</param>
|
protected virtual void ChangeLevelState(LevelState newState)
|
{
|
if (EndlessLeveltate == newState)
|
return;
|
|
LevelState oldState = EndlessLeveltate;
|
EndlessLeveltate = newState;
|
|
if (LevelStateChanged != null)
|
LevelStateChanged(oldState, newState);
|
|
switch (newState)
|
{
|
case LevelState.SpawningEnemies:
|
BeginLevel();
|
break;
|
case LevelState.AllEnemiesSpawned:
|
// if (NumberOfEnemies == 0)
|
ChangeLevelState(LevelState.Win);
|
break;
|
case LevelState.Lose:
|
SafelyCallLevelCompleted();
|
break;
|
case LevelState.Win:
|
SafelyCallLevelCompleted();
|
Debug.Log("--------------------- you are winner !!! ---------------------");
|
break;
|
}
|
}
|
|
/// <summary>
|
/// Fired when a home base is destroyed
|
/// </summary>
|
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);
|
// }
|
}
|
|
/// <summary>
|
/// Calls the <see cref="levelCompleted"/> event
|
/// </summary>
|
protected virtual void SafelyCallLevelCompleted()
|
{
|
EndlessDropManager.instance.PickUpAllDrop();
|
if (LevelCompleted != null)
|
LevelCompleted();
|
}
|
|
/// <summary>
|
/// Calls the <see cref="numberOfEnemiesChanged"/> event
|
/// </summary>
|
protected virtual void SafelyCallNumberOfEnemiesChanged()
|
{
|
if (numberOfEnemiesChanged != null)
|
numberOfEnemiesChanged(NumberOfEnemies);
|
}
|
|
protected virtual void CallDecrementEnemies()
|
{
|
if (DecrementEnemies != null)
|
DecrementEnemies(1);
|
}
|
|
/// <summary>
|
/// 兵线的所有基地都已经被摧毁,停止某一条兵线的出兵
|
/// </summary>
|
/// <param name="index"></param>
|
public void StopWaveLine(int index)
|
{
|
if (WaveManager.waves[index].LineState == EndlessWaveLineState.Spawning)
|
{
|
WaveManager.waves[index].StopWave();
|
WaveManager.waves[index].LineState = EndlessWaveLineState.Destroyed;
|
--WaveManager.TotalWaveLines;
|
}
|
}
|
|
/// <summary>
|
/// 暂停波次,小怪停止移动,塔停止攻击
|
/// </summary>
|
public void PauseWave()
|
{
|
EndlessUIStart.instance.Pause();
|
AgentInsManager.instance.SetWaveLineCanMove(-1, false, false);
|
WaveManager.PauseAllWave();
|
EndlessGameUI.instance.SetAttackingTowerState(false);
|
}
|
|
/// <summary>
|
/// 恢复波次,小怪
|
/// </summary>
|
public void RestartWave()
|
{
|
EndlessUIStart.instance.Restart();
|
AgentInsManager.instance.SetWaveLineCanMove(-1, true, false);
|
WaveManager.RestartAllWave();
|
EndlessGameUI.instance.SetAttackingTowerState(true);
|
}
|
|
/// <summary>
|
/// 停止第二关波次
|
/// </summary>
|
public void StopSecondWave()
|
{
|
Debug.LogError("--------------------- 停止第二关出怪 ---------------------");
|
if (!isStopSecondWaveCompleted)
|
{
|
isStopSecondWaveCompleted = true;
|
PauseWave();
|
}
|
EventCenter.Ins.BroadCast((int)KTGMGemClient.EventType.SkillStep);
|
}
|
}
|
}
|