using CommonAI.RTS; using CommonLang.Vector; using CommonAI.Zone; using CommonAI.Zone.Helper; using CommonLang; using System; using System.Collections.Generic; using CommonAI.Zone.Attributes; using CommonAI.ZoneClient.Agent; using CommonLang.Log; namespace CommonAI.ZoneClient { public class ZoneActor : ZoneUnit { protected Logger log = LoggerFactory.GetLogger("CommonAI"); public override float X { get { return mLocalPos.X; } } public override float Y { get { return mLocalPos.Y; } } public override bool TouchObj { get { if (Parent.Templates.CFG.PLAYER_NONE_TOUCH) return false; return base.TouchObj; } } /// /// 单位释放技能时,自动朝向锁定敌人 /// public bool IsSkillAutoFocusTarget { get; set; } /// /// 当前是否为自动战斗 /// public bool IsGuard { get; set; } /// /// 当前是否为自动跟随 /// public bool IsFollow { get; set; } //标识是否处于被嘲讽中 protected bool mIsMocking = false; //标识点击了技能按钮,等待服务器下发的DoForceSyncPosEvent中 //此期间会停止响应移动操作 //protected int mIsWaittingSkillLaunch = 0; /// /// 选中的目标单位 /// public uint TargetUnitID { get { return (mFocusTarget != null) ? mFocusTarget.targetUnitID : 0; } } public PlayerFocuseTargetEvent LastFocusTarget { get { return mFocusTarget; } } /// /// 进入场景推送过来的数据 /// public LockActorEvent LoginData { get { return mLoginData; } } public UnitActionStatus RemoteStatus { get { return mRemoteState.UnitMainState; } } private readonly LockActorEvent mLoginData; // private TimeInterval mCheckGuard; private SyncMode mCurrentSyncMode; private SyncPosEvent.UnitPos mRemoteSyncPos; //private SyncPosEvent.UnitState mRemoteSyncState; private UnitAxisAction mSendAxis; private bool mSendAxisSmoothTurn = false; private Vector2 mSendFaceTo; private UnitUpdatePosAction mSendPos; private readonly UnitUpdatePosAction mLastSendPos = new UnitUpdatePosAction(); private readonly float mMinStepSEC; private PlayerFocuseTargetEvent mFocusTarget; public ZoneActor(UnitInfo unit, LockActorEvent info, ZoneLayer parent) : base(unit, info.UnitData, parent, null) { this.mMinStepSEC = Templates.CFG.OBJECT_MOVE_TO_MIN_STEP_SEC; //this.mCheckGuard = new TimeInterval(Templates.CFG.AI_VIEW_TRIGGER_CHECK_TIME_MS); this.mLoginData = info; this.ResetItems(); if (info.CurrentPlayerVars != null) { foreach (CommonAI.ZoneClient.ClientStruct.ZoneEnvironmentVar var in info.CurrentPlayerVars) { mEnvironmentVarMap[var.Key] = var.Value; } } } protected override void Disposing() { this.clearAgents(); this.clearSkillAction(); base.Disposing(); //this.mOnGuardFocusTarget = null; } public override void InitSkills() { //actor有单独的消息推送,不读配置 } protected internal override void OnAdded() { base.OnAdded(); /*if (mLoginData.Skills != null) //稍后有消息推送,重复了 { this.DoEvent(mLoginData.Skills); }*/ SyncBuffStatus(mLoginData.UnitData.CurrentBuffStatus); SyncSkillStatus(mLoginData.CurrentSkillStatus); SyncItems(mLoginData.CurrentItemStatus); this.mCurrentSyncMode = Parent.ActorSyncMode; Parent.SendAction(new UnitSetSyncModeAction(this.ObjectID, Parent.ActorSyncMode)); } //------------------------------------------------------------------------------------------- /// /// 截获后端发送的事件 /// /// internal protected override void DoEvent(ObjectEvent e) { if (Parent.ActorSyncMode == SyncMode.MoveByClient_PreSkillByClient) { //忽略Jump,客户端本地PreSkillClient已经处理位移// if (e is UnitJumpEvent) { return; } } if (e is PlayerSkillStopEvent) { doPlayerSkillStopEvent(e as PlayerSkillStopEvent); } else if (e is UnitForceSyncPosEvent) { doForceSyncPosEvent(e as UnitForceSyncPosEvent); } else if (e is UnitSkillActionChangeEvent) { doUnitSkillActionChangeEvent(e as UnitSkillActionChangeEvent); } else if (e is UnitSyncInventoryItemEvent) { DoSyncItem(e as UnitSyncInventoryItemEvent); } else if (e is UnitUseItemEvent) { DoUseItem(e as UnitUseItemEvent); } if (e is UnitForceSyncPosEvent && mCurrentSkillAction is PreSkillByClient) { var action = mCurrentSkillAction as PreSkillByClient; if (action.SkillData.ActionPriority == 0) return; } base.DoEvent(e); } //------------------------------------------------------------------------------------- #region __Agents__ private List mAgents = new List(1); private List mUpdateAgents = new List(1); public int AgentCount { get { return mAgents.Count; } } public AbstractAgent AddAgent(AbstractAgent agent) { if (!agent.IsDuplicate) { for (int i = mAgents.Count - 1; i >= 0; --i) { var ag = mAgents[i]; if (agent.GetType() == ag.GetType()) { ag.Abort(); RemoveAgent(ag); } } } mAgents.Add(agent); agent.InternalInit(this); //Parent.QueueTask((z) => //{ // agent.InternalStart(); //}); agent.InternalStart(); return agent; } public bool RemoveAgent(AbstractAgent agent) { if (mAgents.Remove(agent)) { //Parent.QueueTask((z) => //{ // agent.InternalEnd(); // agent.Dispose(); //}); agent.InternalEnd(); agent.Dispose(); return true; } return false; } public T GetAgentByType() where T : AbstractAgent { for (int i = 0; i < mAgents.Count; i++) { if (mAgents[i] is T) { return mAgents[i] as T; } } return null; } private void ForEachAgent(Action action) { mUpdateAgents.AddRange(mAgents); try { mUpdateAgents.ForEach(action); } finally { mUpdateAgents.Clear(); } } private void MAgents_OnBeginUpdate(AbstractAgent obj) { if (obj.IsEnd) { RemoveAgent(obj); } else { obj.InternalBeginUpdate(Parent.CurrentIntervalMS); } } private void MAgents_OnEndUpdate(AbstractAgent obj) { if (obj.IsEnd) { RemoveAgent(obj); } else { obj.InternalEndUpdate(Parent.CurrentIntervalMS); } } private void ForEachAgentOnBeginUpdate() { mUpdateAgents.AddRange(mAgents); try { for (int i = 0, n = mUpdateAgents.Count; i < n; i++) { MAgents_OnBeginUpdate(mUpdateAgents[i]); } } finally { mUpdateAgents.Clear(); } } private void ForEachAgentOnEndUpdate() { mUpdateAgents.AddRange(mAgents); try { for (int i = 0, n = mUpdateAgents.Count; i < n; i++) { MAgents_OnEndUpdate(mUpdateAgents[i]); } } finally { mUpdateAgents.Clear(); } } private void clearAgents() { foreach (var agt in mAgents) { agt.Dispose(); } mAgents.Clear(); } #endregion //------------------------------------------------------------------------------------------- internal protected override void Update() { base.Update(); UpdateItems(Parent.CurrentIntervalMS); //ForEachAgent(MAgents_OnEndUpdate); ForEachAgentOnEndUpdate(); } //------------------------------------------------------------------------------------------- #region __update_预处理__ internal protected override void UpdateAI() { ForEachAgentOnBeginUpdate(); int intervalMS = Parent.CurrentIntervalMS; if (IsGuard) { update_ai_Guard(intervalMS); } else if (IsFollow) { } else { if (mCurrentSyncMode != Parent.ActorSyncMode) { mCurrentSyncMode = Parent.ActorSyncMode; Parent.SendAction(new UnitSetSyncModeAction(this.ObjectID, Parent.ActorSyncMode)); } switch (Parent.ActorSyncMode) { case SyncMode.ForceByServer: update_ai_ForceByServer(intervalMS); break; case SyncMode.MoveByClient_PreSkillByClient: update_ai_MoveByClient_PreSkillByClient(intervalMS); break; } } updateServerSkillAction(intervalMS); mSendFaceTo = null; mSendPos = null; } private void update_ai_Guard(int intervalMS) { base.UpdateAI(); } // 服务端强同步 // private void update_ai_ForceByServer(int intervalMS) { if (mSendAxis != null) { //请求服务端移动// Parent.SendAction(mSendAxis); } else if (mSendPos != null) { Parent.SendAction(mSendPos); } } // 客户端本地处理移动,实时上传自己坐标位置,技能预先本地表现 // private void update_ai_MoveByClient_PreSkillByClient(int intervalMS) { UnitAxisAction axis = mSendAxis; //有摇杆动作// if (axis != null && !axis.IsZero) { // 处理技能以及控制位移 // if (mCurrentSkillAction is PreSkillByClient) { var action = mCurrentSkillAction as PreSkillByClient; //客户端预先技能动作// if (action.IsDone) { base.mDirection = base.mDirectionChange; clearSkillAction(); Parent.SendAction(axis); SetCurrentState(UnitActionStatus.Move); } else { if (IsCanControlMove) { Parent.SendAction(axis); if (action.SkillData.ActionPriority == -1 || action.SkillData.ID == 110500 || action.SkillData.ID == 110510 || action.SkillData.ID == 110520 || action.SkillData.ID == 110530 || action.SkillData.ID == 110540 || action.SkillData.ID == 110550 || action.SkillData.ID == 110560) { action.setMoveTo(axis); SkillState state = action.State; if (state.ActionType == ActionEnum.chargeAtk && state.CurrentActionID == 1) { this.SetCurrentState(UnitActionStatus.ChargeAtkMove, 0, null); } } } } } else if (mCurrentSkillAction is PreSkillByServer) { float direction = MathVector.getDegree(axis.dx, axis.dy); if (IsCanControlMove) { float ispeed = MoveHelper.GetDistance(intervalMS, base.MoveSpeedSEC); float addX = (float)(Math.Cos(direction) * ispeed); float addY = (float)(Math.Sin(direction) * ispeed); var action = mCurrentSkillAction as PreSkillByServer; if (action != null && action.State != null && action.State.ActionType == ActionEnum.chargeAtk) { this.SetCurrentState(UnitActionStatus.ChargeAtkMove); } this.PreBlockMove(ref addX, ref addY); this.PreMove(addX, addY); } if (IsCanControlFaceTo) { if (mSendAxisSmoothTurn) { base.mDirectionChange = direction; base.mDirection = MoveHelper.DirectionChange( mDirectionChange, mDirection, this.TurnSpeedSEC, intervalMS); } else { base.mDirection = direction; base.mDirectionChange = direction; } } } else { //if (mCurrentSkillAction == null && mIsWaittingSkillLaunch > 0) //{ // launchSkill消息还没下发,暂停移动,解决移动--》普攻的位移抖动 // --mIsWaittingSkillLaunch; // YXJDebug.logWarning(">>ignore moving, when waitting launching skill:{0}", mIsWaittingSkillLaunch); //} //else { float ispeed = MoveHelper.GetDistance(intervalMS, base.MoveSpeedSEC); float direction = MathVector.getDegree(axis.dx, axis.dy); float addX = (float)(Math.Cos(direction) * ispeed); float addY = (float)(Math.Sin(direction) * ispeed); if (IsCanControlMove) { this.PreBlockMove(ref addX, ref addY); this.PreMove(addX, addY); this.SetCurrentState(UnitActionStatus.Move); } if (IsCanControlFaceTo) { if (mSendAxisSmoothTurn) { base.mDirectionChange = direction; base.mDirection = MoveHelper.DirectionChange( mDirectionChange, mDirection, this.TurnSpeedSEC, intervalMS); } else { base.mDirection = direction; base.mDirectionChange = direction; } } } } } else { //停止技能移动// if (mCurrentSkillAction is PreSkillByClient) { var action = mCurrentSkillAction as PreSkillByClient; action.setMoveTo(null); SkillState state = action.State; if (state.ActionType == ActionEnum.chargeAtk && state.CurrentActionID > 0) { this.SetCurrentState(UnitActionStatus.ChargeAtkIdle); } } //处理UpdatePos移动// else if (mSendPos != null) { if (IsCanControlFaceTo) { base.mDirection = mSendPos.d; base.mDirectionChange = mSendPos.d; } if (IsCanControlMove) { SetCurrentState(mSendPos.st); this.PreSetPos(mSendPos.x, mSendPos.y); } } else { if (!mIsMocking && CurrentState == UnitActionStatus.Move) { SetCurrentState(UnitActionStatus.Idle); } //嘲讽时间到了后,服务器没有置状态,客户端强制置回(有隐患) if (CurrentState == UnitActionStatus.ServerSyncMove && (CurrentSubState & (byte)UnitActionSubStatus.Mocking) == 0) { SetCurrentState(UnitActionStatus.Idle); } } if (mSendFaceTo != null) { if (mCurrentSkillAction is PreSkillByClient) { var action = mCurrentSkillAction as PreSkillByClient; //客户端预先技能动作// if (!action.IsDone) { action.setFaceTo(mSendFaceTo); } else { this.PreFaceTo(mSendFaceTo.X, mSendFaceTo.Y); } } else if (CurrentState == UnitActionStatus.Move || CurrentState == UnitActionStatus.Idle) { this.PreFaceTo(mSendFaceTo.X, mSendFaceTo.Y); } } } //有主动控制位移状态// if (CurrentState == UnitActionStatus.Move || CurrentState == UnitActionStatus.Idle || mCurrentSkillAction != null) { if (mSkillMove != null && mSkillMove.Update(intervalMS)) { mIsSkillMove = false; mSkillMove = null; } } else { FixPos(intervalMS, mLocalPos, mPos); if (mSkillMove != null) { mSkillMove.Stop(); mSkillMove = null; } } //客户端预先技能动作// if (mCurrentSkillAction is PreSkillByClient) { var action = mCurrentSkillAction as PreSkillByClient; action.onUpdate(intervalMS); if (mCurrentSkillAction.IsDone) { clearSkillAction(); } } updatePosActionCache.object_id = this.ObjectID; updatePosActionCache.isHalf = Parent.IsHalfSync; updatePosActionCache.x = mLocalPos.X; updatePosActionCache.y = mLocalPos.Y; updatePosActionCache.d = mDirection; updatePosActionCache.st = CurrentState; if (!updatePosActionCache.DataEquals(mLastSendPos)) { //YXJDebug.logWarning(">>>>>>>>>>>>>>>SendServerPos:{0},{1}", updatePosActionCache.x, updatePosActionCache.y); Parent.SendAction(updatePosActionCache); } mLastSendPos.Set(updatePosActionCache); } private readonly UnitUpdatePosAction updatePosActionCache = new UnitUpdatePosAction(); #endregion //----------------------------------------------------------------------------------------------------------- #region __sync_pos_同步服务器坐标__ //------------------------------------------------------------------------------------------- private void doForceSyncPosEvent(UnitForceSyncPosEvent e) { //YXJDebug.logError(">>Player_DoForceSyncPosEvent:{0},{1}, state:{2},{3}", e.X, e.Y, e.UnitMainState, e.UnitSubState); if (this.Parent != null && this.Parent.IsSceneDujie() && e.UnitMainState == (byte)UnitActionStatus.Move) { //YXJDebug.logWarning(">IgnoreForceSyncPos_p@move: {0}{1}, state:{2},{3}", ObjectID, Name, e.UnitMainState, e.UnitSubState); return; } //技能移动本地做预演,坐标修正在update中去做(服务器协议发错,应该是syncpos,之前已经告知服务器) if ((UnitActionStatus)e.UnitMainState != UnitActionStatus.Skill) { ForceSyncPos(e.X, e.Y); } //else if ((e.UnitSubState & (byte)UnitActionSubStatus.ChargeAtkIdle) != 0) //{ // mIsWaittingSkillLaunch = 0; //} this.mDirection = mDirectionChange = mRemoteSyncPos.Direction = e.Direction; this.mRemoteState.UnitMainState = (UnitActionStatus)e.UnitMainState; this.mRemoteState.UnitSubState = e.UnitSubState; base.SetCurrentState(ref mRemoteState); if (mCurrentSkillAction != null) { if (RemoteStatus != UnitActionStatus.Skill) { clearSkillAction(); } else if(mCurrentSkillAction.SkillData.ID == 603064) //成魔3技能,要支持Blink,,,暂时先这么着 { ForceSyncPos(e.X, e.Y); } } } protected internal override void UpdatePos(int intervalMS) { if (IsGuard || IsFollow || mIsMocking) { base.UpdatePos(intervalMS); } } public override void SyncPos(ref SyncPosEvent.UnitState pos) { //if(mIsWaittingSkillLaunch > 0) //{ // if(pos.UnitMainState != UnitActionStatus.Skill) // { // mIsWaittingSkillLaunch = 0; // } //} //更新被嘲讽状态 mIsMocking = (pos.UnitSubState & (byte)UnitActionSubStatus.Mocking) != 0; this.mRemoteState = pos; if (IsGuard || IsFollow) { this.SetCurrentState(ref mRemoteState); } else { switch (Parent.ActorSyncMode) { case SyncMode.ForceByServer: sync_pos_ForceByServer(ref pos); break; case SyncMode.MoveByClient_PreSkillByClient: sync_pos_MoveByClient_PreSkillByClient(ref pos); break; } if (pos.UnitSubState != this.CurrentSubState) { base.SetCurrentSubState(pos.UnitSubState); } } } public override void SyncPos(ref SyncPosEvent.UnitPos pos) { this.mRemoteSyncPos = pos; if (IsGuard || IsFollow) { base.mDirection = pos.Direction; base.mDirectionChange = pos.Direction; base.SyncPos(ref pos); } else { base.mPos.SetX(pos.X); base.mPos.SetY(pos.Y); switch (Parent.ActorSyncMode) { case SyncMode.ForceByServer: sync_pos_ForceByServer(ref pos); break; case SyncMode.MoveByClient_PreSkillByClient: sync_pos_MoveByClient_PreSkillByClient(ref pos); break; } //YXJDebug.logWarning(">>{0}>PlayersyncPos, curState:{1}/{2}-->{3}/{4}, x:{5},y:{6}", Name, (int)CurrentState, (int)CurrentSubState, (int)mRemoteState.UnitMainState, (int)mRemoteState.UnitSubState, pos.X, pos.Y); if (mIsMocking) { this.mDirectionChange = pos.Direction; this.mDirection = MoveHelper.DirectionChange(mDirectionChange, mDirection, mTurnSpeedSEC, Parent.CurrentIntervalMS); if (CurrentState == UnitActionStatus.Idle && mRemoteState.UnitMainState == UnitActionStatus.Move) { this.SetCurrentState(ref mRemoteState); } } } } private void sync_pos_ForceByServer(ref SyncPosEvent.UnitState pos) { this.SetCurrentState(ref pos); } private void sync_pos_ForceByServer(ref SyncPosEvent.UnitPos pos) { // 强同步 // base.mLocalPos.SetX(pos.X); base.mLocalPos.SetY(pos.Y); base.mDirection = pos.Direction; base.mDirectionChange = pos.Direction; if (Parent.IsSyncZ) { this.Z = pos.Z; } } private void sync_pos_MoveByClient_PreSkillByClient(ref SyncPosEvent.UnitState pos) { if (CurrentState == UnitActionStatus.Idle || CurrentState == UnitActionStatus.Move || CurrentState == UnitActionStatus.ServerSyncMove) { if (RemoteStatus == UnitActionStatus.Skill) { this.SetCurrentState(ref mRemoteState); } else if (RemoteStatus != UnitActionStatus.Idle && RemoteStatus != UnitActionStatus.Move && RemoteStatus != UnitActionStatus.ServerSyncMove) { this.SetCurrentState(ref mRemoteState); } //不能移动切入,状态置成Idle(不应该有互斥状态存在 跑和不能移动) else if (pos.UnitMainState == UnitActionStatus.Move && (pos.UnitSubState & (byte)UnitActionSubStatus.CanNotMove) != 0) { this.SetCurrentState(ref mRemoteState); } } else { this.SetCurrentState(ref mRemoteState); } if (mCurrentSkillAction != null) { if (RemoteStatus != UnitActionStatus.Skill) { clearSkillAction(); } } //if (SetStealtState != null) //{ // log.Error("SetStealtState :" + ((pos.UnitSubState & (byte)UnitActionSubStatus.Stealth) != 0).ToString()); // SetStealtState((pos.UnitSubState & (byte)UnitActionSubStatus.Stealth) != 0); //} } private void sync_pos_MoveByClient_PreSkillByClient(ref SyncPosEvent.UnitPos pos) { if (CurrentState == UnitActionStatus.Idle || CurrentState == UnitActionStatus.Move || CurrentState == UnitActionStatus.ServerSyncMove) { if (RemoteStatus == UnitActionStatus.Skill) { } else if (RemoteStatus != UnitActionStatus.Idle && RemoteStatus != UnitActionStatus.Move && RemoteStatus != UnitActionStatus.ServerSyncMove) { base.mDirection = pos.Direction; base.mDirectionChange = pos.Direction; } } else { // 强同步 // if (RemoteStatus != UnitActionStatus.Skill && RemoteStatus != UnitActionStatus.Idle && RemoteStatus != UnitActionStatus.Move) { base.mDirection = pos.Direction; base.mDirectionChange = pos.Direction; //UnityEngine.Debug.Log("syncpos ID = " + pos.ID + " D = " + pos.Direction); } } } #endregion //------------------------------------------------------------------------------------------- #region __Item__ private HashMap> mCoolDownItems = new HashMap>(); internal void SyncItems(ClientStruct.UnitItemStatus[] items) { if (items != null) { mItemSlots = new List(items.Length); foreach (ClientStruct.UnitItemStatus st in items) { ItemSlot slot = new ItemSlot(this); if (st.Count > 0) { slot.Sync(st); } mItemSlots.Add(slot); } } } private void ResetItems() { mItemSlots = new List(Info.InventorySize); for (int i = 0; i < Info.InventorySize; i++) { mItemSlots.Add(new ItemSlot(this)); } } private void UpdateItems(int intervalMS) { if (mCoolDownItems.Count > 0) { using (var removed = ListObjectPool>.AllocAutoRelease()) { foreach (TimeExpire expire in mCoolDownItems.Values) { if (expire.Update(intervalMS)) { removed.Add(expire); } } if (removed.Count > 0) { foreach (TimeExpire expire in removed) { if (expire.IsEnd) { mCoolDownItems.RemoveByKey(expire.Tag.ID); } } } } } } protected virtual void DoSyncItem(UnitSyncInventoryItemEvent me) { ItemSlot slot = GetItem(me.Index); if (slot != null) { slot.Set(me); } } protected virtual void DoUseItem(UnitUseItemEvent me) { ItemTemplate item = Templates.getItem(me.ItemTemplateID); if (item != null) { if (item.UseCoolDownTimeMS > 0) { mCoolDownItems.Put(item.ID, new TimeExpire(item, item.UseCoolDownTimeMS)); } } } public TimeExpire GetCoolDownItem(int itemTemplateID) { return mCoolDownItems.Get(itemTemplateID); } internal List mItemSlots = new List(); public class ItemSlot { public ZoneUnit Owner { get; private set; } private ItemTemplate data; private int count; public bool IsEmpty { get { return count == 0 || data == null; } } public ItemTemplate Data { get { return data; } } public int Count { get { return count; } } public ItemSlot(ZoneUnit unit) { this.Owner = unit; } internal void Sync(ClientStruct.UnitItemStatus syn) { ItemTemplate item = Owner.Templates.getItem(syn.ItemTemplateID); if (item != null) { this.data = item; this.count = syn.Count; } } internal void Set(UnitSyncInventoryItemEvent me) { if (this.data != null && this.data.ID == me.ItemTemplateID) { this.count = me.Count; return; } ItemTemplate item = Owner.Templates.getItem(me.ItemTemplateID); if (item != null) { this.data = item; this.count = me.Count; } } } [Obsolete] public List GetItemSlots() { return new List(mItemSlots); } public void GetItemSlots(List ret) { ret.AddRange(mItemSlots); } public ItemSlot GetItem(int index) { if (index >= 0 && index < mItemSlots.Count) { return mItemSlots[index]; } return null; } public ItemSlot GetItemByTemplateID(int itemTemplateID) { for (int i = mItemSlots.Count - 1; i >= 0; --i) { ItemSlot slot = mItemSlots[i]; if (!slot.IsEmpty && slot.Data.TemplateID == itemTemplateID) { return slot; } } return null; } #endregion //----------------------------------------------------------------------------------------------------------- #region __SEND_ACTION_TO_SERVER__ public void SendAction(ObjectAction act) { Parent.SendAction(act); } public void SendRequest(ActorRequest req, ZoneLayer.OnResponseHandler handler, ZoneLayer.OnRequestTimeoutHandler timeout = null, int timeOutMS = 15000) { Parent.SendRequest(req, handler, timeout, timeOutMS); } public void SendReady() { Parent.SendAction(new UnitReadAction(base.ObjectID)); } public void SendUnitAxis(float angle, bool smooth_turn = false) { this.mSendPos = null; if (IsGuard || IsFollow) return; UnitAxisAction ma = new UnitAxisAction(base.ObjectID); ma.dx = (float)Math.Cos(angle); ma.dy = (float)Math.Sin(angle); mSendAxis = ma; mSendAxisSmoothTurn = smooth_turn; } public void SendUnitAxis(float dx, float dy, bool smooth_turn = false) { this.mSendPos = null; if (IsGuard || IsFollow) return; UnitAxisAction ma = new UnitAxisAction(base.ObjectID); ma.dx = dx; ma.dy = dy; mSendAxis = ma; mSendAxisSmoothTurn = smooth_turn; } public void SendUpdatePos(float x, float y, float direction, UnitActionStatus st) { mSendAxis = null; if (IsGuard || IsFollow) { return; } if (Parent.ActorSyncMode != SyncMode.MoveByClient_PreSkillByClient) { return; } this.mSendPos = new UnitUpdatePosAction(this.ObjectID, Parent.IsHalfSync, x, y, direction, st); } public void SendUnitMove(float x, float y) { mSendAxis = null; mSendPos = null; if (!IsGuard) return; if (Parent.ActorSyncMode == SyncMode.MoveByClient_PreSkillByClient) return; UnitMoveAction ma = new UnitMoveAction(base.ObjectID, x, y); Parent.SendAction(ma); } public void SendUnitFaceTo(float d) { if (Parent.ActorSyncMode == SyncMode.MoveByClient_PreSkillByClient) { float dx = (float)Math.Cos(d) * 100; float dy = (float)Math.Sin(d) * 100; this.mSendFaceTo = new Vector2(dx + this.X, dy + this.Y); } UnitFaceToAction ma = new UnitFaceToAction(base.ObjectID, d); //UnityEngine.Debug.Log("SendUnitFaceTo d = " + d); Parent.SendAction(ma); } public void SendUnitFaceTo(float wx, float wy) { float d = (float)Math.Atan2(wy - this.Y, wx - this.X); if (Parent.ActorSyncMode == SyncMode.MoveByClient_PreSkillByClient) { this.mSendFaceTo = new Vector2(wx, wy); } UnitFaceToAction ma = new UnitFaceToAction(base.ObjectID, d); Parent.SendAction(ma); } public void SendUnitStopMove() { mSendAxis = null; mSendPos = null; UnitStopMoveAction ma = new UnitStopMoveAction(base.ObjectID); Parent.SendAction(ma); } public void SendUnitSlip(float x, float y) { mSendAxis = null; mSendPos = null; if (Parent.ActorSyncMode == SyncMode.MoveByClient_PreSkillByClient) return; UnitSlipAction ma = new UnitSlipAction(base.ObjectID, x, y); Parent.SendAction(ma); } /// /// 新增技能移动 /// /// public void SendUnitSkillMove(SkillMove skillMove) { var skill = this.GetSkillState(skillMove.SkillID); if (skill != null) { Parent.SendAction(skillMove); } } public void SendUnitLaunchSkill(UnitLaunchSkillAction launch) { //mSendAxis = null; //mSendPos = null; var skill = this.GetSkillState(launch.SkillID); if (skill != null) { Parent.SendAction(launch); //mIsWaittingSkillLaunch = 10; //YXJDebug.logWarning(">>LaunchSkill:{0}", launch.SkillID); } } public void SendUnitLaunchSkill(int skillID, uint targetObjectID) { UnitLaunchSkillAction launch = new UnitLaunchSkillAction(base.ObjectID, skillID); launch.IsAutoFocusNearTarget = IsSkillAutoFocusTarget; launch.TargetObjID = targetObjectID; SendUnitLaunchSkill(launch); } public void SendUnitLaunchSkill(int skillID) { UnitLaunchSkillAction launch = new UnitLaunchSkillAction(base.ObjectID, skillID); launch.IsAutoFocusNearTarget = IsSkillAutoFocusTarget; SendUnitLaunchSkill(launch); } public void SendUnitLaunchSkill(int skillID, float x, float y) { UnitLaunchSkillAction launch = new UnitLaunchSkillAction(base.ObjectID, skillID); launch.IsAutoFocusNearTarget = IsSkillAutoFocusTarget; if (x != X || y != Y) { launch.SpellTargetPos = new Vector2(x, y); } SendUnitLaunchSkill(launch); } public void SendUnitLaunchNormalAttack(float x, float y) { UnitLaunchSkillAction launch = new UnitLaunchSkillAction(base.ObjectID, BaseSkillID); launch.IsAutoFocusNearTarget = IsSkillAutoFocusTarget; if (x != X || y != Y) { launch.SpellTargetPos = new Vector2(x, y); } SendUnitLaunchSkill(launch); } public void SendUnitGuard(bool auto) { mSendAxis = null; mSendPos = null; //IsGuard = auto; Parent.SendAction(new UnitGuardAction(ObjectID, auto)); } public void SendUnitFollow(bool auto) { mSendAxis = null; mSendPos = null; //IsFollow = auto; Parent.SendAction(new UnitFollowAction(ObjectID, auto)); } public void SendUnitGuard(bool auto, string reason) { mSendAxis = null; mSendPos = null; //IsGuard = auto; Parent.SendAction(new UnitGuardAction(ObjectID, auto, reason)); } public void SendUnitAttackMoveTo(float x, float y, bool attack = false) { UnitAttackToAction ma = new UnitAttackToAction(base.ObjectID, x, y, attack); Parent.SendAction(ma); } public void SendUnitFocuseTarget(uint targetID) { if ((Parent.GetObject(targetID) != null)) { UnitFocuseTargetAction ma = new UnitFocuseTargetAction(base.ObjectID, targetID); Parent.SendAction(ma); } } public void SendUnitUseItem(int index, int count = 1) { UnitUseItemAction use = new UnitUseItemAction(base.ObjectID, index, count); Parent.SendAction(use); } public void SendUnitPickObject(uint pickableID) { mSendAxis = null; mSendPos = null; UnitPickObjectAction act = new UnitPickObjectAction(ObjectID, pickableID); Parent.SendAction(act); } public void SendCancelBuff(int buffID) { BuffState bs = GetBuff(buffID); if (bs != null) { UnitCancelBuffAction act = new UnitCancelBuffAction(ObjectID, bs.Data.TemplateID); Parent.SendAction(act); } } public void SendSetSubState(byte substate) { UnitSetSubStateAction use = new UnitSetSubStateAction(base.ObjectID, substate); Parent.SendAction(use); } //新增回城状态 public void SetLocalClientState(UnitActionStatus states, object evt) { SetCurrentState(states, evt); } #endregion //----------------------------------------------------------------------------------------------------------- #region __PreMoveAndSkill__ public virtual bool IsCanControlMove { get { //渡劫地图 if(Parent!= null && Parent.IsSceneDujie()) { if (CurrentState == UnitActionStatus.Idle) { //YXJDebug.logError(">>在渡劫场景,try to move??{0}", CurrentState); } return false; } //收到不能移动的状态,就是不能动 if ((CurrentSubState & (byte)UnitActionSubStatus.CanNotMove) != 0) { return false; } if (CurrentState == UnitActionStatus.Skill) { if (this.CurrentActorSkillAction is PreSkillByClient) { var st = this.CurrentActorSkillAction as PreSkillByClient; return st.IsControlMoveable; } else if (this.CurrentActorSkillAction is PreSkillByServer) { var st = this.CurrentActorSkillAction as PreSkillByServer; return st.IsControlMoveable; } return false; } return (CurrentState == UnitActionStatus.Move || CurrentState == UnitActionStatus.Idle || CurrentState == UnitActionStatus.Pick || CurrentState == UnitActionStatus.DaZuo || CurrentState == UnitActionStatus.DaZuoRecoveryAttr || CurrentState == UnitActionStatus.ChargeAtkIdle || CurrentState == UnitActionStatus.ChargeAtkMove || CurrentState == UnitActionStatus.HomeBack); } } public virtual bool IsCanControlFaceTo { get { if (CurrentState == UnitActionStatus.Skill) { if (this.CurrentActorSkillAction is PreSkillByClient) { var st = this.CurrentActorSkillAction as PreSkillByClient; return st.IsControlFaceable; } else if (this.CurrentActorSkillAction is PreSkillByServer) { var st = this.CurrentActorSkillAction as PreSkillByServer; return st.IsControlFaceable; } return false; } return CurrentState == UnitActionStatus.Move || CurrentState == UnitActionStatus.Idle || CurrentState == UnitActionStatus.Pick || CurrentState == UnitActionStatus.ChargeAtkIdle || CurrentState == UnitActionStatus.ChargeAtkMove; } } private PreSkillStartMove mSkillMove = null; internal protected void PreFaceTo(float x, float y) { if (this.X == x && this.Y == y) { return; } float d = (float)(Math.Atan2(y - this.Y, x - this.X)); if (d != mDirection || d != this.mDirectionChange) { this.mDirection = this.mDirectionChange = d; } } internal protected void PreTurnTo(float add) { this.mDirection += add; this.mDirectionChange = this.mDirection; } /// /// 尝试客户端移动 /// /// TRUE=无法移动 internal protected bool PreMoveTo(float x, float y, float speedSEC, int intervalMS) { float distance = MoveHelper.GetDistance(intervalMS, speedSEC); float minstep = MoveHelper.GetDistance(intervalMS, mMinStepSEC); if (Math.Abs(distance) < minstep) { return true; } float ddx = x - mLocalPos.X; float ddy = y - mLocalPos.Y; if (Math.Abs(ddx) < distance && Math.Abs(ddy) < distance) { return false; } float angle = MathVector.getDegree(ddx, ddy); return PreMoveToInner(angle, distance); } /// /// 尝试客户端移动 /// /// /// /// /// TRUE=无法移动 internal protected bool PreMoveTo(float angle, float speedSEC, int intervalMS) { float distance = MoveHelper.GetDistance(intervalMS, speedSEC); float minstep = MoveHelper.GetDistance(intervalMS, mMinStepSEC); if (Math.Abs(distance) < minstep) { return true; } mIsSkillMove = true; return PreMoveToInner(angle, distance); } internal protected bool PreMoveToInner(float angle, float distance) { float dx = (float)(Math.Cos(angle) * distance); float dy = (float)(Math.Sin(angle) * distance); float oldx = mLocalPos.X; float oldy = mLocalPos.Y; int tick = 0; if (this.TouchMap) { mLocalPos.AddX(dx); if (Parent.TouchMap(this)) { mLocalPos.SetX(oldx); tick++; } mLocalPos.AddY(dy); if (Parent.TouchMap(this)) { mLocalPos.SetY(oldy); tick++; } } else { mLocalPos.AddX(dx); mLocalPos.AddY(dy); } if (tick >= 2) { return true; } if (Templates.CFG.OBJECT_NONE_TOUCH || !this.TouchObj) { ZoneUnit zu = Parent.TouchBuilding(this); if (this.TouchMap && zu != null) { mLocalPos.SetY(oldy); mLocalPos.SetX(oldx); if (Parent.TouchObject2(this, zu)) { PreElasticOtherObject(zu); } return true; } } else { ZoneUnit zu = Parent.TouchUnit(this); if (zu != null) { mLocalPos.SetY(oldy); mLocalPos.SetX(oldx); if (Parent.TouchObject2(this, zu)) { PreElasticOtherObject(zu); } return true; } } return false; } //----------------------------------------------------------------------------------------------------------- public virtual void PreSetPos(float x, float y) { mLocalPos.SetX(x); mLocalPos.SetY(y); } protected virtual void PreMove(float dx, float dy) { mLocalPos.AddX(dx); mLocalPos.AddY(dy); } internal protected void PreJumpTo(float direction, float speedSEC, int intervalMS) { float distance = MoveHelper.GetDistance(intervalMS, speedSEC); float dx = (float)(Math.Cos(direction) * distance); float dy = (float)(Math.Sin(direction) * distance); float oldx = mLocalPos.X; float oldy = mLocalPos.Y; if (this.TouchMap) { mLocalPos.AddX(dx); if (Parent.TouchMap(this)) { mLocalPos.SetX(oldx); } mLocalPos.AddY(dy); if (Parent.TouchMap(this)) { mLocalPos.SetY(oldy); } if (Parent.TouchBuilding(this) != null) { mLocalPos.SetY(oldy); mLocalPos.SetX(oldx); } } else { mLocalPos.AddX(dx); mLocalPos.AddY(dy); } } /// /// 获取当前最适合攻击的目标 /// /// /// /// public ZoneUnit PreGetSkillAttackableFirstTarget(SkillTemplate skill, ref bool directionChange) { using (var list = ListObjectPool.AllocAutoRelease()) { Parent.GetSkillAttackableUnits(this, skill, list); if (list.Count > 0) { float rg = GetSkillAttackRange(skill); // 检测攻击范围内的单位 // float dr = skill.AttackAngle / 2; foreach (ZoneUnit u in list) { if (CMath.intersectFanRound(this.X, this.Y, rg, u.X, u.Y, u.Info.BodyHitSize, this.Direction - dr, this.Direction + dr)) { directionChange = false; return u; } } // 优先当前朝向的目标 // dr = CMath.PI_DIV_2; directionChange = true; foreach (ZoneUnit u in list) { if (CMath.intersectFanRound(this.X, this.Y, rg, u.X, u.Y, u.Info.BodyHitSize, this.Direction - dr, this.Direction + dr)) { return u; } } // 最后选取最近的目标 // ZoneUnit min = null; float min_len = float.MaxValue; foreach (ZoneUnit u in list) { float len = MathVector.getDistanceSquare(u.X, u.Y, X, Y); if (min_len > len) { min_len = len; min = u; } } return min; } } return null; } public PreSkillStartMove PreSkillMove( float direction, float rotateSpeedSEC, int expectlTimeMS, float moveSpeedSEC, float moveSpeedAdd, float moveSpeedAcc, float moveZSpeed, float zgravity, float zlimit, bool isNoneTouch) { if (mSkillMove != null) { mSkillMove.Stop(); } PreSkillStartMove move = new PreSkillStartMove(this, direction, rotateSpeedSEC, expectlTimeMS, moveSpeedSEC, moveSpeedAdd, moveSpeedAcc, moveZSpeed, zgravity, zlimit, isNoneTouch); mSkillMove = move; return move; } /// /// 被别的单位挤开 /// /// public bool PreElasticOtherObjects() { if (this.TouchObj) { bool force_sync = false; Parent.ForEachNearObjects(X, Y, (ZoneObject o, ref bool cancel) => { ZoneUnit u = o as ZoneUnit; if ((u != null) && (o != this) && (o.TouchObj) && Parent.TouchObject2(this, o)) { PreElasticOtherObject(u); force_sync = true; } }); return force_sync; } return false; } /// /// 被别的单位挤开 /// /// public void PreElasticOtherObject(ZoneUnit o) { float targetAngle = MathVector.getDegree(this.X, this.Y, o.X, o.Y); float ddr = MathVector.getDistance(this.X, this.Y, o.X, o.Y); float bdr = (this.BodySize + o.BodySize); float distance = -(bdr - ddr); float dx = (float)(Math.Cos(targetAngle) * distance); float dy = (float)(Math.Sin(targetAngle) * distance); float oldx = mLocalPos.X; float oldy = mLocalPos.Y; if (this.TouchMap) { mLocalPos.AddX(dx); if (Parent.TouchMap(this)) { mLocalPos.SetX(oldx); } mLocalPos.AddY(dy); if (Parent.TouchMap(this)) { mLocalPos.SetY(oldy); } } else { mLocalPos.AddX(dx); mLocalPos.AddY(dy); } } /// /// 和所有单位(包括地图)做碰撞检测,是否阻挡 /// /// /// /// /// 阻挡 public bool PreBlockMove(ref float addX, ref float addY) { if (this.TouchMap) { if (Parent.TryTouchMap(this, this.X + addX, this.Y)) { addX = 0; } if (Parent.TryTouchMap(this, this.X, this.Y + addY)) { addY = 0; } if (Parent.TryTouchMap(this, this.X + addX, this.Y + addY)) { addX = 0; addY = 0; } if (addX == 0 && addY == 0) { return true; } } /** 暂时屏蔽 地图上只有地图阻挡 float x = this.X + addX; float y = this.Y + addY; float r = this.Info.BodySize; if (this.TouchObj) { ZoneUnit u = Parent.TryTouchUnit(this, x, y); if (u != null) { addX = 0; addY = 0; if (Parent.TouchObject2(u, this)) { Vector2 bpos = new Vector2(u.X, u.Y); MathVector.movePolar(bpos, MathVector.getDegree(u.X - this.X, u.Y - this.Y), this.Info.BodySize + u.Info.BodySize); addX = bpos.x - this.X; addY = bpos.x - this.X; } return true; } } else if (this.TouchMap) { ZoneUnit u = Parent.TryTouchBuilding(this, x, y); if (u != null) { addX = 0; addY = 0; if (Parent.TouchObject2(u, this)) { Vector2 bpos = new Vector2(u.X, u.Y); MathVector.movePolar(bpos, MathVector.getDegree(u.X - this.X, u.Y - this.Y), this.Info.BodySize + u.Info.BodySize); addX = bpos.x - this.X; addY = bpos.x - this.X; } return true; } } **/ return false; } /* public class ForceMoveAgent { private readonly ZoneActor actor; private AstarManhattan.MWayPoint path; public bool IsEnd { get { return path != null; } } private ForceMoveAgent(ZoneActor actor, float x, float y) { this.actor = actor; } public bool Start(float toX, float toY) { AstarManhattan.FindPathResult ret = actor.Parent.FindPathResult(actor.X, actor.Y, toX, toY, out path); if (ret == AstarManhattan.FindPathResult.Destination) { } else if (ret == AstarManhattan.FindPathResult.Cross) { } else { return false; } return true; } public void Stop() { } internal void Update(int deltatime) { } internal void Dispose() { if (path != null) { path.Dispose(); } } }*/ #endregion //-------------------------------------------------------------------------------------------------------- #region __SkillActionStatus__ /// /// 是否客户端位移模式 /// public bool IsClientControlMove { get { if (IsGuard || IsFollow) return false; if (Parent.ActorSyncMode != SyncMode.MoveByClient_PreSkillByClient) return false; return true; } } private ISkillAction mCurrentSkillAction; public override ISkillAction CurrentSkillAction { get { return mCurrentSkillAction; } } public IActorSkillAction CurrentActorSkillAction { get { return mCurrentSkillAction as IActorSkillAction; } } public SkillState CurrentSkillState { get { if (mCurrentSkillAction is IActorSkillAction) { return (mCurrentSkillAction as IActorSkillAction).State; } return null; } } protected override void doLaunchSkillAction(UnitLaunchSkillEvent me) { clearSkillAction(); SkillState state = GetSkillState(me.skill_id); if (state != null) { if (IsClientControlMove) { PreSkillByClient action = new PreSkillByClient(this, state); action.onLaunch(me); this.mCurrentSkillAction = action; } else { PreSkillByServer action = new PreSkillByServer(this, state); action.onLaunch(me); this.mCurrentSkillAction = action; } invokeSkillActionStart(mCurrentSkillAction); } } private void updateServerSkillAction(int intervalMS) { if (mCurrentSkillAction != null) { if (mCurrentSkillAction is PreSkillByClient) { if (mCurrentSkillAction.IsDone) { clearSkillAction(); } } else { mCurrentSkillAction.onUpdate(intervalMS); if (mCurrentSkillAction.IsDone) { clearSkillAction(); } } } } private void clearSkillAction() { if (mCurrentSkillAction != null) { if (mCurrentSkillAction.IsJumpAction) { base.DoJumpToTargetEnd(); mCurrentSkillAction.RestJumpAction(false); } mCurrentSkillAction.onStop(); mCurrentSkillAction = null; mIsSkillMove = false; } } private void doPlayerSkillStopEvent(PlayerSkillStopEvent evt) { clearSkillAction(); } private void doUnitSkillActionChangeEvent(UnitSkillActionChangeEvent evt) { if (mCurrentSkillAction != null) { mCurrentSkillAction.onUnitSkillActionChangeEvent(evt); } } //------------------------------------------------------------------------------------------------------- public interface IActorSkillAction { SkillState State { get; } } public class PreSkillByServer : UnitSkillAction, IActorSkillAction { readonly private ZoneActor ownerUnit; readonly private SkillState state; public PreSkillByServer(ZoneActor actor, SkillState state) : base(actor, state.Data) { this.state = state; this.ownerUnit = actor; } public SkillState State { get { return state; } } } public class PreSkillByClient : ISkillAction, IActorSkillAction { readonly private ZoneActor ownerUnit; readonly private SkillTemplate skill; readonly private SkillState state; //-------------------------------------------------------- public ZoneLayer Parent { get { return ownerUnit.Parent; } } public Vector2 StopFaceTo { get; private set; } public SkillState State { get { return state; } } public override bool IsJumpAction { get { return is_jump_action; } } public override bool IsDone { get { return is_done; } } public override byte ActionStepIndex { get { return (launch_event != null) ? launch_event.action_index : (byte)0; } } public override int[] ActionTimeArray { get { return action_time_array; } } public override int TotalTimeMS { get { return total_time_ms; } } public override int CurrentActionIndex { get { return current_action_index; } } public override string CurrentActionName { get { if (current_action != null) return current_action.ActionName; return null; } } public override UnitActionData CurrentAction { get { return current_action; } } public override float ExpirePercent { get { return total_pass_time / (float)TotalTimeMS; } } public override SkillTemplate SkillData { get { return skill; } } public override UnitLaunchSkillEvent LaunchEvent { get { return launch_event; } } public override int CurPassTimeMS { get { return current_pass_time; } } public override float ActionSpeed { get { if (launch_event != null) { if (launch_event.action_speed_add != null && launch_event.action_index < launch_event.action_speed_add.Length) { return launch_event.action_speed + launch_event.action_speed_add[launch_event.action_index]; } return launch_event.action_speed; } return action_speed; } } //-------------------------------------------------------- private UnitLaunchSkillEvent launch_event; private int total_pass_time = 0; private int total_time_ms = 0; private float action_speed = 1f; private int current_action_index = 0; private int current_pass_time = 0; private int current_action_total_time = 0; private bool is_done = false; private ZoneUnit targetUnit; private Vector2 targetPos; private bool is_jump_action = false; private Queue action_queue; private UnitActionData current_action = null; private PopupKeyFrames current_frames = new PopupKeyFrames(); private PreSkillStartMove action_move_time; private int[] action_time_array; private Vector2 move_to; //-------------------------------------------------------- public PreSkillByClient(ZoneActor actor, SkillState state) { this.state = state; this.skill = state.Data; this.ownerUnit = actor; } internal override void onLaunch(UnitLaunchSkillEvent e) { this.launch_event = e; this.current_pass_time = 0; this.action_speed = e.action_speed; this.targetUnit = Parent.GetUnit(e.target_object_id); this.RestJumpAction(false); //TODO 屏蔽了下面这段代码 不知道哪个人才写的 //this.targetUnit = null; if (e.IsSpellTargetPos) { this.targetPos = new Vector2(e.spell_target_pos.X, e.spell_target_pos.Y); this.ownerUnit.PreFaceTo(e.spell_target_pos.X, e.spell_target_pos.Y); } if (skill.IsSingleAction) { var sa = skill.ActionQueue[e.action_index]; this.action_queue = new Queue(1); this.action_queue.Enqueue(sa); this.current_action_index = e.action_index; } else { this.action_queue = new Queue(skill.ActionQueue); this.current_action_index = 0; } if (e.action_time_array != null && e.action_time_array.Length > 0) { this.total_time_ms = e.TotalActionTimeMS; this.action_time_array = e.action_time_array; } else if (skill.IsSingleAction) { this.total_time_ms = skill.ActionQueue[launch_event.action_index].TotalTimeMS; this.action_time_array = new int[] { TotalTimeMS }; } else { this.total_time_ms = skill.ActionQueueTimeMS; this.action_time_array = skill.ActionQueueTimeArray; } nextAction(current_action_index); } internal override void onUnitSkillActionChangeEvent(UnitSkillActionChangeEvent e) { while (this.CurrentActionIndex < e.ActionIndex) { if (!nextAction(current_action_index + 1)) { is_done = true; total_pass_time = TotalTimeMS; break; } } } internal override void RestJumpAction(bool isJumpAction) { is_jump_action = isJumpAction; } internal override void onStop() { if (action_move_time != null) { action_move_time.Stop(); action_move_time = null; } is_done = true; total_pass_time = TotalTimeMS; if (StopFaceTo != null) { ownerUnit.PreFaceTo(StopFaceTo.X, StopFaceTo.Y); } //预演未做完,服务器下发结束的通知 if (current_action != null && current_action.IsJumpToTarget) { doJumpToTarget(); } } internal override void onUpdate(int intervalMS) { int pass_time = (int)(intervalMS * ActionSpeed); this.total_pass_time += pass_time; this.total_pass_time = Math.Min(total_pass_time, TotalTimeMS); this.current_pass_time += pass_time; if (current_action == null) { nextAction(current_action_index + 1); } if (current_action == null) { is_done = true; total_pass_time = TotalTimeMS; } else { // 关键帧 // using (var kfs = ListObjectPool.AllocAutoRelease()) { if (current_frames.PopKeyFrames(current_pass_time, kfs) > 0) { for (int i = 0; i < kfs.Count; i++) { doKeyFrame(kfs[i]); } } } //跳跃动作 if (current_action.IsJumpToTarget) { doJumpToTarget(); } // 移动到目标时,不切换动作 // if (current_action.IsMoveToTarget) { // 冲到目标,立即下段 // doMoveToTarget(); } else { // 技能位移 // if (action_move_time != null) { doMove(intervalMS); } if (move_to != null) { if (IsControlMoveable) { ownerUnit.PreMoveTo(move_to.X, move_to.Y, ownerUnit.MoveSpeedSEC, intervalMS); } else { move_to = null; } } if (current_action.BodyBlockOnAttackRange) { doBodyBlock(); } /*if (IsFaceToTarget) { float tx = 0; float ty = 0; if (getTargetPos(out tx, out ty)) { ownerUnit.PreFaceTo(tx, ty); } }*/ } // 下段动作 // if ((current_action != null) && (current_pass_time >= current_action_total_time)) { current_action = null; if (action_queue.Count == 0) { is_done = true; total_pass_time = TotalTimeMS; } } } } private bool nextAction(int index) { if (action_move_time != null) { action_move_time.Stop(); action_move_time = null; } if (action_queue.Count > 0) { this.current_action_index = index; //NewAction// this.current_action = action_queue.Dequeue(); this.current_frames.AddRange(current_action.KeyFrames); this.current_pass_time = 0; //NewAction// if (launch_event.action_time_array != null) { if (skill.IsSingleAction) { this.current_action_total_time = launch_event.TotalActionTimeMS; } else { this.current_action_total_time = launch_event.action_time_array[current_action_index]; } } else { this.current_action_total_time = current_action.TotalTimeMS; } this.IsCancelableBySkill = current_action.IsCancelableBySkill; this.IsNoneBlock = current_action.IsNoneBlock; this.IsNoneTouch = current_action.IsNoneTouch; this.IsFaceToTarget = current_action.IsFaceToTarget; this.IsCancelableByMove = current_action.IsCancelable; this.IsControlMoveable = current_action.IsControlMoveable; this.IsControlFaceable = current_action.IsControlFaceable; if (current_action.IsMoveToTarget) { doMoveToTarget(); } else if (current_action.IsJumpToTarget) { this.RestJumpAction(true); doJumpToTarget(); } else { this.RestJumpAction(false); } /*服务器已经接管这个了 * if (this.IsFaceToTarget || launch_event.IsAutoFocusNearTarget) { if (targetUnit != null && targetUnit != ownerUnit) { ownerUnit.PreFaceTo( targetUnit.X, targetUnit.Y); } }*/ return true; } current_action = null; return false; } private void doKeyFrame(UnitActionData.KeyFrame kf) { // 关键帧改变状态 if (kf.ChangeStatus != null) { this.IsNoneBlock = kf.ChangeStatus.IsNoneBlock; this.IsNoneTouch = kf.ChangeStatus.IsNoneTouch; this.IsFaceToTarget = kf.ChangeStatus.IsFaceToTarget; this.IsCancelableByMove = kf.ChangeStatus.IsCancelable; this.IsCancelableBySkill = kf.ChangeStatus.IsCancelableBySkill; this.IsControlMoveable = kf.ChangeStatus.IsControlMoveable; this.IsControlFaceable = kf.ChangeStatus.IsControlFaceable; } // 如果关键帧绑定单位位移 if (kf.Move != null && (targetUnit == null || kf.hitTargetMoveEnable)) { StartMove action_move = kf.Move; this.action_move_time = ownerUnit.PreSkillMove( ownerUnit.Direction + action_move.Direction, action_move.RotateSpeedSEC, action_move.KeepTimeMS, action_move.SpeedSEC, action_move.SpeedAdd, action_move.SpeedAcc, action_move.ZSpeedSEC, action_move.OverrideGravity, action_move.ZLimit, action_move.IsNoneTouch); } } private void doMove(int intervalMS) { action_move_time.IsNoneTouch = this.IsNoneTouch; if (action_move_time.IsEnd) { action_move_time = null; } } public void setFaceTo(Vector2 face_to) { if (IsControlFaceable) { ownerUnit.PreFaceTo(face_to.X, face_to.Y); } this.StopFaceTo = face_to; } public void setMoveTo(UnitAxisAction axis, int _tm = 0) { if (axis == null || axis.IsZero) { this.move_to = null; return; } if (this.IsCancelableByMove) { is_done = true; total_pass_time = TotalTimeMS; } float degree = MathVector.getDegree(axis.dx, axis.dy); Vector2 pos = new Vector2(ownerUnit.X, ownerUnit.Y); MathVector.movePolar(pos, degree, MoveHelper.GetDistance((_tm == 0) ? this.TotalTimeMS : _tm, ownerUnit.MoveSpeedSEC)); if (IsControlMoveable) { move_to = pos; } if (IsControlFaceable) { ownerUnit.PreFaceTo(pos.X, pos.Y); } this.StopFaceTo = new Vector2(pos.X, pos.Y); } /// /// 防止技能位移导致单位重合 /// private void doBodyBlock() { ownerUnit.PreElasticOtherObjects(); } /// /// 移动到目标面前 /// private bool doMoveToTarget() { //Force Sync from server// return false; } private bool doJumpToTarget() { if (is_done) { ownerUnit.Z = 0; } else { ownerUnit.Z = MoveHelper.CalulateParabolicHeight(current_action.JumpToTargetHeightZ, current_action.TotalTimeMS, this.current_pass_time); } return false; } public bool getTargetPos(out float x, out float y) { if (targetPos != null) { x = targetPos.X; y = targetPos.Y; return true; } else if (targetUnit != null && targetUnit != ownerUnit) { x = targetUnit.X; y = targetUnit.Y; return true; } x = ownerUnit.X; y = ownerUnit.Y; return false; } } public class PreSkillStartMove { private readonly ZoneClient.ZoneActor owner; private readonly float startDirection; private readonly float moveSpeedAdd; private readonly float moveSpeedAcc; private readonly float RotateSpeedSEC; private float moveSpeedSEC; private FallingDown hasFly; private TimeExpire hitMoveTime; private bool isNoneTouch; public PreSkillStartMove( ZoneClient.ZoneActor owner, float direction, float rotateSpeedSEC, int expectlTimeMS, float moveSpeedSEC, float moveSpeedAdd, float moveSpeedAcc, float moveZSpeed, float zgravity, float zlimit, bool isNoneTouch) { this.RotateSpeedSEC = rotateSpeedSEC; this.moveSpeedSEC = moveSpeedSEC; this.moveSpeedAdd = moveSpeedAdd; this.moveSpeedAcc = moveSpeedAcc / 100f; this.owner = owner; this.startDirection = direction; this.isNoneTouch = isNoneTouch; if (moveZSpeed != 0) { this.hasFly = owner.StartFly(moveZSpeed, zgravity, zlimit); this.TotalTimeMS = hasFly.ExpectTimeMS; } else { this.TotalTimeMS = expectlTimeMS; } this.hitMoveTime = new TimeExpire(TotalTimeMS); this.IsEnd = false; } public void Stop() { this.IsEnd = true; } public bool Update(int intervalMS) { if (RotateSpeedSEC != 0) { float add = MoveHelper.GetDistance(intervalMS, RotateSpeedSEC); owner.PreTurnTo(add); } // 落下 // if (hasFly != null) { owner.PreJumpTo(startDirection, moveSpeedSEC, intervalMS); } else { if (IsNoneTouch) { owner.PreJumpTo(startDirection, moveSpeedSEC, intervalMS); } else { owner.PreMoveTo(startDirection, moveSpeedSEC, intervalMS); } } // 后退 // { MoveHelper.UpdateSpeed(intervalMS, ref moveSpeedSEC, moveSpeedAdd, moveSpeedAcc); } if (hitMoveTime.Update(intervalMS)) { IsEnd = true; } return IsEnd; } public bool IsEnd { get; private set; } public int TotalTimeMS { get; private set; } public bool IsNoneTouch { get { return isNoneTouch; } set { isNoneTouch = value; } } } #endregion //-------------------------------------------------------------------------------------------------------- /*private void DoPlayerFocuseTargetEvent(PlayerFocuseTargetEvent e) { if (this.TargetUnitID != e.targetUnitID) { this.mFocusTarget = e; var target = Parent.GetObject(e.targetUnitID); if (mOnGuardFocusTarget != null) { mOnGuardFocusTarget.Invoke(this, target, e.expectTarget); } } this.mFocusTarget = e; } private OnGuardFocusTargetHandler mOnGuardFocusTarget; /// /// 自动战斗锁定目标 /// /// /// /// public delegate void OnGuardFocusTargetHandler(ZoneActor actor, ZoneObject target, SkillTemplate.CastTarget expect); [EventTriggerDescAttribute("单位持有技能发生变化时触发")] public event OnGuardFocusTargetHandler OnGuardFocusTarget { add { mOnGuardFocusTarget += value; } remove { mOnGuardFocusTarget -= value; } }*/ /* public class MoveAgent { public delegate void EndAction(ZoneActor actor); private readonly ZoneActor actor; private List path; private EndAction endAction; internal MoveAgent(ZoneActor actor) { this.actor = actor; } public void Stop() { path = null; } public bool Start(float toX, float toY, EndAction endAction) { AstarManhattan.MWayPoint wayPoints; AstarManhattan.FindPathResult ret = actor.Parent.FindPathResult(actor.X, actor.Y, toX, toY, out wayPoints); if (ret == AstarManhattan.FindPathResult.Destination) { path.Clear(); path.Add(new Vector2(toX, toY)); } else if (ret == AstarManhattan.FindPathResult.Cross) { path.Clear(); path.Add(new Vector2(actor.X, actor.Y)); do { path.Add(new Vector2(wayPoints.PosX, wayPoints.PosY)); wayPoints = wayPoints.Next; } while (wayPoints != null); } else { return false; } this.endAction = endAction; return true; } private void OnStop() { if (endAction != null) { endAction.Invoke(actor); } endAction = null; } internal void update(int deltatime) { if (path != null) { var pos = path[0]; float length = actor.MoveSpeedSEC * deltatime / 1000f; if (length > 0 && path.Count > 1) { float l = MathVector.getDistance(path[1], path[0]); if (l <= length) { path.RemoveAt(0); } else { MathVector.moveTo(path[0], path[1].x, path[1].y, length); } } //pos = path[0] - pos; //pos = path[0]; //updateAction(path[0].x, path[0].y, userdata); if (path.Count < 2) { OnStop(); } } } } */ //-------------------------------------------------------------------------------------------------------- } }