2011-03-10 09:08:14 +00:00
|
|
|
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
|
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
2020-03-31 06:03:25 +00:00
|
|
|
|
2022-02-14 23:22:52 +00:00
|
|
|
#include <climits>
|
2020-03-31 06:03:25 +00:00
|
|
|
|
2011-03-10 09:08:14 +00:00
|
|
|
#include <engine/graphics.h>
|
|
|
|
#include <engine/shared/config.h>
|
2020-09-26 19:41:58 +00:00
|
|
|
#include <engine/textrender.h>
|
2011-03-10 09:08:14 +00:00
|
|
|
|
|
|
|
#include <game/generated/protocol.h>
|
|
|
|
|
|
|
|
#include <game/client/animstate.h>
|
|
|
|
#include <game/client/render.h>
|
2022-05-29 16:33:38 +00:00
|
|
|
#include <game/localization.h>
|
2011-03-10 09:08:14 +00:00
|
|
|
|
2020-04-01 05:52:44 +00:00
|
|
|
#include "camera.h"
|
2020-09-26 19:41:58 +00:00
|
|
|
#include "spectator.h"
|
2011-03-10 09:08:14 +00:00
|
|
|
|
2021-07-12 09:29:59 +00:00
|
|
|
#include <game/client/gameclient.h>
|
|
|
|
|
2020-09-26 20:01:12 +00:00
|
|
|
bool CSpectator::CanChangeSpectator()
|
2011-03-10 09:08:14 +00:00
|
|
|
{
|
2020-09-26 20:01:12 +00:00
|
|
|
// Don't change SpectatorID when not spectating
|
|
|
|
return m_pClient->m_Snap.m_SpecInfo.m_Active;
|
2011-03-10 09:08:14 +00:00
|
|
|
}
|
|
|
|
|
2020-09-26 20:01:12 +00:00
|
|
|
void CSpectator::SpectateNext(bool Reverse)
|
2011-03-10 09:08:14 +00:00
|
|
|
{
|
2020-09-26 20:01:12 +00:00
|
|
|
int CurIndex = -1;
|
2022-06-30 22:36:32 +00:00
|
|
|
const CNetObj_PlayerInfo **paPlayerInfos = m_pClient->m_Snap.m_apInfoByDDTeamName;
|
2011-03-10 09:08:14 +00:00
|
|
|
|
2020-09-26 20:01:12 +00:00
|
|
|
// m_SpectatorID may be uninitialized if m_Active is false
|
|
|
|
if(m_pClient->m_Snap.m_SpecInfo.m_Active)
|
2011-04-03 23:27:23 +00:00
|
|
|
{
|
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
2020-09-26 20:01:12 +00:00
|
|
|
if(paPlayerInfos[i] && paPlayerInfos[i]->m_ClientID == m_pClient->m_Snap.m_SpecInfo.m_SpectatorID)
|
|
|
|
{
|
|
|
|
CurIndex = i;
|
|
|
|
break;
|
|
|
|
}
|
2011-04-03 23:27:23 +00:00
|
|
|
}
|
|
|
|
}
|
2020-09-26 20:01:12 +00:00
|
|
|
|
|
|
|
int Start;
|
|
|
|
if(CurIndex != -1)
|
|
|
|
{
|
|
|
|
if(Reverse)
|
|
|
|
Start = CurIndex - 1;
|
|
|
|
else
|
|
|
|
Start = CurIndex + 1;
|
|
|
|
}
|
2011-04-03 23:27:23 +00:00
|
|
|
else
|
|
|
|
{
|
2020-09-26 20:01:12 +00:00
|
|
|
if(Reverse)
|
|
|
|
Start = -1;
|
|
|
|
else
|
|
|
|
Start = 0;
|
|
|
|
}
|
2011-04-03 23:27:23 +00:00
|
|
|
|
2020-09-26 20:01:12 +00:00
|
|
|
int Increment = Reverse ? -1 : 1;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-09-26 20:01:12 +00:00
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
|
|
|
int PlayerIndex = (Start + i * Increment) % MAX_CLIENTS;
|
|
|
|
// % in C++ takes the sign of the dividend, not divisor
|
|
|
|
if(PlayerIndex < 0)
|
|
|
|
PlayerIndex += MAX_CLIENTS;
|
2011-04-03 23:27:23 +00:00
|
|
|
|
2020-09-26 20:01:12 +00:00
|
|
|
const CNetObj_PlayerInfo *pPlayerInfo = paPlayerInfos[PlayerIndex];
|
|
|
|
if(pPlayerInfo && pPlayerInfo->m_Team != TEAM_SPECTATORS)
|
|
|
|
{
|
|
|
|
Spectate(pPlayerInfo->m_ClientID);
|
|
|
|
break;
|
2011-04-03 23:27:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-26 20:01:12 +00:00
|
|
|
void CSpectator::ConKeySpectator(IConsole::IResult *pResult, void *pUserData)
|
2011-04-03 23:27:23 +00:00
|
|
|
{
|
|
|
|
CSpectator *pSelf = (CSpectator *)pUserData;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-09-26 20:01:12 +00:00
|
|
|
if(pSelf->m_pClient->m_Snap.m_SpecInfo.m_Active || pSelf->Client()->State() == IClient::STATE_DEMOPLAYBACK)
|
|
|
|
pSelf->m_Active = pResult->GetInteger(0) != 0;
|
|
|
|
else
|
|
|
|
pSelf->m_Active = false;
|
|
|
|
}
|
2014-04-24 12:59:16 +00:00
|
|
|
|
2020-09-26 20:01:12 +00:00
|
|
|
void CSpectator::ConSpectate(IConsole::IResult *pResult, void *pUserData)
|
|
|
|
{
|
|
|
|
CSpectator *pSelf = (CSpectator *)pUserData;
|
|
|
|
if(!pSelf->CanChangeSpectator())
|
|
|
|
return;
|
2011-04-03 23:27:23 +00:00
|
|
|
|
2020-09-26 20:01:12 +00:00
|
|
|
pSelf->Spectate(pResult->GetInteger(0));
|
|
|
|
}
|
2011-04-03 23:27:23 +00:00
|
|
|
|
2020-09-26 20:01:12 +00:00
|
|
|
void CSpectator::ConSpectateNext(IConsole::IResult *pResult, void *pUserData)
|
|
|
|
{
|
|
|
|
CSpectator *pSelf = (CSpectator *)pUserData;
|
|
|
|
if(!pSelf->CanChangeSpectator())
|
|
|
|
return;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-09-26 20:01:12 +00:00
|
|
|
pSelf->SpectateNext(false);
|
|
|
|
}
|
2011-04-03 23:27:23 +00:00
|
|
|
|
2020-09-26 20:01:12 +00:00
|
|
|
void CSpectator::ConSpectatePrevious(IConsole::IResult *pResult, void *pUserData)
|
|
|
|
{
|
|
|
|
CSpectator *pSelf = (CSpectator *)pUserData;
|
|
|
|
if(!pSelf->CanChangeSpectator())
|
|
|
|
return;
|
|
|
|
|
|
|
|
pSelf->SpectateNext(true);
|
2011-04-03 23:27:23 +00:00
|
|
|
}
|
|
|
|
|
2020-03-31 06:03:25 +00:00
|
|
|
void CSpectator::ConSpectateClosest(IConsole::IResult *pResult, void *pUserData)
|
|
|
|
{
|
|
|
|
CSpectator *pSelf = (CSpectator *)pUserData;
|
2020-09-26 20:01:12 +00:00
|
|
|
if(!pSelf->CanChangeSpectator())
|
|
|
|
return;
|
|
|
|
|
Declare variables as `const` when possible
According to cppcheck's `constVariable` error:
```
src\engine\client\backend\opengl\opengl_sl.cpp:74:43: style: Variable 'Define' can be declared as reference to const [constVariable]
for(CGLSLCompiler::SGLSLCompilerDefine &Define : pCompiler->m_vDefines)
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:2149:12: style: Variable 'GraphicThreadCommandBuffer' can be declared as reference to const [constVariable]
auto &GraphicThreadCommandBuffer = m_vvThreadDrawCommandBuffers[i + 1][m_CurImageIndex];
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:3192:9: style: Variable 'BufferObject' can be declared as reference to const [constVariable]
auto &BufferObject = m_vBufferObjects[BufferObjectIndex];
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:3200:10: style: Variable 'DescrSet' can be declared as reference to const [constVariable]
auto &DescrSet = m_vTextures[State.m_Texture].m_VKStandard3DTexturedDescrSet;
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:3810:13: style: Variable 'Mode' can be declared as reference to const [constVariable]
for(auto &Mode : vPresentModeList)
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:3818:13: style: Variable 'Mode' can be declared as reference to const [constVariable]
for(auto &Mode : vPresentModeList)
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6511:10: style: Variable 'DescrSet' can be declared as reference to const [constVariable]
auto &DescrSet = m_vTextures[pCommand->m_State.m_Texture].m_aVKStandardTexturedDescrSets[AddressModeIndex];
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6555:10: style: Variable 'DescrSet' can be declared as reference to const [constVariable]
auto &DescrSet = m_vTextures[pCommand->m_State.m_Texture].m_VKStandard3DTexturedDescrSet;
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6660:9: style: Variable 'MemBlock' can be declared as reference to const [constVariable]
auto &MemBlock = m_vBufferObjects[BufferIndex].m_BufferObject.m_Mem;
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6799:9: style: Variable 'BufferObject' can be declared as reference to const [constVariable]
auto &BufferObject = m_vBufferObjects[BufferObjectIndex];
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6808:10: style: Variable 'DescrSet' can be declared as reference to const [constVariable]
auto &DescrSet = m_vTextures[pCommand->m_State.m_Texture].m_aVKStandardTexturedDescrSets[AddressModeIndex];
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6902:9: style: Variable 'BufferObject' can be declared as reference to const [constVariable]
auto &BufferObject = m_vBufferObjects[BufferObjectIndex];
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6907:9: style: Variable 'TextTextureDescr' can be declared as reference to const [constVariable]
auto &TextTextureDescr = m_vTextures[pCommand->m_TextTextureIndex].m_VKTextDescrSet;
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6961:9: style: Variable 'BufferObject' can be declared as reference to const [constVariable]
auto &BufferObject = m_vBufferObjects[BufferObjectIndex];
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6970:10: style: Variable 'DescrSet' can be declared as reference to const [constVariable]
auto &DescrSet = m_vTextures[State.m_Texture].m_aVKStandardTexturedDescrSets[AddressModeIndex];
^
src\game\client\components\hud.cpp:178:8: style: Variable 'aFlagCarrier' can be declared as const array [constVariable]
int aFlagCarrier[2] = {
^
src\game\client\components\hud.cpp:519:16: style: Variable 's_aTextWidth' can be declared as const array [constVariable]
static float s_aTextWidth[5] = {s_TextWidth0, s_TextWidth00, s_TextWidth000, s_TextWidth0000, s_TextWidth00000};
^
src\game\client\components\killmessages.cpp:305:30: style: Variable 'Client' can be declared as reference to const [constVariable]
CGameClient::CClientData &Client = GameClient()->m_aClients[m_aKillmsgs[r].m_KillerID];
^
src\game\client\components\killmessages.cpp:314:30: style: Variable 'Client' can be declared as reference to const [constVariable]
CGameClient::CClientData &Client = GameClient()->m_aClients[m_aKillmsgs[r].m_VictimID];
^
src\game\client\components\menus_ingame.cpp:243:12: style: Variable 'pInfoByName' can be declared as reference to const [constVariable]
for(auto &pInfoByName : m_pClient->m_Snap.m_apInfoByName)
^
src\game\client\components\menus_ingame.cpp:530:12: style: Variable 'pInfoByName' can be declared as reference to const [constVariable]
for(auto &pInfoByName : m_pClient->m_Snap.m_apInfoByName)
^
src\game\client\components\players.cpp:767:44: style: Variable 'CharacterInfo' can be declared as reference to const [constVariable]
CGameClient::CSnapState::CCharacterInfo &CharacterInfo = m_pClient->m_Snap.m_aCharacters[i];
^
src\game\client\components\spectator.cpp:122:27: style: Variable 'Snap' can be declared as reference to const [constVariable]
CGameClient::CSnapState &Snap = pSelf->m_pClient->m_Snap;
^
src\game\client\components\spectator.cpp:221:12: style: Variable 'pInfo' can be declared as reference to const [constVariable]
for(auto &pInfo : m_pClient->m_Snap.m_apInfoByDDTeamName)
^
src\game\client\gameclient.cpp:2220:15: style: Variable 'OwnClientData' can be declared as reference to const [constVariable]
CClientData &OwnClientData = m_aClients[ownID];
^
src\game\client\gameclient.cpp:2227:16: style: Variable 'cData' can be declared as reference to const [constVariable]
CClientData &cData = m_aClients[i];
^
src\game\client\prediction\entities\character.cpp:397:11: style: Variable 'aSpreading' can be declared as const array [constVariable]
float aSpreading[] = {-0.185f, -0.070f, 0, 0.070f, 0.185f};
^
src\game\client\prediction\entities\laser.cpp:53:9: style: Variable 'HitPos' can be declared as reference to const [constVariable]
vec2 &HitPos = pHit->Core()->m_Pos;
^
src\game\editor\auto_map.cpp:507:18: style: Variable 'Index' can be declared as reference to const [constVariable]
for(auto &Index : pRule->m_vIndexList)
^
src\game\editor\auto_map.cpp:518:18: style: Variable 'Index' can be declared as reference to const [constVariable]
for(auto &Index : pRule->m_vIndexList)
^
src\game\editor\editor.cpp:118:12: style: Variable 'Item' can be declared as reference to const [constVariable]
for(auto &Item : vList)
^
src\game\editor\editor.cpp:2983:11: style: Variable 'aAspects' can be declared as const array [constVariable]
float aAspects[] = {4.0f / 3.0f, 16.0f / 10.0f, 5.0f / 4.0f, 16.0f / 9.0f};
^
src\game\editor\editor.cpp:3141:15: style: Variable 's_aShift' can be declared as const array [constVariable]
static int s_aShift[] = {24, 16, 8, 0};
^
src\engine\server\server.cpp:2807:14: style: Variable 'Client' can be declared as reference to const [constVariable]
for(auto &Client : m_aClients)
^
src\engine\server\sql_string_helpers.cpp:51:6: style: Variable 'aTimes' can be declared as const array [constVariable]
int aTimes[7] =
^
src\test\secure_random.cpp:24:6: style: Variable 'BOUNDS' can be declared as const array [constVariable]
int BOUNDS[] = {2, 3, 4, 5, 10, 100, 127, 128, 129};
^
```
2022-11-13 15:29:13 +00:00
|
|
|
const CGameClient::CSnapState &Snap = pSelf->m_pClient->m_Snap;
|
2020-09-26 20:01:12 +00:00
|
|
|
int SpectatorID = Snap.m_SpecInfo.m_SpectatorID;
|
|
|
|
|
2020-03-31 06:03:25 +00:00
|
|
|
int NewSpectatorID = -1;
|
|
|
|
|
2021-07-12 09:43:56 +00:00
|
|
|
vec2 CurPosition(pSelf->m_pClient->m_Camera.m_Center);
|
2020-09-26 20:01:12 +00:00
|
|
|
if(SpectatorID != SPEC_FREEVIEW)
|
2020-03-31 06:03:25 +00:00
|
|
|
{
|
2020-09-26 20:01:12 +00:00
|
|
|
const CNetObj_Character &CurCharacter = Snap.m_aCharacters[SpectatorID].m_Cur;
|
|
|
|
CurPosition.x = CurCharacter.m_X;
|
|
|
|
CurPosition.y = CurCharacter.m_Y;
|
2020-03-31 06:03:25 +00:00
|
|
|
}
|
2020-09-26 20:01:12 +00:00
|
|
|
|
2020-04-01 05:52:44 +00:00
|
|
|
int ClosestDistance = INT_MAX;
|
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
2020-03-31 06:03:25 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
if(i == SpectatorID || !Snap.m_apPlayerInfos[i] || Snap.m_apPlayerInfos[i]->m_Team == TEAM_SPECTATORS || (SpectatorID == SPEC_FREEVIEW && i == Snap.m_LocalClientID))
|
2020-04-01 05:52:44 +00:00
|
|
|
continue;
|
2020-09-26 20:01:12 +00:00
|
|
|
const CNetObj_Character &MaybeClosestCharacter = Snap.m_aCharacters[i].m_Cur;
|
2020-04-01 05:52:44 +00:00
|
|
|
int Distance = distance(CurPosition, vec2(MaybeClosestCharacter.m_X, MaybeClosestCharacter.m_Y));
|
|
|
|
if(NewSpectatorID == -1 || Distance < ClosestDistance)
|
2020-03-31 06:03:25 +00:00
|
|
|
{
|
2020-09-26 20:01:12 +00:00
|
|
|
NewSpectatorID = i;
|
2020-04-01 05:52:44 +00:00
|
|
|
ClosestDistance = Distance;
|
2020-03-31 06:03:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(NewSpectatorID > -1)
|
|
|
|
pSelf->Spectate(NewSpectatorID);
|
|
|
|
}
|
|
|
|
|
2023-05-24 17:29:38 +00:00
|
|
|
void CSpectator::ConMultiView(IConsole::IResult *pResult, void *pUserData)
|
|
|
|
{
|
|
|
|
CSpectator *pSelf = (CSpectator *)pUserData;
|
|
|
|
int Input = pResult->GetInteger(0);
|
|
|
|
|
|
|
|
if(Input == -1)
|
|
|
|
std::fill(std::begin(pSelf->GameClient()->m_aMultiViewId), std::end(pSelf->GameClient()->m_aMultiViewId), false); // remove everyone from multiview
|
|
|
|
else if(Input < MAX_CLIENTS && Input >= 0)
|
|
|
|
pSelf->GameClient()->m_aMultiViewId[Input] = !pSelf->GameClient()->m_aMultiViewId[Input]; // activate or deactivate one player from multiview
|
|
|
|
}
|
|
|
|
|
2011-03-10 09:08:14 +00:00
|
|
|
CSpectator::CSpectator()
|
|
|
|
{
|
|
|
|
OnReset();
|
2021-10-23 11:48:21 +00:00
|
|
|
m_OldMouseX = m_OldMouseY = 0.0f;
|
2011-03-10 09:08:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CSpectator::OnConsoleInit()
|
|
|
|
{
|
2011-08-13 00:11:06 +00:00
|
|
|
Console()->Register("+spectate", "", CFGFLAG_CLIENT, ConKeySpectator, this, "Open spectator mode selector");
|
2015-12-28 15:14:52 +00:00
|
|
|
Console()->Register("spectate", "i[spectator-id]", CFGFLAG_CLIENT, ConSpectate, this, "Switch spectator mode");
|
2011-08-13 00:11:06 +00:00
|
|
|
Console()->Register("spectate_next", "", CFGFLAG_CLIENT, ConSpectateNext, this, "Spectate the next player");
|
|
|
|
Console()->Register("spectate_previous", "", CFGFLAG_CLIENT, ConSpectatePrevious, this, "Spectate the previous player");
|
2020-03-31 06:03:25 +00:00
|
|
|
Console()->Register("spectate_closest", "", CFGFLAG_CLIENT, ConSpectateClosest, this, "Spectate the closest player");
|
2023-05-24 17:29:38 +00:00
|
|
|
Console()->Register("spectate_multiview", "i[id]", CFGFLAG_CLIENT, ConMultiView, this, "Add/remove Client-IDs to spectate them exclusivly (-1 to reset)");
|
2011-03-10 09:08:14 +00:00
|
|
|
}
|
|
|
|
|
2022-06-06 20:03:24 +00:00
|
|
|
bool CSpectator::OnCursorMove(float x, float y, IInput::ECursorType CursorType)
|
2011-03-10 09:08:14 +00:00
|
|
|
{
|
|
|
|
if(!m_Active)
|
2021-10-23 11:48:21 +00:00
|
|
|
return false;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-06-06 20:03:24 +00:00
|
|
|
UI()->ConvertMouseMove(&x, &y, CursorType);
|
2021-10-23 11:48:21 +00:00
|
|
|
m_SelectorMouse += vec2(x, y);
|
|
|
|
return true;
|
2011-03-10 09:08:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CSpectator::OnRelease()
|
|
|
|
{
|
|
|
|
OnReset();
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2011-03-10 09:08:14 +00:00
|
|
|
void CSpectator::OnRender()
|
|
|
|
{
|
2023-07-09 13:53:57 +00:00
|
|
|
if(!GameClient()->m_MultiViewActivated && m_MultiViewActivateDelay != 0.0f)
|
|
|
|
{
|
|
|
|
if(m_MultiViewActivateDelay <= Client()->LocalTime())
|
|
|
|
{
|
|
|
|
m_MultiViewActivateDelay = 0.0f;
|
|
|
|
GameClient()->m_MultiViewActivated = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-10 09:08:14 +00:00
|
|
|
if(!m_Active)
|
|
|
|
{
|
2023-07-09 13:53:57 +00:00
|
|
|
// closing the spectator menu
|
2011-03-10 09:08:14 +00:00
|
|
|
if(m_WasActive)
|
|
|
|
{
|
|
|
|
if(m_SelectedSpectatorID != NO_SELECTION)
|
2023-05-24 17:29:38 +00:00
|
|
|
{
|
2023-07-09 13:53:57 +00:00
|
|
|
if(m_SelectedSpectatorID == MULTI_VIEW)
|
|
|
|
GameClient()->m_MultiViewActivated = true;
|
|
|
|
else if(m_SelectedSpectatorID == SPEC_FREEVIEW || m_SelectedSpectatorID == SPEC_FOLLOW)
|
|
|
|
GameClient()->m_MultiViewActivated = false;
|
|
|
|
|
|
|
|
if(!GameClient()->m_MultiViewActivated)
|
2023-05-24 17:29:38 +00:00
|
|
|
Spectate(m_SelectedSpectatorID);
|
|
|
|
|
2023-07-15 11:32:43 +00:00
|
|
|
if(GameClient()->m_MultiViewActivated && m_SelectedSpectatorID != MULTI_VIEW && m_pClient->m_Teams.Team(m_SelectedSpectatorID) != GameClient()->m_MultiViewTeam)
|
2023-07-09 13:53:57 +00:00
|
|
|
{
|
|
|
|
GameClient()->ResetMultiView();
|
|
|
|
Spectate(m_SelectedSpectatorID);
|
|
|
|
m_MultiViewActivateDelay = Client()->LocalTime() + 0.3f;
|
|
|
|
}
|
2023-05-24 17:29:38 +00:00
|
|
|
}
|
2011-03-12 17:07:57 +00:00
|
|
|
m_WasActive = false;
|
2011-03-10 09:08:14 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2023-07-09 13:53:57 +00:00
|
|
|
if(m_SelectedSpectatorID != NO_SELECTION)
|
|
|
|
{
|
|
|
|
// clicking a component
|
|
|
|
if(m_Clicked)
|
|
|
|
{
|
|
|
|
if(!GameClient()->m_MultiViewActivated)
|
|
|
|
Spectate(m_SelectedSpectatorID);
|
|
|
|
|
|
|
|
if(m_SelectedSpectatorID == MULTI_VIEW)
|
|
|
|
GameClient()->m_MultiViewActivated = true;
|
|
|
|
else if(m_SelectedSpectatorID == SPEC_FREEVIEW || m_SelectedSpectatorID == SPEC_FOLLOW)
|
|
|
|
GameClient()->m_MultiViewActivated = false;
|
|
|
|
|
|
|
|
if(!GameClient()->m_MultiViewActivated && m_SelectedSpectatorID >= 0 && m_SelectedSpectatorID < MAX_CLIENTS)
|
|
|
|
m_Clicked = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-04 09:22:19 +00:00
|
|
|
if(!m_pClient->m_Snap.m_SpecInfo.m_Active && Client()->State() != IClient::STATE_DEMOPLAYBACK)
|
2011-07-11 10:02:45 +00:00
|
|
|
{
|
|
|
|
m_Active = false;
|
|
|
|
m_WasActive = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-03-10 09:08:14 +00:00
|
|
|
m_WasActive = true;
|
|
|
|
m_SelectedSpectatorID = NO_SELECTION;
|
|
|
|
|
|
|
|
// draw background
|
2020-09-26 19:41:58 +00:00
|
|
|
float Width = 400 * 3.0f * Graphics()->ScreenAspect();
|
|
|
|
float Height = 400 * 3.0f;
|
2014-01-12 18:38:22 +00:00
|
|
|
float ObjWidth = 300.0f;
|
|
|
|
float FontSize = 20.0f;
|
|
|
|
float BigFontSize = 20.0f;
|
|
|
|
float StartY = -190.0f;
|
|
|
|
float LineHeight = 60.0f;
|
|
|
|
float TeeSizeMod = 1.0f;
|
|
|
|
float RoundRadius = 30.0f;
|
|
|
|
bool Selected = false;
|
2023-05-24 17:29:38 +00:00
|
|
|
bool MultiViewSelected = false;
|
2014-01-12 18:38:22 +00:00
|
|
|
int TotalPlayers = 0;
|
|
|
|
int PerLine = 8;
|
|
|
|
float BoxMove = -10.0f;
|
2020-10-09 19:14:54 +00:00
|
|
|
float BoxOffset = 0.0f;
|
2014-01-12 18:38:22 +00:00
|
|
|
|
Declare variables as `const` when possible
According to cppcheck's `constVariable` error:
```
src\engine\client\backend\opengl\opengl_sl.cpp:74:43: style: Variable 'Define' can be declared as reference to const [constVariable]
for(CGLSLCompiler::SGLSLCompilerDefine &Define : pCompiler->m_vDefines)
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:2149:12: style: Variable 'GraphicThreadCommandBuffer' can be declared as reference to const [constVariable]
auto &GraphicThreadCommandBuffer = m_vvThreadDrawCommandBuffers[i + 1][m_CurImageIndex];
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:3192:9: style: Variable 'BufferObject' can be declared as reference to const [constVariable]
auto &BufferObject = m_vBufferObjects[BufferObjectIndex];
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:3200:10: style: Variable 'DescrSet' can be declared as reference to const [constVariable]
auto &DescrSet = m_vTextures[State.m_Texture].m_VKStandard3DTexturedDescrSet;
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:3810:13: style: Variable 'Mode' can be declared as reference to const [constVariable]
for(auto &Mode : vPresentModeList)
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:3818:13: style: Variable 'Mode' can be declared as reference to const [constVariable]
for(auto &Mode : vPresentModeList)
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6511:10: style: Variable 'DescrSet' can be declared as reference to const [constVariable]
auto &DescrSet = m_vTextures[pCommand->m_State.m_Texture].m_aVKStandardTexturedDescrSets[AddressModeIndex];
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6555:10: style: Variable 'DescrSet' can be declared as reference to const [constVariable]
auto &DescrSet = m_vTextures[pCommand->m_State.m_Texture].m_VKStandard3DTexturedDescrSet;
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6660:9: style: Variable 'MemBlock' can be declared as reference to const [constVariable]
auto &MemBlock = m_vBufferObjects[BufferIndex].m_BufferObject.m_Mem;
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6799:9: style: Variable 'BufferObject' can be declared as reference to const [constVariable]
auto &BufferObject = m_vBufferObjects[BufferObjectIndex];
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6808:10: style: Variable 'DescrSet' can be declared as reference to const [constVariable]
auto &DescrSet = m_vTextures[pCommand->m_State.m_Texture].m_aVKStandardTexturedDescrSets[AddressModeIndex];
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6902:9: style: Variable 'BufferObject' can be declared as reference to const [constVariable]
auto &BufferObject = m_vBufferObjects[BufferObjectIndex];
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6907:9: style: Variable 'TextTextureDescr' can be declared as reference to const [constVariable]
auto &TextTextureDescr = m_vTextures[pCommand->m_TextTextureIndex].m_VKTextDescrSet;
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6961:9: style: Variable 'BufferObject' can be declared as reference to const [constVariable]
auto &BufferObject = m_vBufferObjects[BufferObjectIndex];
^
src\engine\client\backend\vulkan\backend_vulkan.cpp:6970:10: style: Variable 'DescrSet' can be declared as reference to const [constVariable]
auto &DescrSet = m_vTextures[State.m_Texture].m_aVKStandardTexturedDescrSets[AddressModeIndex];
^
src\game\client\components\hud.cpp:178:8: style: Variable 'aFlagCarrier' can be declared as const array [constVariable]
int aFlagCarrier[2] = {
^
src\game\client\components\hud.cpp:519:16: style: Variable 's_aTextWidth' can be declared as const array [constVariable]
static float s_aTextWidth[5] = {s_TextWidth0, s_TextWidth00, s_TextWidth000, s_TextWidth0000, s_TextWidth00000};
^
src\game\client\components\killmessages.cpp:305:30: style: Variable 'Client' can be declared as reference to const [constVariable]
CGameClient::CClientData &Client = GameClient()->m_aClients[m_aKillmsgs[r].m_KillerID];
^
src\game\client\components\killmessages.cpp:314:30: style: Variable 'Client' can be declared as reference to const [constVariable]
CGameClient::CClientData &Client = GameClient()->m_aClients[m_aKillmsgs[r].m_VictimID];
^
src\game\client\components\menus_ingame.cpp:243:12: style: Variable 'pInfoByName' can be declared as reference to const [constVariable]
for(auto &pInfoByName : m_pClient->m_Snap.m_apInfoByName)
^
src\game\client\components\menus_ingame.cpp:530:12: style: Variable 'pInfoByName' can be declared as reference to const [constVariable]
for(auto &pInfoByName : m_pClient->m_Snap.m_apInfoByName)
^
src\game\client\components\players.cpp:767:44: style: Variable 'CharacterInfo' can be declared as reference to const [constVariable]
CGameClient::CSnapState::CCharacterInfo &CharacterInfo = m_pClient->m_Snap.m_aCharacters[i];
^
src\game\client\components\spectator.cpp:122:27: style: Variable 'Snap' can be declared as reference to const [constVariable]
CGameClient::CSnapState &Snap = pSelf->m_pClient->m_Snap;
^
src\game\client\components\spectator.cpp:221:12: style: Variable 'pInfo' can be declared as reference to const [constVariable]
for(auto &pInfo : m_pClient->m_Snap.m_apInfoByDDTeamName)
^
src\game\client\gameclient.cpp:2220:15: style: Variable 'OwnClientData' can be declared as reference to const [constVariable]
CClientData &OwnClientData = m_aClients[ownID];
^
src\game\client\gameclient.cpp:2227:16: style: Variable 'cData' can be declared as reference to const [constVariable]
CClientData &cData = m_aClients[i];
^
src\game\client\prediction\entities\character.cpp:397:11: style: Variable 'aSpreading' can be declared as const array [constVariable]
float aSpreading[] = {-0.185f, -0.070f, 0, 0.070f, 0.185f};
^
src\game\client\prediction\entities\laser.cpp:53:9: style: Variable 'HitPos' can be declared as reference to const [constVariable]
vec2 &HitPos = pHit->Core()->m_Pos;
^
src\game\editor\auto_map.cpp:507:18: style: Variable 'Index' can be declared as reference to const [constVariable]
for(auto &Index : pRule->m_vIndexList)
^
src\game\editor\auto_map.cpp:518:18: style: Variable 'Index' can be declared as reference to const [constVariable]
for(auto &Index : pRule->m_vIndexList)
^
src\game\editor\editor.cpp:118:12: style: Variable 'Item' can be declared as reference to const [constVariable]
for(auto &Item : vList)
^
src\game\editor\editor.cpp:2983:11: style: Variable 'aAspects' can be declared as const array [constVariable]
float aAspects[] = {4.0f / 3.0f, 16.0f / 10.0f, 5.0f / 4.0f, 16.0f / 9.0f};
^
src\game\editor\editor.cpp:3141:15: style: Variable 's_aShift' can be declared as const array [constVariable]
static int s_aShift[] = {24, 16, 8, 0};
^
src\engine\server\server.cpp:2807:14: style: Variable 'Client' can be declared as reference to const [constVariable]
for(auto &Client : m_aClients)
^
src\engine\server\sql_string_helpers.cpp:51:6: style: Variable 'aTimes' can be declared as const array [constVariable]
int aTimes[7] =
^
src\test\secure_random.cpp:24:6: style: Variable 'BOUNDS' can be declared as const array [constVariable]
int BOUNDS[] = {2, 3, 4, 5, 10, 100, 127, 128, 129};
^
```
2022-11-13 15:29:13 +00:00
|
|
|
for(const auto &pInfo : m_pClient->m_Snap.m_apInfoByDDTeamName)
|
2014-01-12 18:38:22 +00:00
|
|
|
{
|
2020-10-26 14:14:07 +00:00
|
|
|
if(!pInfo || pInfo->m_Team == TEAM_SPECTATORS)
|
2014-01-12 18:38:22 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
++TotalPlayers;
|
|
|
|
}
|
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
if(TotalPlayers > 32)
|
2014-01-12 18:38:22 +00:00
|
|
|
{
|
|
|
|
FontSize = 18.0f;
|
|
|
|
LineHeight = 30.0f;
|
|
|
|
TeeSizeMod = 0.7f;
|
|
|
|
PerLine = 16;
|
|
|
|
RoundRadius = 10.0f;
|
|
|
|
BoxMove = 3.0f;
|
2020-10-09 19:14:54 +00:00
|
|
|
BoxOffset = 6.0f;
|
2014-01-12 18:38:22 +00:00
|
|
|
}
|
2020-09-26 19:41:58 +00:00
|
|
|
if(TotalPlayers > 16)
|
2014-01-12 18:38:22 +00:00
|
|
|
{
|
|
|
|
ObjWidth = 600.0f;
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2011-03-10 09:08:14 +00:00
|
|
|
Graphics()->MapScreen(0, 0, Width, Height);
|
|
|
|
|
2022-07-09 20:27:35 +00:00
|
|
|
Graphics()->DrawRect(Width / 2.0f - ObjWidth, Height / 2.0f - 300.0f, ObjWidth * 2, 600.0f, ColorRGBA(0.0f, 0.0f, 0.0f, 0.3f), IGraphics::CORNER_ALL, 20.0f);
|
2011-03-10 09:08:14 +00:00
|
|
|
|
|
|
|
// clamp mouse position to selector area
|
2014-01-12 18:38:22 +00:00
|
|
|
m_SelectorMouse.x = clamp(m_SelectorMouse.x, -(ObjWidth - 20.0f), ObjWidth - 20.0f);
|
2011-03-10 09:08:14 +00:00
|
|
|
m_SelectorMouse.y = clamp(m_SelectorMouse.y, -280.0f, 280.0f);
|
|
|
|
|
|
|
|
// draw selections
|
2015-07-26 16:21:51 +00:00
|
|
|
if((Client()->State() == IClient::STATE_DEMOPLAYBACK && m_pClient->m_DemoSpecID == SPEC_FREEVIEW) ||
|
2022-08-27 15:41:46 +00:00
|
|
|
(Client()->State() != IClient::STATE_DEMOPLAYBACK && m_pClient->m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW))
|
2011-03-10 09:08:14 +00:00
|
|
|
{
|
2023-05-24 17:29:38 +00:00
|
|
|
Graphics()->DrawRect(Width / 2.0f - (ObjWidth - 20.0f), Height / 2.0f - 280.0f, ((ObjWidth * 2.0f) / 3.0f) - 40.0f, 60.0f, ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f), IGraphics::CORNER_ALL, 20.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(GameClient()->m_MultiViewActivated)
|
|
|
|
{
|
|
|
|
Graphics()->DrawRect(Width / 2.0f - (ObjWidth - 20.0f) + (ObjWidth * 2.0f / 3.0f), Height / 2.0f - 280.0f, ((ObjWidth * 2.0f) / 3.0f) - 40.0f, 60.0f, ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f), IGraphics::CORNER_ALL, 20.0f);
|
2011-03-10 09:08:14 +00:00
|
|
|
}
|
|
|
|
|
2022-08-27 15:38:50 +00:00
|
|
|
if(Client()->State() == IClient::STATE_DEMOPLAYBACK && m_pClient->m_Snap.m_LocalClientID >= 0 && m_pClient->m_DemoSpecID == SPEC_FOLLOW)
|
2015-07-26 16:21:51 +00:00
|
|
|
{
|
2023-05-24 17:29:38 +00:00
|
|
|
Graphics()->DrawRect(Width / 2.0f - (ObjWidth - 20.0f) + (ObjWidth * 2.0f * 2.0f / 3.0f), Height / 2.0f - 280.0f, ((ObjWidth * 2.0f) / 3.0f) - 40.0f, 60.0f, ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f), IGraphics::CORNER_ALL, 20.0f);
|
2015-07-26 16:21:51 +00:00
|
|
|
}
|
|
|
|
|
2023-05-24 17:29:38 +00:00
|
|
|
if(m_SelectorMouse.x >= -(ObjWidth - 20.0f) && m_SelectorMouse.x <= -(ObjWidth - 20.0f) + ((ObjWidth * 2.0f) / 3.0f) - 40.0f &&
|
2011-03-10 09:08:14 +00:00
|
|
|
m_SelectorMouse.y >= -280.0f && m_SelectorMouse.y <= -220.0f)
|
|
|
|
{
|
|
|
|
m_SelectedSpectatorID = SPEC_FREEVIEW;
|
|
|
|
Selected = true;
|
|
|
|
}
|
2020-09-26 19:41:58 +00:00
|
|
|
TextRender()->TextColor(1.0f, 1.0f, 1.0f, Selected ? 1.0f : 0.5f);
|
2023-05-24 17:29:38 +00:00
|
|
|
TextRender()->Text(Width / 2.0f - (ObjWidth - 40.0f), Height / 2.0f - 280.f + (60.f - BigFontSize) / 2.f, BigFontSize, Localize("Free-View"), -1.0f);
|
|
|
|
|
|
|
|
if(m_SelectorMouse.x >= -(ObjWidth - 20.0f) + (ObjWidth * 2.0f / 3.0f) && m_SelectorMouse.x <= -(ObjWidth - 20.0f) + (ObjWidth * 2.0f / 3.0f) + ((ObjWidth * 2.0f) / 3.0f) - 40.0f &&
|
|
|
|
m_SelectorMouse.y >= -280.0f && m_SelectorMouse.y <= -220.0f)
|
|
|
|
{
|
|
|
|
m_SelectedSpectatorID = MULTI_VIEW;
|
|
|
|
MultiViewSelected = true;
|
|
|
|
}
|
|
|
|
TextRender()->TextColor(1.0f, 1.0f, 1.0f, MultiViewSelected ? 1.0f : 0.5f);
|
|
|
|
TextRender()->Text(Width / 2.0f - (ObjWidth - 40.0f) + (ObjWidth * 2.0f / 3.0f), Height / 2.0f - 280.f + (60.f - BigFontSize) / 2.f, BigFontSize, Localize("Multi-View"), -1.0f);
|
2011-03-10 09:08:14 +00:00
|
|
|
|
2022-08-27 15:38:50 +00:00
|
|
|
if(Client()->State() == IClient::STATE_DEMOPLAYBACK && m_pClient->m_Snap.m_LocalClientID >= 0)
|
2015-07-26 16:21:51 +00:00
|
|
|
{
|
|
|
|
Selected = false;
|
2023-05-24 17:29:38 +00:00
|
|
|
if(m_SelectorMouse.x >= -(ObjWidth - 20.0f) + (ObjWidth * 2.0f * 2.0f / 3.0f) && m_SelectorMouse.x <= -(ObjWidth - 20.0f) + (ObjWidth * 2.0f * 2.0f / 3.0f) + ((ObjWidth * 2.0f) / 3.0f) - 40.0f &&
|
2015-07-26 16:21:51 +00:00
|
|
|
m_SelectorMouse.y >= -280.0f && m_SelectorMouse.y <= -220.0f)
|
|
|
|
{
|
|
|
|
m_SelectedSpectatorID = SPEC_FOLLOW;
|
|
|
|
Selected = true;
|
|
|
|
}
|
2020-09-26 19:41:58 +00:00
|
|
|
TextRender()->TextColor(1.0f, 1.0f, 1.0f, Selected ? 1.0f : 0.5f);
|
2023-05-24 17:29:38 +00:00
|
|
|
TextRender()->Text(Width / 2.0f - (ObjWidth - 40.0f) + (ObjWidth * 2.0f * 2.0f / 3.0f), Height / 2.0f - 280.0f + (60.f - BigFontSize) / 2.f, BigFontSize, Localize("Follow"), -1.0f);
|
2015-07-26 16:21:51 +00:00
|
|
|
}
|
|
|
|
|
2020-10-08 10:25:05 +00:00
|
|
|
float x = -(ObjWidth - 35.0f), y = StartY;
|
2014-03-23 23:04:44 +00:00
|
|
|
|
|
|
|
int OldDDTeam = -1;
|
|
|
|
|
2011-03-10 09:08:14 +00:00
|
|
|
for(int i = 0, Count = 0; i < MAX_CLIENTS; ++i)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
if(!m_pClient->m_Snap.m_apInfoByDDTeamName[i] || m_pClient->m_Snap.m_apInfoByDDTeamName[i]->m_Team == TEAM_SPECTATORS)
|
2011-03-10 09:08:14 +00:00
|
|
|
continue;
|
|
|
|
|
2013-12-31 21:15:38 +00:00
|
|
|
++Count;
|
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
if(Count == PerLine + 1 || (Count > PerLine + 1 && (Count - 1) % PerLine == 0))
|
2011-03-10 09:08:14 +00:00
|
|
|
{
|
|
|
|
x += 290.0f;
|
|
|
|
y = StartY;
|
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
const CNetObj_PlayerInfo *pInfo = m_pClient->m_Snap.m_apInfoByDDTeamName[i];
|
2019-04-11 10:21:42 +00:00
|
|
|
int DDTeam = m_pClient->m_Teams.Team(pInfo->m_ClientID);
|
2014-03-23 23:04:44 +00:00
|
|
|
int NextDDTeam = 0;
|
|
|
|
|
|
|
|
for(int j = i + 1; j < MAX_CLIENTS; j++)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
const CNetObj_PlayerInfo *pInfo2 = m_pClient->m_Snap.m_apInfoByDDTeamName[j];
|
2014-03-23 23:04:44 +00:00
|
|
|
|
|
|
|
if(!pInfo2 || pInfo2->m_Team == TEAM_SPECTATORS)
|
|
|
|
continue;
|
|
|
|
|
2019-04-11 10:21:42 +00:00
|
|
|
NextDDTeam = m_pClient->m_Teams.Team(pInfo2->m_ClientID);
|
2014-03-23 23:04:44 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
if(OldDDTeam == -1)
|
2014-03-23 23:04:44 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
for(int j = i - 1; j >= 0; j--)
|
2014-03-23 23:04:44 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
const CNetObj_PlayerInfo *pInfo2 = m_pClient->m_Snap.m_apInfoByDDTeamName[j];
|
2014-03-23 23:04:44 +00:00
|
|
|
|
|
|
|
if(!pInfo2 || pInfo2->m_Team == TEAM_SPECTATORS)
|
|
|
|
continue;
|
|
|
|
|
2019-04-11 10:21:42 +00:00
|
|
|
OldDDTeam = m_pClient->m_Teams.Team(pInfo2->m_ClientID);
|
2014-03-23 23:04:44 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
if(DDTeam != TEAM_FLOCK)
|
2014-03-23 23:04:44 +00:00
|
|
|
{
|
2022-07-09 13:44:06 +00:00
|
|
|
ColorRGBA Color = color_cast<ColorRGBA>(ColorHSLA(DDTeam / 64.0f, 1.0f, 0.5f, 0.5f));
|
2014-03-23 23:04:44 +00:00
|
|
|
int Corners = 0;
|
2020-09-26 19:41:58 +00:00
|
|
|
if(OldDDTeam != DDTeam)
|
2022-07-26 19:17:29 +00:00
|
|
|
Corners |= IGraphics::CORNER_TL | IGraphics::CORNER_TR;
|
2020-09-26 19:41:58 +00:00
|
|
|
if(NextDDTeam != DDTeam)
|
2022-07-26 19:17:29 +00:00
|
|
|
Corners |= IGraphics::CORNER_BL | IGraphics::CORNER_BR;
|
2022-07-09 20:27:35 +00:00
|
|
|
Graphics()->DrawRect(Width / 2.0f + x - 10.0f + BoxOffset, Height / 2.0f + y + BoxMove, 270.0f - BoxOffset, LineHeight, Color, Corners, RoundRadius);
|
2014-03-23 23:04:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
OldDDTeam = DDTeam;
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if((Client()->State() == IClient::STATE_DEMOPLAYBACK && m_pClient->m_DemoSpecID == m_pClient->m_Snap.m_apInfoByDDTeamName[i]->m_ClientID) || (Client()->State() != IClient::STATE_DEMOPLAYBACK && m_pClient->m_Snap.m_SpecInfo.m_SpectatorID == m_pClient->m_Snap.m_apInfoByDDTeamName[i]->m_ClientID))
|
2011-03-10 09:08:14 +00:00
|
|
|
{
|
2022-07-09 20:27:35 +00:00
|
|
|
Graphics()->DrawRect(Width / 2.0f + x - 10.0f + BoxOffset, Height / 2.0f + y + BoxMove, 270.0f - BoxOffset, LineHeight, ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f), IGraphics::CORNER_ALL, RoundRadius);
|
2011-03-10 09:08:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Selected = false;
|
2020-09-26 19:41:58 +00:00
|
|
|
if(m_SelectorMouse.x >= x - 10.0f && m_SelectorMouse.x < x + 260.0f &&
|
|
|
|
m_SelectorMouse.y >= y - (LineHeight / 6.0f) && m_SelectorMouse.y < y + (LineHeight * 5.0f / 6.0f))
|
2011-03-10 09:08:14 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
m_SelectedSpectatorID = m_pClient->m_Snap.m_apInfoByDDTeamName[i]->m_ClientID;
|
2011-03-10 09:08:14 +00:00
|
|
|
Selected = true;
|
2023-07-09 13:53:57 +00:00
|
|
|
if(GameClient()->m_MultiViewActivated && m_Clicked)
|
|
|
|
{
|
|
|
|
if(GameClient()->m_MultiViewTeam == DDTeam)
|
|
|
|
{
|
|
|
|
GameClient()->m_aMultiViewId[m_SelectedSpectatorID] = !GameClient()->m_aMultiViewId[m_SelectedSpectatorID];
|
|
|
|
if(!GameClient()->m_aMultiViewId[m_pClient->m_Snap.m_SpecInfo.m_SpectatorID])
|
|
|
|
{
|
|
|
|
int NewClientID = GameClient()->FindFirstMultiViewId();
|
|
|
|
if(NewClientID < MAX_CLIENTS && NewClientID >= 0)
|
|
|
|
{
|
|
|
|
GameClient()->CleanMultiViewId(NewClientID);
|
|
|
|
GameClient()->m_aMultiViewId[NewClientID] = true;
|
|
|
|
Spectate(NewClientID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GameClient()->ResetMultiView();
|
|
|
|
Spectate(m_SelectedSpectatorID);
|
|
|
|
m_MultiViewActivateDelay = Client()->LocalTime() + 0.3f;
|
|
|
|
}
|
|
|
|
m_Clicked = false;
|
|
|
|
}
|
2011-03-10 09:08:14 +00:00
|
|
|
}
|
2015-07-26 16:52:53 +00:00
|
|
|
float TeeAlpha;
|
|
|
|
if(Client()->State() == IClient::STATE_DEMOPLAYBACK &&
|
2022-06-30 22:36:32 +00:00
|
|
|
!m_pClient->m_Snap.m_aCharacters[m_pClient->m_Snap.m_apInfoByDDTeamName[i]->m_ClientID].m_Active)
|
2015-07-26 16:52:53 +00:00
|
|
|
{
|
|
|
|
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 0.25f);
|
|
|
|
TeeAlpha = 0.5f;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
TextRender()->TextColor(1.0f, 1.0f, 1.0f, Selected ? 1.0f : 0.5f);
|
2015-07-26 16:52:53 +00:00
|
|
|
TeeAlpha = 1.0f;
|
|
|
|
}
|
2023-02-17 17:13:20 +00:00
|
|
|
TextRender()->Text(Width / 2.0f + x + 50.0f, Height / 2.0f + y + BoxMove + (LineHeight - FontSize) / 2.f, FontSize, m_pClient->m_aClients[m_pClient->m_Snap.m_apInfoByDDTeamName[i]->m_ClientID].m_aName, 220.0f);
|
2011-03-10 09:08:14 +00:00
|
|
|
|
2023-07-09 13:53:57 +00:00
|
|
|
if(GameClient()->m_MultiViewActivated)
|
|
|
|
{
|
|
|
|
if(GameClient()->m_aMultiViewId[m_pClient->m_Snap.m_apInfoByDDTeamName[i]->m_ClientID])
|
|
|
|
{
|
|
|
|
TextRender()->TextColor(0.1f, 1.0f, 0.1f, Selected ? 1.0f : 0.5f);
|
|
|
|
TextRender()->Text(Width / 2.0f + x + 50.0f + 180.0f, Height / 2.0f + y + BoxMove + (LineHeight - FontSize) / 2.f, FontSize - 3, "⬤", 220.0f);
|
|
|
|
}
|
|
|
|
else if(GameClient()->m_MultiViewTeam == DDTeam)
|
|
|
|
{
|
|
|
|
TextRender()->TextColor(1.0f, 0.1f, 0.1f, Selected ? 1.0f : 0.5f);
|
|
|
|
TextRender()->Text(Width / 2.0f + x + 50.0f + 180.0f, Height / 2.0f + y + BoxMove + (LineHeight - FontSize) / 2.f, FontSize - 3, "◯", 220.0f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-05 00:00:43 +00:00
|
|
|
// flag
|
2023-04-10 15:27:17 +00:00
|
|
|
if(m_pClient->m_Snap.m_pGameInfoObj && (m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags & GAMEFLAG_FLAGS) &&
|
2022-06-30 22:36:32 +00:00
|
|
|
m_pClient->m_Snap.m_pGameDataObj && (m_pClient->m_Snap.m_pGameDataObj->m_FlagCarrierRed == m_pClient->m_Snap.m_apInfoByDDTeamName[i]->m_ClientID || m_pClient->m_Snap.m_pGameDataObj->m_FlagCarrierBlue == m_pClient->m_Snap.m_apInfoByDDTeamName[i]->m_ClientID))
|
2011-05-05 00:00:43 +00:00
|
|
|
{
|
|
|
|
Graphics()->BlendNormal();
|
2022-06-30 22:36:32 +00:00
|
|
|
if(m_pClient->m_Snap.m_pGameDataObj->m_FlagCarrierBlue == m_pClient->m_Snap.m_apInfoByDDTeamName[i]->m_ClientID)
|
2020-10-09 07:07:05 +00:00
|
|
|
Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpriteFlagBlue);
|
|
|
|
else
|
|
|
|
Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpriteFlagRed);
|
2011-05-05 00:00:43 +00:00
|
|
|
|
2020-10-09 07:07:05 +00:00
|
|
|
Graphics()->QuadsBegin();
|
|
|
|
Graphics()->QuadsSetSubset(1, 0, 0, 1);
|
2011-05-05 00:00:43 +00:00
|
|
|
|
|
|
|
float Size = LineHeight;
|
2020-09-26 19:41:58 +00:00
|
|
|
IGraphics::CQuadItem QuadItem(Width / 2.0f + x - LineHeight / 5.0f, Height / 2.0f + y - LineHeight / 3.0f, Size / 2.0f, Size);
|
2011-05-05 00:00:43 +00:00
|
|
|
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
|
|
|
Graphics()->QuadsEnd();
|
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
CTeeRenderInfo TeeInfo = m_pClient->m_aClients[m_pClient->m_Snap.m_apInfoByDDTeamName[i]->m_ClientID].m_RenderInfo;
|
2014-01-12 18:38:22 +00:00
|
|
|
TeeInfo.m_Size *= TeeSizeMod;
|
2021-03-12 20:23:29 +00:00
|
|
|
|
2023-05-30 22:08:01 +00:00
|
|
|
const CAnimState *pIdleState = CAnimState::GetIdle();
|
2021-03-12 20:23:29 +00:00
|
|
|
vec2 OffsetToMid;
|
|
|
|
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
|
|
|
|
vec2 TeeRenderPos(Width / 2.0f + x + 20.0f, Height / 2.0f + y + BoxMove + LineHeight / 2.0f + OffsetToMid.y);
|
|
|
|
|
|
|
|
RenderTools()->RenderTee(pIdleState, &TeeInfo, EMOTE_NORMAL, vec2(1.0f, 0.0f), TeeRenderPos, TeeAlpha);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(m_pClient->m_aClients[m_pClient->m_Snap.m_apInfoByDDTeamName[i]->m_ClientID].m_Friend)
|
2020-10-08 10:25:05 +00:00
|
|
|
{
|
2020-11-12 18:17:21 +00:00
|
|
|
ColorRGBA rgb = color_cast<ColorRGBA>(ColorHSLA(g_Config.m_ClMessageFriendColor));
|
|
|
|
TextRender()->TextColor(rgb.WithAlpha(1.f));
|
2023-02-17 17:13:20 +00:00
|
|
|
TextRender()->Text(Width / 2.0f + x - TeeInfo.m_Size / 2.0f, Height / 2.0f + y + BoxMove + (LineHeight - FontSize) / 2.f, FontSize, "♥", 220.0f);
|
2020-10-08 10:25:05 +00:00
|
|
|
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
}
|
|
|
|
|
2011-03-10 09:08:14 +00:00
|
|
|
y += LineHeight;
|
|
|
|
}
|
2011-03-18 17:03:50 +00:00
|
|
|
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
|
2011-03-10 09:08:14 +00:00
|
|
|
|
2022-05-27 17:30:20 +00:00
|
|
|
RenderTools()->RenderCursor(m_SelectorMouse + vec2(Width, Height) / 2, 48.0f);
|
2011-03-10 09:08:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CSpectator::OnReset()
|
|
|
|
{
|
|
|
|
m_WasActive = false;
|
|
|
|
m_Active = false;
|
|
|
|
m_SelectedSpectatorID = NO_SELECTION;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSpectator::Spectate(int SpectatorID)
|
|
|
|
{
|
2011-03-12 17:07:57 +00:00
|
|
|
if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
|
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
m_pClient->m_DemoSpecID = clamp(SpectatorID, (int)SPEC_FOLLOW, MAX_CLIENTS - 1);
|
2022-08-28 15:52:49 +00:00
|
|
|
// The tick must be rendered for the spectator mode to be updated, so we do it manually when demo playback is paused
|
|
|
|
if(DemoPlayer()->BaseInfo()->m_Paused)
|
|
|
|
GameClient()->m_Menus.DemoSeekTick(IDemoPlayer::TICK_CURRENT);
|
2011-03-12 17:07:57 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_pClient->m_Snap.m_SpecInfo.m_SpectatorID == SpectatorID)
|
2011-03-10 09:08:14 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
CNetMsg_Cl_SetSpectatorMode Msg;
|
|
|
|
Msg.m_SpectatorID = SpectatorID;
|
2022-01-21 00:54:14 +00:00
|
|
|
Client()->SendPackMsgActive(&Msg, MSGFLAG_VITAL);
|
2011-03-10 09:08:14 +00:00
|
|
|
}
|
2023-07-09 13:53:57 +00:00
|
|
|
|
|
|
|
void CSpectator::SpectateClosest()
|
|
|
|
{
|
|
|
|
ConSpectateClosest(NULL, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CSpectator::OnInput(const IInput::CEvent &Event)
|
|
|
|
{
|
|
|
|
if(m_Active && Event.m_Flags & IInput::FLAG_PRESS && Event.m_Key == KEY_MOUSE_1)
|
|
|
|
{
|
|
|
|
m_Clicked = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if(Event.m_Flags & IInput::FLAG_RELEASE && Event.m_Key == KEY_MOUSE_1)
|
|
|
|
{
|
|
|
|
m_Clicked = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|