mirror of
https://github.com/ornfelt/azerothcore_lua_scripts
synced 2026-08-22 06:26:03 -04:00
760 lines
29 KiB
Diff
760 lines
29 KiB
Diff
/*
|
|
#################################################################
|
|
#################################################################
|
|
#################################################################
|
|
##########Patch by: ??
|
|
##########Fixed by: JunkyBulgaria and SymbolixDEV
|
|
##########Cheat Type: SpeedHack
|
|
##########Cheat Type: FlyHack
|
|
##########Cheat Type: WalkOnWaterHack
|
|
#################################################################
|
|
#################################################################
|
|
#################################################################
|
|
/*
|
|
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
|
|
--- a/src/server/game/Chat/Chat.cpp
|
|
+++ b/src/server/game/Chat/Chat.cpp
|
|
@@ -690,6 +690,15 @@
|
|
{ NULL, 0, false, NULL, "", NULL }
|
|
};
|
|
|
|
+ static ChatCommand anticheatCommandTable[] =
|
|
+ {
|
|
+ { "global", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAntiCheatGlobalCommand, "", NULL },
|
|
+ { "player", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAntiCheatPlayerCommand, "", NULL },
|
|
+ { "delete", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAntiCheatDeleteCommand, "", NULL },
|
|
+ { "handle", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAntiCheatHandleCommand, "", NULL },
|
|
+ { NULL, 0, false, NULL, "", NULL }
|
|
+ };
|
|
+
|
|
static ChatCommand commandTable[] =
|
|
{
|
|
{ "account", SEC_PLAYER, true, NULL, "", accountCommandTable },
|
|
@@ -693,6 +702,7 @@
|
|
static ChatCommand commandTable[] =
|
|
{
|
|
{ "account", SEC_PLAYER, true, NULL, "", accountCommandTable },
|
|
+ { "character", SEC_GAMEMASTER, true, NULL, "", characterCommandTable},
|
|
{ "gm", SEC_MODERATOR, true, NULL, "", gmCommandTable },
|
|
{ "npc", SEC_MODERATOR, false, NULL, "", npcCommandTable },
|
|
{ "go", SEC_MODERATOR, false, NULL, "", goCommandTable },
|
|
diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h
|
|
--- a/src/server/game/Chat/Chat.h
|
|
+++ b/src/server/game/Chat/Chat.h
|
|
@@ -601,6 +601,12 @@
|
|
bool HandleTempGameObjectCommand(const char* args);
|
|
bool HandleTempAddSpwCommand(const char* args);
|
|
|
|
+ // ANTICHEAT
|
|
+ bool HandleAntiCheatGlobalCommand(const char* args); // top3 : Amount || Average || (Amount && Average)
|
|
+ bool HandleAntiCheatPlayerCommand(const char* args); // returns especific player's average and amount
|
|
+ bool HandleAntiCheatDeleteCommand(const char* args); // if no player name as parameter, deletes all logs else deletes specific player's log
|
|
+ bool HandleAntiCheatHandleCommand(const char* args); // turn it on, turn it off
|
|
+
|
|
//! Development Commands
|
|
|
|
/*bool HandleQuestAdd(const char * args);
|
|
diff --git a/src/server/game/Chat/Commands/Level3.cpp b/src/server/game/Chat/Commands/Level3.cpp
|
|
--- a/src/server/game/Chat/Commands/Level3.cpp
|
|
+++ b/src/server/game/Chat/Commands/Level3.cpp
|
|
@@ -7194,6 +7194,173 @@
|
|
PSendSysMessage(LANG_COMMAND_PLAYED_TO_ALL, soundId);
|
|
return true;
|
|
}
|
|
+// ADD BY ANTICHEAT
|
|
+bool ChatHandler::HandleAntiCheatDeleteCommand(const char *args)
|
|
+{
|
|
+ std::string strCommand;
|
|
+
|
|
+ char* command = strtok((char*)args, " "); //get entered name
|
|
+
|
|
+ if (!command)
|
|
+ return true;
|
|
+
|
|
+ strCommand = command;
|
|
+
|
|
+ if (strCommand.compare("deleteall") == 0)
|
|
+ {
|
|
+
|
|
+ for (uint8 uiI = 0; uiI < 3; uiI++)
|
|
+ {
|
|
+ CharacterDatabase.PExecute("DELETE FROM cheat_first_report");
|
|
+ CharacterDatabase.PExecute("DELETE FROM cheat_temp_reports");
|
|
+ CharacterDatabase.PExecute("DELETE FROM cheat_reports");
|
|
+ }
|
|
+
|
|
+ } else
|
|
+ {
|
|
+ normalizePlayerName(strCommand);
|
|
+ Player* pPlayer = sObjectMgr.GetPlayer(strCommand.c_str()); //get player by name
|
|
+
|
|
+ if (!pPlayer)
|
|
+ PSendSysMessage("Player doesn't exist");
|
|
+ else
|
|
+ {
|
|
+ for (uint8 uiI = 0; uiI < 3; uiI++)
|
|
+ {
|
|
+ CharacterDatabase.PExecute("DELETE FROM cheat_reports WHERE guid = %u",pPlayer->GetGUIDLow());
|
|
+ CharacterDatabase.PExecute("DELETE FROM cheat_temp_reports WHERE guid = %u",pPlayer->GetGUIDLow());
|
|
+ CharacterDatabase.PExecute("DELETE FROM cheat_first_report WHERE guid = %u",pPlayer->GetGUIDLow());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+// ADD BY ANTICHEAT
|
|
+bool ChatHandler::HandleAntiCheatPlayerCommand(const char *args)
|
|
+{
|
|
+ std::string strCommand;
|
|
+
|
|
+ char* command = strtok((char*)args, " ");
|
|
+
|
|
+ uint32 uiGUID = 0;
|
|
+ Player* pPlayer = NULL;
|
|
+
|
|
+ if (command)
|
|
+ {
|
|
+ strCommand = command;
|
|
+
|
|
+ normalizePlayerName(strCommand);
|
|
+
|
|
+ pPlayer = sObjectMgr.GetPlayer(strCommand.c_str()); //get player by name
|
|
+
|
|
+ if (pPlayer)
|
|
+ uiGUID = pPlayer->GetGUIDLow();
|
|
+ }else
|
|
+ {
|
|
+ pPlayer = getSelectedPlayer();
|
|
+ if (pPlayer)
|
|
+ uiGUID = pPlayer->GetGUIDLow();
|
|
+ }
|
|
+
|
|
+ if (uiGUID == 0)
|
|
+ {
|
|
+ PSendSysMessage("There is no player.");
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ QueryResult result = CharacterDatabase.PQuery("SELECT count( * ) AS 'Repeticiones' FROM `characters` AS A, `cheat_reports` AS B WHERE A.`online` =1 AND A.`guid` = B.`guid` AND A.`guid`=%u GROUP BY B.`guid` ORDER BY Repeticiones DESC LIMIT 0 , 1",uiGUID);
|
|
+
|
|
+ if (result)
|
|
+ {
|
|
+ do
|
|
+ {
|
|
+ Field* fields=result->Fetch();
|
|
+ uint32 warnings = fields[0].GetUInt32();
|
|
+ PSendSysMessage("Amount: %u", warnings);
|
|
+ }
|
|
+ while (result->NextRow());
|
|
+ } else
|
|
+ PSendSysMessage("Player's amount log is empty!.");
|
|
+
|
|
+ QueryResult resultw = CharacterDatabase.PQuery("SELECT CAST((SUM(B.time ) / count( * ) ) - C.time AS UNSIGNED) AS 'promedio' , CAST(count( * ) AS UNSIGNED) AS 'Repeticiones' FROM `characters` AS A, `cheat_temp_reports` AS B, cheat_first_report AS C WHERE A.`online` =1 AND A.`guid` = B.`guid` AND A.guid = C.guid AND A.`guid`=%u GROUP BY B.`guid` ORDER BY Repeticiones DESC LIMIT 0 , 1",uiGUID);
|
|
+
|
|
+ if (resultw)
|
|
+ {
|
|
+ do
|
|
+ {
|
|
+ Field* fields=resultw->Fetch();
|
|
+ uint32 average = fields[0].GetUInt32();
|
|
+ uint32 warnings = fields[1].GetUInt32();
|
|
+
|
|
+ PSendSysMessage("Average: %u Warnings: %u", average, warnings);
|
|
+ }
|
|
+ while (resultw->NextRow());
|
|
+ } else
|
|
+ PSendSysMessage("Player's average log is empty!.");
|
|
+
|
|
+ return true;
|
|
+}
|
|
+// ADD BY ANTICHEAT
|
|
+bool ChatHandler::HandleAntiCheatHandleCommand(const char *args)
|
|
+{
|
|
+ std::string strCommand;
|
|
+
|
|
+ char* command = strtok((char*)args, " ");
|
|
+
|
|
+ if (!command)
|
|
+ return true;
|
|
+
|
|
+ strCommand = command;
|
|
+
|
|
+ if (strCommand.compare("on") == 0)
|
|
+ sWorld.setBoolConfig(CONFIG_ANTICHEAT_ENABLE,true);
|
|
+ else if (strCommand.compare("off") == 0)
|
|
+ sWorld.setBoolConfig(CONFIG_ANTICHEAT_ENABLE,false);
|
|
+
|
|
+ return true;
|
|
+}
|
|
+// ADD BY ANTICHEAT
|
|
+bool ChatHandler::HandleAntiCheatGlobalCommand(const char *args)
|
|
+{
|
|
+ QueryResult result = CharacterDatabase.PQuery("SELECT A.`name` , count( * ) AS 'Repeticiones' FROM `characters` AS A, `cheat_reports` AS B WHERE A.`online` =1 AND A.`guid` = B.`guid` GROUP BY B.`guid` ORDER BY Repeticiones DESC LIMIT 0 , 3");
|
|
+
|
|
+ PSendSysMessage("Cheaters by Amount: -------------");
|
|
+ if (result)
|
|
+ {
|
|
+ do
|
|
+ {
|
|
+ Field* fields=result->Fetch();
|
|
+ std::string name = fields[0].GetCppString();
|
|
+ uint32 warnings = fields[1].GetUInt32();
|
|
+
|
|
+ PSendSysMessage("Name: %s Warnings: %u", name.c_str(), warnings);
|
|
+ }
|
|
+ while (result->NextRow());
|
|
+ } else
|
|
+ PSendSysMessage("Cheaters amount log empty!.");
|
|
+
|
|
+ PSendSysMessage("Cheaters by Average: -------------");
|
|
+
|
|
+ QueryResult results = CharacterDatabase.PQuery("SELECT A.`name` , CAST((SUM(B.time ) / count( * ) ) - C.time AS UNSIGNED) AS 'promedio' , CAST(count( * ) AS UNSIGNED) AS 'Repeticiones' FROM `characters` AS A, `cheat_temp_reports` AS B, cheat_first_report AS C WHERE A.`online` =1 AND A.`guid` = B.`guid` AND A.guid = C.guid GROUP BY B.`guid` ORDER BY Repeticiones DESC LIMIT 0 , 3;");
|
|
+
|
|
+ if (results)
|
|
+ {
|
|
+ do
|
|
+ {
|
|
+ Field* fields=results->Fetch();
|
|
+ std::string name = fields[0].GetCppString();
|
|
+ uint32 average = fields[1].GetUInt32();
|
|
+ uint32 warnings = fields[2].GetUInt32();
|
|
+
|
|
+ PSendSysMessage("Name: %s Average: %u Warnings: %u", name.c_str(), average, warnings);
|
|
+ }
|
|
+ while (results->NextRow());
|
|
+ } else
|
|
+ PSendSysMessage("Cheaters average log empty!.");
|
|
+
|
|
+ return true;
|
|
+}
|
|
|
|
bool ChatHandler::HandleFreezeCommand(const char *args)
|
|
{
|
|
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
|
|
--- a/src/server/game/Entities/Player/Player.cpp
|
|
+++ b/src/server/game/Entities/Player/Player.cpp
|
|
@@ -619,6 +619,10 @@
|
|
|
|
Player::~Player ()
|
|
{
|
|
+ // anticheat
|
|
+ if (sWorld.getBoolConfig(CONFIG_ANTICHEAT_ENABLE))
|
|
+ CleanTempCheatReports();
|
|
+
|
|
// it must be unloaded already in PlayerLogout and accessed only for loggined player
|
|
//m_social = NULL;
|
|
|
|
@@ -654,6 +658,202 @@
|
|
sWorld.DecreasePlayerCount();
|
|
}
|
|
|
|
+bool Player::HasFirstReport()
|
|
+{
|
|
+ QueryResult result = CharacterDatabase.PQuery("SELECT * FROM cheat_first_report WHERE guid = %u",GetGUIDLow());
|
|
+
|
|
+ if (result)
|
|
+ return true;
|
|
+ else
|
|
+ return false;
|
|
+}
|
|
+
|
|
+void Player::CleanTempCheatReports()
|
|
+{
|
|
+ for (uint8 uiI = 0; uiI < 2; uiI++)
|
|
+ {
|
|
+
|
|
+ if (uiI == 0)
|
|
+ {
|
|
+ // QueryResult result = CharacterDatabase.PQuery( "DELETE FROM cheat_first_report WHERE guid = %u",GetGUIDLow());
|
|
+ }
|
|
+ else
|
|
+ QueryResult result = CharacterDatabase.PQuery("DELETE FROM cheat_temp_reports WHERE guid = %u",GetGUIDLow());
|
|
+
|
|
+ }
|
|
+}
|
|
+
|
|
+void Player::ElaborateCheatReport(Player* pPlayer, uint8 uiCheatType)
|
|
+{
|
|
+ if (!pPlayer)
|
|
+ return;
|
|
+
|
|
+ // cheatType 1 == SpeedHack
|
|
+ // cheatType 2 == FlyHack
|
|
+ // cheatType 3 == WalkOnWaterHack
|
|
+
|
|
+ std::string strReportType;
|
|
+
|
|
+
|
|
+ switch(uiCheatType)
|
|
+ {
|
|
+ case 1:
|
|
+ strReportType = "Speed-Hack";
|
|
+ break;
|
|
+ case 2:
|
|
+ strReportType = "Fly-Hack";
|
|
+ case 3:
|
|
|
|
+ strReportType = "WalkOnWater-Hack";
|
|
+ break;
|
|
+ default:
|
|
+ strReportType = "";
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ std::string name = pPlayer->GetName();
|
|
+ CharacterDatabase.escape_string(name);
|
|
+
|
|
+ if (!HasFirstReport())
|
|
+ {
|
|
+ CharacterDatabase.PExecute("INSERT INTO cheat_first_report (`guid`,`name`,`latency`,`time`) VALUES (%u,'%s',%u,NOW())",
|
|
+ pPlayer->GetGUIDLow(),
|
|
+ name.c_str(),
|
|
+ pPlayer->GetSession()->GetLatency());
|
|
+ ChatHandler(pPlayer).PSendSysMessage("You have been cought cheating and was reported , The Punishment for This offence is a lifetime ip and account and similer accounts ban , you will be punished automaticly if you continue.");
|
|
+ }
|
|
+
|
|
+ for (uint8 uiI = 0; uiI < 2; uiI++)
|
|
+ {
|
|
+ if (uiI == 0)
|
|
+ {
|
|
+ CharacterDatabase.PExecute("INSERT INTO cheat_reports (`guid`,`name`,`latency`,`mapid`,`position_x`,`position_y`,`position_z`,`report`,`time`) VALUES (%u,'%s',%u,%u,%f,%f,%f,'%s',NOW())",
|
|
+ pPlayer->GetGUIDLow(),
|
|
+ name.c_str(),
|
|
+ pPlayer->GetSession()->GetLatency(),
|
|
+ pPlayer->GetMapId(),
|
|
+ pPlayer->GetPositionX(),
|
|
+ pPlayer->GetPositionY(),
|
|
+ pPlayer->GetPositionZ(),
|
|
+ strReportType.c_str());
|
|
+
|
|
+ uint32 charcount = 0;
|
|
+ // check character count
|
|
+ QueryResult count = CharacterDatabase.PQuery("SELECT COUNT(*) FROM cheat_reports WHERE guid = '%d'", pPlayer->GetGUIDLow());
|
|
+ if (count)
|
|
+ {
|
|
+ Field *fields=count->Fetch();
|
|
+ charcount = fields[0].GetUInt32();
|
|
+ }
|
|
+
|
|
+ // If Its Speed Hacking
|
|
+ if(uiCheatType == 1)
|
|
+ {
|
|
+ if(charcount >= 2 && charcount << 4)
|
|
+ {
|
|
+ ChatHandler(pPlayer).PSendSysMessage("You have continued to cheat and you will be killed , if you still continue to cheat you will be automaticly banned , be careful !");
|
|
+ }
|
|
+ if(charcount >= 4 && charcount << 6)
|
|
+ {
|
|
+ if(pPlayer->isDead())
|
|
+ {
|
|
+ pPlayer->GetSession()->KickPlayer();
|
|
+ }else
|
|
+ {
|
|
+ pPlayer->Kill(pPlayer,true);
|
|
+ }
|
|
+ ChatHandler(pPlayer).PSendSysMessage("Next Time Its More then that !");
|
|
+ }
|
|
+ if(charcount >= 6 && charcount << 8)
|
|
+ {
|
|
+ pPlayer->GetSession()->KickPlayer();
|
|
+ }
|
|
+ if(charcount >= 8 && charcount << 10)
|
|
+ {
|
|
+ ChatHandler(pPlayer).PSendSysMessage("Why Do You Continue to cheat , do you think you will get better at the game , get items using cheats , this is the third time you are warned , one more time and you will be banned for life automaticly ! ");
|
|
+ }
|
|
+ if(charcount >= 10 && charcount << 12)
|
|
+ {
|
|
+ pPlayer->GetSession()->KickPlayer();
|
|
+ LoginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 'Anti-Cheat System', '%s', '1')",
|
|
+ pPlayer->GetSession()->GetAccountId(),
|
|
+ strReportType.c_str());
|
|
+ }
|
|
+ if(charcount >= 12 && charcount << 14)
|
|
+ {
|
|
+ ChatHandler(pPlayer).PSendSysMessage("It seems you just do not understand how this works , more cheating will result in an IP Ban , Now Stop it you Idoit ! ");
|
|
+ }
|
|
+ if(charcount >= 16)
|
|
+ {
|
|
+ pPlayer->GetSession()->KickPlayer();
|
|
+ LoginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP(),'Anti-Cheat System','%s')",
|
|
+ pPlayer->GetSession()->GetPlayerName(),
|
|
+ strReportType.c_str());
|
|
+ }
|
|
+ }
|
|
+ // if its Fly hacking
|
|
+ if(uiCheatType == 2 || 3)
|
|
+ {
|
|
+ if(charcount >= 4 && charcount << 6)
|
|
+ {
|
|
+ ChatHandler(pPlayer).PSendSysMessage("You have continued to cheat and you will be killed , if you still continue to cheat you will be automaticly banned , be careful !");
|
|
+ }
|
|
+ if(charcount >= 8 && charcount << 10)
|
|
+ {
|
|
+ if(pPlayer->isDead())
|
|
+ {
|
|
+ pPlayer->GetSession()->KickPlayer();
|
|
+ }else
|
|
+ {
|
|
+ pPlayer->Kill(pPlayer,true);
|
|
+ }
|
|
+ ChatHandler(pPlayer).PSendSysMessage("Next Time Its More then that !");
|
|
+ }
|
|
+ if(charcount >= 10 && charcount << 14)
|
|
+ {
|
|
+ pPlayer->GetSession()->KickPlayer();
|
|
+ }
|
|
+ if(charcount >= 16 && charcount << 18)
|
|
+ {
|
|
+ ChatHandler(pPlayer).PSendSysMessage("Why Do You Continue to cheat , do you think you will get better at the game , get items using cheats , this is the third time you are warned , one more time and you will be banned for life automaticly ! ");
|
|
+ }
|
|
+ if(charcount >= 20 && charcount << 24)
|
|
+ {
|
|
+ pPlayer->GetSession()->KickPlayer();
|
|
+ LoginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 'Anti-Cheat System', '%s', '1')",
|
|
+ pPlayer->GetSession()->GetAccountId(),
|
|
+ strReportType.c_str());
|
|
+ }
|
|
+ if(charcount >= 26 && charcount << 28)
|
|
+ {
|
|
+ ChatHandler(pPlayer).PSendSysMessage("It seems you just do not understand how this works , more cheating will result in an IP Ban , Now Stop it you Idoit ! ");
|
|
+ }
|
|
+ if(charcount >= 30)
|
|
+ {
|
|
+ pPlayer->GetSession()->KickPlayer();
|
|
+ LoginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP(),'Anti-Cheat System','%s')",
|
|
+ pPlayer->GetSession()->GetPlayerName(),
|
|
+ strReportType.c_str());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ CharacterDatabase.PExecute("INSERT INTO cheat_temp_reports (`guid`,`name`,`mapid`,`position_x`,`position_y`,`position_z`,`report`,`time`) VALUES (%u,'%s',%u,%f,%f,%f,'%s',NOW())",
|
|
+ pPlayer->GetGUIDLow(),
|
|
+ name.c_str(),
|
|
+ pPlayer->GetMapId(),
|
|
+ pPlayer->GetPositionX(),
|
|
+ pPlayer->GetPositionY(),
|
|
+ pPlayer->GetPositionZ(),
|
|
+ strReportType.c_str());
|
|
+ // End of Else
|
|
+ }
|
|
+ // End of For
|
|
+ }
|
|
+
|
|
+ // End of Void
|
|
+}
|
|
+
|
|
void Player::CleanupsBeforeDelete(bool finalCleanup)
|
|
{
|
|
TradeCancel(false);
|
|
@@ -19862,6 +20062,24 @@
|
|
}
|
|
}
|
|
|
|
+bool Player::CanFlyAnticheat(MovementInfo& pMovementInfo)
|
|
+{
|
|
+ if (IsUnderWater())
|
|
+ return false;
|
|
+
|
|
+ if (HasAuraType(SPELL_AURA_FLY) || HasAuraType(SPELL_AURA_WATER_WALK) || HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED))
|
|
+ return false;
|
|
+
|
|
+ if (Creature* pCreature = GetVehicleCreatureBase())
|
|
+ if (pCreature->GetCreatureInfo()->InhabitType & INHABIT_AIR)
|
|
+ return false;
|
|
+
|
|
+ if (HasUnitMovementFlag(MOVEMENTFLAG_JUMPING) || pMovementInfo.HasMovementFlag(MOVEMENTFLAG_JUMPING) || GetMap()->GetGameObject(pMovementInfo.t_guid))
|
|
+ return false;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
void Player::UpdatePvPState(bool onlyFFA)
|
|
{
|
|
// TODO: should we always synchronize UNIT_FIELD_BYTES_2, 1 of controller and controlled?
|
|
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
|
|
--- a/src/server/game/Entities/Player/Player.h
|
|
+++ b/src/server/game/Entities/Player/Player.h
|
|
@@ -2375,6 +2375,19 @@
|
|
|
|
float GetAverageItemLevel();
|
|
|
|
+ /********************************************************************/
|
|
+ /*** ANTICHEAT SYSTEM SymbolixDEV ***/
|
|
+ /********************************************************************/
|
|
+ uint32 GetLastPacketTime() { return uiLastPacketTime;}
|
|
+ uint32 GetLastOpcode() { return uiLastOpcode; }
|
|
+ float GetLastSpeedRate() { return fLastSpeedRate; }
|
|
+ void SetLastPacketTime(uint32 uiTime) { uiLastPacketTime = uiTime; }
|
|
+ void SetLastSpeedRate(float fSpeedRateRate) { fLastSpeedRate = fSpeedRateRate; }
|
|
+ void SetLastOpcode(uint32 uiOpcode) { uiLastOpcode = uiOpcode; }
|
|
+ void ElaborateCheatReport(Player* pPlayer, uint8 uiReportType);
|
|
+ bool CanFlyAnticheat(MovementInfo& pMovementInfo);
|
|
+ bool HasFirstReport();
|
|
+ void CleanTempCheatReports();
|
|
protected:
|
|
uint32 m_AreaID;
|
|
uint32 m_regenTimerCount;
|
|
@@ -2614,4 +2627,6 @@
|
|
DeclinedName *m_declinedname;
|
|
Runes *m_runes;
|
|
EquipmentSets m_EquipmentSets;
|
|
+
|
|
+ bool isAlwaysDetectableFor(WorldObject const* seer) const;
|
|
private:
|
|
@@ -2617,4 +2632,11 @@
|
|
private:
|
|
+ /********************************************************************/
|
|
+ /*** ANTICHEAT SYSTEM SymboliXDEV ***/
|
|
+ /********************************************************************/
|
|
+ uint32 uiLastPacketTime;
|
|
+ float fLastSpeedRate;
|
|
+ uint32 uiLastOpcode;
|
|
+
|
|
// internal common parts for CanStore/StoreItem functions
|
|
uint8 _CanStoreItem_InSpecificSlot(uint8 bag, uint8 slot, ItemPosCountVec& dest, ItemPrototype const *pProto, uint32& count, bool swap, Item *pSrcItem) const;
|
|
uint8 _CanStoreItem_InBag(uint8 bag, ItemPosCountVec& dest, ItemPrototype const *pProto, uint32& count, bool merge, bool non_specialized, Item *pSrcItem, uint8 skip_bag, uint8 skip_slot) const;
|
|
diff --git a/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp b/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp
|
|
--- a/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp
|
|
+++ b/src/server/game/Server/Protocol/Handlers/MovementHandler.cpp
|
|
@@ -348,6 +348,129 @@
|
|
}
|
|
|
|
/*----------------------*/
|
|
+
|
|
+ // ANTICHEAT CHECKS
|
|
+ if (sWorld.getBoolConfig(CONFIG_ANTICHEAT_ENABLE))
|
|
+ {
|
|
+ /* Hack Detection doesn't work if:
|
|
|
|
+ * player is in flight/transport
|
|
|
|
+ * player is teleporting
|
|
|
|
+ * when can't free move
|
|
|
|
+ */
|
|
|
|
+
|
|
+ if (plMover &&
|
|
+ !plMover->IsInFlight() &&
|
|
+ !plMover->GetTransport() &&
|
|
+ !plMover->IsBeingTeleported() &&
|
|
+ plMover->CanFreeMove() &&
|
|
+ !plMover->IsGameMaster())
|
|
+ {
|
|
+ // fly hack detection
|
|
+ // PosZ is checked to see if the player is going up when it should not.
|
|
+ // we need a better way :(
|
|
+ if (plMover->CanFlyAnticheat(movementInfo))
|
|
+ {
|
|
+ if (movementInfo.pos.GetPositionZ() > plMover->GetPositionZ() && fabs(movementInfo.pos.GetPositionZ() - plMover->GetPositionZ()) > 1.5f)
|
|
+ {
|
|
+ float ground_Z = plMover->GetMap()->GetHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ());
|
|
+ if (movementInfo.pos.GetPositionZ() > ground_Z && fabs(movementInfo.pos.GetPositionZ() - ground_Z) >= 5.0f)
|
|
+ plMover->ElaborateCheatReport(plMover,2);
|
|
+ }
|
|
+ }
|
|
+ // speed hack detection
|
|
+ if (plMover->GetLastPacketTime() > 0 &&
|
|
+ movementInfo.GetMovementFlags() == plMover->GetUnitMovementFlags() &&
|
|
+ opcode == MSG_MOVE_HEARTBEAT &&
|
|
+ plMover->GetLastOpcode() == opcode &&
|
|
+ !plMover->GetVehicle() &&
|
|
+ plMover->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE)
|
|
+ {
|
|
+ uint8 uiMoveType = 0;
|
|
+
|
|
+ if (plMover->IsFlying())
|
|
+ uiMoveType = MOVE_FLIGHT;
|
|
+ else if (plMover->IsUnderWater())
|
|
+ uiMoveType = MOVE_SWIM;
|
|
+ else
|
|
+ uiMoveType = MOVE_RUN;
|
|
+
|
|
+ // this is the distance doable by a player in 1000 ms.
|
|
+ float fSpeedRate = plMover->GetSpeedRate(UnitMoveType(uiMoveType));
|
|
+
|
|
+ // in my opinion this var must be constant in each check to avoid false reports
|
|
+ if (plMover->GetLastSpeedRate() == fSpeedRate)
|
|
+ {
|
|
+ // Calculate Distance2D
|
|
+ float fDeltaX = pow((movementInfo.pos.GetPositionX() - plMover->GetPositionX()),2);
|
|
+ float fDeltaY = pow(movementInfo.pos.GetPositionY() - plMover->GetPositionY(),2);
|
|
+ // final distance
|
|
+ float fDistance2d = fabs(sqrt(fDeltaX + fDeltaY) - plMover->GetObjectSize() - plMover->GetObjectSize());
|
|
+
|
|
+ // time between packets
|
|
+ uint32 uiDiffTime = getMSTimeDiff(plMover->GetLastPacketTime(), movementInfo.time);
|
|
+
|
|
+ // this is the distance doable by the player in 1 sec using the time between the packets
|
|
+ float fCoreDistance = uiDiffTime * 7.0f * fSpeedRate / 1000;
|
|
+
|
|
+ /* SPEED HACK DETECTION */
|
|
+ if (uiDiffTime < sWorld.getIntConfig(CONFIG_ANTICHEAT_MAX_DIFF_TIME) && uiDiffTime > sWorld.getIntConfig(CONFIG_ANTICHEAT_MIN_DIFF_TIME))
|
|
+ {
|
|
+ // some times (i dont know why) fCoreDistance is 0
|
|
+ if (fCoreDistance > 0.0f && fDistance2d > 0)
|
|
+ {
|
|
+ if (fDistance2d > fCoreDistance)
|
|
+ {
|
|
+ if (fabs(fCoreDistance - fDistance2d) > sWorld.getFloatConfig(CONFIG_ANTICHEAT_MAX_DISTANCE_DIFF_ALLOWED))
|
|
+ {
|
|
+ TC_LOG_INFO("server.worldserver", "Cheater! guid %u name %s fCoreDistance %f fDistance2d %f uiDiffTime %u fSpeedRate %f Latency %u",plMover->GetGUIDLow(),plMover->GetName(),fCoreDistance,fDistance2d,uiDiffTime,fSpeedRate, plMover->GetSession()->GetLatency());
|
|
+ plMover->ElaborateCheatReport(plMover,1);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // just to prevent false reports when we switch (off/on) for example the aura or something.
|
|
|
|
+ if (movementInfo.GetMovementFlags() == plMover->GetUnitMovementFlags())
|
|
|
|
+ {
|
|
|
|
+ // walk on water hack detection
|
|
|
|
+ // AFAIK the player can only do this if has some aura that allows it...
|
|
|
|
+ if (!plMover->HasAuraType(SPELL_AURA_WATER_WALK) &&
|
|
|
|
+ plMover->HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING))
|
|
|
|
+ {
|
|
|
|
+ TC_LOG_INFO("server.worldserver", "Cheater! guid %u name %s Latency %u",plMover->GetGUIDLow(),plMover->GetName(), plMover->GetSession()->GetLatency());
|
|
|
|
+ plMover->ElaborateCheatReport(plMover,3);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // walk on water hack detection
|
|
|
|
+ // AFAIK the player can only do this if has some aura that allows it...
|
|
|
|
+ if (plMover->IsFlying() &&
|
|
|
|
+ !plMover->HasAuraType(SPELL_AURA_FLY)
|
|
|
|
+ && !plMover->GetVehicle())
|
|
|
|
+ {
|
|
|
|
+ TC_LOG_INFO("server.worldserver", "Cheater! guid %u name %s Latency %u",plMover->GetGUIDLow(),plMover->GetName(), plMover->GetSession()->GetLatency());
|
|
|
|
+ plMover->ElaborateCheatReport(plMover,2);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // save packet time for next control.
|
|
+ if (plMover)
|
|
+ {
|
|
+ uint8 uiMoveType = 0;
|
|
+
|
|
+ if (plMover->IsFlying())
|
|
+ uiMoveType = MOVE_FLIGHT;
|
|
+ else if (plMover->IsUnderWater())
|
|
+ uiMoveType = MOVE_SWIM;
|
|
+ else
|
|
+ uiMoveType = MOVE_RUN;
|
|
+
|
|
+ plMover->SetLastPacketTime(movementInfo.time);
|
|
+ plMover->SetLastSpeedRate(plMover->GetSpeedRate(UnitMoveType(uiMoveType)));
|
|
+ plMover->SetLastOpcode(opcode);
|
|
+ }
|
|
+ }
|
|
|
|
/* process position-change */
|
|
WorldPacket data(opcode, recv_data.size());
|
|
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
|
|
--- a/src/server/game/World/World.cpp
|
|
+++ b/src/server/game/World/World.cpp
|
|
@@ -1222,6 +1222,12 @@
|
|
m_int_configs[CONFIG_AUTOBROADCAST_CENTER] = sConfig.GetIntDefault("AutoBroadcast.Center", 0);
|
|
m_int_configs[CONFIG_AUTOBROADCAST_INTERVAL] = sConfig.GetIntDefault("AutoBroadcast.Timer", 60000);
|
|
|
|
+ // anticheat configs
|
|
+ m_bool_configs[CONFIG_ANTICHEAT_ENABLE] = sConfig.GetBoolDefault("Anticheat.Enable", false);
|
|
+ m_int_configs[CONFIG_ANTICHEAT_MAX_DIFF_TIME] = sConfig.GetIntDefault("Anticheat.MaxDiffTime", 1000);
|
|
+ m_int_configs[CONFIG_ANTICHEAT_MIN_DIFF_TIME] = sConfig.GetIntDefault("Anticheat.MinDiffTime", 50);
|
|
+ m_float_configs[CONFIG_ANTICHEAT_MAX_DISTANCE_DIFF_ALLOWED] = sConfig.GetFloatDefault("Anticheat.MaxMaxAllowedDistance",1.0f);
|
|
+
|
|
sScriptMgr.OnConfigLoad(reload);
|
|
}
|
|
|
|
@@ -2597,6 +2603,10 @@
|
|
for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
|
|
if (itr->second->GetPlayer())
|
|
itr->second->GetPlayer()->ResetDailyQuestStatus();
|
|
+
|
|
+ //ANTICHEAT
|
|
+ //CharacterDatabase.Execute("DELETE FROM cheat_reports;");
|
|
+ //CharacterDatabase.Execute("DELETE FROM cheat_first_report;");
|
|
}
|
|
|
|
void World::LoadDBAllowedSecurityLevel()
|
|
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
|
|
--- a/src/server/game/World/World.h
|
|
+++ b/src/server/game/World/World.h
|
|
@@ -163,6 +163,7 @@
|
|
CONFIG_CHATLOG_BGROUND,
|
|
CONFIG_DUNGEON_FINDER_ENABLE,
|
|
CONFIG_AUTOBROADCAST,
|
|
+ CONFIG_ANTICHEAT_ENABLE,
|
|
BOOL_CONFIG_VALUE_COUNT
|
|
};
|
|
|
|
@@ -179,6 +180,7 @@
|
|
CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS,
|
|
CONFIG_THREAT_RADIUS,
|
|
CONFIG_CHANCE_OF_GM_SURVEY,
|
|
+ CONFIG_ANTICHEAT_MAX_DISTANCE_DIFF_ALLOWED,
|
|
FLOAT_CONFIG_VALUE_COUNT
|
|
};
|
|
|
|
@@ -307,6 +309,8 @@
|
|
CONFIG_AUTOBROADCAST_CENTER,
|
|
CONFIG_AUTOBROADCAST_INTERVAL,
|
|
CONFIG_MAX_RESULTS_LOOKUP_COMMANDS,
|
|
+ CONFIG_ANTICHEAT_MAX_DIFF_TIME,
|
|
+ CONFIG_ANTICHEAT_MIN_DIFF_TIME,
|
|
INT_CONFIG_VALUE_COUNT
|
|
};
|
|
|
|
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
|
|
--- a/src/server/worldserver/worldserver.conf.dist
|
|
+++ b/src/server/worldserver/worldserver.conf.dist
|
|
@@ -2069,6 +2069,16 @@
|
|
# Default: 0 - off
|
|
# 1 - on
|
|
#
|
|
+# SymbolixDEV Anticheat.Enable
|
|
+# Enable Anticheat System
|
|
+# Default: 0 - off
|
|
+# 1 - on
|
|
+# Anticheat.MaxDiffTime
|
|
+# Default: 1000 ms
|
|
+# Anticheat.MinDiffTime
|
|
+# Default: 350 ms
|
|
+# Anticheat.MaxMaxAllowedDistance
|
|
+# Default: 1.0 f
|
|
###############################################################################
|
|
|
|
PlayerStart.AllReputation = 0
|
|
@@ -2092,3 +2102,7 @@
|
|
LevelReq.Auction = 1
|
|
LevelReq.Mail = 1
|
|
DungeonFinder.Enable = 0
|
|
+Anticheat.Enable = 0
|
|
+Anticheat.MaxDiffTime = 1000
|
|
+Anticheat.MinDiffTime = 50
|
|
+Anticheat.MaxMaxAllowedDistance = 1.0
|