diff options
Diffstat (limited to 'src/server/game')
31 files changed, 659 insertions, 747 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 4d2b5f88376..f43a7f91f32 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -724,27 +724,18 @@ uint64 SmartAI::GetGUID(int32 /*id*/) const void SmartAI::SetRun(bool run) { - if (run) - me->SetWalk(false); - else - me->SetWalk(true); - + me->SetWalk(!run); mRun = run; } void SmartAI::SetFly(bool fly) { me->SetDisableGravity(fly); - me->SendMovementDisableGravity(); } void SmartAI::SetSwim(bool swim) { - if (swim) - me->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING); - else - me->RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING); - me->SendMovementSwimming(); + me->SetSwim(swim); } void SmartAI::sGossipHello(Player* player) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp index 7b4f323ac31..b5b8a7ce7e2 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp @@ -101,10 +101,10 @@ void BattlegroundIC::DoAction(uint32 action, uint64 var) player->SetTransport(player->GetTeamId() == TEAM_ALLIANCE ? gunshipAlliance : gunshipHorde); - player->m_movementInfo.t_pos.m_positionX = TransportMovementInfo.GetPositionX(); - player->m_movementInfo.t_pos.m_positionY = TransportMovementInfo.GetPositionY(); - player->m_movementInfo.t_pos.m_positionZ = TransportMovementInfo.GetPositionZ(); - player->m_movementInfo.t_guid = (player->GetTeamId() == TEAM_ALLIANCE ? gunshipAlliance : gunshipHorde)->GetGUID(); + player->m_movementInfo.transport.pos.m_positionX = TransportMovementInfo.GetPositionX(); + player->m_movementInfo.transport.pos.m_positionY = TransportMovementInfo.GetPositionY(); + player->m_movementInfo.transport.pos.m_positionZ = TransportMovementInfo.GetPositionZ(); + player->m_movementInfo.transport.guid = (player->GetTeamId() == TEAM_ALLIANCE ? gunshipAlliance : gunshipHorde)->GetGUID(); if (player->TeleportTo(GetMapId(), TeleportToTransportPosition.GetPositionX(), TeleportToTransportPosition.GetPositionY(), diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index ebbf11be586..d8da1e5e286 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -2416,53 +2416,6 @@ bool Creature::IsDungeonBoss() const return cinfo && (cinfo->flags_extra & CREATURE_FLAG_EXTRA_DUNGEON_BOSS); } -bool Creature::SetWalk(bool enable) -{ - if (!Unit::SetWalk(enable)) - return false; - - if (!movespline->Initialized()) - return true; - - SendMovementWalkMode(); - return true; -} - -bool Creature::SetDisableGravity(bool disable, bool packetOnly/*=false*/) -{ - //! It's possible only a packet is sent but moveflags are not updated - //! Need more research on this - if (!packetOnly && !Unit::SetDisableGravity(disable)) - return false; - - if (!movespline->Initialized()) - return true; - - SendMovementDisableGravity(); - return true; -} - -bool Creature::SetHover(bool enable) -{ - if (!Unit::SetHover(enable)) - return false; - - //! Unconfirmed for players: - if (enable) - SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_HOVER); - else - RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_HOVER); - - if (!movespline->Initialized()) - return true; - - // If creature hovers using aura, the hover movement opcode is sent from aura handler - if (!HasAuraType(SPELL_AURA_HOVER)) - SendMovementHover(); - - return true; -} - float Creature::GetAggroRange(Unit const* target) const { // Determines the aggro range for creatures (usually pets), used mainly for aggressive pet target selection. @@ -2549,10 +2502,7 @@ void Creature::UpdateMovementFlags() SetDisableGravity(false); } - if (GetCreatureTemplate()->InhabitType & INHABIT_WATER && IsInWater()) - AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING); - else - RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING); + SetSwim(GetCreatureTemplate()->InhabitType & INHABIT_WATER && IsInWater()); } void Creature::SetObjectScale(float scale) diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index d70a4268235..de826d3f310 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -503,10 +503,6 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature CreatureAI* AI() const { return (CreatureAI*)i_AI; } - bool SetWalk(bool enable); - bool SetDisableGravity(bool disable, bool packetOnly = false); - bool SetHover(bool enable); - SpellSchoolMask GetMeleeDamageSchoolMask() const { return m_meleeDamageSchoolMask; } void SetMeleeDamageSchool(SpellSchools school) { m_meleeDamageSchoolMask = SpellSchoolMask(1 << school); } diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 07a3c0412d2..62426e95987 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -17,22 +17,22 @@ */ #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 "MapManager.h" -#include "GameObjectModel.h" -#include "DynamicTree.h" - GameObject::GameObject(): WorldObject(false), m_model(NULL), m_goValue(), m_AI(NULL) { m_objectType |= TYPEMASK_GAMEOBJECT; @@ -2084,3 +2084,71 @@ 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; + default: + 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 b1d55a6b200..97c9f4a4650 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -624,6 +624,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 eae333bc4c8..9ee58d62194 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -251,12 +251,8 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c buf.append(GetPackGUID()); buf << uint8(m_objectTypeId); - _BuildMovementUpdate(&buf, flags); - - UpdateMask updateMask; - updateMask.SetCount(valCount); - _SetCreateBits(&updateMask, target); - _BuildValuesUpdate(updateType, &buf, &updateMask, target); + BuildMovementUpdate(&buf, flags); + BuildValuesUpdate(updateType, &buf, target); data->AddUpdateBlock(buf); } @@ -278,15 +274,7 @@ void Object::BuildValuesUpdateBlockForPlayer(UpdateData* data, Player* target) c buf << uint8(UPDATETYPE_VALUES); buf.append(GetPackGUID()); - UpdateMask updateMask; - uint32 valCount = m_valuesCount; - if (GetTypeId() == TYPEID_PLAYER && target != this) - valCount = PLAYER_END_NOT_SELF; - - updateMask.SetCount(valCount); - - _SetUpdateBits(&updateMask, target); - _BuildValuesUpdate(UPDATETYPE_VALUES, &buf, &updateMask, target); + BuildValuesUpdate(UPDATETYPE_VALUES, &buf, target); data->AddUpdateBlock(buf); } @@ -359,7 +347,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* self = NULL; ObjectGuid guid = GetGUID(); @@ -434,12 +422,12 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const data->WriteBit(hasFallData); // Has fall data data->WriteBit(!hasSplineElevation); // Has spline elevation data->WriteBit(guid[5]); - data->WriteBit(self->m_movementInfo.t_guid); // Has transport data + data->WriteBit(self->m_movementInfo.transport.guid); // Has transport data data->WriteBit(0); // Is missing time - if (self->m_movementInfo.t_guid) + if (self->m_movementInfo.transport.guid) { - ObjectGuid transGuid = self->m_movementInfo.t_guid; + ObjectGuid transGuid = self->m_movementInfo.transport.guid; data->WriteBit(transGuid[1]); data->WriteBit(hasTransportTime2); // Has transport time 2 @@ -473,7 +461,7 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const if (flags & UPDATEFLAG_GO_TRANSPORT_POSITION) { WorldObject const* self = static_cast<WorldObject const*>(this); - ObjectGuid transGuid = self->m_movementInfo.t_guid; + ObjectGuid transGuid = self->m_movementInfo.transport.guid; data->WriteBit(transGuid[5]); data->WriteBit(0); // Has GO transport time 3 data->WriteBit(transGuid[0]); @@ -521,13 +509,13 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const { if (hasFallDirection) { - *data << float(self->m_movementInfo.j_cosAngle); - *data << float(self->m_movementInfo.j_xyspeed); - *data << float(self->m_movementInfo.j_sinAngle); + *data << float(self->m_movementInfo.jump.cosAngle); + *data << float(self->m_movementInfo.jump.xyspeed); + *data << float(self->m_movementInfo.jump.sinAngle); } - *data << uint32(self->m_movementInfo.fallTime); - *data << float(self->m_movementInfo.j_zspeed); + *data << uint32(self->m_movementInfo.jump.fallTime); + *data << float(self->m_movementInfo.jump.zspeed); } *data << self->GetSpeed(MOVE_SWIM_BACK); @@ -540,16 +528,16 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const *data << float(self->GetPositionZMinusOffset()); data->WriteByteSeq(guid[5]); - if (self->m_movementInfo.t_guid) + if (self->m_movementInfo.transport.guid) { - ObjectGuid transGuid = self->m_movementInfo.t_guid; + ObjectGuid transGuid = self->m_movementInfo.transport.guid; data->WriteByteSeq(transGuid[5]); data->WriteByteSeq(transGuid[7]); *data << uint32(self->GetTransTime()); *data << float(self->GetTransOffsetO()); if (hasTransportTime2) - *data << uint32(self->m_movementInfo.t_time2); + *data << uint32(self->m_movementInfo.transport.time2); *data << float(self->GetTransOffsetY()); *data << float(self->GetTransOffsetX()); @@ -557,7 +545,7 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const *data << float(self->GetTransOffsetZ()); data->WriteByteSeq(transGuid[0]); if (hasTransportTime3) - *data << uint32(self->m_movementInfo.t_time3); + *data << uint32(self->m_movementInfo.transport.time3); *data << int8(self->GetTransSeat()); data->WriteByteSeq(transGuid[1]); @@ -602,12 +590,12 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const if (flags & UPDATEFLAG_GO_TRANSPORT_POSITION) { WorldObject const* self = static_cast<WorldObject const*>(this); - ObjectGuid transGuid = self->m_movementInfo.t_guid; + ObjectGuid transGuid = self->m_movementInfo.transport.guid; data->WriteBit(transGuid[0]); data->WriteBit(transGuid[5]); if (hasTransportTime3) - *data << uint32(self->m_movementInfo.t_time3); + *data << uint32(self->m_movementInfo.transport.time3); data->WriteBit(transGuid[3]); *data << float(self->GetTransOffsetX()); @@ -622,7 +610,7 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const *data << int8(self->GetTransSeat()); *data << float(self->GetTransOffsetO()); if (hasTransportTime2) - *data << uint32(self->m_movementInfo.t_time2); + *data << uint32(self->m_movementInfo.transport.time2); } if (flags & UPDATEFLAG_ROTATION) @@ -688,286 +676,31 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const *data << uint32(getMSTime()); // Unknown - getMSTime is wrong. } -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; + ByteBuffer fieldBuffer; + UpdateMask updateMask; + updateMask.SetCount(m_valuesCount); - // Before trying to convert to each type there is a check, so safe - Unit const* unit = ToUnit(); - GameObject const* go = ToGameObject(); + uint32* flags = NULL; + uint32 visibleFlag = GetUpdateFieldData(target, flags); - if (unit) - { - if (unit->HasFlag(UNIT_FIELD_AURASTATE, PER_CASTER_AURA_STATE_MASK)) - updateMask->SetBit(UNIT_FIELD_AURASTATE); - } - else if (go) + for (uint16 index = 0; index < m_valuesCount; ++index) { - if (updateType == UPDATETYPE_CREATE_OBJECT || updateType == UPDATETYPE_CREATE_OBJECT2) + if (_fieldNotifyFlags & flags[index] || + ((updateType == UPDATETYPE_VALUES ? _changesMask.GetBit(index) : m_uint32Values[index]) && (flags[index] & visibleFlag))) { - 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); - } - } + updateMask.SetBit(index); + fieldBuffer << m_uint32Values[index]; } } - uint32 valCount = m_valuesCount; - if (GetTypeId() == TYPEID_PLAYER && target != this) - valCount = PLAYER_END_NOT_SELF; - - ASSERT(updateMask && updateMask->GetCount() == valCount); - - *data << uint8(updateMask->GetBlockCount()); - updateMask->AppendToPacket(data); - - // 2 specialized loops for speed optimization in non-unit case - if (unit) // unit (creature/player) case - { - Creature const* creature = ToCreature(); - for (uint16 index = 0; index < valCount; ++index) - { - 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]; - } - } - } - } - else if (go) // gameobject case - { - for (uint16 index = 0; index < valCount; ++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); - break; - case GAMEOBJECT_TYPE_GENERIC: - if (target->IsGameMaster()) - *data << uint16(0); - else - *data << uint16(GO_DYNFLAG_LO_SPARKLE); - 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); - break; - default: - *data << uint16(0); // unknown, not happen. - break; - } - } - else - *data << uint16(0); // disable quest object - - *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 < valCount; ++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) @@ -1069,33 +802,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); - uint32 valCount = m_valuesCount; - if (GetTypeId() == TYPEID_PLAYER && target != this) - valCount = PLAYER_END_NOT_SELF; - - for (uint16 index = 0; index < valCount; ++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); - uint32 valCount = m_valuesCount; - if (GetTypeId() == TYPEID_PLAYER && target != this) - valCount = PLAYER_END_NOT_SELF; - - for (uint16 index = 0; index < valCount; ++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)); @@ -1546,17 +1252,17 @@ void MovementInfo::OutDebug() TC_LOG_INFO(LOG_FILTER_GENERAL, "flags2 %s (%u)", Movement::MovementFlagsExtra_ToString(flags2).c_str(), flags2); TC_LOG_INFO(LOG_FILTER_GENERAL, "time %u current time %u", time, getMSTime()); TC_LOG_INFO(LOG_FILTER_GENERAL, "position: `%s`", pos.ToString().c_str()); - if (t_guid) + if (transport.guid) { TC_LOG_INFO(LOG_FILTER_GENERAL, "TRANSPORT:"); - TC_LOG_INFO(LOG_FILTER_GENERAL, "guid: " UI64FMTD, t_guid); - TC_LOG_INFO(LOG_FILTER_GENERAL, "position: `%s`", t_pos.ToString().c_str()); - TC_LOG_INFO(LOG_FILTER_GENERAL, "seat: %i", t_seat); - TC_LOG_INFO(LOG_FILTER_GENERAL, "time: %u", t_time); + TC_LOG_INFO(LOG_FILTER_GENERAL, "guid: " UI64FMTD, transport.guid); + TC_LOG_INFO(LOG_FILTER_GENERAL, "position: `%s`", transport.pos.ToString().c_str()); + TC_LOG_INFO(LOG_FILTER_GENERAL, "seat: %i", transport.seat); + TC_LOG_INFO(LOG_FILTER_GENERAL, "time: %u", transport.time); if (flags2 & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT) - TC_LOG_INFO(LOG_FILTER_GENERAL, "time2: %u", t_time2); + TC_LOG_INFO(LOG_FILTER_GENERAL, "time2: %u", transport.time2); if (bits.hasTransportTime3) - TC_LOG_INFO(LOG_FILTER_GENERAL, "time3: %u", t_time3); + TC_LOG_INFO(LOG_FILTER_GENERAL, "time3: %u", transport.time3); } if ((flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (flags2 & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING)) @@ -1564,9 +1270,9 @@ void MovementInfo::OutDebug() if (flags & MOVEMENTFLAG_FALLING || bits.hasFallData) { - TC_LOG_INFO(LOG_FILTER_GENERAL, "fallTime: %u j_zspeed: %f", fallTime, j_zspeed); + TC_LOG_INFO(LOG_FILTER_GENERAL, "fallTime: %u j_zspeed: %f", jump.fallTime, jump.zspeed); if (flags & MOVEMENTFLAG_FALLING) - TC_LOG_INFO(LOG_FILTER_GENERAL, "j_sinAngle: %f j_cosAngle: %f j_xyspeed: %f", j_sinAngle, j_cosAngle, j_xyspeed); + TC_LOG_INFO(LOG_FILTER_GENERAL, "j_sinAngle: %f j_cosAngle: %f j_xyspeed: %f", jump.sinAngle, jump.cosAngle, jump.xyspeed); } if (flags & MOVEMENTFLAG_SPLINE_ELEVATION) @@ -1692,12 +1398,12 @@ bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool if (m_transport && obj->GetTransport() && obj->GetTransport()->GetGUIDLow() == m_transport->GetGUIDLow()) { - float dtx = m_movementInfo.t_pos.m_positionX - obj->m_movementInfo.t_pos.m_positionX; - float dty = m_movementInfo.t_pos.m_positionY - obj->m_movementInfo.t_pos.m_positionY; + float dtx = m_movementInfo.transport.pos.m_positionX - obj->m_movementInfo.transport.pos.m_positionX; + float dty = m_movementInfo.transport.pos.m_positionY - obj->m_movementInfo.transport.pos.m_positionY; float disttsq = dtx * dtx + dty * dty; if (is3D) { - float dtz = m_movementInfo.t_pos.m_positionZ - obj->m_movementInfo.t_pos.m_positionZ; + float dtz = m_movementInfo.transport.pos.m_positionZ - obj->m_movementInfo.transport.pos.m_positionZ; disttsq += dtz * dtz; } return disttsq < (maxdist * maxdist); diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 427d5a91afd..08bc0ae88ae 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -192,7 +192,7 @@ class Object uint32 GetEntry() const { return GetUInt32Value(OBJECT_FIELD_ENTRY); } void SetEntry(uint32 entry) { SetUInt32Value(OBJECT_FIELD_ENTRY, entry); } - void SetObjectScale(float scale) { SetFloatValue(OBJECT_FIELD_SCALE_X, scale); } + virtual void SetObjectScale(float scale) { SetFloatValue(OBJECT_FIELD_SCALE_X, scale); } TypeID GetTypeId() const { return m_objectTypeId; } bool isType(uint16 mask) const { return (mask & m_objectType); } @@ -296,10 +296,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; @@ -469,19 +467,47 @@ struct MovementInfo uint16 flags2; Position pos; uint32 time; + // transport - uint64 t_guid; - Position t_pos; - int8 t_seat; - uint32 t_time; - uint32 t_time2; - uint32 t_time3; + struct TransportInfo + { + void Reset() + { + guid = 0; + pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); + seat = -1; + time = 0; + time2 = 0; + time3 = 0; + } + + uint64 guid; + Position pos; + int8 seat; + uint32 time; + uint32 time2; + uint32 time3; + } transport; + // swimming/flying float pitch; - // falling - uint32 fallTime; + + // jumping - float j_zspeed, j_sinAngle, j_cosAngle, j_xyspeed; + struct JumpInfo + { + void Reset() + { + fallTime = 0; + zspeed = sinAngle = cosAngle = xyspeed = 0.0f; + } + + uint32 fallTime; + + float zspeed, sinAngle, cosAngle, xyspeed; + + } jump; + // spline float splineElevation; @@ -497,12 +523,11 @@ struct MovementInfo } bits; MovementInfo() : - guid(0), flags(0), flags2(0), time(0), t_guid(0), - t_seat(-1), t_time(0), t_time2(0), t_time3(0), pitch(0.0f), fallTime(0), - j_zspeed(0.0f), j_sinAngle(0.0f), j_cosAngle(0.0f), j_xyspeed(0.0f) + guid(0), flags(0), flags2(0), time(0), pitch(0.0f) { pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); - t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); + transport.Reset(); + jump.Reset(); memset(&bits, 0, sizeof(bits)); } @@ -513,18 +538,25 @@ struct MovementInfo bool HasMovementFlag(uint32 flag) const { return flags & flag; } uint16 GetExtraMovementFlags() const { return flags2; } + void SetExtraMovementFlags(uint16 flag) { flags2 = flag; } void AddExtraMovementFlag(uint16 flag) { flags2 |= flag; } + void RemoveExtraMovementFlag(uint16 flag) { flags2 &= ~flag; } bool HasExtraMovementFlag(uint16 flag) const { return flags2 & flag; } - void SetFallTime(uint32 time) { fallTime = time; } + void SetFallTime(uint32 time) { jump.fallTime = time; } + + void ResetTransport() + { + transport.Reset(); + bits.hasTransportTime2 = false; + bits.hasTransportTime3 = false; + } - void ClearTransport() + void ResetJump() { - t_guid = 0; - t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); - t_seat = -1; - t_time = 0; - t_time2 = 0; + jump.Reset(); + bits.hasFallData = false; + bits.hasFallDirection = false; } void OutDebug(); diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 55043537daa..687f1ab40b5 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -2048,6 +2048,6 @@ void Pet::SetDisplayId(uint32 modelId) if (Unit* owner = GetOwner()) if (Player* player = owner->ToPlayer()) - if (owner->ToPlayer()->GetGroup()) - owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MODEL_ID); + if (player->GetGroup()) + player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MODEL_ID); } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 0fb67ea7d07..bc326d7c232 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" @@ -50,8 +49,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" @@ -60,17 +59,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" @@ -2135,7 +2135,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati { m_transport->RemovePassenger(this); m_transport = NULL; - m_movementInfo.ClearTransport(); + m_movementInfo.ResetTransport(); RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :) } @@ -2159,7 +2159,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati { m_transport->RemovePassenger(this); m_transport = NULL; - m_movementInfo.ClearTransport(); + m_movementInfo.ResetTransport(); } } @@ -2317,10 +2317,10 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati if (m_transport) { - final_x += m_movementInfo.t_pos.GetPositionX(); - final_y += m_movementInfo.t_pos.GetPositionY(); - final_z += m_movementInfo.t_pos.GetPositionZ(); - final_o += m_movementInfo.t_pos.GetOrientation(); + final_x += m_movementInfo.transport.pos.GetPositionX(); + final_y += m_movementInfo.transport.pos.GetPositionY(); + final_z += m_movementInfo.transport.pos.GetPositionZ(); + final_o += m_movementInfo.transport.pos.GetOrientation(); } m_teleport_dest = WorldLocation(mapid, final_x, final_y, final_z, final_o); @@ -5137,8 +5137,7 @@ void Player::BuildPlayerRepop() // convert player body to ghost SetHealth(1); - AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING); - SendMovementWaterWalking(); + SetWaterWalking(true); if (!GetSession()->isLogingOut()) SetRooted(false); @@ -5178,8 +5177,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) setDeathState(ALIVE); - RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING); - SendMovementWaterWalking(); + SetWaterWalking(false); SetRooted(false); m_deathTimer = 0; @@ -17244,18 +17242,18 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) // currently we do not support transport in bg else if (transGUID) { - m_movementInfo.t_guid = MAKE_NEW_GUID(transGUID, 0, HIGHGUID_MO_TRANSPORT); - m_movementInfo.t_pos.Relocate(fields[27].GetFloat(), fields[28].GetFloat(), fields[29].GetFloat(), fields[30].GetFloat()); + m_movementInfo.transport.guid = MAKE_NEW_GUID(transGUID, 0, HIGHGUID_MO_TRANSPORT); + m_movementInfo.transport.pos.Relocate(fields[27].GetFloat(), fields[28].GetFloat(), fields[29].GetFloat(), fields[30].GetFloat()); if (!Trinity::IsValidMapCoord( - GetPositionX()+m_movementInfo.t_pos.m_positionX, GetPositionY()+m_movementInfo.t_pos.m_positionY, - GetPositionZ()+m_movementInfo.t_pos.m_positionZ, GetOrientation()+m_movementInfo.t_pos.GetOrientation()) || + GetPositionX()+m_movementInfo.transport.pos.GetPositionX(), GetPositionY()+m_movementInfo.transport.pos.GetPositionY(), + GetPositionZ()+m_movementInfo.transport.pos.GetPositionZ(), GetOrientation()+m_movementInfo.transport.pos.GetOrientation()) || // transport size limited - m_movementInfo.t_pos.m_positionX > 250 || m_movementInfo.t_pos.m_positionY > 250 || m_movementInfo.t_pos.m_positionZ > 250) + m_movementInfo.transport.pos.m_positionX > 250 || m_movementInfo.transport.pos.m_positionY > 250 || m_movementInfo.transport.pos.m_positionZ > 250) { TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player (guidlow %d) have invalid transport coordinates (X: %f Y: %f Z: %f O: %f). Teleport to bind location.", - guid, GetPositionX()+m_movementInfo.t_pos.m_positionX, GetPositionY()+m_movementInfo.t_pos.m_positionY, - GetPositionZ()+m_movementInfo.t_pos.m_positionZ, GetOrientation()+m_movementInfo.t_pos.GetOrientation()); + guid, GetPositionX()+m_movementInfo.transport.pos.GetPositionX(), GetPositionY()+m_movementInfo.transport.pos.GetPositionY(), + GetPositionZ()+m_movementInfo.transport.pos.GetPositionZ(), GetOrientation()+m_movementInfo.transport.pos.GetOrientation()); RelocateToHomebind(); } @@ -22760,14 +22758,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); } @@ -23387,13 +23401,13 @@ void Player::SendAurasForTarget(Unit* target) These movement packets are usually found in SMSG_COMPRESSED_MOVES */ if (target->HasAuraType(SPELL_AURA_FEATHER_FALL)) - target->SendMovementFeatherFall(); + target->SetFeatherFall(true, true); if (target->HasAuraType(SPELL_AURA_WATER_WALK)) - target->SendMovementWaterWalking(); + target->SetWaterWalking(true, true); if (target->HasAuraType(SPELL_AURA_HOVER)) - target->SendMovementHover(); + target->SetHover(true, true); WorldPacket data(SMSG_AURA_UPDATE_ALL); data.append(target->GetPackGUID()); @@ -25319,7 +25333,7 @@ void Player::HandleFall(MovementInfo const& movementInfo) } //Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction - TC_LOG_DEBUG(LOG_FILTER_PLAYER, "FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d", movementInfo.pos.GetPositionZ(), height, GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall); + TC_LOG_DEBUG(LOG_FILTER_PLAYER, "FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d", movementInfo.pos.GetPositionZ(), height, GetPositionZ(), movementInfo.jump.fallTime, height, damage, safe_fall); } } RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LANDING); // No fly zone - Parachute @@ -25659,8 +25673,8 @@ 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) - SetFallInformation(minfo.fallTime, minfo.pos.GetPositionZ()); + if (m_lastFallTime >= minfo.jump.fallTime || m_lastFallZ <= minfo.pos.GetPositionZ() || opcode == MSG_MOVE_FALL_LAND) + SetFallInformation(minfo.jump.fallTime, minfo.pos.GetPositionZ()); } void Player::UnsummonPetTemporaryIfAny() @@ -26829,10 +26843,9 @@ void Player::_SaveInstanceTimeRestrictions(SQLTransaction& trans) bool Player::IsInWhisperWhiteList(uint64 guid) { for (WhisperListContainer::const_iterator itr = WhisperList.begin(); itr != WhisperList.end(); ++itr) - { if (*itr == guid) return true; - } + return false; } @@ -27240,35 +27253,35 @@ void Player::ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::Ext break; case MSETransportPositionX: if (hasTransportData) - data >> mi->t_pos.m_positionX; + data >> mi->transport.pos.m_positionX; break; case MSETransportPositionY: if (hasTransportData) - data >> mi->t_pos.m_positionY; + data >> mi->transport.pos.m_positionY; break; case MSETransportPositionZ: if (hasTransportData) - data >> mi->t_pos.m_positionZ; + data >> mi->transport.pos.m_positionZ; break; case MSETransportOrientation: if (hasTransportData) - mi->t_pos.SetOrientation(data.read<float>()); + mi->transport.pos.SetOrientation(data.read<float>()); break; case MSETransportSeat: if (hasTransportData) - data >> mi->t_seat; + data >> mi->transport.seat; break; case MSETransportTime: if (hasTransportData) - data >> mi->t_time; + data >> mi->transport.time; break; case MSETransportTime2: if (hasTransportData && mi->bits.hasTransportTime2) - data >> mi->t_time2; + data >> mi->transport.time2; break; case MSETransportTime3: if (hasTransportData && mi->bits.hasTransportTime3) - data >> mi->t_time3; + data >> mi->transport.time3; break; case MSEPitch: if (mi->bits.hasPitch) @@ -27276,23 +27289,23 @@ void Player::ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::Ext break; case MSEFallTime: if (mi->bits.hasFallData) - data >> mi->fallTime; + data >> mi->jump.fallTime; break; case MSEFallVerticalSpeed: if (mi->bits.hasFallData) - data >> mi->j_zspeed; + data >> mi->jump.zspeed; break; case MSEFallCosAngle: if (mi->bits.hasFallData && mi->bits.hasFallDirection) - data >> mi->j_cosAngle; + data >> mi->jump.cosAngle; break; case MSEFallSinAngle: if (mi->bits.hasFallData && mi->bits.hasFallDirection) - data >> mi->j_sinAngle; + data >> mi->jump.sinAngle; break; case MSEFallHorizontalSpeed: if (mi->bits.hasFallData && mi->bits.hasFallDirection) - data >> mi->j_xyspeed; + data >> mi->jump.xyspeed; break; case MSESplineElevation: if (mi->bits.hasSplineElevation) @@ -27315,9 +27328,9 @@ void Player::ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::Ext } mi->guid = guid; - mi->t_guid = tguid; + mi->transport.guid = tguid; - if (hasTransportData && mi->pos.m_positionX != mi->t_pos.m_positionX) + if (hasTransportData && mi->pos.m_positionX != mi->transport.pos.m_positionX) if (GetTransport()) GetTransport()->UpdatePosition(mi); diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index 5361eaff8a2..3b1e031dbb6 100644 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -634,8 +634,8 @@ uint32 Transport::AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y, } creature->SetTransport(this); - creature->m_movementInfo.t_guid = GetGUID(); - creature->m_movementInfo.t_pos.Relocate(x, y, z, o); + creature->m_movementInfo.transport.guid = GetGUID(); + creature->m_movementInfo.transport.pos.Relocate(x, y, z, o); if (anim) creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, anim); @@ -647,7 +647,7 @@ uint32 Transport::AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y, o + GetOrientation()); creature->SetHomePosition(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation()); - creature->SetTransportHomePosition(creature->m_movementInfo.t_pos); + creature->SetTransportHomePosition(creature->m_movementInfo.transport.pos); if (!creature->IsPositionValid()) { @@ -674,10 +674,10 @@ uint32 Transport::AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y, void Transport::UpdatePosition(MovementInfo* mi) { - float transport_o = mi->pos.GetOrientation() - mi->t_pos.GetOrientation(); - float transport_x = mi->pos.m_positionX - (mi->t_pos.m_positionX * std::cos(transport_o) - mi->t_pos.m_positionY * std::sin(transport_o)); - float transport_y = mi->pos.m_positionY - (mi->t_pos.m_positionY * std::cos(transport_o) + mi->t_pos.m_positionX * std::sin(transport_o)); - float transport_z = mi->pos.m_positionZ - mi->t_pos.m_positionZ; + float transport_o = mi->pos.GetOrientation() - mi->transport.pos.GetOrientation(); + float transport_x = mi->pos.m_positionX - (mi->transport.pos.m_positionX * std::cos(transport_o) - mi->transport.pos.m_positionY * std::sin(transport_o)); + float transport_y = mi->pos.m_positionY - (mi->transport.pos.m_positionY * std::cos(transport_o) + mi->transport.pos.m_positionX * std::sin(transport_o)); + float transport_z = mi->pos.m_positionZ - mi->transport.pos.m_positionZ; Relocate(transport_x, transport_y, transport_z, transport_o); UpdatePassengerPositions(); @@ -690,7 +690,7 @@ void Transport::UpdatePassengerPositions() Creature* npc = *itr; float x, y, z, o; - npc->m_movementInfo.t_pos.GetPosition(x, y, z, o); + npc->m_movementInfo.transport.pos.GetPosition(x, y, z, o); CalculatePassengerPosition(x, y, z, &o); GetMap()->CreatureRelocation(npc, x, y, z, o, false); npc->GetTransportHomePosition(x, y, z, o); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index a6084a62fdb..9ca21adb157 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -409,7 +409,7 @@ void Unit::UpdateSplinePosition() Movement::Location loc = movespline->ComputePosition(); if (GetTransGUID()) { - Position& pos = m_movementInfo.t_pos; + Position& pos = m_movementInfo.transport.pos; pos.m_positionX = loc.x; pos.m_positionY = loc.y; pos.m_positionZ = loc.z; @@ -8594,10 +8594,7 @@ void Unit::SetCharm(Unit* charm, bool apply) _isWalkingBeforeCharm = charm->IsWalking(); if (_isWalkingBeforeCharm) - { charm->SetWalk(false); - charm->SendMovementWalkMode(); - } m_Controlled.insert(charm); } @@ -8632,10 +8629,7 @@ void Unit::SetCharm(Unit* charm, bool apply) } if (charm->IsWalking() != _isWalkingBeforeCharm) - { charm->SetWalk(_isWalkingBeforeCharm); - charm->SendMovementWalkMode(); - } if (charm->GetTypeId() == TYPEID_PLAYER || !charm->ToCreature()->HasUnitTypeMask(UNIT_MASK_MINION) @@ -16008,14 +16002,6 @@ bool Unit::IsFalling() const return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR) || movespline->isFalling(); } -void Unit::SetCanFly(bool apply) -{ - if (apply) - AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY); - else - RemoveUnitMovementFlag(MOVEMENTFLAG_CAN_FLY); -} - void Unit::NearTeleportTo(float x, float y, float z, float orientation, bool casting /*= false*/) { DisableSpline(); @@ -16218,11 +16204,11 @@ void Unit::WriteMovementInfo(WorldPacket& data, Movement::ExtraMovementStatusEle break; case MSETransportTime2: if (hasTransportData && hasTransportTime2) - data << mi.t_time2; + data << mi.transport.time2; break; case MSETransportTime3: if (hasTransportData && hasTransportTime3) - data << mi.t_time3; + data << mi.transport.time3; break; case MSEPitch: if (hasPitch) @@ -16230,23 +16216,23 @@ void Unit::WriteMovementInfo(WorldPacket& data, Movement::ExtraMovementStatusEle break; case MSEFallTime: if (hasFallData) - data << mi.fallTime; + data << mi.jump.fallTime; break; case MSEFallVerticalSpeed: if (hasFallData) - data << mi.j_zspeed; + data << mi.jump.zspeed; break; case MSEFallCosAngle: if (hasFallData && hasFallDirection) - data << mi.j_cosAngle; + data << mi.jump.cosAngle; break; case MSEFallSinAngle: if (hasFallData && hasFallDirection) - data << mi.j_sinAngle; + data << mi.jump.sinAngle; break; case MSEFallHorizontalSpeed: if (hasFallData && hasFallDirection) - data << mi.j_xyspeed; + data << mi.jump.xyspeed; break; case MSESplineElevation: if (hasSplineElevation) @@ -16700,103 +16686,146 @@ bool Unit::SetWalk(bool enable) else RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); + ///@ TODO: Find proper opcode for walk mode setting in player mind controlling a player case + if (enable) + Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_WALK_MODE, SMSG_SPLINE_MOVE_SET_WALK_MODE).Send(); + else + Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_RUN_MODE, SMSG_SPLINE_MOVE_SET_WALK_MODE).Send(); + return true; } -bool Unit::SetDisableGravity(bool disable, bool /*packetOnly = false*/) +bool Unit::SetDisableGravity(bool disable, bool packetOnly /*= false*/) { - if (disable == IsLevitating()) - return false; + if (!packetOnly) + { + if (disable == IsLevitating()) + return false; + + if (disable) + AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY); + else + RemoveUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY); + } if (disable) - AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY); + Movement::PacketSender(this, SMSG_SPLINE_MOVE_GRAVITY_DISABLE, SMSG_MOVE_GRAVITY_DISABLE).Send(); else - RemoveUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY); + Movement::PacketSender(this, SMSG_SPLINE_MOVE_GRAVITY_ENABLE, SMSG_MOVE_GRAVITY_ENABLE).Send(); return true; } -bool Unit::SetHover(bool enable) +bool Unit::SetSwim(bool enable) { - if (enable == HasUnitMovementFlag(MOVEMENTFLAG_HOVER)) + if (enable == HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING)) return false; if (enable) - { - //! No need to check height on ascent - AddUnitMovementFlag(MOVEMENTFLAG_HOVER); - if (float hh = GetFloatValue(UNIT_FIELD_HOVERHEIGHT)) - UpdateHeight(GetPositionZ() + hh); - } + AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING); else - { - RemoveUnitMovementFlag(MOVEMENTFLAG_HOVER); - if (float hh = GetFloatValue(UNIT_FIELD_HOVERHEIGHT)) - { - float newZ = GetPositionZ() - hh; - UpdateAllowedPositionZ(GetPositionX(), GetPositionY(), newZ); - UpdateHeight(newZ); - } - } + RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING); + + if (enable) + Movement::PacketSender(this, SMSG_SPLINE_MOVE_START_SWIM, NULL_OPCODE).Send(); + else + Movement::PacketSender(this, SMSG_SPLINE_MOVE_STOP_SWIM, NULL_OPCODE).Send(); return true; } -void Unit::SendMovementHover() +bool Unit::SetCanFly(bool enable) { - if (HasUnitMovementFlag(MOVEMENTFLAG_HOVER)) - Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_HOVER, SMSG_MOVE_SET_HOVER).Send(); + if (enable == HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY)) + return false; + + if (enable) + AddUnitMovementFlag(MOVEMENTFLAG_CAN_FLY); else - Movement::PacketSender(this, SMSG_SPLINE_MOVE_UNSET_HOVER, SMSG_MOVE_UNSET_HOVER).Send(); + RemoveUnitMovementFlag(MOVEMENTFLAG_CAN_FLY); + + if (enable) + Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_FLYING, SMSG_MOVE_SET_CAN_FLY).Send(); + else + Movement::PacketSender(this, SMSG_SPLINE_MOVE_UNSET_FLYING, SMSG_MOVE_UNSET_CAN_FLY).Send(); + + return true; } -void Unit::SendMovementWaterWalking() +bool Unit::SetWaterWalking(bool enable, bool packetOnly /*= false */) { - if (HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING)) + if (!packetOnly) + { + if (enable == HasUnitMovementFlag(MOVEMENTFLAG_WATERWALKING)) + return false; + + if (enable) + AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING); + else + RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING); + } + + if (enable) Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_WATER_WALK, SMSG_MOVE_WATER_WALK).Send(); else Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_LAND_WALK, SMSG_MOVE_LAND_WALK).Send(); + + return true; } -void Unit::SendMovementFeatherFall() +bool Unit::SetFeatherFall(bool enable, bool packetOnly /*= false */) { - if (HasUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW)) + if (!packetOnly) + { + if (enable == HasUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW)) + return false; + + if (enable) + AddUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW); + else + RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW); + } + + if (enable) Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_FEATHER_FALL, SMSG_MOVE_FEATHER_FALL).Send(); else Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_NORMAL_FALL, SMSG_MOVE_NORMAL_FALL).Send(); -} -void Unit::SendMovementCanFlyChange() -{ - if (HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY)) - Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_FLYING, SMSG_MOVE_SET_CAN_FLY).Send(); - else - Movement::PacketSender(this, SMSG_SPLINE_MOVE_UNSET_FLYING, SMSG_MOVE_UNSET_CAN_FLY).Send(); + return true; } -void Unit::SendMovementDisableGravity() +bool Unit::SetHover(bool enable, bool packetOnly /*= false*/) { - if (HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY)) - Movement::PacketSender(this, SMSG_SPLINE_MOVE_GRAVITY_DISABLE, SMSG_MOVE_GRAVITY_DISABLE).Send(); - else - Movement::PacketSender(this, SMSG_SPLINE_MOVE_GRAVITY_ENABLE, SMSG_MOVE_GRAVITY_ENABLE).Send(); -} + if (!packetOnly) + { + if (enable == HasUnitMovementFlag(MOVEMENTFLAG_HOVER)) + return false; -void Unit::SendMovementWalkMode() -{ - ///@ TODO: Find proper opcode for walk mode setting in player mind controlling a player case - if (HasUnitMovementFlag(MOVEMENTFLAG_WALKING)) - Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_WALK_MODE, SMSG_SPLINE_MOVE_SET_WALK_MODE).Send(); - else - Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_RUN_MODE, SMSG_SPLINE_MOVE_SET_WALK_MODE).Send(); -} + if (enable) + { + //! No need to check height on ascent + AddUnitMovementFlag(MOVEMENTFLAG_HOVER); + if (float hh = GetFloatValue(UNIT_FIELD_HOVERHEIGHT)) + UpdateHeight(GetPositionZ() + hh); + } + else + { + RemoveUnitMovementFlag(MOVEMENTFLAG_HOVER); + if (float hh = GetFloatValue(UNIT_FIELD_HOVERHEIGHT)) + { + float newZ = GetPositionZ() - hh; + UpdateAllowedPositionZ(GetPositionX(), GetPositionY(), newZ); + UpdateHeight(newZ); + } + } + } -void Unit::SendMovementSwimming() -{ - if (HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING)) - Movement::PacketSender(this, SMSG_SPLINE_MOVE_START_SWIM, NULL_OPCODE).Send(); + if (enable) + Movement::PacketSender(this, SMSG_SPLINE_MOVE_SET_HOVER, SMSG_MOVE_SET_HOVER).Send(); else - Movement::PacketSender(this, SMSG_SPLINE_MOVE_STOP_SWIM, NULL_OPCODE).Send(); + Movement::PacketSender(this, SMSG_SPLINE_MOVE_UNSET_HOVER, SMSG_MOVE_UNSET_HOVER).Send(); + + return true; } void Unit::SendSetPlayHoverAnim(bool enable) @@ -16874,3 +16903,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 3e8abdd404b..95aaf57a84f 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1597,27 +1597,19 @@ class Unit : public WorldObject void MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath = false, bool forceDestination = false); - /*! These methods send the same packet to the client in apply and unapply case. - The client-side interpretation of this packet depends on the presence of relevant movementflags - which are sent with movementinfo. Furthermore, these packets are broadcast to nearby players as well - as the current unit. - */ - void SendMovementHover(); - void SendMovementFeatherFall(); - void SendMovementWaterWalking(); - void SendMovementCanFlyChange(); - void SendMovementDisableGravity(); - void SendMovementWalkMode(); - void SendMovementSwimming(); void SendSetPlayHoverAnim(bool enable); void SendMovementSetSplineAnim(Movement::AnimType anim); - bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);} - bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING);} + bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY); } + bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING); } virtual bool SetWalk(bool enable); virtual bool SetDisableGravity(bool disable, bool packetOnly = false); - virtual bool SetHover(bool enable); + virtual bool SetSwim(bool enable); + virtual bool SetCanFly(bool enable); + virtual bool SetWaterWalking(bool enable, bool packetOnly = false); + virtual bool SetFeatherFall(bool enable, bool packetOnly = false); + virtual bool SetHover(bool enable, bool packetOnly = false); void SetInFront(WorldObject const* target); void SetFacingTo(float ori); @@ -2026,17 +2018,17 @@ class Unit : public WorldObject bool IsStopped() const { return !(HasUnitState(UNIT_STATE_MOVING)); } void StopMoving(); - void AddUnitMovementFlag(uint32 f) { m_movementInfo.flags |= f; } - void RemoveUnitMovementFlag(uint32 f) { m_movementInfo.flags &= ~f; } - bool HasUnitMovementFlag(uint32 f) const { return (m_movementInfo.flags & f) == f; } - uint32 GetUnitMovementFlags() const { return m_movementInfo.flags; } - void SetUnitMovementFlags(uint32 f) { m_movementInfo.flags = f; } - - void AddExtraUnitMovementFlag(uint16 f) { m_movementInfo.flags2 |= f; } - void RemoveExtraUnitMovementFlag(uint16 f) { m_movementInfo.flags2 &= ~f; } - uint16 HasExtraUnitMovementFlag(uint16 f) const { return m_movementInfo.flags2 & f; } - uint16 GetExtraUnitMovementFlags() const { return m_movementInfo.flags2; } - void SetExtraUnitMovementFlags(uint16 f) { m_movementInfo.flags2 = f; } + void AddUnitMovementFlag(uint32 f) { m_movementInfo.AddMovementFlag(f); } + void RemoveUnitMovementFlag(uint32 f) { m_movementInfo.RemoveMovementFlag(f); } + bool HasUnitMovementFlag(uint32 f) const { return m_movementInfo.HasMovementFlag(f); } + uint32 GetUnitMovementFlags() const { return m_movementInfo.GetMovementFlags(); } + void SetUnitMovementFlags(uint32 f) { m_movementInfo.SetMovementFlags(f); } + + void AddExtraUnitMovementFlag(uint16 f) { m_movementInfo.AddExtraMovementFlag(f); } + void RemoveExtraUnitMovementFlag(uint16 f) { m_movementInfo.RemoveExtraMovementFlag(f); } + uint16 HasExtraUnitMovementFlag(uint16 f) const { return m_movementInfo.HasExtraMovementFlag(f); } + uint16 GetExtraUnitMovementFlags() const { return m_movementInfo.GetExtraMovementFlags(); } + void SetExtraUnitMovementFlags(uint16 f) { m_movementInfo.SetExtraMovementFlags(f); } bool IsSplineEnabled() const; float GetPositionZMinusOffset() const; @@ -2094,12 +2086,12 @@ class Unit : public WorldObject bool IsOnVehicle(const Unit* vehicle) const; Unit* GetVehicleBase() const; Creature* GetVehicleCreatureBase() const; - float GetTransOffsetX() const { return m_movementInfo.t_pos.GetPositionX(); } - float GetTransOffsetY() const { return m_movementInfo.t_pos.GetPositionY(); } - float GetTransOffsetZ() const { return m_movementInfo.t_pos.GetPositionZ(); } - float GetTransOffsetO() const { return m_movementInfo.t_pos.GetOrientation(); } - uint32 GetTransTime() const { return m_movementInfo.t_time; } - int8 GetTransSeat() const { return m_movementInfo.t_seat; } + float GetTransOffsetX() const { return m_movementInfo.transport.pos.GetPositionX(); } + float GetTransOffsetY() const { return m_movementInfo.transport.pos.GetPositionY(); } + float GetTransOffsetZ() const { return m_movementInfo.transport.pos.GetPositionZ(); } + float GetTransOffsetO() const { return m_movementInfo.transport.pos.GetOrientation(); } + uint32 GetTransTime() const { return m_movementInfo.transport.time; } + int8 GetTransSeat() const { return m_movementInfo.transport.seat; } uint64 GetTransGUID() const; /// Returns the transport this unit is on directly (if on vehicle and transport, return vehicle) TransportBase* GetDirectTransport() const; @@ -2122,7 +2114,6 @@ class Unit : public WorldObject virtual bool CanFly() const = 0; bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_DISABLE_GRAVITY); } bool IsFalling() const; - void SetCanFly(bool apply); void RewardRage(uint32 baseRage, bool attacker); @@ -2157,6 +2148,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/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 797430683f4..28429387400 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -517,7 +517,7 @@ Vehicle* Vehicle::RemovePassenger(Unit* unit) _me->RemoveCharmedBy(unit); if (_me->IsInWorld()) - unit->m_movementInfo.ClearTransport(); + unit->m_movementInfo.ResetTransport(); // only for flyable vehicles if (unit->IsFlying()) @@ -554,7 +554,7 @@ void Vehicle::RelocatePassengers() ASSERT(passenger->IsInWorld()); float px, py, pz, po; - passenger->m_movementInfo.t_pos.GetPosition(px, py, pz, po); + passenger->m_movementInfo.transport.pos.GetPosition(px, py, pz, po); CalculatePassengerPosition(px, py, pz, &po); passenger->UpdatePosition(px, py, pz, po); @@ -837,10 +837,10 @@ bool VehicleJoinEvent::Execute(uint64, uint32) Passenger->AddUnitState(UNIT_STATE_ONVEHICLE); VehicleSeatEntry const* veSeat = Seat->second.SeatInfo; - Passenger->m_movementInfo.t_pos.Relocate(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); - Passenger->m_movementInfo.t_time = 0; // 1 for player - Passenger->m_movementInfo.t_seat = Seat->first; - Passenger->m_movementInfo.t_guid = Target->GetBase()->GetGUID(); + Passenger->m_movementInfo.transport.pos.Relocate(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); + Passenger->m_movementInfo.transport.time = 0; + Passenger->m_movementInfo.transport.seat = Seat->first; + Passenger->m_movementInfo.transport.guid = Target->GetBase()->GetGUID(); if (Target->GetBase()->GetTypeId() == TYPEID_UNIT && Passenger->GetTypeId() == TYPEID_PLAYER && Seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL) diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h index 0cb2f32f621..1e4a9ca83b4 100644 --- a/src/server/game/Grids/GridDefines.h +++ b/src/server/game/Grids/GridDefines.h @@ -36,7 +36,7 @@ class AreaTrigger; #define MAX_NUMBER_OF_GRIDS 64 -#define SIZE_OF_GRIDS 533.33333f +#define SIZE_OF_GRIDS 533.3333f #define CENTER_GRID_ID (MAX_NUMBER_OF_GRIDS/2) #define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2) diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index bb7d4b1052f..6bd325f9114 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -1053,8 +1053,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) - pCurrChar->AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING); - pCurrChar->SendMovementWaterWalking(); + pCurrChar->SetWaterWalking(true); } pCurrChar->ContinueTaxiFlight(); diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index d4bfc235595..79cb03c0ab3 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -1154,7 +1154,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) { if (Vehicle* veh = player->GetVehicle()) - *data << uint32(veh->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat]); + *data << uint32(veh->GetVehicleInfo()->m_seatID[player->m_movementInfo.transport.seat]); else *data << uint32(0); @@ -1335,7 +1335,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData) data.put<uint64>(maskPos, petAuraMask); // GROUP_UPDATE_FLAG_PET_AURAS if (updateFlags & GROUP_UPDATE_FLAG_VEHICLE_SEAT) - data << uint32(player->GetVehicle()->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat]); + data << uint32(player->GetVehicle()->GetVehicleInfo()->m_seatID[player->m_movementInfo.transport.seat]); SendPacket(&data); } diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index f45efe0b47e..cad1ef77daa 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -292,18 +292,18 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket) } /* handle special cases */ - if (movementInfo.t_guid) + if (movementInfo.transport.guid) { // transports size limited // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) - if (movementInfo.t_pos.GetPositionX() > 50 || movementInfo.t_pos.GetPositionY() > 50 || movementInfo.t_pos.GetPositionZ() > 50) + if (movementInfo.transport.pos.GetPositionX() > 50 || movementInfo.transport.pos.GetPositionY() > 50 || movementInfo.transport.pos.GetPositionZ() > 50) { recvPacket.rfinish(); // prevent warnings spam return; } - if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.t_pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.t_pos.GetPositionY(), - movementInfo.pos.GetPositionZ() + movementInfo.t_pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.t_pos.GetOrientation())) + if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.transport.pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.transport.pos.GetPositionY(), + movementInfo.pos.GetPositionZ() + movementInfo.transport.pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.transport.pos.GetOrientation())) { recvPacket.rfinish(); // prevent warnings spam return; @@ -317,7 +317,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket) // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just dismount if the guid can be found in the transport list for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) { - if ((*iter)->GetGUID() == movementInfo.t_guid) + if ((*iter)->GetGUID() == movementInfo.transport.guid) { plrMover->m_transport = *iter; (*iter)->AddPassenger(plrMover); @@ -325,13 +325,13 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket) } } } - else if (plrMover->GetTransport()->GetGUID() != movementInfo.t_guid) + else if (plrMover->GetTransport()->GetGUID() != movementInfo.transport.guid) { bool foundNewTransport = false; plrMover->m_transport->RemovePassenger(plrMover); for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) { - if ((*iter)->GetGUID() == movementInfo.t_guid) + if ((*iter)->GetGUID() == movementInfo.transport.guid) { foundNewTransport = true; plrMover->m_transport = *iter; @@ -343,25 +343,23 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket) 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.ResetTransport(); } } } if (!mover->GetTransport() && !mover->GetVehicle()) { - GameObject* go = mover->GetMap()->GetGameObject(movementInfo.t_guid); + GameObject* go = mover->GetMap()->GetGameObject(movementInfo.transport.guid); if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT) - movementInfo.t_guid = 0; + movementInfo.transport.guid = 0; } } else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave { plrMover->m_transport->RemovePassenger(plrMover); plrMover->m_transport = NULL; - movementInfo.ClearTransport(); + movementInfo.ResetTransport(); } // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 57faa5f3ebc..5ca07c095aa 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -4047,7 +4047,7 @@ enum PartyResult }; const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP' -#define MMAP_VERSION 3 +#define MMAP_VERSION 4 struct MmapTileHeader { diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 6ef93402606..ed30b59f0ec 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -97,7 +97,7 @@ dtPolyRef PathGenerator::GetPathPolyByPosition(dtPolyRef const* polyPath, uint32 for (uint32 i = 0; i < polyPathSize; ++i) { float closestPoint[VERTEX_SIZE]; - if (DT_SUCCESS != _navMeshQuery->closestPointOnPoly(polyPath[i], point, closestPoint)) + if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(polyPath[i], point, closestPoint))) continue; float d = dtVdist2DSqr(point, closestPoint); @@ -132,8 +132,7 @@ dtPolyRef PathGenerator::GetPolyByLocation(float const* point, float* distance) // first try with low search box float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; // bounds of poly search area float closestPoint[VERTEX_SIZE] = {0.0f, 0.0f, 0.0f}; - dtStatus result = _navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint); - if (DT_SUCCESS == result && polyRef != INVALID_POLYREF) + if (dtStatusSucceed(_navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint)) && polyRef != INVALID_POLYREF) { *distance = dtVdist(closestPoint, point); return polyRef; @@ -141,9 +140,10 @@ dtPolyRef PathGenerator::GetPolyByLocation(float const* point, float* distance) // still nothing .. // try with bigger search box - extents[1] = 200.0f; - result = _navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint); - if (DT_SUCCESS == result && polyRef != INVALID_POLYREF) + // Note that the extent should not overlap more than 128 polygons in the navmesh (see dtNavMeshQuery::findNearestPoly) + extents[1] = 50.0f; + + if (dtStatusSucceed(_navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint)) && polyRef != INVALID_POLYREF) { *distance = dtVdist(closestPoint, point); return polyRef; @@ -228,7 +228,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con { float closestPoint[VERTEX_SIZE]; // we may want to use closestPointOnPolyBoundary instead - if (DT_SUCCESS == _navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint)) + if (dtStatusSucceed(_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint))) { dtVcopy(endPoint, closestPoint); SetActualEndPosition(G3D::Vector3(endPoint[2], endPoint[0], endPoint[1])); @@ -319,13 +319,13 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con // we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data float suffixEndPoint[VERTEX_SIZE]; - if (DT_SUCCESS != _navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) + if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint))) { // we can hit offmesh connection as last poly - closestPointOnPoly() don't like that // try to recover by using prev polyref --prefixPolyLength; suffixStartPoly = _pathPolyRefs[prefixPolyLength-1]; - if (DT_SUCCESS != _navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) + if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint))) { // suffixStartPoly is still invalid, error state BuildShortcut(); @@ -346,7 +346,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con (int*)&suffixPolyLength, MAX_PATH_LENGTH-prefixPolyLength); // max number of polygons in output path - if (!suffixPolyLength || dtResult != DT_SUCCESS) + if (!suffixPolyLength || dtStatusFailed(dtResult)) { // this is probably an error state, but we'll leave it // and hopefully recover on the next Update @@ -380,7 +380,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con (int*)&_polyLength, MAX_PATH_LENGTH); // max number of polygons in output path - if (!_polyLength || dtResult != DT_SUCCESS) + if (!_polyLength || dtStatusFailed(dtResult)) { // only happens if we passed bad data to findPath(), or navmesh is messed up TC_LOG_ERROR(LOG_FILTER_MAPS, "%u's Path Build failed: 0 length path", _sourceUnit->GetGUIDLow()); @@ -430,7 +430,7 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin _pointPathLimit); // maximum number of points } - if (pointCount < 2 || dtResult != DT_SUCCESS) + if (pointCount < 2 || dtStatusFailed(dtResult)) { // only happens if pass bad data to findStraightPath or navmesh is broken // single point paths can be generated here @@ -577,7 +577,7 @@ bool PathGenerator::HaveTile(const G3D::Vector3& p) const if (tx < 0 || ty < 0) return false; - return (_navMesh->getTileAt(tx, ty) != NULL); + return (_navMesh->getTileAt(tx, ty, 0) != NULL); } uint32 PathGenerator::FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited) @@ -637,7 +637,7 @@ bool PathGenerator::GetSteerTarget(float const* startPos, float const* endPos, uint32 nsteerPath = 0; dtStatus dtResult = _navMeshQuery->findStraightPath(startPos, endPos, path, pathSize, steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS); - if (!nsteerPath || DT_SUCCESS != dtResult) + if (!nsteerPath || dtStatusFailed(dtResult)) return false; // Find vertex far enough to steer to. @@ -674,10 +674,10 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo uint32 npolys = polyPathSize; float iterPos[VERTEX_SIZE], targetPos[VERTEX_SIZE]; - if (DT_SUCCESS != _navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos)) + if (dtStatusFailed(_navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos))) return DT_FAILURE; - if (DT_SUCCESS != _navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos)) + if (dtStatusFailed(_navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos))) return DT_FAILURE; dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); @@ -756,7 +756,7 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo // Handle the connection. float startPos[VERTEX_SIZE], endPos[VERTEX_SIZE]; - if (DT_SUCCESS == _navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos)) + if (dtStatusSucceed(_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos))) { if (nsmoothPath < maxSmoothPathSize) { diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp index 02be702d3c2..1a35271c8c6 100644 --- a/src/server/game/Movement/Spline/MoveSpline.cpp +++ b/src/server/game/Movement/Spline/MoveSpline.cpp @@ -23,10 +23,6 @@ namespace Movement{ -extern float computeFallTime(float path_length, bool isSafeFall); -extern float computeFallElevation(float time_passed, bool isSafeFall, float start_velocy); -extern float computeFallElevation(float time_passed); - Location MoveSpline::ComputePosition() const { ASSERT(Initialized()); @@ -84,12 +80,9 @@ void MoveSpline::computeParabolicElevation(float& el) const void MoveSpline::computeFallElevation(float& el) const { - float z_now = spline.getPoint(spline.first()).z - Movement::computeFallElevation(MSToSec(time_passed)); + float z_now = spline.getPoint(spline.first()).z - Movement::computeFallElevation(MSToSec(time_passed), false); float final_z = FinalDestination().z; - if (z_now < final_z) - el = final_z; - else - el = z_now; + el = std::max(z_now, final_z); } inline uint32 computeDuration(float length, float velocity) @@ -160,7 +153,7 @@ void MoveSpline::init_spline(const MoveSplineInitArgs& args) point_Idx = spline.first(); } -void MoveSpline::Initialize(const MoveSplineInitArgs& args) +void MoveSpline::Initialize(MoveSplineInitArgs const& args) { splineflags = args.flags; facing = args.facing; @@ -168,7 +161,6 @@ void MoveSpline::Initialize(const MoveSplineInitArgs& args) point_Idx_offset = args.path_Idx_offset; initialOrientation = args.initialOrientation; - onTransport = false; time_passed = 0; vertical_acceleration = 0.f; effect_start_time = 0; @@ -196,7 +188,8 @@ void MoveSpline::Initialize(const MoveSplineInitArgs& args) } MoveSpline::MoveSpline() : m_Id(0), time_passed(0), - vertical_acceleration(0.f), initialOrientation(0.f), effect_start_time(0), point_Idx(0), point_Idx_offset(0) + vertical_acceleration(0.f), initialOrientation(0.f), effect_start_time(0), point_Idx(0), point_Idx_offset(0), + onTransport(false) { splineflags.done = true; } diff --git a/src/server/game/Movement/Spline/MoveSpline.h b/src/server/game/Movement/Spline/MoveSpline.h index a76c552079b..75ea89bee81 100644 --- a/src/server/game/Movement/Spline/MoveSpline.h +++ b/src/server/game/Movement/Spline/MoveSpline.h @@ -49,6 +49,7 @@ namespace Movement Result_NextSegment = 0x08 }; friend class PacketBuilder; + protected: MySpline spline; @@ -69,30 +70,30 @@ namespace Movement int32 point_Idx_offset; void init_spline(const MoveSplineInitArgs& args); - protected: - const MySpline::ControlArray& getPath() const { return spline.getPoints(); } + protected: + MySpline::ControlArray const& getPath() const { return spline.getPoints(); } void computeParabolicElevation(float& el) const; void computeFallElevation(float& el) const; UpdateResult _updateState(int32& ms_time_diff); - int32 next_timestamp() const { return spline.length(point_Idx+1); } - int32 segment_time_elapsed() const { return next_timestamp()-time_passed; } + int32 next_timestamp() const { return spline.length(point_Idx + 1); } + int32 segment_time_elapsed() const { return next_timestamp() - time_passed; } int32 timeElapsed() const { return Duration() - time_passed; } int32 timePassed() const { return time_passed; } public: int32 Duration() const { return spline.length(); } - const MySpline& _Spline() const { return spline; } + MySpline const& _Spline() const { return spline; } int32 _currentSplineIdx() const { return point_Idx; } void _Finalize(); - void _Interrupt() { splineflags.done = true;} + void _Interrupt() { splineflags.done = true; } public: void Initialize(const MoveSplineInitArgs&); bool Initialized() const { return !spline.empty(); } - explicit MoveSpline(); + MoveSpline(); template<class UpdateHandler> void updateState(int32 difftime, UpdateHandler& handler) @@ -116,8 +117,8 @@ namespace Movement bool Finalized() const { return splineflags.done; } bool isCyclic() const { return splineflags.cyclic; } bool isFalling() const { return splineflags.falling; } - const Vector3 FinalDestination() const { return Initialized() ? spline.getPoint(spline.last()) : Vector3(); } - const Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx+1) : Vector3(); } + Vector3 FinalDestination() const { return Initialized() ? spline.getPoint(spline.last()) : Vector3(); } + Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx + 1) : Vector3(); } int32 currentPathIdx() const; bool onTransport; diff --git a/src/server/game/Movement/Spline/MoveSplineFlag.h b/src/server/game/Movement/Spline/MoveSplineFlag.h index 08e73c0344b..f86ce6431ed 100644 --- a/src/server/game/Movement/Spline/MoveSplineFlag.h +++ b/src/server/game/Movement/Spline/MoveSplineFlag.h @@ -104,7 +104,8 @@ namespace Movement void EnableAnimation(uint8 anim) { raw() = (raw() & ~(Mask_Animations | Falling | Parabolic | FallingSlow)) | Animation | (anim & Mask_Animations); } void EnableParabolic() { raw() = (raw() & ~(Mask_Animations | Falling | Animation | FallingSlow)) | Parabolic; } - void EnableFalling() { raw() = (raw() & ~(Mask_Animations | Parabolic | Animation)) | Falling; } + void EnableFlying() { raw() = (raw() & ~(Falling)) | Flying; } + void EnableFalling() { raw() = (raw() & ~(Mask_Animations | Parabolic | Animation | Flying)) | Falling; } void EnableCatmullRom() { raw() = (raw() & ~SmoothGroundPath) | Catmullrom; } void EnableFacingPoint() { raw() = (raw() & ~Mask_Final_Facing) | Final_Point; } void EnableFacingAngle() { raw() = (raw() & ~Mask_Final_Facing) | Final_Angle; } diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index 9cc1dbb3f43..65af02360e6 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -98,6 +98,8 @@ namespace Movement uint32 moveFlagsForSpeed = moveFlags; if (args.flags.walkmode) moveFlagsForSpeed |= MOVEMENTFLAG_WALKING; + else + moveFlagsForSpeed &= ~MOVEMENTFLAG_WALKING; args.velocity = unit->GetSpeed(SelectSpeedType(moveFlagsForSpeed)); } diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h index 1eaf1011a2c..c968f660f58 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.h +++ b/src/server/game/Movement/Spline/MoveSplineInit.h @@ -157,7 +157,7 @@ namespace Movement Unit* unit; }; - inline void MoveSplineInit::SetFly() { args.flags.flying = true; } + inline void MoveSplineInit::SetFly() { args.flags.EnableFlying(); } inline void MoveSplineInit::SetWalk(bool enable) { args.flags.walkmode = enable; } inline void MoveSplineInit::SetSmooth() { args.flags.EnableCatmullRom(); } inline void MoveSplineInit::SetUncompressed() { args.flags.uncompressedPath = true; } diff --git a/src/server/game/Movement/Spline/MoveSplineInitArgs.h b/src/server/game/Movement/Spline/MoveSplineInitArgs.h index 4a086094c3f..474541cbf15 100644 --- a/src/server/game/Movement/Spline/MoveSplineInitArgs.h +++ b/src/server/game/Movement/Spline/MoveSplineInitArgs.h @@ -30,9 +30,9 @@ namespace Movement union FacingInfo { - struct{ + struct { float x, y, z; - }f; + } f; uint64 target; float angle; @@ -43,8 +43,8 @@ namespace Movement struct MoveSplineInitArgs { - MoveSplineInitArgs(size_t path_capacity = 16) : path_Idx_offset(0), - velocity(0.f), parabolic_amplitude(0.f), time_perc(0.f), splineId(0), initialOrientation(0.f), + MoveSplineInitArgs(size_t path_capacity = 16) : path_Idx_offset(0), velocity(0.f), + parabolic_amplitude(0.f), time_perc(0.f), splineId(0), initialOrientation(0.f), HasVelocity(false), TransformForTransport(true) { path.reserve(path_capacity); @@ -64,6 +64,7 @@ namespace Movement /** Returns true to show that the arguments were configured correctly and MoveSpline initialization will succeed. */ bool Validate(Unit* unit) const; + private: bool _checkPathBounds() const; }; diff --git a/src/server/game/Movement/Spline/MovementTypedefs.h b/src/server/game/Movement/Spline/MovementTypedefs.h index f044d249fcb..1a0f3d54d27 100644 --- a/src/server/game/Movement/Spline/MovementTypedefs.h +++ b/src/server/game/Movement/Spline/MovementTypedefs.h @@ -44,6 +44,9 @@ namespace Movement return ms / 1000.f; } + float computeFallTime(float path_length, bool isSafeFall); + float computeFallElevation(float t_passed, bool isSafeFall, float start_velocity = 0.0f); + #ifndef static_assert #define CONCAT(x, y) CONCAT1 (x, y) #define CONCAT1(x, y) x##y @@ -75,7 +78,6 @@ namespace Movement typedef counter<uint32, 0xFFFFFFFF> UInt32Counter; extern double gravity; - extern float computeFallElevation(float t_passed, bool isSafeFall, float start_velocity); extern UInt32Counter splineIdGen; extern std::string MovementFlags_ToString(uint32 flags); extern std::string MovementFlagsExtra_ToString(uint32 flags); diff --git a/src/server/game/Movement/Spline/MovementUtil.cpp b/src/server/game/Movement/Spline/MovementUtil.cpp index aaa575c752f..ee47a5ebedc 100644 --- a/src/server/game/Movement/Spline/MovementUtil.cpp +++ b/src/server/game/Movement/Spline/MovementUtil.cpp @@ -30,8 +30,9 @@ namespace Movement float terminalSafefallVelocity = 7.0f; const float terminal_length = float(terminalVelocity * terminalVelocity) / (2.0f * gravity); - const float terminal_safefall_length = (terminalSafefallVelocity * terminalSafefallVelocity) / (2.0f * gravity); - const float terminalFallTime = float(terminalVelocity / gravity); // the time that needed to reach terminalVelocity + const float terminal_safeFall_length = (terminalSafefallVelocity * terminalSafefallVelocity) / (2.0f * gravity); + const float terminal_fallTime = float(terminalVelocity / gravity); // the time that needed to reach terminalVelocity + const float terminal_safeFall_fallTime = float(terminalSafefallVelocity / gravity); // the time that needed to reach terminalVelocity with safefall float computeFallTime(float path_length, bool isSafeFall) { @@ -41,15 +42,15 @@ namespace Movement float time; if (isSafeFall) { - if (path_length >= terminal_safefall_length) - time = (path_length - terminal_safefall_length) / terminalSafefallVelocity + terminalSafefallVelocity / gravity; + if (path_length >= terminal_safeFall_length) + time = (path_length - terminal_safeFall_length) / terminalSafefallVelocity + terminal_safeFall_fallTime; else time = sqrtf(2.0f * path_length / gravity); } else { if (path_length >= terminal_length) - time = (path_length - terminal_length) / terminalVelocity + terminalFallTime; + time = (path_length - terminal_length) / terminalVelocity + terminal_fallTime; else time = sqrtf(2.0f * path_length / gravity); } @@ -57,7 +58,7 @@ namespace Movement return time; } - float computeFallElevation(float t_passed, bool isSafeFall, float start_velocity) + float computeFallElevation(float t_passed, bool isSafeFall, float start_velocity /*= 0.0f*/) { float termVel; float result; @@ -70,11 +71,11 @@ namespace Movement if (start_velocity > termVel) start_velocity = termVel; - float terminal_time = terminalFallTime - start_velocity / gravity; // the time that needed to reach terminalVelocity + float terminal_time = (isSafeFall ? terminal_safeFall_fallTime : terminal_fallTime) - start_velocity / gravity; // the time that needed to reach terminalVelocity if (t_passed > terminal_time) { - result = terminalVelocity * (t_passed - terminal_time) + + result = termVel * (t_passed - terminal_time) + start_velocity * terminal_time + gravity * terminal_time * terminal_time*0.5f; } @@ -84,22 +85,6 @@ namespace Movement return result; } - float computeFallElevation(float t_passed) - { - float result; - - if (t_passed > terminalFallTime) - { - //result = terminalVelocity * (t_passed - terminal_time) + gravity*terminal_time*terminal_time*0.5f; - // simplified view: - result = terminalVelocity * (t_passed - terminalFallTime) + terminal_length; - } - else - result = t_passed * t_passed * gravity * 0.5f; - - return result; - } - #define STR(x) #x char const* g_MovementFlag_names[] = diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 9acc4a15dc4..e6e5386626d 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -1216,7 +1216,6 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_UNROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_UNSET_FLYING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_UNSET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_WATER_WALK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_STABLE_RESULT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_STANDSTATE_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_START_MIRROR_TIMER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index cd72faf5740..0c6d7c82c06 100644 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -1295,7 +1295,7 @@ enum Opcodes SMSG_SPLINE_MOVE_SET_TURN_RATE = 0x78B5, SMSG_SPLINE_MOVE_SET_WALK_MODE = 0x54B6, SMSG_SPLINE_MOVE_SET_WALK_SPEED = 0x34A5, - SMSG_SPLINE_MOVE_SET_WATER_WALK = 0x0000, + SMSG_SPLINE_MOVE_SET_WATER_WALK = 0x50A2, SMSG_SPLINE_MOVE_START_SWIM = 0x31A5, SMSG_SPLINE_MOVE_STOP_SWIM = 0x1DA2, SMSG_SPLINE_MOVE_UNROOT = 0x75B6, diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index faaedf42b74..58f49f72cfd 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -2650,23 +2650,17 @@ void AuraEffect::HandleAuraAllowFlight(AuraApplication const* aurApp, uint8 mode } //! Not entirely sure if this should be sent for creatures as well, but I don't think so. - target->SetCanFly(apply); if (!apply) { - target->RemoveUnitMovementFlag(MOVEMENTFLAG_MASK_MOVING_FLY); - target->GetMotionMaster()->MoveFall(); target->m_movementInfo.SetFallTime(0); + target->RemoveUnitMovementFlag(MOVEMENTFLAG_MASK_MOVING_FLY); + target->AddUnitMovementFlag(MOVEMENTFLAG_FALLING); } - Player* player = target->ToPlayer(); - if (!player) - player = target->m_movedPlayer; - - if (player) - player->SendMovementCanFlyChange(); + target->SetCanFly(apply); - //! We still need to initiate a server-side MoveFall here, - //! which requires MSG_MOVE_FALL_LAND on landing. + if (target->GetTypeId() == TYPEID_UNIT) + target->GetMotionMaster()->MoveFall(); } void AuraEffect::HandleAuraWaterWalk(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -2683,12 +2677,7 @@ void AuraEffect::HandleAuraWaterWalk(AuraApplication const* aurApp, uint8 mode, return; } - if (apply) - target->AddUnitMovementFlag(MOVEMENTFLAG_WATERWALKING); - else - target->RemoveUnitMovementFlag(MOVEMENTFLAG_WATERWALKING); - - target->SendMovementWaterWalking(); + target->SetWaterWalking(apply); } void AuraEffect::HandleAuraFeatherFall(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -2705,12 +2694,7 @@ void AuraEffect::HandleAuraFeatherFall(AuraApplication const* aurApp, uint8 mode return; } - if (apply) - target->AddUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW); - else - target->RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING_SLOW); - - target->SendMovementFeatherFall(); + target->SetFeatherFall(apply); // start fall from current height if (!apply && target->GetTypeId() == TYPEID_PLAYER) @@ -2732,7 +2716,6 @@ void AuraEffect::HandleAuraHover(AuraApplication const* aurApp, uint8 mode, bool } target->SetHover(apply); //! Sets movementflags - target->SendMovementHover(); } void AuraEffect::HandleWaterBreathing(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const @@ -3054,6 +3037,8 @@ void AuraEffect::HandleAuraModIncreaseFlightSpeed(AuraApplication const* aurApp, return; Unit* target = aurApp->GetTarget(); + if (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK) + target->UpdateSpeed(MOVE_FLIGHT, true); //! Update ability to fly if (GetAuraType() == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) @@ -3061,22 +3046,17 @@ void AuraEffect::HandleAuraModIncreaseFlightSpeed(AuraApplication const* aurApp, // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit if (mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK && (apply || (!target->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !target->HasAuraType(SPELL_AURA_FLY)))) { - target->SetCanFly(apply); if (!apply) { target->m_movementInfo.SetFallTime(0); target->RemoveUnitMovementFlag(MOVEMENTFLAG_MASK_MOVING_FLY); + target->AddUnitMovementFlag(MOVEMENTFLAG_FALLING); } - Player* player = target->ToPlayer(); - if (!player) - player = target->m_movedPlayer; - - if (player) - player->SendMovementCanFlyChange(); + target->SetCanFly(apply); - //! We still need to initiate a server-side MoveFall here, - //! which requires MSG_MOVE_FALL_LAND on landing. + if (target->GetTypeId() == TYPEID_UNIT) + target->GetMotionMaster()->MoveFall(); } //! Someone should clean up these hacks and remove it from this function. It doesn't even belong here. @@ -3091,9 +3071,6 @@ void AuraEffect::HandleAuraModIncreaseFlightSpeed(AuraApplication const* aurApp, target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 16314); } } - - if (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK) - target->UpdateSpeed(MOVE_FLIGHT, true); } void AuraEffect::HandleAuraModIncreaseSwimSpeed(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const |
