2010-11-20 10:37: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. */
|
2011-08-31 11:56:04 +00:00
|
|
|
|
|
|
|
#include <base/tl/sorted_array.h>
|
|
|
|
|
2010-11-16 23:38:20 +00:00
|
|
|
#include <engine/demo.h>
|
2011-02-27 16:56:03 +00:00
|
|
|
#include <engine/engine.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <engine/graphics.h>
|
|
|
|
#include <engine/shared/config.h>
|
|
|
|
#include <game/generated/protocol.h>
|
|
|
|
#include <game/generated/client_data.h>
|
|
|
|
|
|
|
|
#include <game/gamecore.h> // get_angle
|
|
|
|
#include <game/client/animstate.h>
|
|
|
|
#include <game/client/gameclient.h>
|
|
|
|
#include <game/client/ui.h>
|
|
|
|
#include <game/client/render.h>
|
|
|
|
|
|
|
|
#include <game/client/components/flow.h>
|
|
|
|
#include <game/client/components/skins.h>
|
|
|
|
#include <game/client/components/effects.h>
|
|
|
|
#include <game/client/components/sounds.h>
|
|
|
|
#include <game/client/components/controls.h>
|
|
|
|
|
2013-10-09 14:02:23 +00:00
|
|
|
#include <engine/textrender.h>
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include "players.h"
|
2013-10-09 14:02:23 +00:00
|
|
|
#include <stdio.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
|
|
|
|
void CPlayers::RenderHand(CTeeRenderInfo *pInfo, vec2 CenterPos, vec2 Dir, float AngleOffset, vec2 PostRotOffset)
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
|
|
|
// for drawing hand
|
|
|
|
//const skin *s = skin_get(skin_id);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
float BaseSize = 10.0f;
|
2008-01-12 17:09:00 +00:00
|
|
|
//dir = normalize(hook_pos-pos);
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 HandPos = CenterPos + Dir;
|
|
|
|
float Angle = GetAngle(Dir);
|
|
|
|
if (Dir.x < 0)
|
|
|
|
Angle -= AngleOffset;
|
2008-01-12 17:09:00 +00:00
|
|
|
else
|
2010-05-29 07:25:38 +00:00
|
|
|
Angle += AngleOffset;
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 DirX = Dir;
|
|
|
|
vec2 DirY(-Dir.y,Dir.x);
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if (Dir.x < 0)
|
|
|
|
DirY = -DirY;
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
HandPos += DirX * PostRotOffset.x;
|
|
|
|
HandPos += DirY * PostRotOffset.y;
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
//Graphics()->TextureSet(data->m_aImages[IMAGE_CHAR_DEFAULT].id);
|
|
|
|
Graphics()->TextureSet(pInfo->m_Texture);
|
2009-10-27 14:38:53 +00:00
|
|
|
Graphics()->QuadsBegin();
|
2010-05-29 07:25:38 +00:00
|
|
|
Graphics()->SetColor(pInfo->m_ColorBody.r, pInfo->m_ColorBody.g, pInfo->m_ColorBody.b, pInfo->m_ColorBody.a);
|
2008-01-12 17:09:00 +00:00
|
|
|
|
|
|
|
// two passes
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
bool OutLine = i == 0;
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderTools()->SelectSprite(OutLine?SPRITE_TEE_HAND_OUTLINE:SPRITE_TEE_HAND, 0, 0, 0);
|
|
|
|
Graphics()->QuadsSetRotation(Angle);
|
|
|
|
IGraphics::CQuadItem QuadItem(HandPos.x, HandPos.y, 2*BaseSize, 2*BaseSize);
|
|
|
|
Graphics()->QuadsDraw(&QuadItem, 1);
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
Graphics()->QuadsSetRotation(0);
|
|
|
|
Graphics()->QuadsEnd();
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
inline float NormalizeAngular(float f)
|
2008-09-03 20:03:01 +00:00
|
|
|
{
|
2008-10-18 10:30:03 +00:00
|
|
|
return fmod(f+pi*2, pi*2);
|
2008-09-03 20:03:01 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
inline float AngularMixDirection (float Src, float Dst) { return sinf(Dst-Src) >0?1:-1; }
|
|
|
|
inline float AngularDistance(float Src, float Dst) { return asinf(sinf(Dst-Src)); }
|
2008-10-18 10:30:03 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
inline float AngularApproach(float Src, float Dst, float Amount)
|
2008-09-03 20:03:01 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
float d = AngularMixDirection (Src, Dst);
|
|
|
|
float n = Src + Amount*d;
|
|
|
|
if(AngularMixDirection (n, Dst) != d)
|
|
|
|
return Dst;
|
2008-10-18 10:30:03 +00:00
|
|
|
return n;
|
2008-09-03 20:03:01 +00:00
|
|
|
}
|
|
|
|
|
2013-10-09 14:02:23 +00:00
|
|
|
void CPlayers::Predict(
|
|
|
|
const CNetObj_Character *pPrevChar,
|
|
|
|
const CNetObj_Character *pPlayerChar,
|
|
|
|
const CNetObj_PlayerInfo *pPrevInfo,
|
|
|
|
const CNetObj_PlayerInfo *pPlayerInfo,
|
|
|
|
vec2 &PrevPredPos,
|
|
|
|
vec2 &SmoothPos,
|
|
|
|
int &MoveCnt,
|
|
|
|
vec2 &Position
|
|
|
|
)
|
|
|
|
{
|
|
|
|
CNetObj_Character Prev;
|
|
|
|
CNetObj_Character Player;
|
|
|
|
Prev = *pPrevChar;
|
|
|
|
Player = *pPlayerChar;
|
|
|
|
|
|
|
|
CNetObj_PlayerInfo pInfo = *pPlayerInfo;
|
|
|
|
|
|
|
|
|
|
|
|
// set size
|
|
|
|
|
|
|
|
float IntraTick = Client()->IntraGameTick();
|
|
|
|
|
|
|
|
|
|
|
|
//float angle = 0;
|
|
|
|
|
|
|
|
if(pInfo.m_Local && Client()->State() != IClient::STATE_DEMOPLAYBACK)
|
|
|
|
{
|
|
|
|
// just use the direct input if it's local player we are rendering
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
float mixspeed = Client()->FrameTime()*2.5f;
|
|
|
|
if(player.attacktick != prev.attacktick) // shooting boosts the mixing speed
|
|
|
|
mixspeed *= 15.0f;
|
|
|
|
|
|
|
|
// move the delta on a constant speed on a x^2 curve
|
|
|
|
float current = g_GameClient.m_aClients[info.cid].angle;
|
|
|
|
float target = player.angle/256.0f;
|
|
|
|
float delta = angular_distance(current, target);
|
|
|
|
float sign = delta < 0 ? -1 : 1;
|
|
|
|
float new_delta = delta - 2*mixspeed*sqrt(delta*sign)*sign + mixspeed*mixspeed;
|
|
|
|
|
|
|
|
// make sure that it doesn't vibrate when it's still
|
|
|
|
if(fabs(delta) < 2/256.0f)
|
|
|
|
angle = target;
|
|
|
|
else
|
|
|
|
angle = angular_approach(current, target, fabs(delta-new_delta));
|
|
|
|
|
|
|
|
g_GameClient.m_aClients[info.cid].angle = angle;*/
|
|
|
|
}
|
|
|
|
|
2015-07-09 00:08:14 +00:00
|
|
|
vec2 NonPredPos = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick);
|
2013-10-09 14:02:23 +00:00
|
|
|
|
|
|
|
// use preditect players if needed
|
|
|
|
if(g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK)
|
|
|
|
{
|
|
|
|
if(m_pClient->m_Snap.m_pLocalCharacter && !(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER))
|
|
|
|
{
|
|
|
|
// apply predicted results
|
|
|
|
m_pClient->m_aClients[pInfo.m_ClientID].m_Predicted.Write(&Player);
|
|
|
|
m_pClient->m_aClients[pInfo.m_ClientID].m_PrevPredicted.Write(&Prev);
|
|
|
|
|
|
|
|
IntraTick = Client()->PredIntraGameTick();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick);
|
|
|
|
|
|
|
|
|
2017-03-21 10:24:44 +00:00
|
|
|
static double s_Ping = 0;
|
2013-10-09 14:02:23 +00:00
|
|
|
|
2014-01-11 23:45:25 +00:00
|
|
|
if(pInfo.m_Local) {
|
2017-03-21 10:24:44 +00:00
|
|
|
s_Ping = mix(s_Ping, (double)pInfo.m_Latency, 0.1);
|
2014-01-11 23:45:25 +00:00
|
|
|
}
|
2013-10-09 14:02:23 +00:00
|
|
|
|
2014-01-11 23:45:25 +00:00
|
|
|
if(!pInfo.m_Local)
|
2013-10-09 14:02:23 +00:00
|
|
|
{
|
2014-01-11 23:45:25 +00:00
|
|
|
/*
|
|
|
|
for ping = 260, usual missprediction distances:
|
2013-10-09 14:02:23 +00:00
|
|
|
|
2014-01-11 23:45:25 +00:00
|
|
|
move = 120-140
|
|
|
|
jump = 130
|
|
|
|
dj = 250
|
2013-10-09 14:02:23 +00:00
|
|
|
|
2014-01-11 23:45:25 +00:00
|
|
|
normalized:
|
|
|
|
move = 0.461 - 0.538
|
|
|
|
jump = 0.5
|
|
|
|
dj = .961
|
2013-10-09 14:02:23 +00:00
|
|
|
|
2014-01-11 23:45:25 +00:00
|
|
|
*/
|
2013-10-09 14:02:23 +00:00
|
|
|
//printf("%d\n", m_pClient->m_Snap.m_pLocalInfo->m_Latency);
|
|
|
|
|
|
|
|
|
2014-01-11 23:45:25 +00:00
|
|
|
if(m_pClient->m_Snap.m_pLocalInfo)
|
2017-03-21 10:24:44 +00:00
|
|
|
s_Ping = mix(s_Ping, (double)m_pClient->m_Snap.m_pLocalInfo->m_Latency, 0.1);
|
2013-10-09 14:02:23 +00:00
|
|
|
|
2017-03-21 10:24:44 +00:00
|
|
|
double d = length(PrevPredPos - Position)/s_Ping;
|
2013-10-09 14:02:23 +00:00
|
|
|
|
|
|
|
if((d > 0.4) && (d < 5.))
|
|
|
|
{
|
|
|
|
// if(MoveCnt == 0)
|
|
|
|
// printf("[\n");
|
|
|
|
if(MoveCnt == 0)
|
|
|
|
SmoothPos = NonPredPos;
|
|
|
|
|
|
|
|
MoveCnt = 10;
|
2014-01-11 23:45:25 +00:00
|
|
|
// SmoothPos = PrevPredPos;
|
|
|
|
// SmoothPos = mix(NonPredPos, Position, 0.6);
|
2013-10-09 14:02:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PrevPredPos = Position;
|
|
|
|
|
|
|
|
if(MoveCnt > 0)
|
|
|
|
{
|
2014-01-11 23:45:25 +00:00
|
|
|
// Position = mix(mix(NonPredPos, Position, 0.5), SmoothPos, (((float)MoveCnt))/15);
|
|
|
|
// Position = mix(mix(NonPredPos, Position, 0.5), SmoothPos, 0.5);
|
2013-10-09 14:02:23 +00:00
|
|
|
Position = mix(NonPredPos, Position, 0.5);
|
|
|
|
|
|
|
|
SmoothPos = Position;
|
|
|
|
MoveCnt--;
|
2014-01-11 23:45:25 +00:00
|
|
|
// if(MoveCnt == 0)
|
|
|
|
// printf("]\n\n");
|
2013-10-09 14:02:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CPlayers::RenderHook(
|
|
|
|
const CNetObj_Character *pPrevChar,
|
|
|
|
const CNetObj_Character *pPlayerChar,
|
|
|
|
const CNetObj_PlayerInfo *pPrevInfo,
|
2013-10-09 14:02:23 +00:00
|
|
|
const CNetObj_PlayerInfo *pPlayerInfo,
|
2014-01-11 23:45:25 +00:00
|
|
|
const vec2 &parPosition,
|
|
|
|
const vec2 &PositionTo
|
2008-01-12 17:09:00 +00:00
|
|
|
)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetObj_Character Prev;
|
|
|
|
CNetObj_Character Player;
|
|
|
|
Prev = *pPrevChar;
|
|
|
|
Player = *pPlayerChar;
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetObj_PlayerInfo pInfo = *pPlayerInfo;
|
2012-01-08 14:44:49 +00:00
|
|
|
CTeeRenderInfo RenderInfo = m_aRenderInfo[pInfo.m_ClientID];
|
2010-05-29 07:25:38 +00:00
|
|
|
|
2014-08-25 14:53:11 +00:00
|
|
|
// don't render hooks to not active character cores
|
|
|
|
if (pPlayerChar->m_HookedPlayer != -1 && !m_pClient->m_Snap.m_aCharacters[pPlayerChar->m_HookedPlayer].m_Active)
|
|
|
|
return;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
float IntraTick = Client()->IntraGameTick();
|
|
|
|
|
2014-01-24 22:11:33 +00:00
|
|
|
bool OtherTeam;
|
|
|
|
|
2014-04-12 14:55:01 +00:00
|
|
|
if (m_pClient->m_aClients[m_pClient->m_Snap.m_LocalClientID].m_Team == TEAM_SPECTATORS && m_pClient->m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW)
|
|
|
|
OtherTeam = false;
|
|
|
|
else if (m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_Snap.m_SpecInfo.m_SpectatorID != SPEC_FREEVIEW)
|
|
|
|
OtherTeam = m_pClient->m_Teams.Team(pInfo.m_ClientID) != m_pClient->m_Teams.Team(m_pClient->m_Snap.m_SpecInfo.m_SpectatorID);
|
2014-01-24 22:11:33 +00:00
|
|
|
else
|
|
|
|
OtherTeam = m_pClient->m_Teams.Team(pInfo.m_ClientID) != m_pClient->m_Teams.Team(m_pClient->m_Snap.m_LocalClientID);
|
|
|
|
|
|
|
|
if (OtherTeam)
|
|
|
|
{
|
2014-05-17 21:00:52 +00:00
|
|
|
RenderInfo.m_ColorBody.a = g_Config.m_ClShowOthersAlpha / 100.0f;
|
|
|
|
RenderInfo.m_ColorFeet.a = g_Config.m_ClShowOthersAlpha / 100.0f;
|
2014-01-24 22:11:33 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// set size
|
|
|
|
RenderInfo.m_Size = 64.0f;
|
|
|
|
|
2015-09-10 11:09:38 +00:00
|
|
|
if (!m_pClient->AntiPingPlayers())
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2013-10-09 14:02:23 +00:00
|
|
|
// use preditect players if needed
|
|
|
|
if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK)
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2013-10-09 14:02:23 +00:00
|
|
|
if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// apply predicted results
|
|
|
|
m_pClient->m_PredictedChar.Write(&Player);
|
|
|
|
m_pClient->m_PredictedPrevChar.Write(&Prev);
|
|
|
|
IntraTick = Client()->PredIntraGameTick();
|
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
2013-10-09 14:02:23 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK)
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2013-10-09 14:02:23 +00:00
|
|
|
if(m_pClient->m_Snap.m_pLocalCharacter && !(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER))
|
|
|
|
{
|
|
|
|
// apply predicted results
|
|
|
|
m_pClient->m_aClients[pInfo.m_ClientID].m_Predicted.Write(&Player);
|
|
|
|
m_pClient->m_aClients[pInfo.m_ClientID].m_PrevPredicted.Write(&Prev);
|
|
|
|
|
|
|
|
IntraTick = Client()->PredIntraGameTick();
|
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-09 14:02:23 +00:00
|
|
|
vec2 Position;
|
2015-09-10 11:09:38 +00:00
|
|
|
if (!m_pClient->AntiPingPlayers())
|
2013-10-09 14:02:23 +00:00
|
|
|
Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick);
|
|
|
|
else
|
|
|
|
Position = parPosition;
|
2010-05-29 07:25:38 +00:00
|
|
|
|
|
|
|
// draw hook
|
|
|
|
if (Prev.m_HookState>0 && Player.m_HookState>0)
|
|
|
|
{
|
|
|
|
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
|
|
|
|
Graphics()->QuadsBegin();
|
|
|
|
//Graphics()->QuadsBegin();
|
|
|
|
|
|
|
|
vec2 Pos = Position;
|
|
|
|
vec2 HookPos;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2015-09-10 11:09:38 +00:00
|
|
|
if (!m_pClient->AntiPingPlayers())
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2013-10-09 14:02:23 +00:00
|
|
|
if(pPlayerChar->m_HookedPlayer != -1)
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2017-04-01 11:10:29 +00:00
|
|
|
if(m_pClient->m_Snap.m_pLocalInfo && pPlayerChar->m_HookedPlayer == m_pClient->m_Snap.m_pLocalInfo->m_ClientID && !m_pClient->m_Snap.m_SpecInfo.m_Active)
|
2013-10-09 14:02:23 +00:00
|
|
|
{
|
|
|
|
if(Client()->State() == IClient::STATE_DEMOPLAYBACK) // only use prediction if needed
|
|
|
|
HookPos = vec2(m_pClient->m_LocalCharacterPos.x, m_pClient->m_LocalCharacterPos.y);
|
|
|
|
else
|
|
|
|
HookPos = mix(vec2(m_pClient->m_PredictedPrevChar.m_Pos.x, m_pClient->m_PredictedPrevChar.m_Pos.y),
|
|
|
|
vec2(m_pClient->m_PredictedChar.m_Pos.x, m_pClient->m_PredictedChar.m_Pos.y), Client()->PredIntraGameTick());
|
|
|
|
}
|
|
|
|
else if(pInfo.m_Local)
|
|
|
|
{
|
|
|
|
HookPos = mix(vec2(m_pClient->m_Snap.m_aCharacters[pPlayerChar->m_HookedPlayer].m_Prev.m_X,
|
|
|
|
m_pClient->m_Snap.m_aCharacters[pPlayerChar->m_HookedPlayer].m_Prev.m_Y),
|
|
|
|
vec2(m_pClient->m_Snap.m_aCharacters[pPlayerChar->m_HookedPlayer].m_Cur.m_X,
|
|
|
|
m_pClient->m_Snap.m_aCharacters[pPlayerChar->m_HookedPlayer].m_Cur.m_Y),
|
|
|
|
Client()->IntraGameTick());
|
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else
|
2013-10-09 14:02:23 +00:00
|
|
|
HookPos = mix(vec2(pPrevChar->m_HookX, pPrevChar->m_HookY), vec2(pPlayerChar->m_HookX, pPlayerChar->m_HookY), Client()->IntraGameTick());
|
2010-09-08 00:54:03 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else
|
2013-10-09 14:02:23 +00:00
|
|
|
HookPos = mix(vec2(Prev.m_HookX, Prev.m_HookY), vec2(Player.m_HookX, Player.m_HookY), IntraTick);
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
else
|
2013-10-09 14:02:23 +00:00
|
|
|
{
|
|
|
|
if(pPrevChar->m_HookedPlayer != -1)
|
|
|
|
HookPos = PositionTo;
|
|
|
|
else
|
|
|
|
HookPos = mix(vec2(Prev.m_HookX, Prev.m_HookY), vec2(Player.m_HookX, Player.m_HookY), IntraTick);
|
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
|
|
|
|
float d = distance(Pos, HookPos);
|
|
|
|
vec2 Dir = normalize(Pos-HookPos);
|
|
|
|
|
|
|
|
Graphics()->QuadsSetRotation(GetAngle(Dir)+pi);
|
|
|
|
|
|
|
|
// render head
|
|
|
|
RenderTools()->SelectSprite(SPRITE_HOOK_HEAD);
|
|
|
|
IGraphics::CQuadItem QuadItem(HookPos.x, HookPos.y, 24,16);
|
2014-01-24 22:11:33 +00:00
|
|
|
if (OtherTeam)
|
2014-05-17 21:00:52 +00:00
|
|
|
Graphics()->SetColor(1.0f, 1.0f, 1.0f, g_Config.m_ClShowOthersAlpha / 100.0f);
|
2010-05-29 07:25:38 +00:00
|
|
|
Graphics()->QuadsDraw(&QuadItem, 1);
|
|
|
|
|
|
|
|
// render chain
|
|
|
|
RenderTools()->SelectSprite(SPRITE_HOOK_CHAIN);
|
|
|
|
IGraphics::CQuadItem Array[1024];
|
|
|
|
int i = 0;
|
|
|
|
for(float f = 24; f < d && i < 1024; f += 24, i++)
|
|
|
|
{
|
|
|
|
vec2 p = HookPos + Dir*f;
|
|
|
|
Array[i] = IGraphics::CQuadItem(p.x, p.y,24,16);
|
|
|
|
}
|
|
|
|
|
2014-01-24 22:11:33 +00:00
|
|
|
if (OtherTeam)
|
2014-05-17 21:00:52 +00:00
|
|
|
Graphics()->SetColor(1.0f, 1.0f, 1.0f, g_Config.m_ClShowOthersAlpha / 100.0f);
|
2010-05-29 07:25:38 +00:00
|
|
|
Graphics()->QuadsDraw(Array, i);
|
|
|
|
Graphics()->QuadsSetRotation(0);
|
|
|
|
Graphics()->QuadsEnd();
|
|
|
|
|
|
|
|
RenderHand(&RenderInfo, Position, normalize(HookPos-Pos), -pi/2, vec2(20, 0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPlayers::RenderPlayer(
|
|
|
|
const CNetObj_Character *pPrevChar,
|
|
|
|
const CNetObj_Character *pPlayerChar,
|
|
|
|
const CNetObj_PlayerInfo *pPrevInfo,
|
2013-10-09 14:02:23 +00:00
|
|
|
const CNetObj_PlayerInfo *pPlayerInfo,
|
2013-11-13 12:25:12 +00:00
|
|
|
const vec2 &parPosition
|
2015-07-09 00:08:14 +00:00
|
|
|
/* vec2 &PrevPos,
|
|
|
|
vec2 &SmoothPos,
|
|
|
|
int &MoveCnt
|
2013-10-09 14:02:23 +00:00
|
|
|
*/ )
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
|
|
|
CNetObj_Character Prev;
|
|
|
|
CNetObj_Character Player;
|
|
|
|
Prev = *pPrevChar;
|
|
|
|
Player = *pPlayerChar;
|
|
|
|
|
|
|
|
CNetObj_PlayerInfo pInfo = *pPlayerInfo;
|
2012-01-08 14:44:49 +00:00
|
|
|
CTeeRenderInfo RenderInfo = m_aRenderInfo[pInfo.m_ClientID];
|
2010-05-29 07:25:38 +00:00
|
|
|
|
|
|
|
bool NewTick = m_pClient->m_NewTick;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2014-01-24 22:11:33 +00:00
|
|
|
bool OtherTeam;
|
|
|
|
|
2014-04-12 14:55:01 +00:00
|
|
|
if (m_pClient->m_aClients[m_pClient->m_Snap.m_LocalClientID].m_Team == TEAM_SPECTATORS && m_pClient->m_Snap.m_SpecInfo.m_SpectatorID == SPEC_FREEVIEW)
|
|
|
|
OtherTeam = false;
|
|
|
|
else if (m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_Snap.m_SpecInfo.m_SpectatorID != SPEC_FREEVIEW)
|
|
|
|
OtherTeam = m_pClient->m_Teams.Team(pInfo.m_ClientID) != m_pClient->m_Teams.Team(m_pClient->m_Snap.m_SpecInfo.m_SpectatorID);
|
2014-01-24 22:11:33 +00:00
|
|
|
else
|
|
|
|
OtherTeam = m_pClient->m_Teams.Team(pInfo.m_ClientID) != m_pClient->m_Teams.Team(m_pClient->m_Snap.m_LocalClientID);
|
|
|
|
|
2008-03-22 10:59:36 +00:00
|
|
|
// set size
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderInfo.m_Size = 64.0f;
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
float IntraTick = Client()->IntraGameTick();
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2015-11-15 14:39:58 +00:00
|
|
|
float Angle;
|
2010-05-29 07:25:38 +00:00
|
|
|
if(pInfo.m_Local && Client()->State() != IClient::STATE_DEMOPLAYBACK)
|
2008-10-18 10:30:03 +00:00
|
|
|
{
|
2015-11-15 14:39:58 +00:00
|
|
|
// just use the direct input if it's the local player we are rendering
|
2014-05-10 12:31:00 +00:00
|
|
|
Angle = GetAngle(m_pClient->m_pControls->m_MousePos[g_Config.m_ClDummy]);
|
2008-10-18 10:30:03 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-11-15 14:39:58 +00:00
|
|
|
// If the player moves their weapon through top, then change
|
|
|
|
// the end angle by 2*Pi, so that the mix function will use the
|
|
|
|
// short path and not the long one.
|
2015-11-14 16:34:48 +00:00
|
|
|
if (Player.m_Angle > (256.0f * pi) && Prev.m_Angle < 0)
|
2015-11-13 20:38:49 +00:00
|
|
|
{
|
2015-11-14 16:34:48 +00:00
|
|
|
Player.m_Angle -= 256.0f * 2 * pi;
|
2015-11-13 20:38:49 +00:00
|
|
|
Angle = mix((float)Prev.m_Angle, (float)Player.m_Angle, IntraTick) / 256.0f;
|
|
|
|
}
|
2015-11-14 16:34:48 +00:00
|
|
|
else if (Player.m_Angle < 0 && Prev.m_Angle > (256.0f * pi))
|
2015-11-13 20:38:49 +00:00
|
|
|
{
|
2015-11-14 16:34:48 +00:00
|
|
|
Player.m_Angle += 256.0f * 2 * pi;
|
2015-11-13 20:38:49 +00:00
|
|
|
Angle = mix((float)Prev.m_Angle, (float)Player.m_Angle, IntraTick) / 256.0f;
|
|
|
|
}
|
2008-10-18 10:30:03 +00:00
|
|
|
else
|
2015-11-15 14:39:58 +00:00
|
|
|
{
|
|
|
|
// No special cases? Just use mix():
|
|
|
|
Angle = mix((float)Prev.m_Angle, (float)Player.m_Angle, IntraTick)/256.0f;
|
|
|
|
}
|
2008-10-18 10:30:03 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2013-10-09 14:02:23 +00:00
|
|
|
|
2008-10-18 10:30:03 +00:00
|
|
|
// use preditect players if needed
|
2015-09-10 11:09:38 +00:00
|
|
|
if (!m_pClient->AntiPingPlayers())
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2013-10-09 14:02:23 +00:00
|
|
|
if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK)
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2013-10-09 14:02:23 +00:00
|
|
|
if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// apply predicted results
|
|
|
|
m_pClient->m_PredictedChar.Write(&Player);
|
|
|
|
m_pClient->m_PredictedPrevChar.Write(&Prev);
|
|
|
|
IntraTick = Client()->PredIntraGameTick();
|
|
|
|
NewTick = m_pClient->m_NewPredictedTick;
|
|
|
|
}
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
2013-10-09 14:02:23 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK)
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2013-10-09 14:02:23 +00:00
|
|
|
if(m_pClient->m_Snap.m_pLocalCharacter && !(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER))
|
|
|
|
{
|
|
|
|
// apply predicted results
|
|
|
|
m_pClient->m_aClients[pInfo.m_ClientID].m_Predicted.Write(&Player);
|
|
|
|
m_pClient->m_aClients[pInfo.m_ClientID].m_PrevPredicted.Write(&Prev);
|
|
|
|
|
|
|
|
IntraTick = Client()->PredIntraGameTick();
|
|
|
|
NewTick = m_pClient->m_NewPredictedTick;
|
|
|
|
}
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 Direction = GetDirection((int)(Angle*256.0f));
|
2013-10-09 14:02:23 +00:00
|
|
|
vec2 Position;
|
2015-09-10 11:09:38 +00:00
|
|
|
if (!m_pClient->AntiPingPlayers())
|
2013-10-09 14:02:23 +00:00
|
|
|
Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick);
|
|
|
|
else
|
|
|
|
Position = parPosition;
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 Vel = mix(vec2(Prev.m_VelX/256.0f, Prev.m_VelY/256.0f), vec2(Player.m_VelX/256.0f, Player.m_VelY/256.0f), IntraTick);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
m_pClient->m_pFlow->Add(Position, Vel*100.0f, 10.0f);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderInfo.m_GotAirJump = Player.m_Jumped&2?0:1;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
|
|
|
|
2009-01-11 15:51:43 +00:00
|
|
|
// detect events
|
2010-05-29 07:25:38 +00:00
|
|
|
if(NewTick)
|
2009-01-11 15:51:43 +00:00
|
|
|
{
|
|
|
|
// detect air jump
|
2010-05-29 07:25:38 +00:00
|
|
|
if(!RenderInfo.m_GotAirJump && !(Prev.m_Jumped&2))
|
|
|
|
m_pClient->m_pEffects->AirJump(Position);
|
2009-01-11 15:51:43 +00:00
|
|
|
}
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
bool Stationary = Player.m_VelX <= 1 && Player.m_VelX >= -1;
|
|
|
|
bool InAir = !Collision()->CheckPoint(Player.m_X, Player.m_Y+16);
|
|
|
|
bool WantOtherDir = (Player.m_Direction == -1 && Vel.x > 0) || (Player.m_Direction == 1 && Vel.x < 0);
|
2008-01-12 17:09:00 +00:00
|
|
|
|
|
|
|
// evaluate animation
|
2010-06-11 11:20:45 +00:00
|
|
|
float WalkTime = fmod(absolute(Position.x), 100.0f)/100.0f;
|
2010-05-29 07:25:38 +00:00
|
|
|
CAnimState State;
|
|
|
|
State.Set(&g_pData->m_aAnimations[ANIM_BASE], 0);
|
|
|
|
|
|
|
|
if(InAir)
|
|
|
|
State.Add(&g_pData->m_aAnimations[ANIM_INAIR], 0, 1.0f); // TODO: some sort of time here
|
|
|
|
else if(Stationary)
|
|
|
|
State.Add(&g_pData->m_aAnimations[ANIM_IDLE], 0, 1.0f); // TODO: some sort of time here
|
|
|
|
else if(!WantOtherDir)
|
|
|
|
State.Add(&g_pData->m_aAnimations[ANIM_WALK], WalkTime, 1.0f);
|
|
|
|
|
2012-01-09 23:49:31 +00:00
|
|
|
static float s_LastGameTickTime = Client()->GameTickTime();
|
|
|
|
if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
|
|
|
|
s_LastGameTickTime = Client()->GameTickTime();
|
2010-05-29 07:25:38 +00:00
|
|
|
if (Player.m_Weapon == WEAPON_HAMMER)
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2012-01-09 23:49:31 +00:00
|
|
|
float ct = (Client()->PrevGameTick()-Player.m_AttackTick)/(float)SERVER_TICK_SPEED + s_LastGameTickTime;
|
2010-05-29 07:25:38 +00:00
|
|
|
State.Add(&g_pData->m_aAnimations[ANIM_HAMMER_SWING], clamp(ct*5.0f,0.0f,1.0f), 1.0f);
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
if (Player.m_Weapon == WEAPON_NINJA)
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2012-01-09 23:49:31 +00:00
|
|
|
float ct = (Client()->PrevGameTick()-Player.m_AttackTick)/(float)SERVER_TICK_SPEED + s_LastGameTickTime;
|
2010-05-29 07:25:38 +00:00
|
|
|
State.Add(&g_pData->m_aAnimations[ANIM_NINJA_SWING], clamp(ct*2.0f,0.0f,1.0f), 1.0f);
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-03-16 22:32:17 +00:00
|
|
|
// do skidding
|
2010-05-29 07:25:38 +00:00
|
|
|
if(!InAir && WantOtherDir && length(Vel*50) > 500.0f)
|
2008-03-16 22:32:17 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
static int64 SkidSoundTime = 0;
|
|
|
|
if(time_get()-SkidSoundTime > time_freq()/10)
|
2008-03-16 22:32:17 +00:00
|
|
|
{
|
2014-10-25 00:52:08 +00:00
|
|
|
if(g_Config.m_SndGame)
|
|
|
|
m_pClient->m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_PLAYER_SKID, 0.25f, Position);
|
2010-05-29 07:25:38 +00:00
|
|
|
SkidSoundTime = time_get();
|
2008-03-16 22:32:17 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
m_pClient->m_pEffects->SkidTrail(
|
|
|
|
Position+vec2(-Player.m_Direction*6,12),
|
|
|
|
vec2(-Player.m_Direction*100*length(Vel),-50)
|
2008-03-16 22:32:17 +00:00
|
|
|
);
|
|
|
|
}
|
2008-01-12 17:09:00 +00:00
|
|
|
|
|
|
|
// draw gun
|
|
|
|
{
|
2017-05-14 10:03:09 +00:00
|
|
|
if (Player.m_PlayerFlags&PLAYERFLAG_AIM && ((!pPlayerInfo->m_Local && g_Config.m_ClShowHookCollOther) || (pPlayerInfo->m_Local && g_Config.m_ClShowHookCollOwn)))
|
2013-08-23 23:50:35 +00:00
|
|
|
{
|
2014-07-08 18:21:19 +00:00
|
|
|
float Alpha = 1.0f;
|
|
|
|
if (OtherTeam)
|
|
|
|
Alpha = g_Config.m_ClShowOthersAlpha / 100.0f;
|
|
|
|
|
2014-01-11 23:45:25 +00:00
|
|
|
vec2 ExDirection = Direction;
|
2014-01-27 04:06:23 +00:00
|
|
|
|
2014-02-08 18:06:24 +00:00
|
|
|
if (pPlayerInfo->m_Local && Client()->State() != IClient::STATE_DEMOPLAYBACK)
|
2014-10-12 15:52:53 +00:00
|
|
|
ExDirection = normalize(vec2(m_pClient->m_pControls->m_InputData[g_Config.m_ClDummy].m_TargetX, m_pClient->m_pControls->m_InputData[g_Config.m_ClDummy].m_TargetY));
|
2014-01-11 23:45:25 +00:00
|
|
|
|
2013-08-23 23:50:35 +00:00
|
|
|
Graphics()->TextureSet(-1);
|
2017-03-21 10:24:44 +00:00
|
|
|
vec2 InitPos = Position;
|
|
|
|
vec2 FinishPos = InitPos + ExDirection * (m_pClient->m_Tuning[g_Config.m_ClDummy].m_HookLength-42.0f);
|
2014-01-27 04:06:23 +00:00
|
|
|
|
2013-08-23 23:50:35 +00:00
|
|
|
Graphics()->LinesBegin();
|
2014-07-08 18:21:19 +00:00
|
|
|
Graphics()->SetColor(1.00f, 0.0f, 0.0f, Alpha);
|
2013-08-23 23:50:35 +00:00
|
|
|
|
2014-01-27 04:06:23 +00:00
|
|
|
float PhysSize = 28.0f;
|
2013-08-23 23:50:35 +00:00
|
|
|
|
2017-03-21 10:24:44 +00:00
|
|
|
vec2 OldPos = InitPos + ExDirection * PhysSize * 1.5f;
|
2014-01-27 04:06:23 +00:00
|
|
|
vec2 NewPos = OldPos;
|
|
|
|
|
2017-03-21 10:24:44 +00:00
|
|
|
bool DoBreak = false;
|
2014-01-30 03:10:52 +00:00
|
|
|
int Hit = 0;
|
2014-01-27 04:06:23 +00:00
|
|
|
|
|
|
|
do {
|
|
|
|
OldPos = NewPos;
|
2014-04-29 01:34:23 +00:00
|
|
|
NewPos = OldPos + ExDirection * m_pClient->m_Tuning[g_Config.m_ClDummy].m_HookFireSpeed;
|
2014-01-27 04:06:23 +00:00
|
|
|
|
2017-03-21 10:24:44 +00:00
|
|
|
if (distance(InitPos, NewPos) > m_pClient->m_Tuning[g_Config.m_ClDummy].m_HookLength)
|
2014-01-27 04:06:23 +00:00
|
|
|
{
|
2017-03-21 10:24:44 +00:00
|
|
|
NewPos = InitPos + normalize(NewPos-InitPos) * m_pClient->m_Tuning[g_Config.m_ClDummy].m_HookLength;
|
|
|
|
DoBreak = true;
|
2014-01-27 04:06:23 +00:00
|
|
|
}
|
|
|
|
|
2017-03-21 10:24:44 +00:00
|
|
|
int TeleNr = 0;
|
|
|
|
Hit = Collision()->IntersectLineTeleHook(OldPos, NewPos, &FinishPos, 0x0, &TeleNr);
|
2014-01-27 04:06:23 +00:00
|
|
|
|
2017-03-21 10:24:44 +00:00
|
|
|
if(!DoBreak && Hit) {
|
2015-11-08 09:20:10 +00:00
|
|
|
if (Hit != TILE_NOHOOK)
|
2014-05-06 14:17:41 +00:00
|
|
|
Graphics()->SetColor(130.0f/255.0f, 232.0f/255.0f, 160.0f/255.0f, Alpha);
|
2014-01-30 03:10:52 +00:00
|
|
|
}
|
|
|
|
|
2017-03-21 10:24:44 +00:00
|
|
|
if(m_pClient->m_Tuning[g_Config.m_ClDummy].m_PlayerHooking && m_pClient->IntersectCharacter(OldPos, FinishPos, FinishPos, pPlayerInfo->m_ClientID) != -1)
|
2014-01-30 03:10:52 +00:00
|
|
|
{
|
2014-05-06 14:17:41 +00:00
|
|
|
Graphics()->SetColor(1.0f, 1.0f, 0.0f, Alpha);
|
2014-01-27 04:06:23 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-01-30 03:10:52 +00:00
|
|
|
if(Hit)
|
|
|
|
break;
|
|
|
|
|
2014-04-26 18:29:42 +00:00
|
|
|
NewPos.x = round_to_int(NewPos.x);
|
|
|
|
NewPos.y = round_to_int(NewPos.y);
|
2013-08-23 23:50:35 +00:00
|
|
|
|
2014-02-17 22:12:29 +00:00
|
|
|
if (OldPos == NewPos)
|
|
|
|
break;
|
|
|
|
|
2014-04-26 18:29:42 +00:00
|
|
|
ExDirection.x = round_to_int(ExDirection.x*256.0f) / 256.0f;
|
|
|
|
ExDirection.y = round_to_int(ExDirection.y*256.0f) / 256.0f;
|
2017-03-21 10:24:44 +00:00
|
|
|
} while (!DoBreak);
|
2013-08-23 23:50:35 +00:00
|
|
|
|
2017-03-21 10:24:44 +00:00
|
|
|
IGraphics::CLineItem LineItem(InitPos.x, InitPos.y, FinishPos.x, FinishPos.y);
|
2013-08-23 23:50:35 +00:00
|
|
|
Graphics()->LinesDraw(&LineItem, 1);
|
|
|
|
Graphics()->LinesEnd();
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id);
|
2009-10-27 14:38:53 +00:00
|
|
|
Graphics()->QuadsBegin();
|
2010-05-29 07:25:38 +00:00
|
|
|
Graphics()->QuadsSetRotation(State.GetAttach()->m_Angle*pi*2+Angle);
|
2008-01-12 17:09:00 +00:00
|
|
|
|
|
|
|
// normal weapons
|
2010-05-29 07:25:38 +00:00
|
|
|
int iw = clamp(Player.m_Weapon, 0, NUM_WEAPONS-1);
|
|
|
|
RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[iw].m_pSpriteBody, Direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0);
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2014-01-24 22:11:33 +00:00
|
|
|
if (OtherTeam)
|
2014-05-17 21:00:52 +00:00
|
|
|
Graphics()->SetColor(1.0f, 1.0f, 1.0f, g_Config.m_ClShowOthersAlpha / 100.0f);
|
2014-01-24 22:11:33 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 Dir = Direction;
|
|
|
|
float Recoil = 0.0f;
|
2008-01-12 17:09:00 +00:00
|
|
|
vec2 p;
|
2010-05-29 07:25:38 +00:00
|
|
|
if (Player.m_Weapon == WEAPON_HAMMER)
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
|
|
|
// Static position for hammer
|
2010-05-29 07:25:38 +00:00
|
|
|
p = Position + vec2(State.GetAttach()->m_X, State.GetAttach()->m_Y);
|
|
|
|
p.y += g_pData->m_Weapons.m_aId[iw].m_Offsety;
|
2008-01-12 17:09:00 +00:00
|
|
|
// if attack is under way, bash stuffs
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Direction.x < 0)
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Graphics()->QuadsSetRotation(-pi/2-State.GetAttach()->m_Angle*pi*2);
|
|
|
|
p.x -= g_pData->m_Weapons.m_aId[iw].m_Offsetx;
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Graphics()->QuadsSetRotation(-pi/2+State.GetAttach()->m_Angle*pi*2);
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderTools()->DrawSprite(p.x, p.y, g_pData->m_Weapons.m_aId[iw].m_VisualSize);
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if (Player.m_Weapon == WEAPON_NINJA)
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
p = Position;
|
|
|
|
p.y += g_pData->m_Weapons.m_aId[iw].m_Offsety;
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Direction.x < 0)
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Graphics()->QuadsSetRotation(-pi/2-State.GetAttach()->m_Angle*pi*2);
|
|
|
|
p.x -= g_pData->m_Weapons.m_aId[iw].m_Offsetx;
|
|
|
|
m_pClient->m_pEffects->PowerupShine(p+vec2(32,0), vec2(32,12));
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Graphics()->QuadsSetRotation(-pi/2+State.GetAttach()->m_Angle*pi*2);
|
|
|
|
m_pClient->m_pEffects->PowerupShine(p-vec2(32,0), vec2(32,12));
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderTools()->DrawSprite(p.x, p.y, g_pData->m_Weapons.m_aId[iw].m_VisualSize);
|
2008-01-12 17:09:00 +00:00
|
|
|
|
|
|
|
// HADOKEN
|
2010-05-29 07:25:38 +00:00
|
|
|
if ((Client()->GameTick()-Player.m_AttackTick) <= (SERVER_TICK_SPEED / 6) && g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles)
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int IteX = rand() % g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles;
|
2012-01-09 23:49:31 +00:00
|
|
|
static int s_LastIteX = IteX;
|
2010-11-16 23:38:20 +00:00
|
|
|
if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
|
|
|
|
{
|
|
|
|
const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
|
|
|
|
if(pInfo->m_Paused)
|
|
|
|
IteX = s_LastIteX;
|
|
|
|
else
|
|
|
|
s_LastIteX = IteX;
|
|
|
|
}
|
2012-01-09 23:49:31 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)
|
|
|
|
IteX = s_LastIteX;
|
|
|
|
else
|
|
|
|
s_LastIteX = IteX;
|
|
|
|
}
|
2010-11-16 23:38:20 +00:00
|
|
|
if(g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX])
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 Dir = vec2(pPlayerChar->m_X,pPlayerChar->m_Y) - vec2(pPrevChar->m_X, pPrevChar->m_Y);
|
|
|
|
Dir = normalize(Dir);
|
2011-04-13 18:37:12 +00:00
|
|
|
float HadOkenAngle = GetAngle(Dir);
|
2017-09-16 16:31:44 +00:00
|
|
|
Graphics()->QuadsSetRotation(HadOkenAngle);
|
2008-01-12 17:09:00 +00:00
|
|
|
//float offsety = -data->weapons[iw].muzzleoffsety;
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX], 0);
|
|
|
|
vec2 DirY(-Dir.y,Dir.x);
|
|
|
|
p = Position;
|
|
|
|
float OffsetX = g_pData->m_Weapons.m_aId[iw].m_Muzzleoffsetx;
|
|
|
|
p -= Dir * OffsetX;
|
|
|
|
RenderTools()->DrawSprite(p.x, p.y, 160.0f);
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// TODO: should be an animation
|
2010-05-29 07:25:38 +00:00
|
|
|
Recoil = 0;
|
2012-01-09 23:49:31 +00:00
|
|
|
static float s_LastIntraTick = IntraTick;
|
|
|
|
if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
|
|
|
|
s_LastIntraTick = IntraTick;
|
|
|
|
|
|
|
|
float a = (Client()->GameTick()-Player.m_AttackTick+s_LastIntraTick)/5.0f;
|
2008-01-12 17:09:00 +00:00
|
|
|
if(a < 1)
|
2010-05-29 07:25:38 +00:00
|
|
|
Recoil = sinf(a*pi);
|
|
|
|
p = Position + Dir * g_pData->m_Weapons.m_aId[iw].m_Offsetx - Dir*Recoil*10.0f;
|
|
|
|
p.y += g_pData->m_Weapons.m_aId[iw].m_Offsety;
|
2014-05-06 14:25:00 +00:00
|
|
|
if (Player.m_Weapon == WEAPON_GUN && g_Config.m_ClOldGunPosition)
|
|
|
|
p.y -= 8;
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderTools()->DrawSprite(p.x, p.y, g_pData->m_Weapons.m_aId[iw].m_VisualSize);
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if (Player.m_Weapon == WEAPON_GUN || Player.m_Weapon == WEAPON_SHOTGUN)
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
|
|
|
// check if we're firing stuff
|
2010-05-29 07:25:38 +00:00
|
|
|
if(g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles)//prev.attackticks)
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
float Alpha = 0.0f;
|
|
|
|
int Phase1Tick = (Client()->GameTick() - Player.m_AttackTick);
|
|
|
|
if (Phase1Tick < (g_pData->m_Weapons.m_aId[iw].m_Muzzleduration + 3))
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
float t = ((((float)Phase1Tick) + IntraTick)/(float)g_pData->m_Weapons.m_aId[iw].m_Muzzleduration);
|
|
|
|
Alpha = mix(2.0f, 0.0f, min(1.0f,max(0.0f,t)));
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int IteX = rand() % g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles;
|
2012-01-09 23:49:31 +00:00
|
|
|
static int s_LastIteX = IteX;
|
2012-01-09 22:43:53 +00:00
|
|
|
if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
|
|
|
|
{
|
|
|
|
const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
|
|
|
|
if(pInfo->m_Paused)
|
|
|
|
IteX = s_LastIteX;
|
|
|
|
else
|
|
|
|
s_LastIteX = IteX;
|
|
|
|
}
|
2012-01-09 23:49:31 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)
|
|
|
|
IteX = s_LastIteX;
|
|
|
|
else
|
|
|
|
s_LastIteX = IteX;
|
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
if (Alpha > 0.0f && g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX])
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
float OffsetY = -g_pData->m_Weapons.m_aId[iw].m_Muzzleoffsety;
|
|
|
|
RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX], Direction.x < 0 ? SPRITE_FLAG_FLIP_Y : 0);
|
|
|
|
if(Direction.x < 0)
|
|
|
|
OffsetY = -OffsetY;
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 DirY(-Dir.y,Dir.x);
|
|
|
|
vec2 MuzzlePos = p + Dir * g_pData->m_Weapons.m_aId[iw].m_Muzzleoffsetx + DirY * OffsetY;
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderTools()->DrawSprite(MuzzlePos.x, MuzzlePos.y, g_pData->m_Weapons.m_aId[iw].m_VisualSize);
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-10-27 14:38:53 +00:00
|
|
|
Graphics()->QuadsEnd();
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2014-01-24 22:11:33 +00:00
|
|
|
if (OtherTeam)
|
|
|
|
{
|
2014-05-17 21:00:52 +00:00
|
|
|
RenderInfo.m_ColorBody.a = g_Config.m_ClShowOthersAlpha / 100.0f;
|
|
|
|
RenderInfo.m_ColorFeet.a = g_Config.m_ClShowOthersAlpha / 100.0f;
|
2014-01-24 22:11:33 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
switch (Player.m_Weapon)
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
case WEAPON_GUN: RenderHand(&RenderInfo, p, Direction, -3*pi/4, vec2(-15, 4)); break;
|
|
|
|
case WEAPON_SHOTGUN: RenderHand(&RenderInfo, p, Direction, -pi/2, vec2(-5, 4)); break;
|
|
|
|
case WEAPON_GRENADE: RenderHand(&RenderInfo, p, Direction, -pi/2, vec2(-4, 7)); break;
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// render the "shadow" tee
|
2014-03-21 13:01:14 +00:00
|
|
|
if(pInfo.m_Local && (g_Config.m_Debug || g_Config.m_ClUnpredictedShadow))
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 GhostPosition = mix(vec2(pPrevChar->m_X, pPrevChar->m_Y), vec2(pPlayerChar->m_X, pPlayerChar->m_Y), Client()->IntraGameTick());
|
|
|
|
CTeeRenderInfo Ghost = RenderInfo;
|
|
|
|
Ghost.m_ColorBody.a = 0.5f;
|
|
|
|
Ghost.m_ColorFeet.a = 0.5f;
|
2011-04-09 06:41:31 +00:00
|
|
|
RenderTools()->RenderTee(&State, &Ghost, Player.m_Emote, Direction, GhostPosition, true); // render ghost
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderInfo.m_Size = 64.0f; // force some settings
|
2014-01-21 23:31:17 +00:00
|
|
|
|
2014-01-24 22:11:33 +00:00
|
|
|
if (OtherTeam)
|
2014-01-21 23:31:17 +00:00
|
|
|
{
|
2014-05-17 21:00:52 +00:00
|
|
|
RenderInfo.m_ColorBody.a = g_Config.m_ClShowOthersAlpha / 100.0f;
|
|
|
|
RenderInfo.m_ColorFeet.a = g_Config.m_ClShowOthersAlpha / 100.0f;
|
2014-01-21 23:31:17 +00:00
|
|
|
}
|
|
|
|
|
2014-04-26 19:00:14 +00:00
|
|
|
if (g_Config.m_ClShowDirection && (!pInfo.m_Local || DemoPlayer()->IsPlaying()))
|
|
|
|
{
|
2014-04-30 23:42:44 +00:00
|
|
|
if (Player.m_Direction == -1)
|
2014-04-26 19:00:14 +00:00
|
|
|
{
|
|
|
|
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_ARROW].m_Id);
|
|
|
|
Graphics()->QuadsBegin();
|
2014-05-06 11:48:08 +00:00
|
|
|
if (OtherTeam)
|
2014-05-17 21:00:52 +00:00
|
|
|
Graphics()->SetColor(1.0f, 1.0f, 1.0f, g_Config.m_ClShowOthersAlpha / 100.0f);
|
2014-04-30 23:42:44 +00:00
|
|
|
IGraphics::CQuadItem QuadItem(Position.x-30, Position.y - 70, 22, 22);
|
2017-09-16 16:31:44 +00:00
|
|
|
Graphics()->QuadsSetRotation(pi);
|
2014-04-30 23:42:44 +00:00
|
|
|
Graphics()->QuadsDraw(&QuadItem, 1);
|
|
|
|
Graphics()->QuadsEnd();
|
|
|
|
}
|
|
|
|
else if (Player.m_Direction == 1)
|
|
|
|
{
|
|
|
|
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_ARROW].m_Id);
|
|
|
|
Graphics()->QuadsBegin();
|
2014-05-06 11:48:08 +00:00
|
|
|
if (OtherTeam)
|
2014-05-17 21:00:52 +00:00
|
|
|
Graphics()->SetColor(1.0f, 1.0f, 1.0f, g_Config.m_ClShowOthersAlpha / 100.0f);
|
2014-04-30 23:42:44 +00:00
|
|
|
IGraphics::CQuadItem QuadItem(Position.x+30, Position.y - 70, 22, 22);
|
2014-04-26 19:00:14 +00:00
|
|
|
Graphics()->QuadsDraw(&QuadItem, 1);
|
|
|
|
Graphics()->QuadsEnd();
|
|
|
|
}
|
|
|
|
if (Player.m_Jumped&1)
|
|
|
|
{
|
|
|
|
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_ARROW].m_Id);
|
|
|
|
Graphics()->QuadsBegin();
|
2014-05-06 11:48:08 +00:00
|
|
|
if (OtherTeam)
|
2014-05-17 21:00:52 +00:00
|
|
|
Graphics()->SetColor(1.0f, 1.0f, 1.0f, g_Config.m_ClShowOthersAlpha / 100.0f);
|
2014-04-30 23:42:44 +00:00
|
|
|
IGraphics::CQuadItem QuadItem(Position.x, Position.y - 70, 22, 22);
|
2017-09-16 16:31:44 +00:00
|
|
|
Graphics()->QuadsSetRotation(3 / 2 * pi);
|
2014-04-26 19:00:14 +00:00
|
|
|
Graphics()->QuadsDraw(&QuadItem, 1);
|
|
|
|
Graphics()->QuadsEnd();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-24 22:11:33 +00:00
|
|
|
RenderTools()->RenderTee(&State, &RenderInfo, Player.m_Emote, Direction, Position, OtherTeam);
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2011-03-01 17:31:20 +00:00
|
|
|
if(Player.m_PlayerFlags&PLAYERFLAG_CHATTING)
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id);
|
2009-10-27 14:38:53 +00:00
|
|
|
Graphics()->QuadsBegin();
|
2010-05-29 07:25:38 +00:00
|
|
|
RenderTools()->SelectSprite(SPRITE_DOTDOT);
|
2014-08-22 00:32:05 +00:00
|
|
|
if (OtherTeam)
|
|
|
|
Graphics()->SetColor(1.0f, 1.0f, 1.0f, g_Config.m_ClShowOthersAlpha / 100.0f);
|
2010-05-29 07:25:38 +00:00
|
|
|
IGraphics::CQuadItem QuadItem(Position.x + 24, Position.y - 40, 64,64);
|
|
|
|
Graphics()->QuadsDraw(&QuadItem, 1);
|
2009-10-27 14:38:53 +00:00
|
|
|
Graphics()->QuadsEnd();
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
|
|
|
|
2011-02-12 10:40:36 +00:00
|
|
|
if (m_pClient->m_aClients[pInfo.m_ClientID].m_EmoticonStart != -1 && m_pClient->m_aClients[pInfo.m_ClientID].m_EmoticonStart + 2 * Client()->GameTickSpeed() > Client()->GameTick())
|
2008-01-12 17:09:00 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id);
|
2009-10-27 14:38:53 +00:00
|
|
|
Graphics()->QuadsBegin();
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2011-02-12 10:40:36 +00:00
|
|
|
int SinceStart = Client()->GameTick() - m_pClient->m_aClients[pInfo.m_ClientID].m_EmoticonStart;
|
|
|
|
int FromEnd = m_pClient->m_aClients[pInfo.m_ClientID].m_EmoticonStart + 2 * Client()->GameTickSpeed() - Client()->GameTick();
|
2008-01-12 17:09:00 +00:00
|
|
|
|
|
|
|
float a = 1;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if (FromEnd < Client()->GameTickSpeed() / 5)
|
|
|
|
a = FromEnd / (Client()->GameTickSpeed() / 5.0);
|
2008-01-12 17:09:00 +00:00
|
|
|
|
|
|
|
float h = 1;
|
2010-05-29 07:25:38 +00:00
|
|
|
if (SinceStart < Client()->GameTickSpeed() / 10)
|
|
|
|
h = SinceStart / (Client()->GameTickSpeed() / 10.0);
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
float Wiggle = 0;
|
|
|
|
if (SinceStart < Client()->GameTickSpeed() / 5)
|
|
|
|
Wiggle = SinceStart / (Client()->GameTickSpeed() / 5.0);
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
float WiggleAngle = sinf(5*Wiggle);
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
Graphics()->QuadsSetRotation(pi/6*WiggleAngle);
|
2008-01-12 17:09:00 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
Graphics()->SetColor(1.0f,1.0f,1.0f,a);
|
2014-08-22 00:32:05 +00:00
|
|
|
if (OtherTeam)
|
2017-03-21 10:24:44 +00:00
|
|
|
Graphics()->SetColor(1.0f, 1.0f, 1.0f, a * (float)g_Config.m_ClShowOthersAlpha / 100.0f);
|
2008-01-12 17:09:00 +00:00
|
|
|
// client_datas::emoticon is an offset from the first emoticon
|
2011-02-12 10:40:36 +00:00
|
|
|
RenderTools()->SelectSprite(SPRITE_OOP + m_pClient->m_aClients[pInfo.m_ClientID].m_Emoticon);
|
2010-05-29 07:25:38 +00:00
|
|
|
IGraphics::CQuadItem QuadItem(Position.x, Position.y - 23 - 32*h, 64, 64*h);
|
|
|
|
Graphics()->QuadsDraw(&QuadItem, 1);
|
2009-10-27 14:38:53 +00:00
|
|
|
Graphics()->QuadsEnd();
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
2013-10-09 14:02:23 +00:00
|
|
|
|
2015-09-10 11:09:38 +00:00
|
|
|
if(g_Config.m_ClNameplates && m_pClient->AntiPingPlayers())
|
2013-10-09 14:02:23 +00:00
|
|
|
{
|
|
|
|
float FontSize = 18.0f + 20.0f * g_Config.m_ClNameplatesSize / 100.0f;
|
2015-06-29 00:06:27 +00:00
|
|
|
float FontSizeClan = 18.0f + 20.0f * g_Config.m_ClNameplatesClanSize / 100.0f;
|
2013-10-09 14:02:23 +00:00
|
|
|
// render name plate
|
|
|
|
if(!pPlayerInfo->m_Local)
|
|
|
|
{
|
|
|
|
float a = 1;
|
|
|
|
if(g_Config.m_ClNameplatesAlways == 0)
|
2014-05-10 12:31:00 +00:00
|
|
|
a = clamp(1-powf(distance(m_pClient->m_pControls->m_TargetPos[g_Config.m_ClDummy], Position)/200.0f,16.0f), 0.0f, 1.0f);
|
2015-06-21 22:44:26 +00:00
|
|
|
|
2013-10-09 14:02:23 +00:00
|
|
|
const char *pName = m_pClient->m_aClients[pPlayerInfo->m_ClientID].m_aName;
|
|
|
|
float tw = TextRender()->TextWidth(0, FontSize, pName, -1);
|
2015-06-21 22:44:26 +00:00
|
|
|
|
2014-04-12 14:55:01 +00:00
|
|
|
vec3 rgb = vec3(1.0f, 1.0f, 1.0f);
|
|
|
|
if(g_Config.m_ClNameplatesTeamcolors && m_pClient->m_Teams.Team(pPlayerInfo->m_ClientID))
|
|
|
|
rgb = HslToRgb(vec3(m_pClient->m_Teams.Team(pPlayerInfo->m_ClientID) / 64.0f, 1.0f, 0.75f));
|
|
|
|
|
2014-01-24 22:11:33 +00:00
|
|
|
if (OtherTeam)
|
|
|
|
{
|
|
|
|
TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.2f);
|
2014-05-17 21:00:52 +00:00
|
|
|
TextRender()->TextColor(rgb.r, rgb.g, rgb.b, g_Config.m_ClShowOthersAlpha / 100.0f);
|
2014-01-24 22:11:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.5f*a);
|
2014-04-12 14:55:01 +00:00
|
|
|
TextRender()->TextColor(rgb.r, rgb.g, rgb.b, a);
|
2014-01-24 22:11:33 +00:00
|
|
|
}
|
2013-10-09 14:02:23 +00:00
|
|
|
if(g_Config.m_ClNameplatesTeamcolors && m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS)
|
|
|
|
{
|
|
|
|
if(pPlayerInfo->m_Team == TEAM_RED)
|
|
|
|
TextRender()->TextColor(1.0f, 0.5f, 0.5f, a);
|
|
|
|
else if(pPlayerInfo->m_Team == TEAM_BLUE)
|
|
|
|
TextRender()->TextColor(0.7f, 0.7f, 1.0f, a);
|
|
|
|
}
|
2015-06-21 22:44:26 +00:00
|
|
|
|
2013-10-09 14:02:23 +00:00
|
|
|
TextRender()->Text(0, Position.x-tw/2.0f, Position.y-FontSize-38.0f, FontSize, pName, -1);
|
2015-06-21 22:44:26 +00:00
|
|
|
|
|
|
|
if(g_Config.m_ClNameplatesClan)
|
|
|
|
{
|
|
|
|
const char *pClan = m_pClient->m_aClients[pPlayerInfo->m_ClientID].m_aClan;
|
2015-06-29 00:06:27 +00:00
|
|
|
float tw_clan = TextRender()->TextWidth(0, FontSizeClan, pClan, -1);
|
|
|
|
TextRender()->Text(0, Position.x-tw_clan/2.0f, Position.y-FontSize-FontSizeClan-38.0f, FontSizeClan, pClan, -1);
|
2015-06-21 22:44:26 +00:00
|
|
|
}
|
|
|
|
|
2013-10-09 14:02:23 +00:00
|
|
|
if(g_Config.m_Debug) // render client id when in debug aswell
|
|
|
|
{
|
|
|
|
char aBuf[128];
|
|
|
|
str_format(aBuf, sizeof(aBuf),"%d", pPlayerInfo->m_ClientID);
|
2015-06-29 00:06:27 +00:00
|
|
|
float Offset = g_Config.m_ClNameplatesClan ? (FontSize * 2 + FontSizeClan) : (FontSize * 2);
|
2015-06-21 22:44:26 +00:00
|
|
|
float tw_id = TextRender()->TextWidth(0, FontSize, aBuf, -1);
|
|
|
|
TextRender()->Text(0, Position.x-tw_id/2.0f, Position.y-Offset-38.0f, 28.0f, aBuf, -1);
|
2013-10-09 14:02:23 +00:00
|
|
|
}
|
2015-07-09 00:08:14 +00:00
|
|
|
|
2013-10-09 14:02:23 +00:00
|
|
|
TextRender()->TextColor(1,1,1,1);
|
|
|
|
TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f);
|
|
|
|
}
|
|
|
|
}
|
2008-01-12 17:09:00 +00:00
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CPlayers::OnRender()
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2012-01-08 14:44:49 +00:00
|
|
|
// update RenderInfo for ninja
|
|
|
|
bool IsTeamplay = false;
|
|
|
|
if(m_pClient->m_Snap.m_pGameInfoObj)
|
|
|
|
IsTeamplay = (m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS) != 0;
|
|
|
|
for(int i = 0; i < MAX_CLIENTS; ++i)
|
|
|
|
{
|
|
|
|
m_aRenderInfo[i] = m_pClient->m_aClients[i].m_RenderInfo;
|
2014-03-28 12:39:30 +00:00
|
|
|
if(m_pClient->m_Snap.m_aCharacters[i].m_Cur.m_Weapon == WEAPON_NINJA && g_Config.m_ClShowNinja)
|
2012-01-08 14:44:49 +00:00
|
|
|
{
|
|
|
|
// change the skin for the player to the ninja
|
|
|
|
int Skin = m_pClient->m_pSkins->Find("x_ninja");
|
|
|
|
if(Skin != -1)
|
|
|
|
{
|
|
|
|
if(IsTeamplay)
|
|
|
|
m_aRenderInfo[i].m_Texture = m_pClient->m_pSkins->Get(Skin)->m_ColorTexture;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_aRenderInfo[i].m_Texture = m_pClient->m_pSkins->Get(Skin)->m_OrgTexture;
|
|
|
|
m_aRenderInfo[i].m_ColorBody = vec4(1,1,1,1);
|
|
|
|
m_aRenderInfo[i].m_ColorFeet = vec4(1,1,1,1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-09 14:02:23 +00:00
|
|
|
static vec2 PrevPos[MAX_CLIENTS];
|
|
|
|
static vec2 SmoothPos[MAX_CLIENTS];
|
|
|
|
static int MoveCnt[MAX_CLIENTS] = {0};
|
|
|
|
static vec2 PredictedPos[MAX_CLIENTS];
|
2015-07-09 00:08:14 +00:00
|
|
|
|
2013-10-09 14:02:23 +00:00
|
|
|
static int predcnt = 0;
|
|
|
|
|
2015-09-10 11:09:38 +00:00
|
|
|
if (m_pClient->AntiPingPlayers())
|
2013-10-09 14:02:23 +00:00
|
|
|
{
|
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
|
|
|
if(!m_pClient->m_Snap.m_aCharacters[i].m_Active)
|
|
|
|
continue;
|
|
|
|
const void *pPrevInfo = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_PLAYERINFO, i);
|
|
|
|
const void *pInfo = Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_PLAYERINFO, i);
|
|
|
|
|
|
|
|
if(pPrevInfo && pInfo)
|
|
|
|
{
|
|
|
|
CNetObj_Character PrevChar = m_pClient->m_Snap.m_aCharacters[i].m_Prev;
|
|
|
|
CNetObj_Character CurChar = m_pClient->m_Snap.m_aCharacters[i].m_Cur;
|
|
|
|
|
|
|
|
Predict(
|
|
|
|
&PrevChar,
|
|
|
|
&CurChar,
|
|
|
|
(const CNetObj_PlayerInfo *)pPrevInfo,
|
|
|
|
(const CNetObj_PlayerInfo *)pInfo,
|
|
|
|
PrevPos[i],
|
|
|
|
SmoothPos[i],
|
|
|
|
MoveCnt[i],
|
|
|
|
PredictedPos[i]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-10 11:09:38 +00:00
|
|
|
if(m_pClient->AntiPingPlayers() && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK)
|
2013-10-09 14:02:23 +00:00
|
|
|
if(m_pClient->m_Snap.m_pLocalCharacter && !(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER))
|
|
|
|
{
|
|
|
|
// double ping = m_pClient->m_Snap.m_pLocalInfo->m_Latency;
|
|
|
|
// static double fps;
|
|
|
|
// fps = mix(fps, (1. / Client()->RenderFrameTime()), 0.1);
|
|
|
|
|
|
|
|
// int predmax = (fps * ping / 1000.);
|
|
|
|
|
|
|
|
int predmax = 19;
|
|
|
|
// if( 0 <= predmax && predmax <= 100)
|
|
|
|
predcnt = (predcnt + 1) % predmax;
|
|
|
|
// else
|
|
|
|
// predcnt = (predcnt + 1) % 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-11 17:55:23 +00:00
|
|
|
// render other players in two passes, first pass we render the other, second pass we render our self
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int p = 0; p < 4; p++)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2009-01-11 17:55:23 +00:00
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
|
|
|
// only render active characters
|
2010-05-29 07:25:38 +00:00
|
|
|
if(!m_pClient->m_Snap.m_aCharacters[i].m_Active)
|
2009-01-11 17:55:23 +00:00
|
|
|
continue;
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
const void *pPrevInfo = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_PLAYERINFO, i);
|
|
|
|
const void *pInfo = Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_PLAYERINFO, i);
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(pPrevInfo && pInfo)
|
2009-01-11 17:55:23 +00:00
|
|
|
{
|
|
|
|
//
|
2010-05-29 07:25:38 +00:00
|
|
|
bool Local = ((const CNetObj_PlayerInfo *)pInfo)->m_Local !=0;
|
|
|
|
if((p % 2) == 0 && Local) continue;
|
|
|
|
if((p % 2) == 1 && !Local) continue;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CNetObj_Character PrevChar = m_pClient->m_Snap.m_aCharacters[i].m_Prev;
|
|
|
|
CNetObj_Character CurChar = m_pClient->m_Snap.m_aCharacters[i].m_Cur;
|
|
|
|
|
|
|
|
if(p<2)
|
2013-10-09 14:02:23 +00:00
|
|
|
{
|
|
|
|
if(PrevChar.m_HookedPlayer != -1)
|
|
|
|
RenderHook(
|
|
|
|
&PrevChar,
|
|
|
|
&CurChar,
|
|
|
|
(const CNetObj_PlayerInfo *)pPrevInfo,
|
|
|
|
(const CNetObj_PlayerInfo *)pInfo,
|
|
|
|
PredictedPos[i],
|
|
|
|
PredictedPos[PrevChar.m_HookedPlayer]
|
|
|
|
);
|
|
|
|
else
|
|
|
|
RenderHook(
|
|
|
|
&PrevChar,
|
|
|
|
&CurChar,
|
|
|
|
(const CNetObj_PlayerInfo *)pPrevInfo,
|
|
|
|
(const CNetObj_PlayerInfo *)pInfo,
|
|
|
|
PredictedPos[i],
|
|
|
|
PredictedPos[i]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RenderPlayer(
|
2010-05-29 07:25:38 +00:00
|
|
|
&PrevChar,
|
|
|
|
&CurChar,
|
|
|
|
(const CNetObj_PlayerInfo *)pPrevInfo,
|
2013-10-09 14:02:23 +00:00
|
|
|
(const CNetObj_PlayerInfo *)pInfo,
|
|
|
|
PredictedPos[i]
|
2010-05-29 07:25:38 +00:00
|
|
|
);
|
2013-10-09 14:02:23 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
}
|
2009-01-11 17:55:23 +00:00
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
}
|