#include #include "SpellProcess.h" #include "Character.h" #include "ObjectManager.h" #include "Effect/EffectManager.h" #include "ItemManager.h" #include "ClientApp.h" #include "SkillManager.h" #include "AudioInterface.h" #include "UI/UISYstem.h" #include "UI/UICastBar.h" #include "ui/UIGamePlay.h" #include "ui/UIShowPlayer.h" #include "ui/SystemTips .h" #include "PlayerInputMgr.h" #include "Console.h" #include "SpellEffect.h" #include "Utils/MersenneTwister.h" #include "Utils/Soundid.h" void SpellInstance::EffectTriggerManager::Reset() { ExecuteTriggerByAction(TA_Deactive); m_TriggerMap.clear(); m_TimeTrigs.clear(); m_EvtTrigs.clear(); } void SpellInstance::EffectTriggerManager::AddTrigger(SpellTriggerBase* pkTriggerInfo) { if (pkTriggerInfo->GetType() == SpellTriggerBase::Event) m_EvtTrigs.push_back(pkTriggerInfo); else if (pkTriggerInfo->GetType() == SpellTriggerBase::Timer) m_TimeTrigs.push_back(pkTriggerInfo); else NIASSERT(0); } void SpellInstance::EffectTriggerManager::AddEffectTriggerPair(int iTriggerID, SpellEffectNode* pkEffectInfoNode) { m_TriggerMap.insert(TRIGGERPAIR_MAP::value_type(iTriggerID, pkEffectInfoNode)); } void SpellInstance::EffectTriggerManager::Update(int iState, float fTime) { ProcessTimeTriggers(fTime); } void SpellInstance::EffectTriggerManager::ExecuteTriggerByAction(const int& iAction) { for (unsigned int ui = 0; ui < m_EvtTrigs.size(); ++ui) { SpellEventTrigger* pkTrig = (SpellEventTrigger*)m_EvtTrigs[ui]; NIASSERT(pkTrig); if ( pkTrig->iAction == TA_Deactive ) { ProcessTrigger(pkTrig->iTrigID, pkTrig->iAction); } } } void SpellInstance::EffectTriggerManager::ExecuteTriggerByEvent(const int& iEvent, bool bAll /*= true*/) { ProcessEvtTriggers(iEvent, 0, bAll); } void SpellInstance::EffectTriggerManager::ProcessTimeTriggers(float fTime) { for (unsigned int ui = 0 ; ui < m_TimeTrigs.size(); ++ui) { SpellTimeTrigger* pTrigger = (SpellTimeTrigger*)m_TimeTrigs[ui]; NIASSERT(pTrigger); if (!pTrigger) continue; static const float fFactor = 1.0f; float fElapse = -FLT_MAX; if (pTrigger->iBegin == TT_Cast) { fElapse = m_pkSpellInst->GetCastElapse(); } else if (pTrigger->iBegin == TT_Attack) { fElapse = m_pkSpellInst->GetAttackElapse(); } else if (pTrigger->iBegin == TT_Spell) { fElapse = m_pkSpellInst->GetSpellElapse(); } if (fElapse >= pTrigger->fOffsetTime) { ProcessTrigger(pTrigger->iTrigID, pTrigger->iAction); } } } void SpellInstance::EffectTriggerManager::ProcessEvtTriggers(const int& iEvent, void* pvParam, bool bIgnoreParam/*=false*/) { for (unsigned int ui = 0; ui < m_EvtTrigs.size(); ++ui) { SpellEventTrigger* pkTrig = (SpellEventTrigger*)m_EvtTrigs[ui]; NIASSERT(pkTrig); if (!pkTrig || pkTrig->iEvent != iEvent) continue; if (iEvent == TE_AnimKey && !bIgnoreParam) { int iAnimKey = *(int*)pvParam; if (iAnimKey != pkTrig->iAnimKey) continue; } ProcessTrigger(pkTrig->iTrigID, pkTrig->iAction); } } void SpellInstance::EffectTriggerManager::ProcessTrigger(const int& iTriggerID, const int& iAction) { TRIGGERPAIR_MAP::iterator it = m_TriggerMap.lower_bound(iTriggerID); for (it; it != m_TriggerMap.upper_bound(iTriggerID); ++it) { SpellEffectNode* pkEffectNode = it->second; NIASSERT(pkEffectNode); if (!pkEffectNode) continue; if (iAction == TA_Active) { m_pkSpellInst->EmitEffect(pkEffectNode); } else if (iAction == TA_Deactive) { m_pkSpellInst->ReleaseEffect(pkEffectNode); m_pkSpellInst->NeedRelease( true ); it->second = NULL; } else NIASSERT(0); } } void SpellInstance::EffectTriggerManager::ProcessEvtTriggers(const int& iSpellID, int iEvent, void* pvParam, bool bIgnoreParam/*=false*/) { for (unsigned int ui = 0; ui < m_EvtTrigs.size(); ++ui) { SpellEventTrigger* pkTrig = (SpellEventTrigger*)m_EvtTrigs[ui]; NIASSERT(pkTrig); if (!pkTrig || pkTrig->iEvent != iEvent) continue; if (iEvent == TE_AnimKey && !bIgnoreParam) { int iAnimKey = *(int*)pvParam; if (iAnimKey != pkTrig->iAnimKey) continue; } ProcessTrigger(iSpellID, pkTrig->iTrigID, pkTrig->iAction); } } void SpellInstance::EffectTriggerManager::ProcessTrigger(const int& iSpellID, const int& iTriggerID, const int& iAction) { if (!m_pkSpellInst) return; if (iAction == TA_Active) { m_pkSpellInst->EmitEffect(iSpellID, iTriggerID); } else if (iAction == TA_Deactive) { m_pkSpellInst->ReleaseEffect(iSpellID, iTriggerID); } } void SpellInstance::EffectTriggerManager::OnEvent(int iEvent, void* pvParam) { ProcessEvtTriggers(iEvent, pvParam); } void SpellInstance::EffectTriggerManager::OnEvent(int iSpellID, int iEvent, void* pvParam) { ProcessEvtTriggers(iSpellID, iEvent, pvParam); } SpellInstance::SpellInstance(CCharacter* pOwner):m_bNeedRelease(false),m_bWaitAnim(false) { m_AttackStep = LPAS_NONE; ResetTime(); m_SpellTemplate = 0; m_pOwner = pOwner; m_bHideWeapon = false; m_bIsEffectSetup = false; m_SpellID = 0; m_pkTriggerMan = new EffectTriggerManager(this); m_fNextEndTime = NiActorManager::INVALID_TIME; m_iCastAniCode = NiActorManager::INVALID_SEQUENCE_ID; m_iTunnelAniCode = NiActorManager::INVALID_SEQUENCE_ID; } void SpellInstance::ResetTime() { m_uiCastFullTime = 0; m_uiCastOverTime = 0; m_fAttackStartTime = FLT_MAX; m_fCastStartTime = FLT_MAX; m_fTunnelStartTime = FLT_MAX; } SpellInstance::~SpellInstance() { if (m_pkTriggerMan) { delete m_pkTriggerMan; m_pkTriggerMan = 0; } } bool SpellInstance::InitSkillTemplate(const SpellID& spellID) { m_SpellTemplate = SYState()->SkillMgr->GetSpellTemplate(spellID); if (!m_SpellTemplate) return false; return true; } void SpellInstance::Reset() { EndSpell(); //if (m_pOwner) //{ // CPlayer* Player = m_pOwner->GetAsPlayer(); // if (Player && Player->IsLocalPlayer()) // { // UInGame* pInGame = UInGame::Get(); // if (pInGame) // { // USpellProcessBar* pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_CASTBAR); // if (pSpellProcessBar) // { // ULog("Reset"); // } // } // } //} } BOOL SpellInstance::BeginMagic(const SpellID& spellID, const vector& vTargetHit, const SpellCastTargets& spellCastTargets) { if (!m_pOwner) return FALSE; if (m_AttackStep == LPAS_CAST) EndCast(); if (m_AttackStep == LPAS_ATTACK && m_SpellID != spellID) Reset(); m_SpellID = spellID; // if (!m_bIsEffectSetup) m_bIsEffectSetup = EffectSetup(spellID); if (!m_bIsEffectSetup) return FALSE; SetTargets(vTargetHit, spellCastTargets); uint32 msCurTime = float2int32(NiGetCurrentTimeInSec() * 1000.0f); m_uiCastOverTime = msCurTime; ChangeLocation(spellCastTargets); ChangeApperance(); return BeginAttack(m_targetList); } void SpellInstance::EndMagic() { m_bIsEffectSetup = false; m_SpellID = 0; RestoreApperance(); EndAttack(); } void SpellInstance::SetTargets(const vector& vTargetHit, const SpellCastTargets& spellCastTargets) { NiPoint3 kSrcPos(spellCastTargets.m_srcX, spellCastTargets.m_srcY, spellCastTargets.m_srcZ); NiPoint3 kDestPos(spellCastTargets.m_destX, spellCastTargets.m_destY, spellCastTargets.m_destZ); m_targetList.Clear(); m_targetListdetail.Clear(); if (spellCastTargets.m_targetMask & TARGET_FLAG_UNIT || spellCastTargets.m_targetMask & TARGET_FLAG_SELF || spellCastTargets.m_targetMask & TARGET_FLAG_CORPSE || spellCastTargets.m_targetMask & TARGET_FLAG_CORPSE2) { m_targetList.AddEntry(spellCastTargets.m_unitTarget); } if (spellCastTargets.m_targetMask & TARGET_FLAG_SOURCE_LOCATION) { m_targetList.AddEntry(kSrcPos, 3.0f); } if (spellCastTargets.m_targetMask & TARGET_FLAG_DEST_LOCATION) { m_targetList.AddEntry(kDestPos, 3.0f); } for ( int i = 0; i < vTargetHit.size(); i++ ) { m_targetListdetail.AddEntry( vTargetHit[i] ); } } void SpellInstance::ChangeLocation(const SpellCastTargets& spellCastTargets) { if (m_pOwner == NULL) return; NiPoint3 kTragetPos; uint32 mask = spellCastTargets.m_targetMask; if ( mask & (TARGET_FLAG_OBJECT | TARGET_FLAG_UNIT | TARGET_FLAG_CORPSE | TARGET_FLAG_CORPSE2 )) { uint64 targetID = spellCastTargets.m_unitTarget; CGameObject* pkObject = (CGameObject*)ObjectMgr->GetObject(targetID); if (!pkObject) return; kTragetPos = pkObject->GetPosition(); if (m_pOwner == pkObject && pkObject->IsLocalPlayer()) { return; } /*if (m_pOwner->GetCurPostureState() != STATE_MOVE) m_pOwner->SetDirectionTo(kTragetPos);*/ } else if ( mask & TARGET_FLAG_SOURCE_LOCATION ) { kTragetPos = NiPoint3(spellCastTargets.m_srcX, spellCastTargets.m_srcY, spellCastTargets.m_srcZ); } else if ( mask & TARGET_FLAG_DEST_LOCATION ) { kTragetPos = NiPoint3(spellCastTargets.m_destX, spellCastTargets.m_destY, spellCastTargets.m_destZ); if (m_pOwner->GetCurPostureState() != STATE_MOVE) m_pOwner->SetDirectionTo(kTragetPos); } else { return; } } void SpellInstance::RestoreApperance() { if (m_pOwner && m_bHideWeapon) { NiNodePtr spNode = m_pOwner->GetSceneNode(); NiAVObject* pRightWeapon = spNode->GetObjectByName("AttackRightHand_Node"); NiAVObject* pLeftWeapon = spNode->GetObjectByName("AttackLeftHand_Node"); NiAVObject* pShield = spNode->GetObjectByName("Shield_Node"); if (pLeftWeapon) { pLeftWeapon->SetAppCulled(false); } if (pRightWeapon) { pRightWeapon->SetAppCulled(false); } if (pShield) { pShield->SetAppCulled(false); } m_bHideWeapon = false; } } BOOL SpellInstance::ChangeApperance() { if (!m_SpellTemplate || !m_pOwner) return FALSE; const SpellVisualDesc* pkVisualKit = m_SpellTemplate->GetVisulalKit(); if (!pkVisualKit) return FALSE; if(!m_pOwner->isType(TYPE_PLAYER)) { return TRUE; } ui32 offhandweapon_entryid = m_pOwner->GetUInt32Value(PLAYER_VISIBLE_ITEM_7_0); ItemPrototype_Client* pkOffHandWeapon = ItemMgr->GetItemPropertyFromDataBase(offhandweapon_entryid); if (pkVisualKit->m_ApperanceDesc.bHideWeapon) { NiNodePtr spNode = m_pOwner->GetSceneNode(); if (!spNode) return FALSE; NiAVObject* pRightWeapon = spNode->GetObjectByName("AttackRightHand_Node"); NiAVObject* pLeftWeapon = spNode->GetObjectByName("AttackLeftHand_Node"); NiAVObject* pShield = spNode->GetObjectByName("Shield_Node"); if (pRightWeapon && !pRightWeapon->GetAppCulled()) { pRightWeapon->SetAppCulled(true); } if (pLeftWeapon) { pLeftWeapon->SetAppCulled(true); } if (pShield) { pShield->SetAppCulled(true); } m_bHideWeapon = true; } else if (pkOffHandWeapon && pkOffHandWeapon->SubClass == ITEM_SUBCLASS_WEAPON_BAOZHU) { NiNodePtr spNode = m_pOwner->GetSceneNode(); if (!spNode) return FALSE; NiAVObject* pLeftWeapon = spNode->GetObjectByName("AttackLeftHand_Node"); if (pLeftWeapon) { pLeftWeapon->SetAppCulled(true); } m_bHideWeapon = true; } return TRUE; } /// return isend:TRUE|FALSE BOOL SpellInstance::Update(float fDelta) { float fCurrentTime = SYState()->ClientApp->GetAccumTime(); m_fUpdateTime = fCurrentTime; BOOL bRet = FALSE; if (m_AttackStep == LPAS_CAST) { bRet = UpdateCast(m_fUpdateTime); } else if (m_AttackStep == LPAS_ATTACK) { bRet = UpdateAttack(m_fUpdateTime); } else if (m_AttackStep == LPAS_TUNNEL) { bRet = UpdateTunnel(m_fUpdateTime); } else { bRet = TRUE; } UpdateCastBar(); UpdateTriggers(); return bRet; } void SpellInstance::UpdateTriggers() { if (m_pkTriggerMan) { if (m_pOwner && m_pOwner->GetTextKeys().GetSize() > 0) { const NiTObjectArray& aTextkeys = m_pOwner->GetTextKeys(); for (unsigned int ui = 0; ui < aTextkeys.GetSize(); ++ui) { const NiFixedString& kStr = aTextkeys.GetAt(ui); const char* p = strstr((const char*)kStr, "effect"); if (p != NULL) { p = strchr(p, '_'); int val = 0; // default key value if (p && p[0] == '_' && p[1] != '0') { val = p[1] - '0'; } m_pkTriggerMan->OnEvent(m_SpellID, TE_AnimKey, (void*)&val); } if (kStr == "end") { int val = 999; m_pkTriggerMan->OnEvent(m_SpellID, TE_AnimKey, (void*)&val); } } } m_pkTriggerMan->Update(m_AttackStep, m_fUpdateTime); } } void SpellInstance::BeginCast(SpellID spellID, const uint32& castTime, const SpellCastTargets& spellCastTargets) { NIASSERT(m_pOwner); if (!m_pOwner) return; Reset(); m_bIsEffectSetup = EffectSetup(spellID); if (!m_bIsEffectSetup) return; m_fCastStartTime = SYState()->ClientApp->GetAccumTime(); uint32 msCurTime = float2int32(NiGetCurrentTimeInSec() * 1000.0f); m_uiCastFullTime = castTime; m_uiCastOverTime = msCurTime + castTime; const SpellVisualDesc* pkVisualKit = m_SpellTemplate->GetVisulalKit(); if (!pkVisualKit) return; if (pkVisualKit->szCastAnimName && pkVisualKit->szCastAnimName[0] != '\0') { m_bWaitAnim = true; m_iCastAniCode = m_pOwner->GetAnimationIDByName(pkVisualKit->szCastAnimName); /*if (m_iCastAniCode != NiActorManager::INVALID_SEQUENCE_ID) m_pOwner->ActivateAnimation(m_iCastAniCode, 2, 2, 0.1f, NiKFMTool::SYNC_SEQUENCE_ID_NONE, true, false, true);*/ } m_SpellID = spellID; if (m_pOwner->GetCurActionState() != STATE_SKILL_ATTACK) m_pOwner->SetNextState(STATE_SKILL_ATTACK, CUR_TIME); ChangeSpellState(LPAS_CAST); ChangeLocation(spellCastTargets); ChangeApperance(); CPlayer* Player = m_pOwner->GetAsPlayer(); CPlayer* pLocalPlayer = (CPlayer*)ObjectMgr->GetLocalPlayer(); CCharacter* pChar = pLocalPlayer->GetTargetObject(); if (Player && Player->IsLocalPlayer()) { UInGame* pInGame = UInGame::Get(); if (pInGame) { USpellProcessBar* pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_CASTBAR); if (pSpellProcessBar) { pSpellProcessBar->SpellCastBegin(); } } } if (m_pOwner && pLocalPlayer->IsTarget(m_pOwner)) { USpellProcessBar* pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_TARGETCASTBAR); if (pSpellProcessBar) { pSpellProcessBar->SpellCastBegin(); } } if (Player && Player->mbIsTargetTarget && pChar && pChar->IsTarget(Player)) { USpellProcessBar* pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_TARGETTARGETCASTBAR); if (pSpellProcessBar && TeamShow->GetTargetTargetShow()) { pSpellProcessBar->SpellCastBegin(); } } if (g_WatchTargetMgr) g_WatchTargetMgr->UpdateSpellProcess(m_pOwner->GetGUID(), 0); } void SpellInstance::BeginTunnel(SpellID spellID, const uint32& castTime ) { NIASSERT(m_pOwner); if (!m_pOwner) return; Reset(); m_bIsEffectSetup = EffectSetup(spellID); if (!m_bIsEffectSetup) return; m_fTunnelStartTime = SYState()->ClientApp->GetAccumTime(); uint32 msCurTime = float2int32(NiGetCurrentTimeInSec() * 1000.0f); m_uiCastFullTime = castTime; m_uiCastOverTime = msCurTime + castTime; const SpellVisualDesc* pkVisualKit = m_SpellTemplate->GetVisulalKit(); if (!pkVisualKit) return; if (pkVisualKit->szTunnelAnimName && pkVisualKit->szTunnelAnimName[0] != '\0') { m_bWaitAnim = true; m_iTunnelAniCode = m_pOwner->GetAnimationIDByName(pkVisualKit->szTunnelAnimName); /*if (m_iCastAniCode != NiActorManager::INVALID_SEQUENCE_ID) m_pOwner->ActivateAnimation(m_iCastAniCode, 2, 2, 0.1f, NiKFMTool::SYNC_SEQUENCE_ID_NONE, true, false, true);*/ } m_SpellID = spellID; if (m_pOwner->GetCurActionState() != STATE_SKILL_ATTACK) m_pOwner->SetNextState(STATE_SKILL_ATTACK, CUR_TIME); ChangeSpellState(LPAS_TUNNEL); //ChangeLocation(spellCastTargets); ChangeApperance(); CPlayer* Player = m_pOwner->GetAsPlayer(); CPlayer* pLocalPlayer = (CPlayer*)ObjectMgr->GetLocalPlayer(); CCharacter* pChar = pLocalPlayer->GetTargetObject(); if (Player && Player->IsLocalPlayer()) { UInGame* pInGame = UInGame::Get(); if (pInGame) { USpellProcessBar* pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_CASTBAR); if (pSpellProcessBar) { pSpellProcessBar->SpellCastBegin(); } } } if (m_pOwner && pLocalPlayer->IsTarget(m_pOwner)) { USpellProcessBar* pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_TARGETCASTBAR); if (pSpellProcessBar) { pSpellProcessBar->SpellCastBegin(); } } if (Player && Player->mbIsTargetTarget && pChar && pChar->IsTarget(Player)) { USpellProcessBar* pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_TARGETTARGETCASTBAR); if (pSpellProcessBar && TeamShow->GetTargetTargetShow()) { pSpellProcessBar->SpellCastBegin(); } } if (g_WatchTargetMgr) g_WatchTargetMgr->UpdateSpellProcess(m_pOwner->GetGUID(), 0); } void SpellInstance::CastDelay(uint32 uiDelay) { m_uiCastFullTime += uiDelay; m_uiCastOverTime += uiDelay; } void SpellInstance::TunnelDelay(uint32 uiDelay) { uint32 msCurTime = float2int32(NiGetCurrentTimeInSec() * 1000.0f); m_uiCastFullTime = msCurTime - m_fTunnelStartTime*1000 + uiDelay; m_uiCastOverTime = msCurTime + uiDelay; } void SpellInstance::SpellFailure(uint32 spellid, uint8 uiErrorCode) { USpellProcessBar* pSpellProcessBar = NULL; CPlayer* pLocalPlayer = (CPlayer*)ObjectMgr->GetLocalPlayer(); CPlayer* pkPlayer = m_pOwner->GetAsPlayer(); CCharacter* pChar = pLocalPlayer->GetTargetObject(); if (pkPlayer && pkPlayer->IsLocalPlayer()) { //SYState()->SkillMgr->CooldownCancel(spellid); if ( m_AttackStep != LPAS_TUNNEL ) { SpellTemplate* pSpellTemplate = SYState()->SkillMgr->GetSpellTemplate(spellid); if (pSpellTemplate && pSpellTemplate->GetSpellGroup() > 0) { SYState()->SkillMgr->CooldownCancel_Group(pSpellTemplate->GetSpellGroup()); }else { SYState()->SkillMgr->CooldownCancel(spellid); } } pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_CASTBAR); if (pSpellProcessBar) { pSpellProcessBar->SpellCastFailure(); } } if (pkPlayer && pLocalPlayer->IsTarget(pkPlayer)) { pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_TARGETCASTBAR); if (pSpellProcessBar) { pSpellProcessBar->SpellCastFailure(); } } if (pkPlayer && pkPlayer->mbIsTargetTarget && pChar && pChar->IsTarget(pkPlayer)) { pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_TARGETTARGETCASTBAR); if (pSpellProcessBar){ pSpellProcessBar->SpellCastFailure(); } } if (g_WatchTargetMgr) g_WatchTargetMgr->UpdateSpellProcess(m_pOwner->GetGUID(), 2); ClearBreakEffects(); EndCast(); } BOOL SpellInstance::UpdateCast(float fTime) { if (m_pOwner->IsCurSecAnimEndInTime(fTime) && m_bWaitAnim ) { if (m_iCastAniCode != NiActorManager::INVALID_SEQUENCE_ID) { m_pOwner->ActivateAnimation(m_iCastAniCode, 2, 2, 0.1f, NiKFMTool::SYNC_SEQUENCE_ID_NONE, true, false, true); m_bWaitAnim = false; } } return FALSE; } BOOL SpellInstance::UpdateTunnel(float fTime) { if (m_pOwner->IsCurSecAnimEndInTime(fTime) && m_bWaitAnim ) { if (m_iTunnelAniCode != NiActorManager::INVALID_SEQUENCE_ID) { m_pOwner->ActivateAnimation(m_iTunnelAniCode, 2, 2, 0.1f, NiKFMTool::SYNC_SEQUENCE_ID_NONE, true, false, true); m_bWaitAnim = false; } } return FALSE; } bool SpellInstance::IsSpellCast(SpellID spellID) { return m_SpellID == spellID; } void SpellInstance::UpdateCastBar() { if(!m_uiCastOverTime) return; USpellProcessBar* pSpellProcessBar = NULL; CPlayer* pLocalPlayer = (CPlayer*)ObjectMgr->GetLocalPlayer(); CCharacter* pChar = pLocalPlayer->GetTargetObject(); pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_CASTBAR); if (m_pOwner == ObjectMgr->GetLocalPlayer()) { if (pSpellProcessBar) { uint32 msCurTime = float2int32(NiGetCurrentTimeInSec() * 1000.0f); if (msCurTime <= m_uiCastOverTime) { uint32 uiRemainTime = m_uiCastOverTime - msCurTime; uint32 uiCurCastElapsed = m_uiCastFullTime - uiRemainTime; if ( m_AttackStep == LPAS_TUNNEL ) { uiCurCastElapsed = uiRemainTime; } pSpellProcessBar->SetSpell(m_SpellTemplate->GetName().c_str(), m_AttackStep == LPAS_TUNNEL); pSpellProcessBar->SetSpellCast(uiCurCastElapsed, m_uiCastFullTime); } else { uint32 uiOverflowTime = msCurTime - m_uiCastOverTime; pSpellProcessBar->SpellCastEnd(); } } } pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_TARGETCASTBAR); if (m_pOwner && pLocalPlayer->IsTarget(m_pOwner)) { if (pSpellProcessBar) { uint32 msCurTime = float2int32(NiGetCurrentTimeInSec() * 1000.0f); if (msCurTime <= m_uiCastOverTime) { uint32 uiRemainTime = m_uiCastOverTime - msCurTime; uint32 uiCurCastElapsed = m_uiCastFullTime - uiRemainTime; if ( m_AttackStep == LPAS_TUNNEL ) { uiCurCastElapsed = uiRemainTime; } pSpellProcessBar->SetSpell(m_SpellTemplate->GetName().c_str(), m_AttackStep == LPAS_TUNNEL); pSpellProcessBar->SetSpellCast(uiCurCastElapsed, m_uiCastFullTime); } else { uint32 uiOverflowTime = msCurTime - m_uiCastOverTime; pSpellProcessBar->SpellCastEnd(); } } } pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_TARGETTARGETCASTBAR); if (m_pOwner && m_pOwner->mbIsTargetTarget && pChar && pChar->IsTarget(m_pOwner)) { if (pSpellProcessBar && TeamShow->GetTargetTargetShow()) { uint32 msCurTime = float2int32(NiGetCurrentTimeInSec() * 1000.0f); if (msCurTime <= m_uiCastOverTime) { uint32 uiRemainTime = m_uiCastOverTime - msCurTime; uint32 uiCurCastElapsed = m_uiCastFullTime - uiRemainTime; if ( m_AttackStep == LPAS_TUNNEL ) { uiCurCastElapsed = uiRemainTime; } pSpellProcessBar->SetSpell(m_SpellTemplate->GetName().c_str(), m_AttackStep == LPAS_TUNNEL); pSpellProcessBar->SetSpellCast(uiCurCastElapsed, m_uiCastFullTime); } else { uint32 uiOverflowTime = msCurTime - m_uiCastOverTime; pSpellProcessBar->SpellCastEnd(); } } } if (g_WatchTargetMgr) { uint32 msCurTime = float2int32(NiGetCurrentTimeInSec() * 1000.0f); if (msCurTime <= m_uiCastOverTime) { uint32 uiRemainTime = m_uiCastOverTime - msCurTime; uint32 uiCurCastElapsed = m_uiCastFullTime - uiRemainTime; if ( m_AttackStep == LPAS_TUNNEL ) { uiCurCastElapsed = uiRemainTime; } g_WatchTargetMgr->UpdateSpellProcess(m_pOwner->GetGUID(), 3, m_SpellTemplate->GetName().c_str(), uiCurCastElapsed, m_uiCastFullTime); } else { g_WatchTargetMgr->UpdateSpellProcess(m_pOwner->GetGUID(), 1); } } } void SpellInstance::EndCast() { if (m_pOwner && m_iCastAniCode != NiActorManager::INVALID_SEQUENCE_ID) { if (m_pOwner->DeactivateAnimation(m_iCastAniCode, 0.0f)) m_iCastAniCode = NiActorManager::INVALID_SEQUENCE_ID; } USpellProcessBar* pSpellProcessBar = NULL; if (m_pOwner == ObjectMgr->GetLocalPlayer()) { pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_CASTBAR); if (pSpellProcessBar) { pSpellProcessBar->SpellCastEnd(); } } if (m_pOwner && ObjectMgr->GetLocalPlayer()->IsTarget(m_pOwner)) { pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_TARGETCASTBAR); if (pSpellProcessBar) { pSpellProcessBar->SpellCastEnd(); } } CCharacter* pChar = ObjectMgr->GetLocalPlayer()->GetTargetObject(); if (m_pOwner && m_pOwner->mbIsTargetTarget && pChar && pChar->IsTarget(m_pOwner)) { pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_TARGETTARGETCASTBAR); if (pSpellProcessBar) { pSpellProcessBar->SpellCastEnd(); } } if (g_WatchTargetMgr) g_WatchTargetMgr->UpdateSpellProcess(m_pOwner->GetGUID(), 1); ChangeSpellState(LPAS_NONE); RestoreApperance(); ResetTime(); } void SpellInstance::EndTunnel() { if (m_pOwner && m_iTunnelAniCode != NiActorManager::INVALID_SEQUENCE_ID) { if (m_pOwner->DeactivateAnimation(m_iTunnelAniCode, 1.0f)) m_iTunnelAniCode = NiActorManager::INVALID_SEQUENCE_ID; } USpellProcessBar* pSpellProcessBar = NULL; if (m_pOwner == ObjectMgr->GetLocalPlayer()) { pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_CASTBAR); if (pSpellProcessBar) { pSpellProcessBar->SpellCastEnd(); } } if (m_pOwner && ObjectMgr->GetLocalPlayer()->IsTarget(m_pOwner)) { pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_TARGETCASTBAR); if (pSpellProcessBar) { pSpellProcessBar->SpellCastEnd(); } } CCharacter* pChar = ObjectMgr->GetLocalPlayer()->GetTargetObject(); if (m_pOwner && m_pOwner->mbIsTargetTarget && pChar && pChar->IsTarget(m_pOwner)) { pSpellProcessBar = INGAMEGETFRAME(USpellProcessBar, FRAME_IG_TARGETTARGETCASTBAR); if (pSpellProcessBar) { pSpellProcessBar->SpellCastEnd(); } } if (g_WatchTargetMgr) g_WatchTargetMgr->UpdateSpellProcess(m_pOwner->GetGUID(), 1); ChangeSpellState(LPAS_NONE); RestoreApperance(); ResetTime(); } BOOL SpellInstance::BeginAttack(const Target& Targets) { float fCurrentTime = SYState()->ClientApp->GetAccumTime(); const SpellVisualDesc* pkVisualKit = m_SpellTemplate->GetVisulalKit(); if (!pkVisualKit) return FALSE; m_fAttackStartTime = fCurrentTime; if (m_pOwner->GetCurActionState() != STATE_SKILL_ATTACK) if (!m_pOwner->ForceStateChange(STATE_SKILL_ATTACK, (DWORD)fCurrentTime)) return FALSE; ChangeSpellState(LPAS_ATTACK); if (pkVisualKit->szAttackAnimName && pkVisualKit->szAttackAnimName[0] != '\0') { m_iAnimCode = m_pOwner->GetAnimationIDByName(pkVisualKit->szAttackAnimName); if(m_iAnimCode != NiActorManager::INVALID_SEQUENCE_ID) { m_pOwner->ActivateAnimation(m_iAnimCode, 2, 2, 0.1f, NiKFMTool::SYNC_SEQUENCE_ID_NONE, false, true, true); } } return TRUE; } BOOL SpellInstance::UpdateAttack(float fTime) { if (m_pOwner->IsCurSecAnimEndInTime(fTime)) { return TRUE; } return FALSE; } void SpellInstance::EndAttack() { ChangeSpellState(LPAS_NONE); ClearActiveEffectMap(); } void SpellInstance::EndSpell() { EndCast(); EndMagic(); EndTunnel(); } void SpellInstance::ChangeSpellState(int iState) { if (iState == m_AttackStep) { return; } if (m_pkTriggerMan != NULL) { int iEvent = 0; if (m_AttackStep == LPAS_CAST) { iEvent = TE_CastEnd; } else if (m_AttackStep == LPAS_ATTACK) { iEvent = TE_AttackEnd; } if (iState == LPAS_CAST) { iEvent = TE_CastStart; } else if (iState == LPAS_ATTACK) { iEvent = TE_AttackStart; } if (iState == LPAS_TUNNEL) { iEvent = TE_TunnelStart; } if (iState == LPAS_ENDTUNNEL) { iEvent = TE_TunnelEnd; } OnEvent(iEvent, NULL); } m_AttackStep = (ESpellStep)iState; } void SpellInstance::OnEvent(int iEvent, void* pvParam) { if (m_pkTriggerMan) m_pkTriggerMan->OnEvent(iEvent, pvParam); } void SpellInstance::EmitEffect(const std::vector& effectnodes) { if (!m_pOwner || effectnodes.size() <= 0) return; for (unsigned int ui = 0; ui < effectnodes.size(); ui++) { CEffectBase* pkEffect = 0; if (m_activeEffMap.GetAt(effectnodes[ui], pkEffect)) { ReleaseEffect(effectnodes[ui]); } } SpellEffectEmit::EmitParam ep; ep.m_iSpellid = m_SpellID; ep.m_OwnerID = m_pOwner->GetGUID(); ep.m_kTargets = m_targetList; ep.m_kTargetsDetail = m_targetListdetail; ep.m_vEffects = effectnodes; std::vector results; SpellEffectEmit::Get()->Emit(ep, results, false); for (unsigned int ui = 0; ui < results.size(); ui++) { if (results[ui].instance != NULL && !results[ui].instance->IsAutoDelete()) { m_activeEffMap.SetAt(results[ui].node, results[ui].instance); } } } void SpellInstance::EmitEffect(SpellEffectNode* pkEffectNode) { if (!m_pOwner || !pkEffectNode) return; CEffectBase* pkEffect = 0; if (m_activeEffMap.GetAt(pkEffectNode, pkEffect)) { ReleaseEffect(pkEffectNode); } SpellEffectEmit::EmitParam ep; ep.m_iSpellid = m_SpellID; ep.m_OwnerID = m_pOwner->GetGUID(); ep.m_kTargets = m_targetList; ep.m_kTargetsDetail = m_targetListdetail; ep.m_vEffects.push_back(pkEffectNode); std::vector results; SpellEffectEmit::Get()->Emit(ep, results, false); for (unsigned int ui = 0; ui < results.size(); ui++) { if (results[ui].instance != NULL && !results[ui].instance->IsAutoDelete()) { /*results[ui].instance->SetAutoDelete(true);*/ m_activeEffMap.SetAt(results[ui].node, results[ui].instance); } } } void SpellInstance::EmitEffect(int iSpellID, int iTriggerID) { m_SpellTemplate = SYState()->SkillMgr->GetSpellTemplate(iSpellID); if (!m_SpellTemplate) return; const SpellVisualDesc* pkVisualKit = m_SpellTemplate->GetVisulalKit(); if (!pkVisualKit) return; const std::vector& effects = pkVisualKit->m_kEffects.vEffects; std::vector doeffects; for ( unsigned int ui = 0; ui < effects.size(); ui++) { SpellEffectNode* pkNode = effects[ui]; NIASSERT(pkNode); for (unsigned int i = 0; i < pkNode->vRefTriggers.size(); ++i) { if (iTriggerID == pkNode->vRefTriggers[i]) { doeffects.push_back(pkNode); } } EmitEffect(doeffects); } } bool SpellInstance::ReleaseEffect(int iSpellID, int iTriggerID) { m_SpellTemplate = SYState()->SkillMgr->GetSpellTemplate(iSpellID); if (!m_SpellTemplate) return false; const SpellVisualDesc* pkVisualKit = m_SpellTemplate->GetVisulalKit(); if (!pkVisualKit) return false; const std::vector& effects = pkVisualKit->m_kEffects.vEffects; for ( unsigned int ui = 0; ui < effects.size(); ui++) { SpellEffectNode* pkNode = effects[ui]; NIASSERT(pkNode); for (unsigned int i = 0; i < pkNode->vRefTriggers.size(); ++i) { if (iTriggerID == pkNode->vRefTriggers[i]) { ReleaseEffect(pkNode); } } } return true; } bool SpellInstance::ReleaseEffect(SpellEffectNode* pkEffectNode) { CEffectBase* pkEffect = 0; m_activeEffMap.GetAt(pkEffectNode, pkEffect); if (pkEffect) EffectMgr->ReleaseEffect(pkEffect, true); else return false; return m_activeEffMap.RemoveAt(pkEffectNode); } void SpellInstance::ClearActiveEffectMap() { ClearBreakEffects(); m_activeEffMap.RemoveAll(); } void SpellInstance::ClearBreakEffects() { if (m_pkTriggerMan) m_pkTriggerMan->ExecuteTriggerByAction(TA_Deactive); } bool SpellInstance::EffectSetup(const SpellID& spellID) { m_pkTriggerMan->Reset(); if (!InitSkillTemplate(spellID)) return false; const SpellVisualDesc* pkVisualKit = m_SpellTemplate->GetVisulalKit(); if (!pkVisualKit) return FALSE; const std::vector& triggers = pkVisualKit->m_kEffects.vTriggers; for (unsigned int ui = 0; ui < triggers.size(); ++ui) { SpellTriggerBase* pTrigger = triggers[ui]; NIASSERT(pTrigger); m_pkTriggerMan->AddTrigger(pTrigger); } const std::vector& effects = pkVisualKit->m_kEffects.vEffects; for ( unsigned int ui = 0; ui < effects.size(); ui++) { SpellEffectNode* pkNode = effects[ui]; NIASSERT(pkNode); for (unsigned int i = 0; i < pkNode->vRefTriggers.size(); ++i) { m_pkTriggerMan->AddEffectTriggerPair(pkNode->vRefTriggers[i], pkNode); } } return true; } float SpellInstance::GetCastElapse() { return m_fUpdateTime - m_fCastStartTime; } float SpellInstance::GetAttackElapse() { return m_fUpdateTime - m_fAttackStartTime; } float SpellInstance::GetSpellElapse() { float fSpellStartTime = NiMax(m_fCastStartTime, m_fAttackStartTime); return m_fUpdateTime - fSpellStartTime; } void SpellInstance::DamageTargets(const Target& Targets) { DamageResult NewDamage; NewDamage.Time = 0.0f; NewDamage.TotalTime = 0.0f; NewDamage.SpellId = m_SpellTemplate->GetSpellID(); for (int t = 0; t < Targets.GetNumTargets(); t++) { const Target::TargetEntry& rTargetEntry = Targets.GetTargetEntry(t); if (rTargetEntry.Object) { CCharacter* TargetObject = (CCharacter*)ObjectMgr->GetObject(rTargetEntry.ObjectID); if (TargetObject == NULL) { continue; } TargetObject->Damage(NewDamage); } } } NormalAttackInstance::NormalAttackInstance(CCharacter* pOwner) : SpellInstance(pOwner) { m_TargetObjectID = 0; m_bBow = false; voicegen = new CRandomMersenne(generate_seed()); } NormalAttackInstance::~NormalAttackInstance() { EndAttack(); if (voicegen) { delete voicegen; voicegen = 0; } } BOOL NormalAttackInstance::IsAvailibleAttackTarget(CCharacter* pkTarget) { if (!pkTarget || !m_pOwner || (pkTarget == m_pOwner)) return FALSE; return TRUE; } BOOL NormalAttackInstance::BeginAttack(const Target& Targets) { if (!m_pOwner) return FALSE; if (Targets.GetNumTargets() <= 0) return FALSE; //if(m_bBow) // m_SpellID = 5003; //else m_SpellID = NORMAL_ATTACK_SPELL_ID; if (!EffectSetup(m_SpellID)) return FALSE; NIASSERT(Targets.GetNumTargets() == 1); // single target attack const Target::TargetEntry& target = Targets.GetTargetEntry(0); if (m_pOwner->GetAsPlayer()) { CPlayer* pkPlayer = (CPlayer*)m_pOwner; if (pkPlayer && pkPlayer->IsLocalPlayer()) { CPlayerInputMgr * InputMsg = SYState()->LocalPlayerInput; InputMsg->SetTargetID(target.ObjectID); } else { m_pOwner->SetTargetObjectID(target.ObjectID); } } else { m_pOwner->SetTargetObjectID(target.ObjectID); } CCharacter* pkTarget = (CCharacter*)ObjectMgr->GetObject(target.ObjectID); if (!pkTarget) return FALSE; if (!IsAvailibleAttackTarget(pkTarget)) return FALSE; ChangeSpellState(LPAS_ATTACK); m_pOwner->SetDirectionTo(pkTarget->GetPosition()); return TRUE; } void NormalAttackInstance::EmitAttackSoundEffect() { ALAudioSource* pkSound = m_pOwner->GetSoundInst(); if (pkSound){ char soundfile[64]; if (m_pOwner->GetGameObjectType() == GOT_CREATURE) { ui32 entryid = m_pOwner->GetUInt32Value(OBJECT_FIELD_ENTRY); CCreatureNameDB::stCNDB cndb; if (!ItemMgr->GetCNDB(entryid, cndb)) return; int chioce, att_1, att_2; att_1 = att_2 = cndb.sound_attack1; if (cndb.sound_attack2 != 0) att_2 = cndb.sound_attack2; int r = rand() % 2; if (r) chioce = att_1; else chioce = att_2; SoundDB::soundfile sf; if ( chioce && g_pkSoundFiles->GetSoundFile(chioce, sf)) { _snprintf(soundfile, 64, "sound/char/%s.wav", sf.filename.c_str()); m_pOwner->GetSceneNode()->AttachChild(pkSound); pkSound->SetMinMaxDistance(5.0f, 80.0f); pkSound->SetGain(0.6f); pkSound->SetLoopCount( 1 ); SYState()->IAudio->PlaySound(pkSound, soundfile); } } else if (m_pOwner->GetAsPlayer()) { std::string soundfiles[3][2] = {"ha_yaonan", "ha_yaonv", "ha_rennan", "ha_rennv", "ha_wunan", "ha_wunv"}; CPlayerLocal* lp = (CPlayerLocal*)m_pOwner; uint8 race = lp->GetRace(); uint8 gender = lp->GetGender(); std::string sf = soundfiles[race-1][1-gender]; _snprintf(soundfile, 64, "sound/ha/%s.wav", sf.c_str()); m_pOwner->GetSceneNode()->AttachChild(pkSound); pkSound->SetMinMaxDistance(10.0f, 50.0f); pkSound->SetGain(1.5f); SYState()->IAudio->PlaySound(pkSound, soundfile); } } } BOOL NormalAttackInstance::UpdateAttack(float fTime) { static float s_fAttackDelay = 1.0f; float fCurrentTime = SYState()->ClientApp->GetAccumTime(); if (!m_pOwner) return TRUE; const Target& Targets = m_pOwner->GetTargetList(); if (Targets.GetNumTargets() <= 0) return TRUE; const Target::TargetEntry& target = Targets.GetTargetEntry(0); CCharacter* pkTarget = (CCharacter*)ObjectMgr->GetObject(target.ObjectID); if (pkTarget) { if (!IsAvailibleAttackTarget(pkTarget)) return TRUE; } BOOL bIsAnimEnd = m_pOwner->IsCurSecAnimEndInTime(fCurrentTime); if (m_pOwner->IsShouldStopAttack() && bIsAnimEnd) return TRUE; if (m_pOwner->m_iAttackUpdate > 0) { if (m_pOwner->GetGameObjectType() == GOT_CREATURE) { EmitAttackSoundEffect(); } else { double d = voicegen->Random(); if (d <= 0.2) { EmitAttackSoundEffect(); } } OnEvent(TE_NormAttackUpdate, NULL); m_pOwner->SetAttackAnimation(false); /*if (pkTarget && m_pOwner->GetCurPostureState() != STATE_MOVE) { m_pOwner->SetDirectionTo(pkTarget->GetPosition()); }*/ m_pOwner->m_iAttackUpdate--; } return FALSE; } void NormalAttackInstance::EndAttack() { m_TargetObjectID = 0; m_fNextEndTime = NiActorManager::INVALID_TIME; ChangeSpellState(LPAS_NONE); if (m_pOwner) m_pOwner->ClearTargetList(); }