965 lines
41 KiB
C#
965 lines
41 KiB
C#
using System.Collections.Generic;
|
||
using Games.GlobeDefine;
|
||
using Games.Scene;
|
||
using GCGame.Table;
|
||
using Module.Log;
|
||
using UnityEngine;
|
||
using UnityEngine.AI;
|
||
|
||
namespace Games.LogicObj
|
||
{
|
||
public partial class Obj_MainPlayer
|
||
{
|
||
public static int fubenId
|
||
{
|
||
get { return GameManager.gameManager.PlayerDataPool.EnterSceneCache.EnterCopySceneID; }
|
||
}
|
||
|
||
// 队员距离队长超过这个距离就开始骑马
|
||
private const float _mountDistance = 15f;
|
||
// 队员最大传送时间
|
||
private const float _maxMemberTeleportTime = 5f;
|
||
|
||
// 组队跟随状态更新
|
||
private const float _updateFollowInterval = 0.2f;
|
||
|
||
// 组队跟随位置差值
|
||
private const float _followDistance = 1.5f;
|
||
|
||
// 模拟器在Obj存在时允许的偏差量
|
||
private const float _objSimulatorDiffer = 3f;
|
||
|
||
// 模拟器最大偏移量 - 同实际角色偏差超过这个数值,就补正位置
|
||
private const float _maxSimulatorDiffer = 5f;
|
||
|
||
// 预测队员移动距离的参数
|
||
private const float _updateFollowPredictTime = 0.3f;
|
||
|
||
// 组队跳跃容忍误差
|
||
private const float _jumpSimulatorDiffer = 1f;
|
||
|
||
// 队员进入自动战斗的距离
|
||
public const float memberEnterAutoCombatDistance = (GlobeVar.MAX_TEAM_MEMBER - 1) * _followDistance + 4f;
|
||
|
||
// 队员离开自动战斗的距离
|
||
public const float memberLeaveAutoCombatDistance = memberEnterAutoCombatDistance + 15f;
|
||
|
||
// 队长路径。注:队长保持这个路径更新,即使没有玩家处于组队跟随状态
|
||
private readonly List<Vector3> _leaderPosList = new List<Vector3>(GlobeVar.MAX_TEAM_MEMBER);
|
||
|
||
// 上次切换跟随状态时间
|
||
private float _enterFollowTime;
|
||
|
||
private float _nextUpdateFollowTime;
|
||
|
||
// 结束组队跟随时,是否进入自动战斗
|
||
public bool debugTeamTeleport;
|
||
|
||
public List<TeamMemberMoveSimulator> moveSimulatorList = new List<TeamMemberMoveSimulator>();
|
||
|
||
/// <summary>
|
||
/// 检查主角是否处于组队跟随状态
|
||
/// </summary>
|
||
public bool IsFollowTeam
|
||
{
|
||
get { return GameManager.gameManager.PlayerDataPool.IsFollowTeam; }
|
||
}
|
||
|
||
public int FollowState
|
||
{
|
||
get { return GameManager.gameManager.PlayerDataPool.TeamInfo.GetFollowState(); }
|
||
}
|
||
|
||
public int sceneAutoType
|
||
{
|
||
get
|
||
{
|
||
if (_sceneAutoType == null)
|
||
_sceneAutoType = CommonUtility.FubenAutoType();
|
||
return _sceneAutoType.Value;
|
||
}
|
||
}
|
||
|
||
private int? _sceneAutoType;
|
||
//邀请某个玩家入队
|
||
public void ReqInviteTeam(ulong playerGuid)
|
||
{
|
||
//检查被邀请者GUID是否为空(由于可以创建单人队伍,所以发空guid说明是单人组队,可以认为合法)
|
||
//if (GlobeVar.INVALID_GUID == playerGuid)
|
||
//{
|
||
// return;
|
||
//}
|
||
|
||
//判断队伍是否已满
|
||
if (GameManager.gameManager.PlayerDataPool.IsHaveTeam())
|
||
if (GameManager.gameManager.PlayerDataPool.TeamInfo.IsFull())
|
||
SendNoticMsg(false, "#{1145}");
|
||
|
||
//非单人组队,增加提示“邀请已发送”
|
||
//if (playerGuid != GlobeVar.INVALID_GUID)
|
||
//{
|
||
// SendNoticMsg(false, "#{3170}");
|
||
//}
|
||
|
||
//向服务器发送邀请某人加入队伍消息
|
||
var msg = (CG_REQ_TEAM_INVITE) PacketDistributed.CreatePacket(MessageID.PACKET_CG_REQ_TEAM_INVITE);
|
||
msg.Guid = playerGuid;
|
||
msg.SendPacket();
|
||
}
|
||
|
||
//申请加入队伍
|
||
public void ReqJoinTeam(int teamId)
|
||
{
|
||
//if (teamID <= 0)
|
||
//{
|
||
// GUIData.AddNotifyData(StrDictionary.GetClientDictionaryString("{#5141}"));
|
||
// return;
|
||
//}
|
||
|
||
//有队伍则不得申请
|
||
if (GameManager.gameManager.PlayerDataPool.IsHaveTeam())
|
||
{
|
||
if (teamId == GameManager.gameManager.PlayerDataPool.TeamInfo.TeamID)
|
||
return;
|
||
//SendNoticMsg(false, "#{2179}");
|
||
MessageBoxLogic.OpenOKCancelBox(StrDictionary.GetClientDictionaryString("#{4605}"), "",
|
||
ReqJoinLeaveOldOK, ReqJoinLeaveOldCancel);
|
||
return;
|
||
}
|
||
|
||
//GUIData.AddNotifyData(StrDictionary.GetClientDictionaryString("{#5142}"));
|
||
//向服务器发送申请加入队伍消息
|
||
var msg = (CG_REQ_TEAM_JOIN) PacketDistributed.CreatePacket(MessageID.PACKET_CG_REQ_TEAM_JOIN);
|
||
msg.Teamid = teamId;
|
||
msg.SendPacket();
|
||
}
|
||
|
||
public void ReqJoinLeaveOldOK()
|
||
{
|
||
var msg = (CG_REQ_TEAM_LEAVE) PacketDistributed.CreatePacket(MessageID.PACKET_CG_REQ_TEAM_LEAVE);
|
||
msg.TeamID = GameManager.gameManager.PlayerDataPool.TeamInfo.TeamID;
|
||
//msg.NewTeamMember = m_NewTeamMemberBuffer;
|
||
msg.SendPacket();
|
||
}
|
||
|
||
public void ReqJoinLeaveOldCancel()
|
||
{
|
||
}
|
||
|
||
//申请离开队伍
|
||
public void ReqLeaveTeam()
|
||
{
|
||
//向服务器发送申请离队消息
|
||
var msg = (CG_REQ_TEAM_LEAVE) PacketDistributed.CreatePacket(MessageID.PACKET_CG_REQ_TEAM_LEAVE);
|
||
msg.SetTeamID(GameManager.gameManager.PlayerDataPool.TeamInfo.TeamID);
|
||
msg.SendPacket();
|
||
}
|
||
|
||
//申请踢人
|
||
public void ReqKickTeamMember(ulong teamMemberGuid)
|
||
{
|
||
if (GlobeVar.INVALID_GUID == teamMemberGuid)
|
||
return;
|
||
|
||
var msg = (CG_REQ_TEAM_KICK_MEMBER) PacketDistributed.CreatePacket(MessageID
|
||
.PACKET_CG_REQ_TEAM_KICK_MEMBER);
|
||
msg.SetTeamMemberGuid(teamMemberGuid);
|
||
msg.SendPacket();
|
||
}
|
||
|
||
//申请变换队长
|
||
public void ReqChangeTeamLeader(ulong teamMemberGuid)
|
||
{
|
||
if (GlobeVar.INVALID_GUID == teamMemberGuid)
|
||
return;
|
||
|
||
var msg = (CG_REQ_TEAM_CHANGE_LEADER) PacketDistributed.CreatePacket(MessageID
|
||
.PACKET_CG_REQ_TEAM_CHANGE_LEADER);
|
||
msg.SetTeamMemberGuid(teamMemberGuid);
|
||
msg.SendPacket();
|
||
}
|
||
|
||
//更新某个组员信息,第三位为是否只更新HP标记
|
||
public void UpdateTeamMemberInfo(int nIndex, GC_TEAM_SYNC_MEMBERINFO packet)
|
||
{
|
||
//下标判断
|
||
if (nIndex < 0 || nIndex >= GlobeVar.MAX_TEAM_MEMBER)
|
||
return;
|
||
|
||
//更新数据
|
||
GameManager.gameManager.PlayerDataPool.TeamInfo.UpdateMember(nIndex, packet);
|
||
|
||
//更新UI数据
|
||
if (TeamList.Instance() == null)
|
||
return;
|
||
TeamList.Instance().UpdateTeamMember();
|
||
}
|
||
|
||
//收到离开队伍消息
|
||
public void LeaveTeam()
|
||
{
|
||
//清理队伍数据
|
||
GameManager.gameManager.PlayerDataPool.TeamInfo.CleanUp();
|
||
|
||
//通知UI清理队伍数据
|
||
TeamList.Instance().ClearTeamListUI();
|
||
|
||
//更新队长头像
|
||
if (null != PlayerFrameLogic.Instance())
|
||
{
|
||
//PlayerFrameLogic.Instance().SetTeamCaptain(false);
|
||
}
|
||
|
||
//退出组队跟随状态
|
||
LeaveTeamFollow();
|
||
}
|
||
|
||
//MainPlayer是否为队长
|
||
public bool IsTeamLeader()
|
||
{
|
||
if (GlobeVar.INVALID_ID == GameManager.gameManager.PlayerDataPool.TeamInfo.TeamID)
|
||
return false;
|
||
|
||
return GUID == GameManager.gameManager.PlayerDataPool.TeamInfo.GetTeamMember(0).Guid;
|
||
}
|
||
|
||
//否个Guid是否为队长
|
||
public bool IsTeamLeader(ulong guid)
|
||
{
|
||
if (GlobeVar.INVALID_ID == GameManager.gameManager.PlayerDataPool.TeamInfo.TeamID ||
|
||
GlobeVar.INVALID_GUID == guid)
|
||
return false;
|
||
return guid == GameManager.gameManager.PlayerDataPool.TeamInfo.GetTeamMember(0).Guid;
|
||
}
|
||
|
||
public void EnterTeamFollow()
|
||
{
|
||
//没有队伍,无法进入组队跟随状态
|
||
if (GlobeVar.INVALID_ID == GameManager.gameManager.PlayerDataPool.TeamInfo.TeamID)
|
||
return;
|
||
|
||
if (Singleton<ObjManager>.Instance.MainPlayer.IsInPaoShang() &&
|
||
!GameManager.gameManager.PlayerDataPool.TeamInfo.IsCaptain())
|
||
{
|
||
GUIData.AddNotifyData(StrDictionary.GetClientDictionaryString("{#34007}"));
|
||
return;
|
||
}
|
||
|
||
//BOSS之家的判断
|
||
//if (InHomeBoss())
|
||
// return;
|
||
|
||
SetTeamFollowState(TeamFollowState.followMove);
|
||
}
|
||
|
||
//跟随进入BOSS之家时需要判断队员是否都满足条件
|
||
private bool InHomeBoss()
|
||
{
|
||
if (GameManager.gameManager.PlayerDataPool.TeamInfo.IsCaptain() == false)
|
||
{
|
||
TeamMember captain = GameManager.gameManager.PlayerDataPool.TeamInfo.GetTeamMember(0);
|
||
if (captain.IsValid() == false)
|
||
return false;
|
||
if (WorldBossData.Instance.IsInHomeBossFuben(captain.SceneClassID) == false)
|
||
return false;
|
||
int sceneVipLevel = WorldBossData.Instance.SceneVipLevel(captain.SceneClassID);
|
||
if (sceneVipLevel > WorldBossData.Instance.VipCanUseLevel)
|
||
{
|
||
GUIData.AddNotifyData(StrDictionary.GetClientDictionaryString("{#49152}",GameManager.gameManager.PlayerDataPool.MainPlayerBaseAttr.RoleName, sceneVipLevel));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (WorldBossData.Instance.IsInHomeBossFuben(GameManager.gameManager.RunningScene) == false)
|
||
return false;
|
||
int sceneVipLevel = WorldBossData.Instance.SceneVipLevel(GameManager.gameManager.RunningScene);
|
||
for (var i = 1; i < GlobeVar.MAX_TEAM_MEMBER; i++)
|
||
{
|
||
TeamMember member = GameManager.gameManager.PlayerDataPool.TeamInfo.GetTeamMember(i);
|
||
if (member.IsValid() == false)
|
||
continue;
|
||
if (WorldBossData.Instance.IsInHomeBossFuben(member.SceneClassID) == false)
|
||
continue;
|
||
if (sceneVipLevel > 0)
|
||
{
|
||
GUIData.AddNotifyData(StrDictionary.GetClientDictionaryString("{#49152}", member.MemberName, sceneVipLevel));
|
||
}
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public void TeamEnterAutoCombat()
|
||
{
|
||
SetTeamFollowState(TeamFollowState.followCombat);
|
||
}
|
||
|
||
public void TeamLeaderEndCombat()
|
||
{
|
||
var teamMembers = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember;
|
||
for (var i = 1; i < teamMembers.Length; i++)
|
||
if (teamMembers[i].IsValid())
|
||
{
|
||
if (teamMembers[i].FollowState == TeamFollowState.followCombat)
|
||
SetTeamFollowState(TeamFollowState.followMove, teamMembers[i].Guid);
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
public void BreakTeamTeleport()
|
||
{
|
||
if (GameManager.gameManager.PlayerDataPool.TeamInfo.IsCaptain())
|
||
{
|
||
var leader = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[0];
|
||
if (leader.IsValid())
|
||
{
|
||
leader.teleportFreezeTime = 0f;
|
||
for (var i = 1; i < GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember.Length; ++i)
|
||
{
|
||
var member = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[i];
|
||
if (member.FollowLeader())
|
||
TryMatchSceneWithLeader(member, leader);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//结束组队跟随状态
|
||
public void LeaveTeamFollow()
|
||
{
|
||
SetTeamFollowState(TeamFollowState.notFollow);
|
||
}
|
||
|
||
private void SetTeamFollowState(int followState, ulong? guid = null)
|
||
{
|
||
if (guid == null)
|
||
guid = GUID;
|
||
var packet =
|
||
(CG_REQ_CHANGE_TEAM_MEMBER_FOLLOWSTATE) PacketDistributed.CreatePacket(MessageID
|
||
.PACKET_CG_REQ_CHANGE_TEAM_MEMBER_FOLLOWSTATE);
|
||
packet.SetOpguid(guid.Value);
|
||
packet.SetFollowstate(followState);
|
||
packet.SendPacket();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 主角在进入一个新场景时,试图根据当前场景配置自动战斗情况
|
||
/// </summary>
|
||
public void RefreshPlayerAutoCombat()
|
||
{
|
||
var autoType =
|
||
CommonUtility.FubenAutoType(GameManager.gameManager.PlayerDataPool.EnterSceneCache.EnterCopySceneID);
|
||
// 是否执行组队队员更新策略
|
||
var teamMemberUpdate = false;
|
||
if (GameManager.gameManager.PlayerDataPool.IsHaveTeam())
|
||
if (!GameManager.gameManager.PlayerDataPool.TeamInfo.IsCaptain())
|
||
teamMemberUpdate = true;
|
||
if (autoType == FubenAutoType.auto)
|
||
{
|
||
if (!isAutoCombat)
|
||
{
|
||
if (LoadingWindow._IsLoadingScene)
|
||
EnterAutoCombatAfterLoading();
|
||
else
|
||
EnterAutoCombat();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
LeveAutoCombat();
|
||
}
|
||
|
||
if (teamMemberUpdate)
|
||
{
|
||
if (autoType == FubenAutoType.noAuto)
|
||
{
|
||
var lastFuben = GameManager.gameManager.PlayerDataPool.EnterSceneCache.LastFuben;
|
||
// 如果副本为退出后跟随副本,则进入跟随状态
|
||
if (lastFuben != null && lastFuben.FollowAfterQuit > 0)
|
||
SetTeamFollowState(TeamFollowState.followMove);
|
||
}
|
||
else
|
||
{
|
||
SetTeamFollowState(TeamFollowState.notFollow);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 试图让队员传送到队长的场景
|
||
/// </summary>
|
||
/// <returns>队员是否处于传送中</returns>
|
||
// 注:这个函数仅仅允许队长调用,队员调用会出错
|
||
private bool TryMatchSceneWithLeader(TeamMember member, TeamMember leader)
|
||
{
|
||
var result = false;
|
||
// 队长处于传送状态,不发送消息
|
||
if (leader.teleportFreezeTime > Time.realtimeSinceStartup)
|
||
{
|
||
result = true;
|
||
}
|
||
// 队员处于传送状态,不接受新的传送指令
|
||
else if (member.teleportFreezeTime > Time.realtimeSinceStartup)
|
||
{
|
||
// 队长不传送,队员和队长在同一场景时,取消传送
|
||
result = member.SceneClassID != fubenId || member.SceneInstID != SceneData.SceneInst;
|
||
}
|
||
// 队长不处于副本场景中
|
||
else if (member.SceneClassID != fubenId)
|
||
{
|
||
if (AllowCallIn(fubenId, member.SceneClassID))
|
||
{
|
||
StartTeleportProcess(member, fubenId, leader.SceneInstID);
|
||
result = true;
|
||
}
|
||
}
|
||
else if (member.SceneInstID != SceneData.SceneInst)
|
||
{
|
||
if (AllowCallIn(fubenId, member.SceneClassID))
|
||
{
|
||
StartInstProcess(member, SceneData.SceneInst);
|
||
result = true;
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
public static bool AllowCallIn(int leaderSceneId, int memberSceneId)
|
||
{
|
||
return AllowCallIn(leaderSceneId) && AllowCallIn(memberSceneId);
|
||
}
|
||
|
||
private static bool AllowCallIn(int fubenId)
|
||
{
|
||
var result = true;
|
||
var fuben = TableManager.GetFubenByID(fubenId, 0);
|
||
if (fuben != null)
|
||
result = fuben.Type < 2 || fuben.CallTeam > 0;
|
||
return result;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 开始传送到队长所在场景
|
||
/// </summary>
|
||
// 注:这一套流程只允许队长执行,非队长执行将会导致问题
|
||
private void StartTeleportProcess(TeamMember member, int fubenId, int sceneInst)
|
||
{
|
||
if (debugTeamTeleport)
|
||
{
|
||
LogModule.DebugLog(string.Format("Teleport Scene {0} Inst {1}", fubenId, sceneInst));
|
||
LogModule.DebugLog(string.Format("Member Scene {0} Inst {1}", member.SceneClassID, member.SceneInstID));
|
||
LogModule.WarningLog("Teleport Start");
|
||
}
|
||
|
||
// 确保都转入组队移动状态
|
||
if (member.FollowState != TeamFollowState.followMove)
|
||
SetTeamFollowState(TeamFollowState.followMove);
|
||
var packet =
|
||
(CG_REQ_MEMBER_CHANGE_SCENE) PacketDistributed.CreatePacket(MessageID
|
||
.PACKET_CG_REQ_MEMBER_CHANGE_SCENE);
|
||
packet.SetMemberguid((long) member.Guid);
|
||
packet.SetCtype((int) AutoSearchPoint.ChangeMap_Type.WORLDMAP);
|
||
packet.SetTeleportid(-1);
|
||
packet.SetSceneclassid(fubenId);
|
||
packet.SetSceneinstid(sceneInst);
|
||
packet.SetPosX(0);
|
||
packet.SetPosZ(0);
|
||
packet.SendPacket();
|
||
member.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 切换到队长世界线
|
||
/// </summary>
|
||
private void StartInstProcess(TeamMember member, int sceneInst)
|
||
{
|
||
if (debugTeamTeleport)
|
||
{
|
||
LogModule.DebugLog(string.Format("Inst Update {0}", sceneInst));
|
||
LogModule.DebugLog(string.Format("Member Scene {0} Inst {1}", member.SceneClassID, member.SceneInstID));
|
||
LogModule.WarningLog("Inst Update Start");
|
||
}
|
||
|
||
// 确保都转入组队移动状态
|
||
if (member.FollowState != TeamFollowState.followMove)
|
||
SetTeamFollowState(TeamFollowState.followMove);
|
||
var packet =
|
||
(CG_REQ_MEMBER_SCENE_CHANGEINST) PacketDistributed.CreatePacket(MessageID
|
||
.PACKET_CG_REQ_MEMBER_SCENE_CHANGEINST);
|
||
packet.SetMemberguid((long) member.Guid);
|
||
packet.SetSceneInst(sceneInst);
|
||
packet.SendPacket();
|
||
member.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 玩家试图进入帮会场景
|
||
/// </summary>
|
||
// 同样只有队长调用,非队长调用会出现问题
|
||
// 注:进入帮会由服务器发起,因此不予以处理
|
||
private void TeamEnterGuildMap()
|
||
{
|
||
var leader = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[0];
|
||
if (leader.IsValid())
|
||
leader.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
|
||
}
|
||
|
||
// 注:这个方法只能主角队长调用,非主角队长调用会出问题
|
||
// 同TryMatchSceneWithLeader不同,这个传送会限定changeType,teleportId等等参数
|
||
public void TeamChangeSceneFollow(int changeType, int teleportId, int sceneId, int sceneInst, int safeX,
|
||
int safeZ)
|
||
{
|
||
var leader = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[0];
|
||
if (leader.IsValid())
|
||
{
|
||
for (var i = 1; i < GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember.Length; ++i)
|
||
{
|
||
var member = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[i];
|
||
if (member.FollowLeader())
|
||
{
|
||
// 特殊处理:如果队长不处于副本中,
|
||
if (debugTeamTeleport)
|
||
{
|
||
LogModule.DebugLog(string.Format("Teleport Scene {0} Inst {1}", sceneId, sceneInst));
|
||
LogModule.DebugLog(string.Format("Member Scene {0} Inst {1}", member.SceneClassID,
|
||
member.SceneInstID));
|
||
LogModule.WarningLog("Teleport Start");
|
||
}
|
||
|
||
// 确保都转入组队移动状态
|
||
//if (member.FollowState != TeamFollowState.followMove)
|
||
// SetTeamFollowState(TeamFollowState.followMove);
|
||
var packet =
|
||
(CG_REQ_MEMBER_CHANGE_SCENE) PacketDistributed.CreatePacket(MessageID
|
||
.PACKET_CG_REQ_MEMBER_CHANGE_SCENE);
|
||
packet.SetMemberguid((long) member.Guid);
|
||
packet.SetCtype(changeType);
|
||
packet.SetTeleportid(teleportId);
|
||
packet.SetSceneclassid(sceneId);
|
||
packet.SetSceneinstid(sceneInst);
|
||
packet.SetPosX(safeX);
|
||
packet.SetPosZ(safeZ);
|
||
packet.SendPacket();
|
||
member.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
|
||
}
|
||
}
|
||
|
||
leader.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
|
||
}
|
||
}
|
||
|
||
// 注:这个方法只能队长调用
|
||
public void TeamChangeInstFollow(int sceneId, int sceneInst)
|
||
{
|
||
var leader = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[0];
|
||
for (var i = 1; i < GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember.Length; ++i)
|
||
{
|
||
var member = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[i];
|
||
if (member.FollowLeader() && AllowCallIn(sceneId, member.SceneClassID))
|
||
{
|
||
if (debugTeamTeleport)
|
||
{
|
||
LogModule.DebugLog(string.Format("Teleport Scene {0} Inst {1}", sceneId, sceneInst));
|
||
LogModule.DebugLog(string.Format("Member Scene {0} Inst {1}", member.SceneClassID,
|
||
member.SceneInstID));
|
||
LogModule.WarningLog("Teleport Start");
|
||
}
|
||
|
||
// 确保都转入组队移动状态
|
||
if (member.FollowState != TeamFollowState.followMove)
|
||
SetTeamFollowState(TeamFollowState.followMove);
|
||
|
||
if (member.SceneClassID == sceneId)
|
||
{
|
||
if (member.SceneInstID != sceneInst)
|
||
{
|
||
var packet =
|
||
(CG_REQ_MEMBER_SCENE_CHANGEINST) PacketDistributed.CreatePacket(MessageID
|
||
.PACKET_CG_REQ_MEMBER_SCENE_CHANGEINST);
|
||
packet.SetMemberguid((long) member.Guid);
|
||
packet.SetSceneInst(sceneInst);
|
||
packet.SendPacket();
|
||
member.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
var packet =
|
||
(CG_REQ_MEMBER_CHANGE_SCENE) PacketDistributed.CreatePacket(MessageID
|
||
.PACKET_CG_REQ_MEMBER_CHANGE_SCENE);
|
||
packet.SetMemberguid((long) member.Guid);
|
||
packet.SetCtype((int) CG_REQ_CHANGE_SCENE.CHANGETYPE.WORLDMAP);
|
||
packet.SetTeleportid(-1);
|
||
packet.SetSceneclassid(sceneId);
|
||
packet.SetSceneinstid(sceneInst);
|
||
packet.SetPosX(0);
|
||
packet.SetPosZ(0);
|
||
packet.SendPacket();
|
||
member.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
|
||
}
|
||
}
|
||
}
|
||
|
||
leader.teleportFreezeTime = Time.realtimeSinceStartup + _maxMemberTeleportTime;
|
||
}
|
||
|
||
public void TeamLeaderRideUpdate()
|
||
{
|
||
var teamMembers = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember;
|
||
for (var i = 0; i < teamMembers.Length; i++)
|
||
teamMembers[i].ridingMatchLead = false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 队员经过跳跃点执行跳跃
|
||
/// </summary>
|
||
public void WrapTeamMember(ulong guid, int jumpId)
|
||
{
|
||
if (GameManager.gameManager.PlayerDataPool.TeamInfo.IsCaptain() && guid != GUID)
|
||
{
|
||
var teamMember = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember.Find(a => a.Guid == guid);
|
||
if (teamMember != null && teamMember.FollowState == TeamFollowState.followMove)
|
||
{
|
||
var jumpData = TableManager.GetJumpByID(jumpId, 0);
|
||
float warpTime;
|
||
jumpData = jumpData.GetFinialJumpData(out warpTime);
|
||
var position =
|
||
ActiveScene.GetTerrainPosition(new Vector3(jumpData.EndPosX, Position.y, jumpData.EndPosZ));
|
||
// Hack:强制处理记录,防止几帧内不同步导致位置回滚,下一次同步位置应该校正到传送后位置
|
||
teamMember.ScenePos = position.RemoveY();
|
||
var simulator = GetMoveSimulator(teamMember.Guid);
|
||
if (simulator != null)
|
||
simulator.WarpToPosition(teamMember, position, warpTime);
|
||
}
|
||
}
|
||
}
|
||
|
||
private TeamMemberMoveSimulator GetMoveSimulator(ulong? guid)
|
||
{
|
||
TeamMemberMoveSimulator result = null;
|
||
for (var i = 0; i < moveSimulatorList.Count; i++)
|
||
if (moveSimulatorList[i].Guid == guid)
|
||
{
|
||
result = moveSimulatorList[i];
|
||
break;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
private void UpdateTeamFollow()
|
||
{
|
||
// 更新队员跟随位置
|
||
PushLeaderPos(Position);
|
||
if (_nextUpdateFollowTime > Time.unscaledTime || Time.realtimeSinceStartup < AutoSearchAgent.unlockTime)
|
||
return;
|
||
if (GameManager.gameManager == null || !GameManager.gameManager.PlayerDataPool.IsHaveTeam())
|
||
return;
|
||
var leader = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[0];
|
||
if (!leader.IsValid())
|
||
return;
|
||
_nextUpdateFollowTime = Time.unscaledTime + _updateFollowInterval;
|
||
// 队长控制
|
||
if (leader.Guid == ObjManager.Instance.MainPlayer.GUID)
|
||
{
|
||
// 试图为每一个队员预测一个应该走向的位置
|
||
var posIndex = 1;
|
||
for (var i = 1; i < GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember.Length; i++)
|
||
{
|
||
var member = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember[i];
|
||
if (member.IsValid() && member.FollowState != TeamFollowState.notFollow &&
|
||
!TryMatchSceneWithLeader(member, leader))
|
||
{
|
||
// 同队长处于同一场景
|
||
// Hack: 队长的信息可能会慢一个周期更新,因此暂时处理为直接使用玩家本身的信息
|
||
if (InTheSameScene(member))
|
||
{
|
||
switch (member.FollowState)
|
||
{
|
||
case TeamFollowState.followMove:
|
||
// 注:如果主角从来没有移动过,仅仅存在Index为0的点
|
||
posIndex = Mathf.Min(posIndex, _leaderPosList.Count - 1);
|
||
SetTeamMemberPos(member, _leaderPosList[posIndex]);
|
||
posIndex++;
|
||
// 骑乘状态重置时,执行一次骑乘切换
|
||
if (!member.ridingMatchLead)
|
||
{
|
||
member.ridingMatchLead = true;
|
||
SetTeamMemberRide(member, AdcaneMountId >= 0 || (member.ScenePos - leader.ScenePos).sqrMagnitude > _mountDistance.ToSquare());
|
||
}
|
||
break;
|
||
case TeamFollowState.followCombat:
|
||
if ((member.ScenePos - Position.RemoveY()).sqrMagnitude >
|
||
memberLeaveAutoCombatDistance.ToSquare())
|
||
SetTeamFollowState(TeamFollowState.followMove, member.Guid);
|
||
break;
|
||
}
|
||
}
|
||
// 同队长不在一个场景
|
||
else
|
||
{
|
||
if (member.FollowState == TeamFollowState.followCombat)
|
||
SetTeamFollowState(TeamFollowState.followMove, member.Guid);
|
||
}
|
||
}
|
||
}
|
||
// 试图移除不需要的移动模拟器
|
||
for (var i = moveSimulatorList.Count - 1; i >= 0; i--)
|
||
{
|
||
var simulator = moveSimulatorList[i];
|
||
if (simulator.Guid != null)
|
||
{
|
||
var member = GameManager.gameManager.PlayerDataPool.TeamInfo.teamMember.Find(a =>
|
||
a.Guid == simulator.Guid);
|
||
if (member == null ||
|
||
member.FollowState != TeamFollowState.followMove ||
|
||
!InTheSameScene(member))
|
||
moveSimulatorList[i].Deactivate();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private static bool InTheSameScene(TeamMember member)
|
||
{
|
||
return fubenId == member.SceneClassID && SceneData.SceneInst == member.SceneInstID;
|
||
}
|
||
|
||
private void PushLeaderPos(Vector3 pos)
|
||
{
|
||
// 如果主角处于跳跃和无敌斩状态,不缓存当前位置
|
||
if (MovementState == MoveState.Leap || MovementState == MoveState.OnmiSlash)
|
||
return;
|
||
// 每一米推送一个位置
|
||
if (_leaderPosList.Count == 0 || (_leaderPosList[0] - pos).sqrMagnitude > _followDistance.ToSquare())
|
||
{
|
||
if (_leaderPosList.Count >= GlobeVar.MAX_TEAM_MEMBER)
|
||
_leaderPosList.RemoveAt(_leaderPosList.Count - 1);
|
||
_leaderPosList.Insert(0, pos);
|
||
}
|
||
}
|
||
|
||
private void SetTeamMemberPos(TeamMember teamMember, Vector3 targetPos)
|
||
{
|
||
var simulator = GetMoveSimulator(teamMember.Guid);
|
||
if (simulator == null)
|
||
{
|
||
// 试图重用一个未激活的模拟器
|
||
simulator = GetMoveSimulator(null);
|
||
if (simulator == null)
|
||
{
|
||
// 构造新的模拟器
|
||
simulator = new TeamMemberMoveSimulator();
|
||
moveSimulatorList.Add(simulator);
|
||
}
|
||
|
||
simulator.Init(teamMember);
|
||
}
|
||
|
||
simulator.MoveToPosition(teamMember, targetPos);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 队长起跳时,需要清空跳跃效果
|
||
/// </summary>
|
||
private void UpdatePositionForLeap(Tab_Jump jumpTable)
|
||
{
|
||
jumpTable = jumpTable.GetFinialJumpData();
|
||
_leaderPosList.Clear();
|
||
_leaderPosList.Add(
|
||
ActiveScene.GetTerrainPosition(new Vector3(jumpTable.EndPosX, Position.y, jumpTable.EndPosZ)));
|
||
}
|
||
|
||
private void SetTeamMemberRide(TeamMember teamMember, bool isRide)
|
||
{
|
||
if (isRide)
|
||
{
|
||
var packet =
|
||
(CG_REQ_TEAM_MEMBER_SINGLE_MOUNT) PacketDistributed.CreatePacket(MessageID
|
||
.PACKET_CG_REQ_TEAM_MEMBER_SINGLE_MOUNT);
|
||
packet.SetMemberguid(teamMember.Guid);
|
||
packet.SendPacket();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 队友运动模拟器
|
||
/// </summary>
|
||
// 注:Team里面,队友位置并不满足0.2s内更新,因此只能使用这个组件来进行高精度追踪
|
||
public class TeamMemberMoveSimulator
|
||
{
|
||
private NavMeshAgent _agent;
|
||
|
||
public ulong? Guid { get; private set; }
|
||
|
||
public void Init(TeamMember teamMember)
|
||
{
|
||
Guid = teamMember.Guid;
|
||
var position = GetTeamMemberPos(teamMember);
|
||
var agentName = "TeamMemberSimulator_" + Guid;
|
||
if (_agent == null)
|
||
{
|
||
var gameObject = new GameObject(agentName);
|
||
gameObject.transform.position = position;
|
||
gameObject.transform.rotation = Quaternion.identity;
|
||
gameObject.transform.localScale = Vector3.one;
|
||
_agent = gameObject.AddComponent<NavMeshAgent>();
|
||
SetBasicNavAgentParameter(_agent);
|
||
SetNavAgentAreaMask(_agent, true);
|
||
_agent.angularSpeed = 30000f;
|
||
_agent.speed = teamMember.MoveSpeed;
|
||
}
|
||
else
|
||
{
|
||
_agent.gameObject.name = agentName;
|
||
_agent.gameObject.SetActive(true);
|
||
_agent.ResetPath();
|
||
_agent.Warp(position);
|
||
}
|
||
}
|
||
|
||
private static Vector3 GetTeamMemberPos(TeamMember teamMember)
|
||
{
|
||
var obj = ObjManager.Instance.FindOtherPlayerByGuid(teamMember.Guid);
|
||
var position = obj == null
|
||
? ActiveScene.GetTerrainPosition(teamMember.ScenePos.InsertY())
|
||
: obj.Position;
|
||
return position;
|
||
}
|
||
|
||
public void Deactivate()
|
||
{
|
||
Guid = null;
|
||
if (_agent != null)
|
||
{
|
||
_agent.gameObject.name = "TeamMemberSimulator_Inactive";
|
||
_agent.gameObject.SetActive(false);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 队员经由跳跃点传送到目标位置
|
||
/// </summary>
|
||
public void WarpToPosition(TeamMember teamMember, Vector3 position, float warpTime)
|
||
{
|
||
if (warpTime > 0f)
|
||
teamMember.warpFreezeTime = Time.unscaledTime + Mathf.Min(_maxMemberTeleportTime, warpTime);
|
||
else
|
||
teamMember.warpFreezeTime = 0f;
|
||
_agent.Warp(position);
|
||
}
|
||
|
||
public void MoveToPosition(TeamMember teamMember, Vector3 position)
|
||
{
|
||
// 动态修改移动速度
|
||
_agent.speed = teamMember.MoveSpeed;
|
||
if (Time.unscaledTime > teamMember.warpFreezeTime)
|
||
{
|
||
var obj = ObjManager.Instance.FindOtherPlayerByGuid(teamMember.Guid);
|
||
var sourcePos = obj == null
|
||
? ActiveScene.GetTerrainPosition(teamMember.ScenePos.InsertY())
|
||
: obj.Position;
|
||
var differDist = obj == null ? _maxSimulatorDiffer : _objSimulatorDiffer;
|
||
// 角色距离差值超过容忍范围
|
||
if ((sourcePos.RemoveY() - _agent.transform.position.RemoveY()).sqrMagnitude >
|
||
differDist.ToSquare())
|
||
{
|
||
LogModule.WarningLog(string.Format("Team Member {0}, Pos {1} is too far from {2}", teamMember.Guid,
|
||
_agent.transform.position.ToPreciseString(),
|
||
sourcePos.ToPreciseString()));
|
||
_agent.Warp(sourcePos);
|
||
teamMember.warpFreezeTime = 0f;
|
||
}
|
||
// 特殊处理跳跃等待情况,防止预测机锁死在OffmeshLink
|
||
if (!_agent.isOnOffMeshLink)
|
||
{
|
||
if (!_agent.isOnNavMesh)
|
||
_agent.Warp(sourcePos);
|
||
if (_agent.isOnNavMesh)
|
||
{
|
||
var path = _agent.path;
|
||
if ((position - _agent.transform.position).RemoveY().sqrMagnitude >
|
||
navAgentPercision.ToSquare())
|
||
{
|
||
Vector3 predictPos;
|
||
if (_agent.CalculatePath(position, path))
|
||
{
|
||
var moveDelta = _agent.speed * _updateFollowPredictTime;
|
||
predictPos = path.GetPointOnPath(_agent.transform.position, moveDelta);
|
||
_agent.SetPath(path);
|
||
}
|
||
else
|
||
{
|
||
_agent.isStopped = true;
|
||
predictPos = _agent.transform.position;
|
||
}
|
||
|
||
// 角色执行常规移动
|
||
var packet =
|
||
(CG_REQ_TEAM_MEMBER_MOVE) PacketDistributed.CreatePacket(MessageID
|
||
.PACKET_CG_REQ_TEAM_MEMBER_MOVE);
|
||
packet.SetMemberguid((long) teamMember.Guid);
|
||
packet.SetPoscount(1);
|
||
packet.AddPosx(predictPos.x.ToServerPos());
|
||
packet.AddPosy(predictPos.y.ToServerPos());
|
||
packet.AddPosz(predictPos.z.ToServerPos());
|
||
packet.SetIsmoving(1);
|
||
packet.SendPacket();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
LogModule.ErrorLog(string.Format("Cannot fix TeamMember {0} at Pos {1} onto NavMesh at Scene {2}!",
|
||
teamMember.Guid, teamMember.ScenePos.ToPreciseString(), GameManager.gameManager == null ? "Null" : fubenId.ToString()));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 非队长移动使用OffmeshLink进行判断
|
||
// 仅仅在服务器位置处于容错范围内时,才正式开始跳跃;否则呼叫角色走到跳跃点位置
|
||
if ((teamMember.ScenePos - _agent.transform.position.RemoveY()).sqrMagnitude >
|
||
_jumpSimulatorDiffer.ToSquare())
|
||
{
|
||
var packet =
|
||
(CG_REQ_TEAM_MEMBER_MOVE) PacketDistributed.CreatePacket(MessageID
|
||
.PACKET_CG_REQ_TEAM_MEMBER_MOVE);
|
||
packet.SetMemberguid((long) teamMember.Guid);
|
||
packet.SetPoscount(1);
|
||
packet.AddPosx(_agent.transform.position.x.ToServerPos());
|
||
packet.AddPosy(_agent.transform.position.y.ToServerPos());
|
||
packet.AddPosz(_agent.transform.position.z.ToServerPos());
|
||
packet.SetIsmoving(1);
|
||
packet.SendPacket();
|
||
}
|
||
else
|
||
{
|
||
teamMember.warpFreezeTime = Time.unscaledTime + MainPlayerJumpWait.maxWaitTime;
|
||
var offMeshLink = _agent.currentOffMeshLinkData.offMeshLink;
|
||
if (offMeshLink != null)
|
||
{
|
||
var jumpPoint = offMeshLink.GetComponent<Obj_JumpPoint>();
|
||
if (jumpPoint != null)
|
||
{
|
||
var jumpProtocol =
|
||
(CG_JUMP) PacketDistributed.CreatePacket(MessageID.PACKET_CG_JUMP);
|
||
// 注:无视这个警告,Guid不存在时,根本不会更新
|
||
jumpProtocol.SetTargetguid(Guid.Value);
|
||
jumpProtocol.SetJumpid(jumpPoint.GetJumpId());
|
||
jumpProtocol.SetTag(0);
|
||
jumpProtocol.SendPacket();
|
||
jumpPoint.GetJumpId();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} |