using System.Collections.Generic;
|
using UnityEngine;
|
using Core.Utilities;
|
using TowerDefense.Towers.Placement;
|
using TowerDefense.Nodes;
|
using TowerDefense.Level;
|
using Core.Economy;
|
using TowerDefense.Towers;
|
using TowerDefense.UI.HUD;
|
using TowerDefense.Agents;
|
using KTGMGemClient;
|
|
/// <summary>
|
/// 对战管理器,主要负责屏幕上方的敌方数据结构和相关的显示展示
|
/// 1: 放置塔防的区域。
|
/// 2: OppomentNodeList 对方Agent的刷新和行进路线。
|
/// 3: CurrencyMgr 对方的现金管理
|
/// 4: OpponentAI 对方的AI管理器,用于管理AI相关的内容,是升级,还是购买,还是其它相关。
|
/// 先做一个简单的功能,在开始之后,Opponent先后购买相关的Tower,然后OpponentAgent开始从对方
|
/// Node行进,直到最后死亡。
|
///
|
/// 先能刷新出来OpponentAgent再说下一步
|
/// </summary>
|
public class OpponentMgr : Singleton<OpponentMgr>
|
{
|
protected static readonly int MAX_TOWER = 5;
|
/// <summary>
|
/// 用于对手刷新出来Agent相对应的数据
|
/// </summary>
|
public WaveManager m_WaveManager;
|
|
/// <summary>
|
/// 思考决策的时间间隔.
|
/// </summary>
|
public float thinkInternal = 0.5f; // 改的时间很长是为了调试
|
|
/// <summary>
|
/// 放置塔防的IPlacementArea. Placement area ghost tower is currently on
|
/// </summary>
|
public IPlacementArea m_CurrentArea;
|
|
/// <summary>
|
/// 处理TowerList相关的数据.AI相关的内容也要
|
/// </summary>
|
protected List<Tower> m_listTower = new List<Tower>();
|
|
protected List<int> m_waitBuyTowerPos = new List<int>();
|
|
/// <summary>
|
/// 对方Agent刷新的StartNode区域.
|
/// </summary>
|
protected Node m_StartNode;
|
|
/// <summary>
|
/// 对手的现金管理器
|
/// </summary>
|
protected Currency m_Currency;
|
|
/// <summary>
|
/// 是否已经开始刷怪
|
/// </summary>
|
protected bool bWaveStart = false;
|
|
/// <summary>
|
/// 用于内部判断是否触发智能的时间变量.
|
/// </summary>
|
protected float thinkTimeEle = 0;
|
|
/// <summary>
|
/// 当前空闲的塔位数目
|
/// </summary>
|
protected int freeTowerPos = 0;
|
|
/// <summary>
|
/// 每一个Tower对应的AttributeID.
|
/// </summary>
|
protected int[] towerAttributeID = new int[5];
|
protected int[] towerLevel = new int[5];
|
|
|
// 是否第一次,测试代码:
|
protected static bool bFirst = true;
|
|
|
public int startingCurrency { get; set; }
|
|
public Currency currency
|
{
|
get { return this.m_Currency; }
|
}
|
|
// 待释放技能宝石队列
|
private Queue<Tower> canReleaseSkillsQueue = new Queue<Tower>();
|
|
// 可释放技能的怪物数量限制 >= 4 可释放
|
private int agentQuantityLimit = 4;
|
|
/// <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;
|
|
//if( lvl >=1 )
|
this.UpdateWaveSpawn(waveline, id);
|
}
|
|
public int GetTowerAttID(int waveline)
|
{
|
return towerAttributeID[waveline];
|
}
|
public int GetTowerLevel(int waveline)
|
{
|
return towerLevel[waveline];
|
}
|
|
|
/// <summary>
|
/// 增加一个Tower.
|
/// </summary>
|
/// <param name="tw"></param>
|
public void addTower(Tower tw)
|
{
|
this.m_listTower.Add(tw);
|
}
|
|
/// <summary>
|
/// 根据坐标获取对应的Tower指针.
|
/// </summary>
|
/// <param name="x"></param>
|
/// <param name="y"></param>
|
public Tower getTower(int x, int y)
|
{
|
foreach (Tower t in m_listTower)
|
{
|
if ((t.gridPosition.x == x) && (t.gridPosition.y == y)) return t;
|
}
|
return null;
|
}
|
|
/// <summary>
|
/// 删除一个Tower.
|
/// </summary>
|
/// <param name="tw"></param>
|
public void removeTower(Tower tw)
|
{
|
m_listTower.Remove(tw);
|
}
|
|
|
/// <summary>
|
/// 更新刷怪时间.
|
/// </summary>
|
/// <param name="gridx"></param>
|
/// <param name="attid"></param>
|
protected void UpdateWaveSpawn(int gridx, int attid)
|
{
|
LevelManager.instance.waveManager.UpdateWaveSpawnTime(gridx, attid);
|
}
|
|
//
|
// Start is called before the first frame update
|
void Start()
|
{
|
bFirst = true;
|
bWaveStart = false;
|
|
for (int ti = 0; ti < MAX_TOWER; ti++)
|
towerAttributeID[ti] = 0;
|
|
// 获取IPlaceArea.获取相应的放置区域。
|
GameObject placeObj = GameObject.FindGameObjectWithTag("PlaceTowerOpponent");
|
if (placeObj == null) return;
|
m_CurrentArea = placeObj.GetComponent<IPlacementArea>();
|
|
|
// 初始化全局的Starting Currency.
|
startingCurrency = LevelManager.instance.startingCurrency;
|
m_Currency = new Currency(startingCurrency);
|
m_Currency.currencyChanged += M_Currency_currencyChanged;
|
if (RandomTower.MAX_INTERNAL)
|
this.thinkInternal = 1000;
|
}
|
|
public void ResetCurrency(int currency)
|
{
|
int curChg = currency - m_Currency.currentCurrency;
|
m_Currency.AddCurrency(curChg);
|
}
|
|
private void M_Currency_currencyChanged()
|
{
|
//int cnum = m_Currency.currentCurrency;
|
//Debug.Log("当前反方的现金数目是:" + cnum);
|
}
|
|
|
/* float updateTime = 6.2f;
|
protected void updateTest()
|
{
|
updateTime -= Time.deltaTime;
|
if( updateTime <= 0 )
|
{
|
updateTime = 100;
|
this.upgradeAttackTower(2);
|
}
|
}*/
|
|
// Update is called once per frame
|
void Update()
|
{
|
//if (!this.bWaveStart) return;
|
if (!UIStart.bGameStart) return;
|
|
// TEST CODE:
|
// this.updateTest();
|
|
this.thinkTimeEle += Time.deltaTime;
|
if (thinkInternal > thinkTimeEle) return;
|
thinkTimeEle -= thinkInternal;
|
|
// 触发思考操作:加入一个随机的Tower.
|
if (bFirst)
|
{
|
bFirst = false;
|
RandomTower.instance.randomOpponentTower(false);
|
|
this.currency.TryPurchase(TowerPrice.instance.opponentTowerPrice);
|
TowerPrice.instance.onTowerBuySuccess();
|
}
|
|
// 更新开格子相关
|
this.updateTowerPosBuy();
|
|
// 触发升级Tower的操作.
|
this.UpdateAttackTower();
|
|
PurchaseTower();
|
|
ReleaseSkills();
|
}
|
|
/// <summary>
|
/// 购买产生塔
|
/// </summary>
|
private void PurchaseTower()
|
{
|
// 首先需要钱够
|
if (currency.currentCurrency >= TowerPrice.instance.opponentTowerPrice)
|
{
|
// 如果还不能产生精灵宝石
|
if (UIStart.instance.gameStartTime <= RandomTower.SKILL_TOWER_TIME)
|
{
|
if (freeTowerPos > 0 && m_CurrentArea.hasFreeAttackPos())
|
{
|
--freeTowerPos;
|
RandomTower.instance.randomOpponentTower(false);
|
}
|
}
|
else
|
{
|
// 先获取一个随机的宝石
|
Tower newTower = RandomTower.instance.GetRandomTower(true, false);
|
|
if (newTower.towerFeature == EFeatureTower.NULL && m_CurrentArea.hasFreeAttackPos())
|
{
|
--freeTowerPos;
|
RandomTower.instance.RandomPlaceTower(newTower, true);
|
}
|
else
|
{
|
// 技能宝石的话,直接购买,购买成功放入队列
|
int cost = TowerPrice.instance.opponentTowerPrice;
|
bool purchaseSuccess = OpponentMgr.instance.currency.TryPurchase(cost);
|
|
if (purchaseSuccess)
|
canReleaseSkillsQueue.Enqueue(newTower);
|
}
|
}
|
}
|
}
|
|
/// <summary>
|
/// AI 如果 有技能宝石 并且 某一条路线的怪物数量 >= 4 释放技能
|
/// </summary>
|
private void ReleaseSkills()
|
{
|
if (canReleaseSkillsQueue.Count == 0)
|
return;
|
|
WaveLineAgentInsMgr[] waveLineList = AgentInsManager.instance.getOppoWaveLineList();
|
int index = -1;
|
|
// 找某一条兵线怪物数量 >= 4 的
|
for (int i = 0; i < waveLineList.Length; ++i)
|
{
|
int num = waveLineList[i].getAgentInsNum();
|
|
if (num >= agentQuantityLimit)
|
{
|
index = i;
|
break;
|
}
|
}
|
|
if (index == -1) return;
|
|
Tower tower = canReleaseSkillsQueue.Dequeue();
|
int level = tower.currentLevel;
|
|
if (tower.towerFeature == EFeatureTower.Skill_Fire)
|
{
|
// 火,列攻击,直接在该兵线释放
|
WaveLineOpponentManager.instance.PlayWaveLineEffect(index);
|
AgentInsManager.instance.ExecWavelineAttack(index, tower.ElfId, level, true);
|
}
|
else if (tower.towerFeature == EFeatureTower.Skill_Bomb)
|
{
|
// 控制,技能中心为离塔最近的小怪的中心点
|
Agent agent = AgentInsManager.instance.GetMinDisAgent(index, true);
|
WaveLineOpponentManager.instance.PlayBattleAreaBombEffect(agent.transform.position);
|
AgentInsManager.instance.ExecBombAttack(agent.transform.position, tower.ElfId, level, true);
|
}
|
}
|
|
/// <summary>
|
/// 更新火属性Tower对左右塔的攻击增加.
|
/// </summary>
|
protected void updateFireTowerAttRise()
|
{
|
for (int ti = 0; ti < MAX_TOWER; ti++)
|
{
|
Tower tw = this.getTower(ti, 0);
|
if (tw)
|
tw.attackRise = 0.0f;
|
}
|
|
for (int ti = 0; ti < MAX_TOWER; ti++)
|
{
|
Tower tw = this.getTower(ti, 0);
|
if (tw.towerFeature == EFeatureTower.LightTower)
|
{
|
int nidx = ti - 1;
|
if (nidx >= 0)
|
{
|
tw = getTower(nidx, 0);
|
if (tw)
|
tw.attackRise = 0.1f;
|
}
|
nidx = ti + 1;
|
if (nidx < MAX_TOWER)
|
{
|
tw = getTower(nidx, 0);
|
if (tw)
|
tw.attackRise = 0.1f;
|
}
|
}
|
}
|
}
|
|
|
/// <summary>
|
/// 更新AI开格子逻辑.
|
/// </summary>
|
protected void updateTowerPosBuy()
|
{
|
if (m_waitBuyTowerPos.Count > 0)
|
{
|
if (currency.currentCurrency >= TowerPlacementGrid.GRID_OPENCASH_OPPO)
|
{
|
m_CurrentArea.buyWaitBuyGrid(m_waitBuyTowerPos[0], 0);
|
m_waitBuyTowerPos.RemoveAt(0);
|
}
|
}
|
else
|
{
|
if (currency.currentCurrency >= TowerPlacementGrid.GRID_OPENCASH_OPPO)
|
{
|
if (m_CurrentArea.isWaitBuyGrid(1, 0))
|
{
|
m_CurrentArea.buyWaitBuyGrid(1, 0);
|
freeTowerPos++;
|
}
|
else if (m_CurrentArea.isWaitBuyGrid(3, 0))
|
{
|
m_CurrentArea.buyWaitBuyGrid(3, 0);
|
freeTowerPos++;
|
}
|
else if (m_CurrentArea.isWaitBuyGrid(0, 0))
|
{
|
m_CurrentArea.buyWaitBuyGrid(0, 0);
|
freeTowerPos++;
|
}
|
else if (m_CurrentArea.isWaitBuyGrid(4, 0))
|
{
|
m_CurrentArea.buyWaitBuyGrid(4, 0);
|
freeTowerPos++;
|
}
|
}
|
}
|
|
return;
|
}
|
|
/// <summary>
|
/// 反方攻击塔位的升级逻辑更新,暂时根据场内小怪数目使用简单的逻辑。
|
/// </summary>
|
protected void UpdateAttackTower()
|
{
|
WaveLineAgentInsMgr[] waveLineList = AgentInsManager.instance.getOppoWaveLineList();
|
|
for (int ti = 0; ti < waveLineList.Length; ti++)
|
{
|
int agentNum = waveLineList[ti].getAgentInsNum();
|
|
Tower tower = this.getTower(ti, 0);
|
if (!tower) continue;
|
int lvl = tower.currentLevel;
|
if (lvl >= ElfUpgradeData.MaxTowerLevel)
|
continue;
|
if ((agentNum - 1) <= lvl) continue;
|
|
// 塔位升级相关的数据:
|
if (tower.towerFeature != EFeatureTower.GrowUp)
|
{
|
if ((lvl == 0) && (currency.TryPurchase(80)))
|
{
|
this.upgradeAttackTower(ti);
|
}
|
else if ((lvl == 1) && (currency.TryPurchase(240)))
|
{
|
this.upgradeAttackTower(ti);
|
}
|
else if ((lvl == 2) && (currency.TryPurchase(440)))
|
{
|
this.upgradeAttackTower(ti);
|
}
|
}
|
|
}
|
}
|
|
|
/// <summary>
|
/// 升级某一个攻击位的Tower.
|
/// </summary>
|
/// <param name="x"></param>
|
protected void upgradeAttackTower(int xpos)
|
{
|
Tower newTower = RandomTower.instance.GetRandomTower(true, true);
|
Tower oldTower = this.getTower(xpos, 0);
|
if (oldTower == null) return;
|
|
GameUI.instance.DisplaceTower(newTower, oldTower);
|
|
}
|
|
/// <summary>
|
/// 开启某一个等待购买的塔位。
|
/// </summary>
|
/// <param name="x"></param>
|
/// <returns></returns>
|
public bool openWaitBuyGrid(int x)
|
{
|
if (null == this.m_CurrentArea) return false;
|
if (m_CurrentArea.isWaitBuyGrid(x, 0))
|
{
|
if (currency.currentCurrency < TowerPlacementGrid.GRID_OPENCASH_OPPO)
|
{
|
m_waitBuyTowerPos.Add(x);
|
return true;
|
}
|
return m_CurrentArea.buyWaitBuyGrid(x, 0);
|
}
|
else
|
return true;
|
}
|
|
/// <summary>
|
/// 开始Wave移动
|
/// </summary>
|
public void StartWaves()
|
{
|
this.bWaveStart = true;
|
m_WaveManager.StartWaves();
|
}
|
|
/// <summary>
|
/// 开启一条兵线.
|
/// </summary>
|
/// <param name="x"></param>
|
public void startWaveLine(int x, int attid)
|
{
|
m_WaveManager.startWaveLine(x, attid);
|
if (m_CurrentArea.isWaitBuyGrid(x, 0))
|
{
|
openWaitBuyGrid(x);
|
freeTowerPos++;
|
}
|
}
|
|
public void prepareWaveline(int x)
|
{
|
m_WaveManager.prepareWaveline(x);
|
}
|
|
/// <summary>
|
/// 停止某一条兵线的出兵。
|
/// </summary>
|
/// <param name="x"></param>
|
public void stopWaveLine(int x)
|
{
|
m_WaveManager.stopWaveLine(x);
|
}
|
}
|