diff --git a/conf/Anticheat.conf.dist b/conf/Anticheat.conf.dist index 89b2647..70ec1d1 100644 --- a/conf/Anticheat.conf.dist +++ b/conf/Anticheat.conf.dist @@ -62,6 +62,7 @@ Anticheat.DetectTelePlaneHack = 1 Anticheat.DetectSpeedHack = 1 Anticheat.DetectClimbHack = 0 Anticheat.DetectTelePortHack =1 +Anticheat.IgnoreControlHack = 1 # Anticheat.StricterFlyHackCheck # Description: Checks moveflag ascending (may give false positives) diff --git a/sql/characters/base/charactersdb_anticheat.sql b/sql/characters/base/charactersdb_anticheat.sql index 61cfb79..507fd00 100644 --- a/sql/characters/base/charactersdb_anticheat.sql +++ b/sql/characters/base/charactersdb_anticheat.sql @@ -10,7 +10,6 @@ CREATE TABLE IF NOT EXISTS `daily_players_reports` ( `waterwalk_reports` bigint unsigned NOT NULL DEFAULT 0, `teleportplane_reports` bigint unsigned NOT NULL DEFAULT 0, `climb_reports` bigint unsigned NOT NULL DEFAULT 0, - `teleporthack_reports` bigint unsigned NOT NULL DEFAULT 0, PRIMARY KEY (`guid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; @@ -26,6 +25,5 @@ CREATE TABLE IF NOT EXISTS `players_reports_status` ( `waterwalk_reports` bigint unsigned NOT NULL DEFAULT 0, `teleportplane_reports` bigint unsigned NOT NULL DEFAULT 0, `climb_reports` bigint unsigned NOT NULL DEFAULT 0, - `teleporthack_reports` bigint unsigned NOT NULL DEFAULT 0, PRIMARY KEY (`guid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/src/AnticheatMgr.cpp b/src/AnticheatMgr.cpp index a0b5b66..5e59137 100644 --- a/src/AnticheatMgr.cpp +++ b/src/AnticheatMgr.cpp @@ -79,14 +79,14 @@ void AnticheatMgr::WalkOnWaterHackDetection(Player* player, MovementInfo moveme LOG_INFO("module", "AnticheatMgr:: Walk on Water - Hack detected and counteracted by kicking player {} ({})", player->GetName(), player->GetGUID().ToString()); player->GetSession()->KickPlayer(true); - if(sConfigMgr->GetOption("Anticheat.AnnounceKick", true)) + if (sConfigMgr->GetOption("Anticheat.AnnounceKick", true)) { std::string plr = player->GetName(); std::string tag_colour = "7bbef7"; std::string plr_colour = "ff0000"; std::ostringstream stream; stream << "|CFF" << plr_colour << "[AntiCheat]|r|CFF" << tag_colour << - " Player |r|cff" << plr_colour << plr << "|r|cff" << tag_colour << + " Player |r|cff" << plr_colour << plr << "|r|cff" << tag_colour << " has been kicked.|r"; sWorld->SendServerMessage(SERVER_MSG_STRING, stream.str().c_str()); } @@ -130,24 +130,24 @@ void AnticheatMgr::FlyHackDetection(Player* player, MovementInfo movementInfo) } player->GetSession()->KickPlayer(true); - if(sConfigMgr->GetOption("Anticheat.AnnounceKick", true)) + if (sConfigMgr->GetOption("Anticheat.AnnounceKick", true)) { std::string plr = player->GetName(); std::string tag_colour = "7bbef7"; std::string plr_colour = "ff0000"; std::ostringstream stream; stream << "|CFF" << plr_colour << "[AntiCheat]|r|CFF" << tag_colour << - " Player |r|cff" << plr_colour << plr << "|r|cff" << tag_colour << + " Player |r|cff" << plr_colour << plr << "|r|cff" << tag_colour << " has been kicked.|r"; sWorld->SendServerMessage(SERVER_MSG_STRING, stream.str().c_str()); } } - else if (sConfigMgr->GetOption("Anticheat.WriteLog", false)) + else if (sConfigMgr->GetOption("Anticheat.WriteLog", false)) { LOG_INFO("module", "AnticheatMgr:: Fly-Hack detected player {} ({})", player->GetName(), player->GetGUID().ToString()); } - BuildReport(player,FLY_HACK_REPORT); + BuildReport(player, FLY_HACK_REPORT); } void AnticheatMgr::TeleportPlaneHackDetection(Player* player, MovementInfo movementInfo) @@ -182,6 +182,37 @@ void AnticheatMgr::TeleportPlaneHackDetection(Player* player, MovementInfo movem } } +void AnticheatMgr::IgnoreControlHackDetection(Player* player, MovementInfo movementInfo) +{ + float x, y; + player->GetPosition(x, y); + ObjectGuid key = player->GetGUID(); + + if (sConfigMgr->GetOption("Anticheat.IgnoreControlHack", true)) + { + if (player->HasUnitState(UNIT_STATE_ROOT) && !player->GetVehicle()) + { + bool unrestricted = movementInfo.pos.GetPositionX() != x || movementInfo.pos.GetPositionY() != y; + if (unrestricted) + { + if (m_Players[key].GetTotalReports() > sConfigMgr->GetOption("Anticheat.ReportsForIngameWarnings", 70)) + { + // display warning at the center of the screen, hacky way? + std::string str = ""; + str = "|cFFFFFC00[Playername:|cFF00FFFF[|cFF60FF00" + std::string(player->GetName().c_str()) + "|cFF00FFFF] Possible Ignore Control Hack Detected!"; + WorldPacket data(SMSG_NOTIFICATION, (str.size() + 1)); + data << str; + sWorld->SendGlobalGMMessage(&data); + } + if (sConfigMgr->GetOption("Anticheat.WriteLog", false)) + LOG_INFO("module", "AnticheatMgr:: Ignore Control - Hack detected player {} ({})", player->GetName(), player->GetGUID().ToString()); + + BuildReport(player, IGNORE_CONTROL_REPORT); + } + } + } +} + void AnticheatMgr::TeleportHackDetection(Player* player, MovementInfo movementInfo) { if (!sConfigMgr->GetOption("Anticheat.DetectTelePortHack", true)) @@ -245,12 +276,13 @@ void AnticheatMgr::StartHackDetection(Player* player, MovementInfo movementInfo, TeleportPlaneHackDetection(player, movementInfo); ClimbHackDetection(player, movementInfo, opcode); TeleportHackDetection(player, movementInfo); + IgnoreControlHackDetection(player, movementInfo); m_Players[key].SetLastMovementInfo(movementInfo); m_Players[key].SetLastOpcode(opcode); } // basic detection -void AnticheatMgr::ClimbHackDetection(Player *player, MovementInfo movementInfo, uint32 opcode) +void AnticheatMgr::ClimbHackDetection(Player* player, MovementInfo movementInfo, uint32 opcode) { if (!sConfigMgr->GetOption("Anticheat.DetectClimbHack", false)) return; @@ -355,8 +387,8 @@ void AnticheatMgr::HandlePlayerLogout(Player* player) } void AnticheatMgr::SavePlayerData(Player* player) -{ - CharacterDatabase.Execute("REPLACE INTO players_reports_status (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,teleporthack_reports,creation_time) VALUES ({},{},{},{},{},{},{},{},{},{},{});",player->GetGUID().GetCounter(), m_Players[player->GetGUID()].GetAverage(), m_Players[player->GetGUID()].GetTotalReports(), m_Players[player->GetGUID()].GetTypeReports(SPEED_HACK_REPORT),m_Players[player->GetGUID()].GetTypeReports(FLY_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(JUMP_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(WALK_WATER_HACK_REPORT),m_Players[player->GetGUID()].GetTypeReports(TELEPORT_PLANE_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(CLIMB_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(TELEPORT_HACK_REPORT), m_Players[player->GetGUID()].GetCreationTime()); +{// 1 2 3 4 5 6 7 8 9 10 + CharacterDatabase.Execute("REPLACE INTO players_reports_status (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,creation_time) VALUES ({},{},{},{},{},{},{},{},{},{});", player->GetGUID().GetCounter(), m_Players[player->GetGUID()].GetAverage(), m_Players[player->GetGUID()].GetTotalReports(), m_Players[player->GetGUID()].GetTypeReports(SPEED_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(FLY_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(JUMP_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(WALK_WATER_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(TELEPORT_PLANE_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(CLIMB_HACK_REPORT), m_Players[player->GetGUID()].GetCreationTime()); } uint32 AnticheatMgr::GetTotalReports(ObjectGuid guid) @@ -382,10 +414,13 @@ bool AnticheatMgr::MustCheckTempReports(uint8 type) if (type == TELEPORT_HACK_REPORT) return false; + if (type == IGNORE_CONTROL_REPORT) + return false; + return true; } -void AnticheatMgr::BuildReport(Player* player, uint8 reportType) +void AnticheatMgr::BuildReport(Player* player, uint16 reportType) { ObjectGuid key = player->GetGUID(); @@ -433,8 +468,8 @@ void AnticheatMgr::BuildReport(Player* player, uint8 reportType) if (sConfigMgr->GetOption("Anticheat.MaxReportsForDailyReport", 70) < m_Players[key].GetTotalReports()) { if (!m_Players[key].GetDailyReportState()) - { - CharacterDatabase.Execute("REPLACE INTO daily_players_reports (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,teleporthack_reports,creation_time) VALUES ({},{},{},{},{},{},{},{},{},{},{});", player->GetGUID().GetCounter(), m_Players[player->GetGUID()].GetAverage(), m_Players[player->GetGUID()].GetTotalReports(), m_Players[player->GetGUID()].GetTypeReports(SPEED_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(FLY_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(JUMP_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(WALK_WATER_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(TELEPORT_PLANE_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(CLIMB_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(TELEPORT_HACK_REPORT), m_Players[player->GetGUID()].GetCreationTime()); + {// 1 2 3 4 5 6 7 8 9 10 + CharacterDatabase.Execute("REPLACE INTO daily_players_reports (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,creation_time) VALUES ({},{},{},{},{},{},{},{},{},{});", player->GetGUID().GetCounter(), m_Players[player->GetGUID()].GetAverage(), m_Players[player->GetGUID()].GetTotalReports(), m_Players[player->GetGUID()].GetTypeReports(SPEED_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(FLY_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(JUMP_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(WALK_WATER_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(TELEPORT_PLANE_HACK_REPORT), m_Players[player->GetGUID()].GetTypeReports(CLIMB_HACK_REPORT), m_Players[player->GetGUID()].GetCreationTime()); m_Players[key].SetDailyReportState(true); } } @@ -467,7 +502,7 @@ void AnticheatMgr::AnticheatGlobalCommand(ChatHandler* handler) handler->PSendSysMessage("Players with the lowest averages:"); do { - Field *fieldsDB = resultDB->Fetch(); + Field* fieldsDB = resultDB->Fetch(); ObjectGuid guid = ObjectGuid::Create(fieldsDB[0].Get()); float average = fieldsDB[1].Get(); @@ -493,7 +528,7 @@ void AnticheatMgr::AnticheatGlobalCommand(ChatHandler* handler) handler->PSendSysMessage("Players with the more reports:"); do { - Field *fieldsDB = resultDB->Fetch(); + Field* fieldsDB = resultDB->Fetch(); ObjectGuid guid = ObjectGuid::Create(fieldsDB[0].Get()); float average = fieldsDB[1].Get(); diff --git a/src/AnticheatMgr.h b/src/AnticheatMgr.h index 2f06905..03fbfaa 100644 --- a/src/AnticheatMgr.h +++ b/src/AnticheatMgr.h @@ -30,12 +30,13 @@ class AnticheatData; enum ReportTypes { SPEED_HACK_REPORT = 0, - FLY_HACK_REPORT, - WALK_WATER_HACK_REPORT, - JUMP_HACK_REPORT, - TELEPORT_PLANE_HACK_REPORT, - CLIMB_HACK_REPORT, - TELEPORT_HACK_REPORT, + FLY_HACK_REPORT = 1, + WALK_WATER_HACK_REPORT = 2, + JUMP_HACK_REPORT = 3, + TELEPORT_PLANE_HACK_REPORT = 4, + CLIMB_HACK_REPORT = 5, + TELEPORT_HACK_REPORT = 6, + IGNORE_CONTROL_REPORT = 7 // MAX_REPORT_TYPES }; @@ -48,7 +49,8 @@ enum DetectionTypes JUMP_HACK_DETECTION = 8, TELEPORT_PLANE_HACK_DETECTION = 16, CLIMB_HACK_DETECTION = 32, - TELEPORT_HACK_DETECTION = 64 + TELEPORT_HACK_DETECTION = 64, + IGNORE_CONTROL_DETECTION = 128 }; // GUID is the key. @@ -89,7 +91,8 @@ class AnticheatMgr void TeleportPlaneHackDetection(Player* player, MovementInfo); void ClimbHackDetection(Player* player,MovementInfo movementInfo,uint32 opcode); void TeleportHackDetection(Player* player, MovementInfo movementInfo); - void BuildReport(Player* player,uint8 reportType); + void IgnoreControlHackDetection(Player* player, MovementInfo movementInfo); + void BuildReport(Player* player,uint16 reportType); bool MustCheckTempReports(uint8 type); diff --git a/src/cs_anticheat.cpp b/src/cs_anticheat.cpp index 95b1612..f87f3d7 100644 --- a/src/cs_anticheat.cpp +++ b/src/cs_anticheat.cpp @@ -210,13 +210,13 @@ public: uint32 teleportplane_reports = sAnticheatMgr->GetTypeReports(guid, 4); uint32 climb_reports = sAnticheatMgr->GetTypeReports(guid, 5); uint32 teleporthack_reports = sAnticheatMgr->GetTypeReports(guid, 6); + uint32 ignorecontrol_reports = sAnticheatMgr->GetTypeReports(guid, 7); handler->PSendSysMessage("Information about player %s",player->GetName().c_str()); handler->PSendSysMessage("Average: %f || Total Reports: %u ",average,total_reports); handler->PSendSysMessage("Speed Reports: %u || Fly Reports: %u || Jump Reports: %u ",speed_reports,fly_reports,jump_reports); handler->PSendSysMessage("Walk On Water Reports: %u || Teleport To Plane Reports: %u",waterwalk_reports,teleportplane_reports); - handler->PSendSysMessage("Climb Reports: %u || Teleport Hack Reports: %u", climb_reports, teleporthack_reports); - + handler->PSendSysMessage("Climb Reports: %u", climb_reports); return true; }