diff options
author | Shauren <shauren.trinity@gmail.com> | 2013-06-15 15:16:36 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2013-06-15 15:16:36 +0200 |
commit | fa75fe78bd76e910ab7dfc614bc75f3ce43f9793 (patch) | |
tree | c58fbf5ca08da0f9726b8045d42a774aaf1fc576 | |
parent | a8a5239aad6f0396948978bdeae0979e7a8dfa97 (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.cpp | 88 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObject.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 325 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.h | 6 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 32 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 174 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 2 | ||||
-rw-r--r-- | src/server/game/Handlers/MovementHandler.cpp | 4 |
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(); } } } |