mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-19 06:29:50 -04:00
Core/Spells: rework part 4: iterate over effects first
Ref #18395 Implement far spell queue processing Closes #7395
This commit is contained in:
@@ -22366,7 +22366,7 @@ Unit* Player::GetSelectedUnit() const
|
||||
Player* Player::GetSelectedPlayer() const
|
||||
{
|
||||
if (ObjectGuid selectionGUID = GetTarget())
|
||||
return ObjectAccessor::GetPlayer(*this, selectionGUID);
|
||||
return ObjectAccessor::FindConnectedPlayer(selectionGUID);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -3395,8 +3395,22 @@ bool Map::IsSpawnGroupActive(uint32 groupId) const
|
||||
return (_toggledSpawnGroupIds.find(groupId) != _toggledSpawnGroupIds.end()) != !(data->flags & SPAWNGROUP_FLAG_MANUAL_SPAWN);
|
||||
}
|
||||
|
||||
void Map::AddFarSpellCallback(FarSpellCallback&& callback)
|
||||
{
|
||||
_farSpellCallbacks.Enqueue(new FarSpellCallback(std::move(callback)));
|
||||
}
|
||||
|
||||
void Map::DelayedUpdate(uint32 t_diff)
|
||||
{
|
||||
{
|
||||
FarSpellCallback* callback;
|
||||
while (_farSpellCallbacks.Dequeue(callback))
|
||||
{
|
||||
(*callback)(this);
|
||||
delete callback;
|
||||
}
|
||||
}
|
||||
|
||||
for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();)
|
||||
{
|
||||
Transport* transport = *_transportsUpdateIter;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "GridDefines.h"
|
||||
#include "GridRefManager.h"
|
||||
#include "MapRefManager.h"
|
||||
#include "MPSCQueue.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "Optional.h"
|
||||
#include "SharedDefines.h"
|
||||
@@ -853,6 +854,9 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
|
||||
// This will not affect any already-present creatures in the group
|
||||
void SetSpawnGroupInactive(uint32 groupId) { SetSpawnGroupActive(groupId, false); }
|
||||
|
||||
typedef std::function<void(Map*)> FarSpellCallback;
|
||||
void AddFarSpellCallback(FarSpellCallback&& callback);
|
||||
|
||||
private:
|
||||
// Type specific code for add/remove to/from grid
|
||||
template<class T>
|
||||
@@ -916,6 +920,8 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
|
||||
std::unordered_set<Corpse*> _corpseBones;
|
||||
|
||||
std::unordered_set<Object*> _updateObjects;
|
||||
|
||||
MPSCQueue<FarSpellCallback> _farSpellCallbacks;
|
||||
};
|
||||
|
||||
enum InstanceResetMethod
|
||||
|
||||
+526
-536
File diff suppressed because it is too large
Load Diff
@@ -445,7 +445,6 @@ class TC_GAME_API Spell
|
||||
|
||||
int32 CalculateDamage(uint8 i, Unit const* target) const;
|
||||
|
||||
bool HaveTargetsForEffect(uint8 effect) const;
|
||||
void Delayed();
|
||||
void DelayedChannel();
|
||||
uint32 getState() const { return m_spellState; }
|
||||
@@ -599,7 +598,7 @@ class TC_GAME_API Spell
|
||||
bool m_executedCurrently; // mark as executed to prevent deleted and access by dead pointers
|
||||
bool m_needComboPoints;
|
||||
uint8 m_applyMultiplierMask;
|
||||
float m_damageMultipliers[3];
|
||||
float m_damageMultipliers[MAX_SPELL_EFFECTS];
|
||||
|
||||
// Current targets, to be used in SpellEffects (MUST BE USED ONLY IN SPELL EFFECTS)
|
||||
Unit* unitTarget;
|
||||
@@ -632,39 +631,70 @@ class TC_GAME_API Spell
|
||||
// Spell target subsystem
|
||||
// *****************************************
|
||||
// Targets store structures and data
|
||||
struct TargetInfo
|
||||
struct TargetInfoBase
|
||||
{
|
||||
ObjectGuid targetGUID;
|
||||
uint64 timeDelay;
|
||||
int32 damage;
|
||||
virtual void PreprocessTarget(Spell* /*spell*/) { }
|
||||
virtual void DoTargetSpellHit(Spell* spell, uint8 effIndex) = 0;
|
||||
virtual void DoDamageAndTriggers(Spell* /*spell*/) { }
|
||||
|
||||
SpellMissInfo missCondition;
|
||||
SpellMissInfo reflectResult;
|
||||
uint8 EffectMask = 0;
|
||||
|
||||
uint8 effectMask;
|
||||
bool processed;
|
||||
bool alive;
|
||||
bool crit;
|
||||
bool scaleAura;
|
||||
protected:
|
||||
TargetInfoBase() { }
|
||||
virtual ~TargetInfoBase() { }
|
||||
};
|
||||
std::list<TargetInfo> m_UniqueTargetInfo;
|
||||
|
||||
struct TargetInfo : public TargetInfoBase
|
||||
{
|
||||
void PreprocessTarget(Spell* spell) override;
|
||||
void DoTargetSpellHit(Spell* spell, uint8 effIndex) override;
|
||||
void DoDamageAndTriggers(Spell* spell) override;
|
||||
|
||||
ObjectGuid TargetGUID;
|
||||
uint64 TimeDelay = 0ULL;
|
||||
int32 Damage = 0;
|
||||
int32 Healing = 0;
|
||||
|
||||
SpellMissInfo MissCondition = SPELL_MISS_NONE;
|
||||
SpellMissInfo ReflectResult = SPELL_MISS_NONE;
|
||||
|
||||
bool IsAlive = false;
|
||||
bool IsCrit = false;
|
||||
bool ScaleAura = false;
|
||||
|
||||
// info set at PreprocessTarget, used by DoTargetSpellHit
|
||||
DiminishingGroup DRGroup = DIMINISHING_NONE;
|
||||
int32 AuraDuration = 0;
|
||||
SpellInfo const* AuraSpellInfo = nullptr;
|
||||
int32 AuraBasePoints[MAX_SPELL_EFFECTS] = { };
|
||||
bool Positive = true;
|
||||
|
||||
private:
|
||||
Unit* _spellHitTarget = nullptr; // changed for example by reflect
|
||||
bool _enablePVP = false; // need to enable PVP at DoDamageAndTriggers?
|
||||
};
|
||||
std::vector<TargetInfo> m_UniqueTargetInfo;
|
||||
uint8 m_channelTargetEffectMask; // Mask req. alive targets
|
||||
|
||||
struct GOTargetInfo
|
||||
struct GOTargetInfo : public TargetInfoBase
|
||||
{
|
||||
ObjectGuid targetGUID;
|
||||
uint64 timeDelay;
|
||||
uint8 effectMask;
|
||||
bool processed;
|
||||
};
|
||||
std::list<GOTargetInfo> m_UniqueGOTargetInfo;
|
||||
void DoTargetSpellHit(Spell* spell, uint8 effIndex) override;
|
||||
|
||||
struct ItemTargetInfo
|
||||
{
|
||||
Item *item;
|
||||
uint8 effectMask;
|
||||
ObjectGuid TargetGUID;
|
||||
uint64 TimeDelay = 0ULL;
|
||||
};
|
||||
std::list<ItemTargetInfo> m_UniqueItemInfo;
|
||||
std::vector<GOTargetInfo> m_UniqueGOTargetInfo;
|
||||
|
||||
struct ItemTargetInfo : public TargetInfoBase
|
||||
{
|
||||
void DoTargetSpellHit(Spell* spell, uint8 effIndex) override;
|
||||
|
||||
Item* TargetItem = nullptr;
|
||||
};
|
||||
std::vector<ItemTargetInfo> m_UniqueItemInfo;
|
||||
|
||||
template <class Container>
|
||||
void DoProcessTargetContainer(Container& targetContainer);
|
||||
|
||||
SpellDestination m_destTargets[MAX_SPELL_EFFECTS];
|
||||
|
||||
@@ -673,15 +703,14 @@ class TC_GAME_API Spell
|
||||
void AddItemTarget(Item* item, uint32 effectMask);
|
||||
void AddDestTarget(SpellDestination const& dest, uint32 effIndex);
|
||||
|
||||
void DoAllEffectOnTarget(TargetInfo* target);
|
||||
SpellMissInfo DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleAura);
|
||||
SpellMissInfo PreprocessSpellHit(Unit* unit, bool scaleAura, TargetInfo& targetInfo);
|
||||
void DoSpellEffectHit(Unit* unit, uint8 effIndex, TargetInfo& targetInfo);
|
||||
|
||||
void DoTriggersOnSpellHit(Unit* unit, uint8 effMask);
|
||||
void DoAllEffectOnTarget(GOTargetInfo* target);
|
||||
void DoAllEffectOnTarget(ItemTargetInfo* target);
|
||||
bool UpdateChanneledTargetList();
|
||||
bool IsValidDeadOrAliveTarget(Unit const* target) const;
|
||||
void HandleLaunchPhase();
|
||||
void DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier);
|
||||
void DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, uint8 effIndex);
|
||||
|
||||
void PrepareTargetProcessing();
|
||||
void FinishTargetProcessing();
|
||||
@@ -696,7 +725,6 @@ class TC_GAME_API Spell
|
||||
void CallScriptOnCastHandlers();
|
||||
void CallScriptAfterCastHandlers();
|
||||
SpellCastResult CallScriptCheckCastHandlers();
|
||||
void PrepareScriptHitHandlers();
|
||||
bool CallScriptEffectHandlers(SpellEffIndex effIndex, SpellEffectHandleMode mode);
|
||||
void CallScriptSuccessfulDispel(SpellEffIndex effIndex);
|
||||
void CallScriptBeforeHitHandlers();
|
||||
@@ -745,7 +773,7 @@ class TC_GAME_API Spell
|
||||
uint8 m_auraScaleMask;
|
||||
std::unique_ptr<PathGenerator> m_preGeneratedPath;
|
||||
|
||||
ByteBuffer * m_effectExecuteData[MAX_SPELL_EFFECTS];
|
||||
ByteBuffer* m_effectExecuteData[MAX_SPELL_EFFECTS];
|
||||
|
||||
Spell(Spell const& right) = delete;
|
||||
Spell& operator=(Spell const& right) = delete;
|
||||
|
||||
@@ -327,8 +327,8 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
|
||||
if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_SHARE_DAMAGE))
|
||||
{
|
||||
uint32 count = 0;
|
||||
for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
|
||||
if (ihit->effectMask & (1<<effIndex))
|
||||
for (auto ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
|
||||
if (ihit->EffectMask & (1 << effIndex))
|
||||
++count;
|
||||
|
||||
damage /= count; // divide to all targets
|
||||
@@ -704,8 +704,8 @@ void Spell::EffectDummy(SpellEffIndex effIndex)
|
||||
case 31789: // Righteous Defense (step 1)
|
||||
{
|
||||
// Clear targets for eff 1
|
||||
for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
|
||||
ihit->effectMask &= ~(1<<1);
|
||||
for (auto ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
|
||||
ihit->EffectMask &= ~(1 << 1);
|
||||
|
||||
// not empty (checked), copy
|
||||
Unit::AttackerSet attackers = unitTarget->getAttackers();
|
||||
@@ -1296,7 +1296,7 @@ void Spell::EffectPowerBurn(SpellEffIndex effIndex)
|
||||
// add log data before multiplication (need power amount, not damage)
|
||||
ExecuteLogEffectTakeTargetPower(effIndex, unitTarget, powerType, newDamage, 0.0f);
|
||||
|
||||
newDamage = int32(newDamage* dmgMultiplier);
|
||||
newDamage = int32(newDamage * dmgMultiplier);
|
||||
|
||||
m_damage += newDamage;
|
||||
}
|
||||
@@ -1321,10 +1321,10 @@ void Spell::EffectHeal(SpellEffIndex effIndex)
|
||||
if (m_spellInfo->Id == 45064)
|
||||
{
|
||||
// Amount of heal - depends from stacked Holy Energy
|
||||
int damageAmount = 0;
|
||||
int32 damageAmount = 0;
|
||||
if (AuraEffect const* aurEff = m_caster->GetAuraEffect(45062, 0))
|
||||
{
|
||||
damageAmount+= aurEff->GetAmount();
|
||||
damageAmount += aurEff->GetAmount();
|
||||
m_caster->RemoveAurasDueToSpell(45062);
|
||||
}
|
||||
|
||||
@@ -1413,7 +1413,7 @@ void Spell::EffectHeal(SpellEffIndex effIndex)
|
||||
if (unitTarget->HasAura(48920) && (unitTarget->GetHealth() + addhealth >= unitTarget->GetMaxHealth()))
|
||||
unitTarget->RemoveAura(48920);
|
||||
|
||||
m_damage -= addhealth;
|
||||
m_healing += addhealth;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -390,19 +390,6 @@ bool SpellEffectInfo::IsAreaAuraEffect() const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SpellEffectInfo::IsFarUnitTargetEffect() const
|
||||
{
|
||||
return (Effect == SPELL_EFFECT_SUMMON_PLAYER)
|
||||
|| (Effect == SPELL_EFFECT_SUMMON_RAF_FRIEND)
|
||||
|| (Effect == SPELL_EFFECT_RESURRECT)
|
||||
|| (Effect == SPELL_EFFECT_RESURRECT_NEW);
|
||||
}
|
||||
|
||||
bool SpellEffectInfo::IsFarDestTargetEffect() const
|
||||
{
|
||||
return Effect == SPELL_EFFECT_TELEPORT_UNITS;
|
||||
}
|
||||
|
||||
bool SpellEffectInfo::IsUnitOwnedAuraEffect() const
|
||||
{
|
||||
return IsAreaAuraEffect() || Effect == SPELL_EFFECT_APPLY_AURA;
|
||||
@@ -3071,14 +3058,14 @@ float SpellInfo::GetMaxRange(bool positive, Unit* caster, Spell* spell) const
|
||||
int32 SpellInfo::GetDuration() const
|
||||
{
|
||||
if (!DurationEntry)
|
||||
return 0;
|
||||
return IsPassive() ? -1 : 0;
|
||||
return (DurationEntry->Duration[0] == -1) ? -1 : abs(DurationEntry->Duration[0]);
|
||||
}
|
||||
|
||||
int32 SpellInfo::GetMaxDuration() const
|
||||
{
|
||||
if (!DurationEntry)
|
||||
return 0;
|
||||
return IsPassive() ? -1 : 0;
|
||||
return (DurationEntry->Duration[2] == -1) ? -1 : abs(DurationEntry->Duration[2]);
|
||||
}
|
||||
|
||||
|
||||
@@ -272,8 +272,6 @@ public:
|
||||
bool IsAura(AuraType aura) const;
|
||||
bool IsTargetingArea() const;
|
||||
bool IsAreaAuraEffect() const;
|
||||
bool IsFarUnitTargetEffect() const;
|
||||
bool IsFarDestTargetEffect() const;
|
||||
bool IsUnitOwnedAuraEffect() const;
|
||||
|
||||
int32 CalcValue(Unit const* caster = nullptr, int32 const* basePoints = nullptr, Unit const* target = nullptr) const;
|
||||
|
||||
@@ -3985,17 +3985,6 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
spellInfo->MaxAffectedTargets = 1;
|
||||
});
|
||||
|
||||
// Boom (XT-002)
|
||||
ApplySpellFix({ 62834 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
// This hack is here because we suspect our implementation of spell effect execution on targets
|
||||
// is done in the wrong order. We suspect that EFFECT_0 needs to be applied on all targets,
|
||||
// then EFFECT_1, etc - instead of applying each effect on target1, then target2, etc.
|
||||
// The above situation causes the visual for this spell to be bugged, so we remove the instakill
|
||||
// effect and implement a script hack for that.
|
||||
spellInfo->Effects[EFFECT_1].Effect = 0;
|
||||
});
|
||||
|
||||
ApplySpellFix({
|
||||
64386, // Terrifying Screech (Auriaya)
|
||||
64389, // Sentinel Blast (Auriaya)
|
||||
|
||||
@@ -629,29 +629,6 @@ class npc_pummeller : public CreatureScript
|
||||
* XE-321 BOOMBOT
|
||||
*
|
||||
*///----------------------------------------------------
|
||||
class BoomEvent : public BasicEvent
|
||||
{
|
||||
public:
|
||||
BoomEvent(Creature* me) : _me(me)
|
||||
{
|
||||
}
|
||||
|
||||
bool Execute(uint64 /*time*/, uint32 /*diff*/) override
|
||||
{
|
||||
// This hack is here because we suspect our implementation of spell effect execution on targets
|
||||
// is done in the wrong order. We suspect that EFFECT_0 needs to be applied on all targets,
|
||||
// then EFFECT_1, etc - instead of applying each effect on target1, then target2, etc.
|
||||
// The above situation causes the visual for this spell to be bugged, so we remove the instakill
|
||||
// effect and implement a script hack for that.
|
||||
|
||||
_me->CastSpell(_me, SPELL_BOOM, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
Creature* _me;
|
||||
};
|
||||
|
||||
class npc_boombot : public CreatureScript
|
||||
{
|
||||
public:
|
||||
@@ -703,12 +680,7 @@ class npc_boombot : public CreatureScript
|
||||
|
||||
damage = 0;
|
||||
|
||||
// Visual only seems to work if the instant kill event is delayed or the spell itself is delayed
|
||||
// Casting done from player and caster source has the same targetinfo flags,
|
||||
// so that can't be the issue
|
||||
// See BoomEvent class
|
||||
// Schedule 1s delayed
|
||||
me->m_Events.AddEvent(new BoomEvent(me), me->m_Events.CalculateTime(1*IN_MILLISECONDS));
|
||||
DoCastAOE(SPELL_BOOM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user