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 { // 当前类所在的Btn. public Button randomBtn; /// /// 倒计时对应的背景图片. /// public Image cdTimeBg; /// /// 倒计划对应的文字. /// public TextMeshProUGUI cdTimeText; /// /// 购买二级宝石的按钮贴图. /// public Sprite buyBtnLevelUp; protected bool bSetBuyLvlUp; protected bool bCdTimeStart; protected float btnLvlUpCdTime; // 玩家初始阵容 protected List towerArray = new List(); // AI 初始阵容 protected List aiTowerArray = new List(); 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 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 = ""; } /// /// 获取TowerList. /// public List towerList { get { return this.towerArray; } } /// /// 处理按钮升级相关. /// 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().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 m_list = new List(); 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); } /// /// 用于测试Action参数的测试函数,Action多参数的用法. /// /// /// protected void multipara(Action 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); } /// /// 获取序列化的Tower /// /// 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; } /// /// 根据Tower名字获取当前的Tower指针。 /// /// /// 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; /// /// 点击反馈. /// 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); } /// /// 点触离开当前的按钮. /// public void onTouchExit() { this.randomBtn.transform.DOKill(); recoverBtnScale(); } protected void recoverBtnScale() { this.randomBtn.transform.localScale = new Vector3(1.0f, 1.0f, 1.0f); } /// /// 获取随机命中位置索引 /// private int GetRandomIndex(List 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; } /// /// 根据规则生成一个随机的塔 /// /// 是否是对手 /// 是否仅产生精灵宝石,而不产生技能宝石 /// public Tower GetRandomTower(bool isOppo, bool onlySpawnElf = true) { if (!isInitFightData) { isInitFightData = true; weightList = new List(); List posWeight = JsonDataCenter.GetList(); 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 list = isOppo ? aiTowerArray : towerArray; // 还没到技能时间,忽略掉技能宝石 if (onlySpawnElf) { // 精灵宝石位置索引列表 List elfIndexList = new List(); 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 elfWeightList = new List(); 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; } /// /// 随机购买Tower的入口,如果购买成功,则需要实时更新价格. /// 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); } /// /// 随机放置一个对手Tower. /// public Tower randomOpponentTower(bool allTower = true) { Tower newTower = GetRandomTower(true, !allTower); if (!newTower) throw new Exception("未能成功产生Tower"); RandomPlaceTower(newTower, true); return newTower; } /// /// 随机找一个空白位置放置塔防 /// /// /// 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); } } /// /// 在固定的位置,放置一个随机的塔防类型. /// /// /// 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; } }