using CommonAI.RTS; using CommonLang.Vector; using CommonAI.Zone.Helper; using CommonAI.Zone.Formula; using CommonLang; using System; using System.Collections.Generic; using System.Linq; using System.Text; using CommonLang.IO; using CommonAI.Data; using CommonAI.Zone.ZoneEditor.EventTrigger; using CommonAI.ZoneClient; namespace CommonAI.Zone.Instance { /// <summary> /// 可自动战斗的可操作单位 /// </summary> public class InstancePlayer : InstanceUnit { private readonly string mPlayerUUID; //private HashMap<string, int> mKilledPlayersID = new HashMap<string, int>(); private CommonAI.ZoneClient.SyncMode mCurrentSyncMode; private bool mIsSkillControlByServer = true; //自动拾取范围 protected float mAutoPickRange = XmdsConstConfig.AUTOPICK_RANGE; protected float mAutoPickSearchRange = XmdsConstConfig.AUTOPICK_RANGE * 3; protected TimeInterval<int> mCheckGuard; protected HashMap<string, QuestData> mQuests = new HashMap<string, QuestData>(); protected UnitLaunchSkillAction mWaitingSkill; protected StatePlayerControlMove mControlMove; protected StatePlayerUpdateMove mUpdateMove; protected StateFollowAndAttack mFocusTarget; protected StateFollowAndPickItem mFocusPickItem; protected StatePlayerAttackTo mAttackTo; public virtual bool isTeamMemberAndFollow() { return false; } public override string PlayerUUID { get { return mPlayerUUID; } } public string ClientID { get; set; } public bool IsGuard { get; set; } public bool IsReady { get; private set; } public override bool IsPlayer { get { return true; } } public override bool IsPlayerUnit { get { return true; } } public override bool IntersectObj { get { return (Templates.CFG.PLAYER_NONE_TOUCH) ? false : base.IntersectObj; } } public override bool IsSkillControllableByServer { get { return mIsSkillControlByServer; } } public CommonAI.ZoneClient.SyncMode ClientSyncMode { get { return mCurrentSyncMode; } } public bool IsRobot { get; set; } public InstancePlayer(InstanceZone zone, UnitInfo info, string name, int force, int level, int alliesForce) : base(zone, info, name, force, level, false, alliesForce) { this.mPlayerUUID = string.IsNullOrEmpty(name) ? "" : name; this.mSyncInfo.PlayerUUID = mPlayerUUID; this.mControlMove = new StatePlayerControlMove(this); this.mUpdateMove = new StatePlayerUpdateMove(this); this.mCheckGuard = new TimeInterval<int>(Templates.CFG.AI_VIEW_TRIGGER_CHECK_TIME_MS); } protected override void Disposing() { /* mControlMove = null; mUpdateMove = null; mFocusTarget = null; mFocusPickItem = null; mAttackTo = null; */ base.Disposing(); } /// <summary> /// 联网模式,断开连接。 /// </summary> public virtual void OnDisconnected() { } /// <summary> /// 联网模式,重新连接。 /// </summary> public virtual void OnReconnected(UnitInfo temp, int force, int level, Vector2 enterPos) { } public virtual LockActorEvent GenLockActorEvent(string displayName, float inRange, float outRange, int updateInterval) { // 准备发送当前场景信息 // var loc = new LockActorEvent(); loc.ServerUpdateInterval = updateInterval; loc.ClientSyncObjectRange = inRange; loc.ClientSyncObjectOutRange = outRange; loc.UnitData = IOUtil.CloneIExternalizable<ZoneClient.SyncUnitInfo>(TemplateManager.MessageCodec, this.GenSyncUnitInfo(true)); loc.UnitData.Name = displayName; loc.UnitData.x = this.X; loc.UnitData.y = this.Y; loc.GameServerProp = CUtils.TryClone(this.Info.Properties); loc.Skills = this.GetSkillEvent(); loc.UnitData.CurrentBuffStatus = this.GetCurrentBuffStatus(); loc.CurrentSkillStatus = this.GetCurrentSkillStatus(); loc.CurrentItemStatus = this.GetCurrentItemStatus(); loc.CurrentPlayerVars = this.GetCurrentUnitVars(); loc.CurrentZoneVars = Parent.GetCurrentZoneVars(); return loc; } protected override void onUpdateRecover() { base.onUpdateRecover(); } override protected void onResetAI() { this.cleanFocus(); this.doSomething(); } protected override void onAdded(bool pointLv) { base.onAdded(pointLv); this.doSomething(); } // override protected void onDead(InstanceUnit attacker) // { // if (attacker is IPlayerUnit) // { // var killer = attacker as IPlayerUnit; // killer.PutKillPlayer(this.PlayerUUID); // } // } override protected void onUpdate(bool slowRefresh) { base.onUpdate(slowRefresh); this.updateGuard(); this.updateCurrentSkill(); this.updateAttackTo(); } protected virtual void updateCurrentSkill() { if (CurrentState is StateSkill) { var current = CurrentState as StateSkill; if (mWaitingSkill != null && current.IsCancelableBySkill) { doLaunchSkill(mWaitingSkill); } else if (IsGuard) { if ((mFocusTarget != null)) { tryLaunchRandomSkillAndCancelCurrentSkill(mFocusTarget.TargetUnit, true); } } } } protected virtual void updateGuard() { if (mFocusTarget != null && !mFocusTarget.IsActive) { mFocusTarget = null; } if (mFocusPickItem != null && !mFocusPickItem.IsActive) { mFocusPickItem = null; } if (IsGuard) { // 旋风斩贴近目标 // if (mFocusTarget != null && CurrentState is StateSkill) { var state = CurrentState as StateSkill; if (state.IsControlMoveable && !state.unit.IsCannotMove) { state.setMoveTo(mFocusTarget.Target.X, mFocusTarget.Target.Y); } } // 没目标定期检测目标 // if ((mFocusTarget == null) && (mFocusPickItem == null)) { if (mCheckGuard.Update(Parent.UpdateIntervalMS)) { var item = findGuardPickItem(); if (item != null) { doFocusPickItem(item); return; } var enemy = findGuardTarget(SkillTemplate.CastTarget.Enemy, AttackReason.Look); if (enemy != null) { doFocusAttack(enemy, SkillTemplate.CastTarget.Enemy); return; } var alias = findGuardTarget(SkillTemplate.CastTarget.AlliesIncludeSelf, AttackReason.Look); if (alias != null) { doFocusAttack(alias, SkillTemplate.CastTarget.AlliesIncludeSelf); return; } } } } } protected virtual void updateAttackTo() { if (mAttackTo != null) { if (mAttackTo.IsDone) { mAttackTo = null; } else if (!mAttackTo.IsAttack) { cleanFocus(); } } } public override void doSomething() { if (mWaitingSkill != null && CurrentState is StateSkill) { if (doLaunchSkill(mWaitingSkill)) { return; } } else if (IsGuard) { if (mFocusPickItem != null && mFocusPickItem.IsActive) { changeState(mFocusPickItem); return; } else { mFocusPickItem = null; } if (mFocusTarget != null && mFocusTarget.IsActive) { if (Parent.IsAttackable(this, mFocusTarget.TargetUnit, SkillTemplate.CastTarget.AlliesIncludeSelf, AttackReason.Attack, Info)) { mFocusTarget = null; } else { changeState(mFocusTarget); return; } } else { mFocusTarget = null; } if (mAttackTo != null && !mAttackTo.IsDone) { changeState(mAttackTo); return; } } base.doSomething(); } public virtual InstanceUnit findGuardTarget(SkillTemplate.CastTarget expect = SkillTemplate.CastTarget.Enemy, AttackReason reason = AttackReason.Look) { InstanceUnit min = null; if (getAvailableSkill(expect) != null) { float min_len = float.MaxValue; Parent.ForEachNearObjects(this.X, this.Y, this.Info.GuardRange, (InstanceUnit u, ref bool cancel) => { if (Parent.IsAttackable(this, u, expect, reason, Info)) { float len = MathVector.getDistanceSquare(u.X, u.Y, this.X, this.Y); if (min_len > len) { min_len = len; min = u; } } }); } return min; } public virtual StateFollowAndAttack doFocusAttack(InstanceUnit target, SkillTemplate.CastTarget expect_target = SkillTemplate.CastTarget.Enemy) { if ((mAttackTo == null || mAttackTo.IsAttack) && Parent.IsAttackable(this, target, expect_target, AttackReason.Tracing, Info)) { if (mFocusTarget != null) { if (mFocusTarget.TargetUnit != target) { mFocusTarget = new StateFollowAndAttack(this, target, expect_target, true); if (changeState(mFocusTarget)) { queueEvent(new PlayerFocuseTargetEvent(this.ID, target.ID, expect_target)); } } } else { mFocusTarget = new StateFollowAndAttack(this, target, expect_target, true); if (changeState(mFocusTarget)) { queueEvent(new PlayerFocuseTargetEvent(this.ID, target.ID, expect_target)); } } } else { mFocusTarget = null; } return mFocusTarget; } //可被自动拾取的,是那种没有进度条的 public virtual InstanceItem findGuardPickItem() { InstanceItem min = null; float min_len = float.MaxValue; Parent.ForEachNearObjects(this.X, this.Y, this.mAutoPickRange, (InstanceItem u, ref bool cancel) => { if (u.IsPickable(this)) { float len = MathVector.getDistanceSquare(u.X, u.Y, this.X, this.Y); if (min_len > len) { min_len = len; min = u; } } }); return min; } public virtual StateFollowAndPickItem doFocusPickItem(InstanceItem target, bool doPick = true) { if (mAttackTo == null || mAttackTo.IsAttack) { if (mFocusPickItem != null) { if (mFocusPickItem.Target != target) { StateFollowAndPickItem focusPickItem = new StateFollowAndPickItem(this, target, doPick); if (changeState(focusPickItem)) { mFocusPickItem = focusPickItem; queueEvent(new PlayerFocuseTargetEvent(this.ID, target.ID, SkillTemplate.CastTarget.NA)); } } } else { StateFollowAndPickItem focusPickItem = new StateFollowAndPickItem(this, target, doPick); if (changeState(focusPickItem)) { mFocusPickItem = focusPickItem; queueEvent(new PlayerFocuseTargetEvent(this.ID, target.ID, SkillTemplate.CastTarget.NA)); } } } else { mFocusPickItem = null; } return mFocusPickItem; } protected virtual void cleanFocus() { mFocusPickItem = null; mFocusTarget = null; } // internal void PutKillPlayer(string killed) // { // int count = 0; // if (mKilledPlayersID.TryGetValue(killed, out count)) // { // mKilledPlayersID.Put(killed, count + 1); // } // else // { // mKilledPlayersID.Put(killed, 1); // } // } //-------------------------------------------------------------------------------------- public virtual bool doRequest(ActorRequest req) { if (req is UnitGetStatisticRequest) { doGetStatisticRequest(req as UnitGetStatisticRequest); return true; } return false; } //设置自动拾取范围 public override void SetAutoPickRange(int value) { this.mAutoPickRange = value; this.mAutoPickSearchRange = value * 3; } protected override void onAction(ObjectAction act) { //log.Info("------<onAction: " + act.ToString()); if (!IsDead()) { if (act is UnitMoveAction) { doMove(act as UnitMoveAction); } else if (act is UnitAxisAction) { doAxis(act as UnitAxisAction); } else if (act is UnitFaceToAction) { doFaceTo(act as UnitFaceToAction); } else if (act is UnitStopMoveAction) { doStopMove(act as UnitStopMoveAction); } else if (act is UnitLaunchSkillAction) { doLaunchSkill(act as UnitLaunchSkillAction); } else if (act is UnitUseItemAction) { doUseItem(act as UnitUseItemAction); } else if (act is UnitPickObjectAction) { doPickObject(act as UnitPickObjectAction); } else if (act is UnitUpdatePosAction) { doUnitUpdatePos(act as UnitUpdatePosAction); } else if (act is UnitCancelBuffAction) { doCancelBuff(act as UnitCancelBuffAction); } else if (act is UnitSetSubStateAction) { doUnitSetSubStateAction(act as UnitSetSubStateAction); } else if (act is PlayPetTeleportAction) { doPetTeleportAction(act as PlayPetTeleportAction); } } if (act is UnitReadAction) { doReady(act as UnitReadAction); } else if (act is UnitGuardAction) { doGuard(act as UnitGuardAction); } else if (act is UnitFollowAction) { doFollow(act as UnitFollowAction); } else if (act is UnitAttackToAction) { doAttackTo(act as UnitAttackToAction); } else if (act is UnitFocuseTargetAction) { doFocusTarget(act as UnitFocuseTargetAction); } else if (act is ChatAction) { doChat(act as ChatAction); } else if (act is UnitSetSyncModeAction) { doSetSyncMode(act as UnitSetSyncModeAction); } else if (act is UnitGetStatisticRequest) { doGetStatisticRequest(act as UnitGetStatisticRequest); } } #region PlayerActions protected virtual void doReady(UnitReadAction act) { if (IsReady == false) { IsReady = true; Parent.cb_playerReady(this); } } protected virtual void doMove(UnitMoveAction ma) { if (CurrentState is StateSkill) { StateSkill ss = CurrentState as StateSkill; ss.setMoveTo(new Vector2(ma.x, ma.y)); } else { cleanFocus(); startMoveTo(ma.x, ma.y); } } protected virtual void doAxis(UnitAxisAction ma) { if (CurrentState is StateSkill) { ma.dx *= 100f; ma.dy *= 100f; StateSkill ss = CurrentState as StateSkill; if (!ma.IsZero) { if (ss.IsCancelableByMove) { cleanFocus(); if (this.mWaitingSkill != null) { doLaunchSkill(this.mWaitingSkill); } else if (mCurrentSyncMode != ZoneClient.SyncMode.MoveByClient_PreSkillByClient) { this.mControlMove.Action = ma; ss.block(mControlMove); } else { ss.block(mUpdateMove); } } else { this.mControlMove.Action = ma; Vector2 moveto = new Vector2(X + ma.dx, Y + ma.dy); ss.setMoveTo(moveto); } } else { ss.setMoveTo(null); } } else if (mCurrentSyncMode != ZoneClient.SyncMode.MoveByClient_PreSkillByClient) { cleanFocus(); if (!ma.IsZero) { this.mControlMove.Action = ma; changeState(mControlMove); } else { doSomething(); } } } protected virtual void doFaceTo(UnitFaceToAction ufa) { if (CurrentActionStatus == UnitActionStatus.Idle || CurrentActionStatus == UnitActionStatus.Move) { this.faceTo(ufa.Direction); } } protected virtual void doStopMove(UnitStopMoveAction act) { cleanFocus(); if (CurrentState is StateSkill) { StateSkill ss = CurrentState as StateSkill; ss.setMoveTo(null); } else if (CurrentState is StateMove || CurrentState is StatePlayerControlMove) { doSomething(); base.SetActionStatus(UnitActionStatus.Idle); } } protected virtual bool doLaunchSkill(UnitLaunchSkillAction sk) { var launched = launchSkill(sk.SkillID, new LaunchSkillParam( sk.TargetObjID, sk.SpellTargetPos, sk.IsAutoFocusNearTarget, sk.SyncDirection, sk.Direction)); if (launched == null) { //Console.WriteLine("UnitLaunchSkillAction - 1"); if (CurrentState is StateSkill) { var state = CurrentState as StateSkill; if (state.SkillData.ID != sk.SkillID || (state.SkillData.IsSingleAction && state.Skill.GetSkillType() != XmdsSkillType.normalAtk)) { //缓存释放技能指令// mWaitingSkill = sk; } } return false; } else { //一旦释放成功,释放指令//\ //Console.WriteLine("UnitLaunchSkillAction - 2"); mWaitingSkill = null; return true; } } protected virtual void doGetStatisticRequest(UnitGetStatisticRequest req) { UnitGetStatisticResponse resp = new UnitGetStatisticResponse(); //if (req.RequestObjectsID != null) //{ // for (int i = 0; i < req.RequestObjectsID.Length; i++) // { // InstanceUnit u = Parent.getUnit(req.RequestObjectsID[i]); // if (u != null) // { // var data = u.Statistic.ToUnitStatisticData(); // resp.Statistics.Put(req.RequestObjectsID[i], data); // } // } //} Parent.sendActorResponse(this, req, resp); } protected virtual void doFocusTarget(UnitFocuseTargetAction focus) { if (IsGuard) { mAttackTo = null; InstanceZoneObject src = Parent.getObject<InstanceZoneObject>(focus.targetUnitID); if ((src is InstanceUnit)) { if (!IsNoneSkill && ((src as InstanceUnit).IsActive)) { doFocusAttack(src as InstanceUnit); } } else if ((src is InstanceItem)) { if (src.Enable) { doFocusPickItem(src as InstanceItem); } } else { cleanFocus(); } } } protected virtual void doAttackTo(UnitAttackToAction act) { if (!act.attack) { cleanFocus(); } mAttackTo = new StatePlayerAttackTo(this, act.targetX, act.targetY, act.attack); changeState(mAttackTo); } protected virtual void doUseItem(UnitUseItemAction use) { UseInventoryItem(use.Index, use.Count); } protected virtual void doPickObject(UnitPickObjectAction pick) { InstanceZoneObject obj = Parent.getObject<InstanceZoneObject>(pick.PickableObjectID); if (obj is InstanceItem) { InstanceItem item = obj as InstanceItem; item.PickItem(this); } else if (obj is InstanceUnit) { InstanceUnit unit = obj as InstanceUnit; this.PickUnit(unit); } } protected virtual void doChat(ChatAction chat) { ChatEvent send = new ChatEvent(chat.To); send.FromPlayerUUID = this.PlayerUUID; send.Message = chat.Message; switch (chat.To) { case ChatMessageType.PlayerToPlayer: InstancePlayer target = Parent.getPlayerByUUID(chat.TargetPlayerUUID); if (target != null) { send.ToPlayerUUID = target.PlayerUUID; Parent.queueEvent(send); } break; case ChatMessageType.PlayerToForce: send.Force = this.Force; Parent.queueEvent(send); break; case ChatMessageType.PlayerToAll: Parent.queueEvent(send); break; } } protected virtual void doUnitUpdatePos(UnitUpdatePosAction act) { //Console.WriteLine("-------------------UnitUpdatePosAction : " + TimeUtil.GetTimestampMS() + ", " + act.x + ", " + act.y + " \t \t" + act.d); if (mCurrentSyncMode == ZoneClient.SyncMode.MoveByClient_PreSkillByClient && !this.IsCannotMove) { //mWaitingSkill = null; mUpdateMove.SetPos(act); if (CurrentState is StateSkill) { var ss = CurrentState as StateSkill; ss.doUpdatePosByClient(act); //服务器判断下,蓄力阶段才同步客户端蓄力状态 if (ss.CurrentActionIndex < ss.SkillData.ActionQueue.Count && ss.SkillData.ActionQueue[ss.CurrentActionIndex].SigleActionType == ActionEnum.chargeAtk) { if (act.st == UnitActionStatus.ChargeAtkMove) { this.RemoveActionSubState(UnitActionSubStatus.ChargeAtkIdle); this.AddActionSubState(UnitActionSubStatus.ChargeAtkMove); } else if (act.st == UnitActionStatus.ChargeAtkIdle) { this.RemoveActionSubState(UnitActionSubStatus.ChargeAtkMove); this.AddActionSubState(UnitActionSubStatus.ChargeAtkIdle); } } } else if (CurrentState is StatePickObject) { if (act.st == UnitActionStatus.Move) { this.faceTo(act.d); this.setPos(act.x, act.y, this.IntersectMap); changeState(mUpdateMove); } } else if (CurrentState is StateDamage || CurrentState is StateDead || CurrentState is IStateNoneControllable) { } else if (CurrentActionStatus == UnitActionStatus.DaZuo || CurrentActionStatus == UnitActionStatus.DaZuoRecoveryAttr || CurrentActionStatus == UnitActionStatus.Idle || CurrentActionStatus == UnitActionStatus.Move) { //changestate在帧中切换状态,这里提前判断下一个动作能否转向 bool canChangeDircetion = true; StateSkill nextSkill = this.NextState as StateSkill; if (nextSkill != null && nextSkill.Skill != null) { UnitActionData action = nextSkill.Skill.GetCurAction(); if(action != null && !action.IsControlFaceable) { canChangeDircetion = false; } } if (canChangeDircetion) { this.faceTo(act.d); } this.setPos(act.x, act.y, this.IntersectMap); if (act.st == UnitActionStatus.Idle) { doSomething(); } else if (act.st == UnitActionStatus.Move) { changeState(mUpdateMove); } //Console.WriteLine("st=" + act.d); } } } protected virtual void doGuard(UnitGuardAction act) { if (this.IsGuard != act.guard) { var IsInCancelingGuard = this.IsGuard; this.IsGuard = act.guard; this.mIsSkillControlByServer = IsGuard || (mCurrentSyncMode != ZoneClient.SyncMode.MoveByClient_PreSkillByClient); if (IsGuard == false) { mAttackTo = null; cleanFocus(); } else { mCheckGuard.Reset(); } resetAI(); if (NextState == null && IsInCancelingGuard && CurrentState is StateSkill) { TryEnqueueIdleState(); } //通知待机状态\ //if (act.forceNotify) { this.Virtual.doEvent(JSGCustomOpType.UpdateAutoBattleFlag); } } } public virtual void doEnterAutoFight() { this.IsGuard = true; } protected virtual void doFollow(UnitFollowAction act) { this.mIsSkillControlByServer = act.follow || (mCurrentSyncMode != ZoneClient.SyncMode.MoveByClient_PreSkillByClient); //this.mIsSkillControlByServer = (mCurrentSyncMode != ZoneClient.SyncMode.MoveByClient_PreSkillByClient); } protected virtual void doSetSyncMode(UnitSetSyncModeAction act) { this.mCurrentSyncMode = act.Mode; this.mIsSkillControlByServer = IsGuard || (mCurrentSyncMode != ZoneClient.SyncMode.MoveByClient_PreSkillByClient); } protected virtual void doCancelBuff(UnitCancelBuffAction act) { BuffState bs = this.GetBuffByID(act.BuffID); if (bs != null && bs.Data.IsCancelBySelf) { this.removeBuff(act.BuffID, BuffState.EndResult_ByClientRemoved); } } protected virtual void doUnitSetSubStateAction(UnitSetSubStateAction act) { base.AddActionSubState((UnitActionSubStatus)(act.UnitSubState)); } protected virtual void doPetTeleportAction(PlayPetTeleportAction act) { InstanceUnit petUnit = this.Virtual.GetPetUnit(); if (petUnit != null) { if (petUnit.petTeleportTime < CommonLang.CUtils.CurrentTimeMS) { petUnit.petTeleportTime = CommonLang.CUtils.CurrentTimeMS+10*1000; petUnit.lastTeleportTime = CommonLang.CUtils.CurrentTimeMS+3*1000; //3秒之后开始返回 //获取玩家当前坐标 float x = this.get_x(); float y = this.get_y(); petUnit.setPos(this.get_x(), this.get_y(), this.IntersectMap); petUnit.faceTo(this.get_direction()); State s = new PetLockState(petUnit); petUnit.changeState(s); } else { if (petUnit.lastTeleportTime < CommonLang.CUtils.CurrentTimeMS) { petUnit.lastTeleportTime = CommonLang.CUtils.CurrentTimeMS+3*1000; //3秒之后开始返回 this.Virtual.SendMsgToClient(CommonAI.XmdsConstConfig.TIPS_CALL_BACK_BTN); } } } } #endregion // -------------------------------------------------------------------------------------- #region PlayerQuests public virtual void InitQuestData(ICollection<QuestData> datas) { foreach (QuestData q in datas) { if (q.QuestID != null) { mQuests.Put(q.QuestID, q); } } } internal QuestData doQuestAccepted(string quest) { if (!string.IsNullOrEmpty(quest)) { QuestData qd = new QuestData(quest); qd.State = QuestState.Accepted; mQuests.Put(quest, qd); return qd; } return null; } internal QuestData doQuestCommitted(string quest) { QuestData qd = mQuests.RemoveByKey(quest); if (qd != null) { qd.State = QuestState.Commited; onQuestCommitted(qd); } return qd; } /// <summary> /// 当任务完成时,子类覆盖的方法被调用 /// </summary> /// <param name="qd"></param> protected virtual void onQuestCommitted(QuestData qd) { } internal QuestData doQuestDropped(string quest) { QuestData qd = mQuests.RemoveByKey(quest); if (qd != null) { qd.State = QuestState.Uncharted; } return qd; } internal QuestData doQuestStatusChanged(string quest, string key, string value) { QuestData qd = mQuests.Get(quest); if (qd != null) { qd.Attributes.Put(key, value); } return qd; } public virtual bool IsQuestAccepted(string quest) { QuestData qd = mQuests.Get(quest); if (qd != null) { string ret; if (qd.Attributes.TryGetValue("state", out ret)) { return ret == "0"; } return qd.State == QuestState.Accepted; } return false; } public virtual string GetQuestStatus(string quest, string key) { QuestData qd = mQuests.Get(quest); if (qd != null) { string value; if (qd.Attributes.TryGetValue(key, out value)) { return value; } } return null; } public virtual QuestData GetQuest(string quest) { return mQuests.Get(quest); } #endregion //-------------------------------------------------------------------------------------- /// <summary> /// 更新坐标移动状态 /// </summary> public class StatePlayerUpdateMove : State { private UnitUpdatePosAction act; public bool IsPosChanged { get { if (act != null) { return act.x != unit.X || act.y != unit.Y; } return false; } } public StatePlayerUpdateMove(InstancePlayer unit) : base(unit) { } public void SetPos(UnitUpdatePosAction act) { // TODO 检测作弊 this.act = act; } public override bool onBlock(State new_state) { return true; } protected override void onStart() { unit.SetActionStatus(UnitActionStatus.Move); } protected override void onUpdate() { unit.SetActionStatus(UnitActionStatus.Move); } protected override void onStop() { } } //-------------------------------------------------------------------------------------- /// <summary> /// 摇杆控制移动状态 /// </summary> protected class StatePlayerControlMove : State { private float mDirection; private UnitAxisAction mAction; public UnitAxisAction Action { get { return mAction; } set { mAction = value; mDirection = MathVector.getDegree(value.dx, value.dy); } } public float Direction { get { return mDirection; } } public StatePlayerControlMove(InstancePlayer unit) : base(unit) { } public override bool onBlock(State new_state) { return true; } protected override void onStart() { unit.SetActionStatus(UnitActionStatus.Move); } protected override void onUpdate() { unit.faceTo(mDirection); unit.moveBlockTo(unit.Direction, unit.MoveSpeedSEC, zone.UpdateIntervalMS); unit.SetActionStatus(UnitActionStatus.Move); } protected override void onStop() { } } //-------------------------------------------------------------------------------------- protected class StatePlayerAttackTo : State { private TargetPos target; private MoveAI moveAI; private bool is_attack; public bool IsAttack { get { return is_attack; } } public bool IsDone { get { return target == null; } } public StatePlayerAttackTo(InstancePlayer unit, float tx, float ty, bool attack) : base(unit) { this.target = new TargetPos(tx, ty); this.is_attack = attack; } public override bool onBlock(State new_state) { return true; } override protected void onStart() { this.moveAI = new MoveAI(unit, true, 0); this.moveAI.IsNoWayAutoFindNear = false; ; if (target != null) { this.moveAI.FindPath(target); unit.SetActionStatus(UnitActionStatus.Move); } else { unit.SetActionStatus(UnitActionStatus.Idle); } } override protected void onUpdate() { if (target == null) { unit.doSomething(); } else { var result = this.moveAI.Update(); if (result.HasFlag(MoveResult.MOVE_RESULT_ARRIVED)) { do_stop(); } else if (result.HasFlag(MoveResult.MOVE_RESULT_MIN_STEP) && result.HasFlag(MoveResult.MOVE_RESULT_NO_WAY)) { do_stop(); } else if (result.HasFlag(MoveResult.MOVE_RESULT_BLOCK_OBJ)) { if (CMath.includeRoundPoint(unit.X, unit.Y, unit.BodyBlockSize, target.X, target.Y)) { do_stop(); } else if (result.obj != null && CMath.includeRoundPoint(result.obj.X, result.obj.Y, result.obj.BodyBlockSize, target.X, target.Y)) { do_stop(); } } } } protected override void onStop() { } private void do_stop() { target = null; unit.doSomething(); } class TargetPos : IPositionObject { public float Direction { get; set; } public float RadiusSize { get; set; } public float X { get; set; } public float Y { get; set; } public TargetPos(float tx, float ty) { this.X = tx; this.Y = ty; } } } } }