ddnet/src/game/client/components/emoticon.cpp
heinrich5991 49bc150afd Refactor: Distinguish between two concepts previously called "Dummy"
On the one hand variables called "Dummy" would tell us whether the
current action refers to the currently inactive tee ("dummy"). On the
other hand, these variables could tell us whether the current action
refers to the main connection to the server, or the secondary one. The
latter use case is now renamed to "Client", with the choices
`CLIENT_MAIN`, `CLIENT_DUMMY` (and `CLIENT_CONTACT`).

Perhaps better names could be found, especially since `Client` also
refers to the engine client class in the game code.

I tried to not fix bugs unless it would complicate the code.
2022-01-21 01:54:14 +01:00

224 lines
5.8 KiB
C++

/* (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. */
#include <engine/graphics.h>
#include <engine/serverbrowser.h>
#include <engine/shared/config.h>
#include <game/generated/client_data.h>
#include <game/generated/protocol.h>
#include "chat.h"
#include "emoticon.h"
#include <game/client/animstate.h>
#include <game/client/render.h>
#include <game/client/ui.h>
#include <game/gamecore.h> // get_angle
#include <game/client/gameclient.h>
CEmoticon::CEmoticon()
{
OnReset();
}
void CEmoticon::ConKeyEmoticon(IConsole::IResult *pResult, void *pUserData)
{
CEmoticon *pSelf = (CEmoticon *)pUserData;
if(!pSelf->m_pClient->m_Snap.m_SpecInfo.m_Active && pSelf->Client()->State() != IClient::STATE_DEMOPLAYBACK)
pSelf->m_Active = pResult->GetInteger(0) != 0;
}
void CEmoticon::ConEmote(IConsole::IResult *pResult, void *pUserData)
{
((CEmoticon *)pUserData)->Emote(pResult->GetInteger(0));
}
void CEmoticon::OnConsoleInit()
{
Console()->Register("+emote", "", CFGFLAG_CLIENT, ConKeyEmoticon, this, "Open emote selector");
Console()->Register("emote", "i[emote-id]", CFGFLAG_CLIENT, ConEmote, this, "Use emote");
}
void CEmoticon::OnReset()
{
m_WasActive = false;
m_Active = false;
m_SelectedEmote = -1;
m_SelectedEyeEmote = -1;
}
void CEmoticon::OnRelease()
{
m_Active = false;
}
bool CEmoticon::OnMouseMove(float x, float y)
{
if(!m_Active)
return false;
UI()->ConvertMouseMove(&x, &y);
m_SelectorMouse += vec2(x, y);
return true;
}
void CEmoticon::DrawCircle(float x, float y, float r, int Segments)
{
RenderTools()->DrawCircle(x, y, r, Segments);
}
void CEmoticon::OnRender()
{
if(!m_Active)
{
if(m_WasActive && m_SelectedEmote != -1)
Emote(m_SelectedEmote);
if(m_WasActive && m_SelectedEyeEmote != -1)
EyeEmote(m_SelectedEyeEmote);
m_WasActive = false;
return;
}
if(m_pClient->m_Snap.m_SpecInfo.m_Active)
{
m_Active = false;
m_WasActive = false;
return;
}
m_WasActive = true;
if(length(m_SelectorMouse) > 170.0f)
m_SelectorMouse = normalize(m_SelectorMouse) * 170.0f;
float SelectedAngle = angle(m_SelectorMouse) + 2 * pi / 24;
if(SelectedAngle < 0)
SelectedAngle += 2 * pi;
m_SelectedEmote = -1;
m_SelectedEyeEmote = -1;
if(length(m_SelectorMouse) > 110.0f)
m_SelectedEmote = (int)(SelectedAngle / (2 * pi) * NUM_EMOTICONS);
else if(length(m_SelectorMouse) > 40.0f)
m_SelectedEyeEmote = (int)(SelectedAngle / (2 * pi) * NUM_EMOTES);
CUIRect Screen = *UI()->Screen();
UI()->MapScreen();
Graphics()->BlendNormal();
Graphics()->TextureClear();
Graphics()->QuadsBegin();
Graphics()->SetColor(0, 0, 0, 0.3f);
DrawCircle(Screen.w / 2, Screen.h / 2, 190.0f, 64);
Graphics()->QuadsEnd();
Graphics()->WrapClamp();
for(int i = 0; i < NUM_EMOTICONS; i++)
{
float Angle = 2 * pi * i / NUM_EMOTICONS;
if(Angle > pi)
Angle -= 2 * pi;
bool Selected = m_SelectedEmote == i;
float Size = Selected ? 80.0f : 50.0f;
Graphics()->TextureSet(GameClient()->m_EmoticonsSkin.m_SpriteEmoticons[i]);
Graphics()->QuadsSetSubset(0, 0, 1, 1);
Graphics()->QuadsBegin();
float NudgeX = 150.0f * cosf(Angle);
float NudgeY = 150.0f * sinf(Angle);
IGraphics::CQuadItem QuadItem(Screen.w / 2 + NudgeX, Screen.h / 2 + NudgeY, Size, Size);
Graphics()->QuadsDraw(&QuadItem, 1);
Graphics()->QuadsEnd();
}
Graphics()->WrapNormal();
if(GameClient()->m_GameInfo.m_AllowEyeWheel && g_Config.m_ClEyeWheel)
{
Graphics()->TextureClear();
Graphics()->QuadsBegin();
Graphics()->SetColor(1.0, 1.0, 1.0, 0.3f);
DrawCircle(Screen.w / 2, Screen.h / 2, 100.0f, 64);
Graphics()->QuadsEnd();
CTeeRenderInfo *pTeeInfo = &m_pClient->m_aClients[m_pClient->m_LocalIDs[g_Config.m_ClDummy]].m_RenderInfo;
for(int i = 0; i < NUM_EMOTES; i++)
{
float Angle = 2 * pi * i / NUM_EMOTES;
if(Angle > pi)
Angle -= 2 * pi;
bool Selected = m_SelectedEyeEmote == i;
float NudgeX = 70.0f * cosf(Angle);
float NudgeY = 70.0f * sinf(Angle);
pTeeInfo->m_Size = Selected ? 64.0f : 48.0f;
RenderTools()->RenderTee(CAnimState::GetIdle(), pTeeInfo, i, vec2(-1, 0), vec2(Screen.w / 2 + NudgeX, Screen.h / 2 + NudgeY));
pTeeInfo->m_Size = 64.0f;
}
Graphics()->TextureClear();
Graphics()->QuadsBegin();
Graphics()->SetColor(0, 0, 0, 0.3f);
DrawCircle(Screen.w / 2, Screen.h / 2, 30.0f, 64);
Graphics()->QuadsEnd();
}
else
m_SelectedEyeEmote = -1;
Graphics()->WrapClamp();
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CURSOR].m_Id);
Graphics()->QuadsBegin();
Graphics()->SetColor(1, 1, 1, 1);
IGraphics::CQuadItem QuadItem(m_SelectorMouse.x + Screen.w / 2, m_SelectorMouse.y + Screen.h / 2, 24, 24);
Graphics()->QuadsDrawTL(&QuadItem, 1);
Graphics()->QuadsEnd();
Graphics()->WrapNormal();
}
void CEmoticon::Emote(int Emoticon)
{
CNetMsg_Cl_Emoticon Msg;
Msg.m_Emoticon = Emoticon;
Client()->SendPackMsgActive(&Msg, MSGFLAG_VITAL);
if(g_Config.m_ClDummyCopyMoves)
{
CMsgPacker Msg(NETMSGTYPE_CL_EMOTICON, false);
Msg.AddInt(Emoticon);
Client()->SendMsg(!g_Config.m_ClDummy, &Msg, MSGFLAG_VITAL);
}
}
void CEmoticon::EyeEmote(int Emote)
{
char aBuf[32];
switch(Emote)
{
case EMOTE_NORMAL:
str_format(aBuf, sizeof(aBuf), "/emote normal %d", g_Config.m_ClEyeDuration);
break;
case EMOTE_PAIN:
str_format(aBuf, sizeof(aBuf), "/emote pain %d", g_Config.m_ClEyeDuration);
break;
case EMOTE_HAPPY:
str_format(aBuf, sizeof(aBuf), "/emote happy %d", g_Config.m_ClEyeDuration);
break;
case EMOTE_SURPRISE:
str_format(aBuf, sizeof(aBuf), "/emote surprise %d", g_Config.m_ClEyeDuration);
break;
case EMOTE_ANGRY:
str_format(aBuf, sizeof(aBuf), "/emote angry %d", g_Config.m_ClEyeDuration);
break;
case EMOTE_BLINK:
str_format(aBuf, sizeof(aBuf), "/emote blink %d", g_Config.m_ClEyeDuration);
break;
}
GameClient()->m_Chat.Say(0, aBuf);
}