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();
}
}
}
}
*/
//--------------------------------------------------------------------------------------------------------
}
}