aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities/Unit
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/Unit
parentedcaac6c959e944dc6d6dc224666b832521412b4 (diff)
Core/Movement: Improve client control logic (#26348)
Diffstat (limited to 'src/server/game/Entities/Unit')
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp71
-rw-r--r--src/server/game/Entities/Unit/Unit.h24
2 files changed, 46 insertions, 49 deletions
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;