diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 692280c09..826e95520 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1060,6 +1060,24 @@ void CGameContext::OnClientEnter(int ClientID) Score()->LoadScore(ClientID); Score()->CheckBirthday(ClientID); + { + int Empty = -1; + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(!Server()->ClientIngame(i)) + { + Empty = i; + break; + } + } + CNetMsg_Sv_Chat Msg; + Msg.m_Team = 0; + Msg.m_ClientID = Empty; + Msg.m_pMessage = "Do you know someone who uses a bot? Please report them to the moderators."; + m_apPlayers[ClientID]->m_EligibleForFinishCheck = time_get(); + Server()->SendPackMsg(&Msg, MSGFLAG_VITAL|MSGFLAG_NORECORD, ClientID); + } + if(!Server()->ClientPrevIngame(ClientID)) { char aBuf[512]; @@ -1211,6 +1229,18 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) { return; } + bool Check = !pPlayer->m_NotEligibleForFinish && pPlayer->m_EligibleForFinishCheck + 10 * time_freq() >= time_get(); + if(Check && str_comp(pMsg->m_pMessage, "xd sure chillerbot.png is lyfe") == 0 && pMsg->m_Team == 0) + { + if(m_TeeHistorianActive) + { + m_TeeHistorian.RecordPlayerMessage(ClientID, pUnpacker->CompleteData(), pUnpacker->CompleteSize()); + } + + pPlayer->m_NotEligibleForFinish = true; + dbg_msg("hack", "bot detected, cid=%d", ClientID); + return; + } int Team = pMsg->m_Team; // trim right and set maximum length to 256 utf8-characters diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index d0c69f81a..531503c0b 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -131,6 +131,9 @@ void CPlayer::Reset() m_FirstVoteTick = Now + g_Config.m_SvJoinVoteDelay * TickSpeed; else m_FirstVoteTick = Now; + + m_NotEligibleForFinish = false; + m_EligibleForFinishCheck = 0; } void CPlayer::Tick() @@ -513,6 +516,7 @@ void CPlayer::SetTeam(int Team, bool DoChatMsg) return; char aBuf[512]; + DoChatMsg = false; if(DoChatMsg) { str_format(aBuf, sizeof(aBuf), "'%s' joined the %s", Server()->ClientName(m_ClientID), GameServer()->m_pController->GetTeamName(Team)); diff --git a/src/game/server/player.h b/src/game/server/player.h index 4465256fb..d2d73c1e8 100644 --- a/src/game/server/player.h +++ b/src/game/server/player.h @@ -196,6 +196,8 @@ public: #if defined(CONF_SQL) int64 m_LastSQLQuery; #endif + bool m_NotEligibleForFinish; + int64 m_EligibleForFinishCheck; }; #endif diff --git a/src/game/server/save.cpp b/src/game/server/save.cpp index d23d4f465..6ebb2008c 100644 --- a/src/game/server/save.cpp +++ b/src/game/server/save.cpp @@ -69,6 +69,8 @@ void CSaveTee::save(CCharacter *pChr) for(int i = 0; i < 25; i++) m_CpCurrent[i] = pChr->m_CpCurrent[i]; + m_NotEligibleForFinish = pChr->m_pPlayer->m_NotEligibleForFinish; + // Core m_CorePos = pChr->m_Core.m_Pos; m_Vel = pChr->m_Core.m_Vel; @@ -140,6 +142,8 @@ void CSaveTee::load(CCharacter *pChr, int Team) for(int i = 0; i < 25; i++) pChr->m_CpCurrent[i] = m_CpCurrent[i]; + pChr->m_pPlayer->m_NotEligibleForFinish = pChr->m_pPlayer->m_NotEligibleForFinish || m_NotEligibleForFinish; + // Core pChr->m_Core.m_Pos = m_CorePos; pChr->m_Core.m_Vel = m_Vel; @@ -170,16 +174,23 @@ void CSaveTee::load(CCharacter *pChr, int Team) char* CSaveTee::GetString() { - str_format(m_String, sizeof(m_String), "%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%f\t%f\t%d\t%d\t%d\t%d\t%d\t%d\t%f\t%f\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f", m_name, m_Alive, m_Paused, m_NeededFaketuning, m_TeeFinished, m_IsSolo, m_aWeapons[0].m_AmmoRegenStart, m_aWeapons[0].m_Ammo, m_aWeapons[0].m_Ammocost, m_aWeapons[0].m_Got, m_aWeapons[1].m_AmmoRegenStart, m_aWeapons[1].m_Ammo, m_aWeapons[1].m_Ammocost, m_aWeapons[1].m_Got, m_aWeapons[2].m_AmmoRegenStart, m_aWeapons[2].m_Ammo, m_aWeapons[2].m_Ammocost, m_aWeapons[2].m_Got, m_aWeapons[3].m_AmmoRegenStart, m_aWeapons[3].m_Ammo, m_aWeapons[3].m_Ammocost, m_aWeapons[3].m_Got, m_aWeapons[4].m_AmmoRegenStart, m_aWeapons[4].m_Ammo, m_aWeapons[4].m_Ammocost, m_aWeapons[4].m_Got, m_aWeapons[5].m_AmmoRegenStart, m_aWeapons[5].m_Ammo, m_aWeapons[5].m_Ammocost, m_aWeapons[5].m_Got, m_LastWeapon, m_QueuedWeapon, m_SuperJump, m_Jetpack, m_NinjaJetpack, m_FreezeTime, m_FreezeTick, m_DeepFreeze, m_EndlessHook, m_DDRaceState, m_Hit, m_Collision, m_TuneZone, m_TuneZoneOld, m_Hook, m_Time, (int)m_Pos.x, (int)m_Pos.y, (int)m_PrevPos.x, (int)m_PrevPos.y, m_TeleCheckpoint, m_LastPenalty, (int)m_CorePos.x, (int)m_CorePos.y, m_Vel.x, m_Vel.y, m_ActiveWeapon, m_Jumped, m_JumpedTotal, m_Jumps, (int)m_HookPos.x, (int)m_HookPos.y, m_HookDir.x, m_HookDir.y, (int)m_HookTeleBase.x, (int)m_HookTeleBase.y, m_HookTick, m_HookState, m_CpTime, m_CpActive, m_CpLastBroadcast, m_CpCurrent[0], m_CpCurrent[1], m_CpCurrent[2], m_CpCurrent[3], m_CpCurrent[4], m_CpCurrent[5], m_CpCurrent[6], m_CpCurrent[7], m_CpCurrent[8], m_CpCurrent[9], m_CpCurrent[10], m_CpCurrent[11], m_CpCurrent[12], m_CpCurrent[13], m_CpCurrent[14], m_CpCurrent[15], m_CpCurrent[16], m_CpCurrent[17], m_CpCurrent[18], m_CpCurrent[19], m_CpCurrent[20], m_CpCurrent[21], m_CpCurrent[22], m_CpCurrent[23], m_CpCurrent[24]); + str_format(m_String, sizeof(m_String), "%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%f\t%f\t%d\t%d\t%d\t%d\t%d\t%d\t%f\t%f\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%d", m_name, m_Alive, m_Paused, m_NeededFaketuning, m_TeeFinished, m_IsSolo, m_aWeapons[0].m_AmmoRegenStart, m_aWeapons[0].m_Ammo, m_aWeapons[0].m_Ammocost, m_aWeapons[0].m_Got, m_aWeapons[1].m_AmmoRegenStart, m_aWeapons[1].m_Ammo, m_aWeapons[1].m_Ammocost, m_aWeapons[1].m_Got, m_aWeapons[2].m_AmmoRegenStart, m_aWeapons[2].m_Ammo, m_aWeapons[2].m_Ammocost, m_aWeapons[2].m_Got, m_aWeapons[3].m_AmmoRegenStart, m_aWeapons[3].m_Ammo, m_aWeapons[3].m_Ammocost, m_aWeapons[3].m_Got, m_aWeapons[4].m_AmmoRegenStart, m_aWeapons[4].m_Ammo, m_aWeapons[4].m_Ammocost, m_aWeapons[4].m_Got, m_aWeapons[5].m_AmmoRegenStart, m_aWeapons[5].m_Ammo, m_aWeapons[5].m_Ammocost, m_aWeapons[5].m_Got, m_LastWeapon, m_QueuedWeapon, m_SuperJump, m_Jetpack, m_NinjaJetpack, m_FreezeTime, m_FreezeTick, m_DeepFreeze, m_EndlessHook, m_DDRaceState, m_Hit, m_Collision, m_TuneZone, m_TuneZoneOld, m_Hook, m_Time, (int)m_Pos.x, (int)m_Pos.y, (int)m_PrevPos.x, (int)m_PrevPos.y, m_TeleCheckpoint, m_LastPenalty, (int)m_CorePos.x, (int)m_CorePos.y, m_Vel.x, m_Vel.y, m_ActiveWeapon, m_Jumped, m_JumpedTotal, m_Jumps, (int)m_HookPos.x, (int)m_HookPos.y, m_HookDir.x, m_HookDir.y, (int)m_HookTeleBase.x, (int)m_HookTeleBase.y, m_HookTick, m_HookState, m_CpTime, m_CpActive, m_CpLastBroadcast, m_CpCurrent[0], m_CpCurrent[1], m_CpCurrent[2], m_CpCurrent[3], m_CpCurrent[4], m_CpCurrent[5], m_CpCurrent[6], m_CpCurrent[7], m_CpCurrent[8], m_CpCurrent[9], m_CpCurrent[10], m_CpCurrent[11], m_CpCurrent[12], m_CpCurrent[13], m_CpCurrent[14], m_CpCurrent[15], m_CpCurrent[16], m_CpCurrent[17], m_CpCurrent[18], m_CpCurrent[19], m_CpCurrent[20], m_CpCurrent[21], m_CpCurrent[22], m_CpCurrent[23], m_CpCurrent[24], m_NotEligibleForFinish); return m_String; } int CSaveTee::LoadString(char* String) { int Num; - Num = sscanf(String, "%[^\t]\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%f\t%f\t%f\t%f\t%d\t%d\t%f\t%f\t%f\t%f\t%d\t%d\t%d\t%d\t%f\t%f\t%f\t%f\t%f\t%f\t%d\t%d\t%d\t%d\t%d\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f", m_name, &m_Alive, &m_Paused, &m_NeededFaketuning, &m_TeeFinished, &m_IsSolo, &m_aWeapons[0].m_AmmoRegenStart, &m_aWeapons[0].m_Ammo, &m_aWeapons[0].m_Ammocost, &m_aWeapons[0].m_Got, &m_aWeapons[1].m_AmmoRegenStart, &m_aWeapons[1].m_Ammo, &m_aWeapons[1].m_Ammocost, &m_aWeapons[1].m_Got, &m_aWeapons[2].m_AmmoRegenStart, &m_aWeapons[2].m_Ammo, &m_aWeapons[2].m_Ammocost, &m_aWeapons[2].m_Got, &m_aWeapons[3].m_AmmoRegenStart, &m_aWeapons[3].m_Ammo, &m_aWeapons[3].m_Ammocost, &m_aWeapons[3].m_Got, &m_aWeapons[4].m_AmmoRegenStart, &m_aWeapons[4].m_Ammo, &m_aWeapons[4].m_Ammocost, &m_aWeapons[4].m_Got, &m_aWeapons[5].m_AmmoRegenStart, &m_aWeapons[5].m_Ammo, &m_aWeapons[5].m_Ammocost, &m_aWeapons[5].m_Got, &m_LastWeapon, &m_QueuedWeapon, &m_SuperJump, &m_Jetpack, &m_NinjaJetpack, &m_FreezeTime, &m_FreezeTick, &m_DeepFreeze, &m_EndlessHook, &m_DDRaceState, &m_Hit, &m_Collision, &m_TuneZone, &m_TuneZoneOld, &m_Hook, &m_Time, &m_Pos.x, &m_Pos.y, &m_PrevPos.x, &m_PrevPos.y, &m_TeleCheckpoint, &m_LastPenalty, &m_CorePos.x, &m_CorePos.y, &m_Vel.x, &m_Vel.y, &m_ActiveWeapon, &m_Jumped, &m_JumpedTotal, &m_Jumps, &m_HookPos.x, &m_HookPos.y, &m_HookDir.x, &m_HookDir.y, &m_HookTeleBase.x, &m_HookTeleBase.y, &m_HookTick, &m_HookState, &m_CpTime, &m_CpActive, &m_CpLastBroadcast, &m_CpCurrent[0], &m_CpCurrent[1], &m_CpCurrent[2], &m_CpCurrent[3], &m_CpCurrent[4], &m_CpCurrent[5], &m_CpCurrent[6], &m_CpCurrent[7], &m_CpCurrent[8], &m_CpCurrent[9], &m_CpCurrent[10], &m_CpCurrent[11], &m_CpCurrent[12], &m_CpCurrent[13], &m_CpCurrent[14], &m_CpCurrent[15], &m_CpCurrent[16], &m_CpCurrent[17], &m_CpCurrent[18], &m_CpCurrent[19], &m_CpCurrent[20], &m_CpCurrent[21], &m_CpCurrent[22], &m_CpCurrent[23], &m_CpCurrent[24]); - if (Num == 96) // Don't forget to update this when you save / load more / less. + Num = sscanf(String, "%[^\t]\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%f\t%f\t%f\t%f\t%d\t%d\t%f\t%f\t%f\t%f\t%d\t%d\t%d\t%d\t%f\t%f\t%f\t%f\t%f\t%f\t%d\t%d\t%d\t%d\t%d\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%d", m_name, &m_Alive, &m_Paused, &m_NeededFaketuning, &m_TeeFinished, &m_IsSolo, &m_aWeapons[0].m_AmmoRegenStart, &m_aWeapons[0].m_Ammo, &m_aWeapons[0].m_Ammocost, &m_aWeapons[0].m_Got, &m_aWeapons[1].m_AmmoRegenStart, &m_aWeapons[1].m_Ammo, &m_aWeapons[1].m_Ammocost, &m_aWeapons[1].m_Got, &m_aWeapons[2].m_AmmoRegenStart, &m_aWeapons[2].m_Ammo, &m_aWeapons[2].m_Ammocost, &m_aWeapons[2].m_Got, &m_aWeapons[3].m_AmmoRegenStart, &m_aWeapons[3].m_Ammo, &m_aWeapons[3].m_Ammocost, &m_aWeapons[3].m_Got, &m_aWeapons[4].m_AmmoRegenStart, &m_aWeapons[4].m_Ammo, &m_aWeapons[4].m_Ammocost, &m_aWeapons[4].m_Got, &m_aWeapons[5].m_AmmoRegenStart, &m_aWeapons[5].m_Ammo, &m_aWeapons[5].m_Ammocost, &m_aWeapons[5].m_Got, &m_LastWeapon, &m_QueuedWeapon, &m_SuperJump, &m_Jetpack, &m_NinjaJetpack, &m_FreezeTime, &m_FreezeTick, &m_DeepFreeze, &m_EndlessHook, &m_DDRaceState, &m_Hit, &m_Collision, &m_TuneZone, &m_TuneZoneOld, &m_Hook, &m_Time, &m_Pos.x, &m_Pos.y, &m_PrevPos.x, &m_PrevPos.y, &m_TeleCheckpoint, &m_LastPenalty, &m_CorePos.x, &m_CorePos.y, &m_Vel.x, &m_Vel.y, &m_ActiveWeapon, &m_Jumped, &m_JumpedTotal, &m_Jumps, &m_HookPos.x, &m_HookPos.y, &m_HookDir.x, &m_HookDir.y, &m_HookTeleBase.x, &m_HookTeleBase.y, &m_HookTick, &m_HookState, &m_CpTime, &m_CpActive, &m_CpLastBroadcast, &m_CpCurrent[0], &m_CpCurrent[1], &m_CpCurrent[2], &m_CpCurrent[3], &m_CpCurrent[4], &m_CpCurrent[5], &m_CpCurrent[6], &m_CpCurrent[7], &m_CpCurrent[8], &m_CpCurrent[9], &m_CpCurrent[10], &m_CpCurrent[11], &m_CpCurrent[12], &m_CpCurrent[13], &m_CpCurrent[14], &m_CpCurrent[15], &m_CpCurrent[16], &m_CpCurrent[17], &m_CpCurrent[18], &m_CpCurrent[19], &m_CpCurrent[20], &m_CpCurrent[21], &m_CpCurrent[22], &m_CpCurrent[23], &m_CpCurrent[24], &m_NotEligibleForFinish); + if(Num == 96) // Don't forget to update this when you save / load more / less. + { + m_NotEligibleForFinish = false; return 0; + } + else if(Num == 97) + { + return 0; + } else { dbg_msg("load", "failed to load tee-string"); diff --git a/src/game/server/save.h b/src/game/server/save.h index 47a7efeea..215a4f003 100644 --- a/src/game/server/save.h +++ b/src/game/server/save.h @@ -66,6 +66,8 @@ private: int m_CpLastBroadcast; float m_CpCurrent[25]; + int m_NotEligibleForFinish; + // Core vec2 m_CorePos; vec2 m_Vel; diff --git a/src/game/server/score.h b/src/game/server/score.h index 412cf2d8c..0e0885602 100644 --- a/src/game/server/score.h +++ b/src/game/server/score.h @@ -47,7 +47,7 @@ public: virtual void MapVote(int ClientID, const char *pMapName) = 0; virtual void CheckBirthday(int ClientID) = 0; virtual void LoadScore(int ClientID) = 0; - virtual void SaveScore(int ClientID, float Time, float aCpTime[NUM_CHECKPOINTS]) = 0; + virtual void SaveScore(int ClientID, float Time, float aCpTime[NUM_CHECKPOINTS], bool NotEligible) = 0; virtual void SaveTeamScore(int *pClientIDs, unsigned int Size, float Time) = 0; diff --git a/src/game/server/score/file_score.cpp b/src/game/server/score/file_score.cpp index 2859054e0..741404d59 100644 --- a/src/game/server/score/file_score.cpp +++ b/src/game/server/score/file_score.cpp @@ -231,7 +231,7 @@ void CFileScore::SaveTeamScore(int* ClientIDs, unsigned int Size, float Time) } void CFileScore::SaveScore(int ClientID, float Time, - float CpTime[NUM_CHECKPOINTS]) + float CpTime[NUM_CHECKPOINTS], bool NotEligible) { CConsole* pCon = (CConsole*) GameServer()->Console(); if (!pCon->m_Cheated || g_Config.m_SvRankCheats) diff --git a/src/game/server/score/file_score.h b/src/game/server/score/file_score.h index 7dee11075..fe964dd1e 100644 --- a/src/game/server/score/file_score.h +++ b/src/game/server/score/file_score.h @@ -67,7 +67,7 @@ public: virtual void MapInfo(int ClientID, const char* MapName); virtual void MapVote(int ClientID, const char* MapName); virtual void SaveScore(int ClientID, float Time, - float CpTime[NUM_CHECKPOINTS]); + float CpTime[NUM_CHECKPOINTS], bool NotEligible); virtual void SaveTeamScore(int* ClientIDs, unsigned int Size, float Time); virtual void ShowTop5(IConsole::IResult *pResult, int ClientID, diff --git a/src/game/server/score/sql_score.cpp b/src/game/server/score/sql_score.cpp index 81574bc90..47301b85e 100644 --- a/src/game/server/score/sql_score.cpp +++ b/src/game/server/score/sql_score.cpp @@ -471,7 +471,7 @@ bool CSqlScore::MapInfoThread(CSqlServer* pSqlServer, const CSqlData *pGameData, return false; } -void CSqlScore::SaveScore(int ClientID, float Time, float CpTime[NUM_CHECKPOINTS]) +void CSqlScore::SaveScore(int ClientID, float Time, float CpTime[NUM_CHECKPOINTS], bool NotEligible) { CConsole* pCon = (CConsole*)GameServer()->Console(); if(pCon->m_Cheated) @@ -480,6 +480,7 @@ void CSqlScore::SaveScore(int ClientID, float Time, float CpTime[NUM_CHECKPOINTS Tmp->m_ClientID = ClientID; Tmp->m_Name = Server()->ClientName(ClientID); Tmp->m_Time = Time; + Tmp->m_NotEligible = NotEligible; for(int i = 0; i < NUM_CHECKPOINTS; i++) Tmp->m_aCpCurrent[i] = CpTime[i]; @@ -506,7 +507,7 @@ bool CSqlScore::SaveScoreThread(CSqlServer* pSqlServer, const CSqlData *pGameDat sqlstr::GetTimeStamp(aTimestamp, sizeof(aTimestamp)); char aBuf[768]; - str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %%s_race(Map, Name, Timestamp, Time, Server, cp1, cp2, cp3, cp4, cp5, cp6, cp7, cp8, cp9, cp10, cp11, cp12, cp13, cp14, cp15, cp16, cp17, cp18, cp19, cp20, cp21, cp22, cp23, cp24, cp25, GameID) VALUES ('%s', '%s', '%s', '%.2f', '%s', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%s');", pData->m_Map.ClrStr(), pData->m_Name.ClrStr(), aTimestamp, pData->m_Time, g_Config.m_SvSqlServerName, pData->m_aCpCurrent[0], pData->m_aCpCurrent[1], pData->m_aCpCurrent[2], pData->m_aCpCurrent[3], pData->m_aCpCurrent[4], pData->m_aCpCurrent[5], pData->m_aCpCurrent[6], pData->m_aCpCurrent[7], pData->m_aCpCurrent[8], pData->m_aCpCurrent[9], pData->m_aCpCurrent[10], pData->m_aCpCurrent[11], pData->m_aCpCurrent[12], pData->m_aCpCurrent[13], pData->m_aCpCurrent[14], pData->m_aCpCurrent[15], pData->m_aCpCurrent[16], pData->m_aCpCurrent[17], pData->m_aCpCurrent[18], pData->m_aCpCurrent[19], pData->m_aCpCurrent[20], pData->m_aCpCurrent[21], pData->m_aCpCurrent[22], pData->m_aCpCurrent[23], pData->m_aCpCurrent[24], pData->m_GameUuid.ClrStr()); + str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %%s_race(Map, Name, Timestamp, Time, Server, cp1, cp2, cp3, cp4, cp5, cp6, cp7, cp8, cp9, cp10, cp11, cp12, cp13, cp14, cp15, cp16, cp17, cp18, cp19, cp20, cp21, cp22, cp23, cp24, cp25, GameID) VALUES ('%s', '%s', '%s', '%.2f', '%s', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%s');%s", pData->m_Map.ClrStr(), pData->m_Name.ClrStr(), aTimestamp, pData->m_Time, g_Config.m_SvSqlServerName, pData->m_aCpCurrent[0], pData->m_aCpCurrent[1], pData->m_aCpCurrent[2], pData->m_aCpCurrent[3], pData->m_aCpCurrent[4], pData->m_aCpCurrent[5], pData->m_aCpCurrent[6], pData->m_aCpCurrent[7], pData->m_aCpCurrent[8], pData->m_aCpCurrent[9], pData->m_aCpCurrent[10], pData->m_aCpCurrent[11], pData->m_aCpCurrent[12], pData->m_aCpCurrent[13], pData->m_aCpCurrent[14], pData->m_aCpCurrent[15], pData->m_aCpCurrent[16], pData->m_aCpCurrent[17], pData->m_aCpCurrent[18], pData->m_aCpCurrent[19], pData->m_aCpCurrent[20], pData->m_aCpCurrent[21], pData->m_aCpCurrent[22], pData->m_aCpCurrent[23], pData->m_aCpCurrent[24], pData->m_GameUuid.ClrStr(), pData->m_NotEligible ? " -- not eligible" : ""); io_write(File, aBuf, str_length(aBuf)); io_write_newline(File); io_close(File); @@ -521,6 +522,11 @@ bool CSqlScore::SaveScoreThread(CSqlServer* pSqlServer, const CSqlData *pGameDat return false; } + if(pData->m_NotEligible) + { + return false; + } + try { char aBuf[768]; @@ -574,10 +580,12 @@ void CSqlScore::SaveTeamScore(int* aClientIDs, unsigned int Size, float Time) if(pCon->m_Cheated) return; CSqlTeamScoreData *Tmp = new CSqlTeamScoreData(); + Tmp->m_NotEligible = false; for(unsigned int i = 0; i < Size; i++) { Tmp->m_aClientIDs[i] = aClientIDs[i]; Tmp->m_aNames[i] = Server()->ClientName(aClientIDs[i]); + Tmp->m_NotEligible = Tmp->m_NotEligible || GameServer()->m_apPlayers[aClientIDs[i]]->m_NotEligibleForFinish; } Tmp->m_Size = Size; Tmp->m_Time = Time; @@ -611,7 +619,7 @@ bool CSqlScore::SaveTeamScoreThread(CSqlServer* pSqlServer, const CSqlData *pGam char aBuf[2300]; for(unsigned int i = 0; i < pData->m_Size; i++) { - str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %%s_teamrace(Map, Name, Timestamp, Time, ID, GameID) VALUES ('%s', '%s', '%s', '%.2f', @id, '%s');", pData->m_Map.ClrStr(), pData->m_aNames[i].ClrStr(), aTimestamp, pData->m_Time, pData->m_GameUuid.ClrStr()); + str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %%s_teamrace(Map, Name, Timestamp, Time, ID, GameID) VALUES ('%s', '%s', '%s', '%.2f', @id, '%s');%s", pData->m_Map.ClrStr(), pData->m_aNames[i].ClrStr(), aTimestamp, pData->m_Time, pData->m_GameUuid.ClrStr(), pData->m_NotEligible ? " -- not eligible" : ""); io_write(File, aBuf, str_length(aBuf)); io_write_newline(File); } @@ -623,6 +631,11 @@ bool CSqlScore::SaveTeamScoreThread(CSqlServer* pSqlServer, const CSqlData *pGam return false; } + if(pData->m_NotEligible) + { + return false; + } + try { char aBuf[2300]; diff --git a/src/game/server/score/sql_score.h b/src/game/server/score/sql_score.h index 66b0aefe4..0ae36b549 100644 --- a/src/game/server/score/sql_score.h +++ b/src/game/server/score/sql_score.h @@ -101,6 +101,7 @@ struct CSqlScoreData : CSqlData sqlstr::CSqlString m_Name; + bool m_NotEligible; float m_Time; float m_aCpCurrent[NUM_CHECKPOINTS]; int m_Num; @@ -110,6 +111,7 @@ struct CSqlScoreData : CSqlData struct CSqlTeamScoreData : CSqlData { + bool m_NotEligible; unsigned int m_Size; int m_aClientIDs[MAX_CLIENTS]; sqlstr::CSqlString m_aNames [MAX_CLIENTS]; @@ -178,7 +180,7 @@ public: virtual void MapInfo(int ClientID, const char* MapName); virtual void MapVote(int ClientID, const char* MapName); virtual void SaveScore(int ClientID, float Time, - float CpTime[NUM_CHECKPOINTS]); + float CpTime[NUM_CHECKPOINTS], bool NotEligible); virtual void SaveTeamScore(int* aClientIDs, unsigned int Size, float Time); virtual void ShowRank(int ClientID, const char* pName, bool Search = false); virtual void ShowTeamRank(int ClientID, const char* pName, bool Search = false); diff --git a/src/game/server/teams.cpp b/src/game/server/teams.cpp index 466afc3ee..bb6da473e 100644 --- a/src/game/server/teams.cpp +++ b/src/game/server/teams.cpp @@ -556,7 +556,7 @@ void CGameTeams::OnFinish(CPlayer* Player) if (CallSaveScore) if (g_Config.m_SvNamelessScore || !str_startswith(Server()->ClientName(Player->GetCID()), "nameless tee")) GameServer()->Score()->SaveScore(Player->GetCID(), Time, - GetCpCurrent(Player)); + GetCpCurrent(Player), Player->m_NotEligibleForFinish); bool NeedToSendNewRecord = false; // update server best time