using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; using static Unity.Cinemachine.CinemachineFreeLookModifier; namespace BrewMonster { public enum GfxHitPos { enumHitCenter, enumHitBottom } public enum GfxSkillEventState { enumWait, enumFlying, enumHit, enumFinished } // TODO: remove singleton later public class A3DSkillGfxMan { public static A3DSkillGfxMan _instance; public static A3DSkillGfxMan Instance { get { if (_instance == null) { _instance = new A3DSkillGfxMan(); } return _instance; } set { _instance = value; } } public bool AddSkillGfxEvent( A3DSkillGfxComposer pComposer, long nHostID, long nTargetID, string szFlyGfx, string szHitGfx, uint dwFlyTimeSpan, bool bTraceTarget, GfxMoveMode FlyMode, int nFlyGfxCount, uint dwInterval, GFX_SKILL_PARAM param, float fFlyGfxScale, float fHitGfxScale, uint dwModifier, bool bOnlyOneHit, bool bFadeOut, bool bIsGoblinSkill, bool bReverse ) { bool bRet = true, bCluster; uint dwDelayTime; if (nFlyGfxCount == 1) { dwDelayTime = dwInterval; bCluster = false; } else { dwDelayTime = 0; bCluster = true; } for (int i = 0; i < nFlyGfxCount; i++) { string value = bOnlyOneHit && i != nFlyGfxCount - 1 ? "" : szHitGfx; if (!AddOneSkillGfxEvent( pComposer, nHostID, nTargetID, szFlyGfx, FlyMode, dwDelayTime, dwFlyTimeSpan, value, param, bTraceTarget, fFlyGfxScale, fHitGfxScale, dwModifier, bCluster, bFadeOut, bIsGoblinSkill, bReverse )) bRet = false; dwDelayTime += dwInterval; } return bRet; } public bool AddOneSkillGfxEvent( A3DSkillGfxComposer pComposer, long nHostID, long nTargetID, string szFlyGfx, GfxMoveMode mode, uint dwDelayTime, uint dwFlyTimeSpan, string szHitGfx, GFX_SKILL_PARAM param, bool bTraceTarget, float fFlyGfxScale, float fHitGfxScale, uint dwModifier, bool bCluster, bool bFadeOut, bool bIsGoblinSkill, bool bReverse) { A3DSkillGfxEvent pEvent = SkillGfxMan.InstanceSub.GetEmptyEvent(mode); pEvent.SetComposer(pComposer); pEvent.SetHostID(nHostID); pEvent.SetTargetID(nTargetID); pEvent.SetFlyTimeSpan(dwFlyTimeSpan); pEvent.SetDelay(dwDelayTime); //pEvent.SetReverse(bReverse); //if (param.value.fVal != float.MinValue) pEvent.SetParam(param); pEvent.SetTraceTarget(bTraceTarget); pEvent.SetModifier(dwModifier); //pEvent.SetIsCluster(bCluster); pEvent.SetFadeOut(bFadeOut); pEvent.SetGoblinSkill(bIsGoblinSkill); ECMODEL_GFX_PROPERTY Prop = new ECMODEL_GFX_PROPERTY(); if (GetPropertyById(nHostID, ref Prop)) { pEvent.SetGfxUseLod(Prop.bGfxUseLod); pEvent.SetDisableCamShake(Prop.bGfxDisableCamShake); pEvent.SetHostModelCreatedByGfx(Prop.bHostECMCreatedByGfx); } /* if (szFlyGfx != 0) { A3DGFXEx pGfx = pEvent.LoadFlyGfx(m_pDevice, szFlyGfx.ToString()); if (pGfx != null) { pGfx.SetScale(fFlyGfxScale); pGfx.SetDisableCamShake(pEvent.GetDisableCamShake()); pGfx.SetCreatedByGFXECM(pEvent.GetHostModelCreatedByGfx()); pGfx.SetUseLOD(pEvent.GetGfxUseLod()); pGfx.SetId(pEvent.GetHostID()); pEvent.SetFlyGfx(pGfx); } }*/ if (string.IsNullOrEmpty(szHitGfx)) { /*game pGfx = pEvent.LoadHitGfx(m_pDevice, szHitGfx.ToString()); if (pGfx != null) { pGfx.SetScale(fHitGfxScale); pEvent.SetHitGfx(pGfx); }*/ } #if !_SKILLGFXCOMPOSER pEvent.Tick(0); #endif pComposer.SpawnGFX(nTargetID); PushEvent(pEvent); return true; } public virtual bool GetPropertyById(long nId, ref ECMODEL_GFX_PROPERTY pProperty) => false; void PushEvent(A3DSkillGfxEvent pEvent) { SkillGfxMan.InstanceSub.m_EventLst.AddLast((CECSkillGfxEvent)pEvent); } } public class A3DSkillGfxEvent { protected A3DSkillGfxComposer m_pComposer; //protected CGfxMoveBase m_pMoveMethod; //protected A3DGFXEx m_pFlyGfx; // 飞行特效 / Fly effect //protected A3DGFXEx m_pHitGfx; // 命中特效 / Hit effect protected uint m_dwFlyTimeSpan; // 飞行时间 / Flight time protected uint m_dwCurSpan; protected uint m_dwDelayTime; protected bool m_bTraceTarget; protected bool m_bFadeOut; protected long m_nHostID; // 施法者ID / Caster ID protected long m_nTargetID; // 目标ID / Target ID protected uint m_dwModifier; // 技能附加效果 / Skill additional effect protected bool m_bIsGoblinSkill; // 是否为小精灵技能 / Whether it's a goblin skill protected Vector3 m_vHostPos; protected Vector3 m_vTargetPos; protected Vector3 m_vTargetDir; protected Vector3 m_vTargetUp; protected bool m_bHostExist; protected bool m_bTargetExist; protected bool m_bHitGfxInfinite; protected bool m_bTargetDirAndUpExist; protected bool m_bGfxUseLod; protected bool m_bGfxDisableCamShake; protected bool m_bHostECMCreatedByGfx; protected GfxSkillEventState m_enumState; public A3DSkillGfxEvent(GfxMoveMode mode) { m_pComposer = null; /* m_pFlyGfx = null; m_pHitGfx = null;*/ m_nHostID = 0; m_nTargetID = 0; m_dwModifier = 0; m_dwFlyTimeSpan = 0; m_dwCurSpan = 0; m_enumState = GfxSkillEventState.enumWait; m_bHitGfxInfinite = false; m_bIsGoblinSkill = false; m_bTargetDirAndUpExist = false; m_bGfxUseLod = true; m_bGfxDisableCamShake = false; m_bHostECMCreatedByGfx = false; //m_pMoveMethod = CGfxMoveBase.CreateMoveMethod(mode); } ~A3DSkillGfxEvent() { //ReleaseGfx(); // Note: m_pMoveMethod will be garbage collected } // Inline functions /* protected void ReleaseFlyGfx() { if (m_pFlyGfx != null) { if (m_bFadeOut) AfxGetGFXExMan().QueueFadeOutGfx(m_pFlyGfx, 1000); else { m_pFlyGfx.Release(); // In C#, we don't need to manually delete } m_pFlyGfx = null; } }*/ /* protected void ReleaseHitGfx() { if (m_pHitGfx != null) { AfxGetGFXExMan().CacheReleasedGfx(m_pHitGfx); m_pHitGfx = null; } }*/ /* protected void ReleaseGfx() { ReleaseFlyGfx(); ReleaseHitGfx(); }*/ // Virtual functions protected virtual void HitTarget(Vector3 vTarget) { m_enumState = GfxSkillEventState.enumHit; //ReleaseFlyGfx(); if (false /*m_pHitGfx != null*/) { //m_bHitGfxInfinite = m_pHitGfx.IsInfinite(); Matrix4x4 matTran; // now try to make the hit gfx face to the attacker if (m_bHostExist) { Vector3 vDir = vTarget - m_vHostPos; vDir.y = 0; if (vDir.magnitude < 1e-3f) vDir = new Vector3(0, 0, 1.0f); else vDir.Normalize(); matTran = _build_matrix(vDir, vTarget); } else { matTran = Matrix4x4.identity; matTran.SetColumn(3, new Vector4(vTarget.x, vTarget.y, vTarget.z, 1)); } /* m_pHitGfx.SetParentTM(matTran); m_pHitGfx.Start(true); m_pHitGfx.TickAnimation(0);*/ } } // Public inline functions public void SetGfxUseLod(bool b) { m_bGfxUseLod = b; } public bool GetGfxUseLod() { return m_bGfxUseLod; } public void SetDisableCamShake(bool b) { m_bGfxDisableCamShake = b; } public bool GetDisableCamShake() { return m_bGfxDisableCamShake; } public void SetHostModelCreatedByGfx(bool b) { m_bHostECMCreatedByGfx = b; } public bool GetHostModelCreatedByGfx() { return m_bHostECMCreatedByGfx; } public void SetComposer(A3DSkillGfxComposer pComposer) { m_pComposer = pComposer; } //public CGfxMoveBase GetMoveMethod() { return m_pMoveMethod; } //public GfxMoveMode GetMode() { return m_pMoveMethod.GetMode(); } //public GfxHitPos GetHitPos() { return m_pMoveMethod.GetHitPos(); } /* public A3DGFXEx GetFlyGfx() { return m_pFlyGfx; } public A3DGFXEx GetHitGfx() { return m_pHitGfx; }*/ public void SetFlyTimeSpan(uint dwSpan) { m_dwFlyTimeSpan = dwSpan; } public void SetDelay(uint dwDelay) { m_dwDelayTime = dwDelay; } //public void SetReverse(bool bReverse) { m_pMoveMethod.SetReverse(bReverse); } //public void SetParam(GFX_SKILL_PARAM param) { m_pMoveMethod.SetParam(param); } //public void SetIsCluster(bool bCluster) { m_pMoveMethod.SetIsCluster(bCluster); } public void SetTraceTarget(bool bTrace) { m_bTraceTarget = bTrace; } public void SetFadeOut(bool bFadeOut) { m_bFadeOut = bFadeOut; } public bool IsFinished() { return m_enumState == GfxSkillEventState.enumFinished; } public long GetHostID() { return m_nHostID; } public void SetHostID(long nID) { m_nHostID = nID; } public long GetTargetID() { return m_nTargetID; } public void SetTargetID(long nID) { m_nTargetID = nID; } public void SetHostPos(Vector3 vPos) { m_vHostPos = vPos; } public void SetTargetPos(Vector3 vPos) { m_vTargetPos = vPos; } public void SetHostExist(bool bExist) { m_bHostExist = bExist; } public void SetTargetExist(bool bExist) { m_bTargetExist = bExist; } public void SetModifier(uint dwModifier) { m_dwModifier = dwModifier; } public void SetGoblinSkill(bool bGoblinSkill) { m_bIsGoblinSkill = bGoblinSkill; } public bool GetGoblinSkill() { return m_bIsGoblinSkill; } public void Resume() { //ReleaseGfx(); m_enumState = GfxSkillEventState.enumWait; m_dwCurSpan = 0; } // Virtual functions /* public virtual A3DGFXEx LoadFlyGfx(A3DDevice pDev, string szPath) { return AfxGetGFXExMan().LoadGfx(pDev, szPath); } public virtual A3DGFXEx LoadHitGfx(A3DDevice pDev, string szPath) { return AfxGetGFXExMan().LoadGfx(pDev, szPath); } public virtual void SetFlyGfx(A3DGFXEx pFlyGfx) { m_pFlyGfx = pFlyGfx; } public virtual void SetHitGfx(A3DGFXEx pHitGfx) { m_pHitGfx = pHitGfx; }*/ public virtual void Tick(uint dwDeltaTime) { m_dwCurSpan += dwDeltaTime; if (m_enumState == GfxSkillEventState.enumFinished) return; // 结束 / Finished else if (m_enumState == GfxSkillEventState.enumHit) // 命中 / Hit { /* if (m_pHitGfx == null || m_pHitGfx.GetState() == ST_STOP) m_enumState = GfxSkillEventState.enumFinished; else { if (!m_bTargetExist || (m_bHitGfxInfinite && m_pHitGfx.GetTimeElapse() > 5000)) // HIT_GFX_MAX_TIMESPAN = 5000 m_enumState = GfxSkillEventState.enumFinished; else { if (m_bTraceTarget) { Matrix4x4 matTran = Matrix4x4.identity; Vector3 targetCenter = GetTargetCenter(); matTran.SetColumn(3, new Vector4(targetCenter.x, targetCenter.y, targetCenter.z, 1)); //m_pHitGfx.SetParentTM(matTran); } //m_pHitGfx.TickAnimation(dwDeltaTime); } }*/ } else if (m_dwCurSpan > m_dwFlyTimeSpan) // 飞行超时 / Flight timeout { if (!m_bTargetExist) m_enumState = GfxSkillEventState.enumFinished; /* else HitTarget(GetTargetCenter());*/ } else if (!m_bTargetExist) m_enumState = GfxSkillEventState.enumFinished; else if (m_enumState == GfxSkillEventState.enumWait) { if (m_dwCurSpan < m_dwDelayTime) return; if (!m_bHostExist) m_enumState = GfxSkillEventState.enumFinished; else { m_enumState = GfxSkillEventState.enumFlying; /* m_pMoveMethod.SetMaxFlyTime(m_dwFlyTimeSpan); m_pMoveMethod.StartMove(m_vHostPos, m_vTargetPos);*/ /* if (m_pFlyGfx != null) { Vector3 vDir, vUp; if (m_pMoveMethod.GetMode() == GfxMoveMode.enumOnTarget && m_pMoveMethod.IsReverse() && GetTargetDirAndUp(out vDir, out vUp)) m_pFlyGfx.SetParentTM(a3d_TransformMatrix(vDir, vUp, m_pMoveMethod.GetPos())); else m_pFlyGfx.SetParentTM(_build_matrix(m_pMoveMethod.GetMoveDir(), m_pMoveMethod.GetPos())); m_pFlyGfx.Start(true); m_pMoveMethod.UpdateGfxParam(m_pFlyGfx, m_vHostPos, m_vTargetPos); m_pFlyGfx.TickAnimation(0); }*/ } } else { /* if (m_pMoveMethod.TickMove(dwDeltaTime, m_vHostPos, m_vTargetPos)) // 目标被命中 / Target hit HitTarget(GetTargetCenter());*/ /*else if (m_pFlyGfx != null) { Vector3 vDir, vUp; if (m_pMoveMethod.GetMode() == GfxMoveMode.enumOnTarget && m_pMoveMethod.IsReverse() && GetTargetDirAndUp(out vDir, out vUp)) m_pFlyGfx.SetParentTM(a3d_TransformMatrix(vDir, vUp, m_pMoveMethod.GetPos())); else m_pFlyGfx.SetParentTM(_build_matrix(m_pMoveMethod.GetMoveDir(), m_pMoveMethod.GetPos())); m_pMoveMethod.UpdateGfxParam(m_pFlyGfx, m_vHostPos, m_vTargetPos); m_pFlyGfx.TickAnimation(dwDeltaTime); }*/ } } /* public virtual void Render() { if (m_pFlyGfx != null) AfxGetGFXExMan().RegisterGfx(m_pFlyGfx); if (m_pHitGfx != null) AfxGetGFXExMan().RegisterGfx(m_pHitGfx); } */ public virtual Vector3 GetTargetCenter() { // Abstract method - must be implemented by derived class throw new NotImplementedException("GetTargetCenter must be implemented by derived class"); } public virtual bool GetTargetDirAndUp(out Vector3 vDir, out Vector3 vUp) { vDir = Vector3.zero; vUp = Vector3.zero; return false; } // Helper methods that need to be implemented elsewhere or provided by utility class /* protected A3DGFXExMan AfxGetGFXExMan() { // This should return the GFX manager instance throw new NotImplementedException("AfxGetGFXExMan needs to be implemented"); } */ protected Matrix4x4 _build_matrix(Vector3 dir, Vector3 pos) { // This should build a transformation matrix from direction and position throw new NotImplementedException("_build_matrix needs to be implemented"); } protected Matrix4x4 a3d_TransformMatrix(Vector3 dir, Vector3 up, Vector3 pos) { // This should build a transformation matrix from direction, up vector and position throw new NotImplementedException("a3d_TransformMatrix needs to be implemented"); } } public struct ECMODEL_GFX_PROPERTY { public bool bGfxUseLod; public bool bGfxDisableCamShake; public bool bHostECMCreatedByGfx; }; }