aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities
diff options
context:
space:
mode:
authorChaouki Dhib <chaodhib@gmail.com>2021-05-16 13:16:08 +0200
committerGitHub <noreply@github.com>2021-05-16 13:16:08 +0200
commit2d114ea560cd8716af2b0d12990fc3480ecaf2b7 (patch)
treeaaa711aa4d63e9b33d8e804d481425368ddcee18 /src/server/game/Entities
parentedcaac6c959e944dc6d6dc224666b832521412b4 (diff)
Core/Movement: Improve client control logic (#26348)
Diffstat (limited to 'src/server/game/Entities')
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.cpp18
-rw-r--r--src/server/game/Entities/Player/Player.h4
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp71
-rw-r--r--src/server/game/Entities/Unit/Unit.h24
5 files changed, 58 insertions, 61 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index d318a941784..4da1b249b64 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -2652,7 +2652,7 @@ void Creature::InitializeMovementFlags()
void Creature::UpdateMovementFlags()
{
// Do not update movement flags if creature is controlled by a player (charm/vehicle)
- if (m_playerMovingMe)
+ if (IsMovedByClient())
return;
// Creatures with CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE should control MovementFlags in your own scripts
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 21410f84f12..bbf68c2a1f9 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -41,6 +41,7 @@
#include "DatabaseEnv.h"
#include "DisableMgr.h"
#include "Formulas.h"
+#include "GameClient.h"
#include "GameEventMgr.h"
#include "GameObjectAI.h"
#include "GameTime.h"
@@ -307,9 +308,6 @@ Player::Player(WorldSession* session): Unit(true)
m_resetTalentsTime = 0;
m_itemUpdateQueueBlocked = false;
- for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
- m_forced_speed_changes[i] = 0;
-
/////////////////// Instance System /////////////////////
m_HomebindTimer = 0;
@@ -354,8 +352,6 @@ Player::Player(WorldSession* session): Unit(true)
// Player summoning
m_summon_expire = 0;
- m_unitMovedByMe = this;
- m_playerMovingMe = this;
m_seer = this;
m_homebindMapId = 0;
@@ -1351,7 +1347,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)
@@ -22352,7 +22347,7 @@ bool Player::IsNeverVisible() const
bool Player::CanAlwaysSee(WorldObject const* obj) const
{
// Always can see self
- if (GetUnitBeingMoved() == obj)
+ if (GetCharmedOrSelf() == obj)
return true;
if (ObjectGuid guid = GetGuidValue(PLAYER_FARSIGHT))
@@ -22727,7 +22722,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
/// SMSG_RESYNC_RUNES
ResyncRunes();
- SetMovedUnit(this);
+ GetSession()->GetGameClient()->AddAllowedMover(this);
}
void Player::SendInitialPacketsAfterAddToMap()
@@ -24045,7 +24040,7 @@ void Player::SetClientControl(Unit* target, bool allowMove)
SetViewpoint(target, true);
}
- SetMovedUnit(target);
+ GetGameClient()->SetMovedUnit(target, allowMove);
}
void Player::UpdateZoneDependentAuras(uint32 newZone)
@@ -26969,3 +26964,8 @@ std::string Player::GetDebugInfo() const
sstr << Unit::GetDebugInfo();
return sstr.str();
}
+
+GameClient* Player::GetGameClient() const
+{
+ return GetSession()->GetGameClient();
+}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index d8ae36a54d2..7a0aef3c5c5 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -61,6 +61,7 @@ class Channel;
class CharacterCreateInfo;
class Creature;
class DynamicObject;
+class GameClient;
class Group;
class Guild;
class Item;
@@ -1653,6 +1654,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void RemovedInsignia(Player* looterPlr);
WorldSession* GetSession() const { return m_session; }
+ GameClient* GetGameClient() const;
void BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const override;
void DestroyForPlayer(Player* target, bool onDeath = false) const override;
@@ -2017,8 +2019,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
template<class T>
void UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& visibleNow);
- uint8 m_forced_speed_changes[MAX_MOVE_TYPE];
-
bool HasAtLoginFlag(AtLoginFlags f) const { return (m_atLoginFlags & f) != 0; }
void SetAtLoginFlag(AtLoginFlags f) { m_atLoginFlags |= f; }
void RemoveAtLoginFlag(AtLoginFlags flags, bool persist = false);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 0bb20566b21..888457c7cbc 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -33,6 +33,7 @@
#include "CreatureAIImpl.h"
#include "CreatureGroups.h"
#include "Formulas.h"
+#include "GameClient.h"
#include "GameObjectAI.h"
#include "GameTime.h"
#include "GridNotifiersImpl.h"
@@ -295,7 +296,7 @@ bool DispelableAura::RollDispel() const
Unit::Unit(bool isWorldObject) :
WorldObject(isWorldObject), m_lastSanctuaryTime(0), LastCharmerGUID(), movespline(new Movement::MoveSpline()),
m_ControlledByPlayer(false), m_AutoRepeatFirstCast(false), m_procDeep(0), m_transformSpell(0),
- m_removedAurasCount(0), m_unitMovedByMe(nullptr), m_playerMovingMe(nullptr), m_charmer(nullptr), m_charmed(nullptr),
+ m_removedAurasCount(0), m_charmer(nullptr), m_charmed(nullptr),
i_motionMaster(new MotionMaster(this)), m_regenTimer(0), m_vehicle(nullptr), m_vehicleKit(nullptr),
m_unitTypeMask(UNIT_MASK_NONE), m_Diminishing(), m_combatManager(this), m_threatManager(this),
m_aiLocked(false), m_comboTarget(nullptr), m_comboPoints(0), m_spellHistory(new SpellHistory(this))
@@ -367,7 +368,11 @@ Unit::Unit(bool isWorldObject) :
for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
m_speed_rate[i] = 1.0f;
+ for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
+ m_forced_speed_changes[i] = 0;
+
m_charmInfo = nullptr;
+ _gameClientMovingMe = nullptr;
// remove aurastates allowing special moves
for (uint8 i = 0; i < MAX_REACTIVE; ++i)
@@ -417,8 +422,6 @@ Unit::~Unit()
ASSERT(m_removedAuras.empty());
ASSERT(m_gameObj.empty());
ASSERT(m_dynObj.empty());
- ASSERT(!m_unitMovedByMe || (m_unitMovedByMe == this));
- ASSERT(!m_playerMovingMe || (m_playerMovingMe == this));
}
void Unit::Update(uint32 p_time)
@@ -5496,7 +5499,7 @@ Unit* Unit::getAttackerForHelper() const // If someone wants to
return nullptr;
if (Unit* victim = GetVictim())
- if ((!IsPet() && !GetPlayerMovingMe()) || IsInCombatWith(victim))
+ if ((!IsPet() && !IsCharmerOrSelfPlayer()) || IsInCombatWith(victim))
return victim;
CombatManager const& mgr = GetCombatManager();
@@ -6270,6 +6273,14 @@ bool Unit::isPossessing() const
return false;
}
+Unit* Unit::GetCharmerOrSelf() const
+{
+ if (IsCharmed())
+ return GetCharmer();
+ else
+ return const_cast<Unit*>(this);
+}
+
Unit* Unit::GetNextRandomRaidMemberOrPet(float radius)
{
Player* player = nullptr;
@@ -8627,15 +8638,17 @@ void Unit::SetSpeedRate(UnitMoveType mtype, float rate)
{
// register forced speed changes for WorldSession::HandleForceSpeedChangeAck
// and do it only for real sent packets and use run for run/mounted as client expected
- ++ToPlayer()->m_forced_speed_changes[mtype];
+ ++m_forced_speed_changes[mtype];
if (!IsInCombat())
if (Pet* pet = ToPlayer()->GetPet())
pet->SetSpeedRate(mtype, m_speed_rate[mtype]);
}
- if (Player* playerMover = Unit::ToPlayer(GetUnitBeingMoved())) // unit controlled by a player.
+ if (IsMovedByClient()) // unit controlled by a player.
{
+ Player* playerMover = GetGameClientMovingMe()->GetBasePlayer();
+
// Send notification to self. this packet is only sent to one client (the client of the player concerned by the change).
WorldPacket self;
self.Initialize(moveTypeToOpcode[mtype][1], mtype != MOVE_RUN ? 8 + 4 + 4 : 8 + 4 + 1 + 4);
@@ -9933,13 +9946,6 @@ void CharmInfo::SetSpellAutocast(SpellInfo const* spellInfo, bool state)
}
}
-void Unit::SetMovedUnit(Unit* target)
-{
- m_unitMovedByMe->m_playerMovingMe = nullptr;
- m_unitMovedByMe = ASSERT_NOTNULL(target);
- m_unitMovedByMe->m_playerMovingMe = ASSERT_NOTNULL(ToPlayer());
-}
-
uint32 createProcHitMask(SpellNonMeleeDamage* damageInfo, SpellMissInfo missCondition)
{
uint32 hitMask = PROC_HIT_NONE;
@@ -10446,7 +10452,7 @@ void Unit::SendComboPoints()
data << uint8(m_comboPoints);
playerMe->SendDirectMessage(&data);
}
- Player* movingMe = GetPlayerMovingMe();
+ Player* movingMe = GetCharmerOrSelfPlayer();
ObjectGuid ownerGuid = GetCharmerOrOwnerGUID();
Player* owner = nullptr;
if (ownerGuid.IsPlayer())
@@ -11435,11 +11441,8 @@ void Unit::SetFeared(bool apply)
}
// block / allow control to real player in control (eg charmer)
- if (GetTypeId() == TYPEID_PLAYER)
- {
- if (m_playerMovingMe)
- m_playerMovingMe->SetClientControl(this, !apply);
- }
+ if (GetCharmerOrSelfPlayer())
+ GetCharmerOrSelfPlayer()->SetClientControl(this, !apply);
}
void Unit::SetConfused(bool apply)
@@ -11460,11 +11463,8 @@ void Unit::SetConfused(bool apply)
}
// block / allow control to real player in control (eg charmer)
- if (GetTypeId() == TYPEID_PLAYER)
- {
- if (m_playerMovingMe)
- m_playerMovingMe->SetClientControl(this, !apply);
- }
+ if (GetCharmerOrSelfPlayer())
+ GetCharmerOrSelfPlayer()->SetClientControl(this, !apply);
}
bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* aurApp)
@@ -12163,18 +12163,7 @@ void Unit::UpdateObjectVisibility(bool forced)
void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
{
- Player* player = ToPlayer();
- if (!player)
- {
- if (Unit* charmer = GetCharmer())
- {
- player = charmer->ToPlayer();
- if (player && player->GetUnitBeingMoved() != this)
- player = nullptr;
- }
- }
-
- if (!player)
+ if (IsMovedByServer())
{
GetMotionMaster()->MoveKnockbackFrom(x, y, speedXY, speedZ);
}
@@ -12190,10 +12179,10 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
data << float(speedXY); // Horizontal speed
data << float(-speedZ); // Z Movement speed (vertical)
- player->SendDirectMessage(&data);
+ GetGameClientMovingMe()->SendDirectMessage(&data);
- if (player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || player->HasAuraType(SPELL_AURA_FLY))
- player->SetCanFly(true, true);
+ if (HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || HasAuraType(SPELL_AURA_FLY))
+ SetCanFly(true, true);
}
}
@@ -12853,9 +12842,9 @@ void Unit::SendTeleportPacket(Position const& pos, bool teleportingTransport /*=
moveUpdateTeleport << GetPackGUID();
Unit* broadcastSource = this;
- // should this really be the unit _being_ moved? not the unit doing the moving?
- if (Player* playerMover = Unit::ToPlayer(GetUnitBeingMoved()))
+ if (IsMovedByClient())
{
+ Player* playerMover = GetGameClientMovingMe()->GetBasePlayer();
WorldPacket moveTeleport(MSG_MOVE_TELEPORT_ACK, 41);
moveTeleport << GetPackGUID();
moveTeleport << uint32(0); // this value increments every time
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index a78c049d9f6..87c2e6d1e87 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -71,6 +71,7 @@ class AuraApplication;
class AuraEffect;
class Creature;
class DynamicObject;
+class GameClient;
class GameObject;
class Guardian;
class Item;
@@ -1184,6 +1185,7 @@ class TC_GAME_API Unit : public WorldObject
void RemoveAllControlled();
bool IsCharmed() const { return !GetCharmerGUID().IsEmpty(); }
+ bool IsCharming() const { return !GetCharmedGUID().IsEmpty(); }
bool isPossessed() const { return HasUnitState(UNIT_STATE_POSSESSED); }
bool isPossessedByPlayer() const;
bool isPossessing() const;
@@ -1193,12 +1195,17 @@ class TC_GAME_API Unit : public WorldObject
CharmInfo* InitCharmInfo();
void DeleteCharmInfo();
- // all of these are for DIRECT CLIENT CONTROL only
- void SetMovedUnit(Unit* target);
- // returns the unit that this player IS CONTROLLING
- Unit* GetUnitBeingMoved() const { return m_unitMovedByMe; }
- // returns the player that this unit is BEING CONTROLLED BY
- Player* GetPlayerMovingMe() const { return m_playerMovingMe; }
+ // base client control of this unit (possess effects, vehicles and similar). Not affected by temporary CC.
+ bool IsCharmerOrSelfPlayer() const { return GetCharmerOrSelf()->IsPlayer(); }
+ Unit* GetCharmerOrSelf() const;
+ Player* GetCharmerOrSelfPlayer() const { return ToPlayer(GetCharmerOrSelf());}
+ Unit* GetCharmedOrSelf() const { return IsCharming() ? GetCharmed() : const_cast<Unit*>(this); }
+
+ // real time client control status of this unit (possess effects, vehicles and similar). For example, if this unit is a player temporarly under fear, it will return false.
+ bool IsMovedByClient() const { return _gameClientMovingMe != nullptr; }
+ bool IsMovedByServer() const { return !IsMovedByClient(); }
+ GameClient* GetGameClientMovingMe() const { return _gameClientMovingMe; }
+ void SetGameClientMovingMe(GameClient* gameClientMovingMe) { _gameClientMovingMe = gameClientMovingMe; }
SharedVisionList const& GetSharedVisionList() { return m_sharedVision; }
void AddPlayerToVision(Player* player);
@@ -1673,6 +1680,8 @@ class TC_GAME_API Unit : public WorldObject
// Movement info
Movement::MoveSpline * movespline;
+ uint8 m_forced_speed_changes[MAX_MOVE_TYPE];
+
int32 GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEff, AuraType auraType, bool checkMiscValue = false, int32 miscValue = 0) const;
bool IsHighestExclusiveAura(Aura const* aura, bool removeOtherAuraApplications = false);
bool IsHighestExclusiveAuraEffect(SpellInfo const* spellInfo, AuraType auraType, int32 effectAmount, uint8 auraEffectMask, bool removeOtherAuraApplications = false);
@@ -1751,12 +1760,11 @@ class TC_GAME_API Unit : public WorldObject
float m_speed_rate[MAX_MOVE_TYPE];
- Unit* m_unitMovedByMe; // only ever set for players, and only for direct client control
- Player* m_playerMovingMe; // only set for direct client control (possess effects, vehicles and similar)
Unit* m_charmer; // Unit that is charming ME
Unit* m_charmed; // Unit that is being charmed BY ME
CharmInfo* m_charmInfo;
SharedVisionList m_sharedVision;
+ GameClient* _gameClientMovingMe;
MotionMaster* i_motionMaster;