#include "StdAfx.h" #include "EffectManager.h" #include "ObjectManager.h" #include "UI/UISystem.h" #include "Projectile.h" #include "MRTShadersEffect.h" #include "ClientState.h" #include "ClientApp.h" #include "ResourceManager.h" #define EffervescentTextLife 3.0f //冒泡的时间 #define EffervescentCount 5 // #define EffervescentSpeed 4.0f #define ShowEffeciSize CEffectManager::CEffectManager(void) { m_Enable = TRUE; m_EnableComboAtcEffect = TRUE; m_Inited = FALSE; m_CharacterName = NULL; m_ShowCharName |= GOT_ITEM; m_EnableChatTextEffect = TRUE; m_testEffectTime = 0.0f; m_IsDrawHpBar = false; m_IsDrawHpBarColorful = false; } CEffectManager::~CEffectManager(void) { } BOOL CEffectManager::Initialize() { if (m_Inited) { return TRUE; } m_CharacterName = NiNew CCharacterName; if (!m_CharacterName->Initialise()) { return FALSE; } m_ChatEffect = NiNew CChatEffect; if (!m_ChatEffect->Initialise()) { return FALSE; } if( ClientState->IsBloomEnabled() ) CreatePostEffect(); if (!InitBubupNumberEffect()) { NILOG("Initialize bubup number effect failed.\n"); return FALSE; } m_vComboAttackEffect.clear(); m_Inited = TRUE; return TRUE; } void CEffectManager::Destroy() { if (m_CharacterName) { NiDelete m_CharacterName; m_CharacterName = NULL; } if(m_ChatEffect) { NiDelete m_ChatEffect; m_ChatEffect = NULL; } m_vComboAttackEffect.clear(); ReleaseAllEffects(); ReleaseAllSceneEffectTemplates(); ShutdownBubupNumberEffect(); CleanupPostEffect(); m_Inited = FALSE; m_Enable = FALSE; CNumberFont::Destory(); } BOOL CEffectManager::InitBubupNumberEffect() { USystem* pUSystem = SYState()->UI->GetUSystem(); NIASSERT(pUSystem); URender* pURender = pUSystem->GetPlugin(); m_spNBFont = pURender->CreateFont("Arial", 22, GB2312_CHARSET); if (m_spNBFont == NULL) { return FALSE; } m_spHudFont = pURender->CreateFont("Arial", 16, GB2312_CHARSET); if (m_spHudFont == NULL) { return FALSE; } return TRUE; } void CEffectManager::ShutdownBubupNumberEffect() { //m_BubNumberEntries.clear(); for( std::list::iterator it = m_EffervescentText.begin(); it != m_EffervescentText.end(); ++it ) delete *it; m_EffervescentText.clear(); for( std::list::iterator it = m_HUDText.begin(); it != m_HUDText.end(); ++it ) delete *it; m_HUDText.clear(); m_spHudFont = NULL; m_spNBFont = NULL; } void CEffectManager::Update(float fAccumTime, float fFrameTime) { if (!m_Enable || !m_Inited) { return; } UpdateEffects(fAccumTime, fFrameTime); SpellEffectEmit::Get()->Update(fAccumTime); #ifdef ShowEffeciSize #ifdef _DEBUG m_testEffectTime += fFrameTime; if (m_testEffectTime >= 10.f) { m_testEffectTime = 0.f; char buf[_MAX_PATH]; NiSprintf(buf, _MAX_PATH,"Current effects number: %d \n",m_EffectInstances.size()); OutputDebugString(buf); } #endif #endif // update projectile //ProjectileList::iterator it = m_Projectiles.begin(); //for (; it != m_Projectiles.end(); ) //{ // Projectile* pProjectile = *it; // if (pProjectile->IsDead()) // { // it = m_Projectiles.erase(it); // pProjectile->Destroy(); // NiDelete pProjectile; // }else // { // pProjectile->Update(fDeltaTime); // it++; // } //} UpdateHudTextEntry(fFrameTime); UpdateEffervescentText(fFrameTime); } void CEffectManager::UpdateHudTextEntry(float fDeltaTime) { std::list::iterator it = m_HUDText.begin(); while (it != m_HUDText.end()) { HUDText* textEntry = *it; if (textEntry->Life > 0.0f) { textEntry->Life -= fDeltaTime; } ++it; } } void CEffectManager::UpdateEffervescentText(float fDeltaTime) { std::list::iterator it = m_EffervescentText.begin(); while (it != m_EffervescentText.end()) { HUDText* textEntry = *it; if (textEntry->Age < textEntry->Life) { textEntry->Age += fDeltaTime; } ++it; } } void CEffectManager::RenderHudText() { if (m_HUDText.empty() || m_spHudFont == NULL) { return; } USystem* pUSystem = SYState()->UI->GetUSystem(); NIASSERT(pUSystem); URender* pURender = pUSystem->GetPlugin(); if (!pURender) return; std::list::iterator it = m_HUDText.begin(); while (it != m_HUDText.end()) { HUDText& Entry = *( *it ); UPoint Pos = Entry.Pos; UColor pColor = Entry.Color; /*if (Entry.NeedEffervescent) { Pos.y -= int(EffervescentLen * (1.f - (Entry.Life / EffervescentTextLife))); pColor.a -= BYTE(255.f * (1 - (Entry.Life / EffervescentTextLife))); if (pColor.a < 0 || Entry.Life < 0) { pColor.a = 0; } } */ pURender->DrawTextN(m_spHudFont, Pos, (const WCHAR*)Entry.wszText, Entry.StrLen, NULL, pColor); if (Entry.Life <= 0.0f) { delete &Entry; it = m_HUDText.erase(it); continue; } ++it; } } void CEffectManager::RenderEffervescentText() { if (m_EffervescentText.empty() || m_spHudFont == NULL) { return; } USystem* pUSystem = SYState()->UI->GetUSystem(); NIASSERT(pUSystem); URender* pURender = pUSystem->GetPlugin(); if (!pURender) return; std::list::iterator it = m_EffervescentText.begin(); while (it != m_EffervescentText.end()) { HUDText& Entry = *( *it ); float fPos = max((Entry.Life - Entry.Age) * 5, 0.f); if(fPos <= 1.f) Entry.Color.a = BYTE(255.f * fPos); int textWidth = m_spHudFont->GetStrNWidth(Entry.wszText, Entry.StrLen); int textHeight = m_spHudFont->GetHeight(); UPoint pos(textWidth + 2, textHeight + 2); UDrawText(pURender, m_spHudFont, Entry.Pos, pos, LCOLOR_ARGB(Entry.Color.a, 0, 0, 0), (const WCHAR*)Entry.wszText, UT_CENTER); UDrawText(pURender, m_spHudFont, Entry.Pos, pos.Offset(-2, -2), Entry.Color, (const WCHAR*)Entry.wszText, UT_CENTER); /*pURender->DrawTextN(m_spHudFont, Entry.Pos, (const WCHAR*)Entry.wszText, Entry.StrLen, NULL, Entry.Color);*/ if (Entry.Age >= Entry.Life) { delete &Entry; it = m_EffervescentText.erase(it); continue; } ++it; } } void CEffectManager::RenderSceneEffects(const NiCamera* pkCamera) { RenderEffects(pkCamera); } void CEffectManager::RenderHudEffects(const NiCamera* pkCamera) { if (!m_Enable || !m_Inited) { return; } //Render2DElements(); if (m_CharacterName) { m_CharacterName->RenderEffect(pkCamera); } if (m_ChatEffect) { m_ChatEffect->RenderEffect(pkCamera); } if( m_spPostEffect ) m_spPostEffect->Render(); std::map::iterator it = m_vComboAttackEffect.begin(); while(it != m_vComboAttackEffect.end()) { it->second->RenderEffect(pkCamera); ++it; } } void CEffectManager::RegisterEffect(CEffectBase* Effect) { NIASSERT(Effect); if (!Effect->SelfManage()) { m_EffectInstances.insert(Effect); if( Effect->SelfRender() ) m_SelfRenderList.insert(Effect); } } void CEffectManager::ReleaseEffect(CEffectBase* Effect, bool bReleaseChild) { stdext::hash_set::iterator it = m_EffectInstances.find( Effect ); if( it != m_EffectInstances.end() ) { m_EffectInstances.erase( it ); if( Effect->SelfRender() ) m_SelfRenderList.erase( Effect ); NiDelete Effect; } } void CEffectManager::ReleaseAllEffects() { for( stdext::hash_set::iterator it = m_EffectInstances.begin(); it != m_EffectInstances.end(); ++it ) { CEffectBase* p = *it; NiDelete p; } m_EffectInstances.clear(); m_SelfRenderList.clear(); } void CEffectManager::UpdateEffects(float fTimeLine, float fDeltaTime) { CEffectBase* Effect; for( stdext::hash_set::iterator it = m_EffectInstances.begin(); it != m_EffectInstances.end(); ) { stdext::hash_set::iterator it2 = it++; Effect = *it2; Effect->Update(fTimeLine, fDeltaTime); } } void CEffectManager::RenderEffects(const NiCamera* pkCamera) { CEffectBase* Effect; for( stdext::hash_set::iterator it = m_SelfRenderList.begin(); it != m_SelfRenderList.end(); ) { stdext::hash_set::iterator it2 = it++; Effect = *it2; Effect->Render(pkCamera); } } void CEffectManager::Render2DElements() { USystem* pUSystem = SYState()->UI->GetUSystem(); NIASSERT(pUSystem); URender* pURender = pUSystem->GetPlugin(); pURender->BeginRender(); RenderHudText(); RenderEffervescentText(); pURender->EndRender(); } void CEffectManager::AddSceneText(const NiPoint3& pos, const char* pcText, unsigned int uiColor, float fLife /*= -FLT_MAX*/ ) { HUDText* NewText = new HUDText; NewText->Pos.x = (int)pos.x; NewText->Pos.y = (int)pos.y; NewText->Color = (DWORD)uiColor; NewText->Life = fLife; NewText->Age = fLife; int nRet = MultiByteToWideChar(CP_UTF8, 0, pcText, strlen(pcText), NewText->wszText, SY_HUDTEXT_MAXLEN -1); if( nRet < 128 && nRet > 0 ) { NewText->wszText[nRet] = 0; int textWidth = m_spHudFont->GetStrNWidth(NewText->wszText, nRet); int textHeight = m_spHudFont->GetHeight(); textWidth >>= 1; textHeight >>= 1; NewText->Pos.x -= textWidth; NewText->Pos.y -= textHeight; NewText->StrLen = nRet; m_HUDText.push_back(NewText); } } void CEffectManager::SetChatPopoShow(BOOL vis) { m_EnableChatTextEffect = vis; } void CEffectManager::AddChatText(const NiPoint3& pos, const char* pcText, unsigned int uiColor, float fLife) { CChatEffect::ChatText* NewText = new CChatEffect::ChatText; NewText->Pos.x = (int)pos.x; NewText->Pos.y = (int)pos.y; NewText->Depth = pos.z; NewText->color = 0xFFFFFFFF; int nRet = MultiByteToWideChar(CP_UTF8, 0, pcText, strlen(pcText), NewText->wszText, SY_CHATTEXT_MAXLEN - 1); if (nRet && m_EnableChatTextEffect) { NewText->wszText[nRet] = 0; NewText->StrLen = nRet; m_ChatEffect->AddEntry(NewText); } else delete NewText; } //冒泡的文字。 void CEffectManager::AddEffectText(const char* pText, int ColorIndex) { DWORD color[] = { 0xFFFF0000, 0xFFFFFF00}; HUDText* NewText = new HUDText; NewText->Pos.x = UControl::sm_System->GetCurFrame()->GetWidth() / 2; NewText->Pos.y = UControl::sm_System->GetCurFrame()->GetHeight() / 3; NewText->Color = color[ColorIndex]; NewText->Age = 0; NewText->Life = EffervescentTextLife; int nRet = MultiByteToWideChar(CP_UTF8, 0, pText, strlen(pText), NewText->wszText, SY_HUDTEXT_MAXLEN -1); if( nRet == 0 || nRet >= 128 ) { delete NewText; return; } NewText->wszText[nRet] = 0; int textWidth = m_spHudFont->GetStrNWidth(NewText->wszText, nRet); int textHeight = m_spHudFont->GetHeight(); textWidth >>= 1; textHeight >>= 1; NewText->Pos.x -= textWidth; NewText->Pos.y -= textHeight; NewText->StrLen = nRet; if (m_EffervescentText.size() && _wcsicmp(m_EffervescentText.back()->wszText, NewText->wszText) == 0) { m_EffervescentText.back()->Age = 0; delete NewText; return ; } m_EffervescentText.push_back(NewText); if (m_EffervescentText.size() > EffervescentCount) { delete m_EffervescentText.front(); m_EffervescentText.pop_front(); } std::list::iterator it = m_EffervescentText.begin(); int height = 300; while (it != m_EffervescentText.end()) { HUDText* textEntry = *it; textEntry->Pos.y = height; height += m_spHudFont->GetHeight() + 2; ++it; } } void CEffectManager::AddEffeText(const NiPoint3& pos, const char* pText, UColor txtcolor ) { AddEffectText(pText); return; HUDText* NewText = new HUDText; NewText->Pos.x = (int)pos.x; NewText->Pos.y = (int)pos.y; NewText->Color = txtcolor; NewText->Life = EffervescentTextLife; NewText->Age = 0; int nRet = MultiByteToWideChar(CP_UTF8, 0, pText, strlen(pText), NewText->wszText, SY_HUDTEXT_MAXLEN -1); if (nRet) { NewText->wszText[nRet] = 0; int textWidth = m_spHudFont->GetStrNWidth(NewText->wszText, nRet); int textHeight = m_spHudFont->GetHeight(); textWidth >>= 1; textHeight >>= 1; NewText->Pos.x -= textWidth; NewText->Pos.y -= textHeight; NewText->StrLen = nRet; int NewLen = (m_EffervescentText.size()) * (m_spHudFont->GetHeight() + 2); NewText->Pos.y += NewLen; //判断是否需要添加进去。 size_t EtxtSize = m_EffervescentText.size(); if (EtxtSize) { if (_wcsicmp(m_EffervescentText.back()->wszText, NewText->wszText) == 0) { delete NewText; return ; } } m_EffervescentText.push_back(NewText); if (m_EffervescentText.size() > EffervescentCount) { delete m_EffervescentText.front(); m_EffervescentText.pop_front(); std::list::iterator it = m_EffervescentText.begin(); while (it != m_EffervescentText.end()) { HUDText* textEntry = *it; textEntry->Age = 0; ++it; } } } else delete NewText; } void CEffectManager::SetCharNameShow(ui32 type, BOOL visible) { if (visible) { m_ShowCharName |= type; } else { m_ShowCharName &= ~type; } } void CEffectManager::SetHostHpBarShow(bool visible) { m_IsDrawHpBar = visible; } void CEffectManager::SetHostHpBarColorful(bool visible) { m_IsDrawHpBarColorful = visible; } void sNameRecode::SetEmblem(uint32 style, uint32 color) { if (emblemStyle != style && emblemColor != color) { emblemStyle = style; emblemColor = color; char buf[256]; if (emblemStyle) { itoa(emblemStyle, buf, 10); std::string str = buf; if (str.length() == 1) str.insert(0,"0"); str += ('a' + emblemColor); sprintf(buf, "Data\\UI\\SocialitySystem\\GuildEmblem\\%s.png", str.c_str()); stName.emblemtexture = UControl::sm_UiRender->LoadTexture(buf); } } } void CEffectManager::AddCharName(sNameRecode* pNameRecode, const NiPoint3& pos, const char* pName, const char* ptitleName, const char* pGuildName, const char* prefixalName, unsigned int uiColor, float Distent, bool Show, bool bTarget) { CharName* NewName = &pNameRecode->stName; if (!pName || !NewName) { return; } NewName->Position = pos; NewName->Color = (DWORD)uiColor; NewName->Scale = Distent; NewName->ShowHpBarColorful = m_IsDrawHpBarColorful; NewName->ShowHp = m_IsDrawHpBar && Show; NewName->bShowName = pNameRecode->type & m_ShowCharName?true:false; NewName->bTarget = bTarget; int nRet = MultiByteToWideChar(CP_UTF8, 0, pName, strlen(pName), NewName->wszName, SY_HUDTEXT_MAXLEN -1); if( nRet < 128 && nRet > 0 ) { NewName->wszName[nRet] = 0; NewName->StrLen = nRet; if (ptitleName) { int usize = MultiByteToWideChar(CP_UTF8, 0, ptitleName, strlen(ptitleName), NewName->wsztitleName, SY_HUDTEXT_MAXLEN -1); NewName->wsztitleName[usize] = 0; NewName->titleStrLen = usize; } else { NewName->wsztitleName[0] = 0; NewName->titleStrLen = 0; } if (pGuildName) { int usize = MultiByteToWideChar(CP_UTF8, 0, pGuildName, strlen(pGuildName), NewName->wszguildName, SY_HUDTEXT_MAXLEN -1); NewName->wszguildName[usize] = 0; NewName->GuildNameLen = usize; } else { NewName->wszguildName[0] = 0; NewName->GuildNameLen = 0; } if (prefixalName) { int usize = MultiByteToWideChar(CP_UTF8, 0, prefixalName, strlen(prefixalName), NewName->wszprefixal, SY_HUDTEXT_MAXLEN -1); NewName->wszprefixal[usize] = 0; NewName->prefixalLen = usize; }else { NewName->wszprefixal[0] = 0; NewName->prefixalLen = 0; } if (NewName->bShowName || NewName->ShowHp || NewName->bShowMask) { m_CharacterName->AddEntry(&pNameRecode->stName); } } } void CEffectManager::BubbleUpEffectNumber( CComboAttackEffect* pEffect, int Type,int SubType, int Number, const NiColorA& InitCol, float fLife /*= 2.0f*/, const WCHAR* extraOutput /*= NULL*/ , ui32 victimstate) { if (m_spNBFont == NULL) { return; } AttackEffectEntry* NewEntry = new AttackEffectEntry; NewEntry->Age = 0.0f; NewEntry->Life = fLife; NewEntry->Color.r = BYTE(InitCol.r * 255); NewEntry->Color.g = BYTE(InitCol.g * 255); NewEntry->Color.b = BYTE(InitCol.b * 255); NewEntry->Color.a = BYTE(InitCol.a * 255); NewEntry->Number = Number; NewEntry->Scale = 0.60f; NewEntry->Type = Type; NewEntry->SubType = SubType; NewEntry->victimstate = victimstate; NewEntry->bNeedUpdatePosition = true; if (Type == BUBBLE_HEADTEXT) { _snwprintf(NewEntry->szNbStr, 64, L"%s", extraOutput); } else { if (extraOutput != NULL) _snwprintf(NewEntry->szNbStr, 64, L"%d%s", Number, extraOutput); else _snwprintf(NewEntry->szNbStr, 64, L"%d", Number); } if (pEffect) { pEffect->AddEntry(NewEntry); } } void CEffectManager::AddCComboAttackEffect(ui64 guid,CComboAttackEffect* pComboAttackEffect) { m_vComboAttackEffect.insert(std::map::value_type(guid, pComboAttackEffect)); } void CEffectManager::DeleteCComboAttackEffect(ui64 guid) { std::map::iterator it = m_vComboAttackEffect.find(guid); if(it != m_vComboAttackEffect.end()) m_vComboAttackEffect.erase(it); } CEffectBase* CEffectManager::CreateSceneEffect(const char* EffectName, bool bAvtive /*=true*/, bool bVisible /*= false*/, bool infinity /*= true*/, unsigned int loopcount /*= -1*/, bool bAttachToScene /*= false*/, bool bAutoDestroy /*= true*/) { float fCurTime = SYState()->ClientApp->GetAccumTime(); NiAVObjectPtr EffectObject = NewSceneEffectObject(EffectName); if (EffectObject) { CSceneEffect* Effect = NiNew CSceneEffect(EffectObject); if (!infinity) { NIASSERT(loopcount >= 1); Effect->SetMaxLifeByEffectLife(loopcount); } // RegisterEffect(Effect); if (bAvtive) { Effect->Activate(fCurTime, bVisible); } if (bAttachToScene) { Effect->AttachToScene(); } Effect->SetAutoRelease( bAutoDestroy ); return Effect; } return NULL; } NiAVObjectPtr CEffectManager::NewSceneEffectObject(const char* EffectName) { NiFixedString Name = EffectName; NiAVObjectPtr EffectTemplate; EffectTemplate = LoadSceneEffectTemplate(Name); if (EffectTemplate != NULL) { NiAVObject* Instance = EffectTemplate; Instance->Update(0.0f, false); Instance->UpdateEffects(); Instance->UpdateProperties(); return Instance; } return NULL; } NiAVObjectPtr CEffectManager::LoadSceneEffectTemplate(const NiFixedString& Name) { CHAR Buffer[MAX_PATH]; NiSprintf(Buffer,MAX_PATH, "Objects\\Effect\\%s", Name); NiAVObjectPtr EffectTemplate = g_ResMgr->LoadNif(Buffer); return EffectTemplate; } NiAVObject* CEffectManager::FindSceneEffectTemplate(const NiFixedString& Name) { FixedStringHashMap::const_iterator it = m_SceneEffectMap.find(Name); if (it != m_SceneEffectMap.end()) { return it->second; } return NULL; } void CEffectManager::ReleaseAllSceneEffectTemplates() { FixedStringHashMap::iterator it = m_SceneEffectMap.begin(); for ( ;it != m_SceneEffectMap.end(); ++it) { NiAVObject* Template = it->second; NiDelete Template; } m_SceneEffectMap.clear(); } // //namespace //{ // PROJECTILE_DESC ProjectileDescs[PROJDESC_MAX] = // { // {"charge.nif", 1.0f, 1000, FALSE, FALSE}, // fireball // {"shot_dmg_01.nif", 0.2f, 500, FALSE, FALSE}, // //{"Arrow.nif", 1, } // }; //}; // //ProjectileEffect* CEffectManager::CreateProjectile(ProjDescID DescID, SYObjID OwnerID) //{ // NIASSERT(DescID >= 0 && DescID < PROJDESC_MAX); // PROJECTILE_DESC* Desc = &ProjectileDescs[DescID]; // ProjectileEffect* NewProj = NiNew ProjectileEffect(OwnerID); // if (NewProj == NULL) // { // return NULL; // } // NewProj->SetProjectileDesc(Desc); // if (!NewProj->Create()) // { // NiDelete NewProj; // return NULL; // } // return NewProj; //} //void CEffectManager::AddProjectile(Projectile* pProjectile) //{ // m_Projectiles.push_back(pProjectile); //} // //void CEffectManager::ReleaseAllProjectiles() //{ // ProjectileList::iterator it = m_Projectiles.begin(); // for (; it != m_Projectiles.end(); it++) // { // Projectile* pProjectile = *it; // // pProjectile->Destroy(); // NiDelete pProjectile; // } // m_Projectiles.clear(); //} void CEffectManager::DeadEffect(bool bIsDead) { if ( m_spPostEffect ) m_spPostEffect->DeadEffect(bIsDead); } void CEffectManager::CreatePostEffect() { if( !m_spPostEffect ) m_spPostEffect = NiNew PostProcessEffect; } void CEffectManager::CleanupPostEffect() { m_spPostEffect = 0; } NiRenderTargetGroup* CEffectManager::GetPostEffectRenderTarget() { if( m_spPostEffect ) return m_spPostEffect->GetRenderTarget(); else return NiRenderer::GetRenderer()->GetDefaultRenderTargetGroup(); }