diff --git a/datasrc/content.py b/datasrc/content.py index 79cffc0ef..61ad317ba 100644 --- a/datasrc/content.py +++ b/datasrc/content.py @@ -396,6 +396,11 @@ container.sprites.Add(Sprite("pickup_ninja", set_game, 2,10,8,2)) container.sprites.Add(Sprite("flag_blue", set_game, 12,8,4,8)) container.sprites.Add(Sprite("flag_red", set_game, 16,8,4,8)) +container.sprites.Add(Sprite("ninja_bar_full_left", set_game, 21,4,1,2)) +container.sprites.Add(Sprite("ninja_bar_full", set_game, 22,4,1,2)) +container.sprites.Add(Sprite("ninja_bar_empty", set_game, 23,4,1,2)) +container.sprites.Add(Sprite("ninja_bar_empty_right", set_game, 24,4,1,2)) + container.sprites.Add(Sprite("tee_body_outline", set_tee_body, 0,0,1,1)) container.sprites.Add(Sprite("tee_body", set_tee_body, 1,0,1,1)) container.sprites.Add(Sprite("tee_body_shadow", set_tee_body, 0,1,1,1)) diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index 8fef03491..3a2948bd9 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -22,7 +22,7 @@ CHud::CHud() { // won't work if zero m_AverageFPS = 1.0f; - + m_WarmupHideTick = 0; } @@ -109,7 +109,7 @@ void CHud::RenderStartCountdown() if(m_pClient->m_Snap.m_pGameData->m_GameStateEndTick == 0) return; - + FontSize = 16.0f; char aBuf[32]; int Seconds = (m_pClient->m_Snap.m_pGameData->m_GameStateEndTick-Client()->GameTick()+SERVER_TICK_SPEED-1)/SERVER_TICK_SPEED; @@ -279,7 +279,7 @@ void CHud::RenderScoreHud() TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreWidth[t])/2-Split, StartY+t*20, 14.0f, aScore[t], -1); if(aPlayerInfo[t].m_pPlayerInfo) - { + { // draw name int ID = aPlayerInfo[t].m_ClientID; char aName[64]; @@ -289,9 +289,9 @@ void CHud::RenderScoreHud() // draw tee CTeeRenderInfo Info = m_pClient->m_aClients[ID].m_RenderInfo; - Info.m_Size = 18.0f; - RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0), - vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, StartY+1.0f+Info.m_Size/2+t*20)); + Info.m_Size = 18.0f; + RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0), + vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, StartY+1.0f+Info.m_Size/2+t*20)); } // draw position @@ -314,7 +314,7 @@ void CHud::RenderWarmupTimer() float FontSize = 20.0f; float w = 0.0f; const char *pText = Localize("Warmup"); - + if(m_WarmupHideTick == 0 || (time_get() - m_WarmupHideTick) / time_freq() < 10) { w = TextRender()->TextWidth(0, FontSize, pText, -1); @@ -325,7 +325,7 @@ void CHud::RenderWarmupTimer() TextRender()->TextColor(1, 1, 0.5f, 1); TextRender()->Text(0x0, 10, 45, 8, pText, -1); } - + FontSize = 16.0f; if(m_pClient->m_Snap.m_pGameData->m_GameStateEndTick == 0) { @@ -348,7 +348,7 @@ void CHud::RenderWarmupTimer() else str_format(aBuf, sizeof(aBuf), "%d", round_to_int(Seconds)); } - + if(m_WarmupHideTick == 0 || (time_get() - m_WarmupHideTick) / time_freq() < 10) { w = TextRender()->TextWidth(0, FontSize, aBuf, -1); @@ -462,6 +462,75 @@ void CHud::RenderCursor() Graphics()->QuadsEnd(); } +void CHud::RenderNinjaBar(float x, float y, float Progress) +{ + Progress = clamp(Progress, 0.0f, 1.0f); + const float EndWidth = 6.0f; + const float BarHeight = 12.0f; + const float WholeBarWidth = 120.f; + const float MiddleBarWidth = WholeBarWidth - (EndWidth * 2.0f); + + IGraphics::CQuadItem QuadStartFull(x, y, EndWidth, BarHeight); + RenderTools()->SelectSprite(&g_pData->m_aSprites[SPRITE_NINJA_BAR_FULL_LEFT]); + Graphics()->QuadsDrawTL(&QuadStartFull, 1); + x += EndWidth; + + const float FullBarWidth = MiddleBarWidth * Progress; + const float EmptyBarWidth = MiddleBarWidth - FullBarWidth; + + // full bar + IGraphics::CQuadItem QuadFull(x, y, FullBarWidth, BarHeight); + + CDataSprite SpriteBarFull = g_pData->m_aSprites[SPRITE_NINJA_BAR_FULL]; + // prevent pixel puree, select only a small slice + if(Progress < 0.1f) + { + int spx = SpriteBarFull.m_X; + int spy = SpriteBarFull.m_Y; + float w = SpriteBarFull.m_W * 0.1f; // magic here + int h = SpriteBarFull.m_H; + int cx = SpriteBarFull.m_pSet->m_Gridx; + int cy = SpriteBarFull.m_pSet->m_Gridy; + float x1 = spx/(float)cx; + float x2 = (spx+w-1/32.0f)/(float)cx; + float y1 = spy/(float)cy; + float y2 = (spy+h-1/32.0f)/(float)cy; + + Graphics()->QuadsSetSubset(x1, y1, x2, y2); + } + else + RenderTools()->SelectSprite(&SpriteBarFull); + + Graphics()->QuadsDrawTL(&QuadFull, 1); + + // empty bar + // select the middle portion of the sprite so we don't get edge bleeding + const CDataSprite SpriteBarEmpty = g_pData->m_aSprites[SPRITE_NINJA_BAR_EMPTY]; + { + float spx = SpriteBarEmpty.m_X + 0.1f; + float spy = SpriteBarEmpty.m_Y; + float w = SpriteBarEmpty.m_W * 0.5f; + int h = SpriteBarEmpty.m_H; + int cx = SpriteBarEmpty.m_pSet->m_Gridx; + int cy = SpriteBarEmpty.m_pSet->m_Gridy; + float x1 = spx/(float)cx; + float x2 = (spx+w-1/32.0f)/(float)cx; + float y1 = spy/(float)cy; + float y2 = (spy+h-1/32.0f)/(float)cy; + + Graphics()->QuadsSetSubset(x1, y1, x2, y2); + } + + IGraphics::CQuadItem QuadEmpty(x + FullBarWidth, y, EmptyBarWidth, BarHeight); + Graphics()->QuadsDrawTL(&QuadEmpty, 1); + + x += MiddleBarWidth; + + IGraphics::CQuadItem QuadEndEmpty(x, y, EndWidth, BarHeight); + RenderTools()->SelectSprite(&g_pData->m_aSprites[SPRITE_NINJA_BAR_EMPTY_RIGHT]); + Graphics()->QuadsDrawTL(&QuadEndEmpty, 1); +} + void CHud::RenderHealthAndAmmo(const CNetObj_Character *pCharacter) { if(!pCharacter) @@ -472,30 +541,21 @@ void CHud::RenderHealthAndAmmo(const CNetObj_Character *pCharacter) int i; IGraphics::CQuadItem Array[10]; + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); + Graphics()->WrapClamp(); + + Graphics()->QuadsBegin(); + Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); + // render ammo if(pCharacter->m_Weapon == WEAPON_NINJA) { - CUIRect Rect = {x, y+24.0f, 118.0f, 10.0f}; - RenderTools()->DrawUIRect(&Rect, vec4(0.8f, 0.8f, 0.8f, 0.5f), 0, 0.0f); - - int Max = g_pData->m_Weapons.m_Ninja.m_Duration * Client()->GameTickSpeed() / 1000; - Rect.x = x+1.0f; - Rect.y = y+25.0f; - Rect.w = 116.0f * clamp(pCharacter->m_AmmoCount-Client()->GameTick(), 0, Max) / Max; - Rect.h = 8.0f; - RenderTools()->DrawUIRect(&Rect, vec4(0.9f, 0.2f, 0.2f, 0.85f), 0, 0.0f); - - Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); - Graphics()->QuadsBegin(); - Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); - RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[WEAPON_NINJA].m_pSpriteBody); - Array[0] = IGraphics::CQuadItem(x+40.0f,y+25, 32.0f, 8.0f); - Graphics()->QuadsDrawTL(Array, 1); + const int Max = g_pData->m_Weapons.m_Ninja.m_Duration * Client()->GameTickSpeed() / 1000; + float NinjaProgress = clamp(pCharacter->m_AmmoCount-Client()->GameTick(), 0, Max) / (float)Max; + RenderNinjaBar(x, y+24.f, NinjaProgress); } else { - Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); - Graphics()->QuadsBegin(); RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[pCharacter->m_Weapon%NUM_WEAPONS].m_pSpriteProj); if(pCharacter->m_Weapon == WEAPON_GRENADE) { diff --git a/src/game/client/components/hud.h b/src/game/client/components/hud.h index e069758ba..68b1b1770 100644 --- a/src/game/client/components/hud.h +++ b/src/game/client/components/hud.h @@ -16,6 +16,7 @@ class CHud : public CComponent void RenderConnectionWarning(); void RenderTeambalanceWarning(); void RenderVoting(); + void RenderNinjaBar(float x, float y, float Progress); void RenderHealthAndAmmo(const CNetObj_Character *pCharacter); void RenderGameTimer(); void RenderPauseTimer();