#include #include "SpellEffect.h" #include "Character.h" //#include "Player.h" #include "ClientApp.h" //#include "SceneManager.h" #include "ObjectManager.h" #include "Effect/EffectManager.h" #include "Effect\DecalManager.h" #include "Trail.h" #include "PosConstraintEffect.h" #include "Effect/DecalEffect.h" #include "Effect/ChainEffect.h" #include "Skill/SkillManager.h" #include "ResourceManager.h" #include "SceneManager.h" #include "ItemManager.h" #include "AudioInterface.h" #include "Console.h" SpellEffectEmit* SpellEffectEmit::m_pkSInst; SpellEffectEmit::SpellEffectEmit() : m_pkTempSource(0) { } SpellEffectEmit::~SpellEffectEmit() { if (m_pkTempSource) { m_pkTempSource = 0; } } CEffectBase* SpellEffectEmit::CreateEffect(SpellEffectNode* pEffectNode ) { NIASSERT(pEffectNode); if (!pEffectNode) return 0; int fxtype = pEffectNode->GetType(); float effscale = pEffectNode->scale; bool bNoAutoScale = pEffectNode->bNoScale; CEffectBase* pEffect = NULL; switch(fxtype) { case ET_MODEL: pEffect = CreateNifEffect((SpellEffectNifNode*)pEffectNode, effscale ); break; case ET_DECAL: pEffect = CreateDecalEffect((SpellDecalEffectNode*)pEffectNode); break; case ET_TRAIL: pEffect = CreateTrailEffect((SpellTrailEffectNode*)pEffectNode); break; case ET_PROJECTILE: pEffect = CreateProjectileEffect((SpellProjectileEffectNode*)pEffectNode); break; case ET_POSCONSTRAINT: pEffect = CreatePosConstraintEffect((SpellPosConstraintEffectNode*)pEffectNode); break; case ET_CHAIN: pEffect = CreateChainEffect((SpellChainEffectNode*)pEffectNode); break; default: break; } // init common property if (pEffect) { if (pEffectNode->MaxLife != FLT_MAX) { pEffect->SetMaxLife(pEffectNode->MaxLife); } pEffect->SetEffScale( effscale ); pEffect->SetIsNoAutoScale( bNoAutoScale ); } return pEffect; } void SpellEffectEmit::AddSound(SpellEffectNode* pkEffectNode, SpellTemplate* pkSpellTemplate, NiNode* pkNode) { if (!pkSpellTemplate || !pkEffectNode || !pkNode) return; if (pkEffectNode->vSounds.size() > 0) { for (unsigned int ui = 0; ui < pkEffectNode->vSounds.size(); ui++) { SpellSoundDesc* pkSD = pkSpellTemplate->FindSoundDesc(pkEffectNode->vSounds[ui]); if (pkSD) { EmitSound(pkNode, *pkSD); } } } } void SpellEffectEmit::EmitSound(NiNode* pkNode, const SpellSoundDesc& desc) { if (!pkNode) return; ALAudioSource* pkSound = (ALAudioSource*)AudioSystem::GetAudioSystem()->CreateSource(AudioSource::TYPE_3D); if (!pkSound) return; pkNode->AttachChild(pkSound); pkNode->Update(0.0f, false); pkSound->SetMinMaxDistance(desc.MinDist, desc.MaxDist ); pkSound->SetGain(desc.Gain ); pkSound->SetLoopCount(desc.uiLoopLimit); pkSound->SetSelectiveUpdate(true); pkSound->SetSelectiveUpdateTransforms(true); pkSound->SetSelectiveUpdatePropertyControllers(false); pkSound->SetSelectiveUpdateRigid(true); pkSound->Update(0.0f); SYState()->IAudio->PlaySound(pkSound, desc.szSource); } void SpellEffectEmit::Emit(SpellEffectEmit::EmitParam& param, std::vector& result, bool all/*=true*/, float delay/*=0.0f*/) { float ct = SYState()->ClientApp->GetAccumTime(); if (delay > 0.f) { DelayEmiter de; de.m_fTime = ct + delay; de.m_bAll = all; de.m_kParam = param; m_vDelayEmiters.push_back(de); } SpellTemplate* pkSpellTemplate = SYState()->SkillMgr->GetSpellTemplate(param.m_iSpellid); if (!pkSpellTemplate) return; const SpellVisualDesc* pkVisualKit = pkSpellTemplate->GetVisulalKit(); if (!pkVisualKit) return; CGameObject* pkOwner = (CGameObject*)ObjectMgr->GetObjectA(param.m_OwnerID); if (!pkOwner) return; const Target& target = param.m_kTargets; const Target& targetdetail = param.m_kTargetsDetail; unsigned int ui = 0; if (all) { const std::vector& effects = pkVisualKit->m_kEffects.vEffects; for ( ui = 0; ui < effects.size(); ui++ ) { SpellEffectEmit::EmitResult ret; SpellEffectNode* pEffect = effects[ui]; if ( ( pEffect->GetType() == ET_PROJECTILE && !target.GetTargetEntry(0).Object )|| pEffect->GetType() == ET_CHAIN ) { ret.instance = EmitEffect(pkOwner, &targetdetail, effects[ui], pkSpellTemplate, true); } else ret.instance = EmitEffect(pkOwner, &target, effects[ui], pkSpellTemplate, true); ret.node = effects[ui]; result.push_back(ret); } } else { const std::vector& effects = param.m_vEffects; for ( ui = 0; ui < effects.size(); ui++ ) { SpellEffectEmit::EmitResult ret; SpellEffectNode* pEffect = effects[ui]; if (( pEffect->GetType() == ET_PROJECTILE && !target.GetTargetEntry(0).Object)&&(!pEffect->bTargetProjetile)|| pEffect->GetType() == ET_CHAIN ) { ret.instance = EmitEffect(pkOwner, &targetdetail, effects[ui], pkSpellTemplate, true); } else ret.instance = EmitEffect(pkOwner, &target, effects[ui], pkSpellTemplate, true); ret.node = effects[ui]; result.push_back(ret); } } } CEffectBase* SpellEffectEmit::EmitEffect(CGameObject* pkOwner, const Target* const pkTargetList, SpellEffectNode* pkEffectNode, SpellTemplate* pkSpellTemplate, bool bActivate) { float fCurrentTime = SYState()->ClientApp->GetAccumTime(); NIASSERT(pkOwner); if (!pkOwner) return 0; CEffectBase* pEffect = CreateEffect(pkEffectNode); if (!pEffect) return 0; const stSpellInfo& spellInfo = pkSpellTemplate->GetSpellInfo(); if (pkEffectNode->GetType() == ET_PROJECTILE) { if (!pkTargetList || pkTargetList->GetNumTargets() <= 0) return 0; NiNode* pAttackerNode = pkOwner->GetSceneNode(); NiNode* RightHandleNode = (NiNode*)pAttackerNode->GetObjectByName("Effect_RightHand"); //NIASSERT(RightHandleNode); if (!RightHandleNode) { RightHandleNode = (NiNode*)pAttackerNode->GetObjectByName("Effect_Chest"); if ( !RightHandleNode ) { return 0; } //return 0; } SpellProjectileEffectNode* pkProjectileInfoNode = (SpellProjectileEffectNode*)pkEffectNode; NIASSERT(pkEffectNode); PROJECTILE_DESC ArrowDesc; ArrowDesc.Billboard = 0; ArrowDesc.MakeTrail = 1; ArrowDesc.Scale = 1.f; ArrowDesc.ExpScale = pkProjectileInfoNode->ExpScale; ArrowDesc.bSelfMissile = pkProjectileInfoNode->bSelfMissile; ArrowDesc.bNeedTarget = pkProjectileInfoNode->bNeedTarget; ArrowDesc.fSelfMissileTime = pkProjectileInfoNode->fSelfMissileTime; ArrowDesc.iProjectileType = pkProjectileInfoNode->iProjectileType; ArrowDesc.fFlySpeed = spellInfo.flyspeed; if ( ArrowDesc.iProjectileType == 2 && pkOwner->GetAsPlayer() ) { CPlayer* pkPlayer = (CPlayer*)pkOwner; ui32 itementry = pkPlayer->GetUInt32Value(PLAYER_VISIBLE_ITEM_6_0); ItemPrototype_Client* ItemInfo = ItemMgr->GetItemPropertyFromDataBase(itementry); std::string strModelFileName; ItemMgr->GetDisplayInfo(ItemInfo->DisplayInfoID[0][0], strModelFileName, 0, 0, true); NiStrcpy(ArrowDesc.ProjectileModel, MAX_PATH, strModelFileName.c_str()); NiStrcpy(ArrowDesc.ExplosionModel, MAX_PATH, ((SpellProjectileEffectNode*)pkEffectNode)->ExpMedia); NiStrcpy(ArrowDesc.ExpSound, MAX_PATH, ((SpellProjectileEffectNode*)pkEffectNode)->ExpSound); ArrowDesc.bSelfMissile = false; } else { NiStrcpy(ArrowDesc.ProjectileModel, MAX_PATH, pkEffectNode->Media); NiStrcpy(ArrowDesc.ExplosionModel, MAX_PATH, ((SpellProjectileEffectNode*)pkEffectNode)->ExpMedia); NiStrcpy(ArrowDesc.ExpSound, MAX_PATH, ((SpellProjectileEffectNode*)pkEffectNode)->ExpSound); } ProjectileEffect* pProjEffect = (ProjectileEffect*)pEffect; NIASSERT(pProjEffect); for (unsigned int ui = 0; ui < (unsigned int)pkTargetList->GetNumTargets(); ++ui) { NiNode* pSoundNode = NULL; for( int num = 0; num < pkProjectileInfoNode->projectileNum; ++num) { int center = (int)(!pkProjectileInfoNode->bCenter); if ( (num != 0) || (ui != 0) ) { pProjEffect = (ProjectileEffect*)CreateEffect(pkEffectNode); } const Target::TargetEntry& rTargetEntry = pkTargetList->GetTargetEntry(ui); NiPoint3 ptRightHand = RightHandleNode->GetWorldTranslate(); NiPoint3 ptRand = NiPoint3::ZERO; int idirect = rand()%2; if ( !idirect ) { idirect = -1; } ptRand.x = rand()%30*(num+center)*idirect; idirect = rand()%2; if ( !idirect ) { idirect = -1; } ptRand.y = rand()%30*(num+center)*idirect; idirect = rand()%2; if ( !idirect ) { idirect = -1; } ptRand.z = rand()%30*(num+center)*idirect; ptRand.Unitize(); ptRand = ptRand*2; ptRightHand = ptRightHand + ptRand; if (pProjEffect->Create(&ArrowDesc, ptRightHand )) { if (rTargetEntry.Object) { if (bActivate) { if (pProjEffect->TrackObject(rTargetEntry.ObjectID)) { pProjEffect->Activate(fCurrentTime, true); std::vector effects; SYState()->SkillMgr->GetSpellEffects(spellInfo.uiId, TE_Damage, TA_Active, effects); SpellEffectEmit::EmitParam ep; ep.m_iSpellid = spellInfo.uiId; ep.m_OwnerID = rTargetEntry.ObjectID; ep.m_kTargets = *pkTargetList; ep.m_vEffects = effects; pProjEffect->AddEP(ep); //AddSound(pkEffectNode, pkSpellTemplate, pProjEffect->GetNode()); if ( num == 0 ) { pSoundNode = pProjEffect->GetNode(); AddSound(pkEffectNode, pkSpellTemplate, pSoundNode ); } } } } else //No Object then { if (pProjEffect->TrackTarget(NiPoint3(rTargetEntry.Pos[0], rTargetEntry.Pos[1], rTargetEntry.Pos[2]))) { pProjEffect->Activate(fCurrentTime, true); std::vector effects; SYState()->SkillMgr->GetSpellEffects(spellInfo.uiId, TE_Damage, TA_Active, effects); SpellEffectEmit::EmitParam ep; ep.m_iSpellid = spellInfo.uiId; ep.m_OwnerID = rTargetEntry.ObjectID; ep.m_kTargets = *pkTargetList; ep.m_vEffects = effects; pProjEffect->AddEP(ep); } if ( num == 0 ) { pSoundNode = pProjEffect->GetNode(); AddSound(pkEffectNode, pkSpellTemplate, pSoundNode ); } } } } } return 0; } else if ( pkEffectNode->GetType() == ET_DECAL) { SpellDecalEffectNode* pkEffNode = (SpellDecalEffectNode*)pkEffectNode; DecalEffect* pkDecalEffect = (DecalEffect*)pEffect; pkDecalEffect->SetTexture(pkEffNode->Media); pkDecalEffect->SetRadius(pkEffNode->fRadius); pkDecalEffect->SetDepth(4.5f); pkDecalEffect->SetFadein(pkEffNode->fFadein); pkDecalEffect->SetFadeout(pkEffNode->fFadeout); pkDecalEffect->SetColor(NiColorA(1.0f, 1.0f, 1.0f, 1.0f)); pkDecalEffect->SetSrcAlphaOP(NiAlphaProperty::ALPHA_SRCALPHA); pkDecalEffect->SetDestAlphaOP(NiAlphaProperty::ALPHA_INVSRCALPHA); const Target::TargetEntry& entry = pkTargetList->GetTargetEntry(0); NIASSERT(!entry.Object); pkDecalEffect->SetPosition(NiPoint3(entry.Pos[0], entry.Pos[1], entry.Pos[2])); pkDecalEffect->SetVisible(true); pkDecalEffect->Activate(SceneMgr->GetDecalMgr(), fCurrentTime, true); AddSound(pkEffectNode, pkSpellTemplate, pkDecalEffect->GetEffectNode()); return pkDecalEffect; } else if (pkEffectNode->GetType() == ET_TRAIL) { NiNode* pkAttackerNode = pkOwner->GetSceneNode(); if (pkAttackerNode) { if (pkOwner->GetGameObjectType() == GOT_PLAYER && !static_cast(pkOwner)->isWeaponAttached()) { static_cast(pkOwner)->AttachWeapon(true); } SpellTrailEffectNode* pkTrailEffectNode = (SpellTrailEffectNode*)pkEffectNode; { NiAVObject* pkRightWeapon = pkAttackerNode->GetObjectByName("RightWeapon"); NiAVObject* pkLeftWeapon = pkAttackerNode->GetObjectByName("LeftWeapon"); if (pkRightWeapon) { TrailEffect* pkRHTrailEffect = (TrailEffect*)pEffect; NiAVObject* pkTop = pkRightWeapon->GetObjectByName("Arms01"); if (pkTop && pkRHTrailEffect) { float fTrailWidth = 0.7f; NiFloatExtraData* pkED = NiStaticCast(NiFloatExtraData, pkTop->GetExtraData("trailwidth")); if (pkED) { fTrailWidth = pkED->GetValue(); } pkRHTrailEffect->BindObject(pkTop, fTrailWidth, pkTrailEffectNode->fLifeTime, pkTrailEffectNode->fTotalTime); pkRHTrailEffect->SetTexture(pkTrailEffectNode->szTexture); pkRHTrailEffect->Activate(fCurrentTime, true); AddSound(pkEffectNode, pkSpellTemplate, pkRHTrailEffect->GetSoundNode()); return pkRHTrailEffect; } } if (pkLeftWeapon) { TrailEffect* pkLHTrailEffect = (TrailEffect*)CreateEffect(pkEffectNode); NiAVObject* pkTop = pkLeftWeapon->GetObjectByName("Arms01"); if (pkTop && pkLHTrailEffect) { float fTrailWidth = 0.7f; NiFloatExtraData* pkED = NiStaticCast(NiFloatExtraData, pkTop->GetExtraData("trailwidth")); if (pkED) { fTrailWidth = pkED->GetValue(); } pkLHTrailEffect->BindObject(pkTop, fTrailWidth, pkTrailEffectNode->fLifeTime); pkLHTrailEffect->SetTexture(pkTrailEffectNode->szTexture); pkLHTrailEffect->Activate(fCurrentTime, true); AddSound(pkEffectNode, pkSpellTemplate, pkLHTrailEffect->GetSoundNode()); return pkLHTrailEffect; } } } } } else if (pkEffectNode->GetType() == ET_POSCONSTRAINT) { PosConstraintEffect* pkConstraint = (PosConstraintEffect*)pEffect; NIASSERT(pkConstraint); SpellPosConstraintEffectNode* pkPosstaintNode = (SpellPosConstraintEffectNode*)pkEffectNode; float freq = 1.0f; if (pkPosstaintNode->type == 0) { if (!pkTargetList || pkTargetList->GetNumTargets() <= 0) return 0; if (pkOwner->GetGameObjectType() == GOT_PLAYER && !static_cast(pkOwner)->isWeaponAttached()) { static_cast(pkOwner)->AttachWeapon(true); } //CCharacter* pkTarget = (CCharacter*)ObjectMgr->GetObject(pkTargetList->GetTargetEntry(0).ObjectID); //if (!pkTarget) // return 0; const Target::TargetEntry& entry = pkTargetList->GetTargetEntry(0); NiPoint3 kTargetPos = NiPoint3(entry.Pos[0], entry.Pos[1], entry.Pos[2]); NiPoint3 kSrcPos = pkOwner->GetPosition(); float fLength = (kTargetPos - kSrcPos).Unitize(); float tsec = 0.0f; if (spellInfo.flyspeed > 0) { tsec = fLength / spellInfo.flyspeed; } pkConstraint->SetTarget(pkOwner->GetGUID()); pkConstraint->Rush(kSrcPos, kTargetPos, 24.0f); NiAVObject* pkChest = pkOwner->GetSceneNode()->GetObjectByName("Effect_Chest"); if (pkChest) { TrailEffect* trail = NiNew TrailEffect; if (trail) { trail->BindObject(pkChest, 0.7f, spellInfo.flyspeed * 0.012f, tsec + 0.5f); trail->SetTexture("Texture/Effect/track_runno_001.dds"); trail->SetAxis(NiPoint3(-1.0f, 0, 0)); trail->Activate(fCurrentTime, true); AddSound(pkEffectNode, pkSpellTemplate, trail->GetSoundNode()); } } freq = spellInfo.flyspeed/8.0f; } else if ( pkPosstaintNode->type == 1) { // float minrange = 0.0f, maxrange = 0.0f; // SpellTemplate::GetRange(spellInfo.uiId, minrange, maxrange); // NIASSERT(minrange >0.0f && maxrange > 0.0f && minrange < maxrange ); // pkConstraint->Teleport(minrange, maxrange); //const Target::TargetEntry& entry = pkTargetList->GetTargetEntry(0); //pkOwner->SetPosition(NiPoint3(entry.Pos[0], entry.Pos[1], entry.Pos[2])); } else if (pkPosstaintNode->type == 2) { // pkConstraint->SetTarget(pkOwner->GetGUID()); // pkConstraint->Strom(10.f); freq = 1.5f; } if (pkOwner->IsAnimObject()) { CPlayer* pkPlayer = pkOwner->GetAsPlayer(); if (pkPlayer && pkPlayer->isMount() && !pkPlayer->IsMountByPlayer()) { if (pkPlayer->HasFlag(PLAYER_FIELD_SHAPE_MOUNT_FLAG, PLAYER_MOUNT_CANTFIGHT)) { if (pkPlayer->IsMountCreature()) { CCreature* pkMount = (CCreature*)pkPlayer->GetMountCreature(); pkMount->SetCurAnimation("Run", freq, TRUE); }else { if (pkPlayer->IsMountPlayer()) { pkPlayer->GetMountFoot()->SetCurAnimation("Run", freq, TRUE); } } }else { if (pkPlayer->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STORM)) { CAnimObject* pkAnimObj = (CAnimObject*)pkOwner; NiControllerSequence* pkSeq = pkAnimObj->SetCurAnimation(pkPosstaintNode->szAnimName, freq, TRUE, TRUE, 2); } } }else { CAnimObject* pkAnimObj = (CAnimObject*)pkOwner; NiControllerSequence* pkSeq = pkAnimObj->SetCurAnimation(pkPosstaintNode->szAnimName, freq, TRUE, TRUE, 2); } } } else if (pkEffectNode->GetType() == ET_MODEL) { CSceneEffect* pkSceneEffect = (CSceneEffect*)pEffect; NIASSERT(pkSceneEffect); bool bAttachToNode = true; bool bAttachToScene = false; NiFixedString strNodeName; switch(pkEffectNode->Slot) { case SES_HEAD01: strNodeName = "Effect_Head01"; break; case SES_HEAD02: strNodeName = "Effect_Head02"; break; case SES_CHEST: strNodeName = "Effect_Chest"; break; case SES_BELT: strNodeName = "Effect_Belt"; break; case SES_RIGHTHAND: strNodeName = "Effect_RightHand"; break; case SES_LEFTHAND: strNodeName = "Effect_LeftHand"; break; case SES_RIGHTFEET: strNodeName = "Effect_RightFeet"; break; case SES_LEFTFEET: strNodeName = "Effect_LeftFeet"; break; case SES_FOOT01: strNodeName = "Effect_Foot01"; break; case SES_FOOT02: strNodeName = "Effect_Foot02"; break; case SES_BACKSIDE: strNodeName = "BacksideWing_Node"; break; case SES_ORIGINAL: { bAttachToNode = false; } break; case SES_SCENE: { bAttachToNode = false; bAttachToScene = true; } break; default: bAttachToNode = false; break; } if (bAttachToScene && pkTargetList) { for (unsigned int ui = 0; ui < (unsigned int)pkTargetList->GetNumTargets(); ui++) { const Target::TargetEntry& entry = pkTargetList->GetTargetEntry(ui); if (!entry.Object) { pEffect->AttachToScene(NiPoint3(entry.Pos[0], entry.Pos[1], entry.Pos[2]), pkOwner->GetGUID(), true ); break; } } } else { if ( pkTargetList && (pkEffectNode->iOwner == EOT_Target )) { for ( unsigned int ui = 0; ui < (unsigned int)pkTargetList->GetNumTargets(); ui++ ) { const Target::TargetEntry& entry = pkTargetList->GetTargetEntry(ui); if (entry.Object) { CGameObject* pkObject = (CGameObject*)ObjectMgr->GetObject(entry.ObjectID); if(pkObject) { if (bAttachToNode) { pEffect->AttachToSceneObject(pkObject->GetGUID(), &strNodeName, pkEffectNode->bWorld, true, pkEffectNode->scale ); } else { pEffect->AttachToSceneObject(pkObject->GetGUID(), 0, pkEffectNode->bWorld, true, pkEffectNode->scale ); } } } } } if ( pkEffectNode->iOwner == EOT_Attacker ) { if (bAttachToNode) { pEffect->AttachToSceneObject(pkOwner->GetGUID(), &strNodeName, pkEffectNode->bWorld, true, pkEffectNode->scale ); } else { pEffect->AttachToSceneObject(pkOwner->GetGUID(), 0, pkEffectNode->bWorld, true, pkEffectNode->scale ); } } } AddSound(pkEffectNode, pkSpellTemplate, pkSceneEffect->GetEffectNode()); } else if ( pkEffectNode->GetType() == ET_CHAIN ) { CChainEffect* pChainEffect = (CChainEffect*)pEffect; SpellChainEffectNode* pChainNod = (SpellChainEffectNode*)pkEffectNode; if ( ( pChainNod->LifeTime - 0.f ) < 0.0001f ) { const Target::TargetEntry& entry = pkTargetList->GetTargetEntry(0); CGameObject* pkObject = (CGameObject*)ObjectMgr->GetObject(entry.ObjectID); if ( pkObject ) { pChainEffect->BindObject( pkOwner->GetSceneNode()->GetObjectByName( pChainNod->SrcNodeName.c_str() ), pkObject->GetSceneNode()->GetObjectByName( pChainNod->DesNodeName.c_str() ) ); pChainEffect->SetTexture( pkEffectNode->Media ); bActivate = true; } } else if ( pkTargetList ) { int TargetNum = pkTargetList->GetNumTargets(); if ( TargetNum > 0 ) { NiAVObject* current = NULL; NiAVObject* last = pkOwner->GetSceneNode()->GetObjectByName( pChainNod->SrcNodeName.c_str() ); for ( int Nums = 0; Nums < TargetNum; Nums++) { const Target::TargetEntry& entry = pkTargetList->GetTargetEntry(Nums); CGameObject* pkObject = (CGameObject*)ObjectMgr->GetObject(entry.ObjectID); if( pkObject ) { current = pkObject->GetSceneNode()->GetObjectByName( pChainNod->DesNodeName.c_str() ); if( current ) { pChainEffect = (CChainEffect*)CreateChainEffect((SpellChainEffectNode*)pkEffectNode); if ( pChainNod->dir == 0 ) { pChainEffect->BindObject( last, current ); } else pChainEffect->BindObject( current, last ); if ( pChainNod->chaintype == 0 ) { last = current; pChainEffect->SetDelayTime( Nums*0.3f ); } pChainEffect->SetTexture( pkEffectNode->Media ); pChainEffect->Activate( fCurrentTime, true ); } } } } } } else { NIASSERT("unknow spelleffect type!"); } if (bActivate) pEffect->Activate(fCurrentTime, true); return pEffect; } bool SpellEffectEmit::ReleaseEffect(CEffectBase* pkEffect) { if (pkEffect) { //pkEffect->Deactivate(true); EffectMgr->ReleaseEffect(pkEffect, true); return true; } return false; } void SpellEffectEmit::Update(float fTime) { float ct = SYState()->ClientApp->GetAccumTime(); std::list::iterator it = m_vDelayEmiters.begin(); for (it; it != m_vDelayEmiters.end(); ) { if (ct >= it->m_fTime) { std::vector result; Emit(it->m_kParam, result, it->m_bAll); it = m_vDelayEmiters.erase(it); } else ++it; } } CEffectBase* SpellEffectEmit::CreateNifEffect( SpellEffectNifNode* pEffectNode,float scale /* = 1.0f */ ) { NiAVObjectPtr pNif = g_ResMgr->LoadNif(pEffectNode->Media); if (!pNif) return 0; pNif->Update(0.0f, false); pNif->UpdateEffects(); pNif->UpdateProperties(); pNif->UpdateNodeBound(); CSceneEffect* pkSceneEffect = NiNew CSceneEffect(pNif); if (pkSceneEffect) { if (pEffectNode->bLoop) { pkSceneEffect->SetCycleType_Loop(); pkSceneEffect->SetMaxLifeByEffectLife(pEffectNode->uiLoopLimit); } else if ( pEffectNode->bClamp ) { pkSceneEffect->SetCycleType_Clamp(); } else if ( !pEffectNode->bInfinite ) { pkSceneEffect->SetMaxLifeByEffectLife(1); } } return pkSceneEffect; } CEffectBase* SpellEffectEmit::CreateDecalEffect(SpellDecalEffectNode* pEffectNode) { DecalEffect* pkDecalEffect = NiNew DecalEffect(); return pkDecalEffect; } CEffectBase* SpellEffectEmit::CreateTrailEffect(SpellTrailEffectNode* pEffectNode) { TrailEffect* pkEffect = NiNew TrailEffect; return pkEffect; } CEffectBase* SpellEffectEmit::CreateChainEffect(SpellChainEffectNode* pEffectNode) { CChainEffect* pkEffect = NiNew CChainEffect; if ( pEffectNode->LifeTime > 0.f ) { pkEffect->SetAutoDelete(true); pkEffect->SetActiveTime( pEffectNode->LifeTime ); } else pkEffect->SetAutoDelete(false); pkEffect->SetUpdateSpeed( pEffectNode->UpdateRate ); pkEffect->SetWidth( pEffectNode->scale ); return pkEffect; } CEffectBase* SpellEffectEmit::CreateProjectileEffect(SpellProjectileEffectNode* pEffectNode) { ProjectileEffect* pEffect = NiNew ProjectileEffect; return pEffect; } CEffectBase* SpellEffectEmit::CreatePosConstraintEffect(SpellPosConstraintEffectNode* pkEffectNode) { PosConstraintEffect* pkEffect = NiNew PosConstraintEffect(0); return pkEffect; } void EffectPostEvent::ActivationChanged(CEffectBase *effect, bool activated) { float fCurrentTime = SYState()->ClientApp->GetAccumTime(); if (g_pkConsole) g_pkConsole->Printf(80, "EffectPostEvent::ActivationChanged %d\n", activated?1:0); CEffectBase* pkEff = effect->GetNext(); if (pkEff) { if (g_pkConsole) g_pkConsole->Printf(80, "activate next effect \n"); pkEff->Activate(fCurrentTime, true); } }