/* * now, it's shit from wow. */ #pragma once #include "Target.h" #include "Utils/SpellDB.h" #include "AudioInterface.h" class CCharacter; class UpdateObj; class CEffectBase; ////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////// typedef int SpellID; #define INVALID_SPELL_ID SpellID(-1) #define INVALID_SPELL_VISUAL_ID 0L #define NORMAL_ATTACK_SPELL_ID 1 enum ESpellClass { SPELL_CLS_BASE = 0, SPELL_CLS_RUSH = 1, }; enum ESpellStep { LPAS_NONE = 0, LPAS_CAST, LPAS_ATTACK, LPAS_TUNNEL, LPAS_ENDTUNNEL, LPAS_END, }; enum SpellTargetRelative { STR_UNKNOWN =0, STR_SELF, // 自身 STR_FRIENDLY, // 友好 STR_hostile, // 敌对 STR_neutrally, // 中立 }; #define STC_MAPPOSITION (TYPE_AREATRIGGER << 1) #define INVALID_SPELL_TRIGGERID -1L enum SpellEffectSlot { SES_NONE = -1, SES_HEAD01 = 0, SES_HEAD02, SES_CHEST, SES_BELT, SES_RIGHTHAND, SES_LEFTHAND, SES_RIGHTFEET, SES_LEFTFEET, SES_FOOT01, SES_FOOT02, SES_BACKSIDE, SES_ORIGINAL, SES_SCENE, }; enum TriggerAction { TA_Active = 0, //"activate" TA_Deactive, //"deactivate" }; enum TriggerTimeStartPosType { TT_Cast = 0, TT_Attack, TT_Spell, }; enum TriggerEvtType { TE_CastStart = 0, // "caststart" TE_CastEnd, // "castend" TE_AttackStart, // "attackstart" TE_NormAttackUpdate, // "normattackstart" TE_AttackEnd, // "attackend" TE_AnimKey, // "animkey" TE_Damage, // "damage" TE_PeriodicDamage, // "periodicdamage" TE_EnvironmentalDamage, // "environmentaldamage" TE_AuraStart, // "aurastart" TE_AuraOver, // "auraover" TE_HealHP, // "healhp" TE_HealMP, // "healmp" TE_PostEvt, // "postevent" TE_TunnelStart, // "tunnelstart" TE_TunnelEnd, // "tunnelend" TE_Unkown, }; enum EffectType { ET_MODEL = 0, ET_DECAL, ET_TRAIL, ET_PROJECTILE, ET_POSCONSTRAINT, ET_CHAIN, // ET_SOUND, }; enum EffectOwnerType { EOT_Attacker = 0, EOT_Target, EOT_Both, }; struct SpellEffectNode : public NiMemObject { SpellEffectNode() { Slot = SES_NONE; MaxLife = FLT_MAX; bFailureBreak = true; Media[0] = 0; bCanBreak = false; iOwner = EOT_Attacker; bWorld = false; iPostTrig = -1; bTargetProjetile = false; bNoScale = false; } virtual ~SpellEffectNode() { } SpellEffectSlot Slot; float MaxLife; // 生命期 MaxLife = max(animtime) bool bWorld; bool bCanBreak; bool bSelfProjetile; bool bTargetProjetile; bool bFailureBreak; int iOwner; int iPostTrig; float scale; bool bNoScale; std::vector vRefTriggers; // trigger id map std::vector vSounds; // sound list char Media[MAX_PATH]; virtual int GetType() const { return -1; } }; struct SpellTriggerBase : public NiMemObject { enum TriggerEvtType { Unkown = -1, Event, Timer, }; SpellTriggerBase() { iType = Unkown; iAction = TA_Active; // default } virtual ~SpellTriggerBase() {} virtual int GetType() { return Unkown; } int iType; // evt, timer int iAction; // active, deactive int iTrigID; }; struct SpellEventTrigger : public SpellTriggerBase { SpellEventTrigger() { iEvent = -1; iAnimKey = 0; } virtual int GetType() { return Event; } int iEvent; // anim, state int iAnimKey; }; struct SpellTimeTrigger : public SpellTriggerBase { SpellTimeTrigger() { iBegin = 0; // 默认为技能开始 fOffsetTime = -FLT_MAX; } virtual int GetType() { return Timer; } int iBegin; // 开始点 float fOffsetTime; // 偏移时间 }; struct SpellEffectNifNode : public SpellEffectNode { SpellEffectNifNode() { bLoop = false; bClamp = false; bInfinite = false; uiLoopLimit = 99999; } virtual int GetType() const { return ET_MODEL;} bool bLoop; bool bClamp; bool bInfinite; uint32 uiLoopLimit; }; struct SpellChainEffectNode : public SpellEffectNode { SpellChainEffectNode() { Count = 10; MediaType = "tga"; LifeTime = 0.f; UpdateRate = 1.f; scale = 1.f; chaintype = 0; dir = 0; } virtual int GetType() const { return ET_CHAIN;} std::string SrcNodeName; std::string DesNodeName; std::string MediaType; int Count; int chaintype; float LifeTime; float UpdateRate; float scale; int dir; }; struct SpellDecalEffectNode : public SpellEffectNode { SpellDecalEffectNode() { FollowOnwer = FALSE; Rotate = 0.0f; fRadius = 0.0f; effectType = 0; fFadein = 0.0f; fFadeout = 0.0f; } virtual int GetType() const { return ET_DECAL;} BOOL FollowOnwer; float Rotate; float fRadius; float fFadein; float fFadeout; int effectType; }; struct SpellPosConstraintEffectNode : public SpellEffectNode { SpellPosConstraintEffectNode() { szAnimName[0] = '\0'; type = 0; } virtual int GetType() const { return ET_POSCONSTRAINT; } int type; char szAnimName[128]; }; struct SpellRushEffectNode : public SpellPosConstraintEffectNode { SpellRushEffectNode(); }; struct SpellPhaseshiftEffectNode : public SpellPosConstraintEffectNode { }; struct SpellTrailEffectNode : public SpellEffectNode { SpellTrailEffectNode() { fLifeTime = 0.0f; szTexture[0] = '\0'; fTotalTime = 0.75f; fWidth = 0.7f; } virtual int GetType() const { return ET_TRAIL;} float fWidth; float fLifeTime; float fTotalTime; char szTexture[MAX_PATH]; }; struct SpellProjectileEffectNode : public SpellEffectNode { SpellProjectileEffectNode() { ExpMedia[0] = '\0'; bSelfMissile = false; bNeedTarget = true; bCenter = true; iProjectileType = 0; fSelfMissileTime = 0.75f; ExpScale = 1.0f; projectileNum = 1; } virtual int GetType() const { return ET_PROJECTILE;} char ExpMedia[MAX_PATH]; char ExpSound[MAX_PATH]; bool bSelfMissile; bool bCenter; bool bNeedTarget; int iProjectileType; int projectileNum; float fSelfMissileTime; float ExpScale; }; struct SpellSoundDesc : public NiMemObject { SpellSoundDesc() { id = 0; bLoop = false; uiLoopLimit = 99999; szSource[0] = '\0'; Gain = 1.f; MinDist = 5; MaxDist = 50.f; } int id; bool bLoop;// = 0; unsigned int uiLoopLimit;// = 99999; float Gain; float MinDist; float MaxDist; char szSource[MAX_PATH]; }; struct SpellTargetSelDesc { int SelMethod; // 0 : 不需要选择 1: 选择对象 2: 选择区域 float SelRadius; // 如果为选择区域,则这里为区域半径 char Brush[128]; // 如果SelMethod为选择对象, 这里表示的是光标 ;若为区域,则表示DECAL 纹理. }; struct SpellApperanceDesc { bool bHideWeapon; // 武器是否需要隐藏 SpellApperanceDesc() { bHideWeapon = false; } }; struct SpellEffectDesc : public NiMemObject { SpellEffectDesc() { } ~SpellEffectDesc() { unsigned int ui = 0; for (ui = 0; ui < vTriggers.size(); ui++) { NiDelete vTriggers[ui]; } vTriggers.clear(); for (ui=0; ui < vEffects.size(); ui++) { NiDelete vEffects[ui]; } vEffects.clear(); for (ui=0; ui GetType() == ET_PROJECTILE) return true; } return false; } std::vector vEffects; std::vector vTriggers; std::vector vSounds; }; class SpellVisualDesc : public NiMemObject { public: SpellVisualDesc() { m_SpellId = -1; m_SpellCls = SPELL_CLS_BASE; // 技能类别 szCastAnimName[0] = '\0'; szAttackAnimName[0] = '\0'; szDamageAnimName[0] = '\0'; szTunnelAnimName[0] = '\0'; m_Brush[0] = '\0'; m_fBrushHeight = 0.05f; auraeffid = -1; } int m_SpellId; float m_fBrushHeight; ESpellClass m_SpellCls; char m_Icon[MAX_PATH]; char m_Brush[MAX_PATH]; char szCastAnimName[128]; char szAttackAnimName[128]; char szDamageAnimName[128]; char szTunnelAnimName[128]; int auraeffid; SpellApperanceDesc m_ApperanceDesc; SpellEffectDesc m_kEffects; }; class AuraVisualDesc : public NiMemObject { public: AuraVisualDesc() { } SpellEffectDesc m_kEffects; }; class SpellInstance; // spell info wrapper class SpellTemplate : public NiMemObject//: public SpellDesc { public: SpellTemplate(const stSpellInfo& info); ~SpellTemplate(); SpellID GetSpellID() const { return m_spellInfo.uiId; } const std::string& GetName() const { return m_spellInfo.name; } unsigned int GetCategory() const{ return m_spellInfo.uiCategory; } unsigned int GetSpellLev() const{ return m_spellInfo.uiSpellLevel; } unsigned int GetSpellMaxLev() const{ return m_spellInfo.uiMaxLevel; } unsigned int GetSpellGroup() const{ return m_spellInfo.uiSpellGroupType; } unsigned int GetSpellMP() const{ return m_spellInfo.uiManaCost; } unsigned int GetAttribute() const{ return m_spellInfo.uiAttribute; } unsigned int GetAuraInfo() const{ return m_spellInfo.uiAuraInfo; } bool GetICON(std::string& icon); bool GetBrush(std::string& brush); float GetBrushHeight(float& fHeight); // 创建技能实例 // SpellInstance* CreateInstance(); // 检查施法者条件是否满足 BOOL CheckOwnerRequest(CCharacter* pOwner) const; // 检查目标类型是否有效 BOOL IsTargetValid(UpdateObj* pTarget) const; // 检查目标关系是否有效 BOOL IsTargetRelativeValid(UpdateObj* pAttacker, UpdateObj* pAttackee) const; // 是否需要选择目标对象 BOOL IsNeedSelectTargetObject(CCharacter* pOwner) const; // 获取选择目标方法 int GetSelectMethod() const; const SpellVisualDesc* GetVisulalKit() const; const AuraVisualDesc* GetAuraVisulalKit() const; SpellSoundDesc* FindSoundDesc(int id); // 选择目标 BOOL SelectTarget(CCharacter* Caller) const; static BOOL CheckRangeInvalid(unsigned int spellid, float fDist); bool GetMpRequestPercentage(unsigned int& uiValue) const; //获取技能变化后数值 bool GetDuration(unsigned int&durtime); bool GetDescription(std::string& str, bool bLocal = true); bool GetMPRequest(unsigned int& uiValue) const; uint32 GetRecoverTime(); uint32 GetCastTime(); float GetRadius() const; static void GetRange(unsigned int spellid, float& minRange, float& maxRange); bool GetSpellPoint(int TypePos, unsigned int& basepoint, unsigned int& miscpoint); uint32 GetMaxStack(); uint32 GetTargetNum(); //获取模版属性 bool GetTDuration(unsigned int&durtime); bool GetTDescription(std::string& str); bool GetTMPRequest(unsigned int& uiValue) const; uint32 GetTCastTime(); uint32 GetTRecoverTime(); float GetTRadius() const; static void GetTRange(unsigned int spellid, float& minRange, float& maxRange); bool GetTSpellPoint(int TypePos, unsigned int& basepoint, unsigned int& miscpoint); uint32 GetTMaxStack(); uint32 GetTTargetNum(); uint32 GetCategoryRecoverTime(){ return m_spellInfo.uiCategoryRecoveryTime; } uint32 GetStartRecoveryTime(){ return m_spellInfo.uiStartRecoveryTime; } uint32 GetCastIndex() { return m_spellInfo.uiCastIndex; } const stSpellInfo& GetSpellInfo() { return m_spellInfo; } uint32 GetLineNameEntry(){ return m_spellInfo.uiLineNameEntry; } uint32 GetSubLineNameEntry(){ return m_spellInfo.uiSubLineNameEntry; } void AddCooldown(); void AddStartCooldown(); static const char* GetSpellErrorString(uint8 uiError); static bool IsDamageSpell(ui32 spellid); static bool IsChongZhuangSpell(ui32 spellid); static bool IsHelpFulSpell(ui32 spellid); static bool IsHealingSpell(ui32 spellid); static bool IsMaNaSpell(ui32 spellid); static bool IsResurrectSpell(ui32 spellid); static bool IsSelfSpell(ui32 spellid); static bool IsSelfOrFriendlySpell(ui32 spellid); static bool IsSingleEnemySpell(ui32 spellid); static bool IsEnemySpell(ui32 spellid); protected: //CEffectBase* CreateNifEffect(SpellEffectNifNode* pEffectNode) const; //CEffectBase* CreateDecalEffect(SpellDecalEffectNode* pEffectNode) const; //CEffectBase* CreateTrailEffect(SpellTrailEffectNode* pEffectNode) const; //CEffectBase* CreateProjectileEffect(SpellProjectileEffectNode* pEffectNode) const; //CEffectBase* CreatePosConstraintEffect(SpellPosConstraintEffectNode* pkEffectNode) const; private: stSpellInfo m_spellInfo; };