aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Player/Player.cpp41
-rw-r--r--src/server/game/Entities/Player/Player.h3
-rw-r--r--src/server/game/World/World.cpp3
-rw-r--r--src/server/game/World/World.h1
-rw-r--r--src/server/worldserver/worldserver.conf.dist10
5 files changed, 53 insertions, 5 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index e2038e91e89..92c9ac89e60 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -501,7 +501,7 @@ Player::Player(WorldSession* session): Unit(true)
m_runes = nullptr;
- m_lastFallTime = 0;
+ m_lastFallTimeClient = 0;
m_lastFallZ = 0;
m_grantableLevels = 0;
@@ -1512,7 +1512,6 @@ void Player::Update(uint32 p_time)
//because we don't want player's ghost teleported from graveyard
if (IsHasDelayedTeleport() && IsAlive())
TeleportTo(m_teleport_dest, m_teleport_options);
-
}
void Player::setDeathState(DeathState s)
@@ -24852,7 +24851,25 @@ InventoryResult Player::CanEquipUniqueItem(ItemTemplate const* itemProto, uint8
void Player::SetFallInformation(uint32 time, float z)
{
- m_lastFallTime = time;
+ if (time < m_lastFallTimeClient)
+ m_fallStartTimeServer = GameTime::GetGameTimeMS() - time;
+ else if (m_fallStartTimeServer && time < std::max<uint32>(GameTime::GetGameTimeMS() - m_fallStartTimeServer, 2500) - 2500)
+ {
+ TC_LOG_WARN("cheat", "Player %s found to be delaying their falling movement.", GetName().c_str());
+ switch (sWorld->getIntConfig(CONFIG_ANTICHEAT_FALL_PUNISHMENT))
+ {
+ case 1: // kill
+ EnvironmentalDamage(DAMAGE_FALL, GetMaxHealth());
+ if (!isDead())
+ Kill(this, false);
+ break;
+ case 2: // disconnect
+ GetSession()->KickPlayer();
+ break;
+ }
+ }
+
+ m_lastFallTimeClient = time;
m_lastFallZ = z;
}
@@ -24860,6 +24877,22 @@ void Player::HandleFall(MovementInfo const& movementInfo)
{
// calculate total z distance of the fall
float z_diff = m_lastFallZ - movementInfo.pos.GetPositionZ();
+ if (m_fallStartTimeServer && movementInfo.fallTime < std::max<uint32>(GameTime::GetGameTimeMS() - m_fallStartTimeServer, 2500) - 2500)
+ {
+ TC_LOG_WARN("cheat", "Player %s found to be delaying their falling movement.", GetName().c_str());
+ switch (sWorld->getIntConfig(CONFIG_ANTICHEAT_FALL_PUNISHMENT))
+ {
+ case 1: // kill
+ z_diff = MAX_HEIGHT;
+ break;
+ case 2: // disconnect
+ GetSession()->KickPlayer();
+ break;
+ default:
+ break;
+ }
+ }
+ m_fallStartTimeServer = 0;
//TC_LOG_DEBUG("zDiff = %f", z_diff);
//Players with low fall distance, Feather Fall or physical immunity (charges used) are ignored
@@ -25189,7 +25222,7 @@ void Player::AddKnownCurrency(uint32 itemId)
void Player::UpdateFallInformationIfNeed(MovementInfo const& minfo, uint16 opcode)
{
- if (m_lastFallTime >= minfo.fallTime || m_lastFallZ <= minfo.pos.GetPositionZ() || opcode == MSG_MOVE_FALL_LAND)
+ if (m_lastFallTimeClient >= minfo.fallTime || m_lastFallZ <= minfo.pos.GetPositionZ() || opcode == MSG_MOVE_FALL_LAND)
SetFallInformation(minfo.fallTime, minfo.pos.GetPositionZ());
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 99e5f37ee7b..fb72eb6af00 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2586,7 +2586,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
MapReference m_mapRef;
- uint32 m_lastFallTime;
+ uint32 m_lastFallTimeClient;
+ uint32 m_fallStartTimeServer;
float m_lastFallZ;
int32 m_MirrorTimer[MAX_TIMERS];
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 2f09d03893f..d8f5923873a 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1349,6 +1349,9 @@ void World::LoadConfigSettings(bool reload)
// Whether to use LoS from game objects
m_bool_configs[CONFIG_CHECK_GOBJECT_LOS] = sConfigMgr->GetBoolDefault("CheckGameObjectLoS", true);
+ // What happens with cheaters that delay their fall
+ m_int_configs[CONFIG_ANTICHEAT_FALL_PUNISHMENT] = sConfigMgr->GetIntDefault("Anticheat.FallDelayed", 1); // 1 - kill
+
// call ScriptMgr if we're reloading the configuration
if (reload)
sScriptMgr->OnConfigLoad(reload);
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index cdf3703a67a..01c2275fade 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -390,6 +390,7 @@ enum WorldIntConfigs
CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE,
CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT,
CONFIG_RESPAWN_GUIDWARNING_FREQUENCY,
+ CONFIG_ANTICHEAT_FALL_PUNISHMENT,
INT_CONFIG_VALUE_COUNT
};
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 83dd87a487e..ff09c324df1 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -1248,6 +1248,16 @@ BirthdayTime = 1222964635
CacheDataQueries = 1
#
+# Anticheat.FallDelayed
+# Description: Decides what happens with players who show invalid fall behavior.
+# Can produce false positives in high latency situations.
+# 2 - (Force disconnect from server)
+# Default: 1 - (Kill player using fall damage)
+# 0 - (Only log to console)
+
+Anticheat.FallDelayed = 1
+
+#
###################################################################################################
###################################################################################################