654 lines
17 KiB
C#
654 lines
17 KiB
C#
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;
|
|
|
|
|
|
/// <summary>
|
|
/// 游戏状态
|
|
/// </summary>
|
|
public enum GameState
|
|
{
|
|
None = 0,
|
|
Playing = 1,
|
|
/// <summary>
|
|
/// 胜利
|
|
/// </summary>
|
|
Victory = 2,
|
|
/// <summary>
|
|
/// 失败
|
|
/// </summary>
|
|
Failur = 3,
|
|
Settle,
|
|
Waiting= 5,
|
|
}
|
|
|
|
public class GameManager : NetworkBehaviour
|
|
{
|
|
public static GameManager Ins { get; private set; }
|
|
|
|
#region 预制体
|
|
public GameObject redDoorPre;
|
|
public GameObject blueDoorPre;
|
|
public GameObject AirdropPlanePre;//空投飞机
|
|
public GameObject[] airdropItems;//空头道具
|
|
|
|
public GameObject startGameItemPre;
|
|
|
|
// 怪物预制集合
|
|
public GameObject[] EnemyPres;
|
|
// 怪物ui预制体
|
|
public GameObject EnemyUIPre;
|
|
|
|
#endregion
|
|
|
|
#region 实例化后物体
|
|
|
|
public GameObject redDoor;
|
|
public GameObject blueDoor;
|
|
|
|
#endregion
|
|
|
|
// json数据库
|
|
private JsonLiteDB DB;
|
|
// 怪物信息集合
|
|
public Dictionary<EnemyType, Dictionary<int, EnemyInfo>> EnemyInfos = new Dictionary<EnemyType, Dictionary<int, EnemyInfo>>();
|
|
// 炮塔信息集合
|
|
public Dictionary<TowerType, Dictionary<int, TowerInfo>> TowerInfos = new Dictionary<TowerType, Dictionary<int, TowerInfo>>();
|
|
// 枪械信息集合
|
|
public Dictionary<GunType, Dictionary<int, GunInfo>> GunInfos = new Dictionary<GunType, Dictionary<int, GunInfo>>();
|
|
// 子弹信息集合
|
|
public Dictionary<BulletType, Dictionary<int, BulletInfo>> BulletInfos = new Dictionary<BulletType, Dictionary<int, BulletInfo>>();
|
|
// 剧情信息
|
|
public Dictionary<int, List<CombatUnitInfo>> CombatUnitInfos = new Dictionary<int, List<CombatUnitInfo>>();
|
|
/// <summary>
|
|
/// 敌人自增
|
|
/// </summary>
|
|
private int enemyIndex = 0;
|
|
|
|
/// <summary>
|
|
/// 所有敌人
|
|
/// </summary>
|
|
public Dictionary<int, Enemy> EnemyList = new Dictionary<int, Enemy>();
|
|
|
|
/// <summary>
|
|
/// 所有敌人UI
|
|
/// </summary>
|
|
public Dictionary<int, PlayerUI> EnemyUIList = new Dictionary<int, PlayerUI>();
|
|
|
|
public Dictionary<string, SettleInfo> SettleInfos = new Dictionary<string, SettleInfo>();
|
|
|
|
/// <summary>
|
|
/// 波次自增
|
|
/// </summary>
|
|
[SyncVar]
|
|
public int roundIndex = 0;
|
|
// 游玩结束时间
|
|
[NonSerialized]
|
|
[SyncVar]
|
|
public long vistEnd = 0;
|
|
// 总游玩时长
|
|
private int vistAllTime = (int)(60 * 10f);
|
|
[SyncVar]
|
|
public string settleData = "";
|
|
|
|
[SyncVar]
|
|
public GameState gameState = GameState.None;
|
|
[SoundGroup] public string JointIn;
|
|
[SoundGroup] public string roundSound;
|
|
|
|
[NonSerialized]
|
|
[SyncVar]
|
|
public int blueScore = 0;
|
|
[NonSerialized]
|
|
[SyncVar]
|
|
public int redScore = 0;
|
|
|
|
void Awake()
|
|
{
|
|
Ins = this;
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
if (isClient)
|
|
{
|
|
AuthorPanel.Show();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 创建门
|
|
/// </summary>
|
|
[Server]
|
|
public void CreateDoor(Transform redPos, Transform bluePos,Transform startGamePos)
|
|
{
|
|
UpdateConf();
|
|
SetGameState(GameState.Waiting);
|
|
if(!isServer)
|
|
return;
|
|
//创建红色门
|
|
redDoor = Instantiate(redDoorPre);
|
|
NetworkServer.Spawn(redDoor);
|
|
redDoor.transform.position = redPos.position;
|
|
|
|
|
|
//创建蓝色门
|
|
blueDoor = Instantiate(blueDoorPre);
|
|
NetworkServer.Spawn(blueDoor);
|
|
blueDoor.transform.position = bluePos.position;
|
|
|
|
//创建开始球
|
|
GameObject gameStartObj = Instantiate(startGameItemPre);
|
|
NetworkServer.Spawn(gameStartObj);
|
|
gameStartObj.transform.position = startGamePos.position;
|
|
|
|
//测试枪械
|
|
GameLocal.Ins.self.GivePistol();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 创建初回合
|
|
/// </summary>
|
|
public void CreateFirstRound()
|
|
{
|
|
SetGameState(GameState.Playing);
|
|
roundIndex = 0;
|
|
CreateRound(roundIndex);
|
|
PlaySound2DRPC(roundSound);
|
|
RpcMessageRound();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 创建下一回合
|
|
/// </summary>
|
|
public void CreateNextRound()
|
|
{
|
|
roundIndex++;
|
|
|
|
if (CreateRound(roundIndex))
|
|
{
|
|
PlaySound2DRPC(roundSound);
|
|
RpcMessageRound();
|
|
}
|
|
else
|
|
{
|
|
GameOver(GameState.Victory);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 创建回合
|
|
/// </summary>
|
|
public bool CreateRound(int progress)
|
|
{
|
|
bool created = false;
|
|
CombatUnitInfos.TryGetValue(progress, out List<CombatUnitInfo> combatUnitInfos);
|
|
if (combatUnitInfos != null)
|
|
{
|
|
created = true;
|
|
foreach (CombatUnitInfo combatUnitInfo in combatUnitInfos)
|
|
{
|
|
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
|
|
{
|
|
if (combatUnitInfo.Special == 0)
|
|
{
|
|
CreateEnemy(
|
|
(EnemyType)combatUnitInfo.EnemyType,
|
|
combatUnitInfo.BornPos,
|
|
combatUnitInfo.BornAngleY
|
|
);
|
|
}
|
|
else
|
|
{
|
|
CreateAir(
|
|
(EnemyType)combatUnitInfo.EnemyType,
|
|
combatUnitInfo.BornPos,
|
|
combatUnitInfo.BornAngleY);
|
|
}
|
|
}, combatUnitInfo.BornTime);
|
|
}
|
|
}
|
|
return created;
|
|
}
|
|
|
|
[Server]
|
|
public void GameStart()
|
|
{
|
|
gameState = GameState.Playing;
|
|
vistEnd = (long)(DateTime.Now.Subtract(new DateTime(1970, 1, 1))).TotalSeconds + vistAllTime;
|
|
_airdropTime = 25;
|
|
_curAirdropTime = _airdropTime;
|
|
ChangeBgmRpc(1);
|
|
StartAirDrop();
|
|
AstarPath.active.Scan();
|
|
|
|
NetworkServer.Destroy(redDoor);
|
|
NetworkServer.Destroy(blueDoor);
|
|
|
|
// 延迟1s后给所有人发放武器
|
|
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
|
|
{
|
|
//GivePistol();
|
|
RpcShowSettle();
|
|
}, 1f);
|
|
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
|
|
{
|
|
GameOver(GameState.Settle);
|
|
}, 60 * 10f);
|
|
}
|
|
|
|
[ClientRpc]
|
|
public void RpcShowSettle()
|
|
{
|
|
GameLocal.Ins.Settle.SetActive(true);
|
|
}
|
|
|
|
[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)
|
|
{
|
|
gameState = state;
|
|
// foreach (string key in SettleInfos.Keys)
|
|
// {
|
|
// string[] titles = { "小菜一碟", "轻松拿捏", "荣耀勇士", "掌控全场", "队伍灵魂"
|
|
// ,"荣耀勇士", "团队之星", "颜值担当", "枪法如神", "弹无虚发", "精准猎手", "铁血战士", "无畏先锋", "无所畏惧" };
|
|
// SetTitle(key, titles[UnityEngine.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)
|
|
{
|
|
GameLocal.Ins.Settle.SetActive(false);
|
|
if (isBlue)
|
|
{
|
|
GameLocal.Ins.BlueWin.SetActive(true);
|
|
}
|
|
else
|
|
{
|
|
GameLocal.Ins.RedWin.SetActive(true);
|
|
}
|
|
}
|
|
|
|
[ClientRpc]
|
|
public void RpcShow()
|
|
{
|
|
SettlePanel.Show();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 下一波进攻开始
|
|
/// </summary>
|
|
[ClientRpc]
|
|
public void RpcMessageRound()
|
|
{
|
|
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
|
|
{
|
|
DragonLi.Core.EventDispatcher.TriggerEvent("NewWaveStart", roundIndex);
|
|
}, 0.5f);
|
|
}
|
|
|
|
[ClientRpc]
|
|
public void ChangeBgmRpc(int i)
|
|
{
|
|
GameLocal.Ins.BGMState.StateChange(i);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 创建敌方单位
|
|
/// </summary>
|
|
public void CreateEnemy(EnemyType type, Vector3 pos, float angleY)
|
|
{
|
|
GameObject enemy = Instantiate(EnemyPres[(int)type]);
|
|
NetworkServer.Spawn(enemy);
|
|
enemy.transform.position = pos;
|
|
enemy.transform.eulerAngles = new Vector3(0, angleY, 0);
|
|
enemyIndex++;
|
|
Enemy enemyScript = enemy.GetComponent<Enemy>();
|
|
enemyScript.OnSpawn(enemyIndex, type, 1);
|
|
EnemyList.Add(enemyIndex, enemyScript);
|
|
}
|
|
|
|
[Server]
|
|
public void CreateAirdropPlane(Vector3 startPos, Vector3 endPos)
|
|
{
|
|
GameObject airdropPlane = Instantiate(AirdropPlanePre);
|
|
NetworkServer.Spawn(airdropPlane);
|
|
airdropPlane.transform.position = startPos;
|
|
|
|
AirdropPlane airdropPlaneScript = airdropPlane.GetComponent<AirdropPlane>();
|
|
airdropPlaneScript.OnSpawn(endPos);
|
|
}
|
|
|
|
[Server]
|
|
public void CreateAirDropItem(GunType type ,Vector3 startPos)
|
|
{
|
|
GameObject airdropItem = Instantiate(airdropItems[(int)type]);
|
|
NetworkServer.Spawn(airdropItem);
|
|
airdropItem.transform.position = startPos;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除敌方单位
|
|
/// </summary>
|
|
[Server]
|
|
public void DeleteEnemy(int id)
|
|
{
|
|
GameObject enemy = EnemyList[id].gameObject;
|
|
EnemyList.Remove(id);
|
|
NetworkServer.Destroy(enemy);
|
|
if (EnemyList.Count == 0)
|
|
{
|
|
CreateNextRound();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 痛击场上所有敌方单位
|
|
/// </summary>
|
|
[Command(requiresAuthority = false)]
|
|
public void DamageAllEnemy()
|
|
{
|
|
foreach (Enemy enemy in EnemyList.Values)
|
|
{
|
|
enemy.ApplyDamage(999999, null, null);
|
|
}
|
|
}
|
|
|
|
public void CreateAir(EnemyType type, Vector3 pos, float angleY)
|
|
{
|
|
GameObject enemy = Instantiate(EnemyPres[(int)type]);
|
|
NetworkServer.Spawn(enemy);
|
|
enemy.transform.position = pos;
|
|
enemy.transform.eulerAngles = new Vector3(0, angleY, 0);
|
|
Airdrop enemyScript = enemy.GetComponent<Airdrop>();
|
|
enemyScript.OnSpawn(type, 1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更新配置表
|
|
/// </summary>
|
|
public void UpdateConf()
|
|
{
|
|
string text = Resources.Load<TextAsset>("Data").text;
|
|
if (text != null)
|
|
{
|
|
ParseGameJson(text);
|
|
}
|
|
}
|
|
|
|
public void ParseGameJson(string text)
|
|
{
|
|
DB = new JsonLiteDB();
|
|
DB.Load(text);
|
|
|
|
TableReader infoReader = DB["GunsInfo"].GetReader();
|
|
while (infoReader.Read())
|
|
{
|
|
GunInfo info = new GunInfo(infoReader);
|
|
GunInfos.TryGetValue((GunType)info.Type, out Dictionary<int, GunInfo> infoList);
|
|
if (infoList == null)
|
|
{
|
|
Dictionary<int, GunInfo> list = new Dictionary<int, GunInfo>();
|
|
list.Add(info.Lvl, info);
|
|
GunInfos.Add((GunType)info.Type, list);
|
|
}
|
|
else
|
|
{
|
|
infoList.Add(info.Lvl, info);
|
|
}
|
|
}
|
|
|
|
Debug.Log("游戏数值更新 -> complete");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取范围内敌人
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
[Server]
|
|
public void CreateEnemyUI(Enemy enemy)
|
|
{
|
|
GameObject enemyUI = Instantiate(EnemyUIPre);
|
|
NetworkServer.Spawn(enemyUI);
|
|
PlayerUI enemyUIScript = enemyUI.GetComponent<PlayerUI>();
|
|
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 空投道具
|
|
/// <summary>
|
|
/// 修复炮塔
|
|
/// </summary>
|
|
public void RepairTower()
|
|
{
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 进入联控
|
|
/// </summary>
|
|
[Server]
|
|
public void JoinControlTower(int playerIndex)
|
|
{
|
|
PlayJointMusic();
|
|
}
|
|
#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 (gameState == GameState.Playing)
|
|
{
|
|
res = FormatTime((int)(vistEnd - DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds));
|
|
}
|
|
return res;
|
|
}
|
|
|
|
public int GetLessTimeSeconds()
|
|
{
|
|
if (isServer)
|
|
{
|
|
return (int)(vistEnd - NetworkTime.time);
|
|
}
|
|
else
|
|
{
|
|
return (int)(vistEnd - NetworkClient.connection.remoteTimeStamp);
|
|
}
|
|
//return (int)(vistEnd - DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds);
|
|
}
|
|
|
|
// 时分秒
|
|
public string FormatTime(int totalSeconds)
|
|
{
|
|
//确保时间不为负
|
|
totalSeconds = Mathf.Max(0, 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
|
|
|
|
[ClientRpc]
|
|
public void PlaySound2DRPC(string sound)
|
|
{
|
|
MasterAudio.PlaySound(sound);
|
|
}
|
|
|
|
[ClientRpc]
|
|
public void PlayJointMusic()
|
|
{
|
|
MasterAudio.PlaySound(JointIn);
|
|
GameLocal.Ins.BGMState.StateChange(2);
|
|
}
|
|
|
|
[SyncVar]
|
|
private int syncRemainingTime;
|
|
|
|
private float _airdropTime;//空投时间
|
|
private float _curAirdropTime;//当前空头时间
|
|
private bool _isStartAirdrop;//是否开始倒计时空投
|
|
|
|
public void StartAirDrop()
|
|
{
|
|
_isStartAirdrop = true;
|
|
}
|
|
|
|
public void StopAirDrop()
|
|
{
|
|
_isStartAirdrop = false;
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (isServer&& gameState==GameState.Playing&&_isStartAirdrop)
|
|
{
|
|
//服务器计算剩余时间并同步
|
|
syncRemainingTime = GetLessTimeSeconds();
|
|
_curAirdropTime+=Time.deltaTime;
|
|
if (_curAirdropTime >= _airdropTime)
|
|
{
|
|
int airdropPosId = Random.Range(0, 4);
|
|
int endAirdropPosId =0;
|
|
if (airdropPosId == 0)
|
|
endAirdropPosId = 1;
|
|
if (airdropPosId == 1)
|
|
endAirdropPosId = 0;
|
|
if (airdropPosId == 2)
|
|
endAirdropPosId = 3;
|
|
if (airdropPosId == 3)
|
|
endAirdropPosId = 2;
|
|
CreateAirdropPlane(GameLocal.Ins.startPlanePos[airdropPosId].position,GameLocal.Ins.startPlanePos[endAirdropPosId].position);
|
|
_curAirdropTime = 0;
|
|
StopAirDrop();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|