feat: add logic and struct class for normal atk.

This commit is contained in:
Tungdv
2025-09-30 17:49:49 +07:00
parent 8b2b181ee2
commit 4bad286d20
13 changed files with 735 additions and 0 deletions
Binary file not shown.
@@ -0,0 +1,417 @@
using DG.Tweening;
using System.Collections.Generic;
using UnityEngine;
using WorkList = System.Collections.Generic.List<CECHPWork>;
public class CECHPWork : CECObjectWork
{
// Host work ID
public static class Host_work_ID
{
public const int WORK_INVALID = -1,
WORK_STAND = 0, // Stand and do nothing
WORK_MOVETOPOS = 1, // Move to a destination terrain position
WORK_TRACEOBJECT = 2, // Trace specified object (NPC, player etc.)
WORK_HACKOBJECT = 3, // Hack specified object (NPC, player etc.)
WORK_SPELLOBJECT = 4, // Spell magic on specified object (NPC, player etc.)
WORK_USEITEM = 5, // Host use item
WORK_DEAD = 6, // Host is dead
WORK_FOLLOW = 7, // Follow some one else
WORK_FLYOFF = 8, // Fly off
WORK_FREEFALL = 9, // Free fall
WORK_SIT = 10, // Sit
WORK_PICKUP = 11, // Pickup item
WORK_CONCENTRATE = 12, // All concentrate work
WORK_REVIVE = 13, // Revive
WORK_FLASHMOVE = 14, // Flash move
WORK_BEBOUND = 15, // Be bound by buddy
WORK_PASSIVEMOVE = 16, // Passive movement (knock back / pull)
WORK_CONGREGATE = 17, // Congregate reply
WORK_SKILLSTATEACT = 18, // skill buff action
WORK_FORCENAVIGATEMOVE = 19, // force navigate move
NUM_WORK = 20;
}
protected static class Work_mask
{
public const uint MASK_STAND = 0x0001,
MASK_MOVETOPOS = 0x0002,
MASK_TRACEOBJECT = 0x0004,
MASK_HACKOBJECT = 0x0008,
MASK_SPELLOBJECT = 0x0010,
MASK_USEITEM = 0x0020,
MASK_DEAD = 0x0040,
MASK_FOLLOW = 0x0080,
MASK_FLYOFF = 0x0100,
MASK_FREEFALL = 0x0200,
MASK_SIT = 0x0400,
MASK_PICKUP = 0x0800,
MASK_CONCENTRATE = 0x1000,
MASK_REVIVE = 0x2000,
MASK_FLASHMOVE = 0x4000,
MASK_BEBOUND = 0x8000,
MASK_CONGREGATE = 0x10000,
MASK_SKILLSTATEACT = 0x20000,
MASK_FORCENAVIGATE = 0x40000;
public const uint MASK_ALLWORK = 0xffffffff;
}
protected CECHPWorkMan m_pWorkMan; // Work manager
protected CECHostPlayer m_pHost; // Host player object
public CECHPWork(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID)
{
m_pWorkMan = pWorkMan;
m_pHost = pWorkMan.GetHostPlayer();
}
// Operations
// Override from CECObjectWork
public virtual void Cancel()
{
}
// This work is do player moving ?
public virtual bool IsMoving()
{
return false;
}
// Copy work data
public virtual bool CopyData(CECHPWork pWork)
{
m_bFinished = pWork.m_bFinished;
m_bFirstTick = pWork.m_bFirstTick;
return true;
}
public string GetWorkName()
{
return GetWorkName(GetWorkID());
}
public static uint GetWorkMask(int iWorkID)
{
if (!Validate(iWorkID))
{
return 0;
}
uint[] l_workMask = new uint[]{
Work_mask.MASK_STAND,
Work_mask.MASK_MOVETOPOS,
Work_mask.MASK_TRACEOBJECT,
Work_mask.MASK_HACKOBJECT,
Work_mask.MASK_SPELLOBJECT,
Work_mask.MASK_USEITEM,
Work_mask.MASK_DEAD,
Work_mask.MASK_FOLLOW,
Work_mask.MASK_FLYOFF,
Work_mask.MASK_FREEFALL,
Work_mask.MASK_SIT,
Work_mask.MASK_PICKUP,
Work_mask.MASK_CONCENTRATE,
Work_mask.MASK_REVIVE,
Work_mask.MASK_FLASHMOVE,
Work_mask.MASK_BEBOUND,
Work_mask.MASK_CONGREGATE,
Work_mask.MASK_SKILLSTATEACT,
Work_mask.MASK_FORCENAVIGATE,
};
return l_workMask[iWorkID];
}
public static bool Validate(int iWorkID)
{
return iWorkID >= 0 && iWorkID < Host_work_ID.NUM_WORK;
}
public static string GetWorkName(int iWorkID)
{
string[] l_WorkName = new string[Host_work_ID.NUM_WORK]
{
"WORK_STAND",
"WORK_MOVETOPOS",
"WORK_TRACEOBJECT",
"WORK_HACKOBJECT",
"WORK_SPELLOBJECT",
"WORK_USEITEM",
"WORK_DEAD",
"WORK_FOLLOW",
"WORK_FLYOFF",
"WORK_FREEFALL",
"WORK_SIT",
"WORK_PICKUP",
"WORK_CONCENTRATE",
"WORK_REVIVE",
"WORK_FLASHMOVE",
"WORK_BEBOUND",
"WORK_PASSIVEMOVE",
"WORK_CONGREGATE",
"WORK_SKILLSTATEACT",
"WORK_FORCENAVIGATEMOVE"
};
if (Validate(iWorkID))
{
return l_WorkName[iWorkID];
}
else if (iWorkID == Host_work_ID.WORK_INVALID)
{
return "WORK_INVALID";
}
else
{
return "Unknown";
}
}
}
///////////////////////////////////////////////////////////////////////////
//
// Class CECHPWorkMan
//
///////////////////////////////////////////////////////////////////////////
public class CECHPWorkMan
{
// Work priority
public static class Work_priority
{
public const int PRIORITY_0 = 0,
PRIORITY_1 = 1,
PRIORITY_2 = 2,
NUM_PRIORITY = 3;
};
// Delayed work info.
public struct DELAYWORK
{
public int iPriority;
public CECHPWork pWork;
}
private CECHostPlayer m_pHost;
private WorkList[] m_WorkStack = new WorkList[Work_priority.NUM_PRIORITY];
private int m_iCurPriority;
private DELAYWORK m_Delayed;
private CECHPWorkPostTickCommand m_pPostTickCommand;
public CECHPWorkMan(CECHostPlayer pHost)
{
m_pHost = pHost;
m_iCurPriority = -1;
m_Delayed = new DELAYWORK
{
iPriority = 0,
pWork = null
};
m_pPostTickCommand = null;
}
bool InternallyStartWork(int iPriority, CECHPWork pWork)
{
bool bStarted = false;
if (CanRunSimultaneouslyWithCurrentWork(iPriority, pWork))
{
WorkList workList = m_WorkStack[iPriority];
workList.Add(pWork);
bStarted = true;
//LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started simultaneously, priority=%d", pWork->GetWorkName(), iPriority));
}
else
{
if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_DEAD)
{
for (int i = iPriority; i < Work_priority.NUM_PRIORITY; i++)
{
FinishWorkAtPriority(i);
}
ClearDelayedWork();
WorkList workList = m_WorkStack[iPriority];
workList.Add(pWork);
m_iCurPriority = iPriority;
bStarted = true;
}
else
{
bool shouldStart = (iPriority >= m_iCurPriority);
FinishWorkAtPriority(iPriority);
WorkList workList = m_WorkStack[iPriority];
workList.Add(pWork);
if (shouldStart)
{
if (iPriority > m_iCurPriority)
{
CancelWorkAtPriority(m_iCurPriority);
}
m_iCurPriority = iPriority;
bStarted = true;
}
}
//if (bStarted)
//{
// LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started, priority=%d", pWork->GetWorkName(), iPriority));
//}
//else
//{
// LOG_DEBUG_INFO(AString().Format("CECHPWork::%s add to priority queue %d", pWork->GetWorkName(), iPriority));
//}
}
return bStarted;
}
bool CanRunSimultaneouslyWithCurrentWork(int iPriority, CECHPWork pWork)
{
if (!ValidatePriority(iPriority) || iPriority != m_iCurPriority)
{
return false;
}
WorkList workList = m_WorkStack[iPriority];
if (workList == null || workList.Count == 0)
{
return false;
}
foreach (var work in workList)
{
if (!CanRunSimultaneously(work, pWork))
{
return false;
}
}
return true;
}
bool CanRunSimultaneously(CECHPWork pWork1, CECHPWork pWork2)
{
if (pWork1.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS &&
pWork2.GetWorkID() == CECHPWork.Host_work_ID.WORK_SPELLOBJECT)
{
return CanSpellWhileMoving(pWork2 as CECHPWorkSpell);
}
if (pWork2.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS &&
pWork1.GetWorkID() == CECHPWork.Host_work_ID.WORK_SPELLOBJECT)
{
return CanSpellWhileMoving(pWork1 as CECHPWorkSpell);
}
return false;
}
bool CanSpellWhileMoving(CECHPWorkSpell pWorkSpell)
{
//return pWorkSpell.GetSkill()
// && CECCastSkillWhenMove::Instance().IsSkillSupported(pWorkSpell->GetSkill()->GetSkillID(), m_pHost);
return false;
}
void StartAwaitingWorks()
{
if (ValidatePriority(m_iCurPriority))
{
for (--m_iCurPriority; m_iCurPriority >= 0; --m_iCurPriority)
{
WorkList workList = m_WorkStack[m_iCurPriority];
if (workList == null || workList.Count == 0)
{
continue;
}
foreach (var work in workList)
{
work.OnWorkShift();
//LOG_DEBUG_INFO(AString().Format("CECHPWork::%s started by decrease priority, priority=%d", workList[j]->GetWorkName(), m_iCurPriority));
}
break;
}
}
StartDelayedWork();
}
void FinishWorkAtPriority(int iPriority)
{
if (!ValidatePriority(iPriority))
{
return;
}
WorkList workList = m_WorkStack[iPriority];
while ((workList != null && workList.Count > 0))
{
KillWork(iPriority, 0);
}
if (m_iCurPriority == iPriority)
{
m_iCurPriority = -1;
}
}
void KillWork(int iPriority, int index)
{
if (!ValidatePriority(iPriority))
{
return;
}
WorkList workList = m_WorkStack[iPriority];
if (index < 0 || index >= workList.Count)
{
return;
}
CECHPWork pWork = workList[index];
KillWork(pWork);
//LOG_DEBUG_INFO(AString().Format("CECHPWork::%s priority=%d killed", pWork->GetWorkName(), iPriority));
//delete pWork;
workList.RemoveAt(index);
}
void KillWork(CECHPWork pWork)
{
if (pWork == null)
{
return;
}
if (pWork.GetWorkID() == CECHPWork.Host_work_ID.WORK_MOVETOPOS)
{
CECHPWorkMove pWorkMove = pWork as CECHPWorkMove;
if (pWorkMove)
{
if (pWorkMove.GetAutoMove())
{
pWorkMove.Finish();
}
else
{
pWorkMove.Cancel();
}
}
}
else
{
pWork.Cancel();
}
}
void CancelWork(CECHPWork pWork)
{
}
void CancelWorkAtPriority(int iPriority)
{
}
bool DelayWork(int iPriority, CECHPWork pWork)
{
}
void StartDelayedWork()
{
}
void ClearDelayedWork()
{
}
CECHPWork GetDelayedWork()
{
return m_Delayed.pWork;
}
bool ValidatePriority(int iPriority)
{
return iPriority >= 0 && iPriority < Work_priority.NUM_PRIORITY;
}
}
public abstract class CECHPWorkPostTickCommand
{
public abstract bool Run(CECHPWorkMan pWorkMan);
};
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: de7b8e482be7d8347b45ab9751adae44
@@ -0,0 +1,159 @@
using CSNetwork.GPDataType;
using UnityEngine;
public class CECHPWorkMove : CECHPWork
{
public static class Types
{
public const int DEST_2D = 0,
DEST_3D = 1,
DEST_DIR = 2,
DEST_PUSH = 3,
DEST_STANDJUMP = 4,
DEST_AUTOPF = 5; // Movement type
}
protected A3DVECTOR3 m_vMoveDest; // Move destination position or direction
protected int m_iDestType; // Destination type
protected bool m_bHaveDest; // true, have destination
protected bool m_bMeetSlide; // true, meet slide
protected A3DVECTOR3 m_vCurDir; // Current move direction
protected bool m_bReadyCancel; // true, ready to cancel
protected bool m_bGliding; // glide
protected float m_fGlideTime;
protected float m_fGlideSpan;
protected float m_fGlideAng;
protected float m_fGlideVel; // glide angular vel
protected float m_fGlidePitch; // glide pitch angle
protected float m_fCurPitch;
protected float m_fPushPitch;
protected float m_fPushLean;
protected bool m_bUseAutoMoveDialog; // Auto move
protected float m_fAutoHeight; // Height of auto moving destination
protected bool m_bAutoLand; // Auto land when arrive at destination
protected bool m_bAutoFly; // Auto fly
protected bool m_bReachedHeight;// Player reached specified height
protected bool m_bAutoFlyPending; // Mark whether a fly command had been executed
protected int m_iNPCTempleId;
protected int m_iTaskId;
protected bool m_bSwitchTo2D;
protected bool m_bResetAutoPF;
public CECHPWorkMove(CECHPWorkMan pWorkMan) : base (Host_work_ID.WORK_MOVETOPOS, pWorkMan)
{
m_dwMask = Work_mask.MASK_MOVETOPOS;
m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_TRACEOBJECT | Work_mask.MASK_FOLLOW;
Reset();
}
public CECHPWorkMove(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID, pWorkMan)
{
}
// Set destination position or direction
public void SetDestination(int iDestType, A3DVECTOR3 vMoveDest)
{
m_iDestType = iDestType;
m_vMoveDest = vMoveDest;
m_bHaveDest = true;
m_bGliding = false;
//m_pHost->SetAdjustOrient(false); // 2014-9-10 徐文彬:在 CECHPWorkMove 创建的时候都会调用此函数,会导致其它时机通过 SetDestDirAndUp 调用对人物的朝向调整失效。
// 重现方法为:月仙“望月咏”技能释放后、马上按住'A'或'D'等移动键并摁住不放,将导致人物施法方向偏离目标而朝向移动方向(需多次尝试)
//清空任务信息
m_iTaskId = 0;
m_iNPCTempleId = 0;
ResetUseAutoPF();
if (iDestType == Types.DEST_DIR)
{
m_vCurDir = vMoveDest;
if (m_bUseAutoMoveDialog)
{
m_bUseAutoMoveDialog = false;
m_bAutoLand = false;
m_fAutoHeight = -1.0f;
m_bAutoFly = false;
m_bReachedHeight = true;
m_bAutoFlyPending = false;
}
}
else if (iDestType == Types.DEST_2D || iDestType == Types.DEST_3D)
{
m_vCurDir = vMoveDest - new A3DVECTOR3(m_pHost.transform.position.x, m_pHost.transform.position.y, m_pHost.transform.position.z);
m_vCurDir.y = 0.0f;
m_vCurDir.Normalize();
}
else if (IsAutoPF())
{
m_vCurDir = CECIntelligentRoute::Instance().GetCurDest() - m_pHost->GetPos();
m_vCurDir.y = 0.0f;
m_vCurDir.Normalize();
if (m_bUseAutoMoveDialog)
{
// 此处禁用 m_bUseAutoMoveDialog,见 SetUseAutoMoveDialog 中说明
m_bUseAutoMoveDialog = false;
m_bAutoLand = false;
m_fAutoHeight = -1.0f;
m_bAutoFly = false;
m_bReachedHeight = true;
m_bAutoFlyPending = false;
}
}
if (m_pHost.m_pMoveTargetGFX)
{
if (iDestType != DEST_PUSH)
m_pHost.m_pMoveTargetGFX.Stop();
}
}
void ResetUseAutoPF()
{
m_bResetAutoPF = true;
}
// Tick routine
virtual bool Tick(uint dwDeltaTime)
{
}
// Reset work
virtual void Reset();
// Work is cancel
virtual void Cancel();
// This work is do player moving ?
virtual bool IsMoving() { return true; }
// Copy work data
virtual bool CopyData(CECHPWork* pWork);
// Play move target effect
void PlayMoveTargetGFX(const A3DVECTOR3& vPos, const A3DVECTOR3& vNormal);
// User press cancel button
void PressCancel() { m_bReadyCancel = true; }
void SetUseAutoMoveDialog(bool bUseAutoMoveDialog);
bool GetUseAutoMoveDialog() { return m_bUseAutoMoveDialog; }
bool GetAutoMove();
void SetAutoLand(bool bAutoLand) { m_bAutoLand = bAutoLand; }
bool GetAutoLand() { return m_bAutoLand; }
void SetAutoHeight(float fHeight) { m_fAutoHeight = fHeight; m_bAutoFly = true; m_bReachedHeight = false; }
float GetAutoHeight() { return m_fAutoHeight; }
bool IsAutoFly() const { return m_bAutoFly;}
bool IsAutoPF()const{ return m_iDestType == DEST_AUTOPF; }
// Finish work
void Finish();
void SetTaskNPCInfo(int tid, int taskid);
void SwitchToDest2D();
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d03d31e6920c13745a437cff8cfe4572
@@ -0,0 +1,75 @@
using UnityEngine;
///////////////////////////////////////////////////////////////////////////
//
// Class CECHPWorkSpell
//
///////////////////////////////////////////////////////////////////////////
public class CECHPWorkSpell : CECHPWork
{
public static class Spell_magic_state
{
public const int ST_INCANT = 0,
ST_SPELL = 1;
}
public CECHPWorkSpell(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_SPELLOBJECT, pWorkMan)
{
m_dwMask = Work_mask.MASK_SPELLOBJECT;
m_dwTransMask = Work_mask.MASK_STAND | Work_mask.MASK_MOVETOPOS | Work_mask.MASK_TRACEOBJECT;
Reset();
}
public CECHPWorkSpell(int iWorkID, CECHPWorkMan pWorkMan) : base(iWorkID, pWorkMan)
{
}
protected CECSkill m_pSkill; // Skill object
protected CECCounter m_OverTimeCnt; // Over time counter
protected int m_iState;
protected int m_idTarget; // Target id
// On first tick
protected virtual void OnFirstTick()
{
//m_pHost.m_iMoveMode = CECHostPlayer::MOVE_STAND;
}
// Prepare cast
public void PrepareCast(int idTarget, CECSkill pSkill, int iIncantTime)
{
}
// Change state
public void ChangeState(int iState)
{
}
// Get state
public int GetState()
{
return m_iState;
}
public CECSkill GetSkill()
{
return m_pSkill;
}
// Tick routine
public virtual bool Tick(uint dwDeltaTime)
{
return false;
}
// Reset work
public virtual void Reset()
{
}
// Copy work data
public virtual bool CopyData(CECHPWork pWork)
{
return false;
}
// Cancel work
public virtual void Cancel()
{
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c82fffc45c6f0534e9a668a8ce937e1a
@@ -0,0 +1,64 @@
using UnityEngine;
public class CECObjectWork
{
// Attributes
protected int m_iWorkID; // Work ID
protected bool m_bFinished; // true, Work is finished
protected uint m_dwMask; // Mask of this work
protected uint m_dwTransMask; // Work transfer masks
protected bool m_bFirstTick;
// Constructor
public CECObjectWork(int iWorkID)
{
m_iWorkID = iWorkID;
m_bFinished = false;
m_dwMask = 0;
m_dwTransMask = 0;
m_bFinished = true;
}
public virtual bool Tick(uint dwDeltaTime)
{
if (m_bFirstTick)
{
m_bFirstTick = false;
OnFirstTick();
}
return true;
}
// Reset work
public virtual void Reset()
{
m_bFinished = false;
m_bFirstTick = true;
}
// Work is cancel
public virtual void Cancel() { }
// Can work transfer to another work with specified mask
public virtual bool CanTransferTo(uint dwMask)
{
return (m_dwTransMask & dwMask) != 0;
}
// On work shift to
public virtual void OnWorkShift() { }
// Get work ID
public int GetWorkID() => m_iWorkID;
// Is work finished?
public bool IsFinished() => m_bFinished;
// Get work mask
public uint GetWorkMask() => m_dwMask;
// Get work transfer works
public uint GetTransferMask() => m_dwTransMask;
// On first tick
protected virtual void OnFirstTick() { }
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8d658d501be8b9f45be5ed066a6efc23
@@ -0,0 +1,6 @@
using UnityEngine;
public class CECSkill
{
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a33568a349c4ee9488a562e2c67002e7
+3
View File
@@ -476,6 +476,9 @@ public class CECHostPlayer : EC_Player
bool bStartNewWork = false;
bool bUseAutoPF = false;
//CECPlayerWrapper* pWrapper = CECAutoPolicy::GetInstance().GetPlayerWrapper();
//if (CECAutoPolicy::GetInstance().IsAutoPolicyEnabled() && pWrapper->GetAttackError() >= 2)
bUseAutoPF = true;
return false;
}
}
+1
View File
@@ -12,6 +12,7 @@ public abstract class EC_Player : MonoBehaviour
[SerializeField] protected INFO m_PlayerInfo;
protected GameObject m_pPlayerModel;
protected float rotationSpeed = 5;
protected int m_iMoveMode; // Player's move mode
protected void Awake()
{