using System;
using System.Collections;
using System.Collections.Generic;
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines;
using Common;
using DragonLi.Core;
using Mirror;
using UnityEngine;
using UnityEngine.PlayerLoop;
using XPlugin.Data.JsonLiteDB;
using static XPlugin.Data.JsonLiteDB.JsonLiteDB;
using LitJson;
using Pathfinding;
using DarkTonic.MasterAudio;
using NaughtyAttributes;
using UnityEngine.UIElements;
using Random = UnityEngine.Random;
///
/// 游戏状态
///
public enum GameState
{
None = 0,
Playing = 1,
///
/// 胜利
///
Victory = 2,
///
/// 失败
///
Failur = 3,
Settle=4,
///
/// 准备阶段
///
Wave=5,
}
public class GameManager : NetworkBehaviour
{
public static GameManager Ins { get; private set; }
#region 预制体
public GameObject DoorPre;
public GameObject gunPropPre;
public GameObject itemPropPre;
// 炮塔预制体集合
//public GameObject[] TowerPres;
// 怪物预制集合
public GameObject[] EnemyPres;
public GameObject explosionPre;
// 怪物ui预制体
public GameObject EnemyUIPre;
#endregion
// json数据库
private JsonLiteDB DB;
// 怪物信息集合
public Dictionary EnemyInfos = new Dictionary();
// 炮塔信息集合
public Dictionary> TowerInfos = new Dictionary>();
// 枪械信息集合
public Dictionary GunInfos = new Dictionary();
// 子弹信息集合
public Dictionary BulletInfos = new Dictionary();
// 防线信息
public List DefenseInfos = new List();
// 剧情信息
public Dictionary CombatUnitInfos = new Dictionary();
private List curGunPropList = new List();
public List curItemPropList = new List();
public Dictionary players = new Dictionary();
///
/// 敌人自增
///
private int enemyIndex = 0;
///
/// 所有敌人
///
public Dictionary EnemyList = new Dictionary();
///
/// 所有敌人UI
///
public Dictionary EnemyUIList = new Dictionary();
///
/// 炮塔自增
///
public int towerIndex = 0;
///
/// 所有炮塔
///
public Dictionary TowerList = new Dictionary();
public Dictionary> TowerList2 = new Dictionary>();
public Dictionary SettleInfos = new Dictionary();
[SyncVar]
public bool isStart;
///
/// 波次自增
///
[SyncVar]
public int roundIndex = 0;
// 游玩结束时间
[NonSerialized]
[SyncVar]
public long vistEnd = 0;
// 总游玩时长
private int vistAllTime = (int)(60*15);
[SyncVar]
public string settleData = "";
[SyncVar]
public GameState gameState = GameState.None;
[SoundGroup] public string JointIn;
[SoundGroup] public string roundSound;
public int roundWaveTime;
public int curRoundWaveTime;
void Awake()
{
Ins = this;
}
void Start()
{
if (isClient)
{
isStart = false;
CreateDoor();
}
}
///
/// 创建门
///
public void CreateDoor()
{
UpdateConf();
if(!isServer)
return;
GameObject door = Instantiate(DoorPre);
door.transform.position = GameLocal.Ins.doorPos.position.ReflectVectorXOZ();
NetworkServer.Spawn(door);
}
///
/// 创建初回合
///
public void CreateFirstRound()
{
RpcShowHUD();
roundIndex = 0;
roundWaveTime = 15;
curRoundWaveTime = 12;
SetGameState(GameState.Wave);
RpcMessageRound();
}
///
/// 创建下一回合
///
public void CreateNextRound()
{
roundIndex++;
SetGameState(GameState.Wave);
roundWaveTime = 15;
curRoundWaveTime = 12;
RpcMessageRound();
}
[Server]
public void GameStart()
{
gameState = GameState.Playing;
vistEnd = (long)(DateTime.Now.Subtract(new DateTime(1970, 1, 1))).TotalSeconds + vistAllTime;
isStart = true;
ChangeBgmRpc(1);
// CreateTowers();
AstarPath.active.Scan();
// CreateFirstRound();
CreateFirstRound();
// 延迟1s后给所有人发放武器
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
GivePistol();
}, 1f);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
GameOver(GameState.Settle);
}, 60f * 15f);
}
[ClientRpc]
public void GivePistol()
{
Debug.Log("创建武器中...");
GameLocal.Ins.self.PickUpGun(GunType.Pistol, -999);
}
[Server]
public void SetGameState(GameState state)
{
gameState = state;
}
//1.游戏时间到
//2.所有怪物被消灭
//3.玩家被消灭
//以上都要跳出结算
[Server]
public void GameOver(GameState state)
{
RpcShow();
DamageAllEnemy();
gameState = state;
isStart = false;
// gameState = state;
foreach (string key in SettleInfos.Keys)
{
string[] titles = { "初露锋芒", "小菜一碟", "熟手", "痛并快乐着", "不死传说"
,"最强守护者", "独孤求败", "佛系玩家", "午时已到", "神枪手", "弹无虚发", "团队护盾", "我叫MT", "钢铁之躯","道具大师","行走的仓库","永不停歇" };
SetTitle(key, titles[Random.Range(0, titles.Length)]);
SetPlayerName(key);
}
string jsonStr = JsonMapper.ToJson(SettleInfos);
settleData = jsonStr;
// //结算页面
// RpcShow();
// if (blueScore >= redScore)
// {
// RpcShowWin(true);
// }
// else
// {
// RpcShowWin(false);
// }
}
[ClientRpc]
public void RpcShowWin(bool isBlue)
{
}
[ClientRpc]
public void RpcShow()
{
SettlePanel.Show();
}
///
/// 下一波进攻开始
///
[Server]
public void RpcMessageRound()
{
if(!isStart)
return;
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
if(!isStart)
return;
ShowHudRoundTime();
}, curRoundWaveTime);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
if(!isStart)
return;
DesGunProList();
GetRoundEnemy();
PlaySound2DRPC(roundSound);
SetGameState(GameState.Playing);
}, roundWaveTime);
}
[ClientRpc]
public void ShowHudRoundTime()
{
DragonLi.Core.EventDispatcher.TriggerEvent("NewWaveStart", roundIndex);
}
[ClientRpc]
public void ChangeBgmRpc(int i)
{
GameLocal.Ins.BGMState.StateChange(i);
}
public int curRoundEnemyCount;
///
/// 创建敌方单位
///
IEnumerator CreateEnemy(CombatUnitInfo info)
{
curRoundEnemyCount = info.EnemyTypeList.Length;
for (int i = 0; i < info.EnemyTypeList.Length; i++)
{
GameObject enemy = Instantiate(EnemyPres[info.EnemyTypeList[i]]);
NetworkServer.Spawn(enemy);
int posId = Random.Range(0, 4);
int posX=Random.Range(-1, 1);
int posZ=Random.Range(-1, 1);
enemy.transform.position = GameLocal.Ins.enemyStartPos[posId].position+new Vector3(posX,0,posZ);
enemy.transform.eulerAngles = new Vector3(0, 0, 0);
enemyIndex++;
Enemy enemyScript = enemy.GetComponent();
enemyScript.OnSpawn(enemyIndex, (EnemyType)info.EnemyTypeList[i], 1);
EnemyList.Add(enemyIndex, enemyScript);
yield return new WaitForSeconds(info.BornTime);
}
CloseWu();
}
[ClientRpc]
public void CloseWu()
{
GameLocal.Ins.CloseWu();
}
public void CreateBoss()
{
GameObject enemy = Instantiate(EnemyPres[(int)EnemyType.ZombieBoss]);
NetworkServer.Spawn(enemy);
int posId = Random.Range(0, 4);
int posX=Random.Range(-1, 1);
int posZ=Random.Range(-1, 1);
enemy.transform.position = GameLocal.Ins.enemyStartPos[posId].position+new Vector3(posX,0,posZ);
enemy.transform.eulerAngles = new Vector3(0, 0, 0);
enemyIndex++;
Enemy enemyScript = enemy.GetComponent();
enemyScript.OnSpawn(enemyIndex, EnemyType.ZombieBoss, 1);
EnemyList.Add(enemyIndex, enemyScript);
curRoundEnemyCount++;
}
public void CreateExplosion(Transform pos)
{
if(!isServer)
return;
var ex= Instantiate(explosionPre, pos.position, Quaternion.identity);
NetworkServer.Spawn(ex);
ex.GetComponent().Init(0);
}
[SyncVar]
public int gunProp1;
[SyncVar]
public int gunProp2;
[Server]
public void CreateGunProp()
{
if(!isStart)
return;
List numbers = new List() { 1, 2, 3, 4, 5 };
gunProp1 = numbers[Random.Range(0, numbers.Count)];
numbers.Remove(gunProp1);
gunProp2 = numbers[Random.Range(0, numbers.Count)];
var gun1= Instantiate(gunPropPre, GameLocal.Ins.gunPropPos[0]);
NetworkServer.Spawn(gun1);
gun1.GetComponent().Init((GunType)gunProp1);
curGunPropList.Add(gun1);
var gun2= Instantiate(gunPropPre, GameLocal.Ins.gunPropPos[1]);
NetworkServer.Spawn(gun2);
gun2.GetComponent().Init((GunType)gunProp2);
curGunPropList.Add(gun2);
}
public void CreateItemProp(Transform pos)
{
if(!isStart)
return;
var item= Instantiate(itemPropPre);
NetworkServer.Spawn(item);
item.transform.position=new Vector3(pos.position.x,0.5f,pos.position.z);
item.GetComponent().SetItemProp(ItemPropType.Hp);
curItemPropList.Add(item);
}
///
///删除枪械
///
public void DesGunProList()
{
if(curGunPropList.Count<=0)
return;
NetworkServer.Destroy(curGunPropList[1]);
NetworkServer.Destroy(curGunPropList[0]);
curGunPropList.Clear();
}
public void DesItemProp(GameObject item)
{
if(curItemPropList.Count<=0)
return;
item.GetComponent().isDeal = true;
curItemPropList.Remove(item);
NetworkServer.Destroy(item);
}
public List GetRoundEnemy()
{
List curEnemyList = new List();
if (roundIndex <= 6)
{
var combatUnitInfo = CombatUnitInfos[roundIndex];
StartCoroutine(CreateEnemy(combatUnitInfo));
}
else
{
int curId = roundIndex;
CombatUnitInfo info = new CombatUnitInfo(curId, curId, GenerateMonsterTypes(), 1);
StartCoroutine(CreateEnemy(info));
}
if (roundIndex % 5 == 0&&roundIndex!=0)
{
CreateBoss();
}
return curEnemyList;
}
public int[] GenerateMonsterTypes()
{
int[] weights = { 2, 6, 1, 3 };
List monsterTypes = new List();
int totalWeight = 0;
int targetWeight = Random.Range(24, 27);// * players.Count; // 24-26
int targetCount = Random.Range(6, 10);// * players.Count; // 4-7
//if (targetCount > 15)
//{
// targetCount = 15;
// targetCount = 15;
//}
// 随机添加怪物直到接近目标
while (monsterTypes.Count < targetCount && totalWeight < targetWeight)
{
int index = GetRandomMonsterIndex(weights);
int weight = weights[index];
// 如果剩余位置不够,跳出
if (monsterTypes.Count == targetCount)
break;
// 如果加上这个怪物不会超过目标权重,添加
if (totalWeight + weight <= targetWeight)
{
monsterTypes.Add(index);
totalWeight += weight;
}
else
{
break;
}
}
// 如果权重还没达到目标,填充最小权重怪物
while (totalWeight < targetWeight && monsterTypes.Count < targetCount)
{
int minIndex = GetMinWeightIndex(weights);
monsterTypes.Add(minIndex);
totalWeight += weights[minIndex];
}
return monsterTypes.ToArray();
}
// 根据权重随机选择怪物
private int GetRandomMonsterIndex(int[] weights)
{
int sumWeight = 0;
foreach (var w in weights) sumWeight += w;
int randomValue = Random.Range(0, sumWeight);
int currentSum = 0;
for (int i = 0; i < weights.Length; i++)
{
currentSum += weights[i];
if (randomValue < currentSum)
return i;
}
return 0;
}
// 获取最小权重怪物的索引
private int GetMinWeightIndex(int[] weights)
{
int minIndex = 0;
for (int i = 1; i < weights.Length; i++)
{
if (weights[i] < weights[minIndex])
minIndex = i;
}
return minIndex;
}
///
/// 删除敌方单位
///
[Server]
public void DeleteEnemy(int id,Transform pos)
{
GameObject enemy = EnemyList[id].gameObject;
// int hpItemPropIndex = 101;//道具爆率
// int randomItemPropIndex = Random.Range(1, 101);
//
// if(randomItemPropIndex
/// 痛击场上所有敌方单位
///
[Command(requiresAuthority = false)]
public void DamageAllEnemy()
{
foreach (Enemy enemy in EnemyList.Values)
{
enemy.ApplyDamage(999999, null, null);
}
}
///
/// 更新配置表
///
public void UpdateConf()
{
string text = Resources.Load("Data").text;
if (text != null)
{
ParseGameJson(text);
}
}
public void ParseGameJson(string text)
{
DB = new JsonLiteDB();
DB.Load(text);
roundWaveTime = 15;
curRoundWaveTime = 12;
TableReader infoReader = DB["EnemysInfo"].GetReader();
EnemyInfos.Clear();
while (infoReader.Read())
{
EnemyInfo info = new EnemyInfo(infoReader);
EnemyInfos.Add((EnemyType)info.Type,info);
}
infoReader = DB["TowersInfo"].GetReader();
while (infoReader.Read())
{
TowerInfo info = new TowerInfo(infoReader);
TowerInfos.TryGetValue((TowerType)info.Type, out Dictionary infoList);
if (infoList == null)
{
Dictionary list = new Dictionary();
list.Add(info.Lvl, info);
TowerInfos.Add((TowerType)info.Type, list);
}
else
{
infoList.Add(info.Lvl, info);
}
}
infoReader = DB["GunsInfo"].GetReader();
GunInfos.Clear();
while (infoReader.Read())
{
GunInfo info = new GunInfo(infoReader);
GunInfos.Add((GunType)info.Type,info);
}
infoReader = DB["BulletsInfo"].GetReader();
BulletInfos.Clear();
while (infoReader.Read())
{
BulletInfo info = new BulletInfo(infoReader);
BulletInfos.Add((BulletType)info.Type,info);
}
infoReader = DB["DefensesInfo"].GetReader();
while (infoReader.Read())
{
DefenseInfo info = new DefenseInfo(infoReader);
DefenseInfos.Add(info);
}
infoReader = DB["StoryProgressInfo"].GetReader();
while (infoReader.Read())
{
CombatUnitInfo info = new CombatUnitInfo(infoReader);
CombatUnitInfos.Add(info.Belong,info);
CombatUnitInfos.TryGetValue(info.Belong, out info);
}
Debug.Log("游戏数值更新 -> complete");
}
///
/// 获取范围内敌人
///
public int GetRangeEnemyId(Vector3 pos, float radius)
{
int res = -1;
foreach (Enemy enemy in EnemyList.Values)
{
float dis = Vector3.Distance(enemy.transform.position, pos);
if (dis <= radius)
{
radius = dis;
res = enemy.id;
break;
}
}
return res;
}
///
/// 获取最近的玩家
///
///
public GameObject GetPlayer()
{
if (players == null || players.Count == 0)
return null;
GameObject nearestPlayer = null;
float minDistance = float.MaxValue;
foreach (var player in players.Values)
{
if (player == null) continue;
// 计算XZ平面距离(使用你的 ReflectVectorXOZ 方法)
float dis = Vector3.Distance(
player.transform.position.ReflectVectorXOZ(),
transform.position.ReflectVectorXOZ()
);
if (dis < minDistance)
{
minDistance = dis;
nearestPlayer = player.gameObject;
}
}
return nearestPlayer;
}
[Server]
public void CreateEnemyUI(Enemy enemy)
{
GameObject enemyUI = Instantiate(EnemyUIPre);
NetworkServer.Spawn(enemyUI);
EnemyUI enemyUIScript = enemyUI.GetComponent();
enemyUIScript.Init(enemy);
EnemyUIList.Add(enemy.id, enemyUIScript);
}
[Server]
public void DeleteEnemyUI(int id)
{
GameObject enemyUI = EnemyUIList[id].gameObject;
EnemyUIList.Remove(id);
NetworkServer.Destroy(enemyUI);
}
[ClientRpc]
public void RpcShowHUD()
{
HUDPanel.Show();
}
#region 空投道具
///
/// 修复炮塔
///
public void RepairTower()
{
}
///
/// 进入联控
///
[Server]
public void JoinControlTower(int playerIndex)
{
PlayJointMusic();
// 修改所有炮塔模式
foreach (Tower tower in TowerList.Values)
{
if (tower.controllerId == -1)
{
tower.controllerId = playerIndex;
tower.mode = TowerMode.Joint;
}
}
TriggerEvent("JoinControlStart", playerIndex);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
ChangeBgmRpc(1);
foreach (Tower tower in TowerList.Values)
{
if (tower.mode == TowerMode.Joint)
{
tower.controllerId = playerIndex;
tower.mode = tower.originalMode;
}
TriggerEvent("JoinControlEnd", playerIndex);
}
}, 30f);
}
#endregion
[ClientRpc]
public void TriggerEvent(string key, int param)
{
DragonLi.Core.EventDispatcher.TriggerEvent(key, param);
}
public void AddScore(string index, int damage)
{
if (SettleInfos.ContainsKey(index))
{
SettleInfos[index].Score += damage;
}
string jsonStr = JsonMapper.ToJson(SettleInfos);
settleData = jsonStr;
}
public void SetTitle(string index, string title)
{
if (SettleInfos.ContainsKey(index))
{
SettleInfos[index].Title = title;
}
Debug.Log(SettleInfos);
}
public void SetPlayerName(string index)
{
if (SettleInfos.ContainsKey(index))
{
SettleInfos[index].playerName = int.Parse(index);
}
}
[Server]
public void AddData(int playerIndex)
{
SettleInfos.Add(playerIndex.ToString(), new SettleInfo());
}
public string SerializeSettleInfos()
{
return JsonUtility.ToJson(SettleInfos);
}
#region 工具
public string GetLessTimeStr()
{
string res = "";
if (isStart)
{
res = FormatTime((int)(vistEnd - DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds));
}
return res;
}
public int GetLessTimeSeconds()
{
return (int)(vistEnd - DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds);
}
// 时分秒
public string FormatTime(int totalSeconds)
{
int hours = totalSeconds / 3600;
// string hh = hours < 10 ? "0" + hours : hours.ToString();
int minutes = (totalSeconds - hours * 3600) / 60;
string mm = minutes < 10f ? "0" + minutes : minutes.ToString();
int seconds = totalSeconds - hours * 3600 - minutes * 60;
string ss = seconds < 10 ? "0" + seconds : seconds.ToString();
return string.Format("{0}:{1}", mm, ss);
}
#endregion
public void PlaySound2DRPC(string sound)
{
MasterAudio.PlaySound(sound);
}
[ClientRpc]
public void PlaySound3DRPC(string sound,Transform tran,bool isStop)
{
if(isStop)
MasterAudio.StopAllSoundsOfTransform(tran);
MasterAudio.PlaySound3DAtTransform(sound, tran);
}
public void PlayJointMusic()
{
MasterAudio.PlaySound(JointIn);
GameLocal.Ins.BGMState.StateChange(2);
}
}