using CSNetwork.GPDataType; using PerfectWorld.Scripts.Player; using System; using System.Collections.Generic; namespace BrewMonster.Scripts { using WorkList = System.Collections.Generic.List; public abstract class CECEPWorkMatcher { public abstract bool Match(CECEPWork work, int workType); } // class CECEPWorkMelee public class CECEPWorkMelee : CECEPWork { int m_iAttackTarget; public CECEPWorkMelee(CECEPWorkMan pWorkMan, int attackTarget) : base(EP_work_ID.WORK_HACKOBJECT, pWorkMan) { m_iAttackTarget = attackTarget; } public override void Start() { GetPlayer().m_iMoveMode = (int)MoveMode.MOVE_STAND; GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_ATTACK_1 + UnityEngine.Random.Range(0, 3)); GetPlayer().EnterFightState(); } public override void Tick(float dwDeltaTime) { GetPlayer().TurnFaceTo(m_iAttackTarget); // Slide to server position A3DVECTOR3 vDir = GetPlayer().m_vServerPos - GetPlayer().GetPos(); float fDist = vDir.Normalize(); if (fDist > 0.0001f) { float fMoveDist = 10.0f * dwDeltaTime * 0.001f; if (fMoveDist > fDist) fMoveDist = fDist; GetPlayer().SetPos(GetPlayer().GetPos() + vDir * fMoveDist); } if (GetPlayer().m_FightCnt.IncCounter(dwDeltaTime)) { Finish(); } } public override void Cancel() { GetPlayer().TurnFaceTo(0); } }; public class CECEPWorkIDMatcher : CECEPWorkMatcher { int m_workID; public CECEPWorkIDMatcher(int workID) { m_workID = workID; } public override bool Match(CECEPWork work, int workType) { return work != null && work.GetWorkID() == m_workID; } } // class CECEPWorkCongregate public class CECEPWorkCongregate : CECEPWork { int m_iType; public CECEPWorkCongregate(CECEPWorkMan pWorkMan, int iType) : base(EP_work_ID.WORK_CONGREGATE, pWorkMan) { m_iType = iType; } public override void Start() { } public int GetType() { return m_iType; } } public class CECEPCongregateWorkMatcher : CECEPWorkMatcher { int m_iType; public CECEPCongregateWorkMatcher(int iType) { m_iType = iType; } public override bool Match(CECEPWork work, int workType) { if (work != null && work.GetWorkID() == CECEPWork.EP_work_ID.WORK_CONGREGATE) { CECEPWorkCongregate pCongregateWork = work as CECEPWorkCongregate; return pCongregateWork.GetType() == m_iType; } return false; } } // class CECEPWorkIdle public class CECEPWorkIdle : CECEPWork { int m_iType; bool m_bOTCheck; CECCounter m_OTCnt; uint m_dwParam; public CECEPWorkIdle(CECEPWorkMan pWorkMan, int iType, int iOTTime, uint dwParam) : base(EP_work_ID.WORK_IDLE, pWorkMan) { m_dwParam = dwParam; m_iType = iType; m_bOTCheck = iOTTime > 0 ? true : false; if (m_bOTCheck) { m_OTCnt.SetPeriod(iOTTime); m_OTCnt.Reset(); } switch (iType) { case Idle_work_type.IDLE_SITDOWN: GetPlayer().m_iMoveMode = (int)MoveMode.MOVE_STAND; if (m_dwParam != 0) GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_SITDOWN_LOOP); else { GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_SITDOWN); GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_SITDOWN_LOOP, true, 200, true); } break; case Idle_work_type.IDLE_REVIVE: GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_REVIVE); break; case Idle_work_type.IDLE_BOOTH: GetPlayer().m_iMoveMode = (int)MoveMode.MOVE_STAND; break; } } public override void Tick(float dwDeltaTime) { base.Tick(dwDeltaTime); } public int GetType() { return m_iType; } } public class CECEPIdleWorkMatcher : CECEPWorkMatcher { int m_iType; public CECEPIdleWorkMatcher(int iType) { m_iType = iType; } public override bool Match(CECEPWork work, int workType) { if (work != null && work.GetWorkID() == CECEPWork.EP_work_ID.WORK_IDLE) { CECEPWorkIdle pIdleWork = work as CECEPWorkIdle; return pIdleWork.GetType() == m_iType; } return false; } } public class CECEPWork { public static class EP_work_ID { public const int WORK_INVALID = -1, WORK_STAND = 0, // Stand and do nothing WORK_MOVE = 1, // Move WORK_HACKOBJECT = 2, // Hack specified object (NPC, player etc.) WORK_SPELL = 3, // Spell magic WORK_PICKUP = 4, // Pickup matter WORK_DEAD = 5, // Dead WORK_USEITEM = 6, // Use item WORK_IDLE = 7, // Idle works WORK_FLASHMOVE = 8, // Flash move WORK_PASSIVEMOVE = 9, // Move controlled by server WORK_CONGREGATE = 10, // Congregate reply WORK_SKILLSTATEACT = 11, // skill buff action NUM_WORK = 12; } // Idle work type public static class Idle_work_type { public const int IDLE_SITDOWN = 0, IDLE_REVIVE = 1, IDLE_BOOTH = 2; } static string[] l_WorkName = new string[EP_work_ID.NUM_WORK] { "WORK_STAND", "WORK_MOVE", "WORK_HACKOBJECT", "WORK_SPELL", "WORK_PICKUP", "WORK_DEAD", "WORK_USEITEM", "WORK_IDLE", "WORK_FLASHMOVE", "WORK_PASSIVEMOVE", "WORK_CONGREGATE", "WORK_SKILLSTATEACT", }; protected int m_iWorkID; protected CECEPWorkMan m_pWorkMan; protected bool m_bFinished; protected EC_ElsePlayer GetPlayer() { return m_pWorkMan.GetPlayer(); } public CECEPWork(int iWorkID, CECEPWorkMan pWorkMan) { m_iWorkID = iWorkID; m_pWorkMan = pWorkMan; m_bFinished = false; } public static string GetWorkName(int iWork) { if (iWork >= EP_work_ID.WORK_STAND && iWork < l_WorkName.Length) { return l_WorkName[iWork]; } else { return "Invalid Work"; } } public string GetWorkName() { return GetWorkName(GetWorkID()); } public int GetWorkID() { return m_iWorkID; } public bool IsFinished() { return m_bFinished; } public virtual void Start() { } public virtual void Tick(float dwDeltaTime) { } public virtual void Cancel() { } public virtual void Finish() { m_bFinished = true; } static bool Validate(int iWork) { return iWork >= EP_work_ID.WORK_STAND && iWork < EP_work_ID.NUM_WORK; } } // class CECEPWorkSpell public class CECEPWorkSpell : CECEPWork { CECCounter m_SkillCnt; CECSkill m_pCurSkill; int m_idCurSkillTarget; public CECEPWorkSpell(CECEPWorkMan pWorkMan, uint dwPeriod, CECSkill pSkill, int target) : base(CECEPWork.EP_work_ID.WORK_SPELL, pWorkMan) { m_pCurSkill = pSkill; m_idCurSkillTarget = target; m_SkillCnt.SetPeriod(dwPeriod); m_SkillCnt.Reset(); } public override void Start() { GetPlayer().m_iMoveMode = (int)MoveMode.MOVE_STAND; } public override void Tick(float dwDeltaTime) { //TO DO: fix later //GetPlayer().m_FightCnt.IncCounter(dwDeltaTime); //int iRealTime = g_pGame.GetRealTickTime(); //if (m_SkillCnt.IncCounter(iRealTime)) //{ // Finish(); //} //else //{ // if (m_idCurSkillTarget != 0) // { // GetPlayer().TurnFaceTo(m_idCurSkillTarget); // } // if (GetPlayer().IsPlayingMoveAction() && !GetPlayer().IsWorkMoveRunning()) // { // 从移动施法到停止移动、会一直在持续播放移动动作,此处暂停 // GetPlayer().PlayAction(CECPlayer::ACT_FIGHTSTAND); // } // if (!GetPlayer().IsPlayingAction()) // { // GetPlayer().PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_FIGHTSTAND); // 技能动作播放完成后、播放战斗站立动作 // } //} } public override void Cancel() { //TO DO: fix later //if (m_pCurSkill != null) //{ // m_pCurSkill = null; //} //m_idCurSkillTarget = 0; //GetPlayer().StopSkillAttackAction(); //GetPlayer().TurnFaceTo(0); } public CECSkill GetSkill() { return m_pCurSkill; } } public class CECEPWorkMan { public static class Work_type { public const int WT_NOTHING = 0, // Do thing WT_NORMAL = 1, // Normal type work WT_INTERRUPT = 2, // Interrupt type work NUM_WORKTYPE = 3; } private EC_ElsePlayer m_pElsePlayer; private WorkList[] m_WorkStack = new WorkList[Work_type.NUM_WORKTYPE] { new List(), new List(), new List() }; private int m_iCurWorkType; public CECEPWorkMan(EC_ElsePlayer pElsePlayer) { m_pElsePlayer = pElsePlayer; m_iCurWorkType = -1; } public EC_ElsePlayer GetPlayer() { return m_pElsePlayer; } public bool ValidateWorkType(int iWorkType) { return iWorkType >= 0 && iWorkType < Work_type.NUM_WORKTYPE; } public bool FindWork(int iWorkType, int iWorkID) { if (!ValidateWorkType(iWorkType)) { return false; } WorkList workList = m_WorkStack[iWorkType]; if (workList != null) { for (int i = 0; i < workList.Count; ++i) { if (iWorkID == workList[i].GetWorkID()) { return true; } } } return false; } public void StartNormalWork(CECEPWork pWork) { StartWork(Work_type.WT_NORMAL, ref pWork); } private bool CanRunSimultaneously(CECEPWork pWork1, CECEPWork pWork2) { if (pWork1.GetWorkID() == CECEPWork.EP_work_ID.WORK_MOVE && pWork2.GetWorkID() == CECEPWork.EP_work_ID.WORK_SPELL) { return CanSpellWhileMoving(pWork2 as CECEPWorkSpell); } if (pWork2.GetWorkID() == CECEPWork.EP_work_ID.WORK_MOVE && pWork1.GetWorkID() == CECEPWork.EP_work_ID.WORK_SPELL) { return CanSpellWhileMoving(pWork1 as CECEPWorkSpell); } return false; } private bool CanReplace(CECEPWork pNewWork, CECEPWork pExistWork) { if (pNewWork.GetWorkID() == CECEPWork.EP_work_ID.WORK_SPELL && pExistWork.GetWorkID() == CECEPWork.EP_work_ID.WORK_SPELL) { return CanSpellWhileMoving(pNewWork as CECEPWorkSpell) && CanSpellWhileMoving(pExistWork as CECEPWorkSpell); } return false; } private bool CanSpellWhileMoving(CECEPWorkSpell pWorkSpell) { return false; // TO DO: fix later // return pWorkSpell.GetSkill() // && CECCastSkillWhenMove.Instance().IsSkillSupported(pWorkSpell.GetSkill().GetSkillID(), GetPlayer()); } private bool CanMergeWithCurrentWork(int iWorkType, CECEPWork pWork) { if (!ValidateWorkType(iWorkType) || iWorkType != m_iCurWorkType) { return false; } WorkList workList = m_WorkStack[iWorkType]; if (workList == null || workList.Count == 0) { return false; } for (int i = 0; i < workList.Count; ++i) { if (!CanRunSimultaneously(pWork, workList[i]) && // 要么同时共存 !CanReplace(pWork, workList[i])) { // 要么可以替换 return false; } } return true; } private void KillWork(int iWorkType, int index) { if (!ValidateWorkType(iWorkType)) { //ASSERT(false); return; } WorkList workList = m_WorkStack[iWorkType]; if (index < 0 || index >= (int)workList.Count) { //ASSERT(false); return; } CECEPWork pWork = workList[index]; pWork.Cancel(); //LOG_DEBUG_INFO(AString().Format("CECEPWorkMan::%s(%s) killed", pWork.GetWorkName(), GetWorkTypeName(iWorkType))); //delete pWork; pWork = null; workList.RemoveAt(index); } private void MergeWork(int iWorkType, CECEPWork pWork) { if (!CanMergeWithCurrentWork(iWorkType, pWork)) { //ASSERT(false); return; } WorkList workList = m_WorkStack[iWorkType]; for (int i = 0; i < workList.Count; ++i) { if (CanReplace(pWork, workList[i])) { //LOG_DEBUG_INFO(AString().Format("CECEPWorkMan::MergeWork %s replacing %s at %s", pWork.GetWorkName(), workList[i].GetWorkName(), GetWorkTypeName(iWorkType))); KillWork(iWorkType, i); workList.Insert(i, pWork); return; } } workList.Add(pWork); //LOG_DEBUG_INFO(AString().Format("CECEPWorkMan::MergeWork %s appended to %s", pWork.GetWorkName(), GetWorkTypeName(iWorkType))); } private void FinishWorkAtWorkType(int iWorkType) { if (!ValidateWorkType(iWorkType)) { //ASSERT(false); return; } WorkList workList = m_WorkStack[iWorkType]; while (workList != null && workList.Count != 0) { KillWork(iWorkType, 0); } if (m_iCurWorkType == iWorkType) { m_iCurWorkType = -1; } } private void AppendWork(int iWorkType, CECEPWork pWork) { if (!ValidateWorkType(iWorkType) || pWork == null) { //ASSERT(false); return; } m_WorkStack[iWorkType].Add(pWork); } private void CancelWorkAtWorkType(int iWorkType) { if (!ValidateWorkType(iWorkType)) { return; } WorkList workList = m_WorkStack[iWorkType]; for (int i = 0; i < workList.Count; ++i) { CancelWork(workList[i]); //LOG_DEBUG_INFO(AString().Format("CECEPWorkMan::%s(%s) cancelled", workList[i].GetWorkName(), GetWorkTypeName(iWorkType))); } } private void CancelWork(CECEPWork pWork) { if (pWork == null) { //ASSERT(false); return; } pWork.Cancel(); } public void StartWork(int iWorkType, ref CECEPWork pWork) { if (!ValidateWorkType(iWorkType)) { pWork = null; return; } if (CanMergeWithCurrentWork(iWorkType, pWork)) { MergeWork(iWorkType, pWork); } else { if (pWork.GetWorkID() == CECEPWork.EP_work_ID.WORK_DEAD) { for (int i = iWorkType; i < Work_type.NUM_WORKTYPE; i++) { FinishWorkAtWorkType(i); } AppendWork(iWorkType, pWork); m_iCurWorkType = iWorkType; } else { bool shouldStart = (iWorkType >= m_iCurWorkType); FinishWorkAtWorkType(iWorkType); AppendWork(iWorkType, pWork); if (!shouldStart) { //LOG_DEBUG_INFO(AString().Format("CECEPWork::StartWork %s flushed %s", pWork.GetWorkName(), GetWorkTypeName(iWorkType))); return; } if (iWorkType > m_iCurWorkType) { CancelWorkAtWorkType(m_iCurWorkType); } m_iCurWorkType = iWorkType; } } pWork.Start(); } private bool IsAnyWorkRunning() { return ValidateWorkType(m_iCurWorkType) && m_WorkStack != null && m_WorkStack[m_iCurWorkType] != null; } private void StartAwaitingWorks() { if (ValidateWorkType(m_iCurWorkType)) { for (--m_iCurWorkType; m_iCurWorkType >= 0; --m_iCurWorkType) { WorkList workList = m_WorkStack[m_iCurWorkType]; if (workList == null || workList.Count == 0) { continue; } for (int j = 0; j < workList.Count; ++j) { workList[j].Start(); //LOG_DEBUG_INFO(AString().Format("CECElsePlayer::StartAwaitingWorks %s(%s) started by decrease priority", workList[j].GetWorkName(), GetWorkTypeName(m_iCurWorkType))); } break; } } } public void Tick(float dwDeltaTime) { if (!IsAnyWorkRunning()) { return; } WorkList workList = m_WorkStack[m_iCurWorkType]; if (workList != null) { for (int i = 0; i < workList.Count;) { CECEPWork pWork = workList[i]; pWork.Tick(dwDeltaTime); if (!pWork.IsFinished()) { ++i; continue; } KillWork(m_iCurWorkType, i); } if (workList == null || workList.Count == 0) { StartAwaitingWorks(); } } } public void FinishWork(CECEPWorkMatcher matcher) { bool bCurrentWorkFinished = false; for (int i = Work_type.NUM_WORKTYPE - 1; i >= 0; --i) { WorkList workList = m_WorkStack[i]; if (workList == null || workList.Count == 0) { continue; } for (int j = 0; j < workList.Count;) { if (!matcher.Match(workList[j], i)) { ++j; continue; } KillWork(i, j); if (i == m_iCurWorkType && (workList == null || workList.Count == 0)) { bCurrentWorkFinished = true; } } } if (bCurrentWorkFinished) { StartAwaitingWorks(); } } public void FinishWork(int idWork) { FinishWork(new CECEPWorkIDMatcher(idWork)); } public bool IsWorkRunning(int iWork) { return FindWork(m_iCurWorkType, iWork); } public void FinishRunningWork(int idWork) { if (!IsWorkRunning(idWork)) { return; } WorkList workList = m_WorkStack[m_iCurWorkType]; if (workList != null) { for (int i = 0; i < workList.Count;) { if (workList[i].GetWorkID() != idWork) { ++i; continue; } //LOG_DEBUG_INFO(AString().Format("CECEPWorkMan::FinishRunningWork %s(%s)", workList[i].GetWorkName(), GetWorkTypeName(m_iCurWorkType))); KillWork(m_iCurWorkType, i); } if (workList == null) { StartAwaitingWorks(); } } } public bool FinishIdleWork(int iType) { FinishWork(new CECEPIdleWorkMatcher(iType)); return true; } public bool FinishCongregateWork(int iType) { FinishWork(new CECEPCongregateWorkMatcher(iType)); return true; } } }