rendered paste bodydiff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp
--- a/src/game/MovementHandler.cpp
+++ b/src/game/MovementHandler.cpp
@@ -33,6 +33,12 @@
#include "WaypointMovementGenerator.h"
#include "InstanceSaveMgr.h"
#include "ObjectMgr.h"
+#include "World.h"
+
+/*Movement anticheat DEBUG defines */
+//#define MOVEMENT_ANTICHEAT_DEBUG true
+//#define MOVEMENT_ANTICHEAT_DEBUG_FULL true
+/*end Movement anticheate defines*/
void WorldSession::HandleMoveWorldportAckOpcode( WorldPacket & /*recv_data*/ )
{
@@ -56,6 +62,10 @@
return;
}
+ //movement anticheat
+ GetPlayer()->m_anti_JustTeleported = 1;
+ //end movement anticheat
+
// get the destination map entry, not the current one, this will fix homebind and reset greeting
MapEntry const* mEntry = sMapStore.LookupEntry(loc.GetMapId());
InstanceTemplate const* mInstance = objmgr.GetInstanceTemplate(loc.GetMapId());
@@ -239,8 +249,14 @@
assert(mover != NULL); // there must always be a mover
Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL;
+ Vehicle *vehMover = mover->GetVehicleKit();
+ if (vehMover)
+ if (mover->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED))
+ if (Unit *charmer = mover->GetCharmer())
+ if (charmer->GetTypeId() == TYPEID_PLAYER)
+ plMover = (Player*)charmer;
// ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
if (plMover && plMover->IsBeingTeleported())
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
@@ -242,8 +258,11 @@
// ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
if (plMover && plMover->IsBeingTeleported())
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
+ // movement anticheat
+ plMover->m_anti_JustTeleported = 1;
+ // end movement anticheat
return;
}
@@ -277,7 +296,7 @@
{
// transports size limited
// (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
- if (movementInfo.t_x > 50 || movementInfo.t_y > 50 || movementInfo.t_z > 50)
+ if( movementInfo.t_x > 60 || movementInfo.t_y > 60 || movementInfo.t_x < -60 || movementInfo.t_y < -60 )
{
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
@@ -290,18 +309,31 @@
return;
}
- // if we boarded a transport, add us to it
- if (plMover && !plMover->GetTransport())
- {
- // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list
- for (MapManager::TransportSet::const_iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter)
- {
- if ((*iter)->GetGUID() == movementInfo.t_guid)
- {
- plMover->m_transport = (*iter);
- (*iter)->AddPassenger(plMover);
- break;
- }
- }
- }
+ if (plMover && plMover->m_anti_TransportGUID == 0 && (movementInfo.t_guid !=0))
+ {
+ // if we boarded a transport, add us to it
+ if (plMover && !plMover->GetTransport())
+ {
+ // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list
+ for (MapManager::TransportSet::const_iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter)
+ {
+ if ((*iter)->GetGUID() == movementInfo.t_guid)
+ {
+ plMover->m_transport = (*iter);
+ (*iter)->AddPassenger(plMover);
+ break;
+ }
+ }
+ }
+ }
+ //movement anticheat;
+ //Correct finding GO guid in DB (thanks to GriffonHeart)
+
+ if (plMover)
+ {
+ GameObject *obj = HashMapHolder<GameObject>::Find(movementInfo.t_guid);
+ if(obj)
+ plMover->m_anti_TransportGUID = obj->GetDBTableGUIDLow();
+ else
+ plMover->m_anti_TransportGUID = GUID_LOPART(movementInfo.t_guid);
@@ -307,4 +339,9 @@
- if (!mover->GetTransport() && !mover->GetVehicle())
+ }
+
+
+ // end movement anticheat
+
+ if ( (!plMover && !mover->GetTransport() && !mover->GetVehicle()) || (plMover && !plMover->GetTransport() && !plMover->GetVehicle()) )
movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT;
}
@@ -309,16 +346,20 @@
movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT;
}
- else if (plMover && plMover->GetTransport()) // if we were on a transport, leave
- {
- plMover->m_transport->RemovePassenger(plMover);
- plMover->m_transport = NULL;
- movementInfo.t_x = 0.0f;
- movementInfo.t_y = 0.0f;
- movementInfo.t_z = 0.0f;
- movementInfo.t_o = 0.0f;
- movementInfo.t_time = 0;
- movementInfo.t_seat = -1;
- }
+ else if (plMover && plMover->m_anti_TransportGUID != 0)
+ {
+ if (plMover && plMover->GetTransport()) // if we were on a transport, leave
+ {
+ plMover->m_transport->RemovePassenger(plMover);
+ plMover->m_transport = NULL;
+ }
+ movementInfo.t_x = 0.0f;
+ movementInfo.t_y = 0.0f;
+ movementInfo.t_z = 0.0f;
+ movementInfo.t_o = 0.0f;
+ movementInfo.t_time = 0;
+ movementInfo.t_seat = -1;
+ plMover->m_anti_TransportGUID = 0;
+ }
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
if (opcode == MSG_MOVE_FALL_LAND && plMover && !plMover->isInFlight())
@@ -322,4 +363,9 @@
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
if (opcode == MSG_MOVE_FALL_LAND && plMover && !plMover->isInFlight())
+ {
+ //movement anticheat
+ plMover->m_anti_JustJumped = 0;
+ plMover->m_anti_JumpBaseZ = 0;
+ //end movement anticheat
plMover->HandleFall(movementInfo);
@@ -325,4 +371,5 @@
plMover->HandleFall(movementInfo);
+ }
if (plMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plMover->IsInWater())
{
@@ -331,4 +378,22 @@
}
/*----------------------*/
+ //---- anti-cheat features -->>>
+ #define FROSTBROOD_VANQUISHER 28670
+ bool check_passed = true;
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG_FULL
+ if (plMover){
+ sLog.outBasic("JAH-%s > client-time:%d fall-time:%d | xyzo: %f,%f,%fo(%f) flags[%X] opcode[%s]| transport (xyzo): %f,%f,%fo(%f)",
+ plMover->GetName(),movementInfo.time,movementInfo.fallTime,movementInfo.x,movementInfo.y,movementInfo.z,movementInfo.o,
+ movementInfo.flags, LookupOpcodeName(opcode),movementInfo.t_x,movementInfo.t_y,movementInfo.t_z,movementInfo.t_o);
+ sLog.outBasic("JAH-%s Transport > server GUID: %d | client GUID: (lo)%d - (hi)%d",
+ plMover->GetName(),plMover->m_anti_TransportGUID, GUID_LOPART(movementInfo.t_guid), GUID_HIPART(movementInfo.t_guid));
+ } else {
+ sLog.outBasic("JAH > client-time:%d fall-time:%d | xyzo: %f,%f,%fo(%f) flags[%X] opcode[%s]| transport (xyzo): %f,%f,%fo(%f)",
+ movementInfo.time,movementInfo.fallTime,movementInfo.x,movementInfo.y,movementInfo.z,movementInfo.o,
+ movementInfo.flags, LookupOpcodeName(opcode),movementInfo.t_x,movementInfo.t_y,movementInfo.t_z,movementInfo.t_o);
+ sLog.outBasic("JAH Transport > server GUID: | client GUID: (lo)%d - (hi)%d",
+ GUID_LOPART(movementInfo.t_guid), GUID_HIPART(movementInfo.t_guid));
+ }
+ #endif
@@ -334,2 +399,338 @@
+ if ( plMover && World::GetEnableMvAnticheat() && !plMover->HasAuraType(SPELL_AURA_MOD_POSSESS) )
+ {
+ //calc time deltas
+ int32 cClientTimeDelta = 1500;
+ if (plMover->m_anti_LastClientTime !=0){
+ cClientTimeDelta = movementInfo.time - plMover->m_anti_LastClientTime;
+ plMover->m_anti_DeltaClientTime += cClientTimeDelta;
+ plMover->m_anti_LastClientTime = movementInfo.time;
+ } else {
+ plMover->m_anti_LastClientTime = movementInfo.time;
+ }
+
+ uint32 cServerTime=getMSTime();
+ uint32 cServerTimeDelta = 1500;
+ if (plMover->m_anti_LastServerTime != 0){
+ cServerTimeDelta = cServerTime - plMover->m_anti_LastServerTime;
+ plMover->m_anti_DeltaServerTime += cServerTimeDelta;
+ plMover->m_anti_LastServerTime = cServerTime;
+ } else {
+ plMover->m_anti_LastServerTime = cServerTime;
+ }
+
+ //resync times on client login (first 15 sec for heavy areas)
+ if (plMover->m_anti_DeltaServerTime < 15000 && plMover->m_anti_DeltaClientTime < 15000)
+ plMover->m_anti_DeltaClientTime = plMover->m_anti_DeltaServerTime;
+
+ int32 sync_time = plMover->m_anti_DeltaClientTime - plMover->m_anti_DeltaServerTime;
+
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG_FULL
+ sLog.outBasic("JAH-%s Time > cClientTimeDelta: %d, cServerTime: %d || deltaC: %d - deltaS: %d || SyncTime: %d",
+ plMover->GetName(),cClientTimeDelta, cServerTime,
+ plMover->m_anti_DeltaClientTime, plMover->m_anti_DeltaServerTime, sync_time);
+ #endif
+
+ //mistiming checks
+ int32 gmd = World::GetMistimingDelta();
+ if (sync_time > gmd || sync_time < -gmd){
+ cClientTimeDelta = cServerTimeDelta;
+ plMover->m_anti_MistimingCount++;
+
+ sLog.outError("JAH-%s, mistiming exception. #:%d, mistiming: %dms ",
+ plMover->GetName(), plMover->m_anti_MistimingCount, sync_time);
+
+ if (plMover->m_anti_MistimingCount > World::GetMistimingAlarms())
+ return;
+
+ check_passed = false;
+ if (vehMover)
+ vehMover->Dismiss();
+ }
+ // end mistiming checks
+
+
+ uint32 curDest = plMover->m_taxi.GetTaxiDestination(); //check taxi flight
+ if ( (plMover->m_anti_TransportGUID == 0) && !curDest )
+ {
+ UnitMoveType move_type;
+
+ // calculating section ---------------------
+ //current speed
+ if (movementInfo.flags & MOVEMENTFLAG_FLYING) move_type = movementInfo.flags & MOVEMENTFLAG_BACKWARD ? MOVE_FLIGHT_BACK : MOVE_FLIGHT;
+ else if (movementInfo.flags & MOVEMENTFLAG_SWIMMING) move_type = movementInfo.flags & MOVEMENTFLAG_BACKWARD ? MOVE_SWIM_BACK : MOVE_SWIM;
+ else if (movementInfo.flags & MOVEMENTFLAG_WALK_MODE) move_type = MOVE_WALK;
+ //hmm... in first time after login player has MOVE_SWIMBACK instead MOVE_WALKBACK
+ else move_type = movementInfo.flags & MOVEMENTFLAG_BACKWARD ? MOVE_SWIM_BACK : MOVE_RUN;
+
+ float current_speed = plMover->GetSpeed(move_type);
+
+ uint32 vehicleEntry = 0;
+
+ if ( plMover->GetVehicle() )
+ {
+ vehicleEntry = plMover->GetVehicleCreatureBase()->GetEntry();
+ current_speed = plMover->GetVehicleBase()->GetSpeed(move_type);
+ }
+ // end current speed
+
+ // movement distance
+ float allowed_delta= 0;
+
+ float delta_x = plMover->GetPositionX() - movementInfo.x;
+ float delta_y = plMover->GetPositionY() - movementInfo.y;
+ float delta_z = plMover->GetPositionZ() - movementInfo.z;
+ float real_delta = delta_x * delta_x + delta_y * delta_y;
+ float tg_z = -99999; //tangens
+ // end movement distance
+
+ if ( cClientTimeDelta < 0 ) {cClientTimeDelta = 0;}
+ float time_delta = (cClientTimeDelta < 1500) ? (float)cClientTimeDelta/1000 : 1.5f; //normalize time - 1.5 second allowed for heavy loaded server
+
+ if ( !(movementInfo.flags & (MOVEMENTFLAG_FLYING | MOVEMENTFLAG_SWIMMING)) )
+ tg_z = (real_delta !=0) ? (delta_z*delta_z / real_delta) : -99999;
+
+ if ( current_speed < plMover->m_anti_Last_HSpeed )
+ {
+ allowed_delta = plMover->m_anti_Last_HSpeed;
+ if (plMover->m_anti_LastSpeedChangeTime == 0 )
+ plMover->m_anti_LastSpeedChangeTime = movementInfo.time + (uint32)floor(((plMover->m_anti_Last_HSpeed / current_speed) * 1500)) + 100; //100ms above for random fluctuating =)))
+ } else {
+ allowed_delta = current_speed;
+ }
+
+ allowed_delta = allowed_delta * time_delta;
+ allowed_delta = allowed_delta * allowed_delta + 2;
+ if ( tg_z > 2.2 )
+ allowed_delta = allowed_delta + (delta_z*delta_z)/2.37; // mountain fall allowed speed
+
+ if ( movementInfo.time>plMover->m_anti_LastSpeedChangeTime )
+ {
+ plMover->m_anti_Last_HSpeed = current_speed; // store current speed
+ plMover->m_anti_Last_VSpeed = -2.3f;
+ if (plMover->m_anti_LastSpeedChangeTime != 0) plMover->m_anti_LastSpeedChangeTime = 0;
+ }
+
+ if ( plMover->GetVehicle() )
+ {
+ allowed_delta = allowed_delta*1.1;
+ }
+ // end calculating section ---------------------
+
+ //AntiGravitation
+ float JumpHeight = plMover->m_anti_JumpBaseZ - movementInfo.z;
+ if ( (plMover->m_anti_JumpBaseZ != 0 )
+ && !(movementInfo.flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLY_MODE | MOVEMENTFLAG_FLYING))
+ && (JumpHeight < plMover->m_anti_Last_VSpeed))
+ {
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("JAH-%s, GraviJump exception. JumpHeight = %f, Allowed Veritcal Speed = %f",
+ plMover->GetName(), JumpHeight, plMover->m_anti_Last_VSpeed);
+ #endif
+ check_passed = false;
+ if (vehMover)
+ vehMover->Dismiss();
+ }
+
+ //multi jump checks
+ if (opcode == MSG_MOVE_JUMP && !plMover->IsInWater())
+ {
+ if (plMover->m_anti_JustJumped >= 1){
+ check_passed = false; //don't process new jump packet
+ if (vehMover)
+ vehMover->Dismiss();
+ } else {
+ plMover->m_anti_JustJumped += 1;
+ plMover->m_anti_JumpBaseZ = movementInfo.z;
+ }
+ } else if (plMover->IsInWater()) {
+ plMover->m_anti_JustJumped = 0;
+ }
+
+ //speed hack checks
+ if ( (real_delta > allowed_delta) )
+ {
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("JAH-%s, speed exception | cDelta=%f aDelta=%f | cSpeed=%f lSpeed=%f deltaTime=%f",
+ plMover->GetName(), real_delta, allowed_delta, current_speed, plMover->m_anti_Last_HSpeed,time_delta);
+ #endif
+ check_passed = false;
+ if (vehMover)
+ vehMover->Dismiss();
+ }
+ //teleport hack checks
+ if ( (real_delta>4900.0f) && !(real_delta < allowed_delta) )
+ {
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("JAH-%s, is teleport exception | cDelta=%f aDelta=%f | cSpeed=%f lSpeed=%f deltaToime=%f",
+ plMover->GetName(),real_delta, allowed_delta, current_speed, plMover->m_anti_Last_HSpeed,time_delta);
+ #endif
+ check_passed = false;
+ if (vehMover)
+ vehMover->Dismiss();
+ }
+
+ //mountian hack checks // 1.56f (delta_z < GetPlayer()->m_anti_Last_VSpeed))
+ if ((delta_z < plMover->m_anti_Last_VSpeed) && (plMover->m_anti_JustJumped == 0) && (tg_z > 2.37f))
+ {
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("JAH-%s, mountain exception | tg_z=%f", plMover->GetName(),tg_z);
+ #endif
+ check_passed = false;
+ if (vehMover)
+ vehMover->Dismiss();
+ }
+ //Fly hack checks
+ if (((movementInfo.flags & (MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLY_MODE | MOVEMENTFLAG_FLYING)) != 0)
+ && !plMover->isGameMaster()
+ && !(movementInfo.flags & (MOVEMENTFLAG_SWIMMING)) // allow X button in water
+ && !(plMover->HasAuraType(SPELL_AURA_FLY) || plMover->HasAuraType(SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED)
+ || plMover->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || plMover->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED)
+ || plMover->HasAuraType(SPELL_AURA_MOD_MOUNTED_FLIGHT_SPEED_ALWAYS) || plMover->HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK) || ( plMover->GetVehicle() && vehicleEntry == FROSTBROOD_VANQUISHER )) )
+ {
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("JAH-%s, flight exception. {SPELL_AURA_FLY=[%X]} {SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED=[%X]} {SPELL_AURA_MOD_SPEED_FLIGHT=[%X]} {SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS=[%X]} {SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK=[%X]}",
+ plMover->GetName(),
+ plMover->HasAuraType(SPELL_AURA_FLY), plMover->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED),
+ plMover->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED), plMover->HasAuraType(SPELL_AURA_MOD_MOUNTED_FLIGHT_SPEED_ALWAYS),
+ plMover->HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK));
+ #endif
+ check_passed = false;
+ if (vehMover)
+ vehMover->Dismiss();
+ }
+ //Water-Walk checks
+ if (((movementInfo.flags & MOVEMENTFLAG_WATERWALKING) != 0)
+ && !plMover->isGameMaster()
+ && !(plMover->HasAuraType(SPELL_AURA_WATER_WALK) | plMover->HasAuraType(SPELL_AURA_GHOST)))
+ {
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("JAH-%s, water-walk exception. [%X]{SPELL_AURA_WATER_WALK=[%X]}",
+ plMover->GetName(), movementInfo.flags, plMover->HasAuraType(SPELL_AURA_WATER_WALK));
+ #endif
+ check_passed = false;
+ if (vehMover)
+ vehMover->Dismiss();
+ }
+ //Teleport To Plane checks
+ if (movementInfo.z < 0.0001f && movementInfo.z > -0.0001f
+ && ((movementInfo.flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLY_MODE | MOVEMENTFLAG_FLYING)) == 0)
+ && !plMover->isGameMaster())
+ {
+ // Prevent using TeleportToPlan.
+ Map *map = plMover->GetMap();
+ if (map){
+ float plane_z = map->GetHeight(movementInfo.x, movementInfo.y, MAX_HEIGHT) - movementInfo.z;
+ plane_z = (plane_z < -500.0f) ? 0 : plane_z; //check holes in heigth map
+ if(plane_z > 0.1f || plane_z < -0.1f)
+ {
+ plMover->m_anti_TeleToPlane_Count++;
+ check_passed = false;
+ if (vehMover)
+ vehMover->Dismiss();
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outDebug("JAH-%s, teleport to plan exception. plane_z: %f ",
+ plMover->GetName(), plane_z);
+ #endif
+ if (plMover->m_anti_TeleToPlane_Count > World::GetTeleportToPlaneAlarms())
+ {
+ sLog.outError("JAH-%s, teleport to plan exception. Exception count: %d ",
+ plMover->GetName(), plMover->m_anti_TeleToPlane_Count);
+ return;
+ }
+ }
+ }
+ } else {
+ if (plMover->m_anti_TeleToPlane_Count != 0)
+ plMover->m_anti_TeleToPlane_Count = 0;
+ }
+ } else if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) {
+ //antiwrap checks
+ if ( plMover->GetTransport() )
+ {
+ float trans_rad = movementInfo.t_x*movementInfo.t_x + movementInfo.t_y*movementInfo.t_y + movementInfo.t_z*movementInfo.t_z;
+ if (trans_rad > 3600.0f){
+ check_passed = false;
+ if (vehMover)
+ vehMover->Dismiss();
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("JAH-%s, leave transport.", plMover->GetName());
+ #endif
+ }
+ } else {
+ if (GameObjectData const* go_data = objmgr.GetGOData(plMover->m_anti_TransportGUID))
+ {
+ float delta_gox = go_data->posX - movementInfo.x;
+ float delta_goy = go_data->posY - movementInfo.y;
+ float delta_goz = go_data->posZ - movementInfo.z;
+ int mapid = go_data->mapid;
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("JAH-%s, transport movement. GO xyzo: %f,%f,%f",
+ plMover->GetName(), go_data->posX,go_data->posY,go_data->posZ);
+ #endif
+ if (plMover->GetMapId() != mapid){
+ check_passed = false;
+ if (vehMover)
+ vehMover->Dismiss();
+ } else if (mapid !=369) {
+ float delta_go = delta_gox*delta_gox + delta_goy*delta_goy;
+ if (delta_go > 3600.0f) {
+ check_passed = false;
+ if (vehMover)
+ vehMover->Dismiss();
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("JAH-%s, leave transport. GO xyzo: %f,%f,%f",
+ plMover->GetName(), go_data->posX,go_data->posY,go_data->posZ);
+ #endif
+ }
+ }
+
+ } else if ( plMover->GetVehicle() )
+ {
+ if ( !plMover->GetVehicle()->GetVehicleInfo() )
+ {
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("JAH-%s, undefined vehicle.", plMover->GetName());
+ #endif
+ check_passed = false;
+ if (vehMover)
+ vehMover->Dismiss();
+ }
+
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("JAH-%s on vehicle %u", plMover->GetName(), plMover->GetVehicleCreatureBase()->GetEntry() );
+ #endif
+ }
+ else
+ {
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("JAH-%s, undefined transport.", plMover->GetName());
+ #endif
+ check_passed = false;
+ if (vehMover)
+ vehMover->Dismiss();
+ }
+ }
+ if (!check_passed){
+ if ( plMover->GetTransport() && !plMover->GetVehicle() )
+ {
+ plMover->m_transport->RemovePassenger(plMover);
+ plMover->m_transport = NULL;
+ plMover->m_anti_TransportGUID = 0;
+ }
+ else if ( plMover->GetVehicle() && !plMover->GetVehicle()->GetVehicleInfo() )
+ {
+ plMover->m_transport->RemovePassenger(plMover);
+ plMover->m_transport = NULL;
+ plMover->GetVehicle()->Dismiss();
+ plMover->m_anti_TransportGUID = 0;
+ }
+ movementInfo.t_x = 0.0f;
+ movementInfo.t_y = 0.0f;
+ movementInfo.t_z = 0.0f;
+ movementInfo.t_o = 0.0f;
+ movementInfo.t_time = 0;
+ }
+ }
+ }
/* process position-change */
@@ -335,4 +736,6 @@
/* process position-change */
+ if (check_passed)
+ {
WorldPacket data(opcode, recv_data.size());
movementInfo.time = getMSTime();
movementInfo.guid = mover->GetGUID();
@@ -348,7 +751,7 @@
return;
}
- if (plMover) // nothing is charmed, or player charmed
+ if (plMover && !vehMover) // nothing is charmed, or player charmed
{
plMover->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
plMover->UpdateFallInformationIfNeed(movementInfo, opcode);
@@ -383,8 +786,14 @@
plMover->RepopAtGraveyard();
}
}
+ //movement anticheat >>>
+ if (plMover->m_anti_AlarmCount > 0){
+ sLog.outError("JAH-%s produce %d anticheat alarms",plMover->GetName(),plMover->m_anti_AlarmCount);
+ plMover->m_anti_AlarmCount = 0;
+ }
+ // end movement anticheat
}
else // creature charmed
{
mover->GetMap()->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
@@ -386,14 +795,16 @@
}
else // creature charmed
{
mover->GetMap()->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
- /*if(mover->canFly())
- {
- bool flying = mover->IsFlying();
- if(flying != ((mover->GetByteValue(UNIT_FIELD_BYTES_1, 3) & 0x02) ? true : false))
- mover->SetFlying(flying);
- }*/
+ }
+ } else if (plMover) {
+ plMover->m_anti_AlarmCount++;
+ WorldPacket data;
+ plMover->SetUnitMovementFlags(0);
+ plMover->SendTeleportAckMsg();
+ plMover->BuildHeartBeatMsg(&data);
+ plMover->SendMessageToSet(&data, true);
}
//sLog.outString("Receive Movement Packet %s:", opcodeTable[recv_data.GetOpcode()]);
@@ -475,7 +886,6 @@
{
sLog.outBasic("Player %s from account id %u kicked for incorrect speed (must be %f instead %f)",
_player->GetName(),_player->GetSession()->GetAccountId(),_player->GetSpeed(move_type), newspeed);
- _player->GetSession()->KickPlayer();
}
}
}
@@ -487,9 +897,7 @@
uint64 guid;
recv_data >> guid;
- if(guid == GetPlayer()->m_mover->GetGUID())
- return;
-
+ if(GetPlayer()->IsInWorld())
if(Unit *mover = ObjectAccessor::GetUnit(*GetPlayer(), guid))
{
GetPlayer()->SetMover(mover);
@@ -625,6 +1033,18 @@
MovementInfo movementInfo;
ReadMovementInfo(recv_data, &movementInfo);
+ _player->m_movementInfo.flags = movementInfo.GetMovementFlags();
+
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outBasic("%s CMSG_MOVE_KNOCK_BACK_ACK: tm:%d ftm:%d | %f,%f,%fo(%f) [%X]",GetPlayer()->GetName(),movementInfo.time,movementInfo.fallTime,movementInfo.x,movementInfo.y,movementInfo.z,movementInfo.o,movementInfo.flags);
+ sLog.outBasic("%s CMSG_MOVE_KNOCK_BACK_ACK additional: vspeed:%f, hspeed:%f",GetPlayer()->GetName(), movementInfo.j_zspeed, movementInfo.j_xyspeed);
+ #endif
+
+ _player->m_movementInfo = movementInfo;
+ _player->m_anti_Last_HSpeed = movementInfo.j_xyspeed;
+ _player->m_anti_Last_VSpeed = movementInfo.j_zspeed < 3.2f ? movementInfo.j_zspeed - 1.0f : 3.2f;
+ uint32 dt = (_player->m_anti_Last_VSpeed < 0) ? (int)(ceil(_player->m_anti_Last_VSpeed/-25)*1000) : (int)(ceil(_player->m_anti_Last_VSpeed/25)*1000);
+ _player->m_anti_LastSpeedChangeTime = movementInfo.time + dt + 1000;
}
void WorldSession::HandleMoveHoverAck( WorldPacket& recv_data )
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -5268,6 +5268,11 @@
}
}
+ //movement anticheat fix
+ if (dist > 3600)
+ id = 0;
+ //movement anticheat fix
+
return id;
}
@@ -8959,4 +8964,4 @@
sLog.outString();
sLog.outString( ">> Loaded %u creature base stats.", counter);
-}
+}
\ No newline at end of file
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -412,6 +412,31 @@
rest_type=REST_TYPE_NO;
////////////////////Rest System/////////////////////
+ //movement anticheat
+ m_anti_LastClientTime = 0; //last movement client time
+ m_anti_LastServerTime = 0; //last movement server time
+ m_anti_DeltaClientTime = 0; //client side session time
+ m_anti_DeltaServerTime = 0; //server side session time
+ m_anti_MistimingCount = 0; //mistiming counts before kick
+
+ m_anti_LastSpeedChangeTime = 0; //last speed change time
+ m_anti_BeginFallTime = 0; //alternative falling begin time (obsolete)
+
+ m_anti_Last_HSpeed = 7.0f; //horizontal speed, default RUN speed
+ m_anti_Last_VSpeed = -2.3f; //vertical speed, default max jump height
+
+ m_anti_TransportGUID = 0; //current transport GUID
+
+ m_anti_JustTeleported = 0; //seted when player was teleported
+ m_anti_TeleToPlane_Count = 0; //Teleport To Plane alarm counter
+
+ m_anti_AlarmCount = 0; //alarm counter
+
+ m_anti_JustJumped = 0; //Jump already began, anti air jump check
+ m_anti_JumpBaseZ = 0; //Z coord before jump (AntiGrav)
+ // << movement anticheat
+ /////////////////////////////////
+
m_mailsLoaded = false;
m_mailsUpdated = false;
unReadMails = 0;
@@ -1676,6 +1701,10 @@
return false;
}
+ //movement anticheat
+ m_anti_JustTeleported = 1;
+ //end movement anticheat
+
// preparing unsummon pet if lost (we must get pet before teleportation or will not find it later)
Pet* pet = GetPet();
@@ -1730,6 +1759,7 @@
if (GetMapId() == mapid && !m_transport)
{
+ m_anti_JumpBaseZ = 0;
//lets reset far teleport flag if it wasn't reset during chained teleports
SetSemaphoreTeleportFar(false);
//setup delayed teleport flag
@@ -1880,6 +1910,7 @@
m_teleport_dest = WorldLocation(mapid, final_x, final_y, final_z, final_o);
SetFallInformation(0, final_z);
+ m_anti_JumpBaseZ = 0;
// if the player is saved before worldportack (at logout for example)
// this will be used instead of the current location in SaveToDB
diff --git a/src/game/Player.h b/src/game/Player.h
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -2482,6 +2482,31 @@
float m_rest_bonus;
RestType rest_type;
////////////////////Rest System/////////////////////
+
+ //movement anticheat
+ uint32 m_anti_LastClientTime; //last movement client time
+ uint32 m_anti_LastServerTime; //last movement server time
+ uint32 m_anti_DeltaClientTime; //client side session time
+ uint32 m_anti_DeltaServerTime; //server side session time
+ uint32 m_anti_MistimingCount; //mistiming counts before kick
+
+ uint32 m_anti_LastSpeedChangeTime;//last speed change time
+ uint32 m_anti_BeginFallTime; //alternative falling begin time (obsolete)
+
+ float m_anti_Last_HSpeed; //horizontal speed, default RUN speed
+ float m_anti_Last_VSpeed; //vertical speed, default max jump height
+
+ uint64 m_anti_TransportGUID; //current transport GUID
+
+ uint32 m_anti_JustTeleported; //seted when player was teleported
+ uint32 m_anti_TeleToPlane_Count; //Teleport To Plane alarm counter
+
+ uint64 m_anti_AlarmCount; //alarm counter
+
+ uint32 m_anti_JustJumped; //Jump already began, anti air jump check
+ float m_anti_JumpBaseZ; //Z coord before jump
+ // << movement anticheat
+
uint32 m_resetTalentsCost;
time_t m_resetTalentsTime;
uint32 m_usedTalentCount;
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -6748,7 +6748,10 @@
float x, y, z;
target->GetContactPoint(m_caster, x, y, z);
- m_caster->GetMotionMaster()->MoveCharge(x, y, z);
+ if (m_caster->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)m_caster)->SetPosition(x, y, z, m_caster->GetOrientation());
+ else
+ m_caster->GetMotionMaster()->MoveCharge(x, y, z);
// not all charge effects used in negative spells
if ( !IsPositiveSpell(m_spellInfo->Id) && m_caster->GetTypeId() == TYPEID_PLAYER)
diff --git a/src/game/World.cpp b/src/game/World.cpp
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -88,6 +88,12 @@
int32 World::m_visibility_notify_periodInInstances = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
int32 World::m_visibility_notify_periodInBGArenas = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
+//movement anticheat
+bool World::m_EnableMvAnticheat = true;
+uint32 World::m_TeleportToPlaneAlarms = 50;
+uint32 World::m_MistimingAlarms = 20;
+uint32 World::m_MistimingDelta = 2000;
+
/// World constructor
World::World()
{
@@ -592,6 +598,37 @@
sLog.outError("DurabilityLossChance.Block (%f) must be >=0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_BLOCK]);
rate_values[RATE_DURABILITY_LOSS_BLOCK] = 0.0f;
}
+
+ // movement anticheat
+ m_EnableMvAnticheat = sConfig.GetBoolDefault("Anticheat.Movement.Enable",true);
+ m_TeleportToPlaneAlarms = sConfig.GetIntDefault("Anticheat.Movement.TeleportToPlaneAlarms", 50);
+ if (m_TeleportToPlaneAlarms<20){
+ sLog.outError("Anticheat.Movement.TeleportToPlaneAlarms (%d) must be >=20. Using 20 instead.",m_TeleportToPlaneAlarms);
+ m_TeleportToPlaneAlarms = 20;
+ }
+ if (m_TeleportToPlaneAlarms>100){
+ sLog.outError("Anticheat.Movement.TeleportToPlaneAlarms (%d) must be <=100. Using 100 instead.",m_TeleportToPlaneAlarms);
+ m_TeleportToPlaneAlarms = 100;
+ }
+ m_MistimingDelta = sConfig.GetIntDefault("Anticheat.Movement.MistimingDelta",10000);
+ if (m_MistimingDelta<1000){
+ sLog.outError("Anticheat.Movement.m_MistimingDelta (%d) must be >=1000ms. Using 1000 instead.",m_TeleportToPlaneAlarms);
+ m_MistimingDelta = 1000;
+ }
+ if (m_MistimingDelta>15000){
+ sLog.outError("Anticheat.Movement.m_MistimingDelta (%d) must be <=15000ms. Using 15000 instead.",m_TeleportToPlaneAlarms);
+ m_MistimingDelta = 15000;
+ }
+ m_MistimingAlarms = sConfig.GetIntDefault("Anticheat.Movement.MistimingAlarms",20);
+ if (m_MistimingAlarms<10) {
+ sLog.outError("Anticheat.Movement.MistimingAlarms (%d) must be >=20. Using 10 instead.",m_TeleportToPlaneAlarms);
+ m_MistimingAlarms = 10;
+ }
+ if (m_MistimingAlarms>50){
+ sLog.outError("Anticheat.Movement.m_MistimingAlarms (%d) must be <=50. Using 50 instead.",m_TeleportToPlaneAlarms);
+ m_MistimingAlarms = 50;
+ }
+
///- Read other configuration items from the config file
m_configs[CONFIG_DURABILITY_LOSS_IN_PVP] = sConfig.GetBoolDefault("DurabilityLoss.InPvP", false);
diff --git a/src/game/World.h b/src/game/World.h
--- a/src/game/World.h
+++ b/src/game/World.h
@@ -631,6 +631,13 @@
uint32 m_WintergrapsTimer;
uint32 m_WintergrapsState;
+ //movement anticheat
+ static bool GetEnableMvAnticheat() {return m_EnableMvAnticheat;}
+ static uint32 GetTeleportToPlaneAlarms() {return m_TeleportToPlaneAlarms;}
+ static uint32 GetMistimingDelta() {return m_MistimingDelta;}
+ static uint32 GetMistimingAlarms() {return m_MistimingAlarms;}
+ //<<< end movement anticheat
+
void ProcessCliCommands();
void QueueCliCommand( CliCommandHolder::Print* zprintf, char const* input ) { cliCmdQueue.add(new CliCommandHolder(input, zprintf)); }
@@ -732,6 +739,12 @@
static int32 m_visibility_notify_periodInInstances;
static int32 m_visibility_notify_periodInBGArenas;
+ //movement anticheat enable flag
+ static bool m_EnableMvAnticheat;
+ static uint32 m_TeleportToPlaneAlarms;
+ static uint32 m_MistimingDelta;
+ static uint32 m_MistimingAlarms;
+
// CLI command holder to be thread safe
ACE_Based::LockedQueue<CliCommandHolder*,ACE_Thread_Mutex> cliCmdQueue;
SqlResultQueue *m_resultQueue;
diff --git a/src/trinitycore/trinitycore.conf.dist b/src/trinitycore/trinitycore.conf.dist
--- a/src/trinitycore/trinitycore.conf.dist
+++ b/src/trinitycore/trinitycore.conf.dist
@@ -2024,6 +2024,30 @@
Ra.Secure = 1
###############################################################################
+# MOVEMENT ANTICHEAT
+#
+# Anticheat.Movement.Enable
+# Enable Movement Anticheat
+# Default: 0 - off
+# 1 - on
+#
+# Anticheat.Movement.TeleportToPlaneAlarms
+# maximum alarms before player will be kicked (default 50, allowed 20 - 100)
+#
+# Anticheat.Movement.MistimingDelta
+# mistiming intelval between client and serverside (default 10000 ms, allowed 1000 - 15000 ms)
+#
+# Anticheat.Movement.MistimingAlarms
+# mistiming alarms before player will be kicked (default 20, allowed 10 - 50)
+#
+###############################################################################
+
+Anticheat.Movement.Enable = 1
+Anticheat.Movement.TeleportToPlaneAlarms = 50
+Anticheat.Movement.MistimingDelta = 10000
+Anticheat.Movement.MistimingAlarms = 20
+
+###############################################################################
# CUSTOM SERVER OPTIONS
#
# PlayerStart.AllReputation