diff options
author | Shauren <shauren.trinity@gmail.com> | 2023-07-17 19:52:25 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2023-07-17 19:52:25 +0200 |
commit | 361fe56bc87456b63e685a53ffc63ca1694d336a (patch) | |
tree | b2717e328ea9c291b6112232910913a634d1a4b6 | |
parent | 38440996ee117ee8d8786755dd3a620b2ca3ed7d (diff) |
Core/AreaTriggers: Update areatrigger scalecurve handling with latest research
-rw-r--r-- | src/server/game/DataStores/DB2Stores.cpp | 122 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Stores.h | 2 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCEnums.h | 11 | ||||
-rw-r--r-- | src/server/game/Entities/AreaTrigger/AreaTrigger.cpp | 100 | ||||
-rw-r--r-- | src/server/game/Entities/AreaTrigger/AreaTrigger.h | 3 | ||||
-rw-r--r-- | src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.cpp | 22 | ||||
-rw-r--r-- | src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h | 43 |
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; |