aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2025-08-13 00:31:39 +0200
committerShauren <shauren.trinity@gmail.com>2025-08-13 00:31:39 +0200
commit5cf0c6c8bb2c4e58a2d66ba5f304af34d18a4782 (patch)
tree0616f3e83f511aae0e10916f0c22161017e09c24 /src/server/game/Entities
parent82f19c898815e3bc5bb6288b0191ee897594f9b5 (diff)
Core: Updated to 11.2.0
Diffstat (limited to 'src/server/game/Entities')
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.cpp446
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.h71
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h4
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp2
-rw-r--r--src/server/game/Entities/Creature/CreatureData.h1
-rw-r--r--src/server/game/Entities/GameObject/GameObjectData.h22
-rw-r--r--src/server/game/Entities/Item/Item.cpp22
-rw-r--r--src/server/game/Entities/Item/ItemDefines.h2
-rw-r--r--src/server/game/Entities/Item/ItemTemplate.h3
-rw-r--r--src/server/game/Entities/Object/Object.cpp167
-rw-r--r--src/server/game/Entities/Object/Object.h1
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateField.h116
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateFields.cpp1481
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateFields.h568
-rw-r--r--src/server/game/Entities/Player/Player.cpp509
-rw-r--r--src/server/game/Entities/Player/Player.h200
-rw-r--r--src/server/game/Entities/Unit/Unit.h6
17 files changed, 2285 insertions, 1336 deletions
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
index 868ad6fbbc1..f1bff65dc63 100644
--- a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
+++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
@@ -24,6 +24,8 @@
#include "Containers.h"
#include "CreatureAISelector.h"
#include "DB2Stores.h"
+#include "G3DPosition.hpp"
+#include "GameTime.h"
#include "GridNotifiersImpl.h"
#include "Language.h"
#include "Log.h"
@@ -46,15 +48,14 @@
#include <bit>
AreaTrigger::AreaTrigger() : WorldObject(false), MapObject(), _spawnId(0), _aurEff(nullptr),
- _duration(0), _totalDuration(0), _timeSinceCreated(0), _verticesUpdatePreviousOrientation(std::numeric_limits<float>::infinity()),
- _isRemoved(false), _reachedDestination(true), _lastSplineIndex(0), _movementTime(0),
+ _duration(0), _totalDuration(0), _verticesUpdatePreviousOrientation(std::numeric_limits<float>::infinity()),
+ _isRemoved(false), _reachedDestination(true), _lastSplineIndex(0),
_areaTriggerCreateProperties(nullptr), _areaTriggerTemplate(nullptr)
{
m_objectType |= TYPEMASK_AREATRIGGER;
m_objectTypeId = TYPEID_AREATRIGGER;
m_updateFlag.Stationary = true;
- m_updateFlag.AreaTrigger = true;
m_entityFragments.Add(WowCS::EntityFragment::Tag_AreaTrigger, false);
}
@@ -146,7 +147,7 @@ bool AreaTrigger::Create(AreaTriggerCreatePropertiesId areaTriggerCreateProperti
SetObjectScale(1.0f);
SetDuration(duration);
- _shape = GetCreateProperties()->Shape;
+ SetShape(GetCreateProperties()->Shape);
auto areaTriggerData = m_values.ModifyValue(&AreaTrigger::m_areaTriggerData);
if (caster)
@@ -199,6 +200,33 @@ bool AreaTrigger::Create(AreaTriggerCreatePropertiesId areaTriggerCreateProperti
if (GetCreateProperties()->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::VisualAnimIsDecay))
SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::VisualAnim).ModifyValue(&UF::VisualAnim::IsDecay), true);
+ AreaTriggerFieldFlags fieldFlags = [flags = GetCreateProperties()->Flags]()
+ {
+ AreaTriggerFieldFlags fieldFlags = AreaTriggerFieldFlags::None;
+ if (flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasAbsoluteOrientation))
+ fieldFlags |= AreaTriggerFieldFlags::AbsoluteOrientation;
+ if (flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasDynamicShape))
+ fieldFlags |= AreaTriggerFieldFlags::DynamicShape;
+ if (flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasAttached))
+ fieldFlags |= AreaTriggerFieldFlags::Attached;
+ if (flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasFaceMovementDir))
+ fieldFlags |= AreaTriggerFieldFlags::FaceMovementDir;
+ if (flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasFollowsTerrain))
+ fieldFlags |= AreaTriggerFieldFlags::FollowsTerrain;
+ if (flags.HasFlag(AreaTriggerCreatePropertiesFlag::AlwaysExterior))
+ fieldFlags |= AreaTriggerFieldFlags::AlwaysExterior;
+ return fieldFlags;
+ }();
+ ReplaceAllAreaTriggerFlags(fieldFlags);
+
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::MovementStartTime), GameTime::GetGameTimeMS());
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::CreationTime), GameTime::GetGameTimeMS());
+
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ScaleCurveId), GetCreateProperties()->ScaleCurveId);
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::FacingCurveId), GetCreateProperties()->FacingCurveId);
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::MorphCurveId), GetCreateProperties()->MorphCurveId);
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::MoveCurveId), GetCreateProperties()->MoveCurveId);
+
if (caster)
PhasingHandler::InheritPhaseShift(this, caster);
else if (IsStaticSpawn() && spawnData)
@@ -207,7 +235,7 @@ bool AreaTrigger::Create(AreaTriggerCreatePropertiesId areaTriggerCreateProperti
PhasingHandler::InitDbPhaseShift(GetPhaseShift(), spawnData->phaseUseFlags, spawnData->phaseId, spawnData->phaseGroup);
}
- if (target && GetCreateProperties()->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasAttached))
+ if (target && HasAreaTriggerFlag(AreaTriggerFieldFlags::Attached))
m_movementInfo.transport.guid = target->GetGUID();
if (!IsStaticSpawn())
@@ -218,7 +246,7 @@ bool AreaTrigger::Create(AreaTriggerCreatePropertiesId areaTriggerCreateProperti
if (GetCreateProperties()->OrbitInfo)
{
AreaTriggerOrbitInfo orbit = *GetCreateProperties()->OrbitInfo;
- if (target && GetCreateProperties() && GetCreateProperties()->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasAttached))
+ if (target && HasAreaTriggerFlag(AreaTriggerFieldFlags::Attached))
orbit.PathTarget = target->GetGUID();
else
orbit.Center = pos;
@@ -229,6 +257,10 @@ bool AreaTrigger::Create(AreaTriggerCreatePropertiesId areaTriggerCreateProperti
{
InitSplineOffsets(GetCreateProperties()->SplinePoints);
}
+ else
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ShapeType), int32(AreaTriggerPathType::None));
+
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::Facing), _stationaryPosition.GetOrientation());
// movement on transport of areatriggers on unit is handled by themself
TransportBase* transport = nullptr;
@@ -307,7 +339,6 @@ bool AreaTrigger::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool /*addTo
void AreaTrigger::Update(uint32 diff)
{
WorldObject::Update(diff);
- _timeSinceCreated += diff;
if (!IsStaticSpawn())
{
@@ -318,18 +349,17 @@ void AreaTrigger::Update(uint32 diff)
}
else if (HasOrbit())
{
- UpdateOrbitPosition(*std::get<std::unique_ptr<AreaTriggerOrbitInfo>>(_movement), diff);
+ UpdateOrbitPosition();
}
- else if (GetCreateProperties() && GetCreateProperties()->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasAttached))
+ else if (HasAreaTriggerFlag(AreaTriggerFieldFlags::Attached))
{
if (Unit* target = GetTarget())
{
float orientation = 0.0f;
- if (AreaTriggerCreateProperties const* createProperties = GetCreateProperties())
- if (createProperties->FacingCurveId)
- orientation = sDB2Manager.GetCurveValueAt(createProperties->FacingCurveId, GetProgress());
+ if (m_areaTriggerData->FacingCurveId)
+ orientation = sDB2Manager.GetCurveValueAt(m_areaTriggerData->FacingCurveId, GetProgress());
- if (!GetCreateProperties() || !GetCreateProperties()->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasAbsoluteOrientation))
+ if (!HasAreaTriggerFlag(AreaTriggerFieldFlags::AbsoluteOrientation))
orientation += target->GetOrientation();
GetMap()->AreaTriggerRelocation(this, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), orientation);
@@ -337,20 +367,17 @@ void AreaTrigger::Update(uint32 diff)
}
else if (HasSplines())
{
- UpdateSplinePosition(*std::get<std::unique_ptr<::Movement::Spline<float>>>(_movement), diff);
+ UpdateSplinePosition(*_spline);
}
else
{
- if (AreaTriggerCreateProperties const* createProperties = GetCreateProperties())
+ if (m_areaTriggerData->FacingCurveId)
{
- if (createProperties->FacingCurveId)
- {
- float orientation = sDB2Manager.GetCurveValueAt(createProperties->FacingCurveId, GetProgress());
- if (!GetCreateProperties() || !GetCreateProperties()->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasAbsoluteOrientation))
- orientation += _stationaryPosition.GetOrientation();
+ float orientation = sDB2Manager.GetCurveValueAt(m_areaTriggerData->FacingCurveId, GetProgress());
+ if (!HasAreaTriggerFlag(AreaTriggerFieldFlags::AbsoluteOrientation))
+ orientation += m_areaTriggerData->Facing;
- SetOrientation(orientation);
- }
+ SetOrientation(orientation);
}
UpdateShape();
@@ -381,6 +408,14 @@ void AreaTrigger::Remove()
}
}
+uint32 AreaTrigger::GetTimeSinceCreated() const
+{
+ uint32 now = GameTime::GetGameTimeMS();
+ if (now >= *m_areaTriggerData->CreationTime)
+ return now - *m_areaTriggerData->CreationTime;
+ return 0;
+}
+
void AreaTrigger::SetOverrideScaleCurve(float overrideScale)
{
SetScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::OverrideScaleCurve), overrideScale);
@@ -467,9 +502,8 @@ float AreaTrigger::CalcCurrentScale() const
float scale = 1.0f;
if (m_areaTriggerData->OverrideScaleCurve->OverrideActive)
scale *= std::max(GetScaleCurveValue(*m_areaTriggerData->OverrideScaleCurve, m_areaTriggerData->TimeToTargetScale), 0.000001f);
- else if (AreaTriggerCreateProperties const* createProperties = GetCreateProperties())
- if (createProperties->ScaleCurveId)
- scale *= std::max(sDB2Manager.GetCurveValueAt(createProperties->ScaleCurveId, GetScaleCurveProgress(*m_areaTriggerData->OverrideScaleCurve, m_areaTriggerData->TimeToTargetScale)), 0.000001f);
+ else if (m_areaTriggerData->ScaleCurveId)
+ scale *= std::max(sDB2Manager.GetCurveValueAt(m_areaTriggerData->ScaleCurveId, GetScaleCurveProgress(*m_areaTriggerData->OverrideScaleCurve, m_areaTriggerData->TimeToTargetScale)), 0.000001f);
scale *= std::max(GetScaleCurveValue(*m_areaTriggerData->ExtraScaleCurve, m_areaTriggerData->TimeToTargetExtraScale), 0.000001f);
@@ -609,29 +643,21 @@ void AreaTrigger::UpdateTargetList()
{
std::vector<Unit*> targetList;
- switch (_shape.Type)
+ m_areaTriggerData->ShapeData.Visit([&]<typename ShapeType>(ShapeType const& shape)
{
- case AreaTriggerShapeType::Sphere:
- SearchUnitInSphere(targetList);
- break;
- case AreaTriggerShapeType::Box:
- SearchUnitInBox(targetList);
- break;
- case AreaTriggerShapeType::Polygon:
- SearchUnitInPolygon(targetList);
- break;
- case AreaTriggerShapeType::Cylinder:
- SearchUnitInCylinder(targetList);
- break;
- case AreaTriggerShapeType::Disk:
- SearchUnitInDisk(targetList);
- break;
- case AreaTriggerShapeType::BoundedPlane:
- SearchUnitInBoundedPlane(targetList);
- break;
- default:
- break;
- }
+ if constexpr (std::is_same_v<ShapeType, UF::AreaTriggerSphere>)
+ this->SearchUnitInSphere(shape, targetList);
+ else if constexpr (std::is_same_v<ShapeType, UF::AreaTriggerBox>)
+ this->SearchUnitInBox(shape, targetList);
+ else if constexpr (std::is_same_v<ShapeType, UF::AreaTriggerPolygon>)
+ this->SearchUnitInPolygon(shape, targetList);
+ else if constexpr (std::is_same_v<ShapeType, UF::AreaTriggerCylinder>)
+ this->SearchUnitInCylinder(shape, targetList);
+ else if constexpr (std::is_same_v<ShapeType, UF::AreaTriggerDisk>)
+ this->SearchUnitInDisk(shape, targetList);
+ else if constexpr (std::is_same_v<ShapeType, UF::AreaTriggerBoundedPlane>)
+ this->SearchUnitInBoundedPlane(shape, targetList);
+ });
if (GetTemplate())
{
@@ -704,30 +730,28 @@ void AreaTrigger::SearchUnits(std::vector<Unit*>& targetList, float radius, bool
}
}
-void AreaTrigger::SearchUnitInSphere(std::vector<Unit*>& targetList)
+void AreaTrigger::SearchUnitInSphere(UF::AreaTriggerSphere const& sphere, std::vector<Unit*>& targetList)
{
float progress = GetProgress();
- if (AreaTriggerCreateProperties const* createProperties = GetCreateProperties())
- if (createProperties->MorphCurveId)
- progress = sDB2Manager.GetCurveValueAt(createProperties->MorphCurveId, progress);
+ if (m_areaTriggerData->MorphCurveId)
+ progress = sDB2Manager.GetCurveValueAt(m_areaTriggerData->MorphCurveId, progress);
float scale = CalcCurrentScale();
- float radius = G3D::lerp(_shape.SphereDatas.Radius, _shape.SphereDatas.RadiusTarget, progress) * scale;
+ float radius = G3D::lerp(sphere.Radius, sphere.RadiusTarget, progress) * scale;
SearchUnits(targetList, radius, true);
}
-void AreaTrigger::SearchUnitInBox(std::vector<Unit*>& targetList)
+void AreaTrigger::SearchUnitInBox(UF::AreaTriggerBox const& box, std::vector<Unit*>& targetList)
{
float progress = GetProgress();
- if (AreaTriggerCreateProperties const* createProperties = GetCreateProperties())
- if (createProperties->MorphCurveId)
- progress = sDB2Manager.GetCurveValueAt(createProperties->MorphCurveId, progress);
+ if (m_areaTriggerData->MorphCurveId)
+ progress = sDB2Manager.GetCurveValueAt(m_areaTriggerData->MorphCurveId, progress);
float scale = CalcCurrentScale();
- float extentsX = G3D::lerp(_shape.BoxDatas.Extents[0], _shape.BoxDatas.ExtentsTarget[0], progress) * scale;
- float extentsY = G3D::lerp(_shape.BoxDatas.Extents[1], _shape.BoxDatas.ExtentsTarget[1], progress) * scale;
- float extentsZ = G3D::lerp(_shape.BoxDatas.Extents[2], _shape.BoxDatas.ExtentsTarget[2], progress) * scale;
+ float extentsX = G3D::lerp(box.Extents->Pos.GetPositionX(), box.ExtentsTarget->Pos.GetPositionX(), progress) * scale;
+ float extentsY = G3D::lerp(box.Extents->Pos.GetPositionY(), box.ExtentsTarget->Pos.GetPositionY(), progress) * scale;
+ float extentsZ = G3D::lerp(box.Extents->Pos.GetPositionZ(), box.ExtentsTarget->Pos.GetPositionZ(), progress) * scale;
float radius = std::sqrt(extentsX * extentsX + extentsY * extentsY);
SearchUnits(targetList, radius, false);
@@ -739,14 +763,13 @@ void AreaTrigger::SearchUnitInBox(std::vector<Unit*>& targetList)
});
}
-void AreaTrigger::SearchUnitInPolygon(std::vector<Unit*>& targetList)
+void AreaTrigger::SearchUnitInPolygon(UF::AreaTriggerPolygon const& polygon, std::vector<Unit*>& targetList)
{
float progress = GetProgress();
- if (AreaTriggerCreateProperties const* createProperties = GetCreateProperties())
- if (createProperties->MorphCurveId)
- progress = sDB2Manager.GetCurveValueAt(createProperties->MorphCurveId, progress);
+ if (m_areaTriggerData->MorphCurveId)
+ progress = sDB2Manager.GetCurveValueAt(m_areaTriggerData->MorphCurveId, progress);
- float height = G3D::lerp(_shape.PolygonDatas.Height, _shape.PolygonDatas.HeightTarget, progress);
+ float height = G3D::lerp(polygon.Height, polygon.HeightTarget, progress);
float minZ = GetPositionZ() - height;
float maxZ = GetPositionZ() + height;
@@ -760,17 +783,16 @@ void AreaTrigger::SearchUnitInPolygon(std::vector<Unit*>& targetList)
});
}
-void AreaTrigger::SearchUnitInCylinder(std::vector<Unit*>& targetList)
+void AreaTrigger::SearchUnitInCylinder(UF::AreaTriggerCylinder const& cylinder, std::vector<Unit*>& targetList)
{
float progress = GetProgress();
- if (AreaTriggerCreateProperties const* createProperties = GetCreateProperties())
- if (createProperties->MorphCurveId)
- progress = sDB2Manager.GetCurveValueAt(createProperties->MorphCurveId, progress);
+ if (m_areaTriggerData->MorphCurveId)
+ progress = sDB2Manager.GetCurveValueAt(m_areaTriggerData->MorphCurveId, progress);
float scale = CalcCurrentScale();
- float radius = G3D::lerp(_shape.CylinderDatas.Radius, _shape.CylinderDatas.RadiusTarget, progress) * scale;
- float height = G3D::lerp(_shape.CylinderDatas.Height, _shape.CylinderDatas.HeightTarget, progress);
- if (!m_areaTriggerData->HeightIgnoresScale)
+ float radius = G3D::lerp(cylinder.Radius, cylinder.RadiusTarget, progress) * scale;
+ float height = G3D::lerp(cylinder.Height, cylinder.HeightTarget, progress);
+ if (!HasAreaTriggerFlag(AreaTriggerFieldFlags::HeightIgnoresScale))
height *= scale;
float minZ = GetPositionZ() - height;
@@ -785,18 +807,17 @@ void AreaTrigger::SearchUnitInCylinder(std::vector<Unit*>& targetList)
});
}
-void AreaTrigger::SearchUnitInDisk(std::vector<Unit*>& targetList)
+void AreaTrigger::SearchUnitInDisk(UF::AreaTriggerDisk const& disk, std::vector<Unit*>& targetList)
{
float progress = GetProgress();
- if (AreaTriggerCreateProperties const* createProperties = GetCreateProperties())
- if (createProperties->MorphCurveId)
- progress = sDB2Manager.GetCurveValueAt(createProperties->MorphCurveId, progress);
+ if (m_areaTriggerData->MorphCurveId)
+ progress = sDB2Manager.GetCurveValueAt(m_areaTriggerData->MorphCurveId, progress);
float scale = CalcCurrentScale();
- float innerRadius = G3D::lerp(_shape.DiskDatas.InnerRadius, _shape.DiskDatas.InnerRadiusTarget, progress) * scale;
- float outerRadius = G3D::lerp(_shape.DiskDatas.OuterRadius, _shape.DiskDatas.OuterRadiusTarget, progress) * scale;
- float height = G3D::lerp(_shape.DiskDatas.Height, _shape.DiskDatas.HeightTarget, progress);
- if (!m_areaTriggerData->HeightIgnoresScale)
+ float innerRadius = G3D::lerp(disk.InnerRadius, disk.InnerRadiusTarget, progress) * scale;
+ float outerRadius = G3D::lerp(disk.OuterRadius, disk.OuterRadiusTarget, progress) * scale;
+ float height = G3D::lerp(disk.Height, disk.HeightTarget, progress);
+ if (!HasAreaTriggerFlag(AreaTriggerFieldFlags::HeightIgnoresScale))
height *= scale;
float minZ = GetPositionZ() - height;
@@ -810,16 +831,15 @@ void AreaTrigger::SearchUnitInDisk(std::vector<Unit*>& targetList)
});
}
-void AreaTrigger::SearchUnitInBoundedPlane(std::vector<Unit*>& targetList)
+void AreaTrigger::SearchUnitInBoundedPlane(UF::AreaTriggerBoundedPlane const& boundedPlane, std::vector<Unit*>& targetList)
{
float progress = GetProgress();
- if (AreaTriggerCreateProperties const* createProperties = GetCreateProperties())
- if (createProperties->MorphCurveId)
- progress = sDB2Manager.GetCurveValueAt(createProperties->MorphCurveId, progress);
+ if (m_areaTriggerData->MorphCurveId)
+ progress = sDB2Manager.GetCurveValueAt(m_areaTriggerData->MorphCurveId, progress);
float scale = CalcCurrentScale();
- float extentsX = G3D::lerp(_shape.BoundedPlaneDatas.Extents[0], _shape.BoundedPlaneDatas.ExtentsTarget[0], progress) * scale;
- float extentsY = G3D::lerp(_shape.BoundedPlaneDatas.Extents[1], _shape.BoundedPlaneDatas.ExtentsTarget[1], progress) * scale;
+ float extentsX = G3D::lerp(boundedPlane.Extents->Pos.GetPositionX(), boundedPlane.ExtentsTarget->Pos.GetPositionX(), progress) * scale;
+ float extentsY = G3D::lerp(boundedPlane.Extents->Pos.GetPositionY(), boundedPlane.ExtentsTarget->Pos.GetPositionY(), progress) * scale;
float radius = std::sqrt(extentsX * extentsX + extentsY * extentsY);
SearchUnits(targetList, radius, false);
@@ -885,9 +905,10 @@ void AreaTrigger::HandleUnitEnterExit(std::vector<Unit*> const& newTargetList)
}
}
- SetUpdateFieldValue(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::NumUnitsInside), _insideUnits.size());
- SetUpdateFieldValue(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::NumPlayersInside),
- std::ranges::count_if(_insideUnits, [](ObjectGuid const& guid) { return guid.IsPlayer(); }));
+ if (std::ranges::any_of(_insideUnits, [](ObjectGuid const& guid) { return guid.IsPlayer(); }))
+ SetAreaTriggerFlag(AreaTriggerFieldFlags::HasPlayers);
+ else
+ RemoveAreaTriggerFlag(AreaTriggerFieldFlags::HasPlayers);
if (IsStaticSpawn())
setActive(!_insideUnits.empty());
@@ -928,6 +949,83 @@ uint32 AreaTrigger::GetFaction() const
return 0;
}
+void AreaTrigger::SetShape(AreaTriggerShapeInfo const& shape)
+{
+ auto areaTriggerData = m_values.ModifyValue(&AreaTrigger::m_areaTriggerData);
+
+ switch (shape.Type)
+ {
+ case AreaTriggerShapeType::Sphere:
+ {
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ShapeType), 0);
+ auto sphere = areaTriggerData.ModifyValue(&UF::AreaTriggerData::ShapeData, UF::VariantCase<UF::AreaTriggerSphere>);
+ SetUpdateFieldValue(sphere.ModifyValue(&UF::AreaTriggerSphere::Radius), shape.SphereDatas.Radius);
+ SetUpdateFieldValue(sphere.ModifyValue(&UF::AreaTriggerSphere::RadiusTarget), shape.SphereDatas.RadiusTarget);
+ break;
+ }
+ case AreaTriggerShapeType::Box:
+ {
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ShapeType), 1);
+ auto box = areaTriggerData.ModifyValue(&UF::AreaTriggerData::ShapeData, UF::VariantCase<UF::AreaTriggerBox>);
+ SetUpdateFieldValue(box.ModifyValue(&UF::AreaTriggerBox::Extents), { shape.BoxDatas.Extents[0], shape.BoxDatas.Extents[1], shape.BoxDatas.Extents[2] });
+ SetUpdateFieldValue(box.ModifyValue(&UF::AreaTriggerBox::ExtentsTarget), { shape.BoxDatas.ExtentsTarget[0], shape.BoxDatas.ExtentsTarget[1], shape.BoxDatas.ExtentsTarget[2] });
+ break;
+ }
+ case AreaTriggerShapeType::Polygon:
+ {
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ShapeType), 3);
+ auto polygon = areaTriggerData.ModifyValue(&UF::AreaTriggerData::ShapeData, UF::VariantCase<UF::AreaTriggerPolygon>);
+ auto vertices = polygon.ModifyValue(&UF::AreaTriggerPolygon::Vertices);
+ ClearDynamicUpdateFieldValues(vertices);
+ for (TaggedPosition<XY> const& vertex : shape.PolygonVertices)
+ AddDynamicUpdateFieldValue(vertices) = vertex;
+ auto verticesTarget = polygon.ModifyValue(&UF::AreaTriggerPolygon::VerticesTarget);
+ ClearDynamicUpdateFieldValues(verticesTarget);
+ for (TaggedPosition<XY> const& vertex : shape.PolygonVerticesTarget)
+ AddDynamicUpdateFieldValue(verticesTarget) = vertex;
+ SetUpdateFieldValue(polygon.ModifyValue(&UF::AreaTriggerPolygon::Height), shape.PolygonDatas.Height);
+ SetUpdateFieldValue(polygon.ModifyValue(&UF::AreaTriggerPolygon::HeightTarget), shape.PolygonDatas.HeightTarget);
+ break;
+ }
+ case AreaTriggerShapeType::Cylinder:
+ {
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ShapeType), 4);
+ auto cylinder = areaTriggerData.ModifyValue(&UF::AreaTriggerData::ShapeData, UF::VariantCase<UF::AreaTriggerCylinder>);
+ SetUpdateFieldValue(cylinder.ModifyValue(&UF::AreaTriggerCylinder::Radius), shape.CylinderDatas.Radius);
+ SetUpdateFieldValue(cylinder.ModifyValue(&UF::AreaTriggerCylinder::RadiusTarget), shape.CylinderDatas.RadiusTarget);
+ SetUpdateFieldValue(cylinder.ModifyValue(&UF::AreaTriggerCylinder::Height), shape.CylinderDatas.Height);
+ SetUpdateFieldValue(cylinder.ModifyValue(&UF::AreaTriggerCylinder::HeightTarget), shape.CylinderDatas.HeightTarget);
+ SetUpdateFieldValue(cylinder.ModifyValue(&UF::AreaTriggerCylinder::LocationZOffset), shape.CylinderDatas.LocationZOffset);
+ SetUpdateFieldValue(cylinder.ModifyValue(&UF::AreaTriggerCylinder::LocationZOffsetTarget), shape.CylinderDatas.LocationZOffsetTarget);
+ break;
+ }
+ case AreaTriggerShapeType::Disk:
+ {
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ShapeType), 7);
+ auto disk = areaTriggerData.ModifyValue(&UF::AreaTriggerData::ShapeData, UF::VariantCase<UF::AreaTriggerDisk>);
+ SetUpdateFieldValue(disk.ModifyValue(&UF::AreaTriggerDisk::InnerRadius), shape.DiskDatas.InnerRadius);
+ SetUpdateFieldValue(disk.ModifyValue(&UF::AreaTriggerDisk::InnerRadiusTarget), shape.DiskDatas.InnerRadiusTarget);
+ SetUpdateFieldValue(disk.ModifyValue(&UF::AreaTriggerDisk::OuterRadius), shape.DiskDatas.OuterRadius);
+ SetUpdateFieldValue(disk.ModifyValue(&UF::AreaTriggerDisk::OuterRadiusTarget), shape.DiskDatas.OuterRadiusTarget);
+ SetUpdateFieldValue(disk.ModifyValue(&UF::AreaTriggerDisk::Height), shape.DiskDatas.Height);
+ SetUpdateFieldValue(disk.ModifyValue(&UF::AreaTriggerDisk::HeightTarget), shape.DiskDatas.HeightTarget);
+ SetUpdateFieldValue(disk.ModifyValue(&UF::AreaTriggerDisk::LocationZOffset), shape.DiskDatas.LocationZOffset);
+ SetUpdateFieldValue(disk.ModifyValue(&UF::AreaTriggerDisk::LocationZOffsetTarget), shape.DiskDatas.LocationZOffsetTarget);
+ break;
+ }
+ case AreaTriggerShapeType::BoundedPlane:
+ {
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ShapeType), 8);
+ auto boundedPlane = areaTriggerData.ModifyValue(&UF::AreaTriggerData::ShapeData, UF::VariantCase<UF::AreaTriggerBoundedPlane>);
+ SetUpdateFieldValue(boundedPlane.ModifyValue(&UF::AreaTriggerBoundedPlane::Extents), { shape.BoundedPlaneDatas.Extents[0], shape.BoundedPlaneDatas.Extents[1] });
+ SetUpdateFieldValue(boundedPlane.ModifyValue(&UF::AreaTriggerBoundedPlane::ExtentsTarget), { shape.BoundedPlaneDatas.ExtentsTarget[0], shape.BoundedPlaneDatas.ExtentsTarget[1] });
+ break;
+ }
+ default:
+ break;
+ }
+}
+
float AreaTrigger::GetMaxSearchRadius() const
{
return *m_areaTriggerData->BoundsRadius2D * CalcCurrentScale();
@@ -935,25 +1033,24 @@ float AreaTrigger::GetMaxSearchRadius() const
void AreaTrigger::UpdatePolygonVertices()
{
- AreaTriggerCreateProperties const* createProperties = GetCreateProperties();
- AreaTriggerShapeInfo const& shape = GetShape();
+ UF::AreaTriggerPolygon const* shape = m_areaTriggerData->ShapeData.Get<UF::AreaTriggerPolygon>();
float newOrientation = GetOrientation();
// No need to recalculate, orientation didn't change
- if (G3D::fuzzyEq(_verticesUpdatePreviousOrientation, newOrientation) && shape.PolygonVerticesTarget.empty())
+ if (G3D::fuzzyEq(_verticesUpdatePreviousOrientation, newOrientation) && shape->VerticesTarget.empty())
return;
- _polygonVertices.assign(shape.PolygonVertices.begin(), shape.PolygonVertices.end());
- if (!shape.PolygonVerticesTarget.empty())
+ _polygonVertices.assign(shape->Vertices.begin(), shape->Vertices.end());
+ if (!shape->VerticesTarget.empty())
{
float progress = GetProgress();
- if (createProperties->MorphCurveId)
- progress = sDB2Manager.GetCurveValueAt(createProperties->MorphCurveId, progress);
+ if (m_areaTriggerData->MorphCurveId)
+ progress = sDB2Manager.GetCurveValueAt(m_areaTriggerData->MorphCurveId, progress);
for (std::size_t i = 0; i < _polygonVertices.size(); ++i)
{
Position& vertex = _polygonVertices[i];
- Position const& vertexTarget = shape.PolygonVerticesTarget[i].Pos;
+ Position const& vertexTarget = shape->VerticesTarget[i].Pos;
vertex.m_positionX = G3D::lerp(vertex.GetPositionX(), vertexTarget.GetPositionX(), progress);
vertex.m_positionY = G3D::lerp(vertex.GetPositionY(), vertexTarget.GetPositionY(), progress);
@@ -983,7 +1080,7 @@ bool AreaTrigger::HasOverridePosition() const
void AreaTrigger::UpdateShape()
{
- if (_shape.IsPolygon())
+ if (m_areaTriggerData->ShapeData.Is<UF::AreaTriggerPolygon>())
UpdatePolygonVertices();
}
@@ -1120,8 +1217,6 @@ void AreaTrigger::InitSplines(std::vector<G3D::Vector3> const& splinePoints, Opt
if (splinePoints.size() < 2)
return;
- _movementTime = 0;
-
std::unique_ptr<Movement::Spline<float>> spline = std::make_unique<::Movement::Spline<float>>();
spline->init_spline(splinePoints.data(), splinePoints.size(), ::Movement::SplineBase::ModeLinear, _stationaryPosition.GetOrientation());
spline->initLengths();
@@ -1131,29 +1226,29 @@ void AreaTrigger::InitSplines(std::vector<G3D::Vector3> const& splinePoints, Opt
speed = 1.0f;
uint32 timeToTarget = spline->length() / speed * float(IN_MILLISECONDS);
- SetUpdateFieldValue(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::TimeToTarget), timeToTarget);
-
- if (IsInWorld())
- {
- if (_reachedDestination)
- {
- WorldPackets::AreaTrigger::AreaTriggerRePath reshape;
- reshape.TriggerGUID = GetGUID();
- SendMessageToSet(reshape.Write(), true);
- }
- WorldPackets::AreaTrigger::AreaTriggerRePath reshape;
- reshape.TriggerGUID = GetGUID();
- reshape.AreaTriggerSpline.emplace();
- reshape.AreaTriggerSpline->ElapsedTimeForMovement = GetElapsedTimeForMovement();
- reshape.AreaTriggerSpline->TimeToTarget = timeToTarget;
- reshape.AreaTriggerSpline->Points = spline.get();
+ auto areaTriggerData = m_values.ModifyValue(&AreaTrigger::m_areaTriggerData);
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::TimeToTarget), timeToTarget);
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::MovementStartTime), GameTime::GetGameTimeMS());
- SendMessageToSet(reshape.Write(), true);
- }
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::PathType), int32(AreaTriggerPathType::Spline));
+ auto pathData = areaTriggerData.ModifyValue(&UF::AreaTriggerData::PathData, UF::VariantCase<UF::AreaTriggerSplineCalculator>);
+ SetUpdateFieldValue(pathData.ModifyValue(&UF::AreaTriggerSplineCalculator::Catmullrom), spline->getPointCount() >= 4);
+ auto points = pathData.ModifyValue(&UF::AreaTriggerSplineCalculator::Points);
+ ClearDynamicUpdateFieldValues(points);
+ for (G3D::Vector3 const& point : spline->getPoints())
+ AddDynamicUpdateFieldValue(points) = Vector3ToPosition(point);
_reachedDestination = false;
- _movement = std::move(spline);
+ _spline = std::move(spline);
+}
+
+uint32 AreaTrigger::GetElapsedTimeForMovement() const
+{
+ uint32 now = GameTime::GetGameTimeMS();
+ if (now >= *m_areaTriggerData->MovementStartTime)
+ return now - *m_areaTriggerData->MovementStartTime;
+ return 0;
}
void AreaTrigger::InitOrbit(AreaTriggerOrbitInfo const& orbit, Optional<float> overrideSpeed)
@@ -1167,40 +1262,37 @@ void AreaTrigger::InitOrbit(AreaTriggerOrbitInfo const& orbit, Optional<float> o
uint32 timeToTarget = static_cast<uint32>(orbit.Radius * 2.0f * static_cast<float>(M_PI) * static_cast<float>(IN_MILLISECONDS) / speed);
- SetUpdateFieldValue(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::TimeToTarget), timeToTarget);
- SetUpdateFieldValue(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::OrbitPathTarget), orbit.PathTarget.value_or(ObjectGuid::Empty));
-
- std::unique_ptr<AreaTriggerOrbitInfo> movementOrbit = std::make_unique<AreaTriggerOrbitInfo>();
-
- movementOrbit->TimeToTarget = timeToTarget;
- movementOrbit->ElapsedTimeForMovement = 0;
-
- if (IsInWorld())
- {
- WorldPackets::AreaTrigger::AreaTriggerRePath reshape;
- reshape.TriggerGUID = GetGUID();
- reshape.AreaTriggerOrbit = *movementOrbit;
-
- SendMessageToSet(reshape.Write(), true);
- }
+ auto areaTriggerData = m_values.ModifyValue(&AreaTrigger::m_areaTriggerData);
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::TimeToTarget), timeToTarget);
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::MovementStartTime), GameTime::GetGameTimeMS());
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::OrbitPathTarget), orbit.PathTarget.value_or(ObjectGuid::Empty));
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ZOffset), orbit.ZOffset);
+ if (orbit.CanLoop)
+ SetAreaTriggerFlag(AreaTriggerFieldFlags::CanLoop);
+ else
+ RemoveAreaTriggerFlag(AreaTriggerFieldFlags::CanLoop);
- _movement = std::move(movementOrbit);
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::PathType), int32(AreaTriggerPathType::Orbit));
+ auto pathData = areaTriggerData.ModifyValue(&UF::AreaTriggerData::PathData, UF::VariantCase<UF::AreaTriggerOrbit>);
+ SetUpdateFieldValue(pathData.ModifyValue(&UF::AreaTriggerOrbit::CounterClockwise), orbit.CounterClockwise);
+ SetUpdateFieldValue(pathData.ModifyValue(&UF::AreaTriggerOrbit::Center), orbit.Center.value_or(Position()));
+ SetUpdateFieldValue(pathData.ModifyValue(&UF::AreaTriggerOrbit::Radius), orbit.Radius);
+ SetUpdateFieldValue(pathData.ModifyValue(&UF::AreaTriggerOrbit::InitialAngle), orbit.InitialAngle);
+ SetUpdateFieldValue(pathData.ModifyValue(&UF::AreaTriggerOrbit::BlendFromRadius), orbit.BlendFromRadius);
+ SetUpdateFieldValue(pathData.ModifyValue(&UF::AreaTriggerOrbit::ExtraTimeForBlending), orbit.ExtraTimeForBlending);
}
Position const* AreaTrigger::GetOrbitCenterPosition() const
{
- if (!HasOrbit())
+ UF::AreaTriggerOrbit const* orbit = m_areaTriggerData->PathData.Get<UF::AreaTriggerOrbit>();
+ if (!orbit)
return nullptr;
- AreaTriggerOrbitInfo const& orbit = *std::get<std::unique_ptr<AreaTriggerOrbitInfo>>(_movement);
- if (orbit.PathTarget)
- if (WorldObject* center = ObjectAccessor::GetWorldObject(*this, *orbit.PathTarget))
+ if (!m_areaTriggerData->OrbitPathTarget->IsEmpty())
+ if (WorldObject* center = ObjectAccessor::GetWorldObject(*this, *m_areaTriggerData->OrbitPathTarget))
return center;
- if (orbit.Center)
- return &orbit.Center->Pos;
-
- return nullptr;
+ return &orbit->Center->Pos;
}
Position AreaTrigger::CalculateOrbitPosition() const
@@ -1209,26 +1301,24 @@ Position AreaTrigger::CalculateOrbitPosition() const
if (!centerPos)
return GetPosition();
- AreaTriggerCreateProperties const* createProperties = GetCreateProperties();
- AreaTriggerOrbitInfo const& cmi = GetOrbit();
+ UF::AreaTriggerOrbit const& cmi = *m_areaTriggerData->PathData.Get<UF::AreaTriggerOrbit>();
// AreaTrigger make exactly "Duration / TimeToTarget" loops during his life time
- float pathProgress = float(cmi.ElapsedTimeForMovement) / float(cmi.TimeToTarget);
- if (createProperties && createProperties->MoveCurveId)
- pathProgress = sDB2Manager.GetCurveValueAt(createProperties->MoveCurveId, pathProgress);
+ float pathProgress = float(GetElapsedTimeForMovement() + *cmi.ExtraTimeForBlending) / float(GetTimeToTarget());
+ if (m_areaTriggerData->MoveCurveId)
+ pathProgress = sDB2Manager.GetCurveValueAt(m_areaTriggerData->MoveCurveId, pathProgress);
// We already made one circle and can't loop
- if (!cmi.CanLoop)
+ if (!HasAreaTriggerFlag(AreaTriggerFieldFlags::CanLoop))
pathProgress = std::min(1.f, pathProgress);
float radius = cmi.Radius;
- if (G3D::fuzzyNe(cmi.BlendFromRadius, radius))
+ if (pathProgress <= 1.0f && G3D::fuzzyNe(cmi.BlendFromRadius, radius))
{
float blendCurve = (cmi.BlendFromRadius - radius) / radius;
- // 4.f Defines four quarters
- blendCurve = RoundToInterval(blendCurve, 1.f, 4.f) / 4.f;
- float blendProgress = std::min(1.f, pathProgress / blendCurve);
- radius = G3D::lerp(cmi.BlendFromRadius, cmi.Radius, blendProgress);
+ RoundToInterval(blendCurve, 1.f, 4.f);
+ float blendProgress = std::min(1.f, pathProgress / blendCurve * 0.63661975f);
+ radius = G3D::lerp(cmi.BlendFromRadius, radius, blendProgress);
}
// Adapt Path progress depending of circle direction
@@ -1238,13 +1328,13 @@ Position AreaTrigger::CalculateOrbitPosition() const
float angle = cmi.InitialAngle + 2.f * float(M_PI) * pathProgress;
float x = centerPos->GetPositionX() + (radius * std::cos(angle));
float y = centerPos->GetPositionY() + (radius * std::sin(angle));
- float z = centerPos->GetPositionZ() + cmi.ZOffset;
+ float z = centerPos->GetPositionZ() + *m_areaTriggerData->ZOffset;
float orientation = 0.0f;
- if (createProperties && createProperties->FacingCurveId)
- orientation = sDB2Manager.GetCurveValueAt(createProperties->FacingCurveId, GetProgress());
+ if (m_areaTriggerData->FacingCurveId)
+ orientation = sDB2Manager.GetCurveValueAt(m_areaTriggerData->FacingCurveId, GetProgress());
- if (!GetCreateProperties() || !GetCreateProperties()->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasAbsoluteOrientation))
+ if (!HasAreaTriggerFlag(AreaTriggerFieldFlags::AbsoluteOrientation))
{
orientation += angle;
orientation += cmi.CounterClockwise ? float(M_PI_4) : -float(M_PI_4);
@@ -1253,13 +1343,8 @@ Position AreaTrigger::CalculateOrbitPosition() const
return { x, y, z, orientation };
}
-void AreaTrigger::UpdateOrbitPosition(AreaTriggerOrbitInfo& orbit, uint32 /*diff*/)
+void AreaTrigger::UpdateOrbitPosition()
{
- if (orbit.StartDelay > GetElapsedTimeForMovement())
- return;
-
- orbit.ElapsedTimeForMovement = GetElapsedTimeForMovement() - orbit.StartDelay;
-
Position pos = CalculateOrbitPosition();
GetMap()->AreaTriggerRelocation(this, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation());
@@ -1268,14 +1353,12 @@ void AreaTrigger::UpdateOrbitPosition(AreaTriggerOrbitInfo& orbit, uint32 /*diff
#endif
}
-void AreaTrigger::UpdateSplinePosition(Movement::Spline<float>& spline, uint32 diff)
+void AreaTrigger::UpdateSplinePosition(Movement::Spline<float>& spline)
{
if (_reachedDestination)
return;
- _movementTime += diff;
-
- if (_movementTime >= GetTimeToTarget())
+ if (GetElapsedTimeForMovement() >= GetTimeToTarget())
{
_reachedDestination = true;
_lastSplineIndex = int32(spline.last());
@@ -1291,19 +1374,19 @@ void AreaTrigger::UpdateSplinePosition(Movement::Spline<float>& spline, uint32 d
return;
}
- float currentTimePercent = float(_movementTime) / float(GetTimeToTarget());
+ float currentTimePercent = float(GetElapsedTimeForMovement()) / float(GetTimeToTarget());
if (currentTimePercent <= 0.f)
return;
- AreaTriggerCreateProperties const* createProperties = GetCreateProperties();
- if (createProperties && createProperties->MoveCurveId)
+ if (m_areaTriggerData->MoveCurveId)
{
- float progress = sDB2Manager.GetCurveValueAt(createProperties->MoveCurveId, currentTimePercent);
+ float progress = sDB2Manager.GetCurveValueAt(m_areaTriggerData->MoveCurveId, currentTimePercent);
if (progress < 0.f || progress > 1.f)
{
+ AreaTriggerCreateProperties const* createProperties = GetCreateProperties();
TC_LOG_ERROR("entities.areatrigger", "AreaTrigger (Id: {}, AreaTriggerCreatePropertiesId: (Id: {}, IsCustom: {})) has wrong progress ({}) caused by curve calculation (MoveCurveId: {})",
- GetEntry(), createProperties->Id.Id, uint32(createProperties->Id.IsCustom), progress, createProperties->MoveCurveId);
+ GetEntry(), createProperties->Id.Id, uint32(createProperties->Id.IsCustom), progress, *m_areaTriggerData->MoveCurveId);
}
else
currentTimePercent = progress;
@@ -1317,10 +1400,10 @@ void AreaTrigger::UpdateSplinePosition(Movement::Spline<float>& spline, uint32 d
spline.evaluate_percent(lastPositionIndex, percentFromLastPoint, currentPosition);
float orientation = _stationaryPosition.GetOrientation();
- if (createProperties && createProperties->FacingCurveId)
- orientation += sDB2Manager.GetCurveValueAt(createProperties->FacingCurveId, GetProgress());
+ if (m_areaTriggerData->FacingCurveId)
+ orientation += sDB2Manager.GetCurveValueAt(m_areaTriggerData->FacingCurveId, GetProgress());
- if (GetCreateProperties() && !GetCreateProperties()->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasAbsoluteOrientation) && GetCreateProperties()->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasFaceMovementDir))
+ if (!HasAreaTriggerFlag(AreaTriggerFieldFlags::AbsoluteOrientation) && HasAreaTriggerFlag(AreaTriggerFieldFlags::FaceMovementDir))
{
G3D::Vector3 derivative;
spline.evaluate_derivative(lastPositionIndex, percentFromLastPoint, derivative);
@@ -1349,14 +1432,11 @@ void AreaTrigger::UpdateOverridePosition()
float z = GetScaleCurveValueAtProgress(*m_areaTriggerData->OverrideMoveCurveZ, progress);
float orientation = GetOrientation();
- if (AreaTriggerCreateProperties const* createProperties = GetCreateProperties())
+ if (m_areaTriggerData->FacingCurveId)
{
- if (createProperties->FacingCurveId)
- {
- orientation = sDB2Manager.GetCurveValueAt(createProperties->FacingCurveId, GetProgress());
- if (!GetCreateProperties() || !GetCreateProperties()->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasAbsoluteOrientation))
- orientation += _stationaryPosition.GetOrientation();
- }
+ orientation = sDB2Manager.GetCurveValueAt(m_areaTriggerData->FacingCurveId, GetProgress());
+ if (HasAreaTriggerFlag(AreaTriggerFieldFlags::AbsoluteOrientation))
+ orientation += m_areaTriggerData->Facing;
}
GetMap()->AreaTriggerRelocation(this, x, y, z, orientation);
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.h b/src/server/game/Entities/AreaTrigger/AreaTrigger.h
index 67074b04d36..6d10f853063 100644
--- a/src/server/game/Entities/AreaTrigger/AreaTrigger.h
+++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.h
@@ -39,6 +39,32 @@ namespace Movement
class Spline;
}
+enum class AreaTriggerFieldFlags : uint32
+{
+ None = 0x0000,
+ HeightIgnoresScale = 0x0001,
+ WowLabsCircle = 0x0002,
+ CanLoop = 0x0004,
+ AbsoluteOrientation = 0x0008,
+ DynamicShape = 0x0010,
+ Attached = 0x0020,
+ FaceMovementDir = 0x0040,
+ FollowsTerrain = 0x0080,
+ Unknown1025 = 0x0100,
+ AlwaysExterior = 0x0200,
+ HasPlayers = 0x0400,
+};
+
+DEFINE_ENUM_FLAG(AreaTriggerFieldFlags);
+
+enum class AreaTriggerPathType : int32
+{
+ Spline = 0,
+ Orbit = 1,
+ None = 2,
+ MovementScript = 3
+};
+
class TC_GAME_API AreaTrigger final : public WorldObject, public GridObject<AreaTrigger>, public MapObject
{
public:
@@ -97,9 +123,13 @@ class TC_GAME_API AreaTrigger final : public WorldObject, public GridObject<Area
bool IsRemoved() const { return _isRemoved; }
uint32 GetSpellId() const { return m_areaTriggerData->SpellID; }
AuraEffect const* GetAuraEffect() const { return _aurEff; }
- uint32 GetTimeSinceCreated() const { return _timeSinceCreated; }
+ uint32 GetTimeSinceCreated() const;
- void SetHeightIgnoresScale(bool heightIgnoresScale) { SetUpdateFieldValue(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::HeightIgnoresScale), heightIgnoresScale); }
+ EnumFlag<AreaTriggerFieldFlags> GetAreaTriggerFlags() const { return static_cast<AreaTriggerFieldFlags>(*m_areaTriggerData->Flags); }
+ bool HasAreaTriggerFlag(AreaTriggerFieldFlags flag) const { return GetAreaTriggerFlags().HasFlag(flag); }
+ void SetAreaTriggerFlag(AreaTriggerFieldFlags flag) { SetUpdateFieldFlagValue(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::Flags), uint32(flag)); }
+ void RemoveAreaTriggerFlag(AreaTriggerFieldFlags flag) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::Flags), uint32(flag)); }
+ void ReplaceAllAreaTriggerFlags(AreaTriggerFieldFlags flag) { SetUpdateFieldValue(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::Flags), uint32(flag)); }
void SetOverrideScaleCurve(float overrideScale);
void SetOverrideScaleCurve(std::array<DBCPosition2D, 2> const& points, Optional<uint32> startTimeOffset = {}, CurveInterpolationMode interpolation = CurveInterpolationMode::Linear);
@@ -147,19 +177,17 @@ class TC_GAME_API AreaTrigger final : public WorldObject, public GridObject<Area
uint32 GetFaction() const override;
- AreaTriggerShapeInfo const& GetShape() const { return _shape; }
+ void SetShape(AreaTriggerShapeInfo const& shape);
float GetMaxSearchRadius() const;
- Position const& GetRollPitchYaw() const { return _rollPitchYaw; }
- Position const& GetTargetRollPitchYaw() const { return _targetRollPitchYaw; }
void InitSplineOffsets(std::vector<Position> const& offsets, Optional<float> overrideSpeed = {});
void InitSplines(std::vector<G3D::Vector3> const& splinePoints, Optional<float> overrideSpeed = {});
- bool HasSplines() const { return std::holds_alternative<std::unique_ptr<::Movement::Spline<float>>>(_movement); }
- ::Movement::Spline<float> const& GetSpline() const { return *std::get<std::unique_ptr<::Movement::Spline<float>>>(_movement); }
- uint32 GetElapsedTimeForMovement() const { return GetTimeSinceCreated(); } /// @todo: research the right value, in sniffs both timers are nearly identical
+ bool HasSplines() const { return _spline != nullptr; }
+ ::Movement::Spline<float> const& GetSpline() const { return *_spline; }
+ uint32 GetElapsedTimeForMovement() const;
void InitOrbit(AreaTriggerOrbitInfo const& orbit, Optional<float> overrideSpeed = {});
- bool HasOrbit() const { return std::holds_alternative<std::unique_ptr<AreaTriggerOrbitInfo>>(_movement); }
- AreaTriggerOrbitInfo const& GetOrbit() const { return *std::get<std::unique_ptr<AreaTriggerOrbitInfo>>(_movement); }
+ bool HasOrbit() const { return m_areaTriggerData->PathData.Is<UF::AreaTriggerOrbit>(); }
+ UF::AreaTriggerOrbit const& GetOrbit() const { return *m_areaTriggerData->PathData.Get<UF::AreaTriggerOrbit>(); }
bool HasOverridePosition() const;
@@ -184,20 +212,20 @@ class TC_GAME_API AreaTrigger final : public WorldObject, public GridObject<Area
void UpdateTargetList();
void SearchUnits(std::vector<Unit*>& targetList, float radius, bool check3D);
- void SearchUnitInSphere(std::vector<Unit*>& targetList);
- void SearchUnitInBox(std::vector<Unit*>& targetList);
- void SearchUnitInPolygon(std::vector<Unit*>& targetList);
- void SearchUnitInCylinder(std::vector<Unit*>& targetList);
- void SearchUnitInDisk(std::vector<Unit*>& targetList);
- void SearchUnitInBoundedPlane(std::vector<Unit*>& targetList);
+ void SearchUnitInSphere(UF::AreaTriggerSphere const& sphere, std::vector<Unit*>& targetList);
+ void SearchUnitInBox(UF::AreaTriggerBox const& box, std::vector<Unit*>& targetList);
+ void SearchUnitInPolygon(UF::AreaTriggerPolygon const& polygon, std::vector<Unit*>& targetList);
+ void SearchUnitInCylinder(UF::AreaTriggerCylinder const& cylinder, std::vector<Unit*>& targetList);
+ void SearchUnitInDisk(UF::AreaTriggerDisk const& disk, std::vector<Unit*>& targetList);
+ void SearchUnitInBoundedPlane(UF::AreaTriggerBoundedPlane const& boundedPlane, std::vector<Unit*>& targetList);
void HandleUnitEnterExit(std::vector<Unit*> const& targetList);
void DoActions(Unit* unit);
void UndoActions(Unit* unit);
void UpdatePolygonVertices();
- void UpdateOrbitPosition(AreaTriggerOrbitInfo& orbit, uint32 diff);
- void UpdateSplinePosition(Movement::Spline<float>& spline, uint32 diff);
+ void UpdateOrbitPosition();
+ void UpdateSplinePosition(Movement::Spline<float>& spline);
void UpdateOverridePosition();
Position const* GetOrbitCenterPosition() const;
@@ -212,21 +240,16 @@ class TC_GAME_API AreaTrigger final : public WorldObject, public GridObject<Area
AuraEffect const* _aurEff;
Position _stationaryPosition;
- AreaTriggerShapeInfo _shape;
int32 _duration;
int32 _totalDuration;
- uint32 _timeSinceCreated;
float _verticesUpdatePreviousOrientation;
bool _isRemoved;
- Position _rollPitchYaw;
- Position _targetRollPitchYaw;
std::vector<Position> _polygonVertices;
- std::variant<std::monostate, std::unique_ptr<::Movement::Spline<float>>, std::unique_ptr<AreaTriggerOrbitInfo>> _movement;
+ std::unique_ptr<::Movement::Spline<float>> _spline;
bool _reachedDestination;
int32 _lastSplineIndex;
- uint32 _movementTime;
AreaTriggerCreateProperties const* _areaTriggerCreateProperties;
AreaTriggerTemplate const* _areaTriggerTemplate;
diff --git a/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h b/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h
index 5dba3e6b499..74ce4e2be79 100644
--- a/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h
+++ b/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h
@@ -193,9 +193,7 @@ struct AreaTriggerOrbitInfo
Optional<TaggedPosition<Position::XYZ>> Center;
bool CounterClockwise = false;
bool CanLoop = false;
- uint32 TimeToTarget = 0;
- int32 ElapsedTimeForMovement = 0;
- uint32 StartDelay = 0;
+ int32 ExtraTimeForBlending = 0;
float Radius = 0.0f;
float BlendFromRadius = 0.0f;
float InitialAngle = 0.0f;
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 1331c819578..472610d4c0f 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -195,6 +195,7 @@ WorldPacket CreatureTemplate::BuildQueryData(LocaleConstant loc, Difficulty diff
stats.Flags[0] = creatureDifficulty->TypeFlags;
stats.Flags[1] = creatureDifficulty->TypeFlags2;
+ stats.Flags[2] = creatureDifficulty->TypeFlags3;
stats.CreatureType = type;
stats.CreatureFamily = family;
@@ -273,6 +274,7 @@ CreatureDifficulty const* CreatureTemplate::GetDifficulty(Difficulty difficulty)
CreatureDifficultyID = 0;
TypeFlags = 0;
TypeFlags2 = 0;
+ TypeFlags3 = 0;
LootID = 0;
PickPocketLootID = 0;
SkinLootID = 0;
diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h
index 1f4f4b5e216..81fcb06a14f 100644
--- a/src/server/game/Entities/Creature/CreatureData.h
+++ b/src/server/game/Entities/Creature/CreatureData.h
@@ -456,6 +456,7 @@ struct CreatureDifficulty
int32 CreatureDifficultyID;
uint32 TypeFlags;
uint32 TypeFlags2;
+ uint32 TypeFlags3;
uint32 LootID;
uint32 PickPocketLootID;
uint32 SkinLootID;
diff --git a/src/server/game/Entities/GameObject/GameObjectData.h b/src/server/game/Entities/GameObject/GameObjectData.h
index 16f4896d968..1938d8d36d4 100644
--- a/src/server/game/Entities/GameObject/GameObjectData.h
+++ b/src/server/game/Entities/GameObject/GameObjectData.h
@@ -707,7 +707,7 @@ struct GameObjectTemplate
uint32 radius; // 4 radius, int, Min value: 0, Max value: 50, Default value: 10
uint32 InteractRadiusOverride; // 5 Interact Radius Override (Yards * 100), int, Min value: 0, Max value: 2147483647, Default value: 0
uint32 ItemInteractionID; // 6 Item Interaction ID, References: UiItemInteraction, NoValue = 0
- uint32 PlayerInteractionType; // 7 Player Interaction Type, enum { None, TradePartner, Item, Gossip, QuestGiver, Merchant, TaxiNode, Trainer, Banker, AlliedRaceDetailsGiver, GuildBanker, Registrar, Vendor, PetitionVendor, GuildTabardVendor, TalentMaster, SpecializationMaster, MailInfo, SpiritHealer, AreaSpiritHealer, Binder, Auctioneer, StableMaster, BattleMaster, Transmogrifier, LFGDungeon, VoidStorageBanker, BlackMarketAuctioneer, AdventureMap, WorldMap, GarrArchitect, GarrTradeskill, GarrMission, ShipmentCrafter, GarrRecruitment, GarrTalent, Trophy, PlayerChoice, ArtifactForge, ObliterumForge, ScrappingMachine, ContributionCollector, AzeriteRespec, IslandQueue, ItemInteraction, ChromieTime, CovenantPreview, AnimaDiversion, LegendaryCrafting, WeeklyRewards, Soulbind, CovenantSanctum, NewPlayerGuide, ItemUpgrade, AdventureJournal, Renown, AzeriteForge, PerksProgramVendor, ProfessionsCraftingOrder, Professions, ProfessionsCustomerOrder, TraitSystem, BarbersChoice, JailersTowerBuffs, MajorFactionRenown, PersonalTabardVendor, ForgeMaster, CharacterBanker, AccountBanker, ProfessionRespec, PlaceholderType71, PlaceholderType72, PlaceholderType73, PlaceholderType74, PlaceholderType75, PlaceholderType76, PlaceholderType77, }; Default: None
+ uint32 PlayerInteractionType; // 7 Player Interaction Type, enum { None, TradePartner, Item, Gossip, QuestGiver, Merchant, TaxiNode, Trainer, Banker, AlliedRaceDetailsGiver, GuildBanker, Registrar, Vendor, PetitionVendor, GuildTabardVendor, TalentMaster, SpecializationMaster, MailInfo, SpiritHealer, AreaSpiritHealer, Binder, Auctioneer, StableMaster, BattleMaster, Transmogrifier, LFGDungeon, VoidStorageBanker, BlackMarketAuctioneer, AdventureMap, WorldMap, GarrArchitect, GarrTradeskill, GarrMission, ShipmentCrafter, GarrRecruitment, GarrTalent, Trophy, PlayerChoice, ArtifactForge, ObliterumForge, ScrappingMachine, ContributionCollector, AzeriteRespec, IslandQueue, ItemInteraction, ChromieTime, CovenantPreview, AnimaDiversion, LegendaryCrafting, WeeklyRewards, Soulbind, CovenantSanctum, NewPlayerGuide, ItemUpgrade, AdventureJournal, Renown, AzeriteForge, PerksProgramVendor, ProfessionsCraftingOrder, Professions, ProfessionsCustomerOrder, TraitSystem, BarbersChoice, JailersTowerBuffs, MajorFactionRenown, PersonalTabardVendor, ForgeMaster, CharacterBanker, AccountBanker, ProfessionRespec, PlaceholderType71, PlaceholderType72, PlaceholderType73, PlaceholderType74, PlaceholderType75, PlaceholderType76, GuildRename, PlaceholderType76, }; Default: None
} UILink;
// 49 GAMEOBJECT_TYPE_KEYSTONE_RECEPTACLE
struct
@@ -838,6 +838,19 @@ struct GameObjectTemplate
uint32 Script; // 0 Script, References: SpellScript, NoValue = 0
uint32 autoClose; // 1 autoClose (ms), int, Min value: 0, Max value: 2147483647, Default value: 3000
} PerksProgramChest;
+ // 63 GAMEOBJECT_TYPE_FUTURE_PATCH
+ struct
+ {
+ } futurePatchGameObject;
+ // 64 GAMEOBJECT_TYPE_ASSIST_ACTION
+ struct
+ {
+ uint32 AssistActionType; // 0 Assist Action Type, enum { None, Lounging Player, Grave Marker, Placed VO, Player Guardian, Player Slayer, Captured Buff, }; Default: None
+ uint32 cooldown; // 1 cooldown, int, Min value: 0, Max value: 2147483647, Default value: 3000
+ uint32 gossipID; // 2 gossipID, References: Gossip, NoValue = 0
+ uint32 spell; // 3 spell, References: Spell, NoValue = 0
+ uint32 playerCast; // 4 playerCast, enum { false, true, }; Default: false
+ } assistAction;
struct
{
uint32 data[MAX_GAMEOBJECT_DATA];
@@ -1114,6 +1127,8 @@ struct GameObjectTemplate
{
case GAMEOBJECT_TYPE_QUESTGIVER: return questgiver.gossipID;
case GAMEOBJECT_TYPE_GOOBER: return goober.gossipID;
+ case GAMEOBJECT_TYPE_SPELL_FOCUS: return spellFocus.gossipID;
+ case GAMEOBJECT_TYPE_ASSIST_ACTION: return assistAction.gossipID;
default: return 0;
}
}
@@ -1216,8 +1231,9 @@ struct GameObjectTemplate
{
switch (type)
{
- case GAMEOBJECT_TYPE_TRAP: return trap.cooldown;
- case GAMEOBJECT_TYPE_GOOBER: return goober.cooldown;
+ case GAMEOBJECT_TYPE_TRAP: return trap.cooldown;
+ case GAMEOBJECT_TYPE_GOOBER: return goober.cooldown;
+ case GAMEOBJECT_TYPE_ASSIST_ACTION: return assistAction.cooldown;
default: return 0;
}
}
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index 247517163df..a3b1187cbff 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -141,9 +141,6 @@ void AddItemsSetItem(Player* player, Item const* item)
if (itemSetSpell->Threshold > eff->EquippedItems.size())
continue;
- if (eff->SetBonuses.count(itemSetSpell))
- continue;
-
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemSetSpell->SpellID, DIFFICULTY_NONE);
if (!spellInfo)
{
@@ -151,10 +148,17 @@ void AddItemsSetItem(Player* player, Item const* item)
continue;
}
- eff->SetBonuses.insert(itemSetSpell);
+ if (!eff->SetBonuses.insert(itemSetSpell).second)
+ continue;
+
// spell cast only if fit form requirement, in other case will cast at form change
- if (!itemSetSpell->ChrSpecID || ChrSpecialization(itemSetSpell->ChrSpecID) == player->GetPrimarySpecialization())
- player->ApplyEquipSpell(spellInfo, nullptr, true);
+ if (itemSetSpell->ChrSpecID && ChrSpecialization(itemSetSpell->ChrSpecID) != player->GetPrimarySpecialization())
+ continue;
+
+ if (itemSetSpell->TraitSubTreeID && int32(itemSetSpell->TraitSubTreeID) != player->m_playerData->CurrentCombatTraitConfigSubTreeID)
+ continue;
+
+ player->ApplyEquipSpell(spellInfo, nullptr, true);
}
}
}
@@ -196,11 +200,10 @@ void RemoveItemsSetItem(Player* player, Item const* item)
if (itemSetSpell->Threshold <= eff->EquippedItems.size())
continue;
- if (!eff->SetBonuses.count(itemSetSpell))
+ if (!eff->SetBonuses.erase(itemSetSpell))
continue;
player->ApplyEquipSpell(sSpellMgr->AssertSpellInfo(itemSetSpell->SpellID, DIFFICULTY_NONE), nullptr, false);
- eff->SetBonuses.erase(itemSetSpell);
}
}
@@ -224,7 +227,8 @@ void UpdateItemSetAuras(Player* player, bool formChange)
{
SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itemSetSpell->SpellID, DIFFICULTY_NONE);
- if (itemSetSpell->ChrSpecID && ChrSpecialization(itemSetSpell->ChrSpecID) != player->GetPrimarySpecialization())
+ if ((itemSetSpell->ChrSpecID && ChrSpecialization(itemSetSpell->ChrSpecID) != player->GetPrimarySpecialization())
+ || (itemSetSpell->TraitSubTreeID && int32(itemSetSpell->TraitSubTreeID) != player->m_playerData->CurrentCombatTraitConfigSubTreeID))
player->ApplyEquipSpell(spellInfo, nullptr, false, false); // item set aura is not for current spec
else
{
diff --git a/src/server/game/Entities/Item/ItemDefines.h b/src/server/game/Entities/Item/ItemDefines.h
index d3278c4987f..0df2bb3bba6 100644
--- a/src/server/game/Entities/Item/ItemDefines.h
+++ b/src/server/game/Entities/Item/ItemDefines.h
@@ -154,6 +154,8 @@ enum InventoryResult : uint8
EQUIP_ERR_BANK_NOT_ACCESSIBLE = 128,// This character does not have access to this bank.
EQUIP_ERR_CANT_TRADE_ACCOUNT_ITEM = 129,// You can't trade an item from the Warband bank.
EQUIP_ERR_ACCOUNT_MONEY_LOCKED = 130,// You cannot withdraw or deposit gold from the warband bank currently; please try again later.
+ EQUIP_ERR_CHARACTER_BANK_NOT_ACCESSIBLE = 131,// This character does not have access to this bank.
+ EQUIP_ERR_CHARACTER_BANK_NOT_CONVERTED = 132,// Your character's bank has not been converted. Please try again later.
};
// EnumUtils: DESCRIBE THIS
diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h
index 42b23f04005..c7d97e22fd0 100644
--- a/src/server/game/Entities/Item/ItemTemplate.h
+++ b/src/server/game/Entities/Item/ItemTemplate.h
@@ -811,6 +811,9 @@ enum ItemIdConstants
ITEM_PURPLE_RIBBONED_HOLIDAY_GIFT = 17308, // Purple Ribboned Holiday Gift
ITEM_EMPTY_WRAPPER = 21830, // Empty Wrapper
ITEM_WRAPPED_GIFT = 21831, // Wrappered Gift
+
+ ITEM_ACCOUNT_BANK_TAB_BAG = 208392, // Account Bank Tab Bag (DNT)
+ ITEM_CHARACTER_BANK_TAB_BAG = 242709, // Character Bank Tab Bag (DNT)
};
class Player;
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index eaea679d01a..d5b732a145e 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -16,8 +16,6 @@
*/
#include "Object.h"
-#include "AreaTriggerPackets.h"
-#include "AreaTriggerTemplate.h"
#include "BattlefieldMgr.h"
#include "CellImpl.h"
#include "CinematicMgr.h"
@@ -46,7 +44,6 @@
#include "SpellAuraEffects.h"
#include "SpellMgr.h"
#include "SpellPackets.h"
-#include "StringConvert.h"
#include "TemporarySummon.h"
#include "Totem.h"
#include "Transport.h"
@@ -310,6 +307,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Playe
data->WriteBit(flags.NoBirthAnim);
data->WriteBit(flags.EnablePortals);
data->WriteBit(flags.PlayHoverAnim);
+ data->WriteBit(flags.ThisIsYou);
data->WriteBit(flags.MovementUpdate);
data->WriteBit(flags.MovementTransport);
data->WriteBit(flags.Stationary);
@@ -318,10 +316,8 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Playe
data->WriteBit(flags.Vehicle);
data->WriteBit(flags.AnimKit);
data->WriteBit(flags.Rotation);
- data->WriteBit(flags.AreaTrigger);
data->WriteBit(flags.GameObject);
data->WriteBit(flags.SmoothPhasing);
- data->WriteBit(flags.ThisIsYou);
data->WriteBit(flags.SceneObject);
data->WriteBit(flags.ActivePlayer);
data->WriteBit(flags.Conversation);
@@ -329,7 +325,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Playe
if (flags.MovementUpdate)
{
- Unit const* unit = ToUnit();
+ Unit const* unit = static_cast<Unit const*>(this);
bool HasFallDirection = unit->HasUnitMovementFlag(MOVEMENTFLAG_FALLING);
bool HasFall = HasFallDirection || unit->m_movementInfo.jump.fallTime != 0;
bool HasSpline = unit->IsSplineEnabled();
@@ -470,14 +466,17 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Playe
}
if (flags.CombatVictim)
- *data << ToUnit()->GetVictim()->GetGUID(); // CombatVictim
+ {
+ Unit const* unit = static_cast<Unit const*>(this);
+ *data << unit->GetVictim()->GetGUID(); // CombatVictim
+ }
if (flags.ServerTime)
*data << uint32(GameTime::GetGameTimeMS());
if (flags.Vehicle)
{
- Unit const* unit = ToUnit();
+ Unit const* unit = static_cast<Unit const*>(this);
*data << uint32(unit->GetVehicleKit()->GetVehicleInfo()->ID); // RecID
*data << float(unit->GetOrientation()); // InitialRawFacing
}
@@ -491,7 +490,10 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Playe
}
if (flags.Rotation)
- *data << uint64(ToGameObject()->GetPackedLocalRotation()); // Rotation
+ {
+ GameObject const* gameObject = static_cast<GameObject const*>(this);
+ *data << uint64(gameObject->GetPackedLocalRotation()); // Rotation
+ }
if (PauseTimes && !PauseTimes->empty())
data->append(PauseTimes->data(), PauseTimes->size());
@@ -502,144 +504,9 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Playe
*data << self->m_movementInfo.transport;
}
- if (flags.AreaTrigger)
- {
- AreaTrigger const* areaTrigger = static_cast<AreaTrigger const*>(this);
- AreaTriggerCreateProperties const* createProperties = areaTrigger->GetCreateProperties();
- AreaTriggerShapeInfo const& shape = areaTrigger->GetShape();
-
- *data << uint32(areaTrigger->GetTimeSinceCreated());
-
- *data << areaTrigger->GetRollPitchYaw().PositionXYZStream();
-
- switch (shape.Type)
- {
- case AreaTriggerShapeType::Sphere:
- *data << int8(0);
- *data << float(shape.SphereDatas.Radius);
- *data << float(shape.SphereDatas.RadiusTarget);
- break;
- case AreaTriggerShapeType::Box:
- *data << int8(1);
- *data << float(shape.BoxDatas.Extents[0]);
- *data << float(shape.BoxDatas.Extents[1]);
- *data << float(shape.BoxDatas.Extents[2]);
- *data << float(shape.BoxDatas.ExtentsTarget[0]);
- *data << float(shape.BoxDatas.ExtentsTarget[1]);
- *data << float(shape.BoxDatas.ExtentsTarget[2]);
- break;
- case AreaTriggerShapeType::Polygon:
- *data << int8(3);
- *data << int32(shape.PolygonVertices.size());
- *data << int32(shape.PolygonVerticesTarget.size());
- *data << float(shape.PolygonDatas.Height);
- *data << float(shape.PolygonDatas.HeightTarget);
-
- for (TaggedPosition<Position::XY> const& vertice : shape.PolygonVertices)
- *data << vertice;
-
- for (TaggedPosition<Position::XY> const& vertice : shape.PolygonVerticesTarget)
- *data << vertice;
- break;
- case AreaTriggerShapeType::Cylinder:
- *data << int8(4);
- *data << float(shape.CylinderDatas.Radius);
- *data << float(shape.CylinderDatas.RadiusTarget);
- *data << float(shape.CylinderDatas.Height);
- *data << float(shape.CylinderDatas.HeightTarget);
- *data << float(shape.CylinderDatas.LocationZOffset);
- *data << float(shape.CylinderDatas.LocationZOffsetTarget);
- break;
- case AreaTriggerShapeType::Disk:
- *data << int8(7);
- *data << float(shape.DiskDatas.InnerRadius);
- *data << float(shape.DiskDatas.InnerRadiusTarget);
- *data << float(shape.DiskDatas.OuterRadius);
- *data << float(shape.DiskDatas.OuterRadiusTarget);
- *data << float(shape.DiskDatas.Height);
- *data << float(shape.DiskDatas.HeightTarget);
- *data << float(shape.DiskDatas.LocationZOffset);
- *data << float(shape.DiskDatas.LocationZOffsetTarget);
- break;
- case AreaTriggerShapeType::BoundedPlane:
- *data << int8(8);
- *data << float(shape.BoundedPlaneDatas.Extents[0]);
- *data << float(shape.BoundedPlaneDatas.Extents[1]);
- *data << float(shape.BoundedPlaneDatas.ExtentsTarget[0]);
- *data << float(shape.BoundedPlaneDatas.ExtentsTarget[1]);
- break;
- default:
- break;
- }
-
- bool hasAbsoluteOrientation = createProperties && createProperties->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasAbsoluteOrientation);
- bool hasDynamicShape = createProperties && createProperties->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasDynamicShape);
- bool hasAttached = createProperties && createProperties->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasAttached);
- bool hasFaceMovementDir = createProperties && createProperties->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasFaceMovementDir);
- bool hasFollowsTerrain = createProperties && createProperties->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasFollowsTerrain);
- bool hasAlwaysExterior = createProperties && createProperties->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::AlwaysExterior);
- bool hasUnknown1025 = false;
- bool hasTargetRollPitchYaw = createProperties && createProperties->Flags.HasFlag(AreaTriggerCreatePropertiesFlag::HasTargetRollPitchYaw);
- bool hasScaleCurveID = createProperties && createProperties->ScaleCurveId != 0;
- bool hasMorphCurveID = createProperties && createProperties->MorphCurveId != 0;
- bool hasFacingCurveID = createProperties && createProperties->FacingCurveId != 0;
- bool hasMoveCurveID = createProperties && createProperties->MoveCurveId != 0;
- bool hasMovementScript = false;
- bool hasPositionalSoundKitID= false;
-
- data->WriteBit(hasAbsoluteOrientation);
- data->WriteBit(hasDynamicShape);
- data->WriteBit(hasAttached);
- data->WriteBit(hasFaceMovementDir);
- data->WriteBit(hasFollowsTerrain);
- data->WriteBit(hasAlwaysExterior);
- data->WriteBit(hasUnknown1025);
- data->WriteBit(hasTargetRollPitchYaw);
- data->WriteBit(hasScaleCurveID);
- data->WriteBit(hasMorphCurveID);
- data->WriteBit(hasFacingCurveID);
- data->WriteBit(hasMoveCurveID);
- data->WriteBit(hasPositionalSoundKitID);
- data->WriteBit(areaTrigger->HasSplines());
- data->WriteBit(areaTrigger->HasOrbit());
- data->WriteBit(hasMovementScript);
-
- data->FlushBits();
-
- if (areaTrigger->HasSplines())
- WorldPackets::AreaTrigger::WriteAreaTriggerSpline(*data, areaTrigger->GetTimeToTarget(), areaTrigger->GetElapsedTimeForMovement(), areaTrigger->GetSpline());
-
- if (hasTargetRollPitchYaw)
- *data << areaTrigger->GetTargetRollPitchYaw().PositionXYZStream();
-
- if (hasScaleCurveID)
- *data << uint32(createProperties->ScaleCurveId);
-
- if (hasMorphCurveID)
- *data << uint32(createProperties->MorphCurveId);
-
- if (hasFacingCurveID)
- *data << uint32(createProperties->FacingCurveId);
-
- if (hasMoveCurveID)
- *data << uint32(createProperties->MoveCurveId);
-
- if (hasPositionalSoundKitID)
- *data << uint32(0);
-
- //if (hasMovementScript)
- // *data << *areaTrigger->GetMovementScript(); // AreaTriggerMovementScriptInfo
-
- if (areaTrigger->HasOrbit())
- {
- using WorldPackets::AreaTrigger::operator<<;
- *data << areaTrigger->GetOrbit();
- }
- }
-
if (flags.GameObject)
{
- GameObject const* gameObject = ToGameObject();
+ GameObject const* gameObject = static_cast<GameObject const*>(this);
Transport const* transport = gameObject->ToTransport();
bool bit8 = false;
@@ -794,10 +661,10 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Playe
if (flags.ActivePlayer)
{
- Player const* player = ToPlayer();
+ Player const* player = static_cast<Player const*>(this);
bool HasSceneInstanceIDs = !player->GetSceneMgr().GetSceneTemplateByInstanceMap().empty();
- bool HasRuneState = ToUnit()->GetPowerIndex(POWER_RUNES) != MAX_POWERS;
+ bool HasRuneState = player->GetPowerIndex(POWER_RUNES) != MAX_POWERS;
data->WriteBit(HasSceneInstanceIDs);
data->WriteBit(HasRuneState);
@@ -805,8 +672,8 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Playe
if (HasSceneInstanceIDs)
{
*data << uint32(player->GetSceneMgr().GetSceneTemplateByInstanceMap().size());
- for (auto const& itr : player->GetSceneMgr().GetSceneTemplateByInstanceMap())
- *data << uint32(itr.first);
+ for (auto const& [sceneInstanceId, _] : player->GetSceneMgr().GetSceneTemplateByInstanceMap())
+ *data << uint32(sceneInstanceId);
}
if (HasRuneState)
{
@@ -823,7 +690,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Playe
if (flags.Conversation)
{
- Conversation const* self = ToConversation();
+ Conversation const* self = static_cast<Conversation const*>(this);
if (data->WriteBit(self->GetTextureKitId() != 0))
*data << uint32(self->GetTextureKitId());
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index b5940dc0b73..971b74494e0 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -93,7 +93,6 @@ struct CreateObjectBits
bool Vehicle : 1;
bool AnimKit : 1;
bool Rotation : 1;
- bool AreaTrigger : 1;
bool GameObject : 1;
bool SmoothPhasing : 1;
bool ThisIsYou : 1;
diff --git a/src/server/game/Entities/Object/Updates/UpdateField.h b/src/server/game/Entities/Object/Updates/UpdateField.h
index ef802f8447d..874b38d87d8 100644
--- a/src/server/game/Entities/Object/Updates/UpdateField.h
+++ b/src/server/game/Entities/Object/Updates/UpdateField.h
@@ -23,6 +23,7 @@
#include "UpdateMask.h"
#include <algorithm>
#include <memory>
+#include <variant>
#include <vector>
class ByteBuffer;
@@ -68,6 +69,15 @@ namespace UF
template<typename T, int32 BlockBit, uint32 Bit>
class OptionalUpdateField;
+ template<typename T>
+ inline constexpr std::type_identity<T> VariantCase;
+
+ template<typename... Types>
+ class VariantUpdateFieldBase;
+
+ template<int32 BlockBit, uint32 Bit, typename... Types>
+ class VariantUpdateField;
+
template<typename T, bool PublicSet>
struct MutableFieldReferenceWithChangesMask;
@@ -352,6 +362,24 @@ namespace UF
return { *((_value.*field)._value) };
}
+ template<typename V, int32 BlockBit, uint32 Bit, typename... Types>
+ std::conditional_t<std::is_base_of_v<IsUpdateFieldStructureTag, V>,
+ MutableFieldReference<V, PublicSet>,
+ std::conditional_t<std::is_base_of_v<IsUpdateFieldHolderTag, V>,
+ MutableNestedFieldReference<V, PublicSet>,
+ UpdateFieldSetter<V, PublicSet>>>
+ ModifyValue(VariantUpdateField<BlockBit, Bit, Types...>(T::* field), [[maybe_unused]] std::type_identity<V> type)
+ {
+ if (!(_value.*field).template Is<V>())
+ (_value.*field).template ConstructValue<V>();
+
+ if constexpr (BlockBit >= 0)
+ _value._changesMask.Set(BlockBit);
+
+ _value._changesMask.Set(Bit);
+ return { *((_value.*field).template Get<V>()) };
+ }
+
private:
T& _value;
};
@@ -538,6 +566,17 @@ namespace UF
_changesMask.Set(Bit);
}
+ template<typename Derived, int32 BlockBit, uint32 Bit, typename... Types>
+ void MarkChanged(VariantUpdateField<BlockBit, Bit, Types...>(Derived::*))
+ {
+ static_assert(std::is_base_of_v<Base, Derived>, "Given field argument must belong to the same structure as this HasChangesMask");
+
+ if constexpr (BlockBit >= 0)
+ _changesMask.Set(BlockBit);
+
+ _changesMask.Set(Bit);
+ }
+
template<typename Derived, typename T, int32 BlockBit, uint32 Bit>
void ClearChanged(UpdateField<T, BlockBit, Bit>(Derived::*))
{
@@ -578,6 +617,14 @@ namespace UF
_changesMask.Reset(Bit);
}
+ template<typename Derived, int32 BlockBit, uint32 Bit, typename... Types>
+ void ClearChanged(VariantUpdateField<BlockBit, Bit, Types...>(Derived::*))
+ {
+ static_assert(std::is_base_of_v<Base, Derived>, "Given field argument must belong to the same structure as this HasChangesMask");
+
+ _changesMask.Reset(Bit);
+ }
+
Mask const& GetChangesMask() const { return _changesMask; }
protected:
@@ -614,6 +661,17 @@ namespace UF
field._value->ClearChangesMask();
}
+ template<int32 BlockBit, uint32 Bit, typename... Types>
+ static void ClearChangesMask(VariantUpdateField<BlockBit, Bit, Types...>& field)
+ {
+ if constexpr ((std::is_base_of_v<HasChangesMaskTag, Types> || ...))
+ std::visit([]<typename T>(T& value)
+ {
+ if constexpr (std::is_base_of_v<HasChangesMaskTag, T>)
+ value.ClearChangesMask();
+ }, field._value);
+ }
+
Mask _changesMask;
};
@@ -894,6 +952,64 @@ namespace UF
{
};
+ template<typename... Types>
+ class VariantUpdateFieldBase : public IsUpdateFieldHolderTag
+ {
+ template<typename F, bool PublicSet>
+ friend struct MutableFieldReferenceWithChangesMask;
+
+ template<typename F, bool PublicSet>
+ friend struct MutableFieldReferenceNoChangesMask;
+
+ template<typename F, bool PublicSet>
+ friend struct MutableNestedFieldReference;
+
+ template<std::size_t Bits>
+ friend class HasChangesMask;
+
+ friend class UpdateFieldHolder;
+
+ public:
+ template<typename T>
+ bool Is() const { return std::holds_alternative<T>(_value); }
+
+ template<typename T>
+ T const* Get() const noexcept
+ {
+ if (std::holds_alternative<T>(_value))
+ return &std::get<T>(_value);
+ return nullptr;
+ }
+
+ template<typename Visitor>
+ decltype(auto) Visit(Visitor&& visitor) const noexcept
+ {
+ return std::visit(std::forward<Visitor>(visitor), _value);
+ }
+
+ private:
+ template<typename T>
+ void ConstructValue()
+ {
+ _value.template emplace<T>();
+ }
+
+ template<typename T>
+ T* Get() noexcept
+ {
+ if (std::holds_alternative<T>(_value))
+ return &std::get<T>(_value);
+ return nullptr;
+ }
+
+ std::variant<std::monostate, Types...> _value;
+ };
+
+ template<int32 BlockBit, uint32 Bit, typename... Types>
+ class VariantUpdateField : public VariantUpdateFieldBase<Types...>
+ {
+ };
+
template<typename T>
struct ViewerDependentValueTag
{
diff --git a/src/server/game/Entities/Object/Updates/UpdateFields.cpp b/src/server/game/Entities/Object/Updates/UpdateFields.cpp
index a86aa7f9988..f70dc26de37 100644
--- a/src/server/game/Entities/Object/Updates/UpdateFields.cpp
+++ b/src/server/game/Entities/Object/Updates/UpdateFields.cpp
@@ -20,6 +20,7 @@
#include "ByteBuffer.h"
#include "Corpse.h"
#include "DynamicObject.h"
+#include "PacketOperators.h"
#include "Player.h"
#include "ViewerDependentValues.h"
@@ -852,18 +853,24 @@ void UnitChannel::WriteCreate(ByteBuffer& data, Unit const* owner, Player const*
{
data << int32(SpellID);
SpellVisual.WriteCreate(data, owner, receiver);
+ data << uint32(StartTimeMs);
+ data << uint32(Duration);
}
void UnitChannel::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Unit const* owner, Player const* receiver) const
{
data << int32(SpellID);
SpellVisual.WriteUpdate(data, ignoreChangesMask, owner, receiver);
+ data << uint32(StartTimeMs);
+ data << uint32(Duration);
}
bool UnitChannel::operator==(UnitChannel const& right) const
{
return SpellID == right.SpellID
- && SpellVisual == right.SpellVisual;
+ && SpellVisual == right.SpellVisual
+ && StartTimeMs == right.StartTimeMs
+ && Duration == right.Duration;
}
void VisibleItem::WriteCreate(ByteBuffer& data, Unit const* owner, Player const* receiver) const
@@ -937,6 +944,51 @@ bool PassiveSpellHistory::operator==(PassiveSpellHistory const& right) const
&& AuraSpellID == right.AuraSpellID;
}
+void UnitAssistActionData::WriteCreate(ByteBuffer& data, Unit const* owner, Player const* receiver) const
+{
+ data << uint8(Type);
+ data << uint32(VirtualRealmAddress);
+ data.WriteBits(PlayerName->size(), 6);
+ data.FlushBits();
+ data << WorldPackets::SizedString::Data(*PlayerName);
+}
+
+void UnitAssistActionData::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Unit const* owner, Player const* receiver) const
+{
+ Mask changesMask = _changesMask;
+ if (ignoreChangesMask)
+ changesMask.SetAll();
+
+ data.WriteBits(changesMask.GetBlock(0), 4);
+
+ data.FlushBits();
+ if (changesMask[0])
+ {
+ if (changesMask[1])
+ {
+ data << uint8(Type);
+ }
+ if (changesMask[3])
+ {
+ data << uint32(VirtualRealmAddress);
+ }
+ if (changesMask[2])
+ {
+ data.WriteBits(PlayerName->size(), 6);
+ data.FlushBits();
+ data << WorldPackets::SizedString::Data(*PlayerName);
+ }
+ }
+}
+
+void UnitAssistActionData::ClearChangesMask()
+{
+ Base::ClearChangesMask(Type);
+ Base::ClearChangesMask(PlayerName);
+ Base::ClearChangesMask(VirtualRealmAddress);
+ _changesMask.ResetAll();
+}
+
void UnitData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Unit const* owner, Player const* receiver) const
{
ViewerDependentValue<StateWorldEffectIDsTag>::value_type stateWorldEffectIDs = {};
@@ -1148,18 +1200,24 @@ void UnitData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisi
{
data << ChannelObjects[i];
}
+ data.FlushBits();
data.WriteBit(Field_314);
+ data.WriteBits(AssistActionData.has_value(), 1);
+ if (AssistActionData.has_value())
+ {
+ AssistActionData->WriteCreate(data, owner, receiver);
+ }
data.FlushBits();
}
static constexpr void UnitDataAppendAllowedFieldsMaskForFlag(UnitData::Mask& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags)
{
if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag::Owner))
- allowedMaskForTarget |= std::array<uint32, 7>{ 0x00010000u, 0xF0040000u, 0xFF080000u, 0x000007FEu, 0xF0000080u, 0xFF80FFFFu, 0x3FFFFFFFu };
+ allowedMaskForTarget |= std::array<uint32, 7>{ 0x00010000u, 0xF0040000u, 0xFF080000u, 0x000007FEu, 0xE0000100u, 0xFF01FFFFu, 0x7FFFFFFFu };
if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag::UnitAll))
- allowedMaskForTarget |= std::array<uint32, 7>{ 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xF0000080u, 0x0000FFFFu, 0x00000000u };
+ allowedMaskForTarget |= std::array<uint32, 7>{ 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xE0000100u, 0x0001FFFFu, 0x00000000u };
if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag::Empath))
- allowedMaskForTarget |= std::array<uint32, 7>{ 0x00000000u, 0xF0000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x0000FF00u };
+ allowedMaskForTarget |= std::array<uint32, 7>{ 0x00000000u, 0xF0000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x0001FE00u };
}
void UnitData::AppendAllowedFieldsMaskForFlag(Mask& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags)
@@ -1169,14 +1227,14 @@ void UnitData::AppendAllowedFieldsMaskForFlag(Mask& allowedMaskForTarget, EnumFl
void UnitData::FilterDisallowedFieldsMaskForFlag(Mask& changesMask, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags)
{
- Mask allowedMaskForTarget({ 0xFFFEFFFFu, 0x0FFBFFFFu, 0x00F7FFFFu, 0xFFFFF801u, 0x0FFFFFFFu, 0x007F0000u, 0x00000000u });
+ Mask allowedMaskForTarget({ 0xFFFEFFFFu, 0x0FFBFFFFu, 0x00F7FFFFu, 0xFFFFF801u, 0x1FFFFFFFu, 0x00FE0000u, 0x00000000u });
UnitDataAppendAllowedFieldsMaskForFlag(allowedMaskForTarget, fieldVisibilityFlags);
changesMask &= allowedMaskForTarget;
}
void UnitData::WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Unit const* owner, Player const* receiver) const
{
- Mask allowedMaskForTarget({ 0xFFFEFFFFu, 0x0FFBFFFFu, 0x00F7FFFFu, 0xFFFFF801u, 0x0FFFFFFFu, 0x007F0000u, 0x00000000u });
+ Mask allowedMaskForTarget({ 0xFFFEFFFFu, 0x0FFBFFFFu, 0x00F7FFFFu, 0xFFFFF801u, 0x1FFFFFFFu, 0x00FE0000u, 0x00000000u });
UnitDataAppendAllowedFieldsMaskForFlag(allowedMaskForTarget, fieldVisibilityFlags);
WriteUpdate(data, _changesMask & allowedMaskForTarget, false, owner, receiver);
}
@@ -1776,84 +1834,93 @@ void UnitData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bool ignor
{
data << *NameplateAttachToGUID;
}
+ data.WriteBits(AssistActionData.has_value(), 1);
+ data.FlushBits();
+ if (changesMask[135])
+ {
+ if (AssistActionData.has_value())
+ {
+ AssistActionData->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ }
+ }
}
- if (changesMask[135])
+ if (changesMask[136])
{
for (uint32 i = 0; i < 10; ++i)
{
- if (changesMask[136 + i])
+ if (changesMask[137 + i])
{
data << int32(Power[i]);
}
- if (changesMask[146 + i])
+ if (changesMask[147 + i])
{
data << int32(MaxPower[i]);
}
- if (changesMask[156 + i])
+ if (changesMask[157 + i])
{
data << float(PowerRegenFlatModifier[i]);
}
- if (changesMask[166 + i])
+ if (changesMask[167 + i])
{
data << float(PowerRegenInterruptedFlatModifier[i]);
}
}
}
- if (changesMask[176])
+ if (changesMask[177])
{
for (uint32 i = 0; i < 3; ++i)
{
- if (changesMask[177 + i])
+ if (changesMask[178 + i])
{
VirtualItems[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
}
}
- if (changesMask[180])
+ if (changesMask[181])
{
for (uint32 i = 0; i < 2; ++i)
{
- if (changesMask[181 + i])
+ if (changesMask[182 + i])
{
data << uint32(AttackRoundBaseTime[i]);
}
}
}
- if (changesMask[183])
+ if (changesMask[184])
{
for (uint32 i = 0; i < 4; ++i)
{
- if (changesMask[184 + i])
+ if (changesMask[185 + i])
{
data << int32(Stats[i]);
}
- if (changesMask[188 + i])
+ if (changesMask[189 + i])
{
data << int32(StatPosBuff[i]);
}
- if (changesMask[192 + i])
+ if (changesMask[193 + i])
{
data << int32(StatNegBuff[i]);
}
- if (changesMask[196 + i])
+ if (changesMask[197 + i])
{
data << int32(StatSupportBuff[i]);
}
}
}
- if (changesMask[200])
+ if (changesMask[201])
{
for (uint32 i = 0; i < 7; ++i)
{
- if (changesMask[201 + i])
+ if (changesMask[202 + i])
{
data << int32(Resistances[i]);
}
- if (changesMask[208 + i])
+ if (changesMask[209 + i])
{
data << int32(BonusResistanceMods[i]);
}
- if (changesMask[215 + i])
+ if (changesMask[216 + i])
{
data << int32(ManaCostModifier[i]);
}
@@ -1994,6 +2061,7 @@ void UnitData::ClearChangesMask()
Base::ClearChangesMask(Field_31C);
Base::ClearChangesMask(Field_320);
Base::ClearChangesMask(NameplateAttachToGUID);
+ Base::ClearChangesMask(AssistActionData);
Base::ClearChangesMask(Power);
Base::ClearChangesMask(MaxPower);
Base::ClearChangesMask(PowerRegenFlatModifier);
@@ -2196,7 +2264,7 @@ void PetCreatureName::WriteCreate(ByteBuffer& data, Player const* owner, Player
{
data << uint32(CreatureID);
data.WriteBits(Name->size(), 8);
- data.WriteString(Name);
+ data << WorldPackets::SizedString::Data(*Name);
data.FlushBits();
}
@@ -2218,7 +2286,7 @@ void PetCreatureName::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Play
if (changesMask[2])
{
data.WriteBits(Name->size(), 8);
- data.WriteString(Name);
+ data << WorldPackets::SizedString::Data(*Name);
}
}
data.FlushBits();
@@ -2252,6 +2320,50 @@ bool CTROptions::operator==(CTROptions const& right) const
&& ChromieTimeExpansionMask == right.ChromieTimeExpansionMask;
}
+void LeaverInfo::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const
+{
+ data << BnetAccountGUID;
+ data << float(LeaveScore);
+ data << uint32(SeasonID);
+ data << uint32(TotalLeaves);
+ data << uint32(TotalSuccesses);
+ data << int32(ConsecutiveSuccesses);
+ data << int64(LastPenaltyTime);
+ data << int64(LeaverExpirationTime);
+ data << int32(Unknown_1120);
+ data.WriteBits(LeaverStatus, 1);
+ data.FlushBits();
+}
+
+void LeaverInfo::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const
+{
+ data << BnetAccountGUID;
+ data << float(LeaveScore);
+ data << uint32(SeasonID);
+ data << uint32(TotalLeaves);
+ data << uint32(TotalSuccesses);
+ data << int32(ConsecutiveSuccesses);
+ data << int64(LastPenaltyTime);
+ data << int64(LeaverExpirationTime);
+ data << int32(Unknown_1120);
+ data.WriteBits(LeaverStatus, 1);
+ data.FlushBits();
+}
+
+bool LeaverInfo::operator==(LeaverInfo const& right) const
+{
+ return BnetAccountGUID == right.BnetAccountGUID
+ && LeaveScore == right.LeaveScore
+ && SeasonID == right.SeasonID
+ && TotalLeaves == right.TotalLeaves
+ && TotalSuccesses == right.TotalSuccesses
+ && ConsecutiveSuccesses == right.ConsecutiveSuccesses
+ && LastPenaltyTime == right.LastPenaltyTime
+ && LeaverExpirationTime == right.LeaverExpirationTime
+ && Unknown_1120 == right.Unknown_1120
+ && LeaverStatus == right.LeaverStatus;
+}
+
void DeclinedNames::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const
{
for (uint32 i = 0; i < 5; ++i)
@@ -2260,7 +2372,7 @@ void DeclinedNames::WriteCreate(ByteBuffer& data, Player const* owner, Player co
}
for (uint32 i = 0; i < 5; ++i)
{
- data.WriteString(Name[i]);
+ data << WorldPackets::SizedString::Data(Name[i]);
}
data.FlushBits();
}
@@ -2292,7 +2404,7 @@ void DeclinedNames::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player
{
if (changesMask[1 + i])
{
- data.WriteString(Name[i]);
+ data << WorldPackets::SizedString::Data(Name[i]);
}
}
}
@@ -2398,6 +2510,7 @@ void PlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVi
data << int32(FakeInebriation);
data << uint32(VirtualPlayerRealm);
data << uint32(CurrentSpecID);
+ data << int32(CurrentCombatTraitConfigSubTreeID);
data << int32(TaxiMountAnimKitID);
for (uint32 i = 0; i < 6; ++i)
{
@@ -2458,7 +2571,8 @@ void PlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVi
data.WriteBit(HasLevelLink);
data.WriteBits(DeclinedNames.has_value(), 1);
data << *DungeonScore;
- data.WriteString(Name);
+ data << WorldPackets::SizedString::Data(*Name);
+ LeaverInfo->WriteCreate(data, owner, receiver);
for (uint32 i = 0; i < 16; ++i)
{
data << VisibleEquipableSpells[i];
@@ -2477,7 +2591,7 @@ void PlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVi
static constexpr void PlayerDataAppendAllowedFieldsMaskForFlag(PlayerData::Mask& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags)
{
if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag::PartyMember))
- allowedMaskForTarget |= std::array<uint32, 11>{ 0x00000022u, 0xFFFE0000u, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x00000001u, 0x00000000u, 0x00000000u, 0x00000000u };
+ allowedMaskForTarget |= std::array<uint32, 11>{ 0x00000022u, 0xFFF80000u, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x00000007u, 0x00000000u, 0x00000000u, 0x00000000u };
}
void PlayerData::AppendAllowedFieldsMaskForFlag(Mask& allowedMaskForTarget, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags)
@@ -2487,14 +2601,14 @@ void PlayerData::AppendAllowedFieldsMaskForFlag(Mask& allowedMaskForTarget, Enum
void PlayerData::FilterDisallowedFieldsMaskForFlag(Mask& changesMask, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags)
{
- Mask allowedMaskForTarget({ 0xFFFFFFDDu, 0x0001FFFFu, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xFFFFFFFEu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x00000003u });
+ Mask allowedMaskForTarget({ 0xFFFFFFDDu, 0x0007FFFFu, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xFFFFFFF8u, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x0000000Fu });
PlayerDataAppendAllowedFieldsMaskForFlag(allowedMaskForTarget, fieldVisibilityFlags);
changesMask &= allowedMaskForTarget;
}
void PlayerData::WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Player const* owner, Player const* receiver) const
{
- Mask allowedMaskForTarget({ 0xFFFFFFDDu, 0x0001FFFFu, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xFFFFFFFEu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x00000003u });
+ Mask allowedMaskForTarget({ 0xFFFFFFDDu, 0x0007FFFFu, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xFFFFFFF8u, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x0000000Fu });
PlayerDataAppendAllowedFieldsMaskForFlag(allowedMaskForTarget, fieldVisibilityFlags);
WriteUpdate(data, _changesMask & allowedMaskForTarget, false, owner, receiver);
}
@@ -2708,74 +2822,82 @@ void PlayerData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bool ign
}
if (changesMask[29])
{
- data << int32(TaxiMountAnimKitID);
+ data << int32(CurrentCombatTraitConfigSubTreeID);
}
if (changesMask[30])
{
- data << uint8(CurrentBattlePetBreedQuality);
+ data << int32(TaxiMountAnimKitID);
}
if (changesMask[31])
{
- data << int32(HonorLevel);
+ data << uint8(CurrentBattlePetBreedQuality);
}
}
if (changesMask[32])
{
if (changesMask[33])
{
+ data << int32(HonorLevel);
+ }
+ if (changesMask[34])
+ {
data << int64(LogoutTime);
}
- if (changesMask[35])
+ if (changesMask[36])
{
data << int32(Field_1AC);
}
- if (changesMask[36])
+ if (changesMask[37])
{
data << int32(Field_1B0);
}
- if (changesMask[37])
+ if (changesMask[38])
{
data << int32(CurrentBattlePetSpeciesID);
}
- if (changesMask[38])
+ if (changesMask[39])
{
CtrOptions->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
- if (changesMask[39])
+ if (changesMask[40])
{
data << int32(CovenantID);
}
- if (changesMask[40])
+ if (changesMask[41])
{
data << int32(SoulbindID);
}
- if (changesMask[42])
+ if (changesMask[44])
{
data << *SpectateTarget;
}
- if (changesMask[43])
+ if (changesMask[45])
{
data << int32(Field_200);
}
- if (changesMask[45])
+ if (changesMask[47])
{
PersonalTabard->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
- if (changesMask[34])
+ if (changesMask[35])
{
data.WriteBits(Name->size(), 6);
}
data.WriteBits(DeclinedNames.has_value(), 1);
data.FlushBits();
- if (changesMask[41])
+ if (changesMask[42])
{
data << *DungeonScore;
}
- if (changesMask[34])
+ if (changesMask[35])
{
- data.WriteString(Name);
+ data << WorldPackets::SizedString::Data(*Name);
}
- if (changesMask[44])
+ if (changesMask[43])
+ {
+ LeaverInfo->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ }
+ if (changesMask[46])
{
if (DeclinedNames.has_value())
{
@@ -2783,21 +2905,21 @@ void PlayerData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bool ign
}
}
}
- if (changesMask[46])
+ if (changesMask[48])
{
for (uint32 i = 0; i < 2; ++i)
{
- if (changesMask[47 + i])
+ if (changesMask[49 + i])
{
data << uint8(PartyType[i]);
}
}
}
- if (changesMask[49])
+ if (changesMask[51])
{
for (uint32 i = 0; i < 175; ++i)
{
- if (changesMask[50 + i])
+ if (changesMask[52 + i])
{
if (noQuestLogChangesMask)
QuestLog[i].WriteCreate(data, owner, receiver);
@@ -2806,51 +2928,51 @@ void PlayerData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bool ign
}
}
}
- if (changesMask[225])
+ if (changesMask[227])
{
for (uint32 i = 0; i < 19; ++i)
{
- if (changesMask[226 + i])
+ if (changesMask[228 + i])
{
VisibleItems[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
}
}
- if (changesMask[245])
+ if (changesMask[247])
{
for (uint32 i = 0; i < 6; ++i)
{
- if (changesMask[246 + i])
+ if (changesMask[248 + i])
{
data << float(AvgItemLevel[i]);
}
}
}
- if (changesMask[252])
+ if (changesMask[254])
{
for (uint32 i = 0; i < 32; ++i)
{
- if (changesMask[253 + i])
+ if (changesMask[255 + i])
{
ForcedReactions[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
}
}
- if (changesMask[302])
+ if (changesMask[304])
{
for (uint32 i = 0; i < 19; ++i)
{
- if (changesMask[303 + i])
+ if (changesMask[305 + i])
{
data << uint32(Field_3120[i]);
}
}
}
- if (changesMask[285])
+ if (changesMask[287])
{
for (uint32 i = 0; i < 16; ++i)
{
- if (changesMask[286 + i])
+ if (changesMask[288 + i])
{
data << VisibleEquipableSpells[i];
}
@@ -2889,6 +3011,7 @@ void PlayerData::ClearChangesMask()
Base::ClearChangesMask(FakeInebriation);
Base::ClearChangesMask(VirtualPlayerRealm);
Base::ClearChangesMask(CurrentSpecID);
+ Base::ClearChangesMask(CurrentCombatTraitConfigSubTreeID);
Base::ClearChangesMask(TaxiMountAnimKitID);
Base::ClearChangesMask(CurrentBattlePetBreedQuality);
Base::ClearChangesMask(HonorLevel);
@@ -2901,6 +3024,7 @@ void PlayerData::ClearChangesMask()
Base::ClearChangesMask(CovenantID);
Base::ClearChangesMask(SoulbindID);
Base::ClearChangesMask(DungeonScore);
+ Base::ClearChangesMask(LeaverInfo);
Base::ClearChangesMask(SpectateTarget);
Base::ClearChangesMask(Field_200);
Base::ClearChangesMask(DeclinedNames);
@@ -3613,6 +3737,7 @@ void TraitEntry::WriteCreate(ByteBuffer& data, Player const* owner, Player const
data << int32(TraitNodeEntryID);
data << int32(Rank);
data << int32(GrantedRanks);
+ data << int32(BonusRanks);
}
void TraitEntry::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const
@@ -3621,6 +3746,7 @@ void TraitEntry::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player co
data << int32(TraitNodeEntryID);
data << int32(Rank);
data << int32(GrantedRanks);
+ data << int32(BonusRanks);
}
bool TraitEntry::operator==(TraitEntry const& right) const
@@ -3628,7 +3754,8 @@ bool TraitEntry::operator==(TraitEntry const& right) const
return TraitNodeID == right.TraitNodeID
&& TraitNodeEntryID == right.TraitNodeEntryID
&& Rank == right.Rank
- && GrantedRanks == right.GrantedRanks;
+ && GrantedRanks == right.GrantedRanks
+ && BonusRanks == right.BonusRanks;
}
void TraitSubTreeCache::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const
@@ -3692,7 +3819,7 @@ void TraitConfig::WriteCreate(ByteBuffer& data, Player const* owner, Player cons
{
SubTrees[i].WriteCreate(data, owner, receiver);
}
- data.WriteString(Name);
+ data << WorldPackets::SizedString::Data(*Name);
data.FlushBits();
}
@@ -3802,7 +3929,7 @@ void TraitConfig::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player c
if (changesMask[5])
{
data.WriteBits(Name->size(), 9);
- data.WriteString(Name);
+ data << WorldPackets::SizedString::Data(*Name);
}
}
data.FlushBits();
@@ -3987,7 +4114,7 @@ void CraftingOrderData::WriteCreate(ByteBuffer& data, Player const* owner, Playe
{
Reagents[i].WriteCreate(data, owner, receiver);
}
- data.WriteString(CustomerNotes);
+ data << WorldPackets::SizedString::Data(*CustomerNotes);
if (Customer.has_value())
{
Customer->WriteCreate(data, owner, receiver);
@@ -4123,7 +4250,7 @@ void CraftingOrderData::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Pl
{
if (changesMask[20])
{
- data.WriteString(CustomerNotes);
+ data << WorldPackets::SizedString::Data(*CustomerNotes);
}
if (changesMask[21])
{
@@ -4398,7 +4525,7 @@ void StablePetInfo::WriteCreate(ByteBuffer& data, Player const* owner, Player co
data << uint8(PetFlags);
data << uint32(Specialization);
data.WriteBits(Name->size(), 8);
- data.WriteString(Name);
+ data << WorldPackets::SizedString::Data(*Name);
data.FlushBits();
}
@@ -4444,7 +4571,7 @@ void StablePetInfo::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player
if (changesMask[6])
{
data.WriteBits(Name->size(), 8);
- data.WriteString(Name);
+ data << WorldPackets::SizedString::Data(*Name);
}
}
data.FlushBits();
@@ -4565,9 +4692,9 @@ void BankTabSettings::WriteCreate(ByteBuffer& data, Player const* owner, Player
data.WriteBits(Icon->size(), 9);
data.WriteBits(Description->size(), 14);
data << int32(DepositFlags);
- data.WriteString(Name);
- data.WriteString(Icon);
- data.WriteString(Description);
+ data << WorldPackets::SizedString::Data(*Name);
+ data << WorldPackets::SizedString::Data(*Icon);
+ data << WorldPackets::SizedString::Data(*Description);
data.FlushBits();
}
@@ -4598,15 +4725,15 @@ void BankTabSettings::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Play
}
if (changesMask[0])
{
- data.WriteString(Name);
+ data << WorldPackets::SizedString::Data(*Name);
}
if (changesMask[1])
{
- data.WriteString(Icon);
+ data << WorldPackets::SizedString::Data(*Icon);
}
if (changesMask[2])
{
- data.WriteString(Description);
+ data << WorldPackets::SizedString::Data(*Description);
}
data.FlushBits();
}
@@ -4687,6 +4814,47 @@ bool DelveData::operator==(DelveData const& right) const
&& Started == right.Started;
}
+void ChallengeModeData::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const
+{
+ data << int32(Unknown_1120_1);
+ data << int32(Unknown_1120_2);
+ data << uint64(Unknown_1120_3);
+ data << int64(Unknown_1120_4);
+ data << KeystoneOwnerGUID;
+ data << LeaverGUID;
+ data.WriteBits(IsActive, 1);
+ data.WriteBits(HasRestrictions, 1);
+ data.WriteBits(CanVoteAbandon, 1);
+ data.FlushBits();
+}
+
+void ChallengeModeData::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const
+{
+ data << int32(Unknown_1120_1);
+ data << int32(Unknown_1120_2);
+ data << uint64(Unknown_1120_3);
+ data << int64(Unknown_1120_4);
+ data << KeystoneOwnerGUID;
+ data << LeaverGUID;
+ data.WriteBits(IsActive, 1);
+ data.WriteBits(HasRestrictions, 1);
+ data.WriteBits(CanVoteAbandon, 1);
+ data.FlushBits();
+}
+
+bool ChallengeModeData::operator==(ChallengeModeData const& right) const
+{
+ return Unknown_1120_1 == right.Unknown_1120_1
+ && Unknown_1120_2 == right.Unknown_1120_2
+ && Unknown_1120_3 == right.Unknown_1120_3
+ && Unknown_1120_4 == right.Unknown_1120_4
+ && KeystoneOwnerGUID == right.KeystoneOwnerGUID
+ && LeaverGUID == right.LeaverGUID
+ && IsActive == right.IsActive
+ && HasRestrictions == right.HasRestrictions
+ && CanVoteAbandon == right.CanVoteAbandon;
+}
+
void Research::WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const
{
data << int16(ResearchProjectID);
@@ -4704,7 +4872,7 @@ bool Research::operator==(Research const& right) const
void ActivePlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Player const* owner, Player const* receiver) const
{
- for (uint32 i = 0; i < 232; ++i)
+ for (uint32 i = 0; i < 105; ++i)
{
data << InvSlots[i];
}
@@ -4819,14 +4987,11 @@ void ActivePlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> f
{
data << uint32(BagSlotFlags[i]);
}
- for (uint32 i = 0; i < 7; ++i)
- {
- data << uint32(BankBagSlotFlags[i]);
- }
data << int32(Honor);
data << int32(HonorNextLevel);
data << int32(PerksProgramCurrency);
data << uint8(NumBankSlots);
+ data << uint8(NumCharacterBankTabs);
data << uint8(NumAccountBankTabs);
for (uint32 i = 0; i < 1; ++i)
{
@@ -5017,9 +5182,11 @@ void ActivePlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> f
data.WriteBit(HasPerksProgramPendingReward);
data.WriteBits(QuestSession.has_value(), 1);
data.WriteBits(PetStable.has_value(), 1);
+ data.WriteBits(CharacterBankTabSettings.size(), 3);
data.WriteBits(AccountBankTabSettings.size(), 3);
data.WriteBits(WalkInData.has_value(), 1);
data.WriteBits(DelveData.has_value(), 1);
+ data.WriteBits(ChallengeModeData.has_value(), 1);
data.FlushBits();
ResearchHistory->WriteCreate(data, owner, receiver);
if (QuestSession.has_value())
@@ -5049,6 +5216,10 @@ void ActivePlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> f
{
PetStable->WriteCreate(data, owner, receiver);
}
+ for (uint32 i = 0; i < CharacterBankTabSettings.size(); ++i)
+ {
+ CharacterBankTabSettings[i].WriteCreate(data, owner, receiver);
+ }
for (uint32 i = 0; i < AccountBankTabSettings.size(); ++i)
{
AccountBankTabSettings[i].WriteCreate(data, owner, receiver);
@@ -5061,6 +5232,10 @@ void ActivePlayerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> f
{
DelveData->WriteCreate(data, owner, receiver);
}
+ if (ChallengeModeData.has_value())
+ {
+ ChallengeModeData->WriteCreate(data, owner, receiver);
+ }
data.FlushBits();
}
@@ -5071,8 +5246,8 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> f
void ActivePlayerData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bool ignoreNestedChangesMask, Player const* owner, Player const* receiver) const
{
- data.WriteBits(changesMask.GetBlocksMask(0), 17);
- for (uint32 i = 0; i < 17; ++i)
+ data.WriteBits(changesMask.GetBlocksMask(0), 13);
+ for (uint32 i = 0; i < 13; ++i)
if (changesMask.GetBlock(i))
data.WriteBits(changesMask.GetBlock(i), 32);
@@ -5131,11 +5306,11 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bo
WriteCompleteDynamicFieldUpdateMask(PvpInfo.size(), data);
}
}
- if (changesMask[42])
+ if (changesMask[43])
{
for (uint32 i = 0; i < 1; ++i)
{
- if (changesMask[43])
+ if (changesMask[44])
{
if (!ignoreNestedChangesMask)
ResearchSites[i].WriteUpdateMask(data);
@@ -5144,11 +5319,11 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bo
}
}
}
- if (changesMask[44])
+ if (changesMask[45])
{
for (uint32 i = 0; i < 1; ++i)
{
- if (changesMask[45])
+ if (changesMask[46])
{
if (!ignoreNestedChangesMask)
ResearchSiteProgress[i].WriteUpdateMask(data);
@@ -5157,11 +5332,11 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bo
}
}
}
- if (changesMask[46])
+ if (changesMask[47])
{
for (uint32 i = 0; i < 1; ++i)
{
- if (changesMask[47])
+ if (changesMask[48])
{
if (!ignoreNestedChangesMask)
Research[i].WriteUpdateMask(data);
@@ -5170,11 +5345,11 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bo
}
}
}
- if (changesMask[42])
+ if (changesMask[43])
{
for (uint32 i = 0; i < 1; ++i)
{
- if (changesMask[43])
+ if (changesMask[44])
{
for (uint32 j = 0; j < ResearchSites[i].size(); ++j)
{
@@ -5186,11 +5361,11 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bo
}
}
}
- if (changesMask[44])
+ if (changesMask[45])
{
for (uint32 i = 0; i < 1; ++i)
{
- if (changesMask[45])
+ if (changesMask[46])
{
for (uint32 j = 0; j < ResearchSiteProgress[i].size(); ++j)
{
@@ -5202,11 +5377,11 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bo
}
}
}
- if (changesMask[46])
+ if (changesMask[47])
{
for (uint32 i = 0; i < 1; ++i)
{
- if (changesMask[47])
+ if (changesMask[48])
{
for (uint32 j = 0; j < Research[i].size(); ++j)
{
@@ -5731,6 +5906,13 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bo
if (changesMask[41])
{
if (!ignoreNestedChangesMask)
+ CharacterBankTabSettings.WriteUpdateMask(data, 3);
+ else
+ WriteCompleteDynamicFieldUpdateMask(CharacterBankTabSettings.size(), data, 3);
+ }
+ if (changesMask[42])
+ {
+ if (!ignoreNestedChangesMask)
AccountBankTabSettings.WriteUpdateMask(data, 3);
else
WriteCompleteDynamicFieldUpdateMask(AccountBankTabSettings.size(), data, 3);
@@ -5784,6 +5966,16 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bo
}
if (changesMask[41])
{
+ for (uint32 i = 0; i < CharacterBankTabSettings.size(); ++i)
+ {
+ if (CharacterBankTabSettings.HasChanged(i) || ignoreNestedChangesMask)
+ {
+ CharacterBankTabSettings[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ }
+ }
+ }
+ if (changesMask[42])
+ {
for (uint32 i = 0; i < AccountBankTabSettings.size(); ++i)
{
if (AccountBankTabSettings.HasChanged(i) || ignoreNestedChangesMask)
@@ -5792,364 +5984,368 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bo
}
}
}
- if (changesMask[48])
- {
- data << *FarsightObject;
- }
if (changesMask[49])
{
- data << *SummonedBattlePetGUID;
+ data << *FarsightObject;
}
if (changesMask[50])
{
- data << uint64(Coinage);
+ data << *SummonedBattlePetGUID;
}
if (changesMask[51])
{
- data << uint64(AccountBankCoinage);
+ data << uint64(Coinage);
}
if (changesMask[52])
{
- data << int32(XP);
+ data << uint64(AccountBankCoinage);
}
if (changesMask[53])
{
- data << int32(NextLevelXP);
+ data << int32(XP);
}
if (changesMask[54])
{
- data << int32(TrialXP);
+ data << int32(NextLevelXP);
}
if (changesMask[55])
{
- Skill->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ data << int32(TrialXP);
}
if (changesMask[56])
{
- data << int32(CharacterPoints);
+ Skill->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
if (changesMask[57])
{
- data << int32(MaxTalentTiers);
+ data << int32(CharacterPoints);
}
if (changesMask[58])
{
- data << uint32(TrackCreatureMask);
+ data << int32(MaxTalentTiers);
}
if (changesMask[59])
{
- data << float(MainhandExpertise);
+ data << uint32(TrackCreatureMask);
}
if (changesMask[60])
{
- data << float(OffhandExpertise);
+ data << float(MainhandExpertise);
}
if (changesMask[61])
{
- data << float(RangedExpertise);
+ data << float(OffhandExpertise);
}
if (changesMask[62])
{
- data << float(CombatRatingExpertise);
+ data << float(RangedExpertise);
}
if (changesMask[63])
{
- data << float(BlockPercentage);
+ data << float(CombatRatingExpertise);
}
if (changesMask[64])
{
- data << float(DodgePercentage);
+ data << float(BlockPercentage);
}
if (changesMask[65])
{
- data << float(DodgePercentageFromAttribute);
+ data << float(DodgePercentage);
}
if (changesMask[66])
{
- data << float(ParryPercentage);
+ data << float(DodgePercentageFromAttribute);
}
if (changesMask[67])
{
- data << float(ParryPercentageFromAttribute);
+ data << float(ParryPercentage);
}
if (changesMask[68])
{
- data << float(CritPercentage);
+ data << float(ParryPercentageFromAttribute);
}
if (changesMask[69])
{
- data << float(RangedCritPercentage);
+ data << float(CritPercentage);
}
}
if (changesMask[70])
{
if (changesMask[71])
{
- data << float(OffhandCritPercentage);
+ data << float(RangedCritPercentage);
}
if (changesMask[72])
{
- data << float(SpellCritPercentage);
+ data << float(OffhandCritPercentage);
}
if (changesMask[73])
{
- data << int32(ShieldBlock);
+ data << float(SpellCritPercentage);
}
if (changesMask[74])
{
- data << float(ShieldBlockCritPercentage);
+ data << int32(ShieldBlock);
}
if (changesMask[75])
{
- data << float(Mastery);
+ data << float(ShieldBlockCritPercentage);
}
if (changesMask[76])
{
- data << float(Speed);
+ data << float(Mastery);
}
if (changesMask[77])
{
- data << float(Avoidance);
+ data << float(Speed);
}
if (changesMask[78])
{
- data << float(Sturdiness);
+ data << float(Avoidance);
}
if (changesMask[79])
{
- data << int32(Versatility);
+ data << float(Sturdiness);
}
if (changesMask[80])
{
- data << float(VersatilityBonus);
+ data << int32(Versatility);
}
if (changesMask[81])
{
- data << float(PvpPowerDamage);
+ data << float(VersatilityBonus);
}
if (changesMask[82])
{
- data << float(PvpPowerHealing);
+ data << float(PvpPowerDamage);
}
if (changesMask[83])
{
- BitVectors->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ data << float(PvpPowerHealing);
}
if (changesMask[84])
{
- data << int32(ModHealingDonePos);
+ BitVectors->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
if (changesMask[85])
{
- data << float(ModHealingPercent);
+ data << int32(ModHealingDonePos);
}
if (changesMask[86])
{
- data << float(ModPeriodicHealingDonePercent);
+ data << float(ModHealingPercent);
}
if (changesMask[87])
{
- data << float(ModSpellPowerPercent);
+ data << float(ModPeriodicHealingDonePercent);
}
if (changesMask[88])
{
- data << float(ModResiliencePercent);
+ data << float(ModSpellPowerPercent);
}
if (changesMask[89])
{
- data << float(OverrideSpellPowerByAPPercent);
+ data << float(ModResiliencePercent);
}
if (changesMask[90])
{
- data << float(OverrideAPBySpellPowerPercent);
+ data << float(OverrideSpellPowerByAPPercent);
}
if (changesMask[91])
{
- data << int32(ModTargetResistance);
+ data << float(OverrideAPBySpellPowerPercent);
}
if (changesMask[92])
{
- data << int32(ModTargetPhysicalResistance);
+ data << int32(ModTargetResistance);
}
if (changesMask[93])
{
- data << uint32(LocalFlags);
+ data << int32(ModTargetPhysicalResistance);
}
if (changesMask[94])
{
- data << uint8(GrantableLevels);
+ data << uint32(LocalFlags);
}
if (changesMask[95])
{
- data << uint8(MultiActionBars);
+ data << uint8(GrantableLevels);
}
if (changesMask[96])
{
- data << uint8(LifetimeMaxRank);
+ data << uint8(MultiActionBars);
}
if (changesMask[97])
{
- data << uint8(NumRespecs);
+ data << uint8(LifetimeMaxRank);
}
if (changesMask[98])
{
- data << uint32(PvpMedals);
+ data << uint8(NumRespecs);
}
if (changesMask[99])
{
- data << uint16(TodayHonorableKills);
+ data << uint32(PvpMedals);
}
if (changesMask[100])
{
- data << uint16(YesterdayHonorableKills);
+ data << uint16(TodayHonorableKills);
}
if (changesMask[101])
{
- data << uint32(LifetimeHonorableKills);
+ data << uint16(YesterdayHonorableKills);
}
}
if (changesMask[102])
{
if (changesMask[103])
{
- data << int32(WatchedFactionIndex);
+ data << uint32(LifetimeHonorableKills);
}
if (changesMask[104])
{
- data << int32(MaxLevel);
+ data << int32(WatchedFactionIndex);
}
if (changesMask[105])
{
- data << int32(ScalingPlayerLevelDelta);
+ data << int32(MaxLevel);
}
if (changesMask[106])
{
- data << int32(MaxCreatureScalingLevel);
+ data << int32(ScalingPlayerLevelDelta);
}
if (changesMask[107])
{
- data << int32(PetSpellPower);
+ data << int32(MaxCreatureScalingLevel);
}
if (changesMask[108])
{
- data << float(UiHitModifier);
+ data << int32(PetSpellPower);
}
if (changesMask[109])
{
- data << float(UiSpellHitModifier);
+ data << float(UiHitModifier);
}
if (changesMask[110])
{
- data << int32(HomeRealmTimeOffset);
+ data << float(UiSpellHitModifier);
}
if (changesMask[111])
{
- data << float(ModPetHaste);
+ data << int32(HomeRealmTimeOffset);
}
if (changesMask[112])
{
- data << int8(JailersTowerLevelMax);
+ data << float(ModPetHaste);
}
if (changesMask[113])
{
- data << int8(JailersTowerLevel);
+ data << int8(JailersTowerLevelMax);
}
if (changesMask[114])
{
- data << uint8(LocalRegenFlags);
+ data << int8(JailersTowerLevel);
}
if (changesMask[115])
{
- data << uint8(AuraVision);
+ data << uint8(LocalRegenFlags);
}
if (changesMask[116])
{
- data << uint8(NumBackpackSlots);
+ data << uint8(AuraVision);
}
if (changesMask[117])
{
- data << int32(OverrideSpellsID);
+ data << uint8(NumBackpackSlots);
}
if (changesMask[118])
{
- data << uint16(LootSpecID);
+ data << int32(OverrideSpellsID);
}
if (changesMask[119])
{
- data << uint32(OverrideZonePVPType);
+ data << uint16(LootSpecID);
}
if (changesMask[120])
{
- data << int32(Honor);
+ data << uint32(OverrideZonePVPType);
}
if (changesMask[121])
{
- data << int32(HonorNextLevel);
+ data << int32(Honor);
}
if (changesMask[122])
{
- data << int32(PerksProgramCurrency);
+ data << int32(HonorNextLevel);
}
if (changesMask[123])
{
- data << uint8(NumBankSlots);
+ data << int32(PerksProgramCurrency);
}
if (changesMask[124])
{
- data << uint8(NumAccountBankTabs);
+ data << uint8(NumBankSlots);
}
- if (changesMask[129])
+ if (changesMask[125])
{
- data << int32(UiChromieTimeExpansionID);
+ data << uint8(NumCharacterBankTabs);
}
- if (changesMask[130])
+ if (changesMask[126])
{
- data << int32(TimerunningSeasonID);
+ data << uint8(NumAccountBankTabs);
}
if (changesMask[131])
{
- data << int32(TransportServerTime);
+ data << int32(UiChromieTimeExpansionID);
}
if (changesMask[132])
{
- data << uint32(WeeklyRewardsPeriodSinceOrigin);
+ data << int32(TimerunningSeasonID);
}
if (changesMask[133])
{
- data << int16(DEBUGSoulbindConduitRank);
+ data << int32(TransportServerTime);
}
}
if (changesMask[134])
{
+ if (changesMask[135])
+ {
+ data << uint32(WeeklyRewardsPeriodSinceOrigin);
+ }
if (changesMask[136])
{
+ data << int16(DEBUGSoulbindConduitRank);
+ }
+ if (changesMask[138])
+ {
data << uint32(ActiveCombatTraitConfigID);
}
- if (changesMask[137])
+ if (changesMask[139])
{
data << int32(ItemUpgradeHighOnehandWeaponItemID);
}
- if (changesMask[138])
+ if (changesMask[140])
{
data << int32(ItemUpgradeHighFingerItemID);
}
- if (changesMask[139])
+ if (changesMask[141])
{
data << float(ItemUpgradeHighFingerWatermark);
}
- if (changesMask[140])
+ if (changesMask[142])
{
data << int32(ItemUpgradeHighTrinketItemID);
}
- if (changesMask[141])
+ if (changesMask[143])
{
data << float(ItemUpgradeHighTrinketWatermark);
}
- if (changesMask[142])
+ if (changesMask[144])
{
data << uint64(LootHistoryInstanceID);
}
- if (changesMask[144])
+ if (changesMask[146])
{
data << uint8(RequiredMountCapabilityFlags);
}
@@ -6163,183 +6359,181 @@ void ActivePlayerData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bo
data.WriteBits(PetStable.has_value(), 1);
data.WriteBits(WalkInData.has_value(), 1);
data.WriteBits(DelveData.has_value(), 1);
+ data.WriteBits(ChallengeModeData.has_value(), 1);
}
data.FlushBits();
if (changesMask[102])
{
- if (changesMask[125])
+ if (changesMask[127])
{
ResearchHistory->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
- if (changesMask[127])
+ if (changesMask[129])
{
if (QuestSession.has_value())
{
QuestSession->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
}
- if (changesMask[126])
+ if (changesMask[128])
{
data << *FrozenPerksVendorItem;
}
- if (changesMask[128])
+ if (changesMask[130])
{
Field_1410->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
}
if (changesMask[134])
{
- if (changesMask[135])
+ if (changesMask[137])
{
data << *DungeonScore;
}
- if (changesMask[143])
+ if (changesMask[145])
{
if (PetStable.has_value())
{
PetStable->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
}
- if (changesMask[145])
+ if (changesMask[147])
{
if (WalkInData.has_value())
{
WalkInData->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
}
- if (changesMask[146])
+ if (changesMask[148])
{
if (DelveData.has_value())
{
DelveData->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
}
+ if (changesMask[149])
+ {
+ if (ChallengeModeData.has_value())
+ {
+ ChallengeModeData->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ }
+ }
}
- if (changesMask[147])
+ if (changesMask[150])
{
- for (uint32 i = 0; i < 232; ++i)
+ for (uint32 i = 0; i < 105; ++i)
{
- if (changesMask[148 + i])
+ if (changesMask[151 + i])
{
data << InvSlots[i];
}
}
}
- if (changesMask[380])
+ if (changesMask[256])
{
for (uint32 i = 0; i < 2; ++i)
{
- if (changesMask[381 + i])
+ if (changesMask[257 + i])
{
RestInfo[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
}
}
- if (changesMask[383])
+ if (changesMask[259])
{
for (uint32 i = 0; i < 7; ++i)
{
- if (changesMask[384 + i])
+ if (changesMask[260 + i])
{
data << int32(ModDamageDonePos[i]);
}
- if (changesMask[391 + i])
+ if (changesMask[267 + i])
{
data << int32(ModDamageDoneNeg[i]);
}
- if (changesMask[398 + i])
+ if (changesMask[274 + i])
{
data << float(ModDamageDonePercent[i]);
}
- if (changesMask[405 + i])
+ if (changesMask[281 + i])
{
data << float(ModHealingDonePercent[i]);
}
}
}
- if (changesMask[412])
+ if (changesMask[288])
{
for (uint32 i = 0; i < 3; ++i)
{
- if (changesMask[413 + i])
+ if (changesMask[289 + i])
{
data << float(WeaponDmgMultipliers[i]);
}
- if (changesMask[416 + i])
+ if (changesMask[292 + i])
{
data << float(WeaponAtkSpeedMultipliers[i]);
}
}
}
- if (changesMask[419])
+ if (changesMask[295])
{
for (uint32 i = 0; i < 12; ++i)
{
- if (changesMask[420 + i])
+ if (changesMask[296 + i])
{
data << uint32(BuybackPrice[i]);
}
- if (changesMask[432 + i])
+ if (changesMask[308 + i])
{
data << int64(BuybackTimestamp[i]);
}
}
}
- if (changesMask[444])
+ if (changesMask[320])
{
for (uint32 i = 0; i < 32; ++i)
{
- if (changesMask[445 + i])
+ if (changesMask[321 + i])
{
data << int32(CombatRatings[i]);
}
}
}
- if (changesMask[477])
+ if (changesMask[353])
{
for (uint32 i = 0; i < 4; ++i)
{
- if (changesMask[478 + i])
+ if (changesMask[354 + i])
{
data << uint32(NoReagentCostMask[i]);
}
}
}
- if (changesMask[482])
+ if (changesMask[358])
{
for (uint32 i = 0; i < 2; ++i)
{
- if (changesMask[483 + i])
+ if (changesMask[359 + i])
{
data << int32(ProfessionSkillLine[i]);
}
}
}
- if (changesMask[485])
+ if (changesMask[361])
{
for (uint32 i = 0; i < 5; ++i)
{
- if (changesMask[486 + i])
+ if (changesMask[362 + i])
{
data << uint32(BagSlotFlags[i]);
}
}
}
- if (changesMask[491])
- {
- for (uint32 i = 0; i < 7; ++i)
- {
- if (changesMask[492 + i])
- {
- data << uint32(BankBagSlotFlags[i]);
- }
- }
- }
- if (changesMask[499])
+ if (changesMask[367])
{
for (uint32 i = 0; i < 17; ++i)
{
- if (changesMask[500 + i])
+ if (changesMask[368 + i])
{
data << float(ItemUpgradeHighWatermark[i]);
}
@@ -6392,6 +6586,7 @@ void ActivePlayerData::ClearChangesMask()
Base::ClearChangesMask(CharacterRestrictions);
Base::ClearChangesMask(TraitConfigs);
Base::ClearChangesMask(CraftingOrders);
+ Base::ClearChangesMask(CharacterBankTabSettings);
Base::ClearChangesMask(AccountBankTabSettings);
Base::ClearChangesMask(FarsightObject);
Base::ClearChangesMask(SummonedBattlePetGUID);
@@ -6467,6 +6662,7 @@ void ActivePlayerData::ClearChangesMask()
Base::ClearChangesMask(HonorNextLevel);
Base::ClearChangesMask(PerksProgramCurrency);
Base::ClearChangesMask(NumBankSlots);
+ Base::ClearChangesMask(NumCharacterBankTabs);
Base::ClearChangesMask(NumAccountBankTabs);
Base::ClearChangesMask(ResearchHistory);
Base::ClearChangesMask(FrozenPerksVendorItem);
@@ -6489,6 +6685,7 @@ void ActivePlayerData::ClearChangesMask()
Base::ClearChangesMask(RequiredMountCapabilityFlags);
Base::ClearChangesMask(WalkInData);
Base::ClearChangesMask(DelveData);
+ Base::ClearChangesMask(ChallengeModeData);
Base::ClearChangesMask(InvSlots);
Base::ClearChangesMask(RestInfo);
Base::ClearChangesMask(ModDamageDonePos);
@@ -6503,11 +6700,44 @@ void ActivePlayerData::ClearChangesMask()
Base::ClearChangesMask(NoReagentCostMask);
Base::ClearChangesMask(ProfessionSkillLine);
Base::ClearChangesMask(BagSlotFlags);
- Base::ClearChangesMask(BankBagSlotFlags);
Base::ClearChangesMask(ItemUpgradeHighWatermark);
_changesMask.ResetAll();
}
+void GameObjectAssistActionData::WriteCreate(ByteBuffer& data, GameObject const* owner, Player const* receiver) const
+{
+ data.WriteBits(PlayerName.size(), 6);
+ data.WriteBits(MonsterName.size() + 1, 11);
+ data << uint32(VirtualRealmAddress);
+ data << uint8(Sex);
+ data << int64(Time);
+ data << int32(DelveTier);
+ data << WorldPackets::SizedString::Data(PlayerName);
+ data << WorldPackets::SizedCString::Data(MonsterName);
+}
+
+void GameObjectAssistActionData::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, GameObject const* owner, Player const* receiver) const
+{
+ data.WriteBits(PlayerName.size(), 6);
+ data.WriteBits(MonsterName.size() + 1, 11);
+ data << uint32(VirtualRealmAddress);
+ data << uint8(Sex);
+ data << int64(Time);
+ data << int32(DelveTier);
+ data << WorldPackets::SizedString::Data(PlayerName);
+ data << WorldPackets::SizedCString::Data(MonsterName);
+}
+
+bool GameObjectAssistActionData::operator==(GameObjectAssistActionData const& right) const
+{
+ return PlayerName == right.PlayerName
+ && MonsterName == right.MonsterName
+ && VirtualRealmAddress == right.VirtualRealmAddress
+ && Sex == right.Sex
+ && Time == right.Time
+ && DelveTier == right.DelveTier;
+}
+
void GameObjectData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, GameObject const* owner, Player const* receiver) const
{
ViewerDependentValue<StateWorldEffectIDsTag>::value_type stateWorldEffectIDs = {};
@@ -6552,6 +6782,12 @@ void GameObjectData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fie
{
data << int32(WorldEffects[i]);
}
+ data.WriteBits(AssistActionData.has_value(), 1);
+ data.FlushBits();
+ if (AssistActionData.has_value())
+ {
+ AssistActionData->WriteCreate(data, owner, receiver);
+ }
}
void GameObjectData::WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, GameObject const* owner, Player const* receiver) const
@@ -6561,7 +6797,7 @@ void GameObjectData::WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fie
void GameObjectData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bool ignoreNestedChangesMask, GameObject const* owner, Player const* receiver) const
{
- data.WriteBits(changesMask.GetBlock(0), 25);
+ data.WriteBits(changesMask.GetBlock(0), 26);
ViewerDependentValue<StateWorldEffectIDsTag>::value_type stateWorldEffectIDs = {};
@@ -6705,6 +6941,15 @@ void GameObjectData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bool
{
data << uint32(UiWidgetItemUnknown1000);
}
+ data.WriteBits(AssistActionData.has_value(), 1);
+ data.FlushBits();
+ if (changesMask[25])
+ {
+ if (AssistActionData.has_value())
+ {
+ AssistActionData->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ }
+ }
}
}
@@ -6734,6 +6979,7 @@ void GameObjectData::ClearChangesMask()
Base::ClearChangesMask(UiWidgetItemID);
Base::ClearChangesMask(UiWidgetItemQuality);
Base::ClearChangesMask(UiWidgetItemUnknown1000);
+ Base::ClearChangesMask(AssistActionData);
_changesMask.ResetAll();
}
@@ -7044,6 +7290,514 @@ void VisualAnim::ClearChangesMask()
_changesMask.ResetAll();
}
+void ForceSetAreaTriggerPositionAndRotation::WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const
+{
+ data << TriggerGUID;
+ data << Position;
+ data << float(Rotation.x);
+ data << float(Rotation.y);
+ data << float(Rotation.z);
+ data << float(Rotation.w);
+}
+
+void ForceSetAreaTriggerPositionAndRotation::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const
+{
+ data << TriggerGUID;
+ data << Position;
+ data << float(Rotation.x);
+ data << float(Rotation.y);
+ data << float(Rotation.z);
+ data << float(Rotation.w);
+}
+
+bool ForceSetAreaTriggerPositionAndRotation::operator==(ForceSetAreaTriggerPositionAndRotation const& right) const
+{
+ return TriggerGUID == right.TriggerGUID
+ && Position == right.Position
+ && Rotation == right.Rotation;
+}
+
+void AreaTriggerSplineCalculator::WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const
+{
+ data.WriteBits(Points.size(), 16);
+ data.WriteBit(Catmullrom);
+ for (uint32 i = 0; i < Points.size(); ++i)
+ {
+ data << Points[i];
+ }
+ data.FlushBits();
+}
+
+void AreaTriggerSplineCalculator::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const
+{
+ Mask changesMask = _changesMask;
+ if (ignoreChangesMask)
+ changesMask.SetAll();
+
+ data.WriteBits(changesMask.GetBlock(0), 3);
+
+ if (changesMask[0])
+ {
+ if (changesMask[1])
+ {
+ data.WriteBit(Catmullrom);
+ }
+ if (changesMask[2])
+ {
+ if (!ignoreChangesMask)
+ Points.WriteUpdateMask(data, 16);
+ else
+ WriteCompleteDynamicFieldUpdateMask(Points.size(), data, 16);
+ }
+ }
+ data.FlushBits();
+ if (changesMask[0])
+ {
+ if (changesMask[2])
+ {
+ for (uint32 i = 0; i < Points.size(); ++i)
+ {
+ if (Points.HasChanged(i) || ignoreChangesMask)
+ {
+ data << Points[i];
+ }
+ }
+ }
+ }
+ data.FlushBits();
+}
+
+void AreaTriggerSplineCalculator::ClearChangesMask()
+{
+ Base::ClearChangesMask(Catmullrom);
+ Base::ClearChangesMask(Points);
+ _changesMask.ResetAll();
+}
+
+void AreaTriggerOrbit::WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const
+{
+ data << *Center;
+ data << float(Radius);
+ data << float(InitialAngle);
+ data << float(BlendFromRadius);
+ data << int32(ExtraTimeForBlending);
+ data.WriteBit(CounterClockwise);
+ data.FlushBits();
+}
+
+void AreaTriggerOrbit::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const
+{
+ Mask changesMask = _changesMask;
+ if (ignoreChangesMask)
+ changesMask.SetAll();
+
+ data.WriteBits(changesMask.GetBlock(0), 7);
+
+ if (changesMask[0])
+ {
+ if (changesMask[1])
+ {
+ data.WriteBit(CounterClockwise);
+ }
+ }
+ data.FlushBits();
+ if (changesMask[0])
+ {
+ if (changesMask[2])
+ {
+ data << *Center;
+ }
+ if (changesMask[3])
+ {
+ data << float(Radius);
+ }
+ if (changesMask[4])
+ {
+ data << float(InitialAngle);
+ }
+ if (changesMask[5])
+ {
+ data << float(BlendFromRadius);
+ }
+ if (changesMask[6])
+ {
+ data << int32(ExtraTimeForBlending);
+ }
+ }
+ data.FlushBits();
+}
+
+void AreaTriggerOrbit::ClearChangesMask()
+{
+ Base::ClearChangesMask(CounterClockwise);
+ Base::ClearChangesMask(Center);
+ Base::ClearChangesMask(Radius);
+ Base::ClearChangesMask(InitialAngle);
+ Base::ClearChangesMask(BlendFromRadius);
+ Base::ClearChangesMask(ExtraTimeForBlending);
+ _changesMask.ResetAll();
+}
+
+void AreaTriggerMovementScript::WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const
+{
+ data << int32(SpellScriptID);
+ data << *Center;
+ data << uint32(CreationTime);
+}
+
+void AreaTriggerMovementScript::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const
+{
+ Mask changesMask = _changesMask;
+ if (ignoreChangesMask)
+ changesMask.SetAll();
+
+ data.WriteBits(changesMask.GetBlock(0), 4);
+
+ data.FlushBits();
+ if (changesMask[0])
+ {
+ if (changesMask[1])
+ {
+ data << int32(SpellScriptID);
+ }
+ if (changesMask[2])
+ {
+ data << *Center;
+ }
+ if (changesMask[3])
+ {
+ data << uint32(CreationTime);
+ }
+ }
+}
+
+void AreaTriggerMovementScript::ClearChangesMask()
+{
+ Base::ClearChangesMask(SpellScriptID);
+ Base::ClearChangesMask(Center);
+ Base::ClearChangesMask(CreationTime);
+ _changesMask.ResetAll();
+}
+
+void AreaTriggerSphere::WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const
+{
+ data << float(Radius);
+ data << float(RadiusTarget);
+}
+
+void AreaTriggerSphere::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const
+{
+ Mask changesMask = _changesMask;
+ if (ignoreChangesMask)
+ changesMask.SetAll();
+
+ data.WriteBits(changesMask.GetBlock(0), 3);
+
+ data.FlushBits();
+ if (changesMask[0])
+ {
+ if (changesMask[1])
+ {
+ data << float(Radius);
+ }
+ if (changesMask[2])
+ {
+ data << float(RadiusTarget);
+ }
+ }
+}
+
+void AreaTriggerSphere::ClearChangesMask()
+{
+ Base::ClearChangesMask(Radius);
+ Base::ClearChangesMask(RadiusTarget);
+ _changesMask.ResetAll();
+}
+
+void AreaTriggerBox::WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const
+{
+ data << *Extents;
+ data << *ExtentsTarget;
+}
+
+void AreaTriggerBox::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const
+{
+ Mask changesMask = _changesMask;
+ if (ignoreChangesMask)
+ changesMask.SetAll();
+
+ data.WriteBits(changesMask.GetBlock(0), 3);
+
+ data.FlushBits();
+ if (changesMask[0])
+ {
+ if (changesMask[1])
+ {
+ data << *Extents;
+ }
+ if (changesMask[2])
+ {
+ data << *ExtentsTarget;
+ }
+ }
+}
+
+void AreaTriggerBox::ClearChangesMask()
+{
+ Base::ClearChangesMask(Extents);
+ Base::ClearChangesMask(ExtentsTarget);
+ _changesMask.ResetAll();
+}
+
+void AreaTriggerPolygon::WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const
+{
+ data << uint32(Vertices.size());
+ data << uint32(VerticesTarget.size());
+ data << float(Height);
+ data << float(HeightTarget);
+ for (uint32 i = 0; i < Vertices.size(); ++i)
+ {
+ data << Vertices[i];
+ }
+ for (uint32 i = 0; i < VerticesTarget.size(); ++i)
+ {
+ data << VerticesTarget[i];
+ }
+}
+
+void AreaTriggerPolygon::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const
+{
+ Mask changesMask = _changesMask;
+ if (ignoreChangesMask)
+ changesMask.SetAll();
+
+ data.WriteBits(changesMask.GetBlock(0), 5);
+
+ if (changesMask[0])
+ {
+ if (changesMask[1])
+ {
+ if (!ignoreChangesMask)
+ Vertices.WriteUpdateMask(data);
+ else
+ WriteCompleteDynamicFieldUpdateMask(Vertices.size(), data);
+ }
+ if (changesMask[2])
+ {
+ if (!ignoreChangesMask)
+ VerticesTarget.WriteUpdateMask(data);
+ else
+ WriteCompleteDynamicFieldUpdateMask(VerticesTarget.size(), data);
+ }
+ }
+ data.FlushBits();
+ if (changesMask[0])
+ {
+ if (changesMask[1])
+ {
+ for (uint32 i = 0; i < Vertices.size(); ++i)
+ {
+ if (Vertices.HasChanged(i) || ignoreChangesMask)
+ {
+ data << Vertices[i];
+ }
+ }
+ }
+ if (changesMask[2])
+ {
+ for (uint32 i = 0; i < VerticesTarget.size(); ++i)
+ {
+ if (VerticesTarget.HasChanged(i) || ignoreChangesMask)
+ {
+ data << VerticesTarget[i];
+ }
+ }
+ }
+ if (changesMask[3])
+ {
+ data << float(Height);
+ }
+ if (changesMask[4])
+ {
+ data << float(HeightTarget);
+ }
+ }
+}
+
+void AreaTriggerPolygon::ClearChangesMask()
+{
+ Base::ClearChangesMask(Vertices);
+ Base::ClearChangesMask(VerticesTarget);
+ Base::ClearChangesMask(Height);
+ Base::ClearChangesMask(HeightTarget);
+ _changesMask.ResetAll();
+}
+
+void AreaTriggerCylinder::WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const
+{
+ data << float(Radius);
+ data << float(RadiusTarget);
+ data << float(Height);
+ data << float(HeightTarget);
+ data << float(LocationZOffset);
+ data << float(LocationZOffsetTarget);
+}
+
+void AreaTriggerCylinder::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const
+{
+ Mask changesMask = _changesMask;
+ if (ignoreChangesMask)
+ changesMask.SetAll();
+
+ data.WriteBits(changesMask.GetBlock(0), 7);
+
+ data.FlushBits();
+ if (changesMask[0])
+ {
+ if (changesMask[1])
+ {
+ data << float(Radius);
+ }
+ if (changesMask[2])
+ {
+ data << float(RadiusTarget);
+ }
+ if (changesMask[3])
+ {
+ data << float(Height);
+ }
+ if (changesMask[4])
+ {
+ data << float(HeightTarget);
+ }
+ if (changesMask[5])
+ {
+ data << float(LocationZOffset);
+ }
+ if (changesMask[6])
+ {
+ data << float(LocationZOffsetTarget);
+ }
+ }
+}
+
+void AreaTriggerCylinder::ClearChangesMask()
+{
+ Base::ClearChangesMask(Radius);
+ Base::ClearChangesMask(RadiusTarget);
+ Base::ClearChangesMask(Height);
+ Base::ClearChangesMask(HeightTarget);
+ Base::ClearChangesMask(LocationZOffset);
+ Base::ClearChangesMask(LocationZOffsetTarget);
+ _changesMask.ResetAll();
+}
+
+void AreaTriggerDisk::WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const
+{
+ data << float(InnerRadius);
+ data << float(InnerRadiusTarget);
+ data << float(OuterRadius);
+ data << float(OuterRadiusTarget);
+ data << float(Height);
+ data << float(HeightTarget);
+ data << float(LocationZOffset);
+ data << float(LocationZOffsetTarget);
+}
+
+void AreaTriggerDisk::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const
+{
+ Mask changesMask = _changesMask;
+ if (ignoreChangesMask)
+ changesMask.SetAll();
+
+ data.WriteBits(changesMask.GetBlock(0), 9);
+
+ data.FlushBits();
+ if (changesMask[0])
+ {
+ if (changesMask[1])
+ {
+ data << float(InnerRadius);
+ }
+ if (changesMask[2])
+ {
+ data << float(InnerRadiusTarget);
+ }
+ if (changesMask[3])
+ {
+ data << float(OuterRadius);
+ }
+ if (changesMask[4])
+ {
+ data << float(OuterRadiusTarget);
+ }
+ if (changesMask[5])
+ {
+ data << float(Height);
+ }
+ if (changesMask[6])
+ {
+ data << float(HeightTarget);
+ }
+ if (changesMask[7])
+ {
+ data << float(LocationZOffset);
+ }
+ if (changesMask[8])
+ {
+ data << float(LocationZOffsetTarget);
+ }
+ }
+}
+
+void AreaTriggerDisk::ClearChangesMask()
+{
+ Base::ClearChangesMask(InnerRadius);
+ Base::ClearChangesMask(InnerRadiusTarget);
+ Base::ClearChangesMask(OuterRadius);
+ Base::ClearChangesMask(OuterRadiusTarget);
+ Base::ClearChangesMask(Height);
+ Base::ClearChangesMask(HeightTarget);
+ Base::ClearChangesMask(LocationZOffset);
+ Base::ClearChangesMask(LocationZOffsetTarget);
+ _changesMask.ResetAll();
+}
+
+void AreaTriggerBoundedPlane::WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const
+{
+ data << *Extents;
+ data << *ExtentsTarget;
+}
+
+void AreaTriggerBoundedPlane::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const
+{
+ Mask changesMask = _changesMask;
+ if (ignoreChangesMask)
+ changesMask.SetAll();
+
+ data.WriteBits(changesMask.GetBlock(0), 3);
+
+ data.FlushBits();
+ if (changesMask[0])
+ {
+ if (changesMask[1])
+ {
+ data << *Extents;
+ }
+ if (changesMask[2])
+ {
+ data << *ExtentsTarget;
+ }
+ }
+}
+
+void AreaTriggerBoundedPlane::ClearChangesMask()
+{
+ Base::ClearChangesMask(Extents);
+ Base::ClearChangesMask(ExtentsTarget);
+ _changesMask.ResetAll();
+}
+
void AreaTriggerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, AreaTrigger const* owner, Player const* receiver) const
{
OverrideScaleCurve->WriteCreate(data, owner, receiver);
@@ -7059,20 +7813,72 @@ void AreaTriggerData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fi
data << float(BoundsRadius2D);
data << uint32(DecalPropertiesID);
data << *CreatingEffectGUID;
- data << uint32(NumUnitsInside);
- data << uint32(NumPlayersInside);
data << *OrbitPathTarget;
data << *RollPitchYaw;
data << int32(PositionalSoundKitID);
+ data << uint32(MovementStartTime);
+ data << uint32(CreationTime);
+ data << float(ZOffset);
+ data << uint32(Flags);
+ data << uint32(ScaleCurveId);
+ data << uint32(FacingCurveId);
+ data << uint32(MorphCurveId);
+ data << uint32(MoveCurveId);
+ data << float(Facing);
+ data << int32(PathType);
+ data << uint8(ShapeType);
+ if (PathType == 3)
+ {
+ PathData.Get<UF::AreaTriggerMovementScript>()->WriteCreate(data, owner, receiver);
+ }
+ if (ShapeType == 0)
+ {
+ ShapeData.Get<UF::AreaTriggerSphere>()->WriteCreate(data, owner, receiver);
+ }
+ if (ShapeType == 1)
+ {
+ ShapeData.Get<UF::AreaTriggerBox>()->WriteCreate(data, owner, receiver);
+ }
+ if (ShapeType == 3)
+ {
+ ShapeData.Get<UF::AreaTriggerPolygon>()->WriteCreate(data, owner, receiver);
+ }
+ if (ShapeType == 4)
+ {
+ ShapeData.Get<UF::AreaTriggerCylinder>()->WriteCreate(data, owner, receiver);
+ }
+ if (ShapeType == 7)
+ {
+ ShapeData.Get<UF::AreaTriggerDisk>()->WriteCreate(data, owner, receiver);
+ }
+ if (ShapeType == 8)
+ {
+ ShapeData.Get<UF::AreaTriggerBoundedPlane>()->WriteCreate(data, owner, receiver);
+ }
ExtraScaleCurve->WriteCreate(data, owner, receiver);
data.FlushBits();
- data.WriteBit(HeightIgnoresScale);
- data.WriteBit(Field_261);
+ data.WriteBits(TargetRollPitchYaw.has_value(), 1);
+ data.WriteBits(ForcedPositionAndRotation.has_value(), 1);
OverrideMoveCurveX->WriteCreate(data, owner, receiver);
+ if (TargetRollPitchYaw.has_value())
+ {
+ data << *TargetRollPitchYaw;
+ }
+ if (ForcedPositionAndRotation.has_value())
+ {
+ ForcedPositionAndRotation->WriteCreate(data, owner, receiver);
+ }
OverrideMoveCurveY->WriteCreate(data, owner, receiver);
OverrideMoveCurveZ->WriteCreate(data, owner, receiver);
VisualAnim->WriteCreate(data, owner, receiver);
- data.FlushBits();
+ if (PathType == 0)
+ {
+ PathData.Get<UF::AreaTriggerSplineCalculator>()->WriteCreate(data, owner, receiver);
+ }
+ if (PathType == 1)
+ {
+ PathData.Get<UF::AreaTriggerOrbit>()->WriteCreate(data, owner, receiver);
+ }
}
void AreaTriggerData::WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, AreaTrigger const* owner, Player const* receiver) const
@@ -7082,122 +7888,232 @@ void AreaTriggerData::WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fi
void AreaTriggerData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bool ignoreNestedChangesMask, AreaTrigger const* owner, Player const* receiver) const
{
- data.WriteBits(changesMask.GetBlock(0), 26);
+ data << uint32(changesMask.GetBlock(0));
+ data.WriteBits(changesMask.GetBlock(1), 4);
+ data.FlushBits();
if (changesMask[0])
{
if (changesMask[1])
{
- data.WriteBit(HeightIgnoresScale);
+ OverrideScaleCurve->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
- if (changesMask[2])
+ if (changesMask[6])
{
- data.WriteBit(Field_261);
+ data << *Caster;
}
- }
- data.FlushBits();
- if (changesMask[0])
- {
- if (changesMask[3])
+ if (changesMask[7])
{
- OverrideScaleCurve->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ data << uint32(Duration);
}
if (changesMask[8])
{
- data << *Caster;
+ data << uint32(TimeToTarget);
}
if (changesMask[9])
{
- data << uint32(Duration);
+ data << uint32(TimeToTargetScale);
}
if (changesMask[10])
{
- data << uint32(TimeToTarget);
+ data << uint32(TimeToTargetExtraScale);
}
if (changesMask[11])
{
- data << uint32(TimeToTargetScale);
+ data << uint32(TimeToTargetPos);
}
if (changesMask[12])
{
- data << uint32(TimeToTargetExtraScale);
+ data << int32(SpellID);
}
if (changesMask[13])
{
- data << uint32(TimeToTargetPos);
+ data << int32(SpellForVisuals);
}
if (changesMask[14])
{
- data << int32(SpellID);
+ SpellVisual->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
if (changesMask[15])
{
- data << int32(SpellForVisuals);
+ data << float(BoundsRadius2D);
}
if (changesMask[16])
{
- SpellVisual->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ data << uint32(DecalPropertiesID);
}
if (changesMask[17])
{
- data << float(BoundsRadius2D);
+ data << *CreatingEffectGUID;
}
if (changesMask[18])
{
- data << uint32(DecalPropertiesID);
+ data << *OrbitPathTarget;
}
if (changesMask[19])
{
- data << *CreatingEffectGUID;
+ data << *RollPitchYaw;
}
if (changesMask[20])
{
- data << uint32(NumUnitsInside);
+ data << int32(PositionalSoundKitID);
}
if (changesMask[21])
{
- data << uint32(NumPlayersInside);
+ data << uint32(MovementStartTime);
}
if (changesMask[22])
{
- data << *OrbitPathTarget;
+ data << uint32(CreationTime);
}
if (changesMask[23])
{
- data << *RollPitchYaw;
+ data << float(ZOffset);
}
- if (changesMask[24])
+ if (changesMask[25])
{
- data << int32(PositionalSoundKitID);
+ data << uint32(Flags);
}
- if (changesMask[4])
+ if (changesMask[27])
+ {
+ data << uint32(ScaleCurveId);
+ }
+ if (changesMask[28])
+ {
+ data << uint32(FacingCurveId);
+ }
+ if (changesMask[29])
+ {
+ data << uint32(MorphCurveId);
+ }
+ if (changesMask[30])
+ {
+ data << uint32(MoveCurveId);
+ }
+ if (changesMask[31])
+ {
+ data << float(Facing);
+ }
+ }
+ if (changesMask[32])
+ {
+ if (changesMask[34])
+ {
+ data << int32(PathType);
+ }
+ if (changesMask[35])
+ {
+ data << uint8(ShapeType);
+ }
+ if (changesMask[34])
+ {
+ if (PathType == 3)
+ {
+ PathData.Get<UF::AreaTriggerMovementScript>()->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ }
+ }
+ if (changesMask[35])
+ {
+ if (ShapeType == 0)
+ {
+ ShapeData.Get<UF::AreaTriggerSphere>()->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ }
+ if (ShapeType == 1)
+ {
+ ShapeData.Get<UF::AreaTriggerBox>()->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ }
+ if (ShapeType == 3)
+ {
+ ShapeData.Get<UF::AreaTriggerPolygon>()->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ }
+ if (ShapeType == 4)
+ {
+ ShapeData.Get<UF::AreaTriggerCylinder>()->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ }
+ if (ShapeType == 7)
+ {
+ ShapeData.Get<UF::AreaTriggerDisk>()->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ }
+ if (ShapeType == 8)
+ {
+ ShapeData.Get<UF::AreaTriggerBoundedPlane>()->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ }
+ }
+ }
+ if (changesMask[0])
+ {
+ if (changesMask[2])
{
ExtraScaleCurve->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
- if (changesMask[5])
+ }
+ data.FlushBits();
+ if (changesMask[0])
+ {
+ data.WriteBits(TargetRollPitchYaw.has_value(), 1);
+ }
+ if (changesMask[32])
+ {
+ data.WriteBits(ForcedPositionAndRotation.has_value(), 1);
+ }
+ data.FlushBits();
+ if (changesMask[0])
+ {
+ if (changesMask[3])
{
OverrideMoveCurveX->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
- if (changesMask[6])
+ if (changesMask[24])
+ {
+ if (TargetRollPitchYaw.has_value())
+ {
+ data << *TargetRollPitchYaw;
+ }
+ }
+ }
+ if (changesMask[32])
+ {
+ if (changesMask[33])
+ {
+ if (ForcedPositionAndRotation.has_value())
+ {
+ ForcedPositionAndRotation->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ }
+ }
+ }
+ if (changesMask[0])
+ {
+ if (changesMask[4])
{
OverrideMoveCurveY->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
- if (changesMask[7])
+ if (changesMask[5])
{
OverrideMoveCurveZ->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
- if (changesMask[25])
+ if (changesMask[26])
{
VisualAnim->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
}
}
- data.FlushBits();
+ if (changesMask[32])
+ {
+ if (changesMask[34])
+ {
+ if (PathType == 0)
+ {
+ PathData.Get<UF::AreaTriggerSplineCalculator>()->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ }
+ if (PathType == 1)
+ {
+ PathData.Get<UF::AreaTriggerOrbit>()->WriteUpdate(data, ignoreNestedChangesMask, owner, receiver);
+ }
+ }
+ }
}
void AreaTriggerData::ClearChangesMask()
{
- Base::ClearChangesMask(HeightIgnoresScale);
- Base::ClearChangesMask(Field_261);
Base::ClearChangesMask(OverrideScaleCurve);
Base::ClearChangesMask(ExtraScaleCurve);
Base::ClearChangesMask(OverrideMoveCurveX);
@@ -7215,12 +8131,25 @@ void AreaTriggerData::ClearChangesMask()
Base::ClearChangesMask(BoundsRadius2D);
Base::ClearChangesMask(DecalPropertiesID);
Base::ClearChangesMask(CreatingEffectGUID);
- Base::ClearChangesMask(NumUnitsInside);
- Base::ClearChangesMask(NumPlayersInside);
Base::ClearChangesMask(OrbitPathTarget);
Base::ClearChangesMask(RollPitchYaw);
Base::ClearChangesMask(PositionalSoundKitID);
+ Base::ClearChangesMask(MovementStartTime);
+ Base::ClearChangesMask(CreationTime);
+ Base::ClearChangesMask(ZOffset);
+ Base::ClearChangesMask(TargetRollPitchYaw);
+ Base::ClearChangesMask(Flags);
Base::ClearChangesMask(VisualAnim);
+ Base::ClearChangesMask(ScaleCurveId);
+ Base::ClearChangesMask(FacingCurveId);
+ Base::ClearChangesMask(MorphCurveId);
+ Base::ClearChangesMask(MoveCurveId);
+ Base::ClearChangesMask(Facing);
+ Base::ClearChangesMask(ForcedPositionAndRotation);
+ Base::ClearChangesMask(PathType);
+ Base::ClearChangesMask(ShapeType);
+ Base::ClearChangesMask(PathData);
+ Base::ClearChangesMask(ShapeData);
_changesMask.ResetAll();
}
diff --git a/src/server/game/Entities/Object/Updates/UpdateFields.h b/src/server/game/Entities/Object/Updates/UpdateFields.h
index 6635950cc62..db0f1859545 100644
--- a/src/server/game/Entities/Object/Updates/UpdateFields.h
+++ b/src/server/game/Entities/Object/Updates/UpdateFields.h
@@ -227,6 +227,8 @@ struct UnitChannel : public IsUpdateFieldStructureTag
{
int32 SpellID;
UF::SpellCastVisual SpellVisual;
+ uint32 StartTimeMs;
+ uint32 Duration;
void WriteCreate(ByteBuffer& data, Unit const* owner, Player const* receiver) const;
void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Unit const* owner, Player const* receiver) const;
@@ -258,7 +260,18 @@ struct PassiveSpellHistory : public IsUpdateFieldStructureTag
bool operator!=(PassiveSpellHistory const& right) const { return !(*this == right); }
};
-struct UnitData : public IsUpdateFieldStructureTag, public HasChangesMask<222>
+struct UnitAssistActionData : public IsUpdateFieldStructureTag, public HasChangesMask<4>
+{
+ UpdateField<uint8, 0, 1> Type;
+ UpdateField<std::string, 0, 2> PlayerName;
+ UpdateField<uint32, 0, 3> VirtualRealmAddress;
+
+ void WriteCreate(ByteBuffer& data, Unit const* owner, Player const* receiver) const;
+ void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Unit const* owner, Player const* receiver) const;
+ void ClearChangesMask();
+};
+
+struct UnitData : public IsUpdateFieldStructureTag, public HasChangesMask<223>
{
UpdateField<bool, 0, 1> Field_314;
UpdateField<std::vector<uint32>, 0, 2> StateWorldEffectIDs;
@@ -406,19 +419,20 @@ struct UnitData : public IsUpdateFieldStructureTag, public HasChangesMask<222>
UpdateField<float, 128, 132> Field_31C;
UpdateField<float, 128, 133> Field_320; // Soft targeting related? When UnitFlags3 & 0x40000000 is set, increases some range check using CombatReach by this amount
UpdateField<ObjectGuid, 128, 134> NameplateAttachToGUID; // When set, nameplate of this unit will instead appear on that object
- UpdateFieldArray<int32, 10, 135, 136> Power;
- UpdateFieldArray<int32, 10, 135, 146> MaxPower;
- UpdateFieldArray<float, 10, 135, 156> PowerRegenFlatModifier;
- UpdateFieldArray<float, 10, 135, 166> PowerRegenInterruptedFlatModifier;
- UpdateFieldArray<UF::VisibleItem, 3, 176, 177> VirtualItems;
- UpdateFieldArray<uint32, 2, 180, 181> AttackRoundBaseTime;
- UpdateFieldArray<int32, 4, 183, 184> Stats;
- UpdateFieldArray<int32, 4, 183, 188> StatPosBuff;
- UpdateFieldArray<int32, 4, 183, 192> StatNegBuff;
- UpdateFieldArray<int32, 4, 183, 196> StatSupportBuff;
- UpdateFieldArray<int32, 7, 200, 201> Resistances;
- UpdateFieldArray<int32, 7, 200, 208> BonusResistanceMods;
- UpdateFieldArray<int32, 7, 200, 215> ManaCostModifier;
+ OptionalUpdateField<UF::UnitAssistActionData, 128, 135> AssistActionData;
+ UpdateFieldArray<int32, 10, 136, 137> Power;
+ UpdateFieldArray<int32, 10, 136, 147> MaxPower;
+ UpdateFieldArray<float, 10, 136, 157> PowerRegenFlatModifier;
+ UpdateFieldArray<float, 10, 136, 167> PowerRegenInterruptedFlatModifier;
+ UpdateFieldArray<UF::VisibleItem, 3, 177, 178> VirtualItems;
+ UpdateFieldArray<uint32, 2, 181, 182> AttackRoundBaseTime;
+ UpdateFieldArray<int32, 4, 184, 185> Stats;
+ UpdateFieldArray<int32, 4, 184, 189> StatPosBuff;
+ UpdateFieldArray<int32, 4, 184, 193> StatNegBuff;
+ UpdateFieldArray<int32, 4, 184, 197> StatSupportBuff;
+ UpdateFieldArray<int32, 7, 201, 202> Resistances;
+ UpdateFieldArray<int32, 7, 201, 209> BonusResistanceMods;
+ UpdateFieldArray<int32, 7, 201, 216> ManaCostModifier;
void WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Unit const* owner, Player const* receiver) const;
void WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Unit const* owner, Player const* receiver) const;
@@ -499,6 +513,25 @@ struct CTROptions : public IsUpdateFieldStructureTag
bool operator!=(CTROptions const& right) const { return !(*this == right); }
};
+struct LeaverInfo : public IsUpdateFieldStructureTag
+{
+ ObjectGuid BnetAccountGUID;
+ float LeaveScore;
+ uint32 SeasonID;
+ uint32 TotalLeaves;
+ uint32 TotalSuccesses;
+ int32 ConsecutiveSuccesses;
+ int64 LastPenaltyTime;
+ int64 LeaverExpirationTime;
+ int32 Unknown_1120;
+ uint32 LeaverStatus;
+
+ void WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const;
+ void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const;
+ bool operator==(LeaverInfo const& right) const;
+ bool operator!=(LeaverInfo const& right) const { return !(*this == right); }
+};
+
struct DeclinedNames : public IsUpdateFieldStructureTag, public HasChangesMask<6>
{
UpdateFieldArray<std::string, 5, 0, 1> Name;
@@ -521,7 +554,7 @@ struct CustomTabardInfo : public IsUpdateFieldStructureTag, public HasChangesMas
void ClearChangesMask();
};
-struct PlayerData : public IsUpdateFieldStructureTag, public HasChangesMask<322>
+struct PlayerData : public IsUpdateFieldStructureTag, public HasChangesMask<324>
{
UpdateField<bool, 0, 1> HasQuestSession;
UpdateField<bool, 0, 2> HasLevelLink;
@@ -551,29 +584,31 @@ struct PlayerData : public IsUpdateFieldStructureTag, public HasChangesMask<322>
UpdateField<int32, 0, 26> FakeInebriation;
UpdateField<uint32, 0, 27> VirtualPlayerRealm;
UpdateField<uint32, 0, 28> CurrentSpecID;
- UpdateField<int32, 0, 29> TaxiMountAnimKitID;
- UpdateField<uint8, 0, 30> CurrentBattlePetBreedQuality;
- UpdateField<int32, 0, 31> HonorLevel;
- UpdateField<int64, 32, 33> LogoutTime;
- UpdateField<std::string, 32, 34> Name;
- UpdateField<int32, 32, 35> Field_1AC;
- UpdateField<int32, 32, 36> Field_1B0;
- UpdateField<int32, 32, 37> CurrentBattlePetSpeciesID;
- UpdateField<UF::CTROptions, 32, 38> CtrOptions;
- UpdateField<int32, 32, 39> CovenantID;
- UpdateField<int32, 32, 40> SoulbindID;
- UpdateField<WorldPackets::MythicPlus::DungeonScoreSummary, 32, 41> DungeonScore;
- UpdateField<ObjectGuid, 32, 42> SpectateTarget;
- UpdateField<int32, 32, 43> Field_200;
- OptionalUpdateField<UF::DeclinedNames, 32, 44> DeclinedNames;
- UpdateField<UF::CustomTabardInfo, 32, 45> PersonalTabard;
- UpdateFieldArray<uint8, 2, 46, 47> PartyType;
- UpdateFieldArray<UF::QuestLog, 175, 49, 50> QuestLog;
- UpdateFieldArray<UF::VisibleItem, 19, 225, 226> VisibleItems;
- UpdateFieldArray<float, 6, 245, 246> AvgItemLevel;
- UpdateFieldArray<UF::ZonePlayerForcedReaction, 32, 252, 253> ForcedReactions;
- UpdateFieldArray<WorldPackets::Item::ItemInstance, 16, 285, 286> VisibleEquipableSpells;
- UpdateFieldArray<uint32, 19, 302, 303> Field_3120;
+ UpdateField<int32, 0, 29> CurrentCombatTraitConfigSubTreeID;
+ UpdateField<int32, 0, 30> TaxiMountAnimKitID;
+ UpdateField<uint8, 0, 31> CurrentBattlePetBreedQuality;
+ UpdateField<int32, 32, 33> HonorLevel;
+ UpdateField<int64, 32, 34> LogoutTime;
+ UpdateField<std::string, 32, 35> Name;
+ UpdateField<int32, 32, 36> Field_1AC;
+ UpdateField<int32, 32, 37> Field_1B0;
+ UpdateField<int32, 32, 38> CurrentBattlePetSpeciesID;
+ UpdateField<UF::CTROptions, 32, 39> CtrOptions;
+ UpdateField<int32, 32, 40> CovenantID;
+ UpdateField<int32, 32, 41> SoulbindID;
+ UpdateField<WorldPackets::MythicPlus::DungeonScoreSummary, 32, 42> DungeonScore;
+ UpdateField<UF::LeaverInfo, 32, 43> LeaverInfo;
+ UpdateField<ObjectGuid, 32, 44> SpectateTarget;
+ UpdateField<int32, 32, 45> Field_200;
+ OptionalUpdateField<UF::DeclinedNames, 32, 46> DeclinedNames;
+ UpdateField<UF::CustomTabardInfo, 32, 47> PersonalTabard;
+ UpdateFieldArray<uint8, 2, 48, 49> PartyType;
+ UpdateFieldArray<UF::QuestLog, 175, 51, 52> QuestLog;
+ UpdateFieldArray<UF::VisibleItem, 19, 227, 228> VisibleItems;
+ UpdateFieldArray<float, 6, 247, 248> AvgItemLevel;
+ UpdateFieldArray<UF::ZonePlayerForcedReaction, 32, 254, 255> ForcedReactions;
+ UpdateFieldArray<WorldPackets::Item::ItemInstance, 16, 287, 288> VisibleEquipableSpells;
+ UpdateFieldArray<uint32, 19, 304, 305> Field_3120;
void WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Player const* owner, Player const* receiver) const;
void WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Player const* owner, Player const* receiver) const;
@@ -791,6 +826,7 @@ struct TraitEntry : public IsUpdateFieldStructureTag
int32 TraitNodeEntryID;
int32 Rank;
int32 GrantedRanks;
+ int32 BonusRanks;
void WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const;
void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const;
@@ -1025,6 +1061,24 @@ struct DelveData : public IsUpdateFieldStructureTag
bool operator!=(DelveData const& right) const { return !(*this == right); }
};
+struct ChallengeModeData : public IsUpdateFieldStructureTag
+{
+ int32 Unknown_1120_1;
+ int32 Unknown_1120_2;
+ uint64 Unknown_1120_3;
+ int64 Unknown_1120_4;
+ ObjectGuid KeystoneOwnerGUID;
+ ObjectGuid LeaverGUID;
+ uint32 IsActive;
+ uint32 HasRestrictions;
+ uint32 CanVoteAbandon;
+
+ void WriteCreate(ByteBuffer& data, Player const* owner, Player const* receiver) const;
+ void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Player const* owner, Player const* receiver) const;
+ bool operator==(ChallengeModeData const& right) const;
+ bool operator!=(ChallengeModeData const& right) const { return !(*this == right); }
+};
+
struct Research : public IsUpdateFieldStructureTag
{
int16 ResearchProjectID;
@@ -1035,7 +1089,7 @@ struct Research : public IsUpdateFieldStructureTag
bool operator!=(Research const& right) const { return !(*this == right); }
};
-struct ActivePlayerData : public IsUpdateFieldStructureTag, public HasChangesMask<517>
+struct ActivePlayerData : public IsUpdateFieldStructureTag, public HasChangesMask<385>
{
UpdateField<bool, 0, 1> BackpackAutoSortDisabled;
UpdateField<bool, 0, 2> BackpackSellJunkDisabled;
@@ -1043,9 +1097,9 @@ struct ActivePlayerData : public IsUpdateFieldStructureTag, public HasChangesMas
UpdateField<bool, 0, 4> SortBagsRightToLeft;
UpdateField<bool, 0, 5> InsertItemsLeftToRight;
UpdateField<bool, 0, 6> HasPerksProgramPendingReward;
- UpdateFieldArray<DynamicUpdateFieldBase<uint16>, 1, 42, 43> ResearchSites;
- UpdateFieldArray<DynamicUpdateFieldBase<uint32>, 1, 44, 45> ResearchSiteProgress;
- UpdateFieldArray<DynamicUpdateFieldBase<UF::Research>, 1, 46, 47> Research;
+ UpdateFieldArray<DynamicUpdateFieldBase<uint16>, 1, 43, 44> ResearchSites;
+ UpdateFieldArray<DynamicUpdateFieldBase<uint32>, 1, 45, 46> ResearchSiteProgress;
+ UpdateFieldArray<DynamicUpdateFieldBase<UF::Research>, 1, 47, 48> Research;
DynamicUpdateField<uint64, 0, 7> KnownTitles;
DynamicUpdateField<UF::PlayerDataElement, 0, 8> CharacterDataElements;
DynamicUpdateField<UF::PlayerDataElement, 0, 9> AccountDataElements;
@@ -1079,119 +1133,121 @@ struct ActivePlayerData : public IsUpdateFieldStructureTag, public HasChangesMas
DynamicUpdateField<UF::CharacterRestriction, 0, 24> CharacterRestrictions;
DynamicUpdateField<UF::TraitConfig, 32, 34> TraitConfigs;
DynamicUpdateField<UF::CraftingOrder, 32, 35> CraftingOrders;
- DynamicUpdateField<UF::BankTabSettings, 32, 41> AccountBankTabSettings;
- UpdateField<ObjectGuid, 32, 48> FarsightObject;
- UpdateField<ObjectGuid, 32, 49> SummonedBattlePetGUID;
- UpdateField<uint64, 32, 50> Coinage;
- UpdateField<uint64, 32, 51> AccountBankCoinage;
- UpdateField<int32, 32, 52> XP;
- UpdateField<int32, 32, 53> NextLevelXP;
- UpdateField<int32, 32, 54> TrialXP;
- UpdateField<UF::SkillInfo, 32, 55> Skill;
- UpdateField<int32, 32, 56> CharacterPoints;
- UpdateField<int32, 32, 57> MaxTalentTiers;
- UpdateField<uint32, 32, 58> TrackCreatureMask;
- UpdateField<float, 32, 59> MainhandExpertise;
- UpdateField<float, 32, 60> OffhandExpertise;
- UpdateField<float, 32, 61> RangedExpertise;
- UpdateField<float, 32, 62> CombatRatingExpertise;
- UpdateField<float, 32, 63> BlockPercentage;
- UpdateField<float, 32, 64> DodgePercentage;
- UpdateField<float, 32, 65> DodgePercentageFromAttribute;
- UpdateField<float, 32, 66> ParryPercentage;
- UpdateField<float, 32, 67> ParryPercentageFromAttribute;
- UpdateField<float, 32, 68> CritPercentage;
- UpdateField<float, 32, 69> RangedCritPercentage;
- UpdateField<float, 70, 71> OffhandCritPercentage;
- UpdateField<float, 70, 72> SpellCritPercentage;
- UpdateField<int32, 70, 73> ShieldBlock;
- UpdateField<float, 70, 74> ShieldBlockCritPercentage;
- UpdateField<float, 70, 75> Mastery;
- UpdateField<float, 70, 76> Speed;
- UpdateField<float, 70, 77> Avoidance;
- UpdateField<float, 70, 78> Sturdiness;
- UpdateField<int32, 70, 79> Versatility;
- UpdateField<float, 70, 80> VersatilityBonus;
- UpdateField<float, 70, 81> PvpPowerDamage;
- UpdateField<float, 70, 82> PvpPowerHealing;
- UpdateField<UF::BitVectors, 70, 83> BitVectors;
- UpdateField<int32, 70, 84> ModHealingDonePos;
- UpdateField<float, 70, 85> ModHealingPercent;
- UpdateField<float, 70, 86> ModPeriodicHealingDonePercent;
- UpdateField<float, 70, 87> ModSpellPowerPercent;
- UpdateField<float, 70, 88> ModResiliencePercent;
- UpdateField<float, 70, 89> OverrideSpellPowerByAPPercent;
- UpdateField<float, 70, 90> OverrideAPBySpellPowerPercent;
- UpdateField<int32, 70, 91> ModTargetResistance;
- UpdateField<int32, 70, 92> ModTargetPhysicalResistance;
- UpdateField<uint32, 70, 93> LocalFlags;
- UpdateField<uint8, 70, 94> GrantableLevels;
- UpdateField<uint8, 70, 95> MultiActionBars;
- UpdateField<uint8, 70, 96> LifetimeMaxRank;
- UpdateField<uint8, 70, 97> NumRespecs;
- UpdateField<uint32, 70, 98> PvpMedals;
- UpdateField<uint16, 70, 99> TodayHonorableKills;
- UpdateField<uint16, 70, 100> YesterdayHonorableKills;
- UpdateField<uint32, 70, 101> LifetimeHonorableKills;
- UpdateField<int32, 102, 103> WatchedFactionIndex;
- UpdateField<int32, 102, 104> MaxLevel;
- UpdateField<int32, 102, 105> ScalingPlayerLevelDelta;
- UpdateField<int32, 102, 106> MaxCreatureScalingLevel;
- UpdateField<int32, 102, 107> PetSpellPower;
- UpdateField<float, 102, 108> UiHitModifier;
- UpdateField<float, 102, 109> UiSpellHitModifier;
- UpdateField<int32, 102, 110> HomeRealmTimeOffset;
- UpdateField<float, 102, 111> ModPetHaste;
- UpdateField<int8, 102, 112> JailersTowerLevelMax;
- UpdateField<int8, 102, 113> JailersTowerLevel;
- UpdateField<uint8, 102, 114> LocalRegenFlags;
- UpdateField<uint8, 102, 115> AuraVision;
- UpdateField<uint8, 102, 116> NumBackpackSlots;
- UpdateField<int32, 102, 117> OverrideSpellsID;
- UpdateField<uint16, 102, 118> LootSpecID;
- UpdateField<uint32, 102, 119> OverrideZonePVPType;
- UpdateField<int32, 102, 120> Honor;
- UpdateField<int32, 102, 121> HonorNextLevel;
- UpdateField<int32, 102, 122> PerksProgramCurrency;
- UpdateField<uint8, 102, 123> NumBankSlots;
- UpdateField<uint8, 102, 124> NumAccountBankTabs;
- UpdateField<UF::ResearchHistory, 102, 125> ResearchHistory;
- UpdateField<WorldPackets::PerksProgram::PerksVendorItem, 102, 126> FrozenPerksVendorItem;
- UpdateField<UF::ActivePlayerUnk901, 102, 128> Field_1410;
- OptionalUpdateField<UF::QuestSession, 102, 127> QuestSession;
- UpdateField<int32, 102, 129> UiChromieTimeExpansionID;
- UpdateField<int32, 102, 130> TimerunningSeasonID;
- UpdateField<int32, 102, 131> TransportServerTime;
- UpdateField<uint32, 102, 132> WeeklyRewardsPeriodSinceOrigin; // week count since Cfg_RegionsEntry::ChallengeOrigin
- UpdateField<int16, 102, 133> DEBUGSoulbindConduitRank;
- UpdateField<WorldPackets::MythicPlus::DungeonScoreData, 134, 135> DungeonScore;
- UpdateField<uint32, 134, 136> ActiveCombatTraitConfigID;
- UpdateField<int32, 134, 137> ItemUpgradeHighOnehandWeaponItemID;
- UpdateField<int32, 134, 138> ItemUpgradeHighFingerItemID;
- UpdateField<float, 134, 139> ItemUpgradeHighFingerWatermark;
- UpdateField<int32, 134, 140> ItemUpgradeHighTrinketItemID;
- UpdateField<float, 134, 141> ItemUpgradeHighTrinketWatermark;
- UpdateField<uint64, 134, 142> LootHistoryInstanceID;
- OptionalUpdateField<UF::StableInfo, 134, 143> PetStable;
- UpdateField<uint8, 134, 144> RequiredMountCapabilityFlags;
- OptionalUpdateField<UF::WalkInData, 134, 145> WalkInData;
- OptionalUpdateField<UF::DelveData, 134, 146> DelveData;
- UpdateFieldArray<ObjectGuid, 232, 147, 148> InvSlots;
- UpdateFieldArray<UF::RestInfo, 2, 380, 381> RestInfo;
- UpdateFieldArray<int32, 7, 383, 384> ModDamageDonePos;
- UpdateFieldArray<int32, 7, 383, 391> ModDamageDoneNeg;
- UpdateFieldArray<float, 7, 383, 398> ModDamageDonePercent;
- UpdateFieldArray<float, 7, 383, 405> ModHealingDonePercent;
- UpdateFieldArray<float, 3, 412, 413> WeaponDmgMultipliers;
- UpdateFieldArray<float, 3, 412, 416> WeaponAtkSpeedMultipliers;
- UpdateFieldArray<uint32, 12, 419, 420> BuybackPrice;
- UpdateFieldArray<int64, 12, 419, 432> BuybackTimestamp;
- UpdateFieldArray<int32, 32, 444, 445> CombatRatings;
- UpdateFieldArray<uint32, 4, 477, 478> NoReagentCostMask;
- UpdateFieldArray<int32, 2, 482, 483> ProfessionSkillLine;
- UpdateFieldArray<uint32, 5, 485, 486> BagSlotFlags;
- UpdateFieldArray<uint32, 7, 491, 492> BankBagSlotFlags;
- UpdateFieldArray<float, 17, 499, 500> ItemUpgradeHighWatermark;
+ DynamicUpdateField<UF::BankTabSettings, 32, 41> CharacterBankTabSettings;
+ DynamicUpdateField<UF::BankTabSettings, 32, 42> AccountBankTabSettings;
+ UpdateField<ObjectGuid, 32, 49> FarsightObject;
+ UpdateField<ObjectGuid, 32, 50> SummonedBattlePetGUID;
+ UpdateField<uint64, 32, 51> Coinage;
+ UpdateField<uint64, 32, 52> AccountBankCoinage;
+ UpdateField<int32, 32, 53> XP;
+ UpdateField<int32, 32, 54> NextLevelXP;
+ UpdateField<int32, 32, 55> TrialXP;
+ UpdateField<UF::SkillInfo, 32, 56> Skill;
+ UpdateField<int32, 32, 57> CharacterPoints;
+ UpdateField<int32, 32, 58> MaxTalentTiers;
+ UpdateField<uint32, 32, 59> TrackCreatureMask;
+ UpdateField<float, 32, 60> MainhandExpertise;
+ UpdateField<float, 32, 61> OffhandExpertise;
+ UpdateField<float, 32, 62> RangedExpertise;
+ UpdateField<float, 32, 63> CombatRatingExpertise;
+ UpdateField<float, 32, 64> BlockPercentage;
+ UpdateField<float, 32, 65> DodgePercentage;
+ UpdateField<float, 32, 66> DodgePercentageFromAttribute;
+ UpdateField<float, 32, 67> ParryPercentage;
+ UpdateField<float, 32, 68> ParryPercentageFromAttribute;
+ UpdateField<float, 32, 69> CritPercentage;
+ UpdateField<float, 70, 71> RangedCritPercentage;
+ UpdateField<float, 70, 72> OffhandCritPercentage;
+ UpdateField<float, 70, 73> SpellCritPercentage;
+ UpdateField<int32, 70, 74> ShieldBlock;
+ UpdateField<float, 70, 75> ShieldBlockCritPercentage;
+ UpdateField<float, 70, 76> Mastery;
+ UpdateField<float, 70, 77> Speed;
+ UpdateField<float, 70, 78> Avoidance;
+ UpdateField<float, 70, 79> Sturdiness;
+ UpdateField<int32, 70, 80> Versatility;
+ UpdateField<float, 70, 81> VersatilityBonus;
+ UpdateField<float, 70, 82> PvpPowerDamage;
+ UpdateField<float, 70, 83> PvpPowerHealing;
+ UpdateField<UF::BitVectors, 70, 84> BitVectors;
+ UpdateField<int32, 70, 85> ModHealingDonePos;
+ UpdateField<float, 70, 86> ModHealingPercent;
+ UpdateField<float, 70, 87> ModPeriodicHealingDonePercent;
+ UpdateField<float, 70, 88> ModSpellPowerPercent;
+ UpdateField<float, 70, 89> ModResiliencePercent;
+ UpdateField<float, 70, 90> OverrideSpellPowerByAPPercent;
+ UpdateField<float, 70, 91> OverrideAPBySpellPowerPercent;
+ UpdateField<int32, 70, 92> ModTargetResistance;
+ UpdateField<int32, 70, 93> ModTargetPhysicalResistance;
+ UpdateField<uint32, 70, 94> LocalFlags;
+ UpdateField<uint8, 70, 95> GrantableLevels;
+ UpdateField<uint8, 70, 96> MultiActionBars;
+ UpdateField<uint8, 70, 97> LifetimeMaxRank;
+ UpdateField<uint8, 70, 98> NumRespecs;
+ UpdateField<uint32, 70, 99> PvpMedals;
+ UpdateField<uint16, 70, 100> TodayHonorableKills;
+ UpdateField<uint16, 70, 101> YesterdayHonorableKills;
+ UpdateField<uint32, 102, 103> LifetimeHonorableKills;
+ UpdateField<int32, 102, 104> WatchedFactionIndex;
+ UpdateField<int32, 102, 105> MaxLevel;
+ UpdateField<int32, 102, 106> ScalingPlayerLevelDelta;
+ UpdateField<int32, 102, 107> MaxCreatureScalingLevel;
+ UpdateField<int32, 102, 108> PetSpellPower;
+ UpdateField<float, 102, 109> UiHitModifier;
+ UpdateField<float, 102, 110> UiSpellHitModifier;
+ UpdateField<int32, 102, 111> HomeRealmTimeOffset;
+ UpdateField<float, 102, 112> ModPetHaste;
+ UpdateField<int8, 102, 113> JailersTowerLevelMax;
+ UpdateField<int8, 102, 114> JailersTowerLevel;
+ UpdateField<uint8, 102, 115> LocalRegenFlags;
+ UpdateField<uint8, 102, 116> AuraVision;
+ UpdateField<uint8, 102, 117> NumBackpackSlots;
+ UpdateField<int32, 102, 118> OverrideSpellsID;
+ UpdateField<uint16, 102, 119> LootSpecID;
+ UpdateField<uint32, 102, 120> OverrideZonePVPType;
+ UpdateField<int32, 102, 121> Honor;
+ UpdateField<int32, 102, 122> HonorNextLevel;
+ UpdateField<int32, 102, 123> PerksProgramCurrency;
+ UpdateField<uint8, 102, 124> NumBankSlots;
+ UpdateField<uint8, 102, 125> NumCharacterBankTabs;
+ UpdateField<uint8, 102, 126> NumAccountBankTabs;
+ UpdateField<UF::ResearchHistory, 102, 127> ResearchHistory;
+ UpdateField<WorldPackets::PerksProgram::PerksVendorItem, 102, 128> FrozenPerksVendorItem;
+ UpdateField<UF::ActivePlayerUnk901, 102, 130> Field_1410;
+ OptionalUpdateField<UF::QuestSession, 102, 129> QuestSession;
+ UpdateField<int32, 102, 131> UiChromieTimeExpansionID;
+ UpdateField<int32, 102, 132> TimerunningSeasonID;
+ UpdateField<int32, 102, 133> TransportServerTime;
+ UpdateField<uint32, 134, 135> WeeklyRewardsPeriodSinceOrigin; // week count since Cfg_RegionsEntry::ChallengeOrigin
+ UpdateField<int16, 134, 136> DEBUGSoulbindConduitRank;
+ UpdateField<WorldPackets::MythicPlus::DungeonScoreData, 134, 137> DungeonScore;
+ UpdateField<uint32, 134, 138> ActiveCombatTraitConfigID;
+ UpdateField<int32, 134, 139> ItemUpgradeHighOnehandWeaponItemID;
+ UpdateField<int32, 134, 140> ItemUpgradeHighFingerItemID;
+ UpdateField<float, 134, 141> ItemUpgradeHighFingerWatermark;
+ UpdateField<int32, 134, 142> ItemUpgradeHighTrinketItemID;
+ UpdateField<float, 134, 143> ItemUpgradeHighTrinketWatermark;
+ UpdateField<uint64, 134, 144> LootHistoryInstanceID;
+ OptionalUpdateField<UF::StableInfo, 134, 145> PetStable;
+ UpdateField<uint8, 134, 146> RequiredMountCapabilityFlags;
+ OptionalUpdateField<UF::WalkInData, 134, 147> WalkInData;
+ OptionalUpdateField<UF::DelveData, 134, 148> DelveData;
+ OptionalUpdateField<UF::ChallengeModeData, 134, 149> ChallengeModeData;
+ UpdateFieldArray<ObjectGuid, 105, 150, 151> InvSlots;
+ UpdateFieldArray<UF::RestInfo, 2, 256, 257> RestInfo;
+ UpdateFieldArray<int32, 7, 259, 260> ModDamageDonePos;
+ UpdateFieldArray<int32, 7, 259, 267> ModDamageDoneNeg;
+ UpdateFieldArray<float, 7, 259, 274> ModDamageDonePercent;
+ UpdateFieldArray<float, 7, 259, 281> ModHealingDonePercent;
+ UpdateFieldArray<float, 3, 288, 289> WeaponDmgMultipliers;
+ UpdateFieldArray<float, 3, 288, 292> WeaponAtkSpeedMultipliers;
+ UpdateFieldArray<uint32, 12, 295, 296> BuybackPrice;
+ UpdateFieldArray<int64, 12, 295, 308> BuybackTimestamp;
+ UpdateFieldArray<int32, 32, 320, 321> CombatRatings;
+ UpdateFieldArray<uint32, 4, 353, 354> NoReagentCostMask;
+ UpdateFieldArray<int32, 2, 358, 359> ProfessionSkillLine;
+ UpdateFieldArray<uint32, 5, 361, 362> BagSlotFlags;
+ UpdateFieldArray<float, 17, 367, 368> ItemUpgradeHighWatermark;
void WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Player const* owner, Player const* receiver) const;
void WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Player const* owner, Player const* receiver) const;
@@ -1199,7 +1255,22 @@ struct ActivePlayerData : public IsUpdateFieldStructureTag, public HasChangesMas
void ClearChangesMask();
};
-struct GameObjectData : public IsUpdateFieldStructureTag, public HasChangesMask<25>
+struct GameObjectAssistActionData : public IsUpdateFieldStructureTag
+{
+ std::string PlayerName;
+ std::string MonsterName;
+ uint32 VirtualRealmAddress;
+ uint8 Sex;
+ int64 Time;
+ int32 DelveTier;
+
+ void WriteCreate(ByteBuffer& data, GameObject const* owner, Player const* receiver) const;
+ void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, GameObject const* owner, Player const* receiver) const;
+ bool operator==(GameObjectAssistActionData const& right) const;
+ bool operator!=(GameObjectAssistActionData const& right) const { return !(*this == right); }
+};
+
+struct GameObjectData : public IsUpdateFieldStructureTag, public HasChangesMask<26>
{
UpdateField<std::vector<uint32>, 0, 1> StateWorldEffectIDs;
struct StateWorldEffectIDsTag : ViewerDependentValueTag<std::vector<uint32>> {};
@@ -1232,6 +1303,7 @@ struct GameObjectData : public IsUpdateFieldStructureTag, public HasChangesMask<
UpdateField<uint32, 0, 22> UiWidgetItemID;
UpdateField<uint32, 0, 23> UiWidgetItemQuality;
UpdateField<uint32, 0, 24> UiWidgetItemUnknown1000;
+ OptionalUpdateField<UF::GameObjectAssistActionData, 0, 25> AssistActionData;
void WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, GameObject const* owner, Player const* receiver) const;
void WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, GameObject const* owner, Player const* receiver) const;
@@ -1300,33 +1372,163 @@ struct VisualAnim : public IsUpdateFieldStructureTag, public HasChangesMask<5>
void ClearChangesMask();
};
-struct AreaTriggerData : public IsUpdateFieldStructureTag, public HasChangesMask<26>
-{
- UpdateField<bool, 0, 1> HeightIgnoresScale;
- UpdateField<bool, 0, 2> Field_261;
- UpdateField<UF::ScaleCurve, 0, 3> OverrideScaleCurve;
- UpdateField<UF::ScaleCurve, 0, 4> ExtraScaleCurve;
- UpdateField<UF::ScaleCurve, 0, 5> OverrideMoveCurveX;
- UpdateField<UF::ScaleCurve, 0, 6> OverrideMoveCurveY;
- UpdateField<UF::ScaleCurve, 0, 7> OverrideMoveCurveZ;
- UpdateField<ObjectGuid, 0, 8> Caster;
- UpdateField<uint32, 0, 9> Duration;
- UpdateField<uint32, 0, 10> TimeToTarget;
- UpdateField<uint32, 0, 11> TimeToTargetScale;
- UpdateField<uint32, 0, 12> TimeToTargetExtraScale;
- UpdateField<uint32, 0, 13> TimeToTargetPos; // Linked to m_overrideMoveCurve
- UpdateField<int32, 0, 14> SpellID;
- UpdateField<int32, 0, 15> SpellForVisuals;
- UpdateField<UF::SpellCastVisual, 0, 16> SpellVisual;
- UpdateField<float, 0, 17> BoundsRadius2D;
- UpdateField<uint32, 0, 18> DecalPropertiesID;
- UpdateField<ObjectGuid, 0, 19> CreatingEffectGUID;
- UpdateField<uint32, 0, 20> NumUnitsInside;
- UpdateField<uint32, 0, 21> NumPlayersInside; // When not 0 this causes SpellVisualEvent 14 to trigger, playing alternate visuals, typically used by "SOAK THIS" areatriggers
- UpdateField<ObjectGuid, 0, 22> OrbitPathTarget;
- UpdateField<TaggedPosition<Position::XYZ>, 0, 23> RollPitchYaw;
- UpdateField<int32, 0, 24> PositionalSoundKitID;
- UpdateField<UF::VisualAnim, 0, 25> VisualAnim;
+struct ForceSetAreaTriggerPositionAndRotation : public IsUpdateFieldStructureTag
+{
+ ObjectGuid TriggerGUID;
+ TaggedPosition<::Position::XYZ> Position;
+ QuaternionData Rotation;
+
+ void WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const;
+ void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const;
+ bool operator==(ForceSetAreaTriggerPositionAndRotation const& right) const;
+ bool operator!=(ForceSetAreaTriggerPositionAndRotation const& right) const { return !(*this == right); }
+};
+
+struct AreaTriggerSplineCalculator : public IsUpdateFieldStructureTag, public HasChangesMask<3>
+{
+ UpdateField<bool, 0, 1> Catmullrom;
+ DynamicUpdateField<TaggedPosition<Position::XYZ>, 0, 2> Points;
+
+ void WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const;
+ void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const;
+ void ClearChangesMask();
+};
+
+struct AreaTriggerOrbit : public IsUpdateFieldStructureTag, public HasChangesMask<7>
+{
+ UpdateField<bool, 0, 1> CounterClockwise;
+ UpdateField<TaggedPosition<Position::XYZ>, 0, 2> Center;
+ UpdateField<float, 0, 3> Radius;
+ UpdateField<float, 0, 4> InitialAngle;
+ UpdateField<float, 0, 5> BlendFromRadius;
+ UpdateField<int32, 0, 6> ExtraTimeForBlending;
+
+ void WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const;
+ void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const;
+ void ClearChangesMask();
+};
+
+struct AreaTriggerMovementScript : public IsUpdateFieldStructureTag, public HasChangesMask<4>
+{
+ UpdateField<int32, 0, 1> SpellScriptID;
+ UpdateField<TaggedPosition<Position::XYZ>, 0, 2> Center;
+ UpdateField<uint32, 0, 3> CreationTime;
+
+ void WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const;
+ void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const;
+ void ClearChangesMask();
+};
+
+struct AreaTriggerSphere : public IsUpdateFieldStructureTag, public HasChangesMask<3>
+{
+ UpdateField<float, 0, 1> Radius;
+ UpdateField<float, 0, 2> RadiusTarget;
+
+ void WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const;
+ void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const;
+ void ClearChangesMask();
+};
+
+struct AreaTriggerBox : public IsUpdateFieldStructureTag, public HasChangesMask<3>
+{
+ UpdateField<TaggedPosition<Position::XYZ>, 0, 1> Extents;
+ UpdateField<TaggedPosition<Position::XYZ>, 0, 2> ExtentsTarget;
+
+ void WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const;
+ void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const;
+ void ClearChangesMask();
+};
+
+struct AreaTriggerPolygon : public IsUpdateFieldStructureTag, public HasChangesMask<5>
+{
+ DynamicUpdateField<TaggedPosition<Position::XY>, 0, 1> Vertices;
+ DynamicUpdateField<TaggedPosition<Position::XY>, 0, 2> VerticesTarget;
+ UpdateField<float, 0, 3> Height;
+ UpdateField<float, 0, 4> HeightTarget;
+
+ void WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const;
+ void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const;
+ void ClearChangesMask();
+};
+
+struct AreaTriggerCylinder : public IsUpdateFieldStructureTag, public HasChangesMask<7>
+{
+ UpdateField<float, 0, 1> Radius;
+ UpdateField<float, 0, 2> RadiusTarget;
+ UpdateField<float, 0, 3> Height;
+ UpdateField<float, 0, 4> HeightTarget;
+ UpdateField<float, 0, 5> LocationZOffset;
+ UpdateField<float, 0, 6> LocationZOffsetTarget;
+
+ void WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const;
+ void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const;
+ void ClearChangesMask();
+};
+
+struct AreaTriggerDisk : public IsUpdateFieldStructureTag, public HasChangesMask<9>
+{
+ UpdateField<float, 0, 1> InnerRadius;
+ UpdateField<float, 0, 2> InnerRadiusTarget;
+ UpdateField<float, 0, 3> OuterRadius;
+ UpdateField<float, 0, 4> OuterRadiusTarget;
+ UpdateField<float, 0, 5> Height;
+ UpdateField<float, 0, 6> HeightTarget;
+ UpdateField<float, 0, 7> LocationZOffset;
+ UpdateField<float, 0, 8> LocationZOffsetTarget;
+
+ void WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const;
+ void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const;
+ void ClearChangesMask();
+};
+
+struct AreaTriggerBoundedPlane : public IsUpdateFieldStructureTag, public HasChangesMask<3>
+{
+ UpdateField<TaggedPosition<Position::XY>, 0, 1> Extents;
+ UpdateField<TaggedPosition<Position::XY>, 0, 2> ExtentsTarget;
+
+ void WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const;
+ void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const;
+ void ClearChangesMask();
+};
+
+struct AreaTriggerData : public IsUpdateFieldStructureTag, public HasChangesMask<36>
+{
+ UpdateField<UF::ScaleCurve, 0, 1> OverrideScaleCurve;
+ UpdateField<UF::ScaleCurve, 0, 2> ExtraScaleCurve;
+ UpdateField<UF::ScaleCurve, 0, 3> OverrideMoveCurveX;
+ UpdateField<UF::ScaleCurve, 0, 4> OverrideMoveCurveY;
+ UpdateField<UF::ScaleCurve, 0, 5> OverrideMoveCurveZ;
+ UpdateField<ObjectGuid, 0, 6> Caster;
+ UpdateField<uint32, 0, 7> Duration;
+ UpdateField<uint32, 0, 8> TimeToTarget;
+ UpdateField<uint32, 0, 9> TimeToTargetScale;
+ UpdateField<uint32, 0, 10> TimeToTargetExtraScale;
+ UpdateField<uint32, 0, 11> TimeToTargetPos; // Linked to m_overrideMoveCurve
+ UpdateField<int32, 0, 12> SpellID;
+ UpdateField<int32, 0, 13> SpellForVisuals;
+ UpdateField<UF::SpellCastVisual, 0, 14> SpellVisual;
+ UpdateField<float, 0, 15> BoundsRadius2D;
+ UpdateField<uint32, 0, 16> DecalPropertiesID;
+ UpdateField<ObjectGuid, 0, 17> CreatingEffectGUID;
+ UpdateField<ObjectGuid, 0, 18> OrbitPathTarget;
+ UpdateField<TaggedPosition<Position::XYZ>, 0, 19> RollPitchYaw;
+ UpdateField<int32, 0, 20> PositionalSoundKitID;
+ UpdateField<uint32, 0, 21> MovementStartTime;
+ UpdateField<uint32, 0, 22> CreationTime;
+ UpdateField<float, 0, 23> ZOffset;
+ OptionalUpdateField<TaggedPosition<Position::XYZ>, 0, 24> TargetRollPitchYaw;
+ UpdateField<uint32, 0, 25> Flags;
+ UpdateField<UF::VisualAnim, 0, 26> VisualAnim;
+ UpdateField<uint32, 0, 27> ScaleCurveId;
+ UpdateField<uint32, 0, 28> FacingCurveId;
+ UpdateField<uint32, 0, 29> MorphCurveId;
+ UpdateField<uint32, 0, 30> MoveCurveId;
+ UpdateField<float, 0, 31> Facing;
+ OptionalUpdateField<UF::ForceSetAreaTriggerPositionAndRotation, 32, 33> ForcedPositionAndRotation;
+ UpdateField<int32, 32, 34> PathType;
+ UpdateField<uint8, 32, 35> ShapeType;
+ VariantUpdateField<32, 34, UF::AreaTriggerSplineCalculator, UF::AreaTriggerOrbit, UF::AreaTriggerMovementScript> PathData;
+ VariantUpdateField<32, 35, UF::AreaTriggerSphere, UF::AreaTriggerBox, UF::AreaTriggerPolygon, UF::AreaTriggerCylinder, UF::AreaTriggerDisk, UF::AreaTriggerBoundedPlane> ShapeData;
void WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, AreaTrigger const* owner, Player const* receiver) const;
void WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, AreaTrigger const* owner, Player const* receiver) const;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 3ac1815f4f6..1d28e4f8aac 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -337,8 +337,6 @@ Player::Player(WorldSession* session) : Unit(true), m_sceneMgr(this)
healthBeforeDuel = 0;
manaBeforeDuel = 0;
- memset(_voidStorageItems, 0, VOID_STORAGE_MAX_SLOT * sizeof(VoidStorageItem*));
-
_cinematicMgr = std::make_unique<CinematicMgr>(this);
m_achievementMgr = std::make_unique<PlayerAchievementMgr>(this);
@@ -374,9 +372,6 @@ Player::~Player()
for (ItemSetEffect* itemSetEff : ItemSetEff)
DeleteItemSetEffects(itemSetEff);
- for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
- delete _voidStorageItems[i];
-
sWorld->DecreasePlayerCount();
}
@@ -3719,21 +3714,9 @@ void Player::DestroyForPlayer(Player* target) const
if (target == this)
{
- for (uint8 i = EQUIPMENT_SLOT_START; i < BANK_SLOT_BAG_END; ++i)
- {
- if (m_items[i] == nullptr)
- continue;
-
- m_items[i]->DestroyForPlayer(target);
- }
-
- for (uint8 i = REAGENT_SLOT_START; i < CHILD_EQUIPMENT_SLOT_END; ++i)
- {
- if (m_items[i] == nullptr)
- continue;
-
- m_items[i]->DestroyForPlayer(target);
- }
+ for (Item* item : m_items)
+ if (item)
+ item->DestroyForPlayer(target);
}
}
@@ -4195,10 +4178,6 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
stmt->setUInt64(0, guid);
trans->Append(stmt);
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_CHAR_GUID);
- stmt->setUInt64(0, guid);
- trans->Append(stmt);
-
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_FISHINGSTEPS);
stmt->setUInt64(0, guid);
trans->Append(stmt);
@@ -4233,6 +4212,18 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
stmt->setUInt64(0, guid);
trans->Append(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_DATA_ELEMENTS_CHARACTER_BY_GUID);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_DATA_FLAGS_CHARACTER_BY_GUID);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_BANK_TAB_SETTINGS);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
sCharacterCache->DeleteCharacterCacheEntry(playerguid, name);
break;
}
@@ -9488,10 +9479,6 @@ uint32 Player::GetFreeInventorySlotCount(EnumFlag<ItemSearchLocation> location /
if (location.HasFlag(ItemSearchLocation::Bank))
{
- for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i)
- if (!GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- ++freeSlotCount;
-
for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i)
if (Bag* bag = GetBagByPos(i))
for (uint32 j = 0; j < GetBagSize(bag); ++j)
@@ -9506,10 +9493,6 @@ uint32 Player::GetFreeInventorySlotCount(EnumFlag<ItemSearchLocation> location /
for (uint32 j = 0; j < GetBagSize(bag); ++j)
if (!GetItemInBag(bag, j))
++freeSlotCount;
-
- for (uint8 i = REAGENT_SLOT_START; i < REAGENT_SLOT_END; ++i)
- if (!GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- ++freeSlotCount;
}
return freeSlotCount;
@@ -9759,21 +9742,10 @@ bool Player::IsEquipmentPos(uint8 bag, uint8 slot)
bool Player::IsBankPos(uint8 bag, uint8 slot)
{
- if (bag == INVENTORY_SLOT_BAG_0 && (slot >= BANK_SLOT_ITEM_START && slot < BANK_SLOT_ITEM_END))
- return true;
if (bag == INVENTORY_SLOT_BAG_0 && (slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END))
return true;
if (bag >= BANK_SLOT_BAG_START && bag < BANK_SLOT_BAG_END)
return true;
- if (bag == INVENTORY_SLOT_BAG_0 && (slot >= REAGENT_SLOT_START && slot < REAGENT_SLOT_END))
- return true;
- return false;
-}
-
-bool Player::IsReagentBankPos(uint8 bag, uint8 slot)
-{
- if (bag == INVENTORY_SLOT_BAG_0 && (slot >= REAGENT_SLOT_START && slot < REAGENT_SLOT_END))
- return true;
return false;
}
@@ -9795,6 +9767,13 @@ bool Player::IsChildEquipmentPos(uint8 bag, uint8 slot)
return bag == INVENTORY_SLOT_BAG_0 && (slot >= CHILD_EQUIPMENT_SLOT_START && slot < CHILD_EQUIPMENT_SLOT_END);
}
+bool Player::IsAccountBankPos(uint8 bag, uint8 /*slot*/)
+{
+ if (bag >= ACCOUNT_BANK_SLOT_BAG_START && bag < ACCOUNT_BANK_SLOT_BAG_END)
+ return true;
+ return false;
+}
+
bool Player::IsValidPos(uint8 bag, uint8 slot, bool explicit_pos) const
{
// post selected
@@ -9827,18 +9806,10 @@ bool Player::IsValidPos(uint8 bag, uint8 slot, bool explicit_pos) const
if (slot >= INVENTORY_SLOT_ITEM_START && slot < INVENTORY_SLOT_ITEM_START + GetInventorySlotCount())
return true;
- // bank main slots
- if (slot >= BANK_SLOT_ITEM_START && slot < BANK_SLOT_ITEM_END)
- return true;
-
// bank bag slots
if (slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END)
return true;
- // reagent bank bag slots
- if (slot >= REAGENT_SLOT_START && slot < REAGENT_SLOT_END)
- return true;
-
return false;
}
@@ -10126,10 +10097,6 @@ InventoryResult Player::CanStoreItem_InSpecificSlot(uint8 bag, uint8 slot, ItemP
// prevent cheating
if ((slot >= BUYBACK_SLOT_START && slot < BUYBACK_SLOT_END) || slot >= PLAYER_SLOT_END)
return EQUIP_ERR_WRONG_BAG_TYPE;
-
- // can't store anything else than crafting reagents in Reagent Bank
- if (IsReagentBankPos(bag, slot) && (!IsReagentBankUnlocked() || !pProto->IsCraftingReagent()))
- return EQUIP_ERR_WRONG_BAG_TYPE;
}
else
{
@@ -11072,12 +11039,6 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec& dest
ASSERT(bag == NULL_BAG && slot == NULL_SLOT); // when reagentBankOnly is true then bag & slot must be hardcoded constants, not client input
}
- if ((IsReagentBankPos(bag, slot) || reagentBankOnly) && !IsReagentBankUnlocked())
- return EQUIP_ERR_REAGENT_BANK_LOCKED;
-
- uint8 slotStart = reagentBankOnly ? uint8(REAGENT_SLOT_START) : uint8(BANK_SLOT_ITEM_START);
- uint8 slotEnd = reagentBankOnly ? uint8(REAGENT_SLOT_END) : uint8(BANK_SLOT_ITEM_END);
-
uint32 count = pItem->GetCount();
TC_LOG_DEBUG("entities.player.items", "Player::CanBankItem: Player '{}' ({}), Bag: {}, Slot: {}, Item: {}, Count: {}",
@@ -11114,7 +11075,7 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec& dest
if (!pItem->IsBag())
return EQUIP_ERR_WRONG_SLOT;
- if (slot - BANK_SLOT_BAG_START >= GetBankBagSlotCount())
+ if (slot - BANK_SLOT_BAG_START >= GetCharacterBankTabCount())
return EQUIP_ERR_NO_BANK_SLOT;
res = CanUseItem(pItem, not_loading);
@@ -11143,12 +11104,7 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec& dest
{
if (bag == INVENTORY_SLOT_BAG_0)
{
- res = CanStoreItem_InInventorySlots(slotStart, slotEnd, dest, pProto, count, true, pItem, bag, slot);
- if (res != EQUIP_ERR_OK)
- return res;
-
- if (count == 0)
- return EQUIP_ERR_OK;
+ return EQUIP_ERR_WRONG_SLOT; // TODO: check if INVENTORY_SLOT_BAG_0 condition is neccessary
}
else
{
@@ -11167,12 +11123,7 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec& dest
// search free slot in bag
if (bag == INVENTORY_SLOT_BAG_0)
{
- res = CanStoreItem_InInventorySlots(slotStart, slotEnd, dest, pProto, count, false, pItem, bag, slot);
- if (res != EQUIP_ERR_OK)
- return res;
-
- if (count == 0)
- return EQUIP_ERR_OK;
+ return EQUIP_ERR_WRONG_SLOT; // TODO: check if INVENTORY_SLOT_BAG_0 condition is neccessary
}
else
{
@@ -11193,50 +11144,14 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec& dest
// search stack for merge to
if (pProto->GetMaxStackSize() != 1)
{
- // in slots
- res = CanStoreItem_InInventorySlots(slotStart, slotEnd, dest, pProto, count, true, pItem, bag, slot);
- if (res != EQUIP_ERR_OK)
- return res;
-
- if (count == 0)
- return EQUIP_ERR_OK;
-
- // don't try to store reagents anywhere else than in Reagent Bank if we're on it
- if (!reagentBankOnly)
- {
- // in special bags
- if (pProto->GetBagFamily())
- {
- for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++)
- {
- res = CanStoreItem_InBag(i, dest, pProto, count, true, false, pItem, bag, slot);
- if (res != EQUIP_ERR_OK)
- continue;
-
- if (count == 0)
- return EQUIP_ERR_OK;
- }
- }
-
- // in regular bags
- for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++)
- {
- res = CanStoreItem_InBag(i, dest, pProto, count, true, true, pItem, bag, slot);
- if (res != EQUIP_ERR_OK)
- continue;
-
- if (count == 0)
- return EQUIP_ERR_OK;
- }
- }
- }
-
- // search free space in special bags (don't try to store reagents anywhere else than in Reagent Bank if we're on it)
- if (!reagentBankOnly && pProto->GetBagFamily())
- {
+ // in regular bags
for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++)
{
- res = CanStoreItem_InBag(i, dest, pProto, count, false, false, pItem, bag, slot);
+ // only consider tabs marked as reagents if requested
+ if (reagentBankOnly && !(*m_activePlayerData->CharacterBankTabSettings[i - BANK_SLOT_BAG_START].DepositFlags & AsUnderlyingType(BagSlotFlags::PriorityReagents)))
+ continue;
+
+ res = CanStoreItem_InBag(i, dest, pProto, count, true, true, pItem, bag, slot);
if (res != EQUIP_ERR_OK)
continue;
@@ -11245,26 +11160,19 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec& dest
}
}
- // search free space
- res = CanStoreItem_InInventorySlots(slotStart, slotEnd, dest, pProto, count, false, pItem, bag, slot);
- if (res != EQUIP_ERR_OK)
- return res;
-
- if (count == 0)
- return EQUIP_ERR_OK;
-
- // search free space in regular bags (don't try to store reagents anywhere else than in Reagent Bank if we're on it)
- if (!reagentBankOnly)
+ // search free space in regular bags
+ for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++)
{
- for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++)
- {
- res = CanStoreItem_InBag(i, dest, pProto, count, false, true, pItem, bag, slot);
- if (res != EQUIP_ERR_OK)
- continue;
+ // only consider tabs marked as reagents if requested
+ if (reagentBankOnly && !(*m_activePlayerData->CharacterBankTabSettings[i - BANK_SLOT_BAG_START].DepositFlags & AsUnderlyingType(BagSlotFlags::PriorityReagents)))
+ continue;
- if (count == 0)
- return EQUIP_ERR_OK;
- }
+ res = CanStoreItem_InBag(i, dest, pProto, count, false, true, pItem, bag, slot);
+ if (res != EQUIP_ERR_OK)
+ continue;
+
+ if (count == 0)
+ return EQUIP_ERR_OK;
}
return reagentBankOnly ? EQUIP_ERR_REAGENT_BANK_FULL : EQUIP_ERR_BANK_FULL;
@@ -12272,33 +12180,6 @@ uint32 Player::DestroyItemCount(uint32 itemEntry, uint32 count, bool update, boo
}
}
- // in bank
- for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; i++)
- {
- if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- {
- if (item->GetEntry() == itemEntry && !item->IsInTrade())
- {
- if (item->GetCount() + remcount <= count)
- {
- remcount += item->GetCount();
- DestroyItem(INVENTORY_SLOT_BAG_0, i, update);
- if (remcount >= count)
- return remcount;
- }
- else
- {
- item->SetCount(item->GetCount() - count + remcount);
- ItemRemovedQuestCheck(item->GetEntry(), count - remcount);
- if (IsInWorld() && update)
- item->SendUpdateToPlayer(this);
- item->SetState(ITEM_CHANGED, this);
- return count;
- }
- }
- }
- }
-
// in bank bags
for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++)
{
@@ -12364,34 +12245,6 @@ uint32 Player::DestroyItemCount(uint32 itemEntry, uint32 count, bool update, boo
}
}
- for (uint8 i = REAGENT_SLOT_START; i < REAGENT_SLOT_END; ++i)
- {
- if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- {
- if (item->GetEntry() == itemEntry && !item->IsInTrade())
- {
- if (item->GetCount() + remcount <= count)
- {
- // all keys can be unequipped
- remcount += item->GetCount();
- DestroyItem(INVENTORY_SLOT_BAG_0, i, update);
-
- if (remcount >= count)
- return remcount;
- }
- else
- {
- item->SetCount(item->GetCount() - count + remcount);
- ItemRemovedQuestCheck(item->GetEntry(), count - remcount);
- if (IsInWorld() && update)
- item->SendUpdateToPlayer(this);
- item->SetState(ITEM_CHANGED, this);
- return count;
- }
- }
- }
- }
-
for (uint8 i = CHILD_EQUIPMENT_SLOT_START; i < CHILD_EQUIPMENT_SLOT_END; ++i)
{
if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
@@ -12746,12 +12599,6 @@ void Player::SwapItem(uint16 src, uint16 dst)
}
}
- if (IsReagentBankPos(dst) && !IsReagentBankUnlocked())
- {
- SendEquipError(EQUIP_ERR_REAGENT_BANK_LOCKED, pSrcItem, pDstItem);
- return;
- }
-
// NOW this is or item move (swap with empty), or swap with another item (including bags in bag possitions)
// or swap empty bag with another empty or not empty bag (with items exchange)
@@ -12785,8 +12632,7 @@ void Player::SwapItem(uint16 src, uint16 dst)
RemoveItem(srcbag, srcslot, true);
BankItem(dest, pSrcItem, true);
- if (!IsReagentBankPos(dst))
- ItemRemovedQuestCheck(pSrcItem->GetEntry(), pSrcItem->GetCount());
+ ItemRemovedQuestCheck(pSrcItem->GetEntry(), pSrcItem->GetCount());
}
else if (IsEquipmentPos(dst))
{
@@ -17819,7 +17665,7 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
struct PlayerLoadData
{
// "SELECT c.guid, account, name, race, class, gender, level, xp, money, inventorySlots, inventoryBagFlags, bagSlotFlags1, bagSlotFlags2, bagSlotFlags3, bagSlotFlags4, bagSlotFlags5, "
- // "bankSlots, bankBagFlags, bankBagSlotFlags1, bankBagSlotFlags2, bankBagSlotFlags3, bankBagSlotFlags4, bankBagSlotFlags5, bankBagSlotFlags6, bankBagSlotFlags7, restState, playerFlags, playerFlagsEx, "
+ // "bankSlots, bankTabs, bankBagFlags, restState, playerFlags, playerFlagsEx, "
// "position_x, position_y, position_z, map, orientation, taximask, createTime, createMode, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, "
// "resettalents_time, primarySpecialization, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, summonedPetNumber, at_login, zone, online, death_expire_time, taxi_path, dungeonDifficulty, "
// "totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, "
@@ -17841,8 +17687,8 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
EnumFlag<BagSlotFlags> inventoryBagFlags = BagSlotFlags::None;
std::array<BagSlotFlags, 5> bagSlotFlags;
uint8 bankSlots;
+ uint8 bankTabs;
EnumFlag<BagSlotFlags> bankBagFlags = BagSlotFlags::None;
- std::array<BagSlotFlags, 7> bankBagSlotFlags;
PlayerRestState restState;
PlayerFlags playerFlags;
PlayerFlagsEx playerFlagsEx;
@@ -17921,9 +17767,8 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
for (BagSlotFlags& flags : bagSlotFlags)
flags = static_cast<BagSlotFlags>(fields[i++].GetUInt32());
bankSlots = fields[i++].GetUInt8();
+ bankTabs = fields[i++].GetUInt8();
bankBagFlags = static_cast<BagSlotFlags>(fields[i++].GetUInt32());
- for (BagSlotFlags& flags : bankBagSlotFlags)
- flags = static_cast<BagSlotFlags>(fields[i++].GetUInt32());
restState = PlayerRestState(fields[i++].GetUInt8());
playerFlags = PlayerFlags(fields[i++].GetUInt32());
playerFlagsEx = PlayerFlagsEx(fields[i++].GetUInt32());
@@ -18083,9 +17928,8 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
for (uint32 bagIndex = 0; bagIndex < fields.bagSlotFlags.size(); ++bagIndex)
ReplaceAllBagSlotFlags(bagIndex, fields.bagSlotFlags[bagIndex]);
SetBankBagSlotCount(fields.bankSlots);
+ SetCharacterBankTabCount(fields.bankTabs);
SetBankAutoSortDisabled(fields.bankBagFlags.HasFlag(BagSlotFlags::DisableAutoSort));
- for (uint32 bagIndex = 0; bagIndex < fields.bankBagSlotFlags.size(); ++bagIndex)
- ReplaceAllBankBagSlotFlags(bagIndex, fields.bankBagSlotFlags[bagIndex]);
SetNativeGender(fields.gender);
SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::Inebriation), fields.drunk);
ReplaceAllPlayerFlags(fields.playerFlags);
@@ -18520,6 +18364,8 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
// must be before inventory (some items required reputation check)
m_reputationMgr->LoadFromDB(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_REPUTATION));
+ _LoadCharacterBankTabSettings(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_BANK_TAB_SETTINGS));
+
_LoadInventory(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_INVENTORY),
holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_ARTIFACTS),
holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_AZERITE),
@@ -18528,9 +18374,6 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_AZERITE_EMPOWERED),
time_diff);
- if (IsVoidStorageUnlocked())
- _LoadVoidStorage(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_VOID_STORAGE));
-
// update items with duration and realtime
UpdateItemDuration(time_diff, true);
@@ -19195,63 +19038,6 @@ void Player::_LoadInventory(PreparedQueryResult result, PreparedQueryResult arti
ApplyAllAzeriteItemMods(true);
}
-void Player::_LoadVoidStorage(PreparedQueryResult result)
-{
- if (!result)
- return;
-
- do
- {
- // SELECT itemId, itemEntry, slot, creatorGuid, randomBonusListId, fixedScalingLevel, artifactKnowledgeLevel, context, bonusListIDs FROM character_void_storage WHERE playerGuid = ?
- Field* fields = result->Fetch();
-
- uint64 itemId = fields[0].GetUInt64();
- uint32 itemEntry = fields[1].GetUInt32();
- uint8 slot = fields[2].GetUInt8();
- ObjectGuid creatorGuid = fields[3].GetUInt64() ? ObjectGuid::Create<HighGuid::Player>(fields[3].GetUInt64()) : ObjectGuid::Empty;
- ItemRandomBonusListId randomBonusListId = fields[4].GetUInt32();
- uint32 fixedScalingLevel = fields[5].GetUInt32();
- uint32 artifactKnowledgeLevel = fields[6].GetUInt32();
- ItemContext context = ItemContext(fields[7].GetUInt8());
- std::vector<int32> bonusListIDs;
- for (std::string_view bonusListIDtoken : Trinity::Tokenize(fields[8].GetStringView(), ' ', false))
- if (Optional<int32> bonusListID = Trinity::StringTo<int32>(bonusListIDtoken))
- bonusListIDs.push_back(*bonusListID);
-
- if (!itemId)
- {
- TC_LOG_ERROR("entities.player", "Player::_LoadVoidStorage: Player '{}' ({}) has an item with an invalid id (item id: {}, entry: {}).",
- GetName(), GetGUID().ToString(), itemId, itemEntry);
- continue;
- }
-
- if (!sObjectMgr->GetItemTemplate(itemEntry))
- {
- TC_LOG_ERROR("entities.player", "Player::_LoadVoidStorage: Player '{}' ({}) has an item with an invalid entry (item id: {}, entry: {}).",
- GetName(), GetGUID().ToString(), itemId, itemEntry);
- continue;
- }
-
- if (slot >= VOID_STORAGE_MAX_SLOT)
- {
- TC_LOG_ERROR("entities.player", "Player::_LoadVoidStorage: Player '{}' ({}) has an item with an invalid slot (item id: {}, entry: {}, slot: {}).",
- GetName(), GetGUID().ToString(), itemId, itemEntry, slot);
- continue;
- }
-
- _voidStorageItems[slot] = new VoidStorageItem(itemId, itemEntry, creatorGuid, randomBonusListId, fixedScalingLevel, artifactKnowledgeLevel,
- context, bonusListIDs);
-
- WorldPackets::Item::ItemInstance voidInstance;
- voidInstance.Initialize(_voidStorageItems[slot]);
- BonusData bonus;
- bonus.Initialize(voidInstance);
-
- GetSession()->GetCollectionMgr()->AddItemAppearance(itemEntry, bonus.AppearanceModID);
- }
- while (result->NextRow());
-}
-
Item* Player::_LoadItem(CharacterDatabaseTransaction trans, uint32 zoneId, uint32 timeDiff, Field* fields)
{
Item* item = nullptr;
@@ -20300,6 +20086,27 @@ void Player::_LoadPlayerData(PreparedQueryResult elementsResult, PreparedQueryRe
}
}
+void Player::_LoadCharacterBankTabSettings(PreparedQueryResult result)
+{
+ if (result)
+ {
+ do
+ {
+ DEFINE_FIELD_ACCESSOR_CACHE_ANONYMOUS(PreparedResultSet, (tabId)(name)(icon)(description)(depositFlags)) fields { *result };
+
+ if (fields.tabId().GetUInt8() >= (BANK_SLOT_BAG_END - BANK_SLOT_BAG_START))
+ continue;
+
+ SetCharacterBankTabSettings(fields.tabId().GetUInt8(), fields.name().GetString(), fields.icon().GetString(),
+ fields.description().GetString(), static_cast<BagSlotFlags>(fields.depositFlags().GetUInt32()));
+
+ } while (result->NextRow());
+ }
+
+ while (m_activePlayerData->CharacterBankTabSettings.size() < *m_activePlayerData->NumCharacterBankTabs)
+ AddDynamicUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::CharacterBankTabSettings));
+}
+
/*********************************************************/
/*** SAVE SYSTEM ***/
/*********************************************************/
@@ -20372,6 +20179,7 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
for (uint32 bagSlotFlag : m_activePlayerData->BagSlotFlags)
stmt->setUInt32(index++, bagSlotFlag);
stmt->setUInt8(index++, GetBankBagSlotCount());
+ stmt->setUInt8(index++, GetCharacterBankTabCount());
stmt->setUInt32(index++, [&]
{
BagSlotFlags inventoryFlags = BagSlotFlags::None;
@@ -20379,8 +20187,6 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
inventoryFlags |= BagSlotFlags::DisableAutoSort;
return AsUnderlyingType(inventoryFlags);
}());
- for (uint32 bankBagSlotFlag : m_activePlayerData->BankBagSlotFlags)
- stmt->setUInt32(index++, bankBagSlotFlag);
stmt->setUInt8(index++, m_activePlayerData->RestInfo[REST_TYPE_XP].StateID);
stmt->setUInt32(index++, m_playerData->PlayerFlags);
stmt->setUInt32(index++, m_playerData->PlayerFlagsEx);
@@ -20512,6 +20318,7 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
for (uint32 bagSlotFlag : m_activePlayerData->BagSlotFlags)
stmt->setUInt32(index++, bagSlotFlag);
stmt->setUInt8(index++, GetBankBagSlotCount());
+ stmt->setUInt8(index++, GetCharacterBankTabCount());
stmt->setUInt32(index++, [&]
{
BagSlotFlags inventoryFlags = BagSlotFlags::None;
@@ -20519,8 +20326,6 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
inventoryFlags |= BagSlotFlags::DisableAutoSort;
return AsUnderlyingType(inventoryFlags);
}());
- for (uint32 bankBagSlotFlag : m_activePlayerData->BankBagSlotFlags)
- stmt->setUInt32(index++, bankBagSlotFlag);
stmt->setUInt8(index++, m_activePlayerData->RestInfo[REST_TYPE_XP].StateID);
stmt->setUInt32(index++, m_playerData->PlayerFlags);
stmt->setUInt32(index++, m_playerData->PlayerFlagsEx);
@@ -20675,7 +20480,6 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
_SaveCustomizations(trans);
_SaveBGData(trans);
_SaveInventory(trans);
- _SaveVoidStorage(trans);
_SaveQuestStatus(trans);
_SaveDailyQuestStatus(trans);
_SaveWeeklyQuestStatus(trans);
@@ -20699,6 +20503,7 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
_SaveCurrency(trans);
_SaveCUFProfiles(trans);
_SavePlayerData(trans);
+ _SaveCharacterBankTabSettings(trans);
if (_garrison)
_garrison->SaveToDB(trans);
@@ -21044,42 +20849,6 @@ void Player::_SaveInventory(CharacterDatabaseTransaction trans)
m_itemUpdateQueue.clear();
}
-void Player::_SaveVoidStorage(CharacterDatabaseTransaction trans)
-{
- CharacterDatabasePreparedStatement* stmt = nullptr;
-
- for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
- {
- if (!_voidStorageItems[i]) // unused item
- {
- // DELETE FROM void_storage WHERE slot = ? AND playerGuid = ?
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT);
- stmt->setUInt8(0, i);
- stmt->setUInt64(1, GetGUID().GetCounter());
- }
- else
- {
- // REPLACE INTO character_void_storage (itemId, playerGuid, itemEntry, slot, creatorGuid, randomBonusListId, upgradeId, fixedScalingLevel, artifactKnowledgeLevel, bonusListIDs) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CHAR_VOID_STORAGE_ITEM);
- stmt->setUInt64(0, _voidStorageItems[i]->ItemId);
- stmt->setUInt64(1, GetGUID().GetCounter());
- stmt->setUInt32(2, _voidStorageItems[i]->ItemEntry);
- stmt->setUInt8(3, i);
- stmt->setUInt64(4, _voidStorageItems[i]->CreatorGuid.GetCounter());
- stmt->setUInt32(5, _voidStorageItems[i]->RandomBonusListId);
- stmt->setUInt32(6, _voidStorageItems[i]->FixedScalingLevel);
- stmt->setUInt32(7, _voidStorageItems[i]->ArtifactKnowledgeLevel);
- stmt->setUInt8(8, AsUnderlyingType(_voidStorageItems[i]->Context));
- std::ostringstream bonusListIDs;
- for (int32 bonusListID : _voidStorageItems[i]->BonusListIDs)
- bonusListIDs << bonusListID << ' ';
- stmt->setString(9, bonusListIDs.str());
- }
-
- trans->Append(stmt);
- }
-}
-
void Player::_SaveCUFProfiles(CharacterDatabaseTransaction trans)
{
CharacterDatabasePreparedStatement* stmt;
@@ -21666,6 +21435,26 @@ void Player::_SavePlayerData(CharacterDatabaseTransaction trans)
_playerDataFlagsNeedSave.clear();
}
+void Player::_SaveCharacterBankTabSettings(CharacterDatabaseTransaction trans) const
+{
+ CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_BANK_TAB_SETTINGS);
+ stmt->setUInt64(0, GetGUID().GetCounter());
+ trans->Append(stmt);
+
+ for (std::size_t i = 0; i < m_activePlayerData->CharacterBankTabSettings.size(); ++i)
+ {
+ UF::BankTabSettings const& tabSetting = m_activePlayerData->CharacterBankTabSettings[i];
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_BANK_TAB_SETTINGS);
+ stmt->setUInt64(0, GetGUID().GetCounter());
+ stmt->setUInt8(1, i);
+ stmt->setString(2, *tabSetting.Name);
+ stmt->setString(3, *tabSetting.Icon);
+ stmt->setString(4, *tabSetting.Description);
+ stmt->setInt32(5, *tabSetting.DepositFlags);
+ trans->Append(stmt);
+ }
+}
+
void Player::outDebugValues() const
{
if (!sLog->ShouldLog("entities.unit", LOG_LEVEL_DEBUG))
@@ -28387,7 +28176,13 @@ void Player::_LoadTraits(PreparedQueryResult configsResult, PreparedQueryResult
});
if (activeConfig >= 0)
- SetActiveCombatTraitConfigID(m_activePlayerData->TraitConfigs[activeConfig].ID);
+ {
+ UF::TraitConfig const& activeTraitConfig = m_activePlayerData->TraitConfigs[activeConfig];
+ SetActiveCombatTraitConfigID(activeTraitConfig.ID);
+ int32 activeSubTree = activeTraitConfig.SubTrees.FindIndexIf([](UF::TraitSubTreeCache const& subTree) { return subTree.Active != 0; });
+ if (activeSubTree >= 0)
+ SetCurrentCombatTraitConfigSubTreeID(activeTraitConfig.SubTrees[activeSubTree].TraitSubTreeID);
+ }
for (UF::TraitConfig const& traitConfig : m_activePlayerData->TraitConfigs)
{
@@ -28657,9 +28452,20 @@ void Player::ActivateTalentGroup(ChrSpecializationEntry const* spec)
&& (static_cast<TraitCombatConfigFlags>(*traitConfig.CombatConfigFlags) & TraitCombatConfigFlags::ActiveForSpec) != TraitCombatConfigFlags::None;
});
if (specTraitConfigIndex >= 0)
- SetActiveCombatTraitConfigID(m_activePlayerData->TraitConfigs[specTraitConfigIndex].ID);
+ {
+ UF::TraitConfig const& activeTraitConfig = m_activePlayerData->TraitConfigs[specTraitConfigIndex];
+ SetActiveCombatTraitConfigID(activeTraitConfig.ID);
+ int32 activeSubTree = activeTraitConfig.SubTrees.FindIndexIf([](UF::TraitSubTreeCache const& subTree) { return subTree.Active != 0; });
+ if (activeSubTree >= 0)
+ SetCurrentCombatTraitConfigSubTreeID(activeTraitConfig.SubTrees[activeSubTree].TraitSubTreeID);
+ else
+ SetCurrentCombatTraitConfigSubTreeID(0);
+ }
else
+ {
SetActiveCombatTraitConfigID(0);
+ SetCurrentCombatTraitConfigSubTreeID(0);
+ }
for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId)
{
@@ -29097,6 +28903,17 @@ void Player::ApplyTraitEntryChanges(int32 editedConfigId, WorldPackets::Traits::
}
}
+ if (applyTraits)
+ {
+ int32 activeSubTree = editedConfig.SubTrees.FindIndexIf([](UF::TraitSubTreeCache const& subTree) { return subTree.Active != 0; });
+ if (activeSubTree >= 0)
+ SetCurrentCombatTraitConfigSubTreeID(editedConfig.SubTrees[activeSubTree].TraitSubTreeID);
+ else
+ SetCurrentCombatTraitConfigSubTreeID(0);
+
+ UpdateItemSetAuras(this, false);
+ }
+
m_traitConfigStates[editedConfigId] = PLAYERSPELL_CHANGED;
}
@@ -29856,86 +29673,6 @@ bool Player::IsInWhisperWhiteList(ObjectGuid guid)
return false;
}
-uint8 Player::GetNextVoidStorageFreeSlot() const
-{
- for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
- if (!_voidStorageItems[i]) // unused item
- return i;
-
- return VOID_STORAGE_MAX_SLOT;
-}
-
-uint8 Player::GetNumOfVoidStorageFreeSlots() const
-{
- uint8 count = 0;
-
- for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
- if (!_voidStorageItems[i])
- count++;
-
- return count;
-}
-
-uint8 Player::AddVoidStorageItem(VoidStorageItem&& item)
-{
- uint8 slot = GetNextVoidStorageFreeSlot();
-
- if (slot >= VOID_STORAGE_MAX_SLOT)
- {
- GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL);
- return 255;
- }
-
- _voidStorageItems[slot] = new VoidStorageItem(std::move(item));
- return slot;
-}
-
-void Player::DeleteVoidStorageItem(uint8 slot)
-{
- if (slot >= VOID_STORAGE_MAX_SLOT)
- {
- GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INTERNAL_ERROR_1);
- return;
- }
-
- delete _voidStorageItems[slot];
- _voidStorageItems[slot] = nullptr;
-}
-
-bool Player::SwapVoidStorageItem(uint8 oldSlot, uint8 newSlot)
-{
- if (oldSlot >= VOID_STORAGE_MAX_SLOT || newSlot >= VOID_STORAGE_MAX_SLOT || oldSlot == newSlot)
- return false;
-
- std::swap(_voidStorageItems[newSlot], _voidStorageItems[oldSlot]);
- return true;
-}
-
-VoidStorageItem* Player::GetVoidStorageItem(uint8 slot) const
-{
- if (slot >= VOID_STORAGE_MAX_SLOT)
- {
- GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INTERNAL_ERROR_1);
- return nullptr;
- }
-
- return _voidStorageItems[slot];
-}
-
-VoidStorageItem* Player::GetVoidStorageItem(uint64 id, uint8& slot) const
-{
- for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i)
- {
- if (_voidStorageItems[i] && _voidStorageItems[i]->ItemId == id)
- {
- slot = i;
- return _voidStorageItems[i];
- }
- }
-
- return nullptr;
-}
-
void Player::CreateGarrison(uint32 garrSiteId)
{
std::unique_ptr<Garrison> garrison(new Garrison(this));
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 2a51422b9a7..2a28c516dc0 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -511,21 +511,24 @@ DEFINE_ENUM_FLAG(PlayerFlagsEx);
enum PlayerLocalFlags
{
- PLAYER_LOCAL_FLAG_CONTROLLING_PET = 0x00000001, // Displays "You have an active summon already" when trying to tame new pet
- PLAYER_LOCAL_FLAG_TRACK_STEALTHED = 0x00000002,
- PLAYER_LOCAL_FLAG_RELEASE_TIMER = 0x00000008, // Display time till auto release spirit
- PLAYER_LOCAL_FLAG_NO_RELEASE_WINDOW = 0x00000010, // Display no "release spirit" window at all
- PLAYER_LOCAL_FLAG_NO_PET_BAR = 0x00000020, // CGPetInfo::IsPetBarUsed
- PLAYER_LOCAL_FLAG_OVERRIDE_CAMERA_MIN_HEIGHT = 0x00000040,
- PLAYER_LOCAL_FLAG_NEWLY_BOOSTED_CHARACTER = 0x00000080,
- PLAYER_LOCAL_FLAG_USING_PARTY_GARRISON = 0x00000100,
- PLAYER_LOCAL_FLAG_CAN_USE_OBJECTS_MOUNTED = 0x00000200,
- PLAYER_LOCAL_FLAG_CAN_VISIT_PARTY_GARRISON = 0x00000400,
- PLAYER_LOCAL_FLAG_WAR_MODE = 0x00000800,
- PLAYER_LOCAL_FLAG_ACCOUNT_SECURED = 0x00001000, // Script_IsAccountSecured
- PLAYER_LOCAL_FLAG_OVERRIDE_TRANSPORT_SERVER_TIME= 0x00008000,
- PLAYER_LOCAL_FLAG_MENTOR_RESTRICTED = 0x00020000,
- PLAYER_LOCAL_FLAG_WEEKLY_REWARD_AVAILABLE = 0x00040000,
+ PLAYER_LOCAL_FLAG_CONTROLLING_PET = 0x00000001, // Displays "You have an active summon already" when trying to tame new pet
+ PLAYER_LOCAL_FLAG_TRACK_STEALTHED = 0x00000002,
+ PLAYER_LOCAL_FLAG_RELEASE_TIMER = 0x00000008, // Display time till auto release spirit
+ PLAYER_LOCAL_FLAG_NO_RELEASE_WINDOW = 0x00000010, // Display no "release spirit" window at all
+ PLAYER_LOCAL_FLAG_NO_PET_BAR = 0x00000020, // CGPetInfo::IsPetBarUsed
+ PLAYER_LOCAL_FLAG_OVERRIDE_CAMERA_MIN_HEIGHT = 0x00000040,
+ PLAYER_LOCAL_FLAG_NEWLY_BOOSTED_CHARACTER = 0x00000080,
+ PLAYER_LOCAL_FLAG_USING_PARTY_GARRISON = 0x00000100,
+ PLAYER_LOCAL_FLAG_CAN_USE_OBJECTS_MOUNTED = 0x00000200,
+ PLAYER_LOCAL_FLAG_CAN_VISIT_PARTY_GARRISON = 0x00000400,
+ PLAYER_LOCAL_FLAG_WAR_MODE = 0x00000800,
+ PLAYER_LOCAL_FLAG_ACCOUNT_SECURED = 0x00001000, // Script_IsAccountSecured
+ PLAYER_LOCAL_FLAG_OVERRIDE_TRANSPORT_SERVER_TIME = 0x00008000,
+ PLAYER_LOCAL_FLAG_MENTOR_RESTRICTED = 0x00020000,
+ PLAYER_LOCAL_FLAG_HAS_ACCOUNT_BANK_LOCK = 0x00040000,
+ PLAYER_LOCAL_FLAG_CHARACTER_BANK_DISABLED = 0x00080000,
+ PLAYER_LOCAL_FLAG_CHARACTER_BANK_CONVERSION_FAILED = 0x00100000,
+ PLAYER_LOCAL_FLAG_ACCOUNT_BANK_DISABLED = 0x00200000,
};
DEFINE_ENUM_FLAG(PlayerLocalFlags);
@@ -642,7 +645,6 @@ typedef std::unordered_map<uint32, SkillStatusData> SkillStatusMap;
class Quest;
class Spell;
-class Item;
class WorldSession;
enum PlayerSlots
@@ -650,7 +652,7 @@ enum PlayerSlots
// first slot for item stored (in any way in player m_items data)
PLAYER_SLOT_START = 0,
// last+1 slot for item stored (in any way in player m_items data)
- PLAYER_SLOT_END = 232,
+ PLAYER_SLOT_END = 105,
PLAYER_SLOTS_COUNT = (PLAYER_SLOT_END - PLAYER_SLOT_START)
};
@@ -722,61 +724,49 @@ enum InventoryPackSlots : uint8 // 28 slots
INVENTORY_SLOT_ITEM_END = 63
};
-enum BankItemSlots // 28 slots
-{
- BANK_SLOT_ITEM_START = 63,
- BANK_SLOT_ITEM_END = 91
-};
-
-enum BankBagSlots // 7 slots
+enum BankBagSlots // 6 slots
{
- BANK_SLOT_BAG_START = 91,
- BANK_SLOT_BAG_END = 98
+ BANK_SLOT_BAG_START = 63,
+ BANK_SLOT_BAG_END = 69
};
enum BuyBackSlots // 12 slots
{
// stored in m_buybackitems
- BUYBACK_SLOT_START = 98,
- BUYBACK_SLOT_END = 110
-};
-
-enum ReagentSlots // 98 slots
-{
- REAGENT_SLOT_START = 110,
- REAGENT_SLOT_END = 208,
+ BUYBACK_SLOT_START = 69,
+ BUYBACK_SLOT_END = 81
};
enum ChildEquipmentSlots
{
- CHILD_EQUIPMENT_SLOT_START = 208,
- CHILD_EQUIPMENT_SLOT_END = 211,
+ CHILD_EQUIPMENT_SLOT_START = 81,
+ CHILD_EQUIPMENT_SLOT_END = 84,
};
enum EquipableSpellSlots
{
- EQUIPABLE_SPELL_OFFENSIVE_SLOT1 = 211,
- EQUIPABLE_SPELL_OFFENSIVE_SLOT2 = 212,
- EQUIPABLE_SPELL_OFFENSIVE_SLOT3 = 213,
- EQUIPABLE_SPELL_OFFENSIVE_SLOT4 = 214,
- EQUIPABLE_SPELL_UTILITY_SLOT1 = 215,
- EQUIPABLE_SPELL_UTILITY_SLOT2 = 216,
- EQUIPABLE_SPELL_UTILITY_SLOT3 = 217,
- EQUIPABLE_SPELL_UTILITY_SLOT4 = 218,
- EQUIPABLE_SPELL_DEFENSIVE_SLOT1 = 219,
- EQUIPABLE_SPELL_DEFENSIVE_SLOT2 = 220,
- EQUIPABLE_SPELL_DEFENSIVE_SLOT3 = 221,
- EQUIPABLE_SPELL_DEFENSIVE_SLOT4 = 222,
- EQUIPABLE_SPELL_WEAPON_SLOT1 = 223,
- EQUIPABLE_SPELL_WEAPON_SLOT2 = 224,
- EQUIPABLE_SPELL_WEAPON_SLOT3 = 225,
- EQUIPABLE_SPELL_WEAPON_SLOT4 = 226,
+ EQUIPABLE_SPELL_OFFENSIVE_SLOT1 = 84,
+ EQUIPABLE_SPELL_OFFENSIVE_SLOT2 = 85,
+ EQUIPABLE_SPELL_OFFENSIVE_SLOT3 = 86,
+ EQUIPABLE_SPELL_OFFENSIVE_SLOT4 = 87,
+ EQUIPABLE_SPELL_UTILITY_SLOT1 = 88,
+ EQUIPABLE_SPELL_UTILITY_SLOT2 = 89,
+ EQUIPABLE_SPELL_UTILITY_SLOT3 = 90,
+ EQUIPABLE_SPELL_UTILITY_SLOT4 = 91,
+ EQUIPABLE_SPELL_DEFENSIVE_SLOT1 = 92,
+ EQUIPABLE_SPELL_DEFENSIVE_SLOT2 = 93,
+ EQUIPABLE_SPELL_DEFENSIVE_SLOT3 = 94,
+ EQUIPABLE_SPELL_DEFENSIVE_SLOT4 = 95,
+ EQUIPABLE_SPELL_WEAPON_SLOT1 = 96,
+ EQUIPABLE_SPELL_WEAPON_SLOT2 = 97,
+ EQUIPABLE_SPELL_WEAPON_SLOT3 = 98,
+ EQUIPABLE_SPELL_WEAPON_SLOT4 = 99,
};
enum AccountBankBagSlots
{
- ACCOUNT_BANK_SLOT_BAG_START = 227,
- ACCOUNT_BANK_SLOT_BAG_END = 232
+ ACCOUNT_BANK_SLOT_BAG_START = 100,
+ ACCOUNT_BANK_SLOT_BAG_END = 105
};
struct ItemPosCount
@@ -810,14 +800,17 @@ enum class ItemSearchCallbackResult
enum class BagSlotFlags : uint32
{
- None = 0x00,
- DisableAutoSort = 0x01,
- PriorityEquipment = 0x02,
- PriorityConsumables = 0x04,
- PriorityTradeGoods = 0x08,
- PriorityJunk = 0x10,
- PriorityQuestItems = 0x20,
- ExcludeJunkSell = 0x40,
+ None = 0x0000,
+ DisableAutoSort = 0x0001,
+ PriorityEquipment = 0x0002,
+ PriorityConsumables = 0x0004,
+ PriorityTradeGoods = 0x0008,
+ PriorityJunk = 0x0010,
+ PriorityQuestItems = 0x0020,
+ ExcludeJunkSell = 0x0040,
+ PriorityReagents = 0x0080,
+ ExpansionCurrent = 0x0100,
+ ExpansionLegacy = 0x0200,
};
DEFINE_ENUM_FLAG(BagSlotFlags);
@@ -939,7 +932,6 @@ enum PlayerLoginQueryIndex
PLAYER_LOGIN_QUERY_LOAD_INSTANCE_LOCK_TIMES,
PLAYER_LOGIN_QUERY_LOAD_SEASONAL_QUEST_STATUS,
PLAYER_LOGIN_QUERY_LOAD_MONTHLY_QUEST_STATUS,
- PLAYER_LOGIN_QUERY_LOAD_VOID_STORAGE,
PLAYER_LOGIN_QUERY_LOAD_CURRENCY,
PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES,
PLAYER_LOGIN_QUERY_LOAD_CORPSE_LOCATION,
@@ -953,6 +945,7 @@ enum PlayerLoginQueryIndex
PLAYER_LOGIN_QUERY_LOAD_TRAIT_CONFIGS,
PLAYER_LOGIN_QUERY_LOAD_DATA_ELEMENTS,
PLAYER_LOGIN_QUERY_LOAD_DATA_FLAGS,
+ PLAYER_LOGIN_QUERY_LOAD_BANK_TAB_SETTINGS,
MAX_PLAYER_LOGIN_QUERY
};
@@ -1084,29 +1077,6 @@ struct BGData
bool HasTaxiPath() const { return taxiPath[0] && taxiPath[1]; }
};
-struct VoidStorageItem
-{
- VoidStorageItem() : ItemId(0), ItemEntry(0), RandomBonusListId(0), FixedScalingLevel(0), ArtifactKnowledgeLevel(0), Context(ItemContext::NONE) { }
- VoidStorageItem(uint64 id, uint32 entry, ObjectGuid const& creator, ItemRandomBonusListId randomBonusListId,
- uint32 fixedScalingLevel, uint32 artifactKnowledgeLevel, ItemContext context, std::vector<int32> const& bonuses)
- : ItemId(id), ItemEntry(entry), CreatorGuid(creator), RandomBonusListId(randomBonusListId),
- FixedScalingLevel(fixedScalingLevel), ArtifactKnowledgeLevel(artifactKnowledgeLevel), Context(context)
- {
- BonusListIDs.insert(BonusListIDs.end(), bonuses.begin(), bonuses.end());
- }
- VoidStorageItem(VoidStorageItem&& vsi) noexcept : ItemId(vsi.ItemId), ItemEntry(vsi.ItemEntry), CreatorGuid(vsi.CreatorGuid), RandomBonusListId(vsi.RandomBonusListId),
- FixedScalingLevel(vsi.FixedScalingLevel), ArtifactKnowledgeLevel(vsi.ArtifactKnowledgeLevel), Context(vsi.Context), BonusListIDs(std::move(vsi.BonusListIDs)) { }
-
- uint64 ItemId;
- uint32 ItemEntry;
- ObjectGuid CreatorGuid;
- ItemRandomBonusListId RandomBonusListId;
- uint32 FixedScalingLevel;
- uint32 ArtifactKnowledgeLevel;
- ItemContext Context;
- std::vector<int32> BonusListIDs;
-};
-
struct ResurrectionData
{
ObjectGuid GUID;
@@ -1391,11 +1361,6 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
if (flag.HasFlag(ItemSearchLocation::Bank))
{
- for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i)
- if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- if (callback(pItem) == ItemSearchCallbackResult::Stop)
- return false;
-
for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i)
if (Bag* pBag = GetBagByPos(i))
for (uint32 j = 0; j < GetBagSize(pBag); ++j)
@@ -1412,11 +1377,6 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
if (Item* pItem = GetItemInBag(bag, j))
if (callback(pItem) == ItemSearchCallbackResult::Stop)
return false;
-
- for (uint8 i = REAGENT_SLOT_START; i < REAGENT_SLOT_END; ++i)
- if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
- if (callback(pItem) == ItemSearchCallbackResult::Stop)
- return false;
}
return true;
@@ -1450,16 +1410,37 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
static bool IsBagPos(uint16 pos);
static bool IsBankPos(uint16 pos) { return IsBankPos(pos >> 8, pos & 255); }
static bool IsBankPos(uint8 bag, uint8 slot);
- static bool IsReagentBankPos(uint16 pos) { return IsReagentBankPos(pos >> 8, pos & 255); }
- static bool IsReagentBankPos(uint8 bag, uint8 slot);
static bool IsChildEquipmentPos(uint16 pos) { return IsChildEquipmentPos(pos >> 8, pos & 255); }
static bool IsChildEquipmentPos(uint8 bag, uint8 slot);
+ static bool IsAccountBankPos(uint16 pos) { return IsBankPos(pos >> 8, pos & 255); }
+ static bool IsAccountBankPos(uint8 bag, uint8 slot);
bool IsValidPos(uint16 pos, bool explicit_pos) const { return IsValidPos(pos >> 8, pos & 255, explicit_pos); }
bool IsValidPos(uint8 bag, uint8 slot, bool explicit_pos) const;
uint8 GetInventorySlotCount() const { return m_activePlayerData->NumBackpackSlots; }
void SetInventorySlotCount(uint8 slots);
uint8 GetBankBagSlotCount() const { return m_activePlayerData->NumBankSlots; }
void SetBankBagSlotCount(uint8 count) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::NumBankSlots), count); }
+ uint8 GetCharacterBankTabCount() const { return m_activePlayerData->NumCharacterBankTabs; }
+ void SetCharacterBankTabCount(uint8 count) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::NumCharacterBankTabs), count); }
+ uint8 GetAccountBankTabCount() const { return m_activePlayerData->NumAccountBankTabs; }
+ void SetAccountBankTabCount(uint8 count) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::NumAccountBankTabs), count); }
+ void SetCharacterBankTabSettings(uint32 tabId, std::string const& name, std::string const& icon, std::string const& description, BagSlotFlags depositFlags)
+ {
+ auto setter = m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::CharacterBankTabSettings, tabId);
+ SetBankTabSettings(setter, name, icon, description, depositFlags);
+ }
+ void SetAccountBankTabSettings(uint32 tabId, std::string const& name, std::string const& icon, std::string const& description, BagSlotFlags depositFlags)
+ {
+ auto setter = m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::AccountBankTabSettings, tabId);
+ SetBankTabSettings(setter, name, icon, description, depositFlags);
+ }
+ void SetBankTabSettings(UF::MutableFieldReferenceWithChangesMask<UF::BankTabSettings, false> setter, std::string const& name, std::string const& icon, std::string const& description, BagSlotFlags depositFlags)
+ {
+ SetUpdateFieldValue(setter.ModifyValue(&UF::BankTabSettings::Name), name);
+ SetUpdateFieldValue(setter.ModifyValue(&UF::BankTabSettings::Icon), icon);
+ SetUpdateFieldValue(setter.ModifyValue(&UF::BankTabSettings::Description), description);
+ SetUpdateFieldValue(setter.ModifyValue(&UF::BankTabSettings::DepositFlags), int32(depositFlags));
+ }
bool IsBackpackAutoSortDisabled() const { return m_activePlayerData->BackpackAutoSortDisabled; }
void SetBackpackAutoSortDisabled(bool disabled) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::BackpackAutoSortDisabled), disabled); }
bool IsBackpackSellJunkDisabled() const { return m_activePlayerData->BackpackSellJunkDisabled; }
@@ -1470,10 +1451,6 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
void SetBagSlotFlag(uint32 bagIndex, EnumFlag<BagSlotFlags> flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::BagSlotFlags, bagIndex), flags.AsUnderlyingType()); }
void RemoveBagSlotFlag(uint32 bagIndex, EnumFlag<BagSlotFlags> flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::BagSlotFlags, bagIndex), flags.AsUnderlyingType()); }
void ReplaceAllBagSlotFlags(uint32 bagIndex, EnumFlag<BagSlotFlags> flags) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::BagSlotFlags, bagIndex), flags.AsUnderlyingType()); }
- EnumFlag<BagSlotFlags> GetBankBagSlotFlags(uint32 bagIndex) const { return static_cast<BagSlotFlags>(m_activePlayerData->BankBagSlotFlags[bagIndex]); }
- void SetBankBagSlotFlag(uint32 bagIndex, EnumFlag<BagSlotFlags> flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::BankBagSlotFlags, bagIndex), flags.AsUnderlyingType()); }
- void RemoveBankBagSlotFlag(uint32 bagIndex, EnumFlag<BagSlotFlags> flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::BankBagSlotFlags, bagIndex), flags.AsUnderlyingType()); }
- void ReplaceAllBankBagSlotFlags(uint32 bagIndex, EnumFlag<BagSlotFlags> flags) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::BankBagSlotFlags, bagIndex), flags.AsUnderlyingType()); }
bool HasItemCount(uint32 item, uint32 count = 1, bool inBankAlso = false) const;
bool HasItemFitToSpellRequirements(SpellInfo const* spellInfo, Item const* ignoreItem = nullptr) const;
bool CanNoReagentCast(SpellInfo const* spellInfo) const;
@@ -1998,6 +1975,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
void ApplyTraitConfig(int32 configId, bool apply);
void ApplyTraitEntry(int32 traitNodeEntryId, int32 rank, int32 grantedRanks, bool apply);
void SetActiveCombatTraitConfigID(int32 traitConfigId) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_activePlayerData).ModifyValue(&UF::ActivePlayerData::ActiveCombatTraitConfigID), traitConfigId); }
+ void SetCurrentCombatTraitConfigSubTreeID(int32 traitSubTreeId) { SetUpdateFieldValue(m_values.ModifyValue(&Player::m_playerData).ModifyValue(&UF::PlayerData::CurrentCombatTraitConfigSubTreeID), traitSubTreeId); }
void SetTraitConfigUseStarterBuild(int32 traitConfigId, bool useStarterBuild);
void SetTraitConfigUseSharedActionBars(int32 traitConfigId, bool usesSharedActionBars, bool isLastSelectedSavedConfig);
Optional<PlayerSpellTrait> GetTraitInfoForSpell(uint32 spellId) const;
@@ -2807,18 +2785,6 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
std::string GetMapAreaAndZoneString() const;
std::string GetCoordsMapAreaAndZoneString() const;
- // Void Storage
- bool IsVoidStorageUnlocked() const { return HasPlayerFlag(PLAYER_FLAGS_VOID_UNLOCKED); }
- void UnlockVoidStorage() { SetPlayerFlag(PLAYER_FLAGS_VOID_UNLOCKED); }
- void LockVoidStorage() { RemovePlayerFlag(PLAYER_FLAGS_VOID_UNLOCKED); }
- uint8 GetNextVoidStorageFreeSlot() const;
- uint8 GetNumOfVoidStorageFreeSlots() const;
- uint8 AddVoidStorageItem(VoidStorageItem&& item);
- void DeleteVoidStorageItem(uint8 slot);
- bool SwapVoidStorageItem(uint8 oldSlot, uint8 newSlot);
- VoidStorageItem* GetVoidStorageItem(uint8 slot) const;
- VoidStorageItem* GetVoidStorageItem(uint64 id, uint8& slot) const;
-
// Reagent Bank
bool IsReagentBankUnlocked() const { return HasPlayerFlagEx(PLAYER_FLAGS_EX_REAGENT_BANK_UNLOCKED); }
void UnlockReagentBank() { SetPlayerFlagEx(PLAYER_FLAGS_EX_REAGENT_BANK_UNLOCKED); }
@@ -3058,7 +3024,6 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
void _LoadInventory(PreparedQueryResult result, PreparedQueryResult artifactsResult, PreparedQueryResult azeriteResult,
PreparedQueryResult azeriteItemMilestonePowersResult, PreparedQueryResult azeriteItemUnlockedEssencesResult,
PreparedQueryResult azeriteEmpoweredItemResult, uint32 timeDiff);
- void _LoadVoidStorage(PreparedQueryResult result);
void _LoadMail(PreparedQueryResult mailsResult, PreparedQueryResult mailItemsResult, PreparedQueryResult artifactResult, PreparedQueryResult azeriteItemResult,
PreparedQueryResult azeriteItemMilestonePowersResult, PreparedQueryResult azeriteItemUnlockedEssencesResult, PreparedQueryResult azeriteEmpoweredItemResult);
static Item* _LoadMailedItem(ObjectGuid const& playerGuid, Player* player, uint64 mailId, Mail* mail, Field* fields, ItemAdditionalLoadInfo* addionalData);
@@ -3090,6 +3055,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
void _LoadCurrency(PreparedQueryResult result);
void _LoadCUFProfiles(PreparedQueryResult result);
void _LoadPlayerData(PreparedQueryResult elementsResult, PreparedQueryResult flagsResult);
+ void _LoadCharacterBankTabSettings(PreparedQueryResult result);
/*********************************************************/
/*** SAVE SYSTEM ***/
@@ -3099,7 +3065,6 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
void _SaveActions(CharacterDatabaseTransaction trans);
void _SaveAuras(CharacterDatabaseTransaction trans);
void _SaveInventory(CharacterDatabaseTransaction trans);
- void _SaveVoidStorage(CharacterDatabaseTransaction trans);
void _SaveMail(CharacterDatabaseTransaction trans);
void _SaveQuestStatus(CharacterDatabaseTransaction trans);
void _SaveDailyQuestStatus(CharacterDatabaseTransaction trans);
@@ -3119,6 +3084,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
void _SaveCurrency(CharacterDatabaseTransaction trans);
void _SaveCUFProfiles(CharacterDatabaseTransaction trans);
void _SavePlayerData(CharacterDatabaseTransaction trans);
+ void _SaveCharacterBankTabSettings(CharacterDatabaseTransaction trans) const;
/*********************************************************/
/*** ENVIRONMENTAL SYSTEM ***/
@@ -3151,8 +3117,6 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
PlayerCurrenciesMap _currencyStorage;
- VoidStorageItem* _voidStorageItems[VOID_STORAGE_MAX_SLOT];
-
std::vector<Item*> m_itemUpdateQueue;
bool m_itemUpdateQueueBlocked;
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index f6917ee88f7..ab91bf1f62b 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1433,6 +1433,12 @@ class TC_GAME_API Unit : public WorldObject
void SetChannelObject(uint32 slot, ObjectGuid guid);
void RemoveChannelObject(ObjectGuid guid);
void ClearChannelObjects();
+ void SetChannelSpellData(uint32 startTimeMs, uint32 durationMs)
+ {
+ auto channelData = m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::ChannelData);
+ SetUpdateFieldValue(channelData.ModifyValue(&UF::UnitChannel::StartTimeMs), startTimeMs);
+ SetUpdateFieldValue(channelData.ModifyValue(&UF::UnitChannel::Duration), durationMs);
+ }
int8 GetSpellEmpowerStage() const { return m_unitData->SpellEmpowerStage; }
void SetSpellEmpowerStage(int8 stage) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::SpellEmpowerStage), stage); }