diff --git a/src/game/Language.h b/src/game/Language.h index ae8eb47..dc49f98 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -899,7 +899,8 @@ enum MangosStrings // Use for not-in-offcial-sources patches // 10000-10999 - + LANG_ANNOUNCE_CHEAT = 11000 + // Use for custom patches 11000-11999 // NOT RESERVED IDS 12000-1999999999 diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 596f80e..f90eafa 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -5674,6 +5674,10 @@ bool ChatHandler::HandleGMFlyCommand(char* args) WorldPacket data(12); data.SetOpcode(value ? SMSG_MOVE_SET_CAN_FLY : SMSG_MOVE_UNSET_CAN_FLY); + if (value) + ((Player*)(target))->SetCanFly(true); + else + ((Player*)(target))->SetCanFly(false); data << target->GetPackGUID(); data << uint32(0); // unknown target->SendMessageToSet(&data, true); diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index b02645f..b7296d7 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -31,6 +31,184 @@ #include "WaypointMovementGenerator.h" #include "InstanceSaveMgr.h" #include "ObjectMgr.h" +#include "World.h" +#include "Language.h" + +//#define __ANTI_DEBUG__ + +#ifdef __ANTI_DEBUG__ +#include "Chat.h" +std::string FlagsToStr(const uint32 Flags) +{ + std::string Ret=""; + if(Flags==0) + { + Ret="None"; + return Ret; + } + + if(Flags & MOVEMENTFLAG_FORWARD) + { Ret+="FW "; } + if(Flags & MOVEMENTFLAG_BACKWARD) + { Ret+="BW "; } + if(Flags & MOVEMENTFLAG_STRAFE_LEFT) + { Ret+="STL "; } + if(Flags & MOVEMENTFLAG_STRAFE_RIGHT) + { Ret+="STR "; } + if(Flags & MOVEMENTFLAG_LEFT) + { Ret+="LF "; } + if(Flags & MOVEMENTFLAG_RIGHT) + { Ret+="RI "; } + if(Flags & MOVEMENTFLAG_PITCH_UP) + { Ret+="PTUP "; } + if(Flags & MOVEMENTFLAG_PITCH_DOWN) + { Ret+="PTDW "; } + if(Flags & MOVEMENTFLAG_WALK_MODE) + { Ret+="WALK "; } + if(Flags & MOVEMENTFLAG_ONTRANSPORT) + { Ret+="TRANS "; } + if(Flags & MOVEMENTFLAG_LEVITATING) + { Ret+="LEVI "; } + if(Flags & MOVEMENTFLAG_FLY_UNK1) + { Ret+="FLYUNK1 "; } + if(Flags & MOVEMENTFLAG_JUMPING) + { Ret+="JUMP "; } + if(Flags & MOVEMENTFLAG_UNK4) + { Ret+="UNK4 "; } + if(Flags & MOVEMENTFLAG_FALLING) + { Ret+="FALL "; } + if(Flags & MOVEMENTFLAG_SWIMMING) + { Ret+="SWIM "; } + if(Flags & MOVEMENTFLAG_FLY_UP) + { Ret+="FLYUP "; } + if(Flags & MOVEMENTFLAG_CAN_FLY) + { Ret+="CFLY "; } + if(Flags & MOVEMENTFLAG_FLYING) + { Ret+="FLY "; } + if(Flags & MOVEMENTFLAG_FLYING2) + { Ret+="FLY2 "; } + if(Flags & MOVEMENTFLAG_WATERWALKING) + { Ret+="WTWALK "; } + if(Flags & MOVEMENTFLAG_SAFE_FALL) + { Ret+="SAFE "; } + if(Flags & MOVEMENTFLAG_UNK3) + { Ret+="UNK3 "; } + if(Flags & MOVEMENTFLAG_SPLINE) + { Ret+="SPLINE "; } + if(Flags & MOVEMENTFLAG_SPLINE2) + { Ret+="SPLINE2 "; } + + return Ret; +} +#endif // __ANTI_DEBUG__ + +bool WorldSession::Anti__ReportCheat(const char* Reason,float Speed,const char* Op,float Val1,uint32 Val2) +{ + if(!Reason) + { + sLog.outError("Anti__ReportCheat: Missing Reason parameter!"); + return false; + } + const char* Player=GetPlayer()->GetName(); + uint32 Acc=GetPlayer()->GetSession()->GetAccountId(); + uint32 Map=GetPlayer()->GetMapId(); + if(!Player) + { + sLog.outError("Anti__ReportCheat: Player with no name?!?"); + return false; + } + + QueryResult *Res=CharacterDatabase.PQuery("SELECT speed,Val1 FROM cheaters WHERE player='%s' AND reason LIKE '%s' AND Map='%u' AND last_date >= NOW()-300",Player,Reason,Map); + if(Res) + { + Field* Fields = Res->Fetch(); + + std::stringstream Query; + Query << "UPDATE cheaters SET count=count+1,last_date=NOW()"; + Query.precision(5); + if(Speed>0.0f && Speed > Fields[0].GetFloat()) + { + Query << ",speed='"; + Query << std::fixed << Speed; + Query << "'"; + } + + if(Val1>0.0f && Val1 > Fields[1].GetFloat()) + { + Query << ",Val1='"; + Query << std::fixed << Val1; + Query << "'"; + } + + Query << " WHERE player='" << Player << "' AND reason='" << Reason << "' AND Map='" << Map << "' AND last_date >= NOW()-300 ORDER BY entry DESC LIMIT 1"; + + CharacterDatabase.Execute(Query.str().c_str()); + delete Res; + } + else + { + if(!Op) + { Op=""; } + std::stringstream Pos; + Pos << "OldPos: " << GetPlayer()->GetPositionX() << " " << GetPlayer()->GetPositionY() << " " + << GetPlayer()->GetPositionZ(); + CharacterDatabase.PExecute("INSERT INTO cheaters (player,acctid,reason,speed,count,first_date,last_date,`Op`,Val1,Val2,Map,Pos,Level) " + "VALUES ('%s','%u','%s','%f','1',NOW(),NOW(),'%s','%f','%u','%u','%s','%u')", + Player,Acc,Reason,Speed,Op,Val1,Val2,Map, + Pos.str().c_str(),GetPlayer()->getLevel()); + } + + if(sWorld.GetMvAnticheatKill() && GetPlayer()->isAlive()) + { + GetPlayer()->DealDamage(GetPlayer(), GetPlayer()->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + if(sWorld.GetMvAnticheatKick()) + { + GetPlayer()->GetSession()->KickPlayer(); + } + if(sWorld.GetMvAnticheatBan() & 1) + { + sWorld.BanAccount(BAN_CHARACTER,Player,sWorld.GetMvAnticheatBanTime(),"Cheat","Anticheat"); + } + if(sWorld.GetMvAnticheatBan() & 2) + { + QueryResult *result = LoginDatabase.PQuery("SELECT last_ip FROM account WHERE id=%u", Acc); + if(result) + { + + Field *fields = result->Fetch(); + std::string LastIP = fields[0].GetCppString(); + if(!LastIP.empty()) + { + sWorld.BanAccount(BAN_IP,LastIP,sWorld.GetMvAnticheatBanTime(),"Cheat","Anticheat"); + } + delete result; + } + } + return true; +} + +bool WorldSession::Anti__CheatOccurred(uint32 CurTime,const char* Reason,float Speed,const char* Op, + float Val1,uint32 Val2) +{ + if(!Reason) + { + sLog.outError("Anti__CheatOccurred: Missing Reason parameter!"); + return false; + } + + GetPlayer()->m_anti_lastalarmtime = CurTime; + GetPlayer()->m_anti_alarmcount = GetPlayer()->m_anti_alarmcount + 1; + + if (GetPlayer()->m_anti_alarmcount > sWorld.GetMvAnticheatAlarmCount()) + { + Anti__ReportCheat(Reason,Speed,Op,Val1,Val2); + if(sWorld.GetMvAnticheatAnnounce()) + sWorld.SendWorldText(LANG_ANNOUNCE_CHEAT, GetPlayer()->GetName(), Reason); + return true; + } + return false; +} void WorldSession::HandleMoveWorldportAckOpcode( WorldPacket & /*recv_data*/ ) { @@ -72,6 +250,7 @@ void WorldSession::HandleMoveWorldportAckOpcode() // relocate the player to the teleport destination GetPlayer()->SetMap(sMapMgr.CreateMap(loc.mapid, GetPlayer())); GetPlayer()->Relocate(loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation); + GetPlayer()->m_anti_TeleTime=time(NULL); GetPlayer()->SendInitialPacketsBeforeAddToMap(); // the CanEnter checks are done in TeleporTo but conditions may change @@ -163,6 +342,8 @@ void WorldSession::HandleMoveWorldportAckOpcode() // resummon pet GetPlayer()->ResummonPetTemporaryUnSummonedIfAny(); + GetPlayer()->Anti__SetLastTeleTime(::time(NULL)); + GetPlayer()->m_anti_BeginFallZ=INVALID_HEIGHT; //lets process all delayed operations on successful teleport GetPlayer()->ProcessDelayedOperations(); @@ -212,6 +393,11 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data) // resummon pet GetPlayer()->ResummonPetTemporaryUnSummonedIfAny(); + if(plMover) + { + plMover->Anti__SetLastTeleTime(::time(NULL)); + plMover->m_anti_BeginFallZ=INVALID_HEIGHT; + } //lets process all delayed operations on successful teleport GetPlayer()->ProcessDelayedOperations(); @@ -268,6 +454,11 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) // if we boarded a transport, add us to it if (plMover && !plMover->m_transport) { + float trans_rad = movementInfo.GetTransportPos()->x*movementInfo.GetTransportPos()->x + movementInfo.GetTransportPos()->y*movementInfo.GetTransportPos()->y + movementInfo.GetTransportPos()->z*movementInfo.GetTransportPos()->z; + if (trans_rad > 3600.0f) // transport radius = 60 yards //cheater with on_transport_flag + { + return; + } // elevators also cause the client to send MOVEFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list for (MapManager::TransportSet::const_iterator iter = sMapMgr.m_Transports.begin(); iter != sMapMgr.m_Transports.end(); ++iter) { @@ -295,9 +486,163 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { // now client not include swimming flag in case jumping under water plMover->SetInWater( !plMover->IsInWater() || plMover->GetBaseMap()->IsUnderWater(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z) ); + if(plMover->GetBaseMap()->IsUnderWater(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z-7.0f)) + { + plMover->m_anti_BeginFallZ=INVALID_HEIGHT; + } } - /*----------------------*/ + // ---- anti-cheat features -->>> + uint32 Anti_TeleTimeDiff=plMover ? time(NULL) - plMover->Anti__GetLastTeleTime() : time(NULL); + static const uint32 Anti_TeleTimeIgnoreDiff=sWorld.GetMvAnticheatIgnoreAfterTeleport(); + if (plMover && (plMover->m_transport == 0) && sWorld.GetMvAnticheatEnable() && + GetPlayer()->GetSession()->GetSecurity() <= sWorld.GetMvAnticheatGmLevel() && + GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()!=FLIGHT_MOTION_TYPE && + Anti_TeleTimeDiff>Anti_TeleTimeIgnoreDiff) + { + const uint32 CurTime=getMSTime(); + if(getMSTimeDiff(GetPlayer()->m_anti_lastalarmtime,CurTime) > sWorld.GetMvAnticheatAlarmPeriod()) + { + GetPlayer()->m_anti_alarmcount = 0; + } + /* I really don't care about movement-type yet (todo) + UnitMoveType move_type; + + if (movementInfo.flags & MOVEMENTFLAG_FLYING) move_type = MOVE_FLY; + else if (movementInfo.flags & MOVEMENTFLAG_SWIMMING) move_type = MOVE_SWIM; + else if (movementInfo.flags & MOVEMENTFLAG_WALK_MODE) move_type = MOVE_WALK; + else move_type = MOVE_RUN;*/ + + float delta_x = GetPlayer()->GetPositionX() - movementInfo.GetPos()->x; + float delta_y = GetPlayer()->GetPositionY() - movementInfo.GetPos()->y; + float delta_z = GetPlayer()->GetPositionZ() - movementInfo.GetPos()->z; + float delta = sqrt(delta_x * delta_x + delta_y * delta_y); // Len of movement-vector via Pythagoras (a^2+b^2=Len^2) + float tg_z = 0.0f; //tangens + float delta_t = getMSTimeDiff(GetPlayer()->m_anti_lastmovetime,CurTime); + + GetPlayer()->m_anti_lastmovetime = CurTime; + GetPlayer()->m_anti_MovedLen += delta; + + if(delta_t > 15000.0f) + { delta_t = 15000.0f; } + + // Tangens of walking angel + if (!(movementInfo.GetMovementFlags() & (MOVEFLAG_FLYING | MOVEFLAG_SWIMMING))) + { + tg_z = ((delta !=0.0f) && (delta_z > 0.0f)) ? (atan((delta_z*delta_z) / delta) * 180.0f / M_PI) : 0.0f; + } + + //antiOFF fall-damage, MOVEMENTFLAG_UNK4 seted by client if player try movement when falling and unset in this case the MOVEMENTFLAG_FALLING flag. + if((!GetPlayer()->CanFly() && GetPlayer()->m_anti_BeginFallZ == INVALID_HEIGHT) && + (movementInfo.GetMovementFlags() & (MOVEFLAG_FALLING | MOVEFLAG_FALLINGFAR)) != 0) + { + GetPlayer()->m_anti_BeginFallZ=(float)(movementInfo.GetPos()->z); + } + + if(GetPlayer()->m_anti_NextLenCheck <= CurTime) + { + // Check every 500ms is a lot more advisable then 1000ms, because normal movment packet arrives every 500ms + uint32 OldNextLenCheck=GetPlayer()->m_anti_NextLenCheck; + float delta_xyt=GetPlayer()->m_anti_MovedLen/(float)(getMSTimeDiff(OldNextLenCheck-500,CurTime)); + GetPlayer()->m_anti_NextLenCheck = CurTime+500; + GetPlayer()->m_anti_MovedLen = 0.0f; + static const float MaxDeltaXYT = sWorld.GetMvAnticheatMaxXYT(); + + if(delta_xyt > MaxDeltaXYT && delta<=100.0f && GetPlayer()->GetZoneId() != 2257) + { + if(sWorld.GetMvAnticheatSpeedCheck()) + Anti__CheatOccurred(CurTime,"Speed hack",delta_xyt,LookupOpcodeName(opcode), + (float)(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()), + (float)(getMSTimeDiff(OldNextLenCheck-500,CurTime))); + } + } + + if(delta > 100.0f && GetPlayer()->GetZoneId() != 2257) + { + if(sWorld.GetMvAnticheatTeleportCheck()) + Anti__ReportCheat("Tele hack",delta,LookupOpcodeName(opcode)); + } + + // Check for waterwalking . Fix new way of checking for waterwalking by Darky88 + if (movementInfo.HasMovementFlag(MOVEFLAG_WATERWALKING) && + !(GetPlayer()->HasAuraType(SPELL_AURA_WATER_WALK) || GetPlayer()->HasAuraType(SPELL_AURA_GHOST))) + { + if(sWorld.GetMvAnticheatWaterCheck()) + Anti__CheatOccurred(CurTime,"Water walking",0.0f,NULL,0.0f,(uint32)(movementInfo.GetMovementFlags())); + } + + // Check for walking upwards a mountain while not beeing able to do that, New check by Darky88 + if((delta_z < -2.3f) && (tg_z > 2.37f)) + { + if(sWorld.GetMvAnticheatMountainCheck()) + Anti__CheatOccurred(CurTime,"Mountain hack",tg_z,NULL,delta,delta_z); + } + + + static const float DIFF_OVERGROUND = 10.0f; + float Anti__GroundZ = GetPlayer()->GetMap()->GetHeight(GetPlayer()->GetPositionX(),GetPlayer()->GetPositionY(),MAX_HEIGHT); + float Anti__FloorZ = GetPlayer()->GetMap()->GetHeight(GetPlayer()->GetPositionX(),GetPlayer()->GetPositionY(),GetPlayer()->GetPositionZ()); + float Anti__MapZ = ((Anti__FloorZ <= (INVALID_HEIGHT+5.0f)) ? Anti__GroundZ : Anti__FloorZ) + DIFF_OVERGROUND; + + if(!GetPlayer()->CanFly() && + !GetPlayer()->GetBaseMap()->IsUnderWater(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z-7.0f) && + Anti__MapZ < GetPlayer()->GetPositionZ() && Anti__MapZ > (INVALID_HEIGHT+DIFF_OVERGROUND + 5.0f)) + { + static const float DIFF_AIRJUMP=25.0f; // 25 is realy high, but to many false positives... + + // Air-Jump-Detection definitively needs a better way to be detected... + if((movementInfo.GetMovementFlags() & (MOVEFLAG_CAN_FLY | MOVEFLAG_FLYING | MOVEFLAG_ROOT)) != 0) // Fly Hack + { + // Fix Aura 55164 by KAPATEJIb + if (!GetPlayer()->HasAura(55164)) + if(sWorld.GetMvAnticheatFlyCheck()) + Anti__CheatOccurred(CurTime,"Fly hack", + ((uint8)(GetPlayer()->HasAuraType(SPELL_AURA_FLY))) + + /*((uint8)(GetPlayer()->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED))*2),*/ + ((uint8)(GetPlayer()->HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_MOUNTED))*2), + NULL,GetPlayer()->GetPositionZ()-Anti__MapZ); + } + + // Need a better way to do that - currently a lot of fake alarms + else if((Anti__MapZ+DIFF_AIRJUMP < GetPlayer()->GetPositionZ() && + (movementInfo.GetMovementFlags() & (MOVEFLAG_FALLINGFAR /*| MOVEFLAG_UNK4*/))==0) || + (Anti__MapZ < GetPlayer()->GetPositionZ() && + opcode==MSG_MOVE_JUMP)) + { + if(sWorld.GetMvAnticheatJumpCheck()) + Anti__CheatOccurred(CurTime,"Possible Air Jump Hack",0.0f,LookupOpcodeName(opcode),0.0f,movementInfo.GetMovementFlags()); + } + } + + + /*if(Anti__FloorZ < -199900.0f && Anti__GroundZ >= -199900.0f && + GetPlayer()->GetPositionZ()+5.0f < Anti__GroundZ) + { + Anti__CheatOccurred(CurTime,"Teleport2Plane hack", + GetPlayer()->GetPositionZ(),NULL,Anti__GroundZ); + }*/ + + //Teleport To Plane checks + if (movementInfo.GetPos()->z < 0.0001f && movementInfo.GetPos()->z > -0.0001f && (!movementInfo.HasMovementFlag(MovementFlags(MOVEFLAG_SWIMMING | MOVEFLAG_CAN_FLY | MOVEFLAG_FLYING)))) + { + if(sWorld.GetMvAnticheatTeleport2PlaneCheck()) + { + // Prevent using TeleportToPlan. + Map *map = GetPlayer()->GetMap(); + if (map) + { + float plane_z = map->GetHeight(movementInfo.GetPos()->x, movementInfo.GetPos()->y, MAX_HEIGHT) - movementInfo.GetPos()->z; + plane_z = (plane_z < -500.0f) ? 0 : plane_z; //check holes in heigth map + if(plane_z > 0.1f || plane_z < -0.1f) + { + if(sWorld.GetMvAnticheatTeleport2PlaneCheck()) + Anti__CheatOccurred(CurTime,"Teleport2Plane hack",GetPlayer()->GetPositionZ(),NULL,plane_z); + } + } + } + } + } + // <<---- anti-cheat features /* process position-change */ movementInfo.UpdateTime(getMSTime()); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 0d91386..6c9ff3d 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -538,6 +538,17 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa rest_type=REST_TYPE_NO; ////////////////////Rest System///////////////////// + //movement anticheat + m_anti_lastmovetime = 0; //last movement time + m_anti_NextLenCheck = 0; + m_anti_MovedLen = 0.0f; + m_anti_BeginFallZ = INVALID_HEIGHT; + m_anti_lastalarmtime = 0; //last time when alarm generated + m_anti_alarmcount = 0; //alarm counter + m_anti_TeleTime = 0; + m_CanFly=false; + ///////////////////////////////// + m_mailsUpdated = false; unReadMails = 0; m_nextMailDelivereTime = 0; @@ -21281,7 +21292,9 @@ uint8 Player::CanEquipUniqueItem( ItemPrototype const* itemProto, uint8 except_s void Player::HandleFall(MovementInfo const& movementInfo) { // calculate total z distance of the fall - float z_diff = m_lastFallZ - movementInfo.GetPos()->z; + float z_diff = (m_lastFallZ >= m_anti_BeginFallZ ? m_lastFallZ : m_anti_BeginFallZ) - movementInfo.GetPos()->z; + + m_anti_BeginFallZ=INVALID_HEIGHT; DEBUG_LOG("zDiff = %f", z_diff); //Players with low fall distance, Feather Fall or physical immunity (charges used) are ignored diff --git a/src/game/Player.h b/src/game/Player.h index 0b32ad4..3e52385 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2235,7 +2235,11 @@ class MANGOS_DLL_SPEC Player : public Unit bool isMoving() const { return m_movementInfo.HasMovementFlag(movementFlagsMask); } bool isMovingOrTurning() const { return m_movementInfo.HasMovementFlag(movementOrTurningFlagsMask); } - bool CanFly() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_CAN_FLY); } + uint32 Anti__GetLastTeleTime() const { return m_anti_TeleTime; } + void Anti__SetLastTeleTime(uint32 TeleTime) { m_anti_TeleTime=TeleTime; } + //bool CanFly() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_CAN_FLY); } + bool CanFly() const { return m_CanFly; } + void SetCanFly(bool CanFly) { m_CanFly=CanFly; } bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_FLYING); } bool IsFreeFlying() const { return HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_MOUNTED) || HasAuraType(SPELL_AURA_FLY); } bool CanStartFlyInArea(uint32 mapid, uint32 zone, uint32 area) const; @@ -2589,6 +2593,16 @@ class MANGOS_DLL_SPEC Player : public Unit RestType rest_type; ////////////////////Rest System///////////////////// + //movement anticheat + uint32 m_anti_lastmovetime; //last movement time + float m_anti_MovedLen; //Length of traveled way + uint32 m_anti_NextLenCheck; + float m_anti_BeginFallZ; //alternative falling begin + uint32 m_anti_lastalarmtime; //last time when alarm generated + uint32 m_anti_alarmcount; //alarm counter + uint32 m_anti_TeleTime; + bool m_CanFly; + // Transports Transport * m_transport; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index ddc276d..8d163ae 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -4243,9 +4243,16 @@ void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real) { WorldPacket data; if(apply) + { + ((Player*)target)->SetCanFly(true); data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12); + } else + { data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12); + ((Player*)target)->SetCanFly(false); + } + //data.append(m_target->GetPackGUID()); data << target->GetPackGUID(); data << uint32(0); // unknown target->SendMessageToSet(&data, true); @@ -6110,9 +6117,15 @@ void Aura::HandleAuraAllowFlight(bool apply, bool Real) // allow fly WorldPacket data; if(apply) + { + ((Player*)GetTarget())->SetCanFly(true); data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12); + } else + { data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12); + ((Player*)GetTarget())->SetCanFly(false); + } data << GetTarget()->GetPackGUID(); data << uint32(0); // unk GetTarget()->SendMessageToSet(&data, true); diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp index 4950a36..cf6f9c2 100644 --- a/src/game/WaypointMovementGenerator.cpp +++ b/src/game/WaypointMovementGenerator.cpp @@ -318,6 +318,7 @@ void FlightPathMovementGenerator::Finalize(Player & player) float x, y, z; i_destinationHolder.GetLocationNow(player.GetBaseMap(), x, y, z); + player.Anti__SetLastTeleTime(time(NULL)); player.SetPosition(x, y, z, player.GetOrientation()); player.Unmount(); diff --git a/src/game/World.cpp b/src/game/World.cpp index f45f20c..37a7ce2 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -513,6 +513,28 @@ void World::LoadConfigSettings(bool reload) setConfigPos(CONFIG_FLOAT_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS, "CreatureFamilyFleeAssistanceRadius", 30.0f); ///- Read other configuration items from the config file + + // movement anticheat + m_MvAnticheatEnable = sConfig.GetBoolDefault("Anticheat.Movement.Enable",false); + m_MvAnticheatKick = sConfig.GetBoolDefault("Anticheat.Movement.Kick",false); + m_MvAnticheatAnnounce = sConfig.GetBoolDefault("Anticheat.Movement.Announce",false); + m_MvAnticheatAlarmCount = (uint32)sConfig.GetIntDefault("Anticheat.Movement.AlarmCount", 5); + m_MvAnticheatAlarmPeriod = (uint32)sConfig.GetIntDefault("Anticheat.Movement.AlarmTime", 5000); + m_MvAntiCheatBan = (unsigned char)sConfig.GetIntDefault("Anticheat.Movement.BanType",0); + m_MvAnticheatBanTime = (uint32)sConfig.GetIntDefault("Anticheat.Movement.BanTime",60); + m_MvAnticheatGmLevel = (unsigned char)sConfig.GetIntDefault("Anticheat.Movement.GmLevel",0); + m_MvAnticheatKill = sConfig.GetBoolDefault("Anticheat.Movement.Kill",false); + m_MvAnticheatMaxXYT = sConfig.GetFloatDefault("Anticheat.Movement.MaxXYT",0.04f); + m_MvAnticheatIgnoreAfterTeleport = (uint16)sConfig.GetIntDefault("Anticheat.Movement.IgnoreSecAfterTeleport",10); + + m_MvAnticheatSpeedCheck = sConfig.GetBoolDefault("Anticheat.Movement.DetectSpeedHack",1); + m_MvAnticheatWaterCheck = sConfig.GetBoolDefault("Anticheat.Movement.DetectWaterWalk",1); + m_MvAnticheatFlyCheck = sConfig.GetBoolDefault("Anticheat.Movement.DetectFlyHack",1); + m_MvAnticheatMountainCheck = sConfig.GetBoolDefault("Anticheat.Movement.DetectMountainHack",1); + m_MvAnticheatJumpCheck = sConfig.GetBoolDefault("Anticheat.Movement.DetectAirJumpHack",1); + m_MvAnticheatTeleportCheck = sConfig.GetBoolDefault("Anticheat.Movement.DetectTeleportHack",1); + m_MvAnticheatTeleport2PlaneCheck = sConfig.GetBoolDefault("Anticheat.Movement.DetectTeleport2PlaneHack",0); + setConfigMinMax(CONFIG_UINT32_COMPRESSION, "Compression", 1, 1, 9); setConfig(CONFIG_BOOL_ADDON_CHANNEL, "AddonChannel", true); setConfig(CONFIG_BOOL_CLEAN_CHARACTER_DB, "CleanCharacterDB", true); diff --git a/src/game/World.h b/src/game/World.h index 9245149..d924de1 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -582,6 +582,28 @@ class World static float GetVisibleUnitGreyDistance() { return m_VisibleUnitGreyDistance; } static float GetVisibleObjectGreyDistance() { return m_VisibleObjectGreyDistance; } + //movement anticheat enable flag + inline bool GetMvAnticheatEnable() {return m_MvAnticheatEnable;} + inline bool GetMvAnticheatKick() {return m_MvAnticheatKick;} + inline bool GetMvAnticheatAnnounce() {return m_MvAnticheatAnnounce;} + inline uint32 GetMvAnticheatAlarmCount() {return m_MvAnticheatAlarmCount;} + inline uint32 GetMvAnticheatAlarmPeriod() {return m_MvAnticheatAlarmPeriod;} + inline unsigned char GetMvAnticheatBan() {return m_MvAntiCheatBan;} + inline uint32 GetMvAnticheatBanTime() {return m_MvAnticheatBanTime;} + inline unsigned char GetMvAnticheatGmLevel() {return m_MvAnticheatGmLevel;} + inline bool GetMvAnticheatKill() {return m_MvAnticheatKill;} + inline float GetMvAnticheatMaxXYT() {return m_MvAnticheatMaxXYT;} + inline uint16 GetMvAnticheatIgnoreAfterTeleport() {return m_MvAnticheatIgnoreAfterTeleport;} + + inline bool GetMvAnticheatSpeedCheck() {return m_MvAnticheatSpeedCheck;} + inline bool GetMvAnticheatWaterCheck() {return m_MvAnticheatWaterCheck;} + inline bool GetMvAnticheatFlyCheck() {return m_MvAnticheatFlyCheck;} + inline bool GetMvAnticheatMountainCheck() {return m_MvAnticheatMountainCheck;} + inline bool GetMvAnticheatJumpCheck() {return m_MvAnticheatJumpCheck;} + inline bool GetMvAnticheatTeleportCheck() {return m_MvAnticheatTeleportCheck;} + inline bool GetMvAnticheatTeleport2PlaneCheck() {return m_MvAnticheatTeleport2PlaneCheck;} + + void ProcessCliCommands(); void QueueCliCommand(CliCommandHolder* commandHolder) { cliCmdQueue.add(commandHolder); } @@ -673,6 +695,26 @@ class World static float m_VisibleUnitGreyDistance; static float m_VisibleObjectGreyDistance; + //movement anticheat enable flag + bool m_MvAnticheatEnable; + bool m_MvAnticheatKick; + bool m_MvAnticheatAnnounce; + uint32 m_MvAnticheatAlarmCount; + uint32 m_MvAnticheatAlarmPeriod; + unsigned char m_MvAntiCheatBan; + uint32 m_MvAnticheatBanTime; + unsigned char m_MvAnticheatGmLevel; + bool m_MvAnticheatKill; + float m_MvAnticheatMaxXYT; + uint16 m_MvAnticheatIgnoreAfterTeleport; + bool m_MvAnticheatSpeedCheck; + bool m_MvAnticheatWaterCheck; + bool m_MvAnticheatFlyCheck; + bool m_MvAnticheatMountainCheck; + bool m_MvAnticheatJumpCheck; + bool m_MvAnticheatTeleportCheck; + bool m_MvAnticheatTeleport2PlaneCheck; + // CLI command holder to be thread safe ACE_Based::LockedQueue cliCmdQueue; SqlResultQueue *m_resultQueue; diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index d9b9759..7c74c0a 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -153,6 +153,9 @@ class MANGOS_DLL_SPEC WorldSession bool PlayerLogout() const { return m_playerLogout; } bool PlayerLogoutWithSave() const { return m_playerLogout && m_playerSave; } + inline bool Anti__CheatOccurred(uint32 CurTime,const char* Reason,float Speed,const char* Op=NULL,float Val1=0.0f,uint32 Val2=0); + bool Anti__ReportCheat(const char* Reason,float Speed,const char* Op=NULL,float Val1=0.0f,uint32 Val2=0); + void SizeError(WorldPacket const& packet, uint32 size) const; void ReadAddonsInfo(WorldPacket &data); diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index cfd767a..4289383 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -1527,6 +1527,106 @@ SOAP.IP = 127.0.0.1 SOAP.Port = 7878 ################################################################################################################### +# MOVEMENT ANTICHEAT +# +# Anticheat.Movement.Enable +# Enable Movement Anticheat +# Default: 0 - off +# 1 - on +# +# Anticheat.Movement.AlarmCount +# Count alarms. After AlarmCount is exceeded, actions are taken against the player. (default 5) +# +# Anticheat.Movement.AlarmTime +# Reset alarm-count after this milliseconds. (default 5000) +# +# Anticheat.Movement.Kill +# Enable Kill cheater +# Default: 0 - off +# 1 - on +# +# Anticheat.Movement.Kick +# Enable Kick cheater +# Default: 0 - off +# 1 - on +# +# Anticheat.Movement.BanType +# Enable Ban cheater +# Default: 0 - off +# 1 - Ban Account +# 2 - Ban IP +# 3 - Ban Account + IP +# +# Anticheat.Movement.Announce +# Enable Announce cheater +# Default: 0 - off +# 1 - on +# +# Anticheat.Movement.DetectSpeedHack +# Turn Speed Check on/off +# Default: 1 (on) +# +# Anticheat.Movement.DetectWaterWalk +# Turn WaterWalk Check on/off +# Default: 1 (on) +# +# Anticheat.Movement.DetectFlyHack +# Turn Fly Hack Check on/off +# Default: 1 (on) +# +# Anticheat.Movement.DetectMountainHack +# Turn Speed Check on/off +# Default: 1 (on) +# Anticheat.Movement.DetectAirJumpHack +# Turn Air/Graviti Jump Check on/off +# Default: 1 (on) +# +# Anticheat.Movement.DetectTeleportHack +# Turn Teleport Check on/off +# Default: 1 (on) +# +# Anticheat.Movement.DetectTeleport2PlaneHack +# Turn Teleport2Plane Check on/off +# Default: 1 (on) +# +# Anticheat.Movement.BanTime +# How long the ban should last. +# Default: 1 Minute - 60 +# +# Anticheat.Movement.MaxXYT +# Max units a player is allowed to travel per millisecond. +# Default: 0.04 (This is ~400% Speed, 0.007 is walk-speed, 310% is 0.0287) +# +# Anticheat.Movement.IgnoreSecAfterTeleport +# After being teleported this number of seconds no cheat is reported. +# Default: 10 seconds - 10 +# +# Anticheat.Movement.GmLevel +# Only accounts that are below this gm-level or exact at the same, are reported for cheating. +# Default: Only normal Players - 0 +# +################################################################################################################### + +Anticheat.Movement.Enable = 1 +Anticheat.Movement.AlarmCount = 5 +Anticheat.Movement.AlarmTime = 5000 +Anticheat.Movement.Kill = 0 +Anticheat.Movement.Kick = 0 +Anticheat.Movement.Announce = 0 +Anticheat.Movement.DetectSpeedHack = 1 +Anticheat.Movement.DetectWaterWalk = 1 +Anticheat.Movement.DetectFlyHack = 1 +Anticheat.Movement.DetectMountainHack = 1 +Anticheat.Movement.DetectAirJumpHack = 1 +Anticheat.Movement.DetectTeleportHack = 1 +Anticheat.Movement.DetectTeleport2PlaneHack = 0 +Anticheat.Movement.BanType = 0 +Anticheat.Movement.BanTime = 60 +Anticheat.Movement.MaxXYT = 0.04 +Anticheat.Movement.IgnoreSecAfterTeleport = 10 +Anticheat.Movement.GmLevel = 0 + +################################################################################################################### # CharDelete.Method # Character deletion behavior # Default: 0 - Completely remove the character from the database