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. */
|
2008-08-14 18:46:52 +00:00
|
|
|
#include <new>
|
2011-01-18 18:09:53 +00:00
|
|
|
#include <engine/shared/config.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
#include "player.h"
|
2008-08-14 18:46:52 +00:00
|
|
|
|
2010-07-29 05:21:18 +00:00
|
|
|
#include <engine/server.h>
|
2010-07-30 12:50:09 +00:00
|
|
|
#include <engine/server/server.h>
|
2010-07-29 05:21:18 +00:00
|
|
|
#include "gamecontext.h"
|
|
|
|
#include <game/gamecore.h>
|
2010-07-29 14:53:25 +00:00
|
|
|
#include "gamemodes/DDRace.h"
|
2011-03-22 19:56:52 +00:00
|
|
|
#include <stdio.h>
|
2008-08-14 18:46:52 +00:00
|
|
|
|
2011-01-29 00:59:50 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
MACRO_ALLOC_POOL_ID_IMPL(CPlayer, MAX_CLIENTS)
|
2008-08-14 18:46:52 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
IServer *CPlayer::Server() const { return m_pGameServer->Server(); }
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2011-02-12 10:40:36 +00:00
|
|
|
CPlayer::CPlayer(CGameContext *pGameServer, int ClientID, int Team)
|
2008-08-14 18:46:52 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_pGameServer = pGameServer;
|
|
|
|
m_RespawnTick = Server()->Tick();
|
|
|
|
m_DieTick = Server()->Tick();
|
2010-05-31 20:35:47 +00:00
|
|
|
m_ScoreStartTick = Server()->Tick();
|
2011-04-19 08:42:48 +00:00
|
|
|
m_pCharacter = 0;
|
|
|
|
m_ClientID = ClientID;
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Team = GameServer()->m_pController->ClampTeam(Team);
|
2011-03-10 09:08:14 +00:00
|
|
|
m_SpectatorID = SPEC_FREEVIEW;
|
2010-10-09 17:14:42 +00:00
|
|
|
m_LastActionTick = Server()->Tick();
|
2011-08-13 00:11:06 +00:00
|
|
|
m_TeamChangeTick = Server()->Tick();
|
2011-04-09 06:41:31 +00:00
|
|
|
|
|
|
|
// DDRace
|
|
|
|
|
2011-03-22 19:49:12 +00:00
|
|
|
m_LastPlaytime = time_get();
|
|
|
|
m_LastTarget_x = 0;
|
|
|
|
m_LastTarget_y = 0;
|
2011-04-23 17:59:25 +00:00
|
|
|
m_Sent1stAfkWarning = 0;
|
|
|
|
m_Sent2ndAfkWarning = 0;
|
2011-02-03 13:39:00 +00:00
|
|
|
m_ChatScore = 0;
|
2010-08-22 13:17:57 +00:00
|
|
|
m_PauseInfo.m_Respawn = false;
|
Added the following settings to Close #123.
sv_time_in_broadcast, 1, 0, 1, CFGFLAG_SERVER, "Whether to display time in broadcast every interval or not by default, later the choice can be changed by players via chat commands"
sv_time_in_broadcast_interval, 1, 0, 60, CFGFLAG_SERVER, "How often to update the broadcast time"
sv_time_in_gametimer, 0, 0, 1, CFGFLAG_SERVER, "Whether to display time in the round/game timer or not by default, later the choice can be changed by players via chat commands"
Added the following Chat commands to give the player the choice over their settings:
"saytime", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTime, this, "Privately messages you your current time in this current running race"
"saytimeall", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTimeAll, this, "Publicly messages everyone your current time in this current running race"
"time", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTime, this, "Privately shows you your current time in this current running race in the broadcast message"
"broadcasttime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetBroadcastTime, this, "Personal Setting of showing time in the broadcast, broadcasttime s, where s = on for on, off for off, toggle for toggle and nothing to show current status"
"servergametime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetServerGameTime, this, "Personal Setting of showing time in the round/game timer, servergametime s, where s = on for on off for off, toggle for toggle and nothing to show current status"
Fixed Chat Command "eyeemote" and made it a set + toggle instead of just toggle for better bin techneques
Moved some vars from CCharacter to CPlayer to keep their status evern after death but not after disconnect.
So now players have the choice to see which timer they wanna see if any.
Note: These changes are all untested Stay away from this update on your main server until they are tested, i don't even know if they will compile propperly
2011-12-29 12:17:34 +00:00
|
|
|
m_EyeEmote = true;
|
|
|
|
m_BroadcastTime = g_Config.m_SvTimeInBroadcast;
|
|
|
|
m_BroadcastTime = g_Config.m_SvTimeInGameTimer;
|
|
|
|
m_GameTimerTime = true;
|
2011-12-29 12:39:51 +00:00
|
|
|
m_DefEmote = EMOTE_HAPPY;
|
Added the following settings to Close #123.
sv_time_in_broadcast, 1, 0, 1, CFGFLAG_SERVER, "Whether to display time in broadcast every interval or not by default, later the choice can be changed by players via chat commands"
sv_time_in_broadcast_interval, 1, 0, 60, CFGFLAG_SERVER, "How often to update the broadcast time"
sv_time_in_gametimer, 0, 0, 1, CFGFLAG_SERVER, "Whether to display time in the round/game timer or not by default, later the choice can be changed by players via chat commands"
Added the following Chat commands to give the player the choice over their settings:
"saytime", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTime, this, "Privately messages you your current time in this current running race"
"saytimeall", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTimeAll, this, "Publicly messages everyone your current time in this current running race"
"time", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTime, this, "Privately shows you your current time in this current running race in the broadcast message"
"broadcasttime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetBroadcastTime, this, "Personal Setting of showing time in the broadcast, broadcasttime s, where s = on for on, off for off, toggle for toggle and nothing to show current status"
"servergametime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetServerGameTime, this, "Personal Setting of showing time in the round/game timer, servergametime s, where s = on for on off for off, toggle for toggle and nothing to show current status"
Fixed Chat Command "eyeemote" and made it a set + toggle instead of just toggle for better bin techneques
Moved some vars from CCharacter to CPlayer to keep their status evern after death but not after disconnect.
So now players have the choice to see which timer they wanna see if any.
Note: These changes are all untested Stay away from this update on your main server until they are tested, i don't even know if they will compile propperly
2011-12-29 12:17:34 +00:00
|
|
|
m_DefEmoteReset = -1;
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-13 05:35:13 +00:00
|
|
|
GameServer()->Score()->PlayerData(ClientID)->Reset();
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2010-10-29 21:28:15 +00:00
|
|
|
m_IsUsingDDRaceClient = false;
|
2011-01-06 05:08:12 +00:00
|
|
|
m_ShowOthers = false;
|
2010-12-13 22:16:53 +00:00
|
|
|
|
|
|
|
// Variable initialized:
|
2011-01-24 20:22:04 +00:00
|
|
|
m_Last_Team = 0;
|
2011-09-07 22:51:55 +00:00
|
|
|
#if defined(CONF_SQL)
|
|
|
|
m_LastSQLQuery = 0;
|
|
|
|
#endif
|
2008-08-14 18:46:52 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CPlayer::~CPlayer()
|
2008-09-24 09:03:49 +00:00
|
|
|
{
|
2011-04-19 08:42:48 +00:00
|
|
|
delete m_pCharacter;
|
|
|
|
m_pCharacter = 0;
|
2008-09-24 09:03:49 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CPlayer::Tick()
|
2008-08-14 18:46:52 +00:00
|
|
|
{
|
2011-01-18 18:09:53 +00:00
|
|
|
#ifdef CONF_DEBUG
|
|
|
|
if(!g_Config.m_DbgDummies || m_ClientID < MAX_CLIENTS-g_Config.m_DbgDummies)
|
|
|
|
#endif
|
2010-09-21 23:00:33 +00:00
|
|
|
if(!Server()->ClientIngame(m_ClientID))
|
|
|
|
return;
|
|
|
|
|
2011-02-03 13:39:00 +00:00
|
|
|
if (m_ChatScore > 0)
|
|
|
|
m_ChatScore--;
|
|
|
|
|
2011-06-06 20:18:37 +00:00
|
|
|
if (m_ForcePauseTime > 0)
|
|
|
|
m_ForcePauseTime--;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
Server()->SetClientScore(m_ClientID, m_Score);
|
2008-08-14 18:46:52 +00:00
|
|
|
|
|
|
|
// do latency stuff
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
IServer::CClientInfo Info;
|
|
|
|
if(Server()->GetClientInfo(m_ClientID, &Info))
|
2008-08-14 18:46:52 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Latency.m_Accum += Info.m_Latency;
|
|
|
|
m_Latency.m_AccumMax = max(m_Latency.m_AccumMax, Info.m_Latency);
|
|
|
|
m_Latency.m_AccumMin = min(m_Latency.m_AccumMin, Info.m_Latency);
|
2008-08-14 18:46:52 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
// each second
|
|
|
|
if(Server()->Tick()%Server()->TickSpeed() == 0)
|
2008-08-14 18:46:52 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Latency.m_Avg = m_Latency.m_Accum/Server()->TickSpeed();
|
|
|
|
m_Latency.m_Max = m_Latency.m_AccumMax;
|
|
|
|
m_Latency.m_Min = m_Latency.m_AccumMin;
|
|
|
|
m_Latency.m_Accum = 0;
|
|
|
|
m_Latency.m_AccumMin = 1000;
|
|
|
|
m_Latency.m_AccumMax = 0;
|
2008-08-14 18:46:52 +00:00
|
|
|
}
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2011-07-05 20:58:54 +00:00
|
|
|
if(!m_pCharacter && m_Team == TEAM_SPECTATORS && m_SpectatorID == SPEC_FREEVIEW)
|
2011-07-23 10:03:15 +00:00
|
|
|
m_ViewPos -= vec2(clamp(m_ViewPos.x-m_LatestActivity.m_TargetX, -500.0f, 500.0f), clamp(m_ViewPos.y-m_LatestActivity.m_TargetY, -400.0f, 400.0f));
|
2011-07-05 20:58:54 +00:00
|
|
|
|
2011-04-19 08:42:48 +00:00
|
|
|
if(!m_pCharacter && m_DieTick+Server()->TickSpeed()*3 <= Server()->Tick())
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Spawning = true;
|
2008-09-24 14:54:51 +00:00
|
|
|
|
2011-04-19 08:42:48 +00:00
|
|
|
if(m_pCharacter)
|
2008-09-24 14:54:51 +00:00
|
|
|
{
|
2011-04-19 08:42:48 +00:00
|
|
|
if(m_pCharacter->IsAlive())
|
2008-09-24 14:54:51 +00:00
|
|
|
{
|
2011-04-19 08:42:48 +00:00
|
|
|
m_ViewPos = m_pCharacter->m_Pos;
|
2008-09-24 14:54:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-04-19 08:42:48 +00:00
|
|
|
delete m_pCharacter;
|
|
|
|
m_pCharacter = 0;
|
2008-09-24 14:54:51 +00:00
|
|
|
}
|
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(m_Spawning && m_RespawnTick <= Server()->Tick())
|
|
|
|
TryRespawn();
|
2008-08-14 18:46:52 +00:00
|
|
|
}
|
|
|
|
|
2011-03-10 09:08:14 +00:00
|
|
|
void CPlayer::PostTick()
|
|
|
|
{
|
|
|
|
// update latency value
|
|
|
|
if(m_PlayerFlags&PLAYERFLAG_SCOREBOARD)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < MAX_CLIENTS; ++i)
|
|
|
|
{
|
|
|
|
if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
|
|
|
|
m_aActLatency[i] = GameServer()->m_apPlayers[i]->m_Latency.m_Min;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// update view pos for spectators
|
|
|
|
if(m_Team == TEAM_SPECTATORS && m_SpectatorID != SPEC_FREEVIEW && GameServer()->m_apPlayers[m_SpectatorID])
|
|
|
|
m_ViewPos = GameServer()->m_apPlayers[m_SpectatorID]->m_ViewPos;
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CPlayer::Snap(int SnappingClient)
|
2008-08-14 18:46:52 +00:00
|
|
|
{
|
2011-01-18 18:09:53 +00:00
|
|
|
#ifdef CONF_DEBUG
|
|
|
|
if(!g_Config.m_DbgDummies || m_ClientID < MAX_CLIENTS-g_Config.m_DbgDummies)
|
|
|
|
#endif
|
2010-09-21 23:00:33 +00:00
|
|
|
if(!Server()->ClientIngame(m_ClientID))
|
|
|
|
return;
|
|
|
|
|
2010-12-16 02:29:08 +00:00
|
|
|
CNetObj_ClientInfo *pClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, m_ClientID, sizeof(CNetObj_ClientInfo)));
|
|
|
|
if(!pClientInfo)
|
|
|
|
return;
|
2010-05-29 07:25:38 +00:00
|
|
|
|
2011-03-15 10:23:49 +00:00
|
|
|
StrToInts(&pClientInfo->m_Name0, 4, Server()->ClientName(m_ClientID));
|
|
|
|
StrToInts(&pClientInfo->m_Clan0, 3, Server()->ClientClan(m_ClientID));
|
|
|
|
pClientInfo->m_Country = Server()->ClientCountry(m_ClientID);
|
2010-12-16 02:29:08 +00:00
|
|
|
StrToInts(&pClientInfo->m_Skin0, 6, m_TeeInfos.m_SkinName);
|
|
|
|
pClientInfo->m_UseCustomColor = m_TeeInfos.m_UseCustomColor;
|
|
|
|
pClientInfo->m_ColorBody = m_TeeInfos.m_ColorBody;
|
|
|
|
pClientInfo->m_ColorFeet = m_TeeInfos.m_ColorFeet;
|
2010-08-23 19:37:27 +00:00
|
|
|
|
2010-12-16 02:29:08 +00:00
|
|
|
CNetObj_PlayerInfo *pPlayerInfo = static_cast<CNetObj_PlayerInfo *>(Server()->SnapNewItem(NETOBJTYPE_PLAYERINFO, m_ClientID, sizeof(CNetObj_PlayerInfo)));
|
|
|
|
if(!pPlayerInfo)
|
|
|
|
return;
|
2010-05-29 07:25:38 +00:00
|
|
|
|
2011-03-01 17:31:20 +00:00
|
|
|
pPlayerInfo->m_Latency = SnappingClient == -1 ? m_Latency.m_Min : GameServer()->m_apPlayers[SnappingClient]->m_aActLatency[m_ClientID];
|
2010-12-16 02:29:08 +00:00
|
|
|
pPlayerInfo->m_Local = 0;
|
2011-02-12 10:40:36 +00:00
|
|
|
pPlayerInfo->m_ClientID = m_ClientID;
|
2011-04-20 20:40:56 +00:00
|
|
|
pPlayerInfo->m_Score = abs(m_Score) * -1;
|
2010-12-16 02:29:08 +00:00
|
|
|
pPlayerInfo->m_Team = m_Team;
|
2010-05-29 07:25:38 +00:00
|
|
|
|
|
|
|
if(m_ClientID == SnappingClient)
|
2011-03-10 09:08:14 +00:00
|
|
|
pPlayerInfo->m_Local = 1;
|
|
|
|
|
2011-03-12 17:07:57 +00:00
|
|
|
if(m_ClientID == SnappingClient && m_Team == TEAM_SPECTATORS)
|
2011-03-10 09:08:14 +00:00
|
|
|
{
|
|
|
|
CNetObj_SpectatorInfo *pSpectatorInfo = static_cast<CNetObj_SpectatorInfo *>(Server()->SnapNewItem(NETOBJTYPE_SPECTATORINFO, m_ClientID, sizeof(CNetObj_SpectatorInfo)));
|
|
|
|
if(!pSpectatorInfo)
|
|
|
|
return;
|
|
|
|
|
|
|
|
pSpectatorInfo->m_SpectatorID = m_SpectatorID;
|
|
|
|
pSpectatorInfo->m_X = m_ViewPos.x;
|
|
|
|
pSpectatorInfo->m_Y = m_ViewPos.y;
|
|
|
|
}
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2010-10-11 18:53:56 +00:00
|
|
|
// send 0 if times of others are not shown
|
|
|
|
if(SnappingClient != m_ClientID && g_Config.m_SvHideScore)
|
2011-04-20 20:40:56 +00:00
|
|
|
pPlayerInfo->m_Score = -9999;
|
2010-08-23 19:37:27 +00:00
|
|
|
else
|
2011-04-20 20:40:56 +00:00
|
|
|
pPlayerInfo->m_Score = abs(m_Score) * -1;
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2010-12-16 04:06:23 +00:00
|
|
|
pPlayerInfo->m_Team = m_Team;
|
2008-08-14 18:46:52 +00:00
|
|
|
}
|
|
|
|
|
2011-02-14 18:41:32 +00:00
|
|
|
void CPlayer::OnDisconnect(const char *pReason)
|
2008-08-14 18:46:52 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
KillCharacter();
|
|
|
|
|
|
|
|
if(Server()->ClientIngame(m_ClientID))
|
|
|
|
{
|
2010-12-23 05:57:26 +00:00
|
|
|
char aBuf[512];
|
2011-02-14 18:41:32 +00:00
|
|
|
if(pReason && *pReason)
|
2011-04-13 18:37:12 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "'%s' has left the game (%s)", Server()->ClientName(m_ClientID), pReason);
|
2011-02-14 18:41:32 +00:00
|
|
|
else
|
2011-04-13 18:37:12 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "'%s' has left the game", Server()->ClientName(m_ClientID));
|
2010-12-23 05:57:26 +00:00
|
|
|
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
|
2011-01-29 00:59:50 +00:00
|
|
|
|
2010-12-23 05:57:26 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "leave player='%d:%s'", m_ClientID, Server()->ClientName(m_ClientID));
|
|
|
|
GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "game", aBuf);
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-14 21:34:46 +00:00
|
|
|
CGameControllerDDRace* Controller = (CGameControllerDDRace*)GameServer()->m_pController;
|
|
|
|
Controller->m_Teams.m_Core.Team(m_ClientID, 0);
|
2008-08-14 18:46:52 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CPlayer::OnPredictedInput(CNetObj_PlayerInput *NewInput)
|
2008-08-14 18:46:52 +00:00
|
|
|
{
|
2011-05-05 00:13:32 +00:00
|
|
|
// skip the input if chat is active
|
|
|
|
if((m_PlayerFlags&PLAYERFLAG_CHATTING) && (NewInput->m_PlayerFlags&PLAYERFLAG_CHATTING))
|
|
|
|
return;
|
|
|
|
|
2011-04-19 08:42:48 +00:00
|
|
|
if(m_pCharacter)
|
|
|
|
m_pCharacter->OnPredictedInput(NewInput);
|
2008-08-14 18:46:52 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CPlayer::OnDirectInput(CNetObj_PlayerInput *NewInput)
|
2008-08-14 18:46:52 +00:00
|
|
|
{
|
2011-08-20 10:53:52 +00:00
|
|
|
if (AfkTimer(NewInput->m_TargetX, NewInput->m_TargetY))
|
|
|
|
return; // we must return if kicked, as player struct is already deleted
|
2011-06-09 20:30:03 +00:00
|
|
|
if(NewInput->m_PlayerFlags&PLAYERFLAG_CHATTING)
|
|
|
|
{
|
2011-08-13 00:11:06 +00:00
|
|
|
// skip the input if chat is active
|
2011-06-09 20:30:03 +00:00
|
|
|
if(m_PlayerFlags&PLAYERFLAG_CHATTING)
|
2011-08-13 00:11:06 +00:00
|
|
|
return;
|
2011-06-09 20:30:03 +00:00
|
|
|
|
|
|
|
// reset input
|
|
|
|
if(m_pCharacter)
|
|
|
|
m_pCharacter->ResetInput();
|
|
|
|
|
2011-08-13 00:11:06 +00:00
|
|
|
m_PlayerFlags = NewInput->m_PlayerFlags;
|
2011-06-09 20:30:03 +00:00
|
|
|
return;
|
|
|
|
}
|
2011-05-05 00:13:32 +00:00
|
|
|
|
2011-03-01 17:31:20 +00:00
|
|
|
m_PlayerFlags = NewInput->m_PlayerFlags;
|
|
|
|
|
2011-04-19 08:42:48 +00:00
|
|
|
if(m_pCharacter)
|
|
|
|
m_pCharacter->OnDirectInput(NewInput);
|
2008-08-14 18:46:52 +00:00
|
|
|
|
2011-04-19 08:42:48 +00:00
|
|
|
if(!m_pCharacter && m_Team != TEAM_SPECTATORS && (NewInput->m_Fire&1))
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Spawning = true;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-10-09 17:14:42 +00:00
|
|
|
// check for activity
|
|
|
|
if(NewInput->m_Direction || m_LatestActivity.m_TargetX != NewInput->m_TargetX ||
|
|
|
|
m_LatestActivity.m_TargetY != NewInput->m_TargetY || NewInput->m_Jump ||
|
|
|
|
NewInput->m_Fire&1 || NewInput->m_Hook)
|
|
|
|
{
|
|
|
|
m_LatestActivity.m_TargetX = NewInput->m_TargetX;
|
|
|
|
m_LatestActivity.m_TargetY = NewInput->m_TargetY;
|
|
|
|
m_LastActionTick = Server()->Tick();
|
|
|
|
}
|
2008-08-14 18:46:52 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CCharacter *CPlayer::GetCharacter()
|
2008-08-14 18:46:52 +00:00
|
|
|
{
|
2011-04-19 08:42:48 +00:00
|
|
|
if(m_pCharacter && m_pCharacter->IsAlive())
|
|
|
|
return m_pCharacter;
|
2008-08-14 18:46:52 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CPlayer::KillCharacter(int Weapon)
|
2008-08-14 18:46:52 +00:00
|
|
|
{
|
2011-04-19 08:42:48 +00:00
|
|
|
if(m_pCharacter)
|
2008-09-23 18:08:19 +00:00
|
|
|
{
|
2011-04-19 08:42:48 +00:00
|
|
|
m_pCharacter->Die(m_ClientID, Weapon);
|
|
|
|
delete m_pCharacter;
|
|
|
|
m_pCharacter = 0;
|
2008-09-23 18:08:19 +00:00
|
|
|
}
|
2008-08-14 18:46:52 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CPlayer::Respawn()
|
2008-08-14 18:46:52 +00:00
|
|
|
{
|
2011-01-03 11:50:38 +00:00
|
|
|
if(m_Team != TEAM_SPECTATORS)
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Spawning = true;
|
2008-08-14 18:46:52 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CPlayer::SetTeam(int Team)
|
2008-08-14 18:46:52 +00:00
|
|
|
{
|
|
|
|
// clamp the team
|
2010-05-29 07:25:38 +00:00
|
|
|
Team = GameServer()->m_pController->ClampTeam(Team);
|
|
|
|
if(m_Team == Team)
|
2008-08-14 18:46:52 +00:00
|
|
|
return;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-08-17 22:06:00 +00:00
|
|
|
char aBuf[512];
|
2011-06-06 19:54:34 +00:00
|
|
|
if(m_InfoSaved)
|
|
|
|
{
|
|
|
|
if(Team == TEAM_SPECTATORS)
|
|
|
|
str_format(aBuf, sizeof(aBuf), "'%s' paused", Server()->ClientName(m_ClientID));
|
|
|
|
else
|
|
|
|
str_format(aBuf, sizeof(aBuf), "'%s' resumed", Server()->ClientName(m_ClientID));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
str_format(aBuf, sizeof(aBuf), "'%s' joined the %s", Server()->ClientName(m_ClientID), GameServer()->m_pController->GetTeamName(Team));
|
2011-04-13 18:37:12 +00:00
|
|
|
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
KillCharacter();
|
2010-06-03 14:35:18 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Team = Team;
|
2011-06-01 14:08:45 +00:00
|
|
|
m_LastSetTeam = Server()->Tick();
|
2010-10-09 17:14:42 +00:00
|
|
|
m_LastActionTick = Server()->Tick();
|
2010-05-29 07:25:38 +00:00
|
|
|
// we got to wait 0.5 secs before respawning
|
|
|
|
m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
|
2011-08-13 00:11:06 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' m_Team=%d", m_ClientID, Server()->ClientName(m_ClientID), m_Team);
|
|
|
|
GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-07-29 05:21:18 +00:00
|
|
|
//GameServer()->m_pController->OnPlayerInfoChange(GameServer()->m_apPlayers[m_ClientID]);
|
2011-03-28 21:45:47 +00:00
|
|
|
|
|
|
|
if(Team == TEAM_SPECTATORS)
|
|
|
|
{
|
|
|
|
// update spectator modes
|
|
|
|
for(int i = 0; i < MAX_CLIENTS; ++i)
|
|
|
|
{
|
|
|
|
if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->m_SpectatorID == m_ClientID)
|
|
|
|
GameServer()->m_apPlayers[i]->m_SpectatorID = SPEC_FREEVIEW;
|
|
|
|
}
|
|
|
|
}
|
2008-08-14 18:46:52 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CPlayer::TryRespawn()
|
2008-08-14 18:46:52 +00:00
|
|
|
{
|
2010-09-17 06:05:27 +00:00
|
|
|
if(m_PauseInfo.m_Respawn)
|
|
|
|
{
|
2011-05-09 16:40:14 +00:00
|
|
|
m_pCharacter = new(m_ClientID) CCharacter(&GameServer()->m_World);
|
|
|
|
m_pCharacter->Spawn(this, m_PauseInfo.m_Core.m_Pos);
|
2011-09-02 18:04:18 +00:00
|
|
|
GameServer()->CreatePlayerSpawn(m_PauseInfo.m_Core.m_Pos, ((CGameControllerDDRace*)GameServer()->m_pController)->m_Teams.TeamMask((m_PauseInfo.m_Team > 0 && m_PauseInfo.m_Team < TEAM_SUPER) ? m_PauseInfo.m_Team : 0, -1, m_ClientID));
|
2010-08-22 13:17:57 +00:00
|
|
|
LoadCharacter();
|
2010-09-17 06:05:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-08-13 00:11:06 +00:00
|
|
|
vec2 SpawnPos;
|
2008-08-14 18:46:52 +00:00
|
|
|
|
2011-08-13 00:11:06 +00:00
|
|
|
if(!GameServer()->m_pController->CanSpawn(m_Team, &SpawnPos))
|
|
|
|
return;
|
2010-08-22 13:17:57 +00:00
|
|
|
|
2011-08-13 00:11:06 +00:00
|
|
|
m_Spawning = false;
|
|
|
|
m_pCharacter = new(m_ClientID) CCharacter(&GameServer()->m_World);
|
|
|
|
m_pCharacter->Spawn(this, SpawnPos);
|
|
|
|
GameServer()->CreatePlayerSpawn(SpawnPos);
|
2008-08-14 18:46:52 +00:00
|
|
|
}
|
|
|
|
}
|
2010-07-29 19:55:33 +00:00
|
|
|
|
2010-09-17 09:34:13 +00:00
|
|
|
void CPlayer::LoadCharacter()
|
|
|
|
{
|
2011-05-09 16:40:14 +00:00
|
|
|
m_pCharacter->SetCore(m_PauseInfo.m_Core);
|
2010-09-05 18:37:42 +00:00
|
|
|
if(g_Config.m_SvPauseTime)
|
2011-05-09 16:40:14 +00:00
|
|
|
m_pCharacter->m_StartTime = Server()->Tick() - (m_PauseInfo.m_PauseTime - m_PauseInfo.m_StartTime);
|
2010-09-17 12:21:12 +00:00
|
|
|
else
|
2011-05-09 16:40:14 +00:00
|
|
|
m_pCharacter->m_StartTime = m_PauseInfo.m_StartTime;
|
|
|
|
m_pCharacter->m_DDRaceState = m_PauseInfo.m_DDRaceState;
|
|
|
|
m_pCharacter->m_RefreshTime = Server()->Tick();
|
2010-09-17 09:34:13 +00:00
|
|
|
for(int i = 0; i < NUM_WEAPONS; ++i)
|
|
|
|
{
|
2010-08-22 22:46:39 +00:00
|
|
|
if(m_PauseInfo.m_aHasWeapon[i])
|
2010-12-07 17:44:23 +00:00
|
|
|
{
|
|
|
|
if(!m_PauseInfo.m_FreezeTime)
|
2011-05-09 16:40:14 +00:00
|
|
|
m_pCharacter->GiveWeapon(i, -1);
|
2010-12-07 17:44:23 +00:00
|
|
|
else
|
2011-05-09 16:40:14 +00:00
|
|
|
m_pCharacter->GiveWeapon(i, 0);
|
2010-12-07 17:44:23 +00:00
|
|
|
}
|
2010-08-22 13:17:57 +00:00
|
|
|
}
|
2011-05-09 16:40:14 +00:00
|
|
|
m_pCharacter->m_FreezeTime = m_PauseInfo.m_FreezeTime;
|
|
|
|
m_pCharacter->SetLastAction(Server()->Tick());
|
|
|
|
m_pCharacter->SetArmor(m_PauseInfo.m_Armor);
|
|
|
|
m_pCharacter->m_LastMove = m_PauseInfo.m_LastMove;
|
|
|
|
m_pCharacter->m_PrevPos = m_PauseInfo.m_PrevPos;
|
|
|
|
m_pCharacter->SetActiveWeapon(m_PauseInfo.m_ActiveWeapon);
|
|
|
|
m_pCharacter->SetLastWeapon(m_PauseInfo.m_LastWeapon);
|
|
|
|
m_pCharacter->m_Super = m_PauseInfo.m_Super;
|
|
|
|
m_pCharacter->m_DeepFreeze = m_PauseInfo.m_DeepFreeze;
|
|
|
|
m_pCharacter->m_EndlessHook = m_PauseInfo.m_EndlessHook;
|
2011-05-17 23:12:39 +00:00
|
|
|
m_pCharacter->m_TeleCheckpoint = m_PauseInfo.m_TeleCheckpoint;
|
2011-06-06 19:24:27 +00:00
|
|
|
m_pCharacter->m_CpActive = m_PauseInfo.m_CpActive;
|
2011-07-25 19:15:51 +00:00
|
|
|
m_pCharacter->m_Hit = m_PauseInfo.m_Hit;
|
2011-09-02 18:04:18 +00:00
|
|
|
m_pCharacter->Teams()->m_Core.SetSolo(m_ClientID, m_PauseInfo.m_Solo);
|
2011-06-06 19:24:27 +00:00
|
|
|
for(int i = 0; i < NUM_CHECKPOINTS; i++)
|
|
|
|
m_pCharacter->m_CpCurrent[i] = m_PauseInfo.m_CpCurrent[i];
|
2011-04-20 14:32:41 +00:00
|
|
|
((CGameControllerDDRace*)GameServer()->m_pController)->m_Teams.m_Core.Team(GetCID(), m_PauseInfo.m_Team);
|
2010-08-22 13:17:57 +00:00
|
|
|
m_PauseInfo.m_Respawn = false;
|
2010-09-17 06:05:27 +00:00
|
|
|
m_InfoSaved = false;
|
2010-08-22 13:17:57 +00:00
|
|
|
}
|
|
|
|
|
2010-08-22 22:04:26 +00:00
|
|
|
void CPlayer::SaveCharacter()
|
|
|
|
{
|
2011-05-09 16:40:14 +00:00
|
|
|
m_PauseInfo.m_Core = m_pCharacter->GetCore();
|
|
|
|
m_PauseInfo.m_StartTime = m_pCharacter->m_StartTime;
|
|
|
|
m_PauseInfo.m_DDRaceState = m_pCharacter->m_DDRaceState;
|
2010-08-22 22:04:26 +00:00
|
|
|
for(int i = 0; i < WEAPON_NINJA; ++i)
|
2011-05-09 16:40:14 +00:00
|
|
|
m_PauseInfo.m_aHasWeapon[i] = m_pCharacter->GetWeaponGot(i);
|
|
|
|
m_PauseInfo.m_FreezeTime=m_pCharacter->m_FreezeTime;
|
|
|
|
m_PauseInfo.m_Armor = m_pCharacter->GetArmor();
|
|
|
|
m_PauseInfo.m_LastMove = m_pCharacter->m_LastMove;
|
|
|
|
m_PauseInfo.m_PrevPos = m_pCharacter->m_PrevPos;
|
|
|
|
m_PauseInfo.m_ActiveWeapon = m_pCharacter->GetActiveWeapon();
|
|
|
|
m_PauseInfo.m_LastWeapon = m_pCharacter->GetLastWeapon();
|
|
|
|
m_PauseInfo.m_Super = m_pCharacter->m_Super;
|
|
|
|
m_PauseInfo.m_DeepFreeze = m_pCharacter->m_DeepFreeze;
|
|
|
|
m_PauseInfo.m_EndlessHook = m_pCharacter->m_EndlessHook;
|
2011-04-20 14:32:41 +00:00
|
|
|
m_PauseInfo.m_Team = ((CGameControllerDDRace*)GameServer()->m_pController)->m_Teams.m_Core.Team(GetCID());
|
2010-08-22 23:59:54 +00:00
|
|
|
m_PauseInfo.m_PauseTime = Server()->Tick();
|
2011-05-17 23:12:39 +00:00
|
|
|
m_PauseInfo.m_TeleCheckpoint = m_pCharacter->m_TeleCheckpoint;
|
2011-06-06 19:24:27 +00:00
|
|
|
m_PauseInfo.m_CpActive = m_pCharacter->m_CpActive;
|
2011-07-25 19:15:51 +00:00
|
|
|
m_PauseInfo.m_Hit = m_pCharacter->m_Hit;
|
2011-09-02 18:04:18 +00:00
|
|
|
m_PauseInfo.m_Solo = m_pCharacter->Teams()->m_Core.GetSolo(m_ClientID);
|
2011-06-06 19:24:27 +00:00
|
|
|
for(int i = 0; i < NUM_CHECKPOINTS; i++)
|
|
|
|
m_PauseInfo.m_CpCurrent[i] = m_pCharacter->m_CpCurrent[i];
|
2011-05-09 16:40:14 +00:00
|
|
|
//m_PauseInfo.m_RefreshTime = m_pCharacter->m_RefreshTime;
|
2010-08-22 13:17:57 +00:00
|
|
|
}
|
2011-03-22 19:49:12 +00:00
|
|
|
|
2011-05-06 19:16:53 +00:00
|
|
|
bool CPlayer::AfkTimer(int NewTargetX, int NewTargetY)
|
2011-03-22 19:49:12 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
afk timer (x, y = mouse coordinates)
|
|
|
|
Since a player has to move the mouse to play, this is a better method than checking
|
|
|
|
the player's position in the game world, because it can easily be bypassed by just locking a key.
|
|
|
|
Frozen players could be kicked as well, because they can't move.
|
|
|
|
It also works for spectators.
|
2011-05-06 19:16:53 +00:00
|
|
|
returns true if kicked
|
2011-03-22 19:49:12 +00:00
|
|
|
*/
|
|
|
|
|
2011-04-20 14:32:41 +00:00
|
|
|
if(m_Authed)
|
2011-05-06 19:16:53 +00:00
|
|
|
return false; // don't kick admins
|
2011-04-20 14:32:41 +00:00
|
|
|
if(g_Config.m_SvMaxAfkTime == 0)
|
2011-05-06 19:16:53 +00:00
|
|
|
return false; // 0 = disabled
|
2011-03-22 19:49:12 +00:00
|
|
|
|
2011-04-20 14:32:41 +00:00
|
|
|
if(NewTargetX != m_LastTarget_x || NewTargetY != m_LastTarget_y)
|
2011-03-22 19:49:12 +00:00
|
|
|
{
|
|
|
|
m_LastPlaytime = time_get();
|
2011-04-20 14:32:41 +00:00
|
|
|
m_LastTarget_x = NewTargetX;
|
|
|
|
m_LastTarget_y = NewTargetY;
|
2011-04-23 17:59:25 +00:00
|
|
|
m_Sent1stAfkWarning = 0; // afk timer's 1st warning after 50% of sv_max_afk_time
|
|
|
|
m_Sent2ndAfkWarning = 0;
|
2011-03-22 19:49:12 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// not playing, check how long
|
2011-04-23 17:59:25 +00:00
|
|
|
if(m_Sent1stAfkWarning == 0 && m_LastPlaytime < time_get()-time_freq()*(int)(g_Config.m_SvMaxAfkTime*0.5))
|
2011-03-22 19:49:12 +00:00
|
|
|
{
|
|
|
|
sprintf(
|
|
|
|
m_pAfkMsg,
|
|
|
|
"You have been afk for %d seconds now. Please note that you get kicked after not playing for %d seconds.",
|
|
|
|
(int)(g_Config.m_SvMaxAfkTime*0.5),
|
|
|
|
g_Config.m_SvMaxAfkTime
|
|
|
|
);
|
|
|
|
m_pGameServer->SendChatTarget(m_ClientID, m_pAfkMsg);
|
2011-04-23 17:59:25 +00:00
|
|
|
m_Sent1stAfkWarning = 1;
|
2011-04-20 14:32:41 +00:00
|
|
|
}
|
2011-04-23 17:59:25 +00:00
|
|
|
else if(m_Sent2ndAfkWarning == 0 && m_LastPlaytime < time_get()-time_freq()*(int)(g_Config.m_SvMaxAfkTime*0.9))
|
2011-03-22 19:49:12 +00:00
|
|
|
{
|
|
|
|
sprintf(
|
|
|
|
m_pAfkMsg,
|
|
|
|
"You have been afk for %d seconds now. Please note that you get kicked after not playing for %d seconds.",
|
|
|
|
(int)(g_Config.m_SvMaxAfkTime*0.9),
|
|
|
|
g_Config.m_SvMaxAfkTime
|
|
|
|
);
|
|
|
|
m_pGameServer->SendChatTarget(m_ClientID, m_pAfkMsg);
|
2011-04-23 17:59:25 +00:00
|
|
|
m_Sent2ndAfkWarning = 1;
|
2011-04-20 14:32:41 +00:00
|
|
|
}
|
|
|
|
else if(m_LastPlaytime < time_get()-time_freq()*g_Config.m_SvMaxAfkTime)
|
2011-03-22 19:49:12 +00:00
|
|
|
{
|
|
|
|
CServer* serv = (CServer*)m_pGameServer->Server();
|
|
|
|
serv->Kick(m_ClientID,"Away from keyboard");
|
2011-05-06 19:16:53 +00:00
|
|
|
return true;
|
2011-03-22 19:49:12 +00:00
|
|
|
}
|
|
|
|
}
|
2011-05-06 19:16:53 +00:00
|
|
|
return false;
|
2011-03-22 19:49:12 +00:00
|
|
|
}
|
2011-06-06 19:24:27 +00:00
|
|
|
|
|
|
|
bool CPlayer::IsPlaying()
|
|
|
|
{
|
|
|
|
if(m_InfoSaved || (m_pCharacter && m_pCharacter->IsAlive()))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|