mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-21 09:44:45 +01:00
Core/AreaTriggers: Update areatrigger scalecurve handling with latest research
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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 AreaTriggerScaleInfo
|
||||
struct AreaTriggerScaleCurvePointsTemplate
|
||||
{
|
||||
AreaTriggerScaleInfo();
|
||||
AreaTriggerScaleCurvePointsTemplate();
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 StartTimeOffset;
|
||||
float Points[4];
|
||||
struct
|
||||
{
|
||||
uint32 NoData : 1;
|
||||
uint32 InterpolationMode : 3;
|
||||
uint32 FirstPointOffset : 23;
|
||||
uint32 PointCount : 5;
|
||||
} CurveParameters;
|
||||
uint32 OverrideActive;
|
||||
} Structured;
|
||||
CurveInterpolationMode Mode;
|
||||
std::array<DBCPosition2D, 2> Points;
|
||||
};
|
||||
|
||||
uint32 Raw[MAX_AREATRIGGER_SCALE];
|
||||
} Data;
|
||||
struct AreaTriggerScaleCurveTemplate
|
||||
{
|
||||
AreaTriggerScaleCurveTemplate();
|
||||
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user