mirror of
https://github.com/ddnet/ddnet.git
synced 2024-09-19 17:14:18 +00:00
Add Freeze Bar
This commit is contained in:
parent
78a0a3d31e
commit
b403f474a0
|
@ -1914,6 +1914,8 @@ if(CLIENT)
|
|||
components/emoticon.h
|
||||
components/flow.cpp
|
||||
components/flow.h
|
||||
components/freezebars.cpp
|
||||
components/freezebars.h
|
||||
components/ghost.cpp
|
||||
components/ghost.h
|
||||
components/hud.cpp
|
||||
|
|
76
src/game/client/components/freezebars.cpp
Normal file
76
src/game/client/components/freezebars.cpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
#include <game/client/gameclient.h>
|
||||
|
||||
#include "freezebars.h"
|
||||
|
||||
|
||||
void CFreezeBars::RenderFreezeBar(const int ClientID)
|
||||
{
|
||||
const float FreezeBarWidth = 64.0f;
|
||||
const float FreezeBarHalfWidth = 32.0f;
|
||||
const float FreezeBarHight = 16.0f;
|
||||
|
||||
if(m_pClient->m_aClients[ClientID].m_Predicted.m_FreezeEnd <= 0.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const int Max = m_pClient->m_aClients[ClientID].m_Predicted.m_FreezeEnd - m_pClient->m_aClients[ClientID].m_Predicted.m_FreezeTick;
|
||||
float FreezeProgress = clamp(Max - (m_pClient->m_GameWorld.GameTick() - m_pClient->m_aClients[ClientID].m_Predicted.m_FreezeTick), 0, Max) / (float)Max;
|
||||
if(FreezeProgress <= 0.0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 Position;
|
||||
if(ClientID >= 0 && ClientID < MAX_CLIENTS)
|
||||
Position = m_pClient->m_aClients[ClientID].m_RenderPos;
|
||||
else
|
||||
Position = mix(vec2(m_pClient->m_aClients[ClientID].m_RenderPrev.m_X, m_pClient->m_aClients[ClientID].m_RenderPrev.m_Y), vec2(m_pClient->m_aClients[ClientID].m_RenderCur.m_X, m_pClient->m_aClients[ClientID].m_RenderCur.m_Y), Client()->IntraGameTick(g_Config.m_ClDummy));
|
||||
Position.x -= FreezeBarHalfWidth;
|
||||
Position.y += 32;
|
||||
|
||||
float Alpha = m_pClient->IsOtherTeam(ClientID) ? g_Config.m_ClShowOthersAlpha / 100.0f : 1.0f;
|
||||
|
||||
m_pClient->m_Hud.RenderProgressBar(Position.x, Position.y, FreezeBarWidth, FreezeBarHight, FreezeProgress, Alpha);
|
||||
}
|
||||
|
||||
void CFreezeBars::OnRender()
|
||||
{
|
||||
// get screen edges to avoid rendering offscreen
|
||||
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
|
||||
Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
|
||||
// expand the edges to prevent popping in/out onscreen
|
||||
//
|
||||
// it is assumed that the tee with the freeze bar fit into a 240x240 box centered on the tee
|
||||
// this may need to be changed or calculated differently in the future
|
||||
float BorderBuffer = 120;
|
||||
ScreenX0 -= BorderBuffer;
|
||||
ScreenX1 += BorderBuffer;
|
||||
ScreenY0 -= BorderBuffer;
|
||||
ScreenY1 += BorderBuffer;
|
||||
|
||||
int LocalClientID = m_pClient->m_Snap.m_LocalClientID;
|
||||
|
||||
// render everyone else's freeze bar, then our own
|
||||
for(int ClientID = 0; ClientID < MAX_CLIENTS; ClientID++)
|
||||
{
|
||||
if(ClientID == LocalClientID || !m_pClient->m_Snap.m_aCharacters[ClientID].m_Active || !m_pClient->m_Players.IsPlayerInfoAvailable(ClientID))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//don't render if the tee is offscreen
|
||||
vec2 *pRenderPos = &m_pClient->m_aClients[ClientID].m_RenderPos;
|
||||
if(pRenderPos->x < ScreenX0 || pRenderPos->x > ScreenX1 || pRenderPos->y < ScreenY0 || pRenderPos->y > ScreenY1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RenderFreezeBar(ClientID);
|
||||
|
||||
|
||||
}
|
||||
if(LocalClientID != -1 && m_pClient->m_Snap.m_aCharacters[LocalClientID].m_Active && m_pClient->m_Players.IsPlayerInfoAvailable(LocalClientID))
|
||||
{
|
||||
RenderFreezeBar(LocalClientID);
|
||||
}
|
||||
}
|
14
src/game/client/components/freezebars.h
Normal file
14
src/game/client/components/freezebars.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef GAME_CLIENT_COMPONENTS_FREEZEBARS_H
|
||||
#define GAME_CLIENT_COMPONENTS_FREEZEBARS_H
|
||||
#include <game/client/component.h>
|
||||
|
||||
class CFreezeBars : public CComponent
|
||||
{
|
||||
void RenderFreezeBar(const int ClientID);
|
||||
|
||||
public:
|
||||
virtual int Sizeof() const override { return sizeof(*this); }
|
||||
virtual void OnRender() override;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -824,10 +824,6 @@ void CHud::PreparePlayerStateQuads()
|
|||
m_LiveFrozenOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f);
|
||||
m_DummyHammerOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f);
|
||||
m_DummyCopyOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f);
|
||||
|
||||
// Quads for displaying ninja bar
|
||||
m_NinjaBarFullLeftOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 6.f, 12.f);
|
||||
m_NinjaBarEmptyRightOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 6.f, 12.f);
|
||||
}
|
||||
|
||||
void CHud::RenderPlayerState(const int ClientID)
|
||||
|
@ -970,7 +966,7 @@ void CHud::RenderPlayerState(const int ClientID)
|
|||
{
|
||||
x = 5;
|
||||
y += 12;
|
||||
RenderNinjaBar(x, y, NinjaProgress);
|
||||
RenderProgressBar(x, y, 90.0f, 12.0f, NinjaProgress);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1107,13 +1103,13 @@ void CHud::RenderPlayerState(const int ClientID)
|
|||
}
|
||||
}
|
||||
|
||||
void CHud::RenderNinjaBar(float x, float y, float Progress)
|
||||
void CHud::RenderProgressBar(float x, const float y, const float width, const float height, float Progress, const float Alpha)
|
||||
{
|
||||
Progress = clamp(Progress, 0.0f, 1.0f);
|
||||
// half of the ends are also used for the progress display
|
||||
const float EndWidth = 6.0f;
|
||||
const float BarHeight = 12.0f;
|
||||
const float WholeBarWidth = 90.f;
|
||||
const float BarHeight = height;
|
||||
const float WholeBarWidth = width;
|
||||
const float MiddleBarWidth = WholeBarWidth - (EndWidth * 2.0f);
|
||||
const float EndProgressWidth = EndWidth / 2.0f;
|
||||
const float ProgressBarWidth = WholeBarWidth - (EndProgressWidth * 2.0f);
|
||||
|
@ -1121,7 +1117,7 @@ void CHud::RenderNinjaBar(float x, float y, float Progress)
|
|||
const float MiddleProgressProportion = MiddleBarWidth / ProgressBarWidth;
|
||||
|
||||
// we cut 10% of both sides (right and left) of all sprites so we don't get edge bleeding
|
||||
|
||||
|
||||
// beginning piece
|
||||
float BeginningPieceProgress = 1;
|
||||
if(Progress <= EndProgressProportion)
|
||||
|
@ -1132,6 +1128,7 @@ void CHud::RenderNinjaBar(float x, float y, float Progress)
|
|||
// full
|
||||
Graphics()->TextureSet(m_pClient->m_HudSkin.m_SpriteHudFreezeBarFullLeft);
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(1.f, 1.f, 1.f, Alpha);
|
||||
Graphics()->QuadsSetSubset(0.1f, 0, 0.1f + 0.8f * BeginningPiecePercentVisible, 1);
|
||||
IGraphics::CQuadItem QuadFullBeginning(x, y, EndWidth * BeginningPiecePercentVisible, BarHeight);
|
||||
Graphics()->QuadsDrawTL(&QuadFullBeginning, 1);
|
||||
|
@ -1141,6 +1138,7 @@ void CHud::RenderNinjaBar(float x, float y, float Progress)
|
|||
// empty
|
||||
Graphics()->TextureSet(m_pClient->m_HudSkin.m_SpriteHudFreezeBarEmptyRight);
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(1.f, 1.f, 1.f, Alpha);
|
||||
Graphics()->QuadsSetSubset(0.1f, 1, 0.1f + 0.8f * (1.0f - BeginningPiecePercentVisible), 0);
|
||||
Graphics()->QuadsSetRotation(pi);
|
||||
IGraphics::CQuadItem QuadEmptyBeginning(x + (EndWidth * BeginningPiecePercentVisible), y, EndWidth * (1.0f - BeginningPiecePercentVisible), BarHeight);
|
||||
|
@ -1172,6 +1170,7 @@ void CHud::RenderNinjaBar(float x, float y, float Progress)
|
|||
// full ninja bar
|
||||
Graphics()->TextureSet(m_pClient->m_HudSkin.m_SpriteHudFreezeBarFull);
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(1.f, 1.f, 1.f, Alpha);
|
||||
// select the middle portion of the sprite so we don't get edge bleeding
|
||||
if(MiddlePieceProgress * MiddleBarWidth <= EndWidth * 0.8f)
|
||||
{
|
||||
|
@ -1189,6 +1188,7 @@ void CHud::RenderNinjaBar(float x, float y, float Progress)
|
|||
// empty ninja bar
|
||||
Graphics()->TextureSet(m_pClient->m_HudSkin.m_SpriteHudFreezeBarEmpty);
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(1.f, 1.f, 1.f, Alpha);
|
||||
// select the middle portion of the sprite so we don't get edge bleeding
|
||||
if((1.0f - MiddlePieceProgress) * MiddleBarWidth <= EndWidth * 0.8f)
|
||||
{
|
||||
|
@ -1224,6 +1224,7 @@ void CHud::RenderNinjaBar(float x, float y, float Progress)
|
|||
{
|
||||
Graphics()->TextureSet(m_pClient->m_HudSkin.m_SpriteHudFreezeBarFullLeft);
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(1.f, 1.f, 1.f, Alpha);
|
||||
Graphics()->QuadsSetSubset(0.5f + 0.4f * (1.0f - EndingPieceProgress), 1, 0.90f, 0);
|
||||
Graphics()->QuadsSetRotation(pi);
|
||||
IGraphics::CQuadItem QuadFullEnding(x, y, (EndWidth / 2) * EndingPieceProgress, BarHeight);
|
||||
|
@ -1234,11 +1235,13 @@ void CHud::RenderNinjaBar(float x, float y, float Progress)
|
|||
// empty
|
||||
Graphics()->TextureSet(m_pClient->m_HudSkin.m_SpriteHudFreezeBarEmptyRight);
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(1.f, 1.f, 1.f, Alpha);
|
||||
Graphics()->QuadsSetSubset(0.5f - 0.4f * (1.0f - EndingPieceProgress), 0, 0.9f, 1);
|
||||
IGraphics::CQuadItem QuadEmptyEnding(x + ((EndWidth / 2) * EndingPieceProgress), y, (EndWidth / 2) * (1.0f - EndingPieceProgress) + (EndWidth / 2), BarHeight);
|
||||
Graphics()->QuadsDrawTL(&QuadEmptyEnding, 1);
|
||||
Graphics()->QuadsEnd();
|
||||
Graphics()->QuadsSetSubset(0, 0, 1, 1);
|
||||
Graphics()->SetColor(1.f, 1.f, 1.f, 1.f);
|
||||
}
|
||||
|
||||
void CHud::RenderSpectatorHud()
|
||||
|
|
|
@ -54,7 +54,6 @@ class CHud : public CComponent
|
|||
|
||||
void PreparePlayerStateQuads();
|
||||
void RenderPlayerState(const int ClientID);
|
||||
void RenderNinjaBar(float x, float y, float Progress);
|
||||
|
||||
void RenderGameTimer();
|
||||
void RenderPauseNotification();
|
||||
|
@ -79,6 +78,7 @@ public:
|
|||
// DDRace
|
||||
|
||||
virtual void OnMessage(int MsgType, void *pRawMsg) override;
|
||||
void RenderProgressBar(float x, const float y, const float width, const float height, float Progress, float Alpha = 1.0f);
|
||||
|
||||
private:
|
||||
void RenderRecord();
|
||||
|
@ -125,8 +125,6 @@ private:
|
|||
int m_LiveFrozenOffset;
|
||||
int m_DummyHammerOffset;
|
||||
int m_DummyCopyOffset;
|
||||
int m_NinjaBarFullLeftOffset;
|
||||
int m_NinjaBarEmptyRightOffset;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -37,10 +37,11 @@ class CPlayers : public CComponent
|
|||
int m_WeaponSpriteMuzzleQuadContainerIndex[NUM_WEAPONS];
|
||||
|
||||
public:
|
||||
vec2 m_CurPredictedPos[MAX_CLIENTS];
|
||||
virtual int Sizeof() const override { return sizeof(*this); }
|
||||
virtual void OnInit() override;
|
||||
virtual void OnRender() override;
|
||||
|
||||
bool IsPlayerInfoAvailable(int ClientID) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "components/effects.h"
|
||||
#include "components/emoticon.h"
|
||||
#include "components/flow.h"
|
||||
#include "components/freezebars.h"
|
||||
#include "components/hud.h"
|
||||
#include "components/items.h"
|
||||
#include "components/killmessages.h"
|
||||
|
@ -125,6 +126,7 @@ void CGameClient::OnConsoleInit()
|
|||
m_All.Add(&m_Particles.m_RenderExplosions);
|
||||
m_All.Add(&m_NamePlates);
|
||||
m_All.Add(&m_Particles.m_RenderGeneral);
|
||||
m_All.Add(&m_FreezeBars);
|
||||
m_All.Add(&m_DamageInd);
|
||||
m_All.Add(&m_Hud);
|
||||
m_All.Add(&m_Spectator);
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "components/effects.h"
|
||||
#include "components/emoticon.h"
|
||||
#include "components/flow.h"
|
||||
#include "components/freezebars.h"
|
||||
#include "components/ghost.h"
|
||||
#include "components/hud.h"
|
||||
#include "components/items.h"
|
||||
|
@ -131,6 +132,7 @@ public:
|
|||
|
||||
CPlayers m_Players;
|
||||
CNamePlates m_NamePlates;
|
||||
CFreezeBars m_FreezeBars;
|
||||
CItems m_Items;
|
||||
CMapImages m_MapImages;
|
||||
|
||||
|
|
|
@ -982,10 +982,10 @@ bool CCharacter::Freeze(int Seconds)
|
|||
return false;
|
||||
if((Seconds <= 0 || m_Super || m_FreezeTime == -1 || m_FreezeTime > Seconds * GameWorld()->GameTickSpeed()) && Seconds != -1)
|
||||
return false;
|
||||
if(m_FreezeTick < GameWorld()->GameTick() - GameWorld()->GameTickSpeed() || Seconds == -1)
|
||||
if(m_Core.m_FreezeTick < GameWorld()->GameTick() - GameWorld()->GameTickSpeed() || Seconds == -1)
|
||||
{
|
||||
m_FreezeTime = Seconds == -1 ? Seconds : Seconds * GameWorld()->GameTickSpeed();
|
||||
m_FreezeTick = GameWorld()->GameTick();
|
||||
m_Core.m_FreezeTick = GameWorld()->GameTick();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1003,7 +1003,7 @@ bool CCharacter::UnFreeze()
|
|||
if(!m_Core.m_aWeapons[m_Core.m_ActiveWeapon].m_Got)
|
||||
m_Core.m_ActiveWeapon = WEAPON_GUN;
|
||||
m_FreezeTime = 0;
|
||||
m_FreezeTick = 0;
|
||||
m_Core.m_FreezeTick = 0;
|
||||
m_FrozenLastTick = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -1100,7 +1100,7 @@ void CCharacter::ResetPrediction()
|
|||
m_Core.m_Collision = true;
|
||||
m_NumInputs = 0;
|
||||
m_FreezeTime = 0;
|
||||
m_FreezeTick = 0;
|
||||
m_Core.m_FreezeTick = 0;
|
||||
m_DeepFreeze = false;
|
||||
m_LiveFreeze = false;
|
||||
m_FrozenLastTick = false;
|
||||
|
@ -1241,7 +1241,7 @@ void CCharacter::Read(CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtende
|
|||
// detect unfreeze (in case the player was frozen in the tile prediction and not correctly unfrozen)
|
||||
if(pChar->m_Emote != EMOTE_PAIN && pChar->m_Emote != EMOTE_NORMAL)
|
||||
m_DeepFreeze = false;
|
||||
if(pChar->m_Weapon != WEAPON_NINJA || pChar->m_AttackTick > m_FreezeTick || absolute(pChar->m_VelX) == 256 * 10 || !GameWorld()->m_WorldConfig.m_PredictFreeze)
|
||||
if(pChar->m_Weapon != WEAPON_NINJA || pChar->m_AttackTick > m_Core.m_FreezeTick || absolute(pChar->m_VelX) == 256 * 10 || !GameWorld()->m_WorldConfig.m_PredictFreeze)
|
||||
{
|
||||
m_DeepFreeze = false;
|
||||
UnFreeze();
|
||||
|
|
|
@ -79,7 +79,6 @@ public:
|
|||
bool m_Jetpack;
|
||||
bool m_NinjaJetpack;
|
||||
int m_FreezeTime;
|
||||
int m_FreezeTick;
|
||||
bool m_FrozenLastTick;
|
||||
bool m_DeepFreeze;
|
||||
bool m_LiveFreeze;
|
||||
|
|
|
@ -290,6 +290,7 @@ public:
|
|||
bool m_HasTelegunGun;
|
||||
bool m_HasTelegunGrenade;
|
||||
bool m_HasTelegunLaser;
|
||||
int m_FreezeTick;
|
||||
int m_FreezeEnd;
|
||||
bool m_DeepFrozen;
|
||||
bool m_LiveFrozen;
|
||||
|
|
|
@ -1145,7 +1145,7 @@ void CCharacter::SnapCharacter(int SnappingClient, int ID)
|
|||
pCharacter->m_AmmoCount = AmmoCount;
|
||||
|
||||
if(m_FreezeTime > 0 || m_FreezeTime == -1 || m_DeepFreeze)
|
||||
pCharacter->m_AmmoCount = m_FreezeTick + g_Config.m_SvFreezeDelay * Server()->TickSpeed();
|
||||
pCharacter->m_AmmoCount = m_Core.m_FreezeTick + g_Config.m_SvFreezeDelay * Server()->TickSpeed();
|
||||
else if(Weapon == WEAPON_NINJA)
|
||||
pCharacter->m_AmmoCount = m_Core.m_Ninja.m_ActivationTick + g_pData->m_Weapons.m_Ninja.m_Duration * Server()->TickSpeed() / 1000;
|
||||
|
||||
|
@ -2181,11 +2181,11 @@ bool CCharacter::Freeze(int Seconds)
|
|||
{
|
||||
if((Seconds <= 0 || m_Super || m_FreezeTime == -1 || m_FreezeTime > Seconds * Server()->TickSpeed()) && Seconds != -1)
|
||||
return false;
|
||||
if(m_FreezeTick < Server()->Tick() - Server()->TickSpeed() || Seconds == -1)
|
||||
if(m_Core.m_FreezeTick < Server()->Tick() - Server()->TickSpeed() || Seconds == -1)
|
||||
{
|
||||
m_Armor = 0;
|
||||
m_FreezeTime = Seconds == -1 ? Seconds : Seconds * Server()->TickSpeed();
|
||||
m_FreezeTick = Server()->Tick();
|
||||
m_Core.m_FreezeTick = Server()->Tick();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -2204,7 +2204,7 @@ bool CCharacter::UnFreeze()
|
|||
if(!m_Core.m_aWeapons[m_Core.m_ActiveWeapon].m_Got)
|
||||
m_Core.m_ActiveWeapon = WEAPON_GUN;
|
||||
m_FreezeTime = 0;
|
||||
m_FreezeTick = 0;
|
||||
m_Core.m_FreezeTick = 0;
|
||||
m_FrozenLastTick = true;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -183,7 +183,6 @@ public:
|
|||
bool m_NinjaJetpack;
|
||||
int m_TeamBeforeSuper;
|
||||
int m_FreezeTime;
|
||||
int m_FreezeTick;
|
||||
bool m_FrozenLastTick;
|
||||
bool m_DeepFreeze;
|
||||
bool m_LiveFreeze;
|
||||
|
|
|
@ -39,7 +39,7 @@ void CSaveTee::Save(CCharacter *pChr)
|
|||
m_Jetpack = pChr->m_Jetpack;
|
||||
m_NinjaJetpack = pChr->m_NinjaJetpack;
|
||||
m_FreezeTime = pChr->m_FreezeTime;
|
||||
m_FreezeTick = pChr->Server()->Tick() - pChr->m_FreezeTick;
|
||||
m_FreezeTick = pChr->Server()->Tick() - pChr->m_Core.m_FreezeTick;
|
||||
|
||||
m_DeepFreeze = pChr->m_DeepFreeze;
|
||||
m_LiveFreeze = pChr->m_LiveFreeze;
|
||||
|
@ -134,7 +134,7 @@ void CSaveTee::Load(CCharacter *pChr, int Team, bool IsSwap)
|
|||
pChr->m_Jetpack = m_Jetpack;
|
||||
pChr->m_NinjaJetpack = m_NinjaJetpack;
|
||||
pChr->m_FreezeTime = m_FreezeTime;
|
||||
pChr->m_FreezeTick = pChr->Server()->Tick() - m_FreezeTick;
|
||||
pChr->m_Core.m_FreezeTick = pChr->Server()->Tick() - m_FreezeTick;
|
||||
|
||||
pChr->m_DeepFreeze = m_DeepFreeze;
|
||||
pChr->m_LiveFreeze = m_LiveFreeze;
|
||||
|
|
Loading…
Reference in a new issue