GameManager.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. using cfg;
  2. using SimpleJSON;
  3. using Sirenix.OdinInspector;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.IO;
  7. using TMPro;
  8. using UnityEngine;
  9. using UnityEngine.UI;
  10. public enum AttributeTag
  11. {
  12. [LabelText("飞行")] Flying = 1,
  13. [LabelText("风")] Wind = 2,
  14. [LabelText("水")] Water = 3,
  15. [LabelText("岩")] Earth = 4,
  16. [LabelText("地面")] Ground = 5,
  17. [LabelText("雷")] Lightning = 6,
  18. [LabelText("火")] Fire = 7,
  19. [LabelText("木")] Nature = 8,
  20. }
  21. public enum SoldierType
  22. {
  23. Conduct,
  24. [LabelText("飞剑")] sword = 0,
  25. [LabelText("胖子")] shield = 1,
  26. [LabelText("林冲")] spear = 2,
  27. [LabelText("阴灵")] Spirits = 3,
  28. }
  29. public enum GameType
  30. {
  31. Gaming,
  32. GameEnd,
  33. Shop,
  34. }
  35. public enum TargetType
  36. {
  37. None = 0,
  38. Demonic = 1,
  39. Tower = 2,
  40. Player = 3,
  41. Enemy = 4,
  42. EnemyTower = 5,
  43. Boss = 6,
  44. Portal = 7,
  45. }
  46. public class GameManager : MonoBehaviour
  47. {
  48. public static GameManager instance;
  49. [FoldoutGroup("组件", order: -1)] public UIHP p1uiHP;
  50. [FoldoutGroup("组件")] public UIHP p1uiMP;
  51. [FoldoutGroup("组件")] public Transform p1uiRush;
  52. [FoldoutGroup("组件")] public GameObject[] demonicNum;
  53. [FoldoutGroup("组件")] public TextMeshProUGUI text;
  54. [FoldoutGroup("组件")] public GameObject chapterBG; //当前关卡的原始背景(用于和boss背景做替换)
  55. [FoldoutGroup("组件")] public GameObject shopButton;
  56. [FoldoutGroup("组件")] public ShopUI shopUI;
  57. [FoldoutGroup("组件")] public TextMeshProUGUI moneyText;
  58. [FoldoutGroup("金币结算", order: -1)][LabelText("限制时间")] public int rewardTime;
  59. [FoldoutGroup("金币结算")][LabelText("金币奖励")] public int totalMoney;
  60. [FoldoutGroup("金币结算")][LabelText("额外金币奖励")] public int extraMoney;
  61. [FoldoutGroup("金币结算")][LabelText("惩罚时间间隔")] public int deductMoneyTime;
  62. [FoldoutGroup("金币结算")][LabelText("每次惩罚扣除金币数量")] public int deductMoney;
  63. [Header("金币掉落")]
  64. [FoldoutGroup("金币结算")][LabelText("怪物掉落金币数量")] public int enemyGoldDrop;
  65. [FoldoutGroup("金币结算")][LabelText("金币掉落特效")] public GameObject dropGoldFX;
  66. [FoldoutGroup("金币结算")][LabelText("金币掉落字体")] public GameObject dropGoldText;
  67. [FoldoutGroup("标签")]
  68. [FoldoutGroup("标签/火")] [LabelText("是否启用")] public bool isFireEnable = false;
  69. [FoldoutGroup("标签/火")] [LabelText("触发概率")] [PropertyRange(0, 100)] public int fireProbability = 100;
  70. [FoldoutGroup("标签/火")] [LabelText("伤害占总生命百分比")] [PropertyRange(0, 1)] public float fireDamageRadio = 0.01f;
  71. [FoldoutGroup("标签/冰")] [LabelText("是否启用")] public bool isIceEnable = false;
  72. [FoldoutGroup("标签/冰")] [LabelText("触发概率")] [PropertyRange(0, 100)] public int iceProbability = 100;
  73. [FoldoutGroup("标签/冰")] [LabelText("冰冻时间")] public float frozenTime = 3;
  74. [FoldoutGroup("标签/雷")] [LabelText("是否启用")] public bool isThunderEnable = false;
  75. [FoldoutGroup("标签/雷")] [LabelText("触发概率")] [PropertyRange(0, 100)] public int thunderProbability = 100;
  76. [FoldoutGroup("标签/雷")] [LabelText("感电移速比值")] [PropertyRange(0, 1)] public float moveSpeedScale = 0.6f;
  77. [FoldoutGroup("标签/雷")] [LabelText("感电攻速比值")] [PropertyRange(0, 1)] public float attackSpeedScale = 0.6f;
  78. [FoldoutGroup("标签/雷")] [LabelText("伤害")] public int thunderDamage =3;
  79. [FoldoutGroup("标签/风")] [LabelText("是否启用")] public bool isWindEnable = false;
  80. [FoldoutGroup("标签/风")] [LabelText("触发概率")] [PropertyRange(0, 100)] public int windProbability = 100;
  81. [FoldoutGroup("标签/风")] [LabelText("削减体重比值")] [PropertyRange(0, 1)] public float weightReductionratio = 0.1f;
  82. [FoldoutGroup("标签/风")] [LabelText("伤害")] public int windDamage = 3;
  83. [FoldoutGroup("标签/木")] [LabelText("是否启用")] public bool isWoodEnable = false;
  84. [FoldoutGroup("标签/木")] [LabelText("触发概率")] [PropertyRange(0, 100)] public int woodProbability = 100;
  85. [FoldoutGroup("标签/岩")] [LabelText("是否启用")] public bool isRockEnable = false;
  86. [FoldoutGroup("标签/岩")] [LabelText("触发概率")] [PropertyRange(0, 100)] public int rockProbability = 100;
  87. [FoldoutGroup("标签/岩")] [LabelText("石像生命值占总生命比值")] public float stoneHpRadio = 1;
  88. [FoldoutGroup("标签/天")] [LabelText("是否启用")] public bool isSkyEnable = false;
  89. [FoldoutGroup("标签/天")] [LabelText("触发概率")] [PropertyRange(0, 100)] public int skyProbability = 100;
  90. [FoldoutGroup("标签/地")] [LabelText("是否启用")] public bool isGroundEnable = false;
  91. [FoldoutGroup("标签/地")] [LabelText("触发概率")] [PropertyRange(0, 100)] public int groundProbability = 100;
  92. [FoldoutGroup("标签/地")] [LabelText("复活时间")] [PropertyRange(0, 100)] public float resurrectionTime = 3;
  93. [FoldoutGroup("标签/地")] [LabelText("魂骸血量")] [PropertyRange(0, 100)] public int deadHp = 20;
  94. [Header("商店刷新")]
  95. [ValidateInput("CheckTagWeight","标签池子概率总和不是100%")]
  96. [FoldoutGroup("Rogue")] [LabelText("标签池子比重(%)")] [Tooltip("最高标签池;标签池;公共池")] public List<float> tagWeight;
  97. public static readonly Dictionary<string, TargetType> TagToTargetTypeMap = new Dictionary<string, TargetType>(StringComparer.Ordinal);
  98. public bool CheckTagWeight(List<float> weights)
  99. {
  100. float num = 0;
  101. for(int i = 0; i < 3; i++)
  102. {
  103. num += weights[i];
  104. }
  105. if(num == 100)
  106. {
  107. return true;
  108. }
  109. else
  110. {
  111. return false;
  112. }
  113. }
  114. [FoldoutGroup("Rogue")] [LabelText("第几关开始出现(%)")] public List<int> unlockLevel;
  115. [FoldoutGroup("Rogue")] [LabelText("基础几率(%)")] public List<float> baseChance;
  116. [FoldoutGroup("Rogue")] [LabelText("每关增加的几率(%)")] public List<float> chanceIncreasePerLevel;
  117. [FoldoutGroup("Rogue")] [LabelText("最大几率(%)")] public List<float> maximumChance ;
  118. [FoldoutGroup("Rogue")] public List<List<List<SingleTreasureConfig>>> treasuresList;
  119. [FoldoutGroup("Rogue")] [DisplayOnly] public List<float> trueRefreshChance;
  120. [FoldoutGroup("Rogue")] [HideInInspector] public List<float> refreshChance;
  121. [Header("数值加成")]
  122. [FoldoutGroup("Rogue")] [LabelText("伤害")] public int damage;
  123. [FoldoutGroup("Rogue")] [LabelText("暴击率")] public int criticalChance;
  124. [FoldoutGroup("Rogue")] [LabelText("回血")] public int regeneration;
  125. [FoldoutGroup("Rogue")] [LabelText("吸血")] public int lifesteal;
  126. [FoldoutGroup("Rogue")] [LabelText("护甲")] public int armor;
  127. [FoldoutGroup("Rogue")] [LabelText("闪避")] public int dodge;
  128. [FoldoutGroup("Rogue")] [LabelText("血量上限")] public int totalHp;
  129. [FoldoutGroup("Rogue")] [LabelText("金币获得增加")] public int increasedGoldGain;
  130. [FoldoutGroup("Rogue")] [LabelText("经验获得增加")] public int increasedEXPGain;
  131. [FoldoutGroup("Rogue")] [LabelText("冲刺次数")] public int dashCharges;
  132. [FoldoutGroup("Rogue")] [LabelText("蓝量")] public int totalMp;
  133. [FoldoutGroup("Rogue")] [LabelText("回蓝速度")] public int mpRegen;
  134. public LeveType leveType;
  135. [LabelText("下一关倍率增幅")] public List<float> ratioIncrease = new List<float> { 0.4f, 1.6f, -0.8f };
  136. public int nowLevel;
  137. public int money;
  138. public List<Treasure> myTreasures;
  139. public List<int> myTreasuresTag;
  140. public int maxTreasuresTag;
  141. public float gameTime;
  142. public float totalGameTime;
  143. public Tables allCfgData;
  144. static public SoldierType[] curSoldiers; //本局游戏选择的三个士兵
  145. public List<CreateEnemyConfig> createEnemyConfigs;
  146. [DisplayOnly] public GameType gameType;
  147. [DisplayOnly] public float levelRatio = 1;
  148. private JSONNode Loader(string fileName)
  149. {
  150. return JSON.Parse(File.ReadAllText("GenerateDatas/json/" + fileName + ".json"));
  151. }
  152. public void GetAllExcel()
  153. {
  154. allCfgData = new Tables(Loader);
  155. }
  156. public void ReloadCfgCreateEnemyData()
  157. {
  158. createEnemyConfigs = new List<CreateEnemyConfig>(); ;
  159. for (int i = 0; i < 9; i++)
  160. {
  161. JSONNode keyValuePairs = JSON.Parse(File.ReadAllText($"GenerateDatas/json/CfgCreateEnemy{i}.json"));
  162. CreateEnemyConfig createEnemyConfig = new CreateEnemyConfig(keyValuePairs);
  163. createEnemyConfigs.Add(createEnemyConfig);
  164. }
  165. }
  166. private void Awake()
  167. {
  168. //选定本局游戏有哪些士兵,后面兵多了这里要改
  169. curSoldiers = new SoldierType[3];
  170. curSoldiers[0] = SoldierType.sword;
  171. curSoldiers[1] = SoldierType.shield;
  172. curSoldiers[2] = SoldierType.spear;
  173. if (!instance)
  174. {
  175. instance = this;
  176. GetAllExcel();
  177. ReloadCfgCreateEnemyData();
  178. }
  179. else
  180. {
  181. DestroyImmediate(gameObject);
  182. return;
  183. }
  184. leveType = LeveType.Introduction;
  185. myTreasures = new List<Treasure>();
  186. treasuresList = new List<List<List<SingleTreasureConfig>>>();
  187. refreshChance = new List<float>();
  188. for (int i = 0; i < 4; i++)
  189. {
  190. treasuresList.Add(new List<List<SingleTreasureConfig>>());
  191. refreshChance.Add(baseChance[i]);
  192. for(int j = 0; j < 9; j++)
  193. {
  194. treasuresList[i].Add(new List<SingleTreasureConfig>());
  195. }
  196. }
  197. trueRefreshChance = new List<float>();
  198. for (int i = 0; i < 3; i++)
  199. {
  200. trueRefreshChance.Add(refreshChance[i] - refreshChance[i + 1]);
  201. }
  202. trueRefreshChance.Add(refreshChance[3]);
  203. List<SingleTreasureConfig> cfgTreasureList = allCfgData.CfgTreasure.DataList;
  204. for(int i = 0;i< cfgTreasureList.Count; i++)
  205. {
  206. SingleTreasureConfig singleTreasureConfig = cfgTreasureList[i];
  207. treasuresList[singleTreasureConfig.Quality][0].Add(singleTreasureConfig);
  208. for(int j = 0; j < singleTreasureConfig.Tag.Count;j++)
  209. {
  210. treasuresList[singleTreasureConfig.Quality][singleTreasureConfig.Tag[j]].Add(singleTreasureConfig);
  211. }
  212. }
  213. maxTreasuresTag = -1;
  214. nowLevel = 1;
  215. foreach (TargetType type in Enum.GetValues(typeof(TargetType)))
  216. {
  217. string tagName = type.ToString();
  218. if (!string.IsNullOrEmpty(tagName))
  219. {
  220. TagToTargetTypeMap[tagName] = type;
  221. }
  222. }
  223. }
  224. private void Start()
  225. {
  226. gameTime = 0;
  227. gameType = GameType.Gaming;
  228. }
  229. private void FixedUpdate()
  230. {
  231. if (gameType == GameType.Gaming)
  232. {
  233. gameTime += Time.deltaTime;
  234. totalGameTime += Time.deltaTime;
  235. EnemyCreater.instance.OnGameTimeChange(gameTime);
  236. int timeText = (int)gameTime;
  237. //text.text = $"{timeText / 60:D2}:{timeText % 60:D2}({timeText}s)";
  238. text.text = $"{timeText}";
  239. }
  240. }
  241. //游戏结束
  242. public void GameEnd()
  243. {
  244. gameType = GameType.GameEnd;
  245. int dropGold = 0;
  246. foreach (List<Enemy> objs in EnemyCreater.instance.enemyDic.Values)
  247. {
  248. for (int i = 0; i < objs.Count; i++)
  249. {
  250. if (objs[i].gameObject.activeSelf)
  251. {
  252. objs[i].killer = null;
  253. objs[i].ChangeState(CharacterState.Die);
  254. dropGold += enemyGoldDrop;
  255. }
  256. }
  257. }
  258. if (leveType == LeveType.Boss)
  259. {
  260. return;
  261. }
  262. AddMoney(dropGold);
  263. shopButton.SetActive(true);
  264. }
  265. public void AddMoney(int enemyDrop)
  266. {
  267. int addMoney;
  268. if(gameTime < rewardTime)
  269. {
  270. addMoney = totalMoney + extraMoney;
  271. }
  272. else
  273. {
  274. int extraTime = (int)gameTime - rewardTime;
  275. addMoney = Mathf.Clamp(totalMoney - (extraTime / deductMoneyTime) * deductMoney, 0, totalMoney);
  276. }
  277. addMoney += enemyDrop;
  278. money += Mathf.RoundToInt(addMoney * (1 + increasedGoldGain / 100f));
  279. moneyText.text = $"{money}";
  280. }
  281. //下一关
  282. public void NextLevel()
  283. {
  284. shopButton.SetActive(false);
  285. if(nowLevel - 1 < ratioIncrease.Count)
  286. {
  287. levelRatio += ratioIncrease[nowLevel - 1];
  288. }
  289. switch (leveType)
  290. {
  291. case LeveType.Introduction:
  292. EnemyCreater.instance.GetLevelOrientation(0);
  293. leveType = LeveType.Development;
  294. break;
  295. case LeveType.Development:
  296. EnemyCreater.instance.GetLevelOrientation(1);
  297. leveType = LeveType.Transition;
  298. break;
  299. case LeveType.Transition:
  300. leveType = LeveType.Conclusion;
  301. break;
  302. case LeveType.Conclusion:
  303. leveType = LeveType.Boss;
  304. break;
  305. }
  306. PlayersInput.instance[0].PlayerRevive();
  307. foreach(List<GameObject> objs in PoolManager.instance.activeObjs.Values)
  308. {
  309. List<GameObject> newObjs = new List<GameObject>(objs);
  310. for(int i = 0; i < newObjs.Count; i++)
  311. {
  312. newObjs[i].gameObject.SetActive(false);
  313. }
  314. }
  315. for(int i = 0; i < 3; i++)
  316. {
  317. demonicNum[i].GetComponentInChildren<TextMeshProUGUI>().text = "0";
  318. }
  319. EnemyCreater.instance.Init();
  320. LevelSelect.instance.ChangeText();
  321. gameTime = 0;
  322. gameType = GameType.Gaming;
  323. nowLevel += 1;
  324. ChangeRogueChance();
  325. }
  326. public void ShowShop()
  327. {
  328. gameType = GameType.Shop;
  329. shopUI.Init();
  330. GameUI.instance.gameObject.SetActive(false);
  331. }
  332. public void GetTreasure(Treasure treasure)
  333. {
  334. PlayerController player = PlayersInput.instance[0];
  335. for (int i = 0; i < treasure.type.Count; i++)
  336. {
  337. float data = treasure.data[i];
  338. switch (treasure.type[i])
  339. {
  340. case "伤害":
  341. damage += (int)data;
  342. break;
  343. case "暴击率":
  344. criticalChance += (int)data;
  345. break;
  346. case "回血":
  347. regeneration += (int)data;
  348. break;
  349. case "吸血":
  350. lifesteal += (int)data;
  351. break;
  352. case "护甲":
  353. armor += (int)data;
  354. break;
  355. case "闪避":
  356. dodge += (int)data;
  357. break;
  358. case "血量上限":
  359. totalHp += (int)data;
  360. break;
  361. case "金币获得增加":
  362. increasedGoldGain += (int)data;
  363. break;
  364. case "经验获得增加":
  365. increasedEXPGain += (int)data;
  366. break;
  367. case "冲刺次数":
  368. dashCharges += (int)data;
  369. player.rushChargeTotalNums += (int)data;
  370. player.rushChargeNums = player.rushChargeTotalNums;
  371. for (int j = 0; j < player.rushChargeTotalNums; j++)
  372. {
  373. if (player.uiRush.childCount <= j)
  374. {
  375. Transform rushUIchid = Instantiate(player.uiRush.GetChild(0), player.uiRush);
  376. rushUIchid.localPosition = player.uiRush.GetChild(0).transform.localPosition + Vector3.right * 50 * j;
  377. }
  378. UIController.ChangeImageFill(player.uiRush.GetChild(j).GetComponent<Image>(), 1);
  379. }
  380. break;
  381. case "蓝量":
  382. totalMp += (int)data;
  383. player.totalMp += (int)data;
  384. player.mp = player.totalMp;
  385. player.uiMp.Show(player.mp, player.totalMp);
  386. break;
  387. case "回蓝速度":
  388. mpRegen += (int)data;
  389. player.mpReplySpeed += (int)data;
  390. break;
  391. default:
  392. Debug.LogError($"宝物配置出错,不存在词条【{treasure.type[i]}】");
  393. break;
  394. }
  395. }
  396. }
  397. public void ChangeRogueChance()
  398. {
  399. for(int i = 0; i < 4; i++)
  400. {
  401. if(nowLevel >= unlockLevel[i])
  402. {
  403. refreshChance[i] += chanceIncreasePerLevel[i];
  404. if(refreshChance[i] > maximumChance[i])
  405. {
  406. refreshChance[i] = maximumChance[i];
  407. }
  408. }
  409. }
  410. for (int i = 0; i < 3; i++)
  411. {
  412. trueRefreshChance.Add(refreshChance[i] - refreshChance[i + 1]);
  413. }
  414. trueRefreshChance.Add(refreshChance[3]);
  415. }
  416. }