Compare commits

...

13 commits

Author SHA1 Message Date
KebsCS 0d993d65c2
Merge 34871095dc into 0f12044fcd 2024-09-15 05:47:43 -05:00
Dennis Felsing 0f12044fcd
Merge pull request #8956 from Robyt3/UI-Scrollbar-Rail-HotItem
Fix scrollbar rail clicking being active while popups open
2024-09-15 10:21:41 +00:00
Robert Müller 8f2c288698 Fix scrollbar rail clicking being active while popups open
Scrollbars are now also set as the hot item when the rail is hovered and the rail clicking function is now only enabled for the scrollbar that is the hot item.

Closes #8954.
2024-09-15 11:45:22 +02:00
Dennis Felsing 4b6f2e22a8
Merge pull request #8955 from furo321/url-master-parsing
Don't allow URLs without port from the masterserver
2024-09-15 09:28:43 +00:00
furo 7bbd51cf73 Don't allow URLs without port from the masterserver 2024-09-15 11:04:48 +02:00
Dennis Felsing dcd02b50bb
Merge pull request #8953 from ChillerDragon/pr_bind_null
Add BindNull to SQL api
2024-09-15 06:31:43 +00:00
Dennis Felsing 4fe956dffc
Merge pull request #8951 from furo321/fix-capture-count
Fix captures not being counted for certain names
2024-09-15 06:13:40 +00:00
ChillerDragon 7c2f058c40 Add BindNull to SQL api
Comes in handy in my downstream project
2024-09-15 09:14:00 +08:00
furo 6bf4a016ba Fix captures not being counted for certain names 2024-09-15 00:51:39 +02:00
Dennis Felsing 0feee9aa3e
Merge pull request #8948 from Robyt3/Client-Chat-TeeRenderInfo-Cleanup
Store `CTeeRenderInfo` instead of members for chat lines, extract `CTeeRenderInfo::Apply(const CSkin *)` function
2024-09-14 21:39:46 +00:00
Robert Müller 65cf776846 Extract CTeeRenderInfo::Apply(const CSkin *) function
Add function to apply information of `CSkin` to a `CTeeRenderInfo` to reduce duplicate code.
2024-09-14 21:12:43 +02:00
Robert Müller 62075d22e3 Store CTeeRenderInfo instead of members for chat lines
Avoid code to convert from `CTeeRenderInfo` to chat-internal representation and back to `CTeeRenderInfo`.
2024-09-14 21:12:25 +02:00
KebsCS 34871095dc
Add /unspec command 2024-09-10 00:16:55 +02:00
19 changed files with 121 additions and 156 deletions

View file

@ -424,7 +424,10 @@ void CServerBrowserHttp::Refresh()
}
bool ServerbrowserParseUrl(NETADDR *pOut, const char *pUrl)
{
return net_addr_from_url(pOut, pUrl, nullptr, 0) != 0;
int Failure = net_addr_from_url(pOut, pUrl, nullptr, 0);
if(Failure || pOut->port == 0)
return true;
return false;
}
bool CServerBrowserHttp::Validate(json_value *pJson)
{

View file

@ -61,6 +61,7 @@ public:
virtual void BindInt(int Idx, int Value) = 0;
virtual void BindInt64(int Idx, int64_t Value) = 0;
virtual void BindFloat(int Idx, float Value) = 0;
virtual void BindNull(int Idx) = 0;
// Print expanded sql statement
virtual void Print() = 0;

View file

@ -89,6 +89,7 @@ public:
void BindInt(int Idx, int Value) override;
void BindInt64(int Idx, int64_t Value) override;
void BindFloat(int Idx, float Value) override;
void BindNull(int Idx) override;
void Print() override {}
bool Step(bool *pEnd, char *pError, int ErrorSize) override;
@ -421,6 +422,22 @@ void CMysqlConnection::BindFloat(int Idx, float Value)
pParam->error = nullptr;
}
void CMysqlConnection::BindNull(int Idx)
{
m_NewQuery = true;
Idx -= 1;
dbg_assert(0 <= Idx && Idx < (int)m_vStmtParameters.size(), "index out of bounds");
MYSQL_BIND *pParam = &m_vStmtParameters[Idx];
pParam->buffer_type = MYSQL_TYPE_NULL;
pParam->buffer = nullptr;
pParam->buffer_length = 0;
pParam->length = nullptr;
pParam->is_null = nullptr;
pParam->is_unsigned = false;
pParam->error = nullptr;
}
bool CMysqlConnection::Step(bool *pEnd, char *pError, int ErrorSize)
{
if(m_NewQuery)

View file

@ -37,6 +37,7 @@ public:
void BindInt(int Idx, int Value) override;
void BindInt64(int Idx, int64_t Value) override;
void BindFloat(int Idx, float Value) override;
void BindNull(int Idx) override;
void Print() override;
bool Step(bool *pEnd, char *pError, int ErrorSize) override;
@ -241,6 +242,13 @@ void CSqliteConnection::BindFloat(int Idx, float Value)
m_Done = false;
}
void CSqliteConnection::BindNull(int Idx)
{
int Result = sqlite3_bind_null(m_pStmt, Idx);
AssertNoError(Result);
m_Done = false;
}
// Keep support for SQLite < 3.14 on older Linux distributions. MinGW does not
// support __attribute__((weak)): https://sourceware.org/bugzilla/show_bug.cgi?id=9687
#if defined(__GNUC__) && !defined(__MINGW32__)

View file

@ -805,50 +805,9 @@ void CChat::AddLine(int ClientId, int Team, const char *pLine)
{
if(!g_Config.m_ClChatOld)
{
pCurrentLine->m_CustomColoredSkin = LineAuthor.m_RenderInfo.m_CustomColoredSkin;
if(pCurrentLine->m_CustomColoredSkin)
pCurrentLine->m_RenderSkin = LineAuthor.m_RenderInfo.m_ColorableRenderSkin;
else
pCurrentLine->m_RenderSkin = LineAuthor.m_RenderInfo.m_OriginalRenderSkin;
str_copy(pCurrentLine->m_aSkinName, LineAuthor.m_aSkinName);
pCurrentLine->m_ColorBody = LineAuthor.m_RenderInfo.m_ColorBody;
pCurrentLine->m_ColorFeet = LineAuthor.m_RenderInfo.m_ColorFeet;
pCurrentLine->m_RenderSkinMetrics = LineAuthor.m_RenderInfo.m_SkinMetrics;
pCurrentLine->m_TeeRenderInfo = LineAuthor.m_RenderInfo;
pCurrentLine->m_HasRenderTee = true;
// 0.7
if(Client()->IsSixup())
{
for(int Part = 0; Part < protocol7::NUM_SKINPARTS; Part++)
{
const char *pPartName = LineAuthor.m_aSixup[g_Config.m_ClDummy].m_aaSkinPartNames[Part];
int Id = m_pClient->m_Skins7.FindSkinPart(Part, pPartName, false);
const CSkins7::CSkinPart *pSkinPart = m_pClient->m_Skins7.GetSkinPart(Part, Id);
if(LineAuthor.m_aSixup[g_Config.m_ClDummy].m_aUseCustomColors[Part])
{
pCurrentLine->m_Sixup.m_aTextures[Part] = pSkinPart->m_ColorTexture;
pCurrentLine->m_Sixup.m_aColors[Part] = m_pClient->m_Skins7.GetColor(
LineAuthor.m_aSixup[g_Config.m_ClDummy].m_aSkinPartColors[Part],
Part == protocol7::SKINPART_MARKING);
}
else
{
pCurrentLine->m_Sixup.m_aTextures[Part] = pSkinPart->m_OrgTexture;
pCurrentLine->m_Sixup.m_aColors[Part] = vec4(1.0f, 1.0f, 1.0f, 1.0f);
}
if(LineAuthor.m_SkinInfo.m_aSixup[g_Config.m_ClDummy].m_HatTexture.IsValid())
{
if(Part == protocol7::SKINPART_BODY && str_comp(pPartName, "standard"))
pCurrentLine->m_Sixup.m_HatSpriteIndex = CSkins7::HAT_OFFSET_SIDE + (ClientId % CSkins7::HAT_NUM);
if(Part == protocol7::SKINPART_DECORATION && str_comp(pPartName, "twinbopp"))
pCurrentLine->m_Sixup.m_HatSpriteIndex = CSkins7::HAT_OFFSET_SIDE + (ClientId % CSkins7::HAT_NUM);
pCurrentLine->m_Sixup.m_HatTexture = LineAuthor.m_SkinInfo.m_aSixup[g_Config.m_ClDummy].m_HatTexture;
}
}
}
}
}
}
@ -917,17 +876,11 @@ void CChat::OnRefreshSkins()
{
if(Line.m_HasRenderTee)
{
const CSkin *pSkin = m_pClient->m_Skins.Find(Line.m_aSkinName);
if(Line.m_CustomColoredSkin)
Line.m_RenderSkin = pSkin->m_ColorableSkin;
else
Line.m_RenderSkin = pSkin->m_OriginalSkin;
Line.m_RenderSkinMetrics = pSkin->m_Metrics;
Line.m_TeeRenderInfo.Apply(m_pClient->m_Skins.Find(Line.m_aSkinName));
}
else
{
Line.m_RenderSkin.Reset();
Line.m_TeeRenderInfo.Reset();
}
}
}
@ -1291,28 +1244,7 @@ void CChat::OnRender()
if(!g_Config.m_ClChatOld && Line.m_HasRenderTee)
{
const int TeeSize = MessageTeeSize();
CTeeRenderInfo RenderInfo;
RenderInfo.m_CustomColoredSkin = Line.m_CustomColoredSkin;
if(Line.m_CustomColoredSkin)
RenderInfo.m_ColorableRenderSkin = Line.m_RenderSkin;
else
RenderInfo.m_OriginalRenderSkin = Line.m_RenderSkin;
RenderInfo.m_SkinMetrics = Line.m_RenderSkinMetrics;
RenderInfo.m_ColorBody = Line.m_ColorBody;
RenderInfo.m_ColorFeet = Line.m_ColorFeet;
RenderInfo.m_Size = TeeSize;
if(Client()->IsSixup())
{
for(int Part = 0; Part < protocol7::NUM_SKINPARTS; Part++)
{
RenderInfo.m_aSixup[g_Config.m_ClDummy].m_aColors[Part] = Line.m_Sixup.m_aColors[Part];
RenderInfo.m_aSixup[g_Config.m_ClDummy].m_aTextures[Part] = Line.m_Sixup.m_aTextures[Part];
RenderInfo.m_aSixup[g_Config.m_ClDummy].m_HatSpriteIndex = Line.m_Sixup.m_HatSpriteIndex;
RenderInfo.m_aSixup[g_Config.m_ClDummy].m_HatTexture = Line.m_Sixup.m_HatTexture;
}
}
Line.m_TeeRenderInfo.m_Size = TeeSize;
float RowHeight = FontSize() + RealMsgPaddingY;
float OffsetTeeY = TeeSize / 2.0f;
@ -1320,9 +1252,9 @@ void CChat::OnRender()
const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid;
CRenderTools::GetRenderTeeOffsetToRenderedTee(pIdleState, &RenderInfo, OffsetToMid);
CRenderTools::GetRenderTeeOffsetToRenderedTee(pIdleState, &Line.m_TeeRenderInfo, OffsetToMid);
vec2 TeeRenderPos(x + (RealMsgPaddingX + TeeSize) / 2.0f, y + OffsetTeeY + FullHeightMinusTee / 2.0f + OffsetToMid.y);
RenderTools()->RenderTee(pIdleState, &RenderInfo, EMOTE_NORMAL, vec2(1, 0.1f), TeeRenderPos, Blend);
RenderTools()->RenderTee(pIdleState, &Line.m_TeeRenderInfo, EMOTE_NORMAL, vec2(1, 0.1f), TeeRenderPos, Blend);
}
const ColorRGBA TextColor = TextRender()->DefaultTextColor().WithMultipliedAlpha(Blend);

View file

@ -11,6 +11,7 @@
#include <game/client/component.h>
#include <game/client/lineinput.h>
#include <game/client/render.h>
#include <game/client/skin.h>
#include <game/generated/protocol7.h>
@ -45,30 +46,12 @@ class CChat : public CComponent
int m_QuadContainerIndex;
char m_aSkinName[std::size(g_Config.m_ClPlayerSkin)];
CSkin::SSkinTextures m_RenderSkin;
CSkin::SSkinMetrics m_RenderSkinMetrics;
bool m_CustomColoredSkin;
ColorRGBA m_ColorBody;
ColorRGBA m_ColorFeet;
bool m_HasRenderTee;
CTeeRenderInfo m_TeeRenderInfo;
float m_TextYOffset;
int m_TimesRepeated;
class CSixup
{
public:
IGraphics::CTextureHandle m_aTextures[protocol7::NUM_SKINPARTS];
IGraphics::CTextureHandle m_HatTexture;
IGraphics::CTextureHandle m_BotTexture;
int m_HatSpriteIndex;
ColorRGBA m_BotColor;
ColorRGBA m_aColors[protocol7::NUM_SKINPARTS];
};
// 0.7 Skin
CSixup m_Sixup;
};
bool m_PrevScoreBoardShowed;

View file

@ -366,10 +366,7 @@ void CGhost::OnRender()
IsTeamplay = (m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags & GAMEFLAG_TEAMS) != 0;
GhostNinjaRenderInfo = Ghost.m_RenderInfo;
GhostNinjaRenderInfo.m_OriginalRenderSkin = pSkin->m_OriginalSkin;
GhostNinjaRenderInfo.m_ColorableRenderSkin = pSkin->m_ColorableSkin;
GhostNinjaRenderInfo.m_BloodColor = pSkin->m_BloodColor;
GhostNinjaRenderInfo.m_SkinMetrics = pSkin->m_Metrics;
GhostNinjaRenderInfo.Apply(pSkin);
GhostNinjaRenderInfo.m_CustomColoredSkin = IsTeamplay;
if(!IsTeamplay)
{
@ -392,11 +389,7 @@ void CGhost::InitRenderInfos(CGhostItem *pGhost)
IntsToStr(&pGhost->m_Skin.m_Skin0, 6, aSkinName, std::size(aSkinName));
CTeeRenderInfo *pRenderInfo = &pGhost->m_RenderInfo;
const CSkin *pSkin = m_pClient->m_Skins.Find(aSkinName);
pRenderInfo->m_OriginalRenderSkin = pSkin->m_OriginalSkin;
pRenderInfo->m_ColorableRenderSkin = pSkin->m_ColorableSkin;
pRenderInfo->m_BloodColor = pSkin->m_BloodColor;
pRenderInfo->m_SkinMetrics = pSkin->m_Metrics;
pRenderInfo->Apply(m_pClient->m_Skins.Find(aSkinName));
pRenderInfo->m_CustomColoredSkin = pGhost->m_Skin.m_UseCustomColor;
if(pGhost->m_Skin.m_UseCustomColor)
{
@ -697,11 +690,7 @@ void CGhost::OnRefreshSkins()
CTeeRenderInfo *pRenderInfo = &Ghost.m_RenderInfo;
if(aSkinName[0] != '\0')
{
const CSkin *pSkin = m_pClient->m_Skins.Find(aSkinName);
pRenderInfo->m_OriginalRenderSkin = pSkin->m_OriginalSkin;
pRenderInfo->m_ColorableRenderSkin = pSkin->m_ColorableSkin;
pRenderInfo->m_BloodColor = pSkin->m_BloodColor;
pRenderInfo->m_SkinMetrics = pSkin->m_Metrics;
pRenderInfo->Apply(m_pClient->m_Skins.Find(aSkinName));
}
else
{

View file

@ -1822,12 +1822,8 @@ bool CMenus::PrintHighlighted(const char *pName, F &&PrintFn)
CTeeRenderInfo CMenus::GetTeeRenderInfo(vec2 Size, const char *pSkinName, bool CustomSkinColors, int CustomSkinColorBody, int CustomSkinColorFeet) const
{
const CSkin *pSkin = m_pClient->m_Skins.Find(pSkinName);
CTeeRenderInfo TeeInfo;
TeeInfo.m_OriginalRenderSkin = pSkin->m_OriginalSkin;
TeeInfo.m_ColorableRenderSkin = pSkin->m_ColorableSkin;
TeeInfo.m_SkinMetrics = pSkin->m_Metrics;
TeeInfo.Apply(m_pClient->m_Skins.Find(pSkinName));
TeeInfo.m_CustomColoredSkin = CustomSkinColors;
if(CustomSkinColors)
{

View file

@ -633,11 +633,8 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
// Note: get the skin info after the settings buttons, because they can trigger a refresh
// which invalidates the skin.
const CSkin *pSkin = m_pClient->m_Skins.Find(pSkinName);
CTeeRenderInfo OwnSkinInfo;
OwnSkinInfo.m_OriginalRenderSkin = pSkin->m_OriginalSkin;
OwnSkinInfo.m_ColorableRenderSkin = pSkin->m_ColorableSkin;
OwnSkinInfo.m_SkinMetrics = pSkin->m_Metrics;
OwnSkinInfo.Apply(m_pClient->m_Skins.Find(pSkinName));
OwnSkinInfo.m_CustomColoredSkin = *pUseCustomColor;
if(*pUseCustomColor)
{

View file

@ -844,10 +844,7 @@ void CPlayers::OnRender()
{
aRenderInfo[i].m_aSixup[g_Config.m_ClDummy].Reset();
aRenderInfo[i].m_OriginalRenderSkin = pSkin->m_OriginalSkin;
aRenderInfo[i].m_ColorableRenderSkin = pSkin->m_ColorableSkin;
aRenderInfo[i].m_BloodColor = pSkin->m_BloodColor;
aRenderInfo[i].m_SkinMetrics = pSkin->m_Metrics;
aRenderInfo[i].Apply(pSkin);
aRenderInfo[i].m_CustomColoredSkin = IsTeamplay;
if(!IsTeamplay)
{
@ -857,12 +854,8 @@ void CPlayers::OnRender()
}
}
}
const CSkin *pSkin = m_pClient->m_Skins.Find("x_spec");
CTeeRenderInfo RenderInfoSpec;
RenderInfoSpec.m_OriginalRenderSkin = pSkin->m_OriginalSkin;
RenderInfoSpec.m_ColorableRenderSkin = pSkin->m_ColorableSkin;
RenderInfoSpec.m_BloodColor = pSkin->m_BloodColor;
RenderInfoSpec.m_SkinMetrics = pSkin->m_Metrics;
RenderInfoSpec.Apply(m_pClient->m_Skins.Find("x_spec"));
RenderInfoSpec.m_CustomColoredSkin = false;
RenderInfoSpec.m_Size = 64.0f;
const int LocalClientId = m_pClient->m_Snap.m_LocalClientId;

View file

@ -102,7 +102,7 @@ void CStatboard::OnMessage(int MsgType, void *pRawMsg)
if(t <= p)
return;
str_utf8_truncate(aName, sizeof(aName), p, t - p);
str_truncate(aName, sizeof(aName), p, t - p);
for(int i = 0; i < MAX_CLIENTS; i++)
{

View file

@ -1554,11 +1554,7 @@ void CGameClient::OnNewSnapshot()
pClient->m_SkinInfo.m_Size = 64;
// find new skin
const CSkin *pSkin = m_Skins.Find(pClient->m_aSkinName);
pClient->m_SkinInfo.m_OriginalRenderSkin = pSkin->m_OriginalSkin;
pClient->m_SkinInfo.m_ColorableRenderSkin = pSkin->m_ColorableSkin;
pClient->m_SkinInfo.m_SkinMetrics = pSkin->m_Metrics;
pClient->m_SkinInfo.m_BloodColor = pSkin->m_BloodColor;
pClient->m_SkinInfo.Apply(m_Skins.Find(pClient->m_aSkinName));
pClient->m_SkinInfo.m_CustomColoredSkin = pClient->m_UseCustomColor;
if(!pClient->m_UseCustomColor)
@ -3750,13 +3746,9 @@ void CGameClient::RefreshSkins()
for(auto &Client : m_aClients)
{
Client.m_SkinInfo.m_OriginalRenderSkin.Reset();
Client.m_SkinInfo.m_ColorableRenderSkin.Reset();
if(Client.m_aSkinName[0] != '\0')
{
const CSkin *pSkin = m_Skins.Find(Client.m_aSkinName);
Client.m_SkinInfo.m_OriginalRenderSkin = pSkin->m_OriginalSkin;
Client.m_SkinInfo.m_ColorableRenderSkin = pSkin->m_ColorableSkin;
Client.m_SkinInfo.Apply(m_Skins.Find(Client.m_aSkinName));
}
else
{

View file

@ -56,6 +56,14 @@ public:
Sixup.Reset();
}
void Apply(const CSkin *pSkin)
{
m_OriginalRenderSkin = pSkin->m_OriginalSkin;
m_ColorableRenderSkin = pSkin->m_ColorableSkin;
m_BloodColor = pSkin->m_BloodColor;
m_SkinMetrics = pSkin->m_Metrics;
}
CSkin::SSkinTextures m_OriginalRenderSkin;
CSkin::SSkinTextures m_ColorableRenderSkin;

View file

@ -1300,6 +1300,8 @@ float CUi::DoScrollbarV(const void *pId, const CUIRect *pRect, float Current)
}
}
else if(HotItem() == pId)
{
if(InsideHandle)
{
if(MouseButton(0))
{
@ -1308,14 +1310,15 @@ float CUi::DoScrollbarV(const void *pId, const CUIRect *pRect, float Current)
Grabbed = true;
}
}
else if(MouseButtonClicked(0) && !InsideHandle && InsideRail)
else if(MouseButtonClicked(0))
{
SetActiveItem(pId);
m_ActiveScrollbarOffset = Handle.h / 2.0f;
Grabbed = true;
}
}
if(InsideHandle && !MouseButton(0))
if(InsideRail && !MouseButton(0))
{
SetHotItem(pId);
}
@ -1379,6 +1382,8 @@ float CUi::DoScrollbarH(const void *pId, const CUIRect *pRect, float Current, co
}
}
else if(HotItem() == pId)
{
if(InsideHandle)
{
if(MouseButton(0))
{
@ -1387,12 +1392,13 @@ float CUi::DoScrollbarH(const void *pId, const CUIRect *pRect, float Current, co
Grabbed = true;
}
}
else if(MouseButtonClicked(0) && !InsideHandle && InsideRail)
else if(MouseButtonClicked(0))
{
SetActiveItem(pId);
m_ActiveScrollbarOffset = Handle.w / 2.0f;
Grabbed = true;
}
}
if(!pColorInner && (InsideHandle || Grabbed) && (CheckActiveItem(pId) || HotItem() == pId))
{
@ -1400,7 +1406,7 @@ float CUi::DoScrollbarH(const void *pId, const CUIRect *pRect, float Current, co
Handle.y -= 1.5f;
}
if(InsideHandle && !MouseButton(0))
if(InsideRail && !MouseButton(0))
{
SetHotItem(pId);
}

View file

@ -376,6 +376,37 @@ void CGameContext::ConToggleSpec(IConsole::IResult *pResult, void *pUserData)
ToggleSpecPause(pResult, pUserData, g_Config.m_SvPauseable ? CPlayer::PAUSE_SPEC : CPlayer::PAUSE_PAUSED);
}
void CGameContext::ConUnspec(IConsole::IResult *pResult, void *pUserData)
{
if(!CheckClientId(pResult->m_ClientId))
return;
CGameContext *pSelf = (CGameContext *)pUserData;
CPlayer *pPlayer = pSelf->m_apPlayers[pResult->m_ClientId];
if(!pPlayer)
return;
int PauseState = pPlayer->IsPaused();
int PauseType = g_Config.m_SvPauseable ? CPlayer::PAUSE_SPEC : CPlayer::PAUSE_PAUSED;
if(PauseState > 0)
{
IServer *pServ = pSelf->Server();
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "You are force-paused for %d seconds.", (PauseState - pServ->Tick()) / pServ->TickSpeed());
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "chatresp", aBuf);
}
else
{
if(-PauseState != CPlayer::PAUSE_NONE && PauseType != CPlayer::PAUSE_NONE)
{
pPlayer->Pause(CPlayer::PAUSE_NONE, false);
if(pPlayer->m_SpectatorId != pResult->m_ClientId)
pPlayer->SpectateFreeView();
}
}
}
void CGameContext::ConToggleSpecVoted(IConsole::IResult *pResult, void *pUserData)
{
ToggleSpecPauseVoted(pResult, pUserData, g_Config.m_SvPauseable ? CPlayer::PAUSE_SPEC : CPlayer::PAUSE_PAUSED);

View file

@ -3747,6 +3747,7 @@ void CGameContext::RegisterChatCommands()
Console()->Register("converse", "r[message]", CFGFLAG_CHAT | CFGFLAG_SERVER | CFGFLAG_NONTEEHISTORIC, ConConverse, this, "Converse with the last person you whispered to (private message)");
Console()->Register("pause", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTogglePause, this, "Toggles pause");
Console()->Register("spec", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER, ConToggleSpec, this, "Toggles spec (if not available behaves as /pause)");
Console()->Register("unspec", "", CFGFLAG_CHAT | CFGFLAG_SERVER, ConUnspec, this, "Stops spectating the current player and returns to free view mode");
Console()->Register("pausevoted", "", CFGFLAG_CHAT | CFGFLAG_SERVER, ConTogglePauseVoted, this, "Toggles pause on the currently voted player");
Console()->Register("specvoted", "", CFGFLAG_CHAT | CFGFLAG_SERVER, ConToggleSpecVoted, this, "Toggles spec on the currently voted player");
Console()->Register("dnd", "?i['0'|'1']", CFGFLAG_CHAT | CFGFLAG_SERVER | CFGFLAG_NONTEEHISTORIC, ConDND, this, "Toggle Do Not Disturb (no chat and server messages)");

View file

@ -426,6 +426,7 @@ private:
static void ConTogglePause(IConsole::IResult *pResult, void *pUserData);
static void ConTogglePauseVoted(IConsole::IResult *pResult, void *pUserData);
static void ConToggleSpec(IConsole::IResult *pResult, void *pUserData);
static void ConUnspec(IConsole::IResult *pResult, void *pUserData);
static void ConToggleSpecVoted(IConsole::IResult *pResult, void *pUserData);
static void ConForcePause(IConsole::IResult *pResult, void *pUserData);
static void ConTeamTop5(IConsole::IResult *pResult, void *pUserData);

View file

@ -867,6 +867,12 @@ void CPlayer::SpectatePlayerName(const char *pName)
}
}
void CPlayer::SpectateFreeView()
{
if(m_SpectatorId >= 0)
m_SpectatorId = SPEC_FREEVIEW;
}
void CPlayer::ProcessScoreResult(CScorePlayerResult &Result)
{
if(Result.m_Success) // SQL request was successful

View file

@ -67,6 +67,7 @@ public:
const CCharacter *GetCharacter() const;
void SpectatePlayerName(const char *pName);
void SpectateFreeView();
//---------------------------------------------------------
// this is used for snapping so we know how we can clip the view for the player