using Core.Extensions;
|
using Core.Utilities;
|
using System;
|
using System.Collections.Generic;
|
using TowerDefense.Level;
|
using TowerDefense.Towers;
|
using TowerDefense.UI.HUD;
|
using UnityEngine;
|
using MoreMountains.NiceVibrations;
|
using UnityEngine.UI;
|
using DG.Tweening;
|
using TMPro;
|
using KTGMGemClient;
|
|
public class RandomTower : Singleton<RandomTower>
|
{
|
// 当前类所在的Btn.
|
public Button randomBtn;
|
|
/// <summary>
|
/// 倒计时对应的背景图片.
|
/// </summary>
|
public Image cdTimeBg;
|
|
/// <summary>
|
/// 倒计划对应的文字.
|
/// </summary>
|
public TextMeshProUGUI cdTimeText;
|
|
/// <summary>
|
/// 购买二级宝石的按钮贴图.
|
/// </summary>
|
public Sprite buyBtnLevelUp;
|
protected bool bSetBuyLvlUp;
|
protected bool bCdTimeStart;
|
protected float btnLvlUpCdTime;
|
|
// 玩家初始阵容
|
protected List<Tower> towerArray = new List<Tower>();
|
|
// AI 初始阵容
|
protected List<Tower> aiTowerArray = new List<Tower>();
|
|
protected int maxTower = 0;
|
private bool firstDeploy = false;
|
|
public static readonly int MAX_TOWERDIS = 5;
|
|
// 开始出现技能塔的时间:
|
public static float SKILL_TOWER_TIME = 30.0f;
|
|
// 购买之后直接出现2级宝石的时间.
|
public static float LEVELUP_TOWER_TIME = 10.0f;
|
|
protected System.Random mRandom;
|
|
protected int rTowerIdx = 2;
|
|
// 所有宝石随机总权重
|
private int randomTotalWeight;
|
|
// 所有宝石位置权重列表
|
private List<int> weightList;
|
|
// 是否初始化过出战数据
|
private bool isInitFightData = false;
|
|
// Start is called before the first frame update
|
void Start()
|
{
|
if (!LevelManager.instanceExists)
|
{
|
Debug.LogError("[UI] No level manager for tower list");
|
}
|
foreach (Tower tower in LevelManager.instance.towerLibrary)
|
{
|
towerArray.Add(tower);
|
aiTowerArray.Add(tower);
|
}
|
maxTower = towerArray.Count;
|
|
while (maxTower > MAX_TOWERDIS)
|
{
|
maxTower--;
|
towerArray.RemoveAt(towerArray.Count - 1);
|
aiTowerArray.RemoveAt(towerArray.Count - 1);
|
}
|
|
mRandom = new System.Random();
|
|
bSetBuyLvlUp = false;
|
bCdTimeStart = false;
|
|
cdTimeBg.gameObject.SetActive(false);
|
cdTimeText.text = "";
|
}
|
|
/// <summary>
|
/// 获取TowerList.
|
/// </summary>
|
public List<Tower> towerList
|
{
|
get { return this.towerArray; }
|
}
|
|
/// <summary>
|
/// 处理按钮升级相关.
|
/// </summary>
|
private void Update()
|
{
|
float gstime = UIStart.instance.gameStartTime;
|
if (gstime <= 0) return;
|
|
if ((!bCdTimeStart) && (LEVELUP_TOWER_TIME - gstime) <= JsonDataCenter.TOWERLVLUP_CDTIME)
|
{
|
bCdTimeStart = true;
|
btnLvlUpCdTime = LEVELUP_TOWER_TIME - gstime;
|
cdTimeBg.gameObject.SetActive(true);
|
}
|
if ((!bSetBuyLvlUp) && (gstime > LEVELUP_TOWER_TIME))
|
{
|
bSetBuyLvlUp = true;
|
this.randomBtn.GetComponent<Image>().sprite = buyBtnLevelUp;
|
cdTimeBg.gameObject.SetActive(false);
|
cdTimeText.text = "";
|
}
|
|
|
// 更新倒计时:
|
if ((!bSetBuyLvlUp) && bCdTimeStart)
|
{
|
btnLvlUpCdTime -= Time.deltaTime;
|
string distr = ((int)Math.Ceiling(btnLvlUpCdTime)).ToString() + "s";
|
cdTimeText.text = distr;
|
}
|
}
|
|
public void actionTest()
|
{
|
multipara((str, strnew) => { Debug.Log(str + strnew); }, "Ying");
|
}
|
|
protected void actadd(string str, string strnew)
|
{
|
Debug.Log("这是新增的Action String:" + str);
|
}
|
|
protected void testList()
|
{
|
List<int> m_list = new List<int>();
|
m_list.Add(10);
|
m_list.Add(15);
|
m_list.Add(20);
|
m_list.Add(30);
|
m_list.Add(100);
|
int curNode = 0;
|
string strNumber = m_list[0].ToString();
|
bool hasNext = m_list.Next(ref curNode);
|
while (hasNext)
|
{
|
strNumber += ",";
|
strNumber += m_list[curNode];
|
hasNext = m_list.Next(ref curNode);
|
}
|
Debug.Log("The Final Test List String is:" + strNumber);
|
}
|
|
/// <summary>
|
/// 用于测试Action参数的测试函数,Action多参数的用法.
|
/// </summary>
|
/// <param name="act"></param>
|
/// <param name="p1"></param>
|
protected void multipara(Action<string, string> act, string p1)
|
{
|
string finalstr = "Welcome to " + p1;
|
act += this.actadd;
|
act(finalstr, "YingYing");
|
}
|
|
|
protected void testCode()
|
{
|
/*
|
System.Random rd = new System.Random();
|
string randstr = "";
|
for( int ti = 0;ti<10;ti ++)
|
{
|
randstr += rd.Next(0, 100).ToString();
|
randstr += ",";
|
}
|
Debug.Log("最终的随机数数据是:" + randstr);*/
|
|
|
// TEST CODE TO DELETE:
|
//TestTcpSocket.instance.connectTcp();
|
//return;
|
|
/*
|
// TEST CODE TO read json file
|
Debug.Log("DataPath:" + Application.dataPath);
|
Debug.Log("PersistentDataPath:" + Application.persistentDataPath);
|
StreamReader tstream = new StreamReader(Application.dataPath + "/configdata/tjson.txt");
|
String line;
|
string fcontent = "";
|
while ((line = tstream.ReadLine()) != null)
|
{
|
fcontent += line.ToString();
|
}
|
Debug.Log("文件信息数据:" + fcontent);
|
JSONNode root = JSONNode.Parse(fcontent);
|
Debug.Log("解析Node成功.");*/
|
|
// 测试
|
//this.actionTest();
|
|
// TEST CODE TO DELETE:
|
//SingleTonCls sts = SingleTonCls.instance;
|
//if (sts != null)
|
// Debug.Log("The Fuck String is:" + sts.getString());
|
|
// test List function:
|
// this.testList();
|
|
// 输出TowerPrice的测试:
|
//int curtp = TowerPrice.instance.currentTowerPrice;
|
//Debug.Log("当前的Tower Price is:" + curtp);
|
}
|
|
/// <summary>
|
/// 获取序列化的Tower
|
/// </summary>
|
/// <returns></returns>
|
public Tower getRTower()
|
{
|
Tower t = this.towerArray[this.rTowerIdx];
|
rTowerIdx++;
|
if (rTowerIdx >= this.maxTower)
|
rTowerIdx = 2;
|
return t;
|
}
|
|
protected int customTowerBuy()
|
{
|
// 0: 机枪塔 火骰子 1: 火箭塔 冰骰子 2: 激光塔 电骰子 3: 铁骰子 4: 位置重设的骰子.
|
// River TEST CODE: 用于放置固定的塔防,方便调试相关的防御塔
|
int tidx = 0; // 机关枪塔.
|
if (this.firstDeploy == false)
|
{
|
tidx = 0; // 火箭塔.
|
tidx = 4; // 现金塔.
|
this.firstDeploy = true;
|
}
|
else
|
tidx = 0; // 机枪塔.
|
tidx = 3; // 机枪塔.
|
|
return tidx;
|
}
|
|
/// <summary>
|
/// 根据Tower名字获取当前的Tower指针。
|
/// </summary>
|
/// <param name="name"></param>
|
/// <returns></returns>
|
public Tower getTowerByName(string name)
|
{
|
for (int ti = 0; ti < this.maxTower; ti++)
|
if (name == this.towerArray[ti].towerName)
|
return towerArray[ti];
|
|
return GetRandomTower(false, false);
|
}
|
|
public static bool MAX_INTERNAL = false;
|
|
|
/// <summary>
|
/// 点击反馈.
|
/// </summary>
|
public void onRandomButtonDown()
|
{
|
MMVibrationManager.Haptic(HapticTypes.MediumImpact);
|
|
// 按钮缩放相关内容
|
if ((!randomBtn) || (!randomBtn.interactable)) return;
|
|
this.randomBtn.transform.DOKill();
|
this.randomBtn.transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
|
|
// 开始缩小Button
|
Sequence scaleTweenSeq = DOTween.Sequence();
|
Tweener btnScale = this.randomBtn.transform.DOScale(0.92f, 0.15f);
|
scaleTweenSeq.Append(btnScale);
|
//scaleTweenSeq.AppendCallback(recoverBtnScale);
|
|
}
|
|
/// <summary>
|
/// 点触离开当前的按钮.
|
/// </summary>
|
public void onTouchExit()
|
{
|
this.randomBtn.transform.DOKill();
|
recoverBtnScale();
|
}
|
|
protected void recoverBtnScale()
|
{
|
this.randomBtn.transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
|
}
|
|
/// <summary>
|
/// 获取随机命中位置索引
|
/// </summary>
|
private int GetRandomIndex(List<int> list, int totalWeight)
|
{
|
int random = mRandom.Next(0, totalWeight);
|
int index = -1;
|
int total = 0;
|
|
for (int i = 0; i < list.Count; ++i)
|
{
|
total += list[i];
|
if (total >= random)
|
{
|
index = i;
|
break;
|
}
|
}
|
|
return index;
|
}
|
|
/// <summary>
|
/// 根据规则生成一个随机的塔
|
/// </summary>
|
/// <param name="isOppo">是否是对手</param>
|
/// <param name="onlySpawnElf">是否仅产生精灵宝石,而不产生技能宝石</param>
|
/// <returns></returns>
|
public Tower GetRandomTower(bool isOppo, bool onlySpawnElf = true)
|
{
|
if (!isInitFightData)
|
{
|
isInitFightData = true;
|
weightList = new List<int>();
|
List<posWeight> posWeight = JsonDataCenter.GetList<posWeight>();
|
randomTotalWeight = 0;
|
|
for (int i = 0; i < posWeight.Count; ++i)
|
{
|
weightList.Add(posWeight[i].weight);
|
randomTotalWeight += posWeight[i].weight;
|
}
|
|
// 游戏开始之前先把出站组乱序
|
GameUtils.Shuffle(towerArray);
|
GameUtils.Shuffle(aiTowerArray);
|
}
|
|
Tower ret = null;
|
List<Tower> list = isOppo ? aiTowerArray : towerArray;
|
|
// 还没到技能时间,忽略掉技能宝石
|
if (onlySpawnElf)
|
{
|
// 精灵宝石位置索引列表
|
List<int> elfIndexList = new List<int>();
|
|
for (int i = 0; i < list.Count; ++i)
|
{
|
if (list[i].towerFeature == EFeatureTower.NULL)
|
elfIndexList.Add(i);
|
}
|
|
// 没有上阵精灵宝石
|
if (elfIndexList.Count == 0)
|
{
|
Debug.LogError("--------------------- 没有上阵精灵宝石 ---------------------");
|
return null;
|
}
|
|
// 计算所有精灵宝石位置的总权重
|
int elfTotalWeight = 0;
|
// 精灵宝石位置权重列表
|
List<int> elfWeightList = new List<int>();
|
|
for (int i = 0; i < elfIndexList.Count; ++i)
|
{
|
elfTotalWeight += weightList[elfIndexList[i]];
|
elfWeightList.Add(weightList[elfIndexList[i]]);
|
}
|
|
// 所有精灵宝石位置的权重都为0,直接等概率出一个精灵宝石
|
int index = elfTotalWeight == 0 ? mRandom.Next(0, elfIndexList.Count) : GetRandomIndex(elfWeightList, elfTotalWeight);
|
ret = list[elfIndexList[index]];
|
}
|
// 可以自由产生
|
else
|
{
|
int index = randomTotalWeight == 0 ? mRandom.Next(0, list.Count) : GetRandomIndex(weightList, randomTotalWeight);
|
ret = list[index];
|
}
|
|
// 生成宝石成功,需要调整宝石位置,把宝石放到队尾
|
list.Remove(ret);
|
list.Add(ret);
|
|
return ret;
|
}
|
|
/// <summary>
|
/// 随机购买Tower的入口,如果购买成功,则需要实时更新价格.
|
/// </summary>
|
public void onClick()
|
{
|
this.testCode();
|
|
// 恢复RandomTowerBtn的缩放
|
this.recoverBtnScale();
|
|
// 还没到技能时间,忽略掉技能宝石
|
Tower newTower = GetRandomTower(false, UIStart.instance.gameStartTime <= SKILL_TOWER_TIME);
|
|
if (!newTower)
|
throw new Exception("未能成功产生Tower");
|
|
RandomPlaceTower(newTower, false);
|
}
|
|
/// <summary>
|
/// 随机放置一个对手Tower.
|
/// </summary>
|
public Tower randomOpponentTower(bool allTower = true)
|
{
|
Tower newTower = GetRandomTower(true, !allTower);
|
|
if (!newTower)
|
throw new Exception("未能成功产生Tower");
|
|
RandomPlaceTower(newTower, true);
|
|
return newTower;
|
}
|
|
/// <summary>
|
/// 随机找一个空白位置放置塔防
|
/// </summary>
|
/// <param name="tower"></param>
|
/// <param name="isOpponent"></param>
|
public void RandomPlaceTower(Tower tower, bool isOpponent)
|
{
|
var gameUI = GameUI.instance;
|
|
if (isOpponent)
|
{
|
if (UIStart.instance.gameStartTime >= LEVELUP_TOWER_TIME)
|
gameUI.RandomOpponentTower(tower, -1, -1, 1);
|
else
|
gameUI.RandomOpponentTower(tower);
|
}
|
else
|
{
|
if (gameUI.isBuilding)
|
gameUI.CancelGhostPlacement();
|
if (UIStart.instance.gameStartTime >= LEVELUP_TOWER_TIME)
|
gameUI.RandomPlaceTower(tower, -1, -1, 1);
|
else
|
gameUI.RandomPlaceTower(tower);
|
}
|
}
|
|
/// <summary>
|
/// 在固定的位置,放置一个随机的塔防类型.
|
/// </summary>
|
/// <param name="x"></param>
|
/// <param name="y"></param>
|
public void randomTower(int x, int y, int lvl, string tname = "")
|
{
|
int tidx = 0;
|
Tower targetTower = null;
|
if (tname == "")
|
{
|
tidx = mRandom.Next(0, this.maxTower);
|
// 随机升级的Tower,不能升级成为成长骰子.
|
int maxLoop = 20;
|
while (this.towerArray[tidx].towerFeature != EFeatureTower.NULL)
|
{
|
tidx = mRandom.Next(0, this.maxTower);
|
maxLoop--;
|
|
if (maxLoop <= 0)
|
{
|
tidx = this.rTowerIdx;
|
rTowerIdx++;
|
if (rTowerIdx >= maxTower)
|
rTowerIdx = 2;
|
|
Debug.LogError("超级循环发生了.");
|
break;
|
}
|
}
|
targetTower = this.towerArray[tidx];
|
}
|
else
|
{
|
targetTower = getTowerByName(tname);
|
}
|
|
// River: 随机找一个空白位置放置塔防。
|
GameUI.instance.RandomPlaceTower(targetTower, x, y, lvl, true);
|
return;
|
}
|
}
|