aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2013-06-15 15:16:36 +0200
committerShauren <shauren.trinity@gmail.com>2013-06-15 15:16:36 +0200
commitfa75fe78bd76e910ab7dfc614bc75f3ce43f9793 (patch)
treec58fbf5ca08da0f9726b8045d42a774aaf1fc576
parenta8a5239aad6f0396948978bdeae0979e7a8dfa97 (diff)
Core/Objects
* Split BuildValuesUpdate into separate virtual methods for every object type that does something special with update fields * Removed _SetCreateBits/_SetUpdateBits to halve the amount of checks if field needs to be sent
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp88
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h2
-rw-r--r--src/server/game/Entities/Object/Object.cpp325
-rw-r--r--src/server/game/Entities/Object/Object.h6
-rw-r--r--src/server/game/Entities/Player/Player.cpp32
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp174
-rw-r--r--src/server/game/Entities/Unit/Unit.h2
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp4
8 files changed, 301 insertions, 332 deletions
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index fbad85e8182..2a4c0b1c1c9 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -17,21 +17,21 @@
*/
#include "GameObjectAI.h"
-#include "ObjectMgr.h"
+#include "BattlegroundAV.h"
+#include "CellImpl.h"
+#include "CreatureAISelector.h"
+#include "DynamicTree.h"
+#include "GameObjectModel.h"
+#include "GridNotifiersImpl.h"
+#include "Group.h"
#include "GroupMgr.h"
+#include "ObjectMgr.h"
+#include "OutdoorPvPMgr.h"
#include "PoolMgr.h"
+#include "ScriptMgr.h"
#include "SpellMgr.h"
+#include "UpdateFieldFlags.h"
#include "World.h"
-#include "GridNotifiersImpl.h"
-#include "CellImpl.h"
-#include "OutdoorPvPMgr.h"
-#include "BattlegroundAV.h"
-#include "ScriptMgr.h"
-#include "CreatureAISelector.h"
-#include "Group.h"
-
-#include "GameObjectModel.h"
-#include "DynamicTree.h"
GameObject::GameObject(): WorldObject(false), m_model(NULL), m_goValue(), m_AI(NULL)
{
@@ -2083,3 +2083,69 @@ bool GameObject::IsLootAllowedFor(Player const* player) const
return true;
}
+
+void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const
+{
+ if (!target)
+ return;
+
+ bool forcedFlags = GetGoType() == GAMEOBJECT_TYPE_CHEST && GetGOInfo()->chest.groupLootRules && HasLootRecipient();
+ bool targetIsGM = target->IsGameMaster();
+
+ ByteBuffer fieldBuffer;
+
+ UpdateMask updateMask;
+ updateMask.SetCount(m_valuesCount);
+
+ uint32* flags = GameObjectUpdateFieldFlags;
+ uint32 visibleFlag = UF_FLAG_PUBLIC;
+ if (GetOwnerGUID() == target->GetGUID())
+ visibleFlag |= UF_FLAG_OWNER;
+
+ for (uint16 index = 0; index < m_valuesCount; ++index)
+ {
+ if (_fieldNotifyFlags & flags[index] ||
+ ((updateType == UPDATETYPE_VALUES ? _changesMask.GetBit(index) : m_uint32Values[index]) && (flags[index] & visibleFlag)) ||
+ (index == GAMEOBJECT_FLAGS && forcedFlags))
+ {
+ updateMask.SetBit(index);
+
+ if (index == GAMEOBJECT_DYNAMIC)
+ {
+ uint16 dynFlags = 0;
+ switch (GetGoType())
+ {
+ case GAMEOBJECT_TYPE_CHEST:
+ case GAMEOBJECT_TYPE_GOOBER:
+ if (ActivateToQuest(target))
+ dynFlags |= GO_DYNFLAG_LO_ACTIVATE | GO_DYNFLAG_LO_SPARKLE;
+ else if (targetIsGM)
+ dynFlags |= GO_DYNFLAG_LO_ACTIVATE;
+ break;
+ case GAMEOBJECT_TYPE_GENERIC:
+ if (ActivateToQuest(target))
+ dynFlags |= GO_DYNFLAG_LO_SPARKLE;
+ break;
+ }
+
+ fieldBuffer << uint16(dynFlags);
+ fieldBuffer << uint16(-1);
+ }
+ else if (index == GAMEOBJECT_FLAGS)
+ {
+ uint32 flags = m_uint32Values[GAMEOBJECT_FLAGS];
+ if (GetGoType() == GAMEOBJECT_TYPE_CHEST)
+ if (GetGOInfo()->chest.groupLootRules && !IsLootAllowedFor(target))
+ flags |= GO_FLAG_LOCKED | GO_FLAG_NOT_SELECTABLE;
+
+ fieldBuffer << flags;
+ }
+ else
+ fieldBuffer << m_uint32Values[index]; // other cases
+ }
+ }
+
+ *data << uint8(updateMask.GetBlockCount());
+ updateMask.AppendToPacket(data);
+ data->append(fieldBuffer);
+}
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index 164735a56b5..cf916afd6dc 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -623,6 +623,8 @@ class GameObject : public WorldObject, public GridObject<GameObject>
explicit GameObject();
~GameObject();
+ void BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, Player* target) const;
+
void AddToWorld();
void RemoveFromWorld();
void CleanupsBeforeDelete(bool finalCleanup = true);
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 3076ce8b4ab..5ddc632e573 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -194,7 +194,7 @@ void Object::BuildMovementUpdateBlock(UpdateData* data, uint32 flags) const
buf << uint8(UPDATETYPE_MOVEMENT);
buf.append(GetPackGUID());
- _BuildMovementUpdate(&buf, flags);
+ BuildMovementUpdate(&buf, flags);
data->AddUpdateBlock(buf);
}
@@ -254,12 +254,8 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
buf.append(GetPackGUID());
buf << uint8(m_objectTypeId);
- _BuildMovementUpdate(&buf, flags);
-
- UpdateMask updateMask;
- updateMask.SetCount(m_valuesCount);
- _SetCreateBits(&updateMask, target);
- _BuildValuesUpdate(updateType, &buf, &updateMask, target);
+ BuildMovementUpdate(&buf, flags);
+ BuildValuesUpdate(updateType, &buf, target);
data->AddUpdateBlock(buf);
}
@@ -281,11 +277,7 @@ void Object::BuildValuesUpdateBlockForPlayer(UpdateData* data, Player* target) c
buf << uint8(UPDATETYPE_VALUES);
buf.append(GetPackGUID());
- UpdateMask updateMask;
- updateMask.SetCount(m_valuesCount);
-
- _SetUpdateBits(&updateMask, target);
- _BuildValuesUpdate(UPDATETYPE_VALUES, &buf, &updateMask, target);
+ BuildValuesUpdate(UPDATETYPE_VALUES, &buf, target);
data->AddUpdateBlock(buf);
}
@@ -358,7 +350,7 @@ uint16 Object::GetUInt16Value(uint16 index, uint8 offset) const
return *(((uint16*)&m_uint32Values[index])+offset);
}
-void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
+void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
{
Unit const* unit = NULL;
WorldObject const* object = NULL;
@@ -510,289 +502,31 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
*data << int64(ToGameObject()->GetRotation());
}
-void Object::_BuildValuesUpdate(uint8 updateType, ByteBuffer* data, UpdateMask* updateMask, Player* target) const
+void Object::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const
{
if (!target)
return;
- bool IsActivateToQuest = false;
-
- // Before trying to convert to each type there is a check, so safe
- Unit const* unit = ToUnit();
- GameObject const* go = ToGameObject();
-
- if (unit)
- {
- if (unit->HasFlag(UNIT_FIELD_AURASTATE, PER_CASTER_AURA_STATE_MASK))
- updateMask->SetBit(UNIT_FIELD_AURASTATE);
- }
- else if (go)
- {
- if (updateType == UPDATETYPE_CREATE_OBJECT || updateType == UPDATETYPE_CREATE_OBJECT2)
- {
- if (!go->IsDynTransport())
- {
- if (go->ActivateToQuest(target) || target->IsGameMaster())
- IsActivateToQuest = true;
-
- if (go->GetGoArtKit())
- updateMask->SetBit(GAMEOBJECT_BYTES_1);
- }
- }
- else
- {
- if (!go->IsTransport())
- {
- if (go->ActivateToQuest(target) || target->IsGameMaster())
- IsActivateToQuest = true;
-
- updateMask->SetBit(GAMEOBJECT_BYTES_1);
-
- if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST && go->GetGOInfo()->chest.groupLootRules &&
- go->HasLootRecipient())
- {
- updateMask->SetBit(GAMEOBJECT_FLAGS);
- }
- }
- }
- }
-
- ASSERT(updateMask && updateMask->GetCount() == m_valuesCount);
+ ByteBuffer fieldBuffer;
+ UpdateMask updateMask;
+ updateMask.SetCount(m_valuesCount);
- *data << uint8(updateMask->GetBlockCount());
- updateMask->AppendToPacket(data);
+ uint32* flags = NULL;
+ uint32 visibleFlag = GetUpdateFieldData(target, flags);
- // 2 specialized loops for speed optimization in non-unit case
- if (unit) // unit (creature/player) case
+ for (uint16 index = 0; index < m_valuesCount; ++index)
{
- Creature const* creature = ToCreature();
- for (uint16 index = 0; index < m_valuesCount; ++index)
+ if (_fieldNotifyFlags & flags[index] ||
+ ((updateType == UPDATETYPE_VALUES ? _changesMask.GetBit(index) : m_uint32Values[index]) && (flags[index] & visibleFlag)))
{
- if (updateMask->GetBit(index))
- {
- if (index == UNIT_NPC_FLAGS)
- {
- // remove custom flag before sending
- uint32 appendValue = m_uint32Values[index];
-
- if (GetTypeId() == TYPEID_UNIT)
- {
- if (!target->CanSeeSpellClickOn(this->ToCreature()))
- appendValue &= ~UNIT_NPC_FLAG_SPELLCLICK;
- }
-
- *data << uint32(appendValue);
- }
- else if (index == UNIT_FIELD_AURASTATE)
- {
- // Check per caster aura states to not enable using a spell in client if specified aura is not by target
- *data << unit->BuildAuraStateUpdateForTarget(target);
- }
- // FIXME: Some values at server stored in float format but must be sent to client in uint32 format
- else if (index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME)
- {
- // convert from float to uint32 and send
- *data << uint32(m_floatValues[index] < 0 ? 0 : m_floatValues[index]);
- }
- // there are some float values which may be negative or can't get negative due to other checks
- else if ((index >= UNIT_FIELD_NEGSTAT0 && index <= UNIT_FIELD_NEGSTAT4) ||
- (index >= UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE && index <= (UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + 6)) ||
- (index >= UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE && index <= (UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + 6)) ||
- (index >= UNIT_FIELD_POSSTAT0 && index <= UNIT_FIELD_POSSTAT4))
- {
- *data << uint32(m_floatValues[index]);
- }
- // Gamemasters should be always able to select units - remove not selectable flag
- else if (index == UNIT_FIELD_FLAGS)
- {
- if (target->IsGameMaster())
- *data << (m_uint32Values[index] & ~UNIT_FLAG_NOT_SELECTABLE);
- else
- *data << m_uint32Values[index];
- }
- // use modelid_a if not gm, _h if gm for CREATURE_FLAG_EXTRA_TRIGGER creatures
- else if (index == UNIT_FIELD_DISPLAYID)
- {
- if (GetTypeId() == TYPEID_UNIT)
- {
- CreatureTemplate const* cinfo = creature->GetCreatureTemplate();
-
- // this also applies for transform auras
- if (SpellInfo const* transform = sSpellMgr->GetSpellInfo(ToUnit()->getTransForm()))
- for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- if (transform->Effects[i].IsAura(SPELL_AURA_TRANSFORM))
- if (CreatureTemplate const* transformInfo = sObjectMgr->GetCreatureTemplate(transform->Effects[i].MiscValue))
- {
- cinfo = transformInfo;
- break;
- }
-
- if (cinfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
- {
- if (target->IsGameMaster())
- {
- if (cinfo->Modelid1)
- *data << cinfo->Modelid1;//Modelid1 is a visible model for gms
- else
- *data << 17519; // world invisible trigger's model
- }
- else
- {
- if (cinfo->Modelid2)
- *data << cinfo->Modelid2;//Modelid2 is an invisible model for players
- else
- *data << 11686; // world invisible trigger's model
- }
- }
- else
- *data << m_uint32Values[index];
- }
- else
- *data << m_uint32Values[index];
- }
- // hide lootable animation for unallowed players
- else if (index == UNIT_DYNAMIC_FLAGS)
- {
- uint32 dynamicFlags = m_uint32Values[index];
-
- if (creature)
- {
- if (creature->hasLootRecipient())
- {
- if (creature->isTappedBy(target))
- {
- dynamicFlags |= (UNIT_DYNFLAG_TAPPED | UNIT_DYNFLAG_TAPPED_BY_PLAYER);
- }
- else
- {
- dynamicFlags |= UNIT_DYNFLAG_TAPPED;
- dynamicFlags &= ~UNIT_DYNFLAG_TAPPED_BY_PLAYER;
- }
- }
- else
- {
- dynamicFlags &= ~UNIT_DYNFLAG_TAPPED;
- dynamicFlags &= ~UNIT_DYNFLAG_TAPPED_BY_PLAYER;
- }
-
- if (!target->isAllowedToLoot(creature))
- dynamicFlags &= ~UNIT_DYNFLAG_LOOTABLE;
- }
-
- // unit UNIT_DYNFLAG_TRACK_UNIT should only be sent to caster of SPELL_AURA_MOD_STALKED auras
- if (dynamicFlags & UNIT_DYNFLAG_TRACK_UNIT)
- if (!unit->HasAuraTypeWithCaster(SPELL_AURA_MOD_STALKED, target->GetGUID()))
- dynamicFlags &= ~UNIT_DYNFLAG_TRACK_UNIT;
- *data << dynamicFlags;
- }
- // FG: pretend that OTHER players in own group are friendly ("blue")
- else if (index == UNIT_FIELD_BYTES_2 || index == UNIT_FIELD_FACTIONTEMPLATE)
- {
- if (unit->IsControlledByPlayer() && target != this && sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && unit->IsInRaidWith(target))
- {
- FactionTemplateEntry const* ft1 = unit->GetFactionTemplateEntry();
- FactionTemplateEntry const* ft2 = target->GetFactionTemplateEntry();
- if (ft1 && ft2 && !ft1->IsFriendlyTo(*ft2))
- {
- if (index == UNIT_FIELD_BYTES_2)
- {
- // Allow targetting opposite faction in party when enabled in config
- *data << (m_uint32Values[index] & ((UNIT_BYTE2_FLAG_SANCTUARY /*| UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5*/) << 8)); // this flag is at uint8 offset 1 !!
- }
- else
- {
- // pretend that all other HOSTILE players have own faction, to allow follow, heal, rezz (trade wont work)
- uint32 faction = target->getFaction();
- *data << uint32(faction);
- }
- }
- else
- *data << m_uint32Values[index];
- }
- else
- *data << m_uint32Values[index];
- }
- else
- {
- // send in current format (float as float, uint32 as uint32)
- *data << m_uint32Values[index];
- }
- }
+ updateMask.SetBit(index);
+ fieldBuffer << m_uint32Values[index];
}
}
- else if (go) // gameobject case
- {
- for (uint16 index = 0; index < m_valuesCount; ++index)
- {
- if (updateMask->GetBit(index))
- {
- // send in current format (float as float, uint32 as uint32)
- if (index == GAMEOBJECT_DYNAMIC)
- {
- if (IsActivateToQuest)
- {
- switch (go->GetGoType())
- {
- case GAMEOBJECT_TYPE_CHEST:
- if (target->IsGameMaster())
- *data << uint16(GO_DYNFLAG_LO_ACTIVATE);
- else
- *data << uint16(GO_DYNFLAG_LO_ACTIVATE | GO_DYNFLAG_LO_SPARKLE);
- *data << uint16(-1);
- break;
- case GAMEOBJECT_TYPE_GENERIC:
- if (target->IsGameMaster())
- *data << uint16(0);
- else
- *data << uint16(GO_DYNFLAG_LO_SPARKLE);
- *data << uint16(-1);
- break;
- case GAMEOBJECT_TYPE_GOOBER:
- if (target->IsGameMaster())
- *data << uint16(GO_DYNFLAG_LO_ACTIVATE);
- else
- *data << uint16(GO_DYNFLAG_LO_ACTIVATE | GO_DYNFLAG_LO_SPARKLE);
- *data << uint16(-1);
- break;
- default:
- // unknown, not happen.
- *data << uint16(0);
- *data << uint16(-1);
- break;
- }
- }
- else
- {
- // disable quest object
- *data << uint16(0);
- *data << uint16(-1);
- }
- }
- else if (index == GAMEOBJECT_FLAGS)
- {
- uint32 flags = m_uint32Values[index];
- if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST)
- if (go->GetGOInfo()->chest.groupLootRules && !go->IsLootAllowedFor(target))
- flags |= GO_FLAG_LOCKED | GO_FLAG_NOT_SELECTABLE;
- *data << flags;
- }
- else
- *data << m_uint32Values[index]; // other cases
- }
- }
- }
- else // other objects case (no special index checks)
- {
- for (uint16 index = 0; index < m_valuesCount; ++index)
- {
- if (updateMask->GetBit(index))
- {
- // send in current format (float as float, uint32 as uint32)
- *data << m_uint32Values[index];
- }
- }
- }
+ *data << uint8(updateMask.GetBlockCount());
+ updateMask.AppendToPacket(data);
+ data->append(fieldBuffer);
}
void Object::ClearUpdateMask(bool remove)
@@ -891,27 +625,6 @@ void Object::_LoadIntoDataField(std::string const& data, uint32 startOffset, uin
}
}
-void Object::_SetUpdateBits(UpdateMask* updateMask, Player* target) const
-{
- uint32* flags = NULL;
- uint32 visibleFlag = GetUpdateFieldData(target, flags);
-
- for (uint16 index = 0; index < m_valuesCount; ++index)
- if (_fieldNotifyFlags & flags[index] || ((flags[index] & visibleFlag) & UF_FLAG_SPECIAL_INFO) || (_changesMask.GetBit(index) && (flags[index] & visibleFlag)))
- updateMask->SetBit(index);
-}
-
-void Object::_SetCreateBits(UpdateMask* updateMask, Player* target) const
-{
- uint32* value = m_uint32Values;
- uint32* flags = NULL;
- uint32 visibleFlag = GetUpdateFieldData(target, flags);
-
- for (uint16 index = 0; index < m_valuesCount; ++index, ++value)
- if (_fieldNotifyFlags & flags[index] || ((flags[index] & visibleFlag) & UF_FLAG_SPECIAL_INFO) || (*value && (flags[index] & visibleFlag)))
- updateMask->SetBit(index);
-}
-
void Object::SetInt32Value(uint16 index, int32 value)
{
ASSERT(index < m_valuesCount || PrintIndexError(index, true));
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index af9b6a38fc8..25f71deabe9 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -236,10 +236,8 @@ class Object
uint32 GetUpdateFieldData(Player const* target, uint32*& flags) const;
- void _SetUpdateBits(UpdateMask* updateMask, Player* target) const;
- void _SetCreateBits(UpdateMask* updateMask, Player* target) const;
- void _BuildMovementUpdate(ByteBuffer * data, uint16 flags) const;
- void _BuildValuesUpdate(uint8 updatetype, ByteBuffer *data, UpdateMask* updateMask, Player* target) const;
+ void BuildMovementUpdate(ByteBuffer* data, uint16 flags) const;
+ virtual void BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, Player* target) const;
uint16 m_objectType;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 2b2032d063e..04f246d716d 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -24,15 +24,14 @@
#include "Battlefield.h"
#include "BattlefieldMgr.h"
#include "BattlefieldWG.h"
-#include "BattlegroundAV.h"
#include "Battleground.h"
+#include "BattlegroundAV.h"
#include "BattlegroundMgr.h"
#include "CellImpl.h"
#include "Channel.h"
#include "ChannelMgr.h"
#include "CharacterDatabaseCleaner.h"
#include "Chat.h"
-#include <cmath>
#include "Common.h"
#include "ConditionMgr.h"
#include "CreatureAI.h"
@@ -49,8 +48,8 @@
#include "GuildMgr.h"
#include "InstanceSaveMgr.h"
#include "InstanceScript.h"
-#include "Language.h"
#include "LFGMgr.h"
+#include "Language.h"
#include "Log.h"
#include "MapInstanced.h"
#include "MapManager.h"
@@ -59,17 +58,18 @@
#include "Opcodes.h"
#include "OutdoorPvP.h"
#include "OutdoorPvPMgr.h"
-#include "ReputationMgr.h"
#include "Pet.h"
#include "QuestDef.h"
+#include "ReputationMgr.h"
#include "SkillDiscovery.h"
#include "SocialMgr.h"
+#include "Spell.h"
#include "SpellAuraEffects.h"
#include "SpellAuras.h"
-#include "Spell.h"
#include "SpellMgr.h"
#include "Transport.h"
#include "UpdateData.h"
+#include "UpdateFieldFlags.h"
#include "UpdateMask.h"
#include "Util.h"
#include "Vehicle.h"
@@ -22229,14 +22229,30 @@ void Player::UpdateTriggerVisibility()
{
if (IS_CREATURE_GUID(*itr))
{
- Creature* obj = GetMap()->GetCreature(*itr);
- if (!obj || !(obj->IsTrigger() || obj->HasAuraType(SPELL_AURA_TRANSFORM))) // can transform into triggers
+ Creature* creature = GetMap()->GetCreature(*itr);
+ // Update fields of triggers, transformed units or unselectable units (values dependent on GM state)
+ if (!creature || (!creature->IsTrigger() && !creature->HasAuraType(SPELL_AURA_TRANSFORM) && !creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)))
continue;
- obj->BuildValuesUpdateBlockForPlayer(&udata, this);
+ creature->SetFieldNotifyFlag(UF_FLAG_PUBLIC);
+ creature->BuildValuesUpdateBlockForPlayer(&udata, this);
+ creature->RemoveFieldNotifyFlag(UF_FLAG_PUBLIC);
+ }
+ else if (IS_GAMEOBJECT_GUID((*itr)))
+ {
+ GameObject* go = GetMap()->GetGameObject(*itr);
+ if (!go)
+ continue;
+
+ go->SetFieldNotifyFlag(UF_FLAG_PUBLIC);
+ go->BuildValuesUpdateBlockForPlayer(&udata, this);
+ go->RemoveFieldNotifyFlag(UF_FLAG_PUBLIC);
}
}
+ if (!udata.HasData())
+ return;
+
udata.BuildPacket(&packet);
GetSession()->SendPacket(&packet);
}
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index c10bffbbe92..e274c40e336 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -17549,3 +17549,177 @@ void Unit::ReleaseFocus(Spell const* focusSpell)
if (focusSpell->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_DONT_TURN_DURING_CAST)
ClearUnitState(UNIT_STATE_ROTATING);
}
+
+void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const
+{
+ if (!target)
+ return;
+
+ ByteBuffer fieldBuffer;
+
+ UpdateMask updateMask;
+ updateMask.SetCount(m_valuesCount);
+
+ uint32* flags = UnitUpdateFieldFlags;
+ uint32 visibleFlag = UF_FLAG_PUBLIC;
+
+ if (target == this)
+ visibleFlag |= UF_FLAG_PRIVATE;
+
+ Player* plr = GetCharmerOrOwnerPlayerOrPlayerItself();
+ if (GetOwnerGUID() == target->GetGUID())
+ visibleFlag |= UF_FLAG_OWNER;
+
+ if (HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO))
+ if (HasAuraTypeWithCaster(SPELL_AURA_EMPATHY, target->GetGUID()))
+ visibleFlag |= UF_FLAG_SPECIAL_INFO;
+
+ if (plr && plr->IsInSameRaidWith(target))
+ visibleFlag |= UF_FLAG_PARTY_MEMBER;
+
+ Creature const* creature = ToCreature();
+ for (uint16 index = 0; index < m_valuesCount; ++index)
+ {
+ if (_fieldNotifyFlags & flags[index] ||
+ ((flags[index] & visibleFlag) & UF_FLAG_SPECIAL_INFO) ||
+ ((updateType == UPDATETYPE_VALUES ? _changesMask.GetBit(index) : m_uint32Values[index]) && (flags[index] & visibleFlag)) ||
+ (index == UNIT_FIELD_AURASTATE && HasFlag(UNIT_FIELD_AURASTATE, PER_CASTER_AURA_STATE_MASK)))
+ {
+ updateMask.SetBit(index);
+
+ if (index == UNIT_NPC_FLAGS)
+ {
+ uint32 appendValue = m_uint32Values[UNIT_NPC_FLAGS];
+
+ if (creature)
+ if (!target->CanSeeSpellClickOn(creature))
+ appendValue &= ~UNIT_NPC_FLAG_SPELLCLICK;
+
+ fieldBuffer << uint32(appendValue);
+ }
+ else if (index == UNIT_FIELD_AURASTATE)
+ {
+ // Check per caster aura states to not enable using a spell in client if specified aura is not by target
+ fieldBuffer << BuildAuraStateUpdateForTarget(target);
+ }
+ // FIXME: Some values at server stored in float format but must be sent to client in uint32 format
+ else if (index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME)
+ {
+ // convert from float to uint32 and send
+ fieldBuffer << uint32(m_floatValues[index] < 0 ? 0 : m_floatValues[index]);
+ }
+ // there are some float values which may be negative or can't get negative due to other checks
+ else if ((index >= UNIT_FIELD_NEGSTAT0 && index <= UNIT_FIELD_NEGSTAT4) ||
+ (index >= UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE && index <= (UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + 6)) ||
+ (index >= UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE && index <= (UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + 6)) ||
+ (index >= UNIT_FIELD_POSSTAT0 && index <= UNIT_FIELD_POSSTAT4))
+ {
+ fieldBuffer << uint32(m_floatValues[index]);
+ }
+ // Gamemasters should be always able to select units - remove not selectable flag
+ else if (index == UNIT_FIELD_FLAGS)
+ {
+ uint32 appendValue = m_uint32Values[UNIT_FIELD_FLAGS];
+ if (target->IsGameMaster())
+ appendValue &= ~UNIT_FLAG_NOT_SELECTABLE;
+
+ fieldBuffer << uint32(appendValue);
+ }
+ // use modelid_a if not gm, _h if gm for CREATURE_FLAG_EXTRA_TRIGGER creatures
+ else if (index == UNIT_FIELD_DISPLAYID)
+ {
+ uint32 displayId = m_uint32Values[UNIT_FIELD_DISPLAYID];
+ if (creature)
+ {
+ CreatureTemplate const* cinfo = creature->GetCreatureTemplate();
+
+ // this also applies for transform auras
+ if (SpellInfo const* transform = sSpellMgr->GetSpellInfo(getTransForm()))
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ if (transform->Effects[i].IsAura(SPELL_AURA_TRANSFORM))
+ if (CreatureTemplate const* transformInfo = sObjectMgr->GetCreatureTemplate(transform->Effects[i].MiscValue))
+ {
+ cinfo = transformInfo;
+ break;
+ }
+
+ if (cinfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
+ {
+ if (target->IsGameMaster())
+ {
+ if (cinfo->Modelid1)
+ displayId = cinfo->Modelid1; // Modelid1 is a visible model for gms
+ else
+ displayId = 17519; // world visible trigger's model
+ }
+ else
+ {
+ if (cinfo->Modelid2)
+ displayId = cinfo->Modelid2; // Modelid2 is an invisible model for players
+ else
+ displayId = 11686; // world invisible trigger's model
+ }
+ }
+ }
+
+ fieldBuffer << uint32(displayId);
+ }
+ // hide lootable animation for unallowed players
+ else if (index == UNIT_DYNAMIC_FLAGS)
+ {
+ uint32 dynamicFlags = m_uint32Values[UNIT_DYNAMIC_FLAGS] & ~(UNIT_DYNFLAG_TAPPED | UNIT_DYNFLAG_TAPPED_BY_PLAYER);
+
+ if (creature)
+ {
+ if (creature->hasLootRecipient())
+ {
+ dynamicFlags |= UNIT_DYNFLAG_TAPPED;
+ if (creature->isTappedBy(target))
+ dynamicFlags |= UNIT_DYNFLAG_TAPPED_BY_PLAYER;
+ }
+
+ if (!target->isAllowedToLoot(creature))
+ dynamicFlags &= ~UNIT_DYNFLAG_LOOTABLE;
+ }
+
+ // unit UNIT_DYNFLAG_TRACK_UNIT should only be sent to caster of SPELL_AURA_MOD_STALKED auras
+ if (dynamicFlags & UNIT_DYNFLAG_TRACK_UNIT)
+ if (!HasAuraTypeWithCaster(SPELL_AURA_MOD_STALKED, target->GetGUID()))
+ dynamicFlags &= ~UNIT_DYNFLAG_TRACK_UNIT;
+
+ fieldBuffer << dynamicFlags;
+ }
+ // FG: pretend that OTHER players in own group are friendly ("blue")
+ else if (index == UNIT_FIELD_BYTES_2 || index == UNIT_FIELD_FACTIONTEMPLATE)
+ {
+ if (IsControlledByPlayer() && target != this && sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && IsInRaidWith(target))
+ {
+ FactionTemplateEntry const* ft1 = GetFactionTemplateEntry();
+ FactionTemplateEntry const* ft2 = target->GetFactionTemplateEntry();
+ if (ft1 && ft2 && !ft1->IsFriendlyTo(*ft2))
+ {
+ if (index == UNIT_FIELD_BYTES_2)
+ // Allow targetting opposite faction in party when enabled in config
+ fieldBuffer << (m_uint32Values[UNIT_FIELD_BYTES_2] & ((UNIT_BYTE2_FLAG_SANCTUARY /*| UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5*/) << 8)); // this flag is at uint8 offset 1 !!
+ else
+ // pretend that all other HOSTILE players have own faction, to allow follow, heal, rezz (trade wont work)
+ fieldBuffer << uint32(target->getFaction());
+ }
+ else
+ fieldBuffer << m_uint32Values[index];
+ }
+ else
+ fieldBuffer << m_uint32Values[index];
+ }
+ else
+ {
+ // send in current format (float as float, uint32 as uint32)
+ fieldBuffer << m_uint32Values[index];
+ }
+ }
+ }
+
+ *data << uint8(updateMask.GetBlockCount());
+ updateMask.AppendToPacket(data);
+ data->append(fieldBuffer);
+}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index da954fc9e40..04950cfdcbd 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -2149,6 +2149,8 @@ class Unit : public WorldObject
protected:
explicit Unit (bool isWorldObject);
+ void BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, Player* target) const;
+
UnitAI* i_AI, *i_disabledAI;
void _UpdateSpells(uint32 time);
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index 2ab0f967756..19fdc3a1fe8 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -330,9 +330,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
if (!foundNewTransport)
{
plrMover->m_transport = NULL;
- movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
- movementInfo.t_time = 0;
- movementInfo.t_seat = -1;
+ movementInfo.ClearTransport();
}
}
}