广西桂平帝恒管道燃气投资有限公司多角色网上演练
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

616 lines
24 KiB

using System;
using System.Collections;
using System.Collections.Generic;
using AX.MessageSystem;
using UnityEngine;
using AX.InputSystem;
using UnityEngine.AI;
using AX.NetworkSystem;
using System.Linq.Expressions.Reimplement;
using System.Reflection;
public class CloneStayingAreaTool : CloneBase//集结区调车时注意场景中是否还有名称显示的预设(TheHeadName)
{
[SerializeField]
[Tooltip("距离地面距离")]
protected float Height = 0;
public float AreaPrefabSize;
private List<FireCarEngine> NowMyCarList;
public List<Vector3> PosPoints;//集结区停放车辆点位总位置集合
public List<Vector3> HadPos = new List<Vector3>();//没有停车的空位
private CloneCmdArgs data;
private CarMoveOutController Controller;
private long AreaID;
private int PosNum;
public bool isGetedCars;
public float SafeRange = 15f;
public bool IsSafe;
private List<GameObject> DangerousList = new List<GameObject>();
private Transform P_Disasters;
private NavMeshQueryFilter filter;
private NavMeshHit nhit;
private GameObject WaterCarParent;
Vector2 vLU;
Vector2 vLD;
Vector2 vRU;
Vector2 vRD;
Ray rayLU;
Ray rayLD;
Ray rayRU;
Ray rayRD;
RaycastHit HitLU;
RaycastHit HitLD;
RaycastHit HitRU;
RaycastHit HitRD;
public bool cloneAble;//true表示能克隆或停放;否则不行
void Awake()
{
NowMyCarList = new List<FireCarEngine>();
P_Disasters = transform.parent.parent.Find("P_Disasters");
WaterCarParent = GameObject.Find("P_Cars").transform.Find("P_WaterTanker").gameObject;
filter.agentTypeID = WaterCarParent.GetComponent<CloneCar>().clonePrefab.GetComponent<NavMeshAgent>().agentTypeID;
filter.areaMask = WaterCarParent.GetComponent<CloneCar>().clonePrefab.GetComponent<NavMeshAgent>().areaMask;
}
public override void Execute(IMessage obj)
{
if (!isGetedCars)
{
GetMyCars();
isGetedCars = true;
}
if (transform.childCount > 0)
{
foreach (Transform t in transform)
{
if (t.GetComponent<BaseGameObjInfo>().UserID == CurrentUserInfo.mySelf.Id)
return;
}
}
var gameObjID = (long)obj.Sender;
data = ((CloneCmdArgs)obj.Data);
if (data.cloneObjType == cloneObjType)
{
var hitPoint = data.hitPos;
CheckCloneAble(hitPoint);
if (!cloneAble)
{
return;
}
Vector3 clonedObjPos = new Vector3(hitPoint.x, hitPoint.y + Height, hitPoint.z);
var clonedObj = EntitiesManager.Instance.CreateObj(clonePrefab, clonedObjPos, transform, gameObjID);
clonedObj.name = CloneObjNameTool.Instance().GetCloneObjectName(cloneObjType);
SelectedObjs.gameObjs.Add(clonedObj);
//设置克隆物体所在楼层等基本属性,属性从点击的对象上获取
var hitObj = EntitiesManager.Instance.GetEntityByID(data.gameObjID);
CloneGameObjInfo hitObjInfo = hitObj.GetComponent<CloneGameObjInfo>();
CloneGameObjInfo cloneObjInfo = clonedObj.GetComponent<CloneGameObjInfo>();
cloneObjInfo.gameObjType = cloneObjType;
cloneObjInfo.UserID = CurrentUserInfo.mySelf.Id;
cloneObjInfo.buildNum = hitObjInfo.buildNum;
cloneObjInfo.floorNum = hitObjInfo.floorNum;
cloneObjInfo.interlayerNum = hitObjInfo.interlayerNum;
AreaID = clonedObj.GetComponent<CloneGameObjInfo>().gameObjID;
Controller = clonedObj.GetComponent<CarMoveOutController>();
//获取集结区停车位置,总共8个
PosPoints = GetPoints(data.hitPos, AreaPrefabSize / 2, 8);
HadPos.Clear();
//停放车辆
SetMyCars();
//判断集结区位置是否在火灾下风向
GetDangerousList(clonedObjPos);
//判断设置位置是否在下风向
if (!IsSafeJude(clonedObjPos))
{
//发送错误报告同步信息
ReportErroeSyncData arg = new ReportErroeSyncData();
//if (GetComponent<TIME_SYNC>())
{
arg.Time = TIME_SYNC.time;
}
arg.SendUserID = CurrentUserInfo.mySelf.Id;
arg.errorset = CurrentUserInfo.role.ToString();//"集结区设置错误";
arg.describe = "集结区设置在火灾下风口";
NetworkManager.Default.SendAsync("REPORT_ERROR_SYNC", arg);
}
}
}
/// <summary>
/// 检查当前克隆位置能否克隆集结区(或者当前位置能否停放集结区)
/// </summary>
/// <param name="hitPoint"></param>
public bool CheckCloneAble(Vector3 hitPoint)
{
vLU = Camera.main.WorldToScreenPoint(hitPoint + Vector3.left * AreaPrefabSize / 2 + Vector3.forward * AreaPrefabSize / 2);
vLD = Camera.main.WorldToScreenPoint(hitPoint + Vector3.left * AreaPrefabSize / 2 + Vector3.back * AreaPrefabSize / 2);
vRU = Camera.main.WorldToScreenPoint(hitPoint + Vector3.right * AreaPrefabSize / 2 + Vector3.forward * AreaPrefabSize / 2);
vRD = Camera.main.WorldToScreenPoint(hitPoint + Vector3.right * AreaPrefabSize / 2 + Vector3.back * AreaPrefabSize / 2);
rayLU = Camera.main.ScreenPointToRay(vLU);
rayLD = Camera.main.ScreenPointToRay(vLD);
rayRU = Camera.main.ScreenPointToRay(vRU);
rayRD = Camera.main.ScreenPointToRay(vRD);
if (Physics.Raycast(rayLU, out HitLU))
{
//if (!(HitLU.transform.gameObject.layer == LayerMask.NameToLayer("CarRoad") && HitLU.transform.GetComponent<CloneGameObjInfo>()))
if (NavMesh.SamplePosition(HitLU.point, out nhit, 0.5f, filter))
{
if (Vector3.Distance(HitLU.point, nhit.position) > 0.2f)
{
LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f);
cloneAble = false;
return cloneAble;
}
}
else
{
LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f);
cloneAble = false;
return cloneAble;
}
}
if (Physics.Raycast(rayLD, out HitLD))
{
if (NavMesh.SamplePosition(HitLD.point, out nhit, 0.5f, filter))
{
if (Vector3.Distance(HitLD.point, nhit.position) > 0.2f)
{
LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f);
cloneAble = false;
return cloneAble;
}
}
else
{
LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f);
cloneAble = false;
return cloneAble;
}
}
if (Physics.Raycast(rayRU, out HitRU))
{
if (NavMesh.SamplePosition(HitRU.point, out nhit, 0.5f, filter))
{
if (Vector3.Distance(HitRU.point, nhit.position) > 0.2f)
{
LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f);
cloneAble = false;
return cloneAble;
}
}
else
{
LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f);
cloneAble = false;
return cloneAble;
}
}
if (Physics.Raycast(rayRD, out HitRD))
{
if (NavMesh.SamplePosition(HitRD.point, out nhit, 0.5f, filter))
{
if (Vector3.Distance(HitRD.point, nhit.position) > 0.2f)
{
LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f);
cloneAble = false;
return cloneAble;
}
}
else
{
LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f);
cloneAble = false;
return cloneAble;
}
}
return cloneAble = true;
}
private void GetMyCars()
{
//if (GameSettings.othersSettings.mode == Mode.manoeuvre)
//{
// if (GameSettings.othersSettings.CarList.Count > 0)
// foreach (var item in GameSettings.othersSettings.CarList)
// {
// if (NowMyCarList.Count > 0)
// {
// for (int i = 0; i < NowMyCarList.Count; i++)
// {
// if (!NowMyCarList.Contains(item.Key))
// {
// NowMyCarList.Add(item.Key);
// break;
// }
// }
// }
// else
// {
// NowMyCarList.Add(item.Key);
// }
// }
//}
//if (GameSettings.othersSettings.mode == Mode.Practice)
//{
if (GameSettings.othersSettings.CarList.Count > 0)
{
foreach (var item in GameSettings.othersSettings.CarList)
{
for (int i = 0; i < item.Value; i++)
{
FireCarEngine car = DeepCopyByReflection(item.Key);
NowMyCarList.Add(car);
}
}
// 演习模式单独处理车辆载人数
if (GameSettings.othersSettings.mode == Mode.manoeuvre)
{
// if(GameSettings.othersSettings.personNum >0)
{
int carnum = 0;
foreach (var item in GameSettings.othersSettings.CarList)
{
carnum += item.Value;
}
int[] PersonNum = new int[carnum];
int nowperson = GameSettings.othersSettings.personNum;
while (nowperson > 0)
{
for (int i = 0; i < NowMyCarList.Count; i++)
{
if (nowperson > 0 && PersonNum[i] < NowMyCarList[i].PassengerCapacity)
{
PersonNum[i] += 1;
nowperson--;
}
}
}
for (int i = 0; i < NowMyCarList.Count; i++)
{
NowMyCarList[i].PassengerCapacity = PersonNum[i];
}
for (int i = 0; i < PersonNum.Length; i++)
{
NowMyCarList[i].PassengerCapacity = PersonNum[i];
Debug.Log(NowMyCarList[i].PassengerCapacity);
}
}
}
}
//}
}
//用来显示收到新调派的车辆
public void ReceiveNewCars(List<FireCarEngine> NewCars)
{
List<FireCarEngine> deepnewcars = new List<FireCarEngine>();
for (int i = 0; i < NewCars.Count; i++)
{
FireCarEngine car = DeepCopyByReflection(NewCars[i]);
deepnewcars.Add(car);
}
//演练模式单独处理当前客户端车辆载人数
if (GameSettings.othersSettings.mode == Mode.manoeuvre)
{
int nowperson = GameSettings.othersSettings.nowperson;
if (nowperson > 0)
{
int[] PersonNum = new int[deepnewcars.Count];
while (nowperson > 0)
{
for (int i = 0; i < deepnewcars.Count; i++)
{
if (nowperson > 0 && PersonNum[i] < deepnewcars[i].PassengerCapacity)
{
PersonNum[i] += 1;
nowperson--;
}
}
}
for (int i = 0; i < deepnewcars.Count; i++)
{
deepnewcars[i].PassengerCapacity = PersonNum[i];
}
}
}
foreach (var NewCar in deepnewcars)
{
NowMyCarList.Add(NewCar);
}
if (Controller == null)//没有克隆集结区直接返回
return;
//if (Controller.PosList.Count == 0)//集结区没有车了
//{
// SetMyCars();
// return;
//}
while (HadPos.Count > 0 && NowMyCarList.Count > 0)
{
FillCarSpace();
}
//while (Controller.PosList.Count < PosNum && NowMyCarList.Count > 0)
//{
// if (Controller.PosList.Count == 0)//车辆都不在集结区了重新刷出车辆
// {
// //SetMyCars(NowMyCarList.Count > PosNum ? PosNum : NowMyCarList.Count);
// }
// else
// {
// List<Vector3> PosList = GetPoints(data.hitPos, AreaPrefabSize / 2, PosNum);
// foreach (var pos in PosList)
// {
// if (!Controller.PosList.Contains(pos))
// {
// FillCarSpace();//空点位点出车
// break;
// }
// }
// }
//}
}
/// <summary>
/// 空位出车
/// </summary>
public void FillCarSpace()
{
if (NowMyCarList.Count > 0)
{
CloneCmdArgs arg = new CloneCmdArgs();
arg.gameObjID = AreaID;
arg.cloneObjType = (CloneObjType)NowMyCarList[0].Type;
arg.hitPos = HadPos[0];
arg.fireCarEngine = NowMyCarList[0];
long Id = EntitiesManager.Instance.CreateObjID(CurrentUserInfo.mySelf.Id);
CloneCommand.Instance.Execute(Id, arg);
NowMyCarList.Remove(NowMyCarList[0]);
Controller.PosList.Add(HadPos[0]);
HadPos.RemoveAt(0);
}
}
//克隆车的控制
public void SetMyCars()
{
Controller.tool = this;
int j = 0;
for (; ; )
{
if (j > 7 || NowMyCarList.Count == 0)
break;
CloneCmdArgs arg = new CloneCmdArgs();
arg.gameObjID = AreaID;
arg.cloneObjType = (CloneObjType)NowMyCarList[0].Type;
arg.hitPos = PosPoints[j];
Controller.PosList.Add(PosPoints[j]);
arg.fireCarEngine = NowMyCarList[0];
if (GameSettings.othersSettings.mode == Mode.manoeuvre)
{
arg.fireCarEngine.PassengerCapacity = NowMyCarList[0].PassengerCapacity;
}
long Id = EntitiesManager.Instance.CreateObjID(CurrentUserInfo.mySelf.Id);
CloneCommand.Instance.Execute(Id, arg);
NowMyCarList.Remove(NowMyCarList[0]);
j++;
}
for (int i = j; i < PosPoints.Count; i++)
{
HadPos.Add(PosPoints[i]);
}
}
//集结区点位,目前最大是8
private List<Vector3> GetPoints(Vector3 centerPoint, float radius, int num)
{
List<Vector3> ResultList = new List<Vector3>();
switch (num)
{
case 1:
ResultList.Add(centerPoint); break;
case 2:
ResultList.Add(centerPoint + Vector3.left * radius / 3);
ResultList.Add(centerPoint + Vector3.right * radius / 3);
break;
case 3:
ResultList.Add(centerPoint);
ResultList.Add(centerPoint + Vector3.left * radius / 2);
ResultList.Add(centerPoint + Vector3.right * radius / 2);
break;
case 4:
ResultList.Add(centerPoint + Vector3.left * radius / 4);
ResultList.Add(centerPoint + Vector3.right * radius / 4);
ResultList.Add(centerPoint + Vector3.left * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.right * radius / 1.2f);
break;
case 5:
ResultList.Add(centerPoint);
ResultList.Add(centerPoint + Vector3.right * radius / 1.2f + Vector3.forward * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.right * radius / 1.2f + Vector3.back * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.left * radius / 1.2f + Vector3.forward * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.left * radius / 1.2f + Vector3.back * radius / 1.2f);
break;
case 6:
ResultList.Add(centerPoint + Vector3.forward * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.back * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.left * radius / 1.5f + Vector3.forward * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.left * radius / 1.5f + Vector3.back * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.right * radius / 1.5f + Vector3.forward * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.right * radius / 1.5f + Vector3.back * radius / 1.2f);
break;
case 7:
ResultList.Add(centerPoint);
ResultList.Add(centerPoint + Vector3.right * radius / 3f);
ResultList.Add(centerPoint + Vector3.right * radius + Vector3.forward * radius);
ResultList.Add(centerPoint + Vector3.right * radius + Vector3.back * radius);
ResultList.Add(centerPoint + Vector3.left * radius / 3f);
ResultList.Add(centerPoint + Vector3.left * radius + Vector3.forward * radius);
ResultList.Add(centerPoint + Vector3.left * radius + Vector3.back * radius);
break;
case 8:
ResultList.Add(centerPoint + Vector3.left * radius / 4f + Vector3.forward * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.left * radius / 4f + Vector3.back * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.right * radius / 4f + Vector3.forward * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.right * radius / 4f + Vector3.back * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.left * radius / 1.3f + Vector3.forward * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.left * radius / 1.3f + Vector3.back * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.right * radius / 1.3f + Vector3.forward * radius / 1.2f);
ResultList.Add(centerPoint + Vector3.right * radius / 1.3f + Vector3.back * radius / 1.2f);
break;
}
return ResultList;
}
/// <summary>
/// 克隆点周围火灾列表
/// </summary>
/// <param name="setpos"></param>
void GetDangerousList(Vector3 setpos)
{
float Helfdiagonal = Mathf.Sqrt(2) * (AreaPrefabSize / 2);
DangerousList.Clear();
CloneGameObjInfo[] allDisaster = P_Disasters.GetComponentsInChildren<CloneGameObjInfo>();
for (int i = 0; i < allDisaster.Length; i++)
{
if (
allDisaster[i].gameObjType == CloneObjType.fireNormal ||
allDisaster[i].gameObjType == CloneObjType.LiquidLevel)
{
if (allDisaster[i].gameObjType == CloneObjType.fireNormal)
{
//普通火,计算普通火到集结区对角线一半的距离
if (Vector3.Distance(setpos, allDisaster[i].transform.position) < (SafeRange + Helfdiagonal))
{
DangerousList.Add(allDisaster[i].gameObject);
}
}
if (allDisaster[i].gameObjType == CloneObjType.LiquidLevel)
{
//如果是全液面火
long guanID = allDisaster[i].GetComponent<FireLiquidLevelCtrl>().TargetNormalID;
if (EntitiesManager.Instance.GetEntityByID(guanID)
&& EntitiesManager.Instance.GetEntityByID(guanID).GetComponent<OilTankMessage>())
{
OilTankMessage msg = EntitiesManager.Instance.GetEntityByID(guanID).GetComponent<OilTankMessage>();
float direction = msg.Tank_D;
Vector3 tankpos = new Vector3(msg.transform.position.x, setpos.y + Height, transform.position.z);
if (Vector3.Distance(setpos, tankpos) < (SafeRange + Helfdiagonal + direction / 2))
{
DangerousList.Add(allDisaster[i].gameObject);
}
}
else
{
Debug.LogError("找不到Id为" + guanID + "的油罐或者油罐上没有OilTankMessage");
}
}
}
}
}
/// <summary>
/// 判断集结区是否在下风向
/// </summary>
/// <returns></returns>
private bool IsSafeJude(Vector3 setpos)
{
bool safe = true;
GameObject wind = GameObject.Find("WindZone");
if (wind.GetComponent<WindZone>().windMain <= 0)
{
safe = true;
}
else//设置了风力
{
if (DangerousList.Count <= 0)
{
safe = true;
}
else//防止范围内有火灾
{
Vector3 windNormal = wind.transform.forward.normalized;//风向
for (int i = 0; i < DangerousList.Count; i++)
{
Vector3 pos_fire = DangerousList[i].transform.position - setpos;//集结区-火的向量
Vector2 xoz = new Vector2(pos_fire.x, pos_fire.z);//集结区-火的向量 的xoz平面向量
float dot_vec2 = Vector2.Dot(xoz, new Vector2(windNormal.x, windNormal.z));//该向量与风向的点成
if (dot_vec2 > 0)
{
safe = false;
break;
}
}
//Vector3 verticalNormal = Vector3.Cross(windNormal, Vector3.up).normalized;//风向垂直方向
//float Slope = verticalNormal.z / verticalNormal.x;//斜率
//float intercept = setpos.z - Slope * setpos.x;//截距
////集结区的中心点所在直线方程为:y=slope*x+intercept
//for (int i = 0; i < DangerousList.Count; i++)
//{
// float y = Slope * DangerousList[i].transform.position.x + intercept + Mathf.Sqrt(2) * (AreaPrefabSize / 2);
// if (y < DangerousList[i].transform.position.z)
// {
// safe = false;
// }
//}
}
}
return safe;
}
public static T DeepCopyByReflection<T>(T obj)
{
if (obj is string || obj.GetType().IsValueType)
return obj;
object retval = Activator.CreateInstance(obj.GetType());
FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
foreach (var field in fields)
{
try
{
field.SetValue(retval, DeepCopyByReflection(field.GetValue(obj)));
}
catch { }
}
return (T)retval;
}
}