mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Spells: rework part 4: iterate over effects first
Ref #18395
Implement far spell queue processing
Closes #7395
(cherry picked from commit 080d2c6cd4)
This commit is contained in:
@@ -24078,7 +24078,7 @@ Player* Player::GetSelectedPlayer() const
|
||||
{
|
||||
ObjectGuid selectionGUID = GetTarget();
|
||||
if (!selectionGUID.IsEmpty())
|
||||
return ObjectAccessor::GetPlayer(*this, selectionGUID);
|
||||
return ObjectAccessor::FindConnectedPlayer(selectionGUID);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -3534,8 +3534,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;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "GridRefManager.h"
|
||||
#include "MapDefines.h"
|
||||
#include "MapRefManager.h"
|
||||
#include "MPSCQueue.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "Optional.h"
|
||||
#include "SharedDefines.h"
|
||||
@@ -775,6 +776,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>
|
||||
@@ -839,6 +843,8 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
|
||||
std::unordered_set<Corpse*> _corpseBones;
|
||||
|
||||
std::unordered_set<Object*> _updateObjects;
|
||||
|
||||
MPSCQueue<FarSpellCallback> _farSpellCallbacks;
|
||||
};
|
||||
|
||||
enum InstanceResetMethod
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -567,7 +567,6 @@ class TC_GAME_API Spell
|
||||
|
||||
int32 CalculateDamage(uint8 i, Unit const* target, float* var = nullptr) const;
|
||||
|
||||
bool HaveTargetsForEffect(uint8 effect) const;
|
||||
void Delayed();
|
||||
void DelayedChannel();
|
||||
uint32 getState() const { return m_spellState; }
|
||||
@@ -793,39 +792,69 @@ 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;
|
||||
uint32 EffectMask = 0;
|
||||
|
||||
uint32 effectMask;
|
||||
bool processed;
|
||||
bool alive;
|
||||
bool crit;
|
||||
protected:
|
||||
TargetInfoBase() { }
|
||||
virtual ~TargetInfoBase() { }
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
// info set at PreprocessTarget, used by DoTargetSpellHit
|
||||
DiminishingGroup DRGroup = DIMINISHING_NONE;
|
||||
int32 AuraDuration = 0;
|
||||
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;
|
||||
uint32 m_channelTargetEffectMask; // Mask req. alive targets
|
||||
uint32 m_channelTargetEffectMask; // Mask req. alive targets
|
||||
|
||||
struct GOTargetInfo
|
||||
struct GOTargetInfo : public TargetInfoBase
|
||||
{
|
||||
ObjectGuid targetGUID;
|
||||
uint64 timeDelay;
|
||||
uint32 effectMask;
|
||||
bool processed;
|
||||
void DoTargetSpellHit(Spell* spell, uint8 effIndex) override;
|
||||
|
||||
ObjectGuid TargetGUID;
|
||||
uint64 TimeDelay = 0ULL;
|
||||
};
|
||||
std::vector<GOTargetInfo> m_UniqueGOTargetInfo;
|
||||
|
||||
struct ItemTargetInfo
|
||||
struct ItemTargetInfo : public TargetInfoBase
|
||||
{
|
||||
Item *item;
|
||||
uint32 effectMask;
|
||||
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];
|
||||
|
||||
void AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid = true, bool implicit = true, Position const* losPosition = nullptr);
|
||||
@@ -833,15 +862,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);
|
||||
SpellMissInfo PreprocessSpellHit(Unit* unit, TargetInfo& targetInfo);
|
||||
void DoSpellEffectHit(Unit* unit, uint8 effIndex, TargetInfo& targetInfo);
|
||||
|
||||
void DoTriggersOnSpellHit(Unit* unit, uint32 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, SpellEffectInfo const* effect);
|
||||
|
||||
void PrepareTargetProcessing();
|
||||
void FinishTargetProcessing();
|
||||
@@ -852,7 +880,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(SpellMissInfo missInfo);
|
||||
|
||||
@@ -577,8 +577,8 @@ void Spell::EffectDummy(SpellEffIndex effIndex)
|
||||
case 31789: // Righteous Defense (step 1)
|
||||
{
|
||||
// Clear targets for eff 1
|
||||
for (std::vector<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();
|
||||
@@ -1152,7 +1152,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;
|
||||
}
|
||||
@@ -1177,10 +1177,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);
|
||||
}
|
||||
|
||||
@@ -1208,7 +1208,7 @@ void Spell::EffectHeal(SpellEffIndex /*effIndex*/)
|
||||
if (unitTarget->HasAura(48920) && (unitTarget->GetHealth() + addhealth >= unitTarget->GetMaxHealth()))
|
||||
unitTarget->RemoveAura(48920);
|
||||
|
||||
m_damage -= addhealth;
|
||||
m_healing += addhealth;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -447,18 +447,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);
|
||||
}
|
||||
|
||||
bool SpellEffectInfo::IsFarDestTargetEffect() const
|
||||
{
|
||||
return Effect == SPELL_EFFECT_TELEPORT_UNITS;
|
||||
}
|
||||
|
||||
bool SpellEffectInfo::IsUnitOwnedAuraEffect() const
|
||||
{
|
||||
return IsAreaAuraEffect() || Effect == SPELL_EFFECT_APPLY_AURA || Effect == SPELL_EFFECT_APPLY_AURA_ON_PET;
|
||||
@@ -3740,14 +3728,14 @@ int32 SpellInfo::CalcDuration(Unit* caster /*= nullptr*/) const
|
||||
int32 SpellInfo::GetDuration() const
|
||||
{
|
||||
if (!DurationEntry)
|
||||
return 0;
|
||||
return IsPassive() ? -1 : 0;
|
||||
return (DurationEntry->Duration == -1) ? -1 : abs(DurationEntry->Duration);
|
||||
}
|
||||
|
||||
int32 SpellInfo::GetMaxDuration() const
|
||||
{
|
||||
if (!DurationEntry)
|
||||
return 0;
|
||||
return IsPassive() ? -1 : 0;
|
||||
return (DurationEntry->MaxDuration == -1) ? -1 : abs(DurationEntry->MaxDuration);
|
||||
}
|
||||
|
||||
|
||||
@@ -312,8 +312,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, float* variance = nullptr, uint32 castItemId = 0, int32 itemLevel = -1) const;
|
||||
|
||||
@@ -3894,20 +3894,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.
|
||||
ApplySpellEffectFix(spellInfo, EFFECT_1, [](SpellEffectInfo* spellEffectInfo)
|
||||
{
|
||||
spellEffectInfo->Effect = 0;
|
||||
});
|
||||
});
|
||||
|
||||
ApplySpellFix({
|
||||
64386, // Terrifying Screech (Auriaya)
|
||||
64389, // Sentinel Blast (Auriaya)
|
||||
|
||||
@@ -631,29 +631,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:
|
||||
@@ -699,12 +676,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