aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2023-07-17 19:52:25 +0200
committerShauren <shauren.trinity@gmail.com>2023-07-17 19:52:25 +0200
commit361fe56bc87456b63e685a53ffc63ca1694d336a (patch)
treeb2717e328ea9c291b6112232910913a634d1a4b6 /src
parent38440996ee117ee8d8786755dd3a620b2ca3ed7d (diff)
Core/AreaTriggers: Update areatrigger scalecurve handling with latest research
Diffstat (limited to 'src')
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp122
-rw-r--r--src/server/game/DataStores/DB2Stores.h2
-rw-r--r--src/server/game/DataStores/DBCEnums.h11
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.cpp100
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.h3
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.cpp22
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h43
7 files changed, 185 insertions, 118 deletions
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index f864655f588..5f48fc65b4d 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -386,7 +386,7 @@ typedef std::unordered_map<uint32, std::vector<ArtifactPowerEntry const*>> Artif
typedef std::unordered_map<uint32, std::vector<uint32>> ArtifactPowerLinksContainer;
typedef std::unordered_map<std::pair<uint32, uint8>, ArtifactPowerRankEntry const*> ArtifactPowerRanksContainer;
typedef ChrSpecializationEntry const* ChrSpecializationByIndexContainer[MAX_CLASSES + 1][MAX_SPECIALIZATIONS];
-typedef std::unordered_map<uint32 /*curveID*/, std::vector<CurvePointEntry const*>> CurvePointsContainer;
+typedef std::unordered_map<uint32 /*curveID*/, std::vector<DBCPosition2D>> CurvePointsContainer;
typedef std::map<std::tuple<uint32, uint8, uint8, uint8>, EmotesTextSoundEntry const*> EmotesTextSoundContainer;
typedef std::unordered_map<uint32, std::vector<uint32>> FactionTeamContainer;
typedef std::unordered_map<uint32, HeirloomEntry const*> HeirloomItemsContainer;
@@ -1205,12 +1205,20 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
for (CurrencyContainerEntry const* currencyContainer : sCurrencyContainerStore)
_currencyContainers.emplace(currencyContainer->CurrencyTypesID, currencyContainer);
- for (CurvePointEntry const* curvePoint : sCurvePointStore)
- if (sCurveStore.LookupEntry(curvePoint->CurveID))
- _curvePoints[curvePoint->CurveID].push_back(curvePoint);
+ {
+ std::unordered_map<uint32 /*curveID*/, std::vector<CurvePointEntry const*>> unsortedPoints;
+ for (CurvePointEntry const* curvePoint : sCurvePointStore)
+ if (sCurveStore.LookupEntry(curvePoint->CurveID))
+ unsortedPoints[curvePoint->CurveID].push_back(curvePoint);
- for (auto itr = _curvePoints.begin(); itr != _curvePoints.end(); ++itr)
- std::sort(itr->second.begin(), itr->second.end(), [](CurvePointEntry const* point1, CurvePointEntry const* point2) { return point1->OrderIndex < point2->OrderIndex; });
+ for (auto& [curveId, curvePoints] : unsortedPoints)
+ {
+ std::sort(curvePoints.begin(), curvePoints.end(), [](CurvePointEntry const* point1, CurvePointEntry const* point2) { return point1->OrderIndex < point2->OrderIndex; });
+ std::vector<DBCPosition2D>& points = _curvePoints[curveId];
+ points.resize(curvePoints.size());
+ std::transform(curvePoints.begin(), curvePoints.end(), points.begin(), [](CurvePointEntry const* point) { return point->Pos; });
+ }
+ }
for (EmotesTextSoundEntry const* emoteTextSound : sEmotesTextSoundStore)
_emoteTextSounds[EmotesTextSoundContainer::key_type(emoteTextSound->EmotesTextID, emoteTextSound->RaceID, emoteTextSound->SexID, emoteTextSound->ClassID)] = emoteTextSound;
@@ -2126,24 +2134,13 @@ CurrencyContainerEntry const* DB2Manager::GetCurrencyContainerForCurrencyQuantit
std::pair<float, float> DB2Manager::GetCurveXAxisRange(uint32 curveId) const
{
- if (std::vector<CurvePointEntry const*> const* points = Trinity::Containers::MapGetValuePtr(_curvePoints, curveId))
- return { points->front()->Pos.X, points->back()->Pos.X };
+ if (std::vector<DBCPosition2D> const* points = Trinity::Containers::MapGetValuePtr(_curvePoints, curveId))
+ return { points->front().X, points->back().X };
return { 0.0f, 0.0f };
}
-enum class CurveInterpolationMode : uint8
-{
- Linear = 0,
- Cosine = 1,
- CatmullRom = 2,
- Bezier3 = 3,
- Bezier4 = 4,
- Bezier = 5,
- Constant = 6,
-};
-
-static CurveInterpolationMode DetermineCurveType(CurveEntry const* curve, std::vector<CurvePointEntry const*> const& points)
+static CurveInterpolationMode DetermineCurveType(CurveEntry const* curve, std::vector<DBCPosition2D> const& points)
{
switch (curve->Type)
{
@@ -2182,91 +2179,96 @@ float DB2Manager::GetCurveValueAt(uint32 curveId, float x) const
return 0.0f;
CurveEntry const* curve = sCurveStore.AssertEntry(curveId);
- std::vector<CurvePointEntry const*> const& points = itr->second;
+ std::vector<DBCPosition2D> const& points = itr->second;
if (points.empty())
return 0.0f;
- switch (DetermineCurveType(curve, points))
+ return GetCurveValueAt(DetermineCurveType(curve, points), points, x);
+}
+
+float DB2Manager::GetCurveValueAt(CurveInterpolationMode mode, std::span<DBCPosition2D const> points, float x) const
+{
+ switch (mode)
{
case CurveInterpolationMode::Linear:
{
std::size_t pointIndex = 0;
- while (pointIndex < points.size() && points[pointIndex]->Pos.X <= x)
+ while (pointIndex < points.size() && points[pointIndex].X <= x)
++pointIndex;
if (!pointIndex)
- return points[0]->Pos.Y;
+ return points[0].Y;
if (pointIndex >= points.size())
- return points.back()->Pos.Y;
- float xDiff = points[pointIndex]->Pos.X - points[pointIndex - 1]->Pos.X;
+ return points.back().Y;
+ float xDiff = points[pointIndex].X - points[pointIndex - 1].X;
if (xDiff == 0.0)
- return points[pointIndex]->Pos.Y;
- return (((x - points[pointIndex - 1]->Pos.X) / xDiff) * (points[pointIndex]->Pos.Y - points[pointIndex - 1]->Pos.Y)) + points[pointIndex - 1]->Pos.Y;
+ return points[pointIndex].Y;
+ return (((x - points[pointIndex - 1].X) / xDiff) * (points[pointIndex].Y - points[pointIndex - 1].Y)) + points[pointIndex - 1].Y;
}
case CurveInterpolationMode::Cosine:
{
std::size_t pointIndex = 0;
- while (pointIndex < points.size() && points[pointIndex]->Pos.X <= x)
+ while (pointIndex < points.size() && points[pointIndex].X <= x)
++pointIndex;
if (!pointIndex)
- return points[0]->Pos.Y;
+ return points[0].Y;
if (pointIndex >= points.size())
- return points.back()->Pos.Y;
- float xDiff = points[pointIndex]->Pos.X - points[pointIndex - 1]->Pos.X;
+ return points.back().Y;
+ float xDiff = points[pointIndex].X - points[pointIndex - 1].X;
if (xDiff == 0.0)
- return points[pointIndex]->Pos.Y;
- return ((points[pointIndex]->Pos.Y - points[pointIndex - 1]->Pos.Y) * (1.0f - std::cos((x - points[pointIndex - 1]->Pos.X) / xDiff * float(M_PI))) * 0.5f) + points[pointIndex - 1]->Pos.Y;
+ return points[pointIndex].Y;
+ return ((points[pointIndex].Y - points[pointIndex - 1].Y) * (1.0f - std::cos((x - points[pointIndex - 1].X) / xDiff * float(M_PI))) * 0.5f) + points[pointIndex - 1].Y;
}
case CurveInterpolationMode::CatmullRom:
{
std::size_t pointIndex = 1;
- while (pointIndex < points.size() && points[pointIndex]->Pos.X <= x)
+ while (pointIndex < points.size() && points[pointIndex].X <= x)
++pointIndex;
if (pointIndex == 1)
- return points[1]->Pos.Y;
+ return points[1].Y;
if (pointIndex >= points.size() - 1)
- return points[points.size() - 2]->Pos.Y;
- float xDiff = points[pointIndex]->Pos.X - points[pointIndex - 1]->Pos.X;
+ return points[points.size() - 2].Y;
+ float xDiff = points[pointIndex].X - points[pointIndex - 1].X;
if (xDiff == 0.0)
- return points[pointIndex]->Pos.Y;
+ return points[pointIndex].Y;
- float mu = (x - points[pointIndex - 1]->Pos.X) / xDiff;
- float a0 = -0.5f * points[pointIndex - 2]->Pos.Y + 1.5f * points[pointIndex - 1]->Pos.Y - 1.5f * points[pointIndex]->Pos.Y + 0.5f * points[pointIndex + 1]->Pos.Y;
- float a1 = points[pointIndex - 2]->Pos.Y - 2.5f * points[pointIndex - 1]->Pos.Y + 2.0f * points[pointIndex]->Pos.Y - 0.5f * points[pointIndex + 1]->Pos.Y;
- float a2 = -0.5f * points[pointIndex - 2]->Pos.Y + 0.5f * points[pointIndex]->Pos.Y;
- float a3 = points[pointIndex - 1]->Pos.Y;
+ float mu = (x - points[pointIndex - 1].X) / xDiff;
+ float a0 = -0.5f * points[pointIndex - 2].Y + 1.5f * points[pointIndex - 1].Y - 1.5f * points[pointIndex].Y + 0.5f * points[pointIndex + 1].Y;
+ float a1 = points[pointIndex - 2].Y - 2.5f * points[pointIndex - 1].Y + 2.0f * points[pointIndex].Y - 0.5f * points[pointIndex + 1].Y;
+ float a2 = -0.5f * points[pointIndex - 2].Y + 0.5f * points[pointIndex].Y;
+ float a3 = points[pointIndex - 1].Y;
return a0 * mu * mu * mu + a1 * mu * mu + a2 * mu + a3;
}
case CurveInterpolationMode::Bezier3:
{
- float xDiff = points[2]->Pos.X - points[0]->Pos.X;
+ float xDiff = points[2].X - points[0].X;
if (xDiff == 0.0)
- return points[1]->Pos.Y;
- float mu = (x - points[0]->Pos.X) / xDiff;
- return ((1.0f - mu) * (1.0f - mu) * points[0]->Pos.Y) + (1.0f - mu) * 2.0f * mu * points[1]->Pos.Y + mu * mu * points[2]->Pos.Y;
+ return points[1].Y;
+ float mu = (x - points[0].X) / xDiff;
+ return ((1.0f - mu) * (1.0f - mu) * points[0].Y) + (1.0f - mu) * 2.0f * mu * points[1].Y + mu * mu * points[2].Y;
}
case CurveInterpolationMode::Bezier4:
{
- float xDiff = points[3]->Pos.X - points[0]->Pos.X;
+ float xDiff = points[3].X - points[0].X;
if (xDiff == 0.0)
- return points[1]->Pos.Y;
- float mu = (x - points[0]->Pos.X) / xDiff;
- return (1.0f - mu) * (1.0f - mu) * (1.0f - mu) * points[0]->Pos.Y
- + 3.0f * mu * (1.0f - mu) * (1.0f - mu) * points[1]->Pos.Y
- + 3.0f * mu * mu * (1.0f - mu) * points[2]->Pos.Y
- + mu * mu * mu * points[3]->Pos.Y;
+ return points[1].Y;
+ float mu = (x - points[0].X) / xDiff;
+ return (1.0f - mu) * (1.0f - mu) * (1.0f - mu) * points[0].Y
+ + 3.0f * mu * (1.0f - mu) * (1.0f - mu) * points[1].Y
+ + 3.0f * mu * mu * (1.0f - mu) * points[2].Y
+ + mu * mu * mu * points[3].Y;
}
case CurveInterpolationMode::Bezier:
{
- float xDiff = points.back()->Pos.X - points[0]->Pos.X;
+ float xDiff = points.back().X - points[0].X;
if (xDiff == 0.0f)
- return points.back()->Pos.Y;
+ return points.back().Y;
std::vector<float> tmp(points.size());
for (std::size_t i = 0; i < points.size(); ++i)
- tmp[i] = points[i]->Pos.Y;
+ tmp[i] = points[i].Y;
- float mu = (x - points[0]->Pos.X) / xDiff;
+ float mu = (x - points[0].X) / xDiff;
int32 i = int32(points.size()) - 1;
while (i > 0)
{
@@ -2280,7 +2282,7 @@ float DB2Manager::GetCurveValueAt(uint32 curveId, float x) const
return tmp[0];
}
case CurveInterpolationMode::Constant:
- return points[0]->Pos.Y;
+ return points[0].Y;
default:
break;
}
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index f4c5a30bbdf..973ecd2ce54 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -25,6 +25,7 @@
#include "advstd.h"
#include <map>
#include <set>
+#include <span>
#include <vector>
// temporary hack until includes are sorted out (don't want to pull in Windows.h)
@@ -439,6 +440,7 @@ public:
CurrencyContainerEntry const* GetCurrencyContainerForCurrencyQuantity(uint32 currencyId, int32 quantity) const;
std::pair<float, float> GetCurveXAxisRange(uint32 curveId) const;
float GetCurveValueAt(uint32 curveId, float x) const;
+ float GetCurveValueAt(CurveInterpolationMode mode, std::span<DBCPosition2D const> points, float x) const;
EmotesTextSoundEntry const* GetTextSoundEmoteFor(uint32 emote, uint8 race, uint8 gender, uint8 class_) const;
float EvaluateExpectedStat(ExpectedStatType stat, uint32 level, int32 expansion, uint32 contentTuningId, Classes unitClass, int32 mythicPlusMilestoneSeason) const;
std::vector<uint32> const* GetFactionTeamList(uint32 faction) const;
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index df040e5efe2..730f6635ce3 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -750,6 +750,17 @@ enum Curves
CURVE_ID_AZERITE_EMPOWERED_ITEM_RESPEC_COST = 6785
};
+enum class CurveInterpolationMode : uint8
+{
+ Linear = 0,
+ Cosine = 1,
+ CatmullRom = 2,
+ Bezier3 = 3,
+ Bezier4 = 4,
+ Bezier = 5,
+ Constant = 6,
+};
+
enum Difficulty : uint8
{
DIFFICULTY_NONE = 0,
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
index a6fed3e9ab6..80a31903120 100644
--- a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
+++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
@@ -39,6 +39,7 @@
#include "Transport.h"
#include "Unit.h"
#include "UpdateData.h"
+#include <bit>
AreaTrigger::AreaTrigger() : WorldObject(false), MapObject(), _spawnId(0), _aurEff(nullptr), _maxSearchRadius(0.0f),
_duration(0), _totalDuration(0), _timeSinceCreated(0), _previousCheckOrientation(std::numeric_limits<float>::infinity()),
@@ -139,22 +140,7 @@ bool AreaTrigger::Create(uint32 areaTriggerCreatePropertiesId, Unit* caster, Uni
SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::BoundsRadius2D), GetMaxSearchRadius());
SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::DecalPropertiesID), GetCreateProperties()->DecalPropertiesId);
- if (GetCreateProperties()->ExtraScale.Data.Structured.StartTimeOffset)
- SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ExtraScaleCurve).ModifyValue(&UF::ScaleCurve::StartTimeOffset), GetCreateProperties()->ExtraScale.Data.Structured.StartTimeOffset);
- if (GetCreateProperties()->ExtraScale.Data.Structured.Points[0] || GetCreateProperties()->ExtraScale.Data.Structured.Points[1])
- {
- Position point(GetCreateProperties()->ExtraScale.Data.Structured.Points[0], GetCreateProperties()->ExtraScale.Data.Structured.Points[1]);
- SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ExtraScaleCurve).ModifyValue(&UF::ScaleCurve::Points, 0), point);
- }
- if (GetCreateProperties()->ExtraScale.Data.Structured.Points[2] || GetCreateProperties()->ExtraScale.Data.Structured.Points[3])
- {
- Position point(GetCreateProperties()->ExtraScale.Data.Structured.Points[2], GetCreateProperties()->ExtraScale.Data.Structured.Points[3]);
- SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ExtraScaleCurve).ModifyValue(&UF::ScaleCurve::Points, 1), point);
- }
- if (GetCreateProperties()->ExtraScale.Data.Raw[5])
- SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ExtraScaleCurve).ModifyValue(&UF::ScaleCurve::ParameterCurve), GetCreateProperties()->ExtraScale.Data.Raw[5]);
- if (GetCreateProperties()->ExtraScale.Data.Structured.OverrideActive)
- SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ExtraScaleCurve).ModifyValue(&UF::ScaleCurve::OverrideActive), GetCreateProperties()->ExtraScale.Data.Structured.OverrideActive);
+ SetScaleCurve(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ExtraScaleCurve), GetCreateProperties()->ExtraScale);
SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::VisualAnim).ModifyValue(&UF::VisualAnim::AnimationDataID), GetCreateProperties()->AnimId);
SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::VisualAnim).ModifyValue(&UF::VisualAnim::AnimKitID), GetCreateProperties()->AnimKitId);
@@ -372,6 +358,88 @@ float AreaTrigger::GetProgress() const
return GetTimeSinceCreated() < GetTimeToTargetScale() ? float(GetTimeSinceCreated()) / float(GetTimeToTargetScale()) : 1.0f;
}
+float AreaTrigger::GetScaleCurveValue(UF::ScaleCurve const& scaleCurve, float x) const
+{
+ ASSERT(*scaleCurve.OverrideActive, "ScaleCurve must be active to evaluate it");
+
+ // unpack ParameterCurve
+ if (*scaleCurve.ParameterCurve & 1)
+ return std::bit_cast<float>(*scaleCurve.ParameterCurve & ~1);
+
+ std::array<DBCPosition2D, 2> points;
+ for (std::size_t i = 0; i < scaleCurve.Points.size(); ++i)
+ points[i] = { .X = scaleCurve.Points[i].Pos.GetPositionX(), .Y = scaleCurve.Points[i].Pos.GetPositionY() };
+
+ CurveInterpolationMode mode = CurveInterpolationMode(*scaleCurve.ParameterCurve >> 1 & 0x7);
+ std::size_t pointCount = *scaleCurve.ParameterCurve >> 24 & 0xFF;
+
+ return sDB2Manager.GetCurveValueAt(mode, std::span(points.begin(), pointCount), x);
+}
+
+void AreaTrigger::SetScaleCurve(UF::MutableFieldReference<UF::ScaleCurve, false>&& scaleCurveMutator, Optional<AreaTriggerScaleCurveTemplate> const& curve)
+{
+ if (!curve)
+ {
+ SetUpdateFieldValue(scaleCurveMutator.ModifyValue(&UF::ScaleCurve::OverrideActive), false);
+ return;
+ }
+
+ SetUpdateFieldValue(scaleCurveMutator.ModifyValue(&UF::ScaleCurve::OverrideActive), true);
+ SetUpdateFieldValue(scaleCurveMutator.ModifyValue(&UF::ScaleCurve::StartTimeOffset), curve->StartTimeOffset);
+
+ Position point;
+ // ParameterCurve packing information
+ // (not_using_points & 1) | ((interpolation_mode & 0x7) << 1) | ((first_point_offset & 0xFFFFF) << 4) | ((point_count & 0xFF) << 24)
+ // if not_using_points is set then the entire field is simply read as a float (ignoring that lowest bit)
+
+ if (float const* simpleFloat = std::get_if<float>(&curve->Curve))
+ {
+ uint32 packedCurve = std::bit_cast<uint32>(*simpleFloat);
+ packedCurve |= 1;
+
+ SetUpdateFieldValue(scaleCurveMutator.ModifyValue(&UF::ScaleCurve::ParameterCurve), packedCurve);
+
+ // clear points
+ for (std::size_t i = 0; i < UF::size<decltype(UF::ScaleCurve::Points)>(); ++i)
+ SetUpdateFieldValue(scaleCurveMutator.ModifyValue(&UF::ScaleCurve::Points, i), point);
+ }
+ else if (AreaTriggerScaleCurvePointsTemplate const* curvePoints = std::get_if<AreaTriggerScaleCurvePointsTemplate>(&curve->Curve))
+ {
+ CurveInterpolationMode mode = curvePoints->Mode;
+ if (curvePoints->Points[1].X < curvePoints->Points[0].X)
+ mode = CurveInterpolationMode::Constant;
+
+ switch (mode)
+ {
+ case CurveInterpolationMode::CatmullRom:
+ // catmullrom requires at least 4 points, impossible here
+ mode = CurveInterpolationMode::Cosine;
+ break;
+ case CurveInterpolationMode::Bezier3:
+ case CurveInterpolationMode::Bezier4:
+ case CurveInterpolationMode::Bezier:
+ // bezier requires more than 2 points, impossible here
+ mode = CurveInterpolationMode::Linear;
+ break;
+ default:
+ break;
+ }
+
+ uint32 pointCount = 2;
+ if (mode == CurveInterpolationMode::Constant)
+ pointCount = 1;
+
+ uint32 packedCurve = (uint32(mode) << 1) | (pointCount << 24);
+ SetUpdateFieldValue(scaleCurveMutator.ModifyValue(&UF::ScaleCurve::ParameterCurve), packedCurve);
+
+ for (std::size_t i = 0; i < curvePoints->Points.size(); ++i)
+ {
+ point.Relocate(curvePoints->Points[i].X, curvePoints->Points[i].Y);
+ SetUpdateFieldValue(scaleCurveMutator.ModifyValue(&UF::ScaleCurve::Points, i), point);
+ }
+ }
+}
+
void AreaTrigger::UpdateTargetList()
{
std::vector<Unit*> targetList;
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.h b/src/server/game/Entities/AreaTrigger/AreaTrigger.h
index a461a11a173..ccb83e22c4f 100644
--- a/src/server/game/Entities/AreaTrigger/AreaTrigger.h
+++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.h
@@ -134,6 +134,9 @@ class TC_GAME_API AreaTrigger : public WorldObject, public GridObject<AreaTrigge
void _UpdateDuration(int32 newDuration);
float GetProgress() const;
+ float GetScaleCurveValue(UF::ScaleCurve const& scaleCurve, float x) const;
+ void SetScaleCurve(UF::MutableFieldReference<UF::ScaleCurve, false>&& scaleCurveMutator, Optional<AreaTriggerScaleCurveTemplate> const& curve);
+
void UpdateTargetList();
void SearchUnits(std::vector<Unit*>& targetList, float radius, bool check3D);
void SearchUnitInSphere(std::vector<Unit*>& targetList);
diff --git a/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.cpp b/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.cpp
index 52bd9704259..c1917919be8 100644
--- a/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.cpp
+++ b/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.cpp
@@ -21,9 +21,12 @@
#include <cstring>
#include <cmath>
-AreaTriggerScaleInfo::AreaTriggerScaleInfo()
+AreaTriggerScaleCurvePointsTemplate::AreaTriggerScaleCurvePointsTemplate() : Mode(CurveInterpolationMode::Linear), Points()
+{
+}
+
+AreaTriggerScaleCurveTemplate::AreaTriggerScaleCurveTemplate() : StartTimeOffset(0), Curve(1.0f)
{
- memset(Data.Raw, 0, sizeof(Data.Raw));
}
AreaTriggerShapeInfo::AreaTriggerShapeInfo()
@@ -59,9 +62,7 @@ AreaTriggerTemplate::AreaTriggerTemplate()
Flags = 0;
}
-AreaTriggerTemplate::~AreaTriggerTemplate()
-{
-}
+AreaTriggerTemplate::~AreaTriggerTemplate() = default;
AreaTriggerCreateProperties::AreaTriggerCreateProperties()
{
@@ -80,21 +81,14 @@ AreaTriggerCreateProperties::AreaTriggerCreateProperties()
TimeToTarget = 0;
TimeToTargetScale = 0;
- // legacy code from before it was known what each curve field does
- // wtf? thats not how you pack curve data
- float tmp = 1.0000001f;
- memcpy(&ExtraScale.Data.Raw[5], &tmp, sizeof(tmp));
- // also OverrideActive does nothing on ExtraScale
- ExtraScale.Data.Structured.OverrideActive = 1;
+ ExtraScale.emplace();
Template = nullptr;
ScriptId = 0;
}
-AreaTriggerCreateProperties::~AreaTriggerCreateProperties()
-{
-}
+AreaTriggerCreateProperties::~AreaTriggerCreateProperties() = default;
bool AreaTriggerCreateProperties::HasSplines() const
{
diff --git a/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h b/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h
index 5ae1f7fba25..8485944a4fa 100644
--- a/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h
+++ b/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h
@@ -22,6 +22,7 @@
#include "ObjectGuid.h"
#include "Optional.h"
#include "SpawnData.h"
+#include <variant>
#include <vector>
#define MAX_AREATRIGGER_ENTITY_DATA 8
@@ -87,34 +88,20 @@ struct AreaTriggerAction
AreaTriggerActionUserTypes TargetType;
};
-// Scale array definition
-// 0 - time offset from creation for starting of scaling
-// 1+2,3+4 are values for curve points Vector2[2]
-// 5 is packed curve information (has_no_data & 1) | ((interpolation_mode & 0x7) << 1) | ((first_point_offset & 0x7FFFFF) << 4) | ((point_count & 0x1F) << 27)
-// 6 bool is_override, only valid for AREATRIGGER_OVERRIDE_SCALE_CURVE, if true then use data from AREATRIGGER_OVERRIDE_SCALE_CURVE instead of ScaleCurveId from CreateObject
+struct AreaTriggerScaleCurvePointsTemplate
+{
+ AreaTriggerScaleCurvePointsTemplate();
+
+ CurveInterpolationMode Mode;
+ std::array<DBCPosition2D, 2> Points;
+};
-struct AreaTriggerScaleInfo
+struct AreaTriggerScaleCurveTemplate
{
- AreaTriggerScaleInfo();
+ AreaTriggerScaleCurveTemplate();
- union
- {
- struct
- {
- uint32 StartTimeOffset;
- float Points[4];
- struct
- {
- uint32 NoData : 1;
- uint32 InterpolationMode : 3;
- uint32 FirstPointOffset : 23;
- uint32 PointCount : 5;
- } CurveParameters;
- uint32 OverrideActive;
- } Structured;
-
- uint32 Raw[MAX_AREATRIGGER_SCALE];
- } Data;
+ uint32 StartTimeOffset;
+ std::variant<float, AreaTriggerScaleCurvePointsTemplate> Curve;
};
struct AreaTriggerShapeInfo
@@ -213,7 +200,7 @@ public:
AreaTriggerTemplate();
~AreaTriggerTemplate();
- bool HasFlag(uint32 flag) const { return (Flags & flag) != 0; }
+ bool HasFlag(AreaTriggerFlags flag) const { return (Flags & flag) != 0; }
AreaTriggerId Id;
uint32 Flags;
@@ -245,8 +232,8 @@ public:
uint32 TimeToTarget;
uint32 TimeToTargetScale;
- AreaTriggerScaleInfo OverrideScale;
- AreaTriggerScaleInfo ExtraScale;
+ Optional<AreaTriggerScaleCurveTemplate> OverrideScale;
+ Optional<AreaTriggerScaleCurveTemplate> ExtraScale;
AreaTriggerShapeInfo Shape;
std::vector<TaggedPosition<Position::XY>> PolygonVertices;