Core/Spells: rework part 4: iterate over effects first

Ref #18395

Implement far spell queue processing
Closes #7395
This commit is contained in:
ariel-
2018-02-01 13:10:51 -03:00
committed by Ariel Silva
parent e8d5aa56cc
commit 080d2c6cd4
10 changed files with 619 additions and 635 deletions
+1 -1
View File
@@ -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;
}
+14
View File
@@ -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;
+6
View File
@@ -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
File diff suppressed because it is too large Load Diff
+61 -33
View File
@@ -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;
+8 -8
View File
@@ -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;
}
}
+2 -15
View File
@@ -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]);
}
-2
View File
@@ -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;
-11
View File
@@ -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);
}
}