#include "StdAfx.h" #include "NumberFont.h" #include "NiDX9TextureData.h" #include "Player.h" #include "ClientApp.h" #include "ObjectManager.h" #include "UI\UISystem.h" #include "UI\UFun.h" const float RowCount = 3.f;//图片中行数,用于计算UV CNumberFont::Vertex CNumberFont::sm_Vertics[CNumberFont::MAX_VERTEX]; CNumberFont* CNumberFont::sm_NumberFont = NULL; CNumberFont* CNumberFont::Instance() { if(sm_NumberFont == NULL) { sm_NumberFont = NiNew CNumberFont; if(!sm_NumberFont) return NULL; } return sm_NumberFont; } void CNumberFont::Destory() { if(sm_NumberFont) { delete sm_NumberFont; sm_NumberFont = NULL; } } CNumberFont::CNumberFont(void) { m_CharWidth = m_CharHeight = 1; m_bCreate = false; } CNumberFont::~CNumberFont(void) { m_bCreate = false; } BOOL CNumberFont::Create(const char* BitmapFile) { if(m_bCreate) return TRUE; NIASSERT(BitmapFile); USystem * pUISys = SYState()->UI->GetUSystem(); NIASSERT(pUISys); m_Texture = NiSourceTexture::Create(BitmapFile); if (m_Texture == NULL){ return FALSE; } NiDX9TextureData* DTexData = (NiDX9TextureData*)m_Texture->GetRendererData(); NIASSERT(DTexData); m_DTexture = DTexData->GetD3DTexture(); m_Width = (float)m_Texture->GetWidth(); m_CharHeight = (float)m_Texture->GetHeight()/RowCount; m_CharWidth = m_Width/12.0f; m_bCreate = true; return TRUE; } INT CNumberFont::TextOut(INT X, INT Y, INT TextLen, const WCHAR* Text, DWORD ColorValue, UINT State, float Scale ) { NIASSERT(Text && m_Texture); if (TextLen == -1) TextLen = wcslen(Text); X -= INT(m_CharWidth * TextLen * Scale * 0.5f); NiRect CharUV; INT CurVertIndex = 0; bool bHasNum = false; switch(State) { case ISTATE_NONE: { bHasNum = true; if (TextLen == 0) return X; } break; case ISTATE_MISS: { if (GetTextureUV(NUM_MISS, CharUV)){ CurVertIndex = SetupCharVertex(CurVertIndex, X, Y,(int)m_CharHeight, 97, ColorValue, CharUV, Scale); } } break; case ISTATE_BLOCK: { if (GetTextureUV(NUM_BLOCK, CharUV)){ CurVertIndex = SetupCharVertex(CurVertIndex, X, Y,(int)m_CharHeight, 52, ColorValue, CharUV, Scale); } } break; case ISTATE_CRICTICAL: { float CriScale = (m_CharHeight + 20) / m_CharHeight ; if (GetTextureUV(NUM_CRICTIAL, CharUV)){ CurVertIndex = SetupCharVertex(CurVertIndex, X, Y - 10, (int)m_CharHeight * CriScale, 54 * CriScale , LCOLOR_ARGB(ColorValue>>24, 255, 255, 255), CharUV, Scale); } X += (INT)((54 * CriScale) * Scale); bHasNum = true; if (TextLen == 0) return X; } break; case ISTATE_ABSORB: { if (GetTextureUV(NUM_ABSORB, CharUV)){ CurVertIndex = SetupCharVertex(CurVertIndex, X, Y,(int)m_CharHeight, 51, ColorValue, CharUV, Scale); } } break; case ISTATE_RESIST: { if (GetTextureUV(NUM_RESIST, CharUV)){ CurVertIndex = SetupCharVertex(CurVertIndex, X, Y,(int)m_CharHeight, 51, ColorValue, CharUV, Scale); } } break; case ISTATE_IMMUNE: { if (GetTextureUV(NUM_IMMUNE, CharUV)){ CurVertIndex = SetupCharVertex(CurVertIndex, X, Y,(int)m_CharHeight, 49, ColorValue, CharUV, Scale); } } break; case ISTATE_DODGE: { if (GetTextureUV(NUM_DODGE, CharUV)){ CurVertIndex = SetupCharVertex(CurVertIndex, X, Y,(int)m_CharHeight, 49, ColorValue, CharUV, Scale); } } break; } if(bHasNum) { INT Num; for (INT c = 0; c < TextLen; c++) { if (Text[c] == L'-'){ Num = NUM_REDUCE; }else if (Text[c] == L'+'){ Num = NUM_ADD; }else if(Text[c] == L'X') Num = NUM_X; else Num = Text[c] - L'0'; if (!GetTextureUV(Num, CharUV)) continue; CurVertIndex = SetupCharVertex(CurVertIndex, X, Y,(int)m_CharHeight,(int)m_CharWidth,ColorValue, CharUV, Scale); X += (INT)(m_CharWidth*Scale); } } if (CurVertIndex > 0) { PushDrawStatic(); g_pRenderInterface->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, (CurVertIndex -2), sm_Vertics, sizeof(Vertex)); PopDrawStatic(); } return X; } void CNumberFont::PushDrawStatic() { // Flush g_pRenderInterface->SetVertexShader(NULL); g_pRenderInterface->SetPixelShader(NULL); g_pRenderInterface->SetFVF(D3DFVF_XYZRHW |D3DFVF_DIFFUSE| D3DFVF_TEX1); IDirect3DBaseTexture9* Texture = (IDirect3DBaseTexture9*)m_DTexture; g_pRenderInterface->SetTexture(0,Texture); g_pRenderInterface->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); g_pRenderInterface->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); g_pRenderInterface->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); g_pRenderInterface->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); g_pRenderInterface->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); //// setup texture addressing settings g_pRenderInterface->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); g_pRenderInterface->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); // setup colour calculations g_pRenderInterface->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); g_pRenderInterface->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); g_pRenderInterface->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); // setup alpha calculations g_pRenderInterface->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); g_pRenderInterface->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); g_pRenderInterface->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); // setup filtering g_pRenderInterface->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); g_pRenderInterface->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); // disable texture stages we do not need. g_pRenderInterface->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); g_pRenderInterface->SetRenderState(D3DRS_LIGHTING, FALSE); //// setup scene alpha blending g_pRenderInterface->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); g_pRenderInterface->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_pRenderInterface->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); } void CNumberFont::PopDrawStatic() { } INT CNumberFont::SetupCharVertex(INT Index, INT X, INT Y,INT CharHeight,INT CharWidth, DWORD ColorValue, NiRect& CharUV, float Scale) { sm_Vertics[Index].X = (float)X; sm_Vertics[Index].Y = (float)Y; sm_Vertics[Index].Z = 0.4f; sm_Vertics[Index].W = 1.0f; sm_Vertics[Index].Color = ColorValue; sm_Vertics[Index].u = CharUV.m_left; sm_Vertics[Index].v = CharUV.m_top; Index++; sm_Vertics[Index].X = (float)X; sm_Vertics[Index].Y = (float)Y + CharHeight*Scale; sm_Vertics[Index].Z = 0.4f; sm_Vertics[Index].W = 1.0f; sm_Vertics[Index].Color = ColorValue; sm_Vertics[Index].u = CharUV.m_left; sm_Vertics[Index].v = CharUV.m_bottom; Index++; sm_Vertics[Index].X = (float)X + CharWidth*Scale; sm_Vertics[Index].Y = (float)Y; sm_Vertics[Index].Z = 0.4f; sm_Vertics[Index].W = 1.0f; sm_Vertics[Index].Color = ColorValue; sm_Vertics[Index].u = CharUV.m_right; sm_Vertics[Index].v = CharUV.m_top; Index++; sm_Vertics[Index].X = (float)X + CharWidth*Scale; sm_Vertics[Index].Y = (float)Y + CharHeight*Scale; sm_Vertics[Index].Z = 0.4f; sm_Vertics[Index].W = 1.0f; sm_Vertics[Index].Color = ColorValue; sm_Vertics[Index].u = CharUV.m_right; sm_Vertics[Index].v = CharUV.m_bottom; Index++; return Index; } BOOL CNumberFont::GetTextureUV(INT Number, NiRect& UvRect) { BOOL BFine = FALSE; float fInvWidth = 1.0f / m_Width; float fInvHeight = (m_CharHeight + 0.5f) / m_Texture->GetHeight(); switch (Number) { case NUM_0: { UvRect.m_left = (9.0f * m_CharWidth + 0.5f) * fInvWidth; UvRect.m_top = 0.0f; UvRect.m_bottom = fInvHeight; UvRect.m_right = UvRect.m_left + ( m_CharWidth + 0.5f) * fInvWidth; BFine = TRUE; } break; case NUM_1:case NUM_2:case NUM_3: case NUM_4:case NUM_5:case NUM_6: case NUM_7:case NUM_8:case NUM_9: { float num = float(Number - 1.0f); UvRect.m_left = (num * m_CharWidth + 1.0f) * fInvWidth; UvRect.m_top = 0.0f; UvRect.m_bottom = fInvHeight; UvRect.m_right = UvRect.m_left + (m_CharWidth - 0.5f) * fInvWidth; BFine = TRUE; } break; case NUM_REDUCE://减号 { UvRect.m_left = 11.0f*m_CharWidth/m_Width; UvRect.m_top = 0.0f; UvRect.m_bottom = fInvHeight; UvRect.m_right = (UvRect.m_left + m_CharWidth/m_Width); BFine = TRUE; } break; case NUM_ADD://加号 { UvRect.m_left = 10.0f*m_CharWidth/m_Width; UvRect.m_top = 0.0f; UvRect.m_bottom = fInvHeight; UvRect.m_right = (UvRect.m_left + m_CharWidth/m_Width); BFine = TRUE; } break; case NUM_MISS://miss { UvRect.m_left = 0.0f; UvRect.m_top = fInvHeight; UvRect.m_bottom = 2 * fInvHeight; UvRect.m_right = (UvRect.m_left + 97.f/m_Width); BFine = TRUE; } break; case NUM_BLOCK://格挡 { UvRect.m_left = 97.0f/m_Width; UvRect.m_top = fInvHeight; UvRect.m_bottom = 2 * fInvHeight; UvRect.m_right = (UvRect.m_left + 52.f/m_Width); BFine = TRUE; } break; case NUM_ABSORB://吸收 { UvRect.m_left = (148.0f + 0.5f)/m_Width; UvRect.m_top = fInvHeight; UvRect.m_bottom = 2 * fInvHeight; UvRect.m_right = (UvRect.m_left + 51.f/m_Width); BFine = TRUE; } break; case NUM_CRICTIAL://暴击 { UvRect.m_left = 200.5f/m_Width; UvRect.m_top = fInvHeight; UvRect.m_bottom = 2 * fInvHeight; UvRect.m_right = (UvRect.m_left + 54.f/m_Width); BFine = TRUE; } break; case NUM_RESIST://抵抗 { UvRect.m_left = 0.f; UvRect.m_top = 2 * fInvHeight; UvRect.m_bottom = 1.f; UvRect.m_right = (UvRect.m_left + 51.f/m_Width); BFine = TRUE; } break; case NUM_IMMUNE://免疫 { UvRect.m_left = 51.f/m_Width; UvRect.m_top = 2 * fInvHeight; UvRect.m_bottom = 1.f; UvRect.m_right = (UvRect.m_left + 49.f/m_Width); BFine = TRUE; } break; case NUM_DODGE://躲闪 { UvRect.m_left = (100.f + 0.5f)/m_Width; UvRect.m_top = 2 * fInvHeight; UvRect.m_bottom = 1.f; UvRect.m_right = (UvRect.m_left + 49.f/m_Width); BFine = TRUE; } break; case NUM_X: { UvRect.m_left = (254.f + 0.5f)/m_Width; UvRect.m_top = fInvHeight; UvRect.m_bottom = 2 * fInvHeight; UvRect.m_right = (UvRect.m_left + m_CharWidth/m_Width); BFine = TRUE; } break; } return BFine; } CComboAttackEffect::CComboAttackEffect() { m_pComboCharacter = NULL; m_bLocalPlayer = false; m_ViewCamera = NULL; } CComboAttackEffect::~CComboAttackEffect() { Destroy(); } BOOL CComboAttackEffect::Initialise() { if (CNumberFont::Instance() && !CNumberFont::Instance()->Create("Texture\\number.bmp")) { return FALSE; } CPlayer* pLocPlayer = ObjectMgr->GetLocalPlayer(); if(pLocPlayer) m_ViewCamera = &pLocPlayer->GetNiCamera(); return TRUE; } #include "EffectManager.h" void CComboAttackEffect::Destroy() { for( std::list::iterator it = m_AttackEffectEntrys.begin(); it != m_AttackEffectEntrys.end(); ++it ) delete *it; EffectMgr->DeleteCComboAttackEffect(m_pComboCharacter->GetGUID()); m_AttackEffectEntrys.clear(); m_pComboCharacter = NULL; m_bLocalPlayer = false; } UINT GetiStateSpell(ui32 hitstatus) { if (hitstatus == SPELL_LOG_NONE){ return ISTATE_NONE; } if (hitstatus == SPELL_LOG_MISS){ return ISTATE_MISS; } if (hitstatus == SPELL_LOG_RESIST){ return ISTATE_RESIST; } if (hitstatus == SPELL_LOG_DODGE){ return ISTATE_DODGE; } if (hitstatus == SPELL_LOG_PARRY){ return ISTATE_MISS; } if (hitstatus == SPELL_LOG_BLOCK){ return ISTATE_BLOCK; } if (hitstatus == SPELL_LOG_EVADE){ return ISTATE_MISS; } if (hitstatus == SPELL_LOG_IMMUNE){ return ISTATE_IMMUNE; } if (hitstatus == SPELL_LOG_IMMUNE2){ return ISTATE_IMMUNE; } if (hitstatus == SPELL_LOG_DEFLECT){ return ISTATE_MISS; } if (hitstatus == SPELL_LOG_ABSORB){ return ISTATE_ABSORB; } if (hitstatus == SPELL_LOG_REFLECT){ return ISTATE_MISS; } if (hitstatus == SPELL_LOG_REFLECT + 1){ return ISTATE_CRICTICAL; } return ISTATE_NONE; } UINT GetiState(ui32 hitstatus) { if ( hitstatus & HITSTATUS_MISS ) { return ISTATE_MISS; } else if ( hitstatus & HITSTATUS_HITANIMATION ) { return ISTATE_NONE; } else if ( hitstatus & HITSTATUS_DUALWIELD ) { return ISTATE_NONE; } else if ( hitstatus & HITSTATUS_GLANCING ) { return ISTATE_NONE; } else if ( hitstatus & HITSTATUS_ABSORBED ) { return ISTATE_ABSORB; } else if ( hitstatus & HITSTATUS_RESIST ) { return ISTATE_RESIST; } else if ( hitstatus & HITSTATUS_BLOCK ) { return ISTATE_BLOCK; } else if ( hitstatus & HITSTATUS_CRUSHINGBLOW ) { return ISTATE_NONE; } else if ( hitstatus & HITSTATUS_NOACTION ) { return ISTATE_NONE; } else if ( hitstatus & HITSTATUS_SWINGNOHITSOUND ) { return ISTATE_MISS; } else if ( hitstatus & HITSTATUS_CRICTICAL ) { return ISTATE_CRICTICAL; } return ISTATE_NONE; } #define EFFECTDELAY 0.35f const int BlubleUpy = 40; const int BlubleUpx = 150; void CComboAttackEffect::UpdateEffect(float fTimeLine, float fDeltaTime) { if(!m_AttackEffectEntrys.size()) return; EffectMgr->AddCComboAttackEffect(m_pComboCharacter->GetGUID(), this); //TODO每一个生命期的变化以及每一个位置以及大小的变化 int increase = 1; std::list::reverse_iterator it = m_AttackEffectEntrys.rbegin(); while(it != m_AttackEffectEntrys.rend()) { CalculatePosition(*it); //TODO生命期的变化 AttackEffectEntry& AEntry = *( *it ); AEntry.Age += fDeltaTime; if (AEntry.Age < 0.f){ ++it; continue; } if (AEntry.Age >= AEntry.Life){ ++it; continue; } //TODO ALPHA float progressPos = (AEntry.Life - AEntry.Age) * 2.5f; if(progressPos <= 1.f) AEntry.Color.a = (BYTE)( progressPos * 255); //TODO位置的变化 if(AEntry.Type == BUBBLE_COMBAT || AEntry.Type == BUBBLE_HEADTEXT){ ++it; continue; } if(m_bLocalPlayer) { if(AEntry.iState == ISTATE_CRICTICAL) { if(AEntry.Age < 0.15f) { float angle =AEntry.Age * 1.5f / 0.15f * NI_PI; float temp = 0.7f; if(angle > NI_PI) temp = 0.3f; AEntry.Scale = 1.0f + temp * NiSin(angle); } else AEntry.Scale = 0.7f; } int fff = -1; if(AEntry.Type == BUBBLE_HEALHP || AEntry.Type == BUBBLE_HEALMP) fff = 1; if(AEntry.Age < 0.2f) { AEntry.BubbleUpPos_Cal.x += fff * ( AEntry.Age * 5.f ) * BlubleUpx; } else { AEntry.BubbleUpPos_Cal.x += fff * BlubleUpx; if(progressPos <= 1.f) { AEntry.BubbleUpPos_Cal.x += fff * (1 - progressPos) * 50; AEntry.BubbleUpPos_Cal.y+= (1 - progressPos) * BlubleUpy; } } } else { float fincrease; if(AEntry.iState == ISTATE_CRICTICAL) fincrease = 30; else fincrease = 27 * AEntry.Scale; if( increase < 3){ float fPosChange = (increase%3 - 1) * fincrease; AEntry.BubbleUpPos_Cal.y -= fPosChange; }else if( increase == 3 ){ AEntry.BubbleUpPos_Cal.y -= 15; AEntry.BubbleUpPos_Cal.x += AEntry.StrLen * 26; }else if( increase == 4 ){ AEntry.BubbleUpPos_Cal.y -= 15; AEntry.BubbleUpPos_Cal.x += -AEntry.StrLen * 26; }else if(increase > 4){ float fPosChange = (increase - 3) * fincrease; AEntry.BubbleUpPos_Cal.y += fPosChange; } increase++; if(AEntry.iState == ISTATE_CRICTICAL) { //TODO大小变化 if(AEntry.Age < 0.15f) { float angle =AEntry.Age * 1.5f / 0.15f * NI_PI; float temp = 0.7f; if(angle > NI_PI) temp = 0.3f; AEntry.Scale = 1.0f + temp * NiSin(angle); } else AEntry.Scale = 0.7f; } else { AEntry.BubbleUpPos_Cal.y -= (AEntry.Age/AEntry.Life) * BlubleUpy; } } ++it; } if(!m_AttackEffectEntrys.size()) EffectMgr->DeleteCComboAttackEffect(m_pComboCharacter->GetGUID()); } void CComboAttackEffect::RenderEffect(const NiCamera* pkCamera) { std::list::iterator it = m_AttackEffectEntrys.begin(); while(it != m_AttackEffectEntrys.end()) { AttackEffectEntry& Entry = *( *it ); if (Entry.Age < 0.f) { ++it; continue; } CNumberFont::Instance()->TextOut( (INT)Entry.BubbleUpPos_Cal.x, (INT)Entry.BubbleUpPos_Cal.y, Entry.StrLen ,Entry.szNbStr,Entry.Color, Entry.iState,Entry.Scale); if (Entry.Age >= Entry.Life){ delete &Entry; it = m_AttackEffectEntrys.erase(it); continue; } ++it; } } void CComboAttackEffect::AddEntry(AttackEffectEntry* NewEntry) { m_bLocalPlayer = m_pComboCharacter->IsLocalPlayer(); float addtime = min(m_AttackEffectEntrys.size() * 0.005f, 2.f); NewEntry->Age = -EFFECTDELAY - addtime; NewEntry->iState = ISTATE_NONE; if(NewEntry->Type == BUBBLE_DEMAGE) { switch (NewEntry->victimstate) { case ATTACK://物理攻击 NewEntry->iState = GetiState(NewEntry->SubType); break; case IMMUNE://免疫 NewEntry->iState = ISTATE_IMMUNE; break; case DODGE://躲闪 case EVADE://避开 NewEntry->iState = ISTATE_DODGE; break; case BLOCK://格挡 NewEntry->iState = ISTATE_BLOCK; break; case PARRY: case INTERRUPT: case DEFLECT://擦过 break; } } if(NewEntry->Type == BUBBLE_SPELLDEMAGE) NewEntry->iState = GetiStateSpell(NewEntry->SubType); switch (NewEntry->Type) { case BUBBLE_HEALHP: case BUBBLE_HEALMP: { if (NewEntry->Number == 0) { _snwprintf(NewEntry->szNbStr, 64, L"%d",NewEntry->Number); }else{ if (m_bLocalPlayer) _snwprintf(NewEntry->szNbStr, 64, L"+%d",NewEntry->Number); else _snwprintf(NewEntry->szNbStr, 64, L"+%d",NewEntry->Number); } } break; case BUBBLE_COMBAT: { NewEntry->iState = ISTATE_DODGE + 1; NewEntry->StrLen = 8; } break; case BUBBLE_HEADTEXT: { if (NewEntry->SubType == 0 ) { NewEntry->Scale = 0.7f; }else { NewEntry->Scale = 1.5f; } } break; } if(NewEntry->iState == ISTATE_CRICTICAL) { NewEntry->Scale = 1.0f; NewEntry->Life = 1.5f; } else if(NewEntry->iState != ISTATE_NONE) NewEntry->Scale = 1.0f; if(NewEntry->Number == 0 && NewEntry->iState != ISTATE_NONE) { NewEntry->StrLen = 4; if(NewEntry->iState == ISTATE_CRICTICAL) NewEntry->StrLen += 4 + wcslen(NewEntry->szNbStr); } else NewEntry->StrLen = wcslen(NewEntry->szNbStr); NewEntry->BubbleUpPos_Init = m_pComboCharacter->GetSceneNode()->GetWorldTranslate(); if(m_bLocalPlayer) NewEntry->BubbleUpPos_Init.z += 1.0f; else NewEntry->BubbleUpPos_Init.z += 3.0f; if(m_ViewCamera == NULL) { CPlayer* pLocPlayer = ObjectMgr->GetLocalPlayer(); if(pLocPlayer) m_ViewCamera = &pLocPlayer->GetNiCamera(); } int count = m_AttackEffectEntrys.size() / 100; if(count > 1){ NewEntry->Life = max(NewEntry->Life - float(count * 0.4f), 0.5f); } m_AttackEffectEntrys.push_back(NewEntry); } void CComboAttackEffect::CalculatePosition(AttackEffectEntry* temp) { if(m_bLocalPlayer && temp->Type != BUBBLE_COMBAT) { temp->BubbleUpPos_Init = m_pComboCharacter->GetSceneNode()->GetWorldTranslate(); temp->BubbleUpPos_Init.z += 1.0f; } temp->BubbleUpPos_Cal = temp->BubbleUpPos_Init; if(m_ViewCamera) WorldPtToUIPt(temp->BubbleUpPos_Cal, &(*m_ViewCamera)); } #undef EFFECTDELAY