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:
ariel-
2018-02-01 13:10:51 -03:00
committed by Shauren
parent f3548d45d0
commit 65dca120d3
10 changed files with 581 additions and 599 deletions

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);
}
}