Core/Spells: Refactor CastSpellExtraArgs

* Allow C++20 designated initializers
* Allow precise float values for SPELLVALUE_RADIUS_MOD, SPELLVALUE_CRIT_CHANCE and SPELLVALUE_DURATION_PCT
This commit is contained in:
Shauren
2024-09-12 21:57:16 +02:00
parent d3b05c591c
commit 975e7cc072
9 changed files with 92 additions and 61 deletions

View File

@@ -2949,8 +2949,13 @@ SpellCastResult WorldObject::CastSpell(CastSpellTargetArg const& targets, uint32
}
Spell* spell = new Spell(this, info, args.TriggerFlags, args.OriginalCaster, args.OriginalCastId);
for (auto const& pair : args.SpellValueOverrides)
spell->SetSpellValue(pair.first, pair.second);
for (auto const& [Type, Value] : args.SpellValueOverrides)
{
if (Type < SPELLVALUE_INT_END)
spell->SetSpellValue(SpellValueMod(Type), Value.I);
else
spell->SetSpellValue(SpellValueModFloat(Type), Value.F);
}
spell->m_CastItem = args.CastItem;
if (args.OriginalCastItemLevel)

View File

@@ -8793,21 +8793,12 @@ void Spell::SetSpellValue(SpellValueMod mod, int32 value)
switch (mod)
{
case SPELLVALUE_RADIUS_MOD:
m_spellValue->RadiusMod = (float)value / 10000;
break;
case SPELLVALUE_MAX_TARGETS:
m_spellValue->MaxAffectedTargets = (uint32)value;
break;
case SPELLVALUE_AURA_STACK:
m_spellValue->AuraStackAmount = uint8(value);
break;
case SPELLVALUE_CRIT_CHANCE:
m_spellValue->CriticalChance = value / 100.0f; // @todo ugly /100 remove when basepoints are double
break;
case SPELLVALUE_DURATION_PCT:
m_spellValue->DurationMul = float(value) / 100.0f;
break;
case SPELLVALUE_DURATION:
m_spellValue->Duration = value;
break;
@@ -8822,6 +8813,24 @@ void Spell::SetSpellValue(SpellValueMod mod, int32 value)
}
}
void Spell::SetSpellValue(SpellValueModFloat mod, float value)
{
switch (mod)
{
case SPELLVALUE_RADIUS_MOD:
m_spellValue->RadiusMod = value;
break;
case SPELLVALUE_CRIT_CHANCE:
m_spellValue->CriticalChance = value;
break;
case SPELLVALUE_DURATION_PCT:
m_spellValue->DurationMul = value / 100.0f;
break;
default:
break;
}
}
void Spell::PrepareTargetProcessing()
{
}
@@ -9662,8 +9671,10 @@ CastSpellExtraArgs& CastSpellExtraArgs::SetTriggeringSpell(Spell const* triggeri
TriggeringSpell = triggeringSpell;
if (triggeringSpell)
{
OriginalCastItemLevel = triggeringSpell->m_castItemLevel;
OriginalCastId = triggeringSpell->m_castId;
if (!OriginalCastItemLevel)
OriginalCastItemLevel = triggeringSpell->m_castItemLevel;
if (!OriginalCastItemLevel)
OriginalCastId = triggeringSpell->m_castId;
}
return *this;
}

View File

@@ -65,7 +65,8 @@ enum ProcFlagsHit : uint32;
enum ProcFlagsSpellType : uint32;
enum SpellTargetCheckTypes : uint8;
enum SpellTargetObjectTypes : uint8;
enum SpellValueMod : uint8;
enum SpellValueMod : int32;
enum SpellValueModFloat : int32;
enum TriggerCastFlags : uint32;
enum WeaponAttackType : uint8;
@@ -673,6 +674,7 @@ class TC_GAME_API Spell
void CleanupTargetList();
void SetSpellValue(SpellValueMod mod, int32 value);
void SetSpellValue(SpellValueModFloat mod, float value);
Spell** m_selfContainer; // pointer to our spell container (if applicable)

View File

@@ -194,7 +194,7 @@ enum class SpellModOp : uint8
#define MAX_SPELLMOD 40
enum SpellValueMod : uint8
enum SpellValueMod : int32
{
SPELLVALUE_BASE_POINT0,
SPELLVALUE_BASE_POINT1,
@@ -228,15 +228,23 @@ enum SpellValueMod : uint8
SPELLVALUE_BASE_POINT29,
SPELLVALUE_BASE_POINT30,
SPELLVALUE_BASE_POINT31,
SPELLVALUE_BASE_POINT_END,
SPELLVALUE_RADIUS_MOD,
SPELLVALUE_MAX_TARGETS,
SPELLVALUE_MAX_TARGETS = SPELLVALUE_BASE_POINT_END,
SPELLVALUE_AURA_STACK,
SPELLVALUE_CRIT_CHANCE,
SPELLVALUE_DURATION_PCT,
SPELLVALUE_DURATION,
SPELLVALUE_PARENT_SPELL_TARGET_COUNT,
SPELLVALUE_PARENT_SPELL_TARGET_INDEX
SPELLVALUE_PARENT_SPELL_TARGET_INDEX,
SPELLVALUE_INT_END
};
enum SpellValueModFloat : int32
{
SPELLVALUE_RADIUS_MOD = uint8(SPELLVALUE_INT_END),
SPELLVALUE_CRIT_CHANCE,
SPELLVALUE_DURATION_PCT,
};
enum SpellFacingFlags
@@ -448,16 +456,46 @@ struct TC_GAME_API CastSpellTargetArg
Optional<SpellCastTargets> Targets; // empty optional used to signal error state
};
struct TC_GAME_API CastSpellExtraArgs
struct CastSpellExtraArgsInit
{
TriggerCastFlags TriggerFlags = TRIGGERED_NONE;
Item* CastItem = nullptr;
Spell const* TriggeringSpell = nullptr;
AuraEffect const* TriggeringAura = nullptr;
ObjectGuid OriginalCaster = ObjectGuid::Empty;
Difficulty CastDifficulty = Difficulty(0);
ObjectGuid OriginalCastId = ObjectGuid::Empty;
Optional<int32> OriginalCastItemLevel;
struct SpellValueOverride
{
SpellValueOverride(SpellValueMod mod, int32 val) : Type(mod) { Value.I = val; }
SpellValueOverride(SpellValueModFloat mod, float val) : Type(mod) { Value.F = val; }
int32 Type;
union
{
float F;
int32 I;
} Value;
};
std::vector<SpellValueOverride> SpellValueOverrides;
std::any CustomArg;
Optional<Scripting::v2::ActionResultSetter<SpellCastResult>> ScriptResult;
bool ScriptWaitsForSpellHit = false;
};
struct TC_GAME_API CastSpellExtraArgs : public CastSpellExtraArgsInit
{
CastSpellExtraArgs();
CastSpellExtraArgs(bool triggered) : TriggerFlags(triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE) {}
CastSpellExtraArgs(TriggerCastFlags trigger) : TriggerFlags(trigger) {}
CastSpellExtraArgs(Item* item) : TriggerFlags(TRIGGERED_FULL_MASK), CastItem(item) {}
CastSpellExtraArgs(Spell const* triggeringSpell) : TriggerFlags(TRIGGERED_FULL_MASK) { SetTriggeringSpell(triggeringSpell); }
CastSpellExtraArgs(AuraEffect const* eff) : TriggerFlags(TRIGGERED_FULL_MASK) { SetTriggeringAura(eff); }
CastSpellExtraArgs(Difficulty castDifficulty) : CastDifficulty(castDifficulty) {}
CastSpellExtraArgs(SpellValueMod mod, int32 val) { SpellValueOverrides.AddMod(mod, val); }
CastSpellExtraArgs(bool triggered) { TriggerFlags = triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE; }
CastSpellExtraArgs(TriggerCastFlags trigger) { TriggerFlags = trigger; }
CastSpellExtraArgs(Item* item) { TriggerFlags = TRIGGERED_FULL_MASK; CastItem = item; }
CastSpellExtraArgs(Spell const* triggeringSpell) { TriggerFlags = TRIGGERED_FULL_MASK; SetTriggeringSpell(triggeringSpell); }
CastSpellExtraArgs(AuraEffect const* eff) { TriggerFlags = TRIGGERED_FULL_MASK; SetTriggeringAura(eff); }
CastSpellExtraArgs(Difficulty castDifficulty) { CastDifficulty = castDifficulty; }
CastSpellExtraArgs(SpellValueMod mod, int32 val) { SpellValueOverrides.emplace_back(mod, val); }
CastSpellExtraArgs(SpellValueModFloat mod, float val) { SpellValueOverrides.emplace_back(mod, val); }
CastSpellExtraArgs(CastSpellExtraArgsInit&& init) : CastSpellExtraArgsInit(std::move(init)) { SetTriggeringSpell(TriggeringSpell); }
CastSpellExtraArgs(CastSpellExtraArgs const& other);
CastSpellExtraArgs(CastSpellExtraArgs&& other) noexcept;
@@ -474,37 +512,12 @@ struct TC_GAME_API CastSpellExtraArgs
CastSpellExtraArgs& SetOriginalCaster(ObjectGuid const& guid) { OriginalCaster = guid; return *this; }
CastSpellExtraArgs& SetCastDifficulty(Difficulty castDifficulty) { CastDifficulty = castDifficulty; return *this; }
CastSpellExtraArgs& SetOriginalCastId(ObjectGuid const& castId) { OriginalCastId = castId; return *this; }
CastSpellExtraArgs& AddSpellMod(SpellValueMod mod, int32 val) { SpellValueOverrides.AddMod(mod, val); return *this; }
CastSpellExtraArgs& AddSpellMod(SpellValueMod mod, int32 val) { SpellValueOverrides.emplace_back(mod, val); return *this; }
CastSpellExtraArgs& AddSpellMod(SpellValueModFloat mod, float val) { SpellValueOverrides.emplace_back(mod, val); return *this; }
CastSpellExtraArgs& AddSpellBP0(int32 val) { return AddSpellMod(SPELLVALUE_BASE_POINT0, val); } // because i don't want to type SPELLVALUE_BASE_POINT0 300 times
CastSpellExtraArgs& SetCustomArg(std::any customArg) { CustomArg = std::move(customArg); return *this; }
CastSpellExtraArgs& SetScriptResult(Scripting::v2::ActionResultSetter<SpellCastResult> scriptResult) { ScriptResult.emplace(std::move(scriptResult)); return *this; }
CastSpellExtraArgs& SetScriptWaitsForSpellHit(bool scriptWaitsForSpellHit) { ScriptWaitsForSpellHit = scriptWaitsForSpellHit; return *this; }
TriggerCastFlags TriggerFlags = TRIGGERED_NONE;
Item* CastItem = nullptr;
Spell const* TriggeringSpell = nullptr;
AuraEffect const* TriggeringAura = nullptr;
ObjectGuid OriginalCaster = ObjectGuid::Empty;
Difficulty CastDifficulty = Difficulty(0);
ObjectGuid OriginalCastId = ObjectGuid::Empty;
Optional<int32> OriginalCastItemLevel;
struct
{
friend struct CastSpellExtraArgs;
friend class WorldObject;
private:
void AddMod(SpellValueMod mod, int32 val) { data.push_back({ mod, val }); }
auto begin() const { return data.cbegin(); }
auto end() const { return data.cend(); }
std::vector<std::pair<SpellValueMod, int32>> data;
} SpellValueOverrides;
std::any CustomArg;
Optional<Scripting::v2::ActionResultSetter<SpellCastResult>> ScriptResult;
bool ScriptWaitsForSpellHit = false;
};
struct SpellCastVisual

View File

@@ -555,7 +555,7 @@ public:
{
void SetRadiusMod()
{
GetSpell()->SetSpellValue(SPELLVALUE_RADIUS_MOD, int32(GetCaster()->GetObjectScale() * 10000 * 2 / 3));
GetSpell()->SetSpellValue(SPELLVALUE_RADIUS_MOD, GetCaster()->GetObjectScale() * 2 / 3);
}
void FilterTargets(std::list<WorldObject*>& unitList)
@@ -626,7 +626,7 @@ public:
{
void SetRadiusMod()
{
GetSpell()->SetSpellValue(SPELLVALUE_RADIUS_MOD, int32(GetCaster()->GetObjectScale() * 10000 * 2 / 3));
GetSpell()->SetSpellValue(SPELLVALUE_RADIUS_MOD, GetCaster()->GetObjectScale() * 2 / 3);
}
void Register() override

View File

@@ -1506,7 +1506,7 @@ class spell_halion_combustion_consumption_periodic : public SpellScriptLoader
return;
uint32 triggerSpell = aurEff->GetSpellEffectInfo().TriggerSpell;
int32 radius = caster->GetObjectScale() * M_PI * 10000 / 3;
float radius = caster->GetObjectScale() * M_PI / 3;
CastSpellExtraArgs args(aurEff);
args.OriginalCaster = caster->GetGUID();

View File

@@ -1208,7 +1208,7 @@ class spell_jormungars_slime_pool : public AuraScript
{
PreventDefaultAction();
int32 const radius = static_cast<int32>(((aurEff->GetTickNumber() / 60.f) * 0.9f + 0.1f) * 10000.f * 2.f / 3.f);
float const radius = ((aurEff->GetTickNumber() / 60.f) * 0.9f + 0.1f) * 2.f / 3.f;
CastSpellExtraArgs args(aurEff);
args.AddSpellMod(SPELLVALUE_RADIUS_MOD, radius);
GetTarget()->CastSpell(nullptr, aurEff->GetSpellEffectInfo().TriggerSpell, args);

View File

@@ -226,7 +226,7 @@ class spell_grobbulus_poison_cloud : public AuraScript
return;
uint32 triggerSpell = aurEff->GetSpellEffectInfo().TriggerSpell;
int32 mod = int32(((float(aurEff->GetTickNumber()) / aurEff->GetTotalTicks()) * 0.9f + 0.1f) * 10000 * 2 / 3);
float mod = ((float(aurEff->GetTickNumber()) / aurEff->GetTotalTicks()) * 0.9f + 0.1f) * 2 / 3;
CastSpellExtraArgs args(aurEff);
args.AddSpellMod(SPELLVALUE_RADIUS_MOD, mod);

View File

@@ -292,7 +292,7 @@ class spell_broggok_poison_cloud : public SpellScriptLoader
return;
uint32 triggerSpell = aurEff->GetSpellEffectInfo().TriggerSpell;
int32 mod = int32(((float(aurEff->GetTickNumber()) / aurEff->GetTotalTicks()) * 0.9f + 0.1f) * 10000 * 2 / 3);
float mod = ((float(aurEff->GetTickNumber()) / aurEff->GetTotalTicks()) * 0.9f + 0.1f) * 10000 * 2 / 3;
GetTarget()->CastSpell(nullptr, triggerSpell, CastSpellExtraArgs(aurEff).AddSpellMod(SPELLVALUE_RADIUS_MOD, mod));
}