commit
fc72b48f84
@ -365,13 +365,22 @@ void GameObject::Update(uint32 update_diff, uint32 p_time)
|
||||
}
|
||||
}
|
||||
|
||||
// Should trap trigger?
|
||||
Unit* enemy = NULL; // pointer to appropriate target if found any
|
||||
MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, radius);
|
||||
MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck> checker(enemy, u_check);
|
||||
Cell::VisitAllObjects(this, checker, radius);
|
||||
if (enemy)
|
||||
{ Use(enemy); }
|
||||
SpellEntry const* se = sSpellStore.LookupEntry(goInfo->trap.spellId);
|
||||
if(IsAreaOfEffectSpell(se))
|
||||
{
|
||||
MaNGOS::AllSpecificUnitsInGameObjectRangeDo unit_do(this, radius, IsPositiveSpell(se));
|
||||
MaNGOS::UnitWorker<MaNGOS::AllSpecificUnitsInGameObjectRangeDo> worker(unit_do);
|
||||
Cell::VisitAllObjects(this,worker,radius);
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit* targetUnit = NULL; // pointer to appropriate target if found any
|
||||
MaNGOS::AnySpecificUnitInGameObjectRangeCheck u_check(this, radius, IsPositiveSpell(se));
|
||||
MaNGOS::UnitSearcher<MaNGOS::AnySpecificUnitInGameObjectRangeCheck> checker(targetUnit, u_check);
|
||||
Cell::VisitAllObjects(this, checker, radius);
|
||||
if (targetUnit)
|
||||
{ Use(targetUnit); }
|
||||
}
|
||||
}
|
||||
|
||||
if (uint32 max_charges = goInfo->GetCharges())
|
||||
|
@ -2912,43 +2912,40 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
|
||||
// replace spells in action bars and spellbook to bigger rank if only one spell rank must be accessible
|
||||
if (newspell.active && !newspell.disabled)
|
||||
{
|
||||
SpellChainMapNext const& nextMap = sSpellMgr.GetSpellChainNext();
|
||||
for (SpellChainMapNext::const_iterator next_itr = nextMap.lower_bound(spell_id); next_itr != nextMap.upper_bound(spell_id); ++next_itr)
|
||||
do
|
||||
{
|
||||
uint32 tested_spell_id = next_itr->second; // synonym just for the code clarity
|
||||
if (m_spells.find(tested_spell_id) == m_spells.end())
|
||||
uint32 prev_spell_id = sSpellMgr.GetPrevSpellInChain(spell_id); // get the previous spell in chain (if any)
|
||||
if(!prev_spell_id) //spell_id does not have ranks or is the first spell in chain; must add in spellbook
|
||||
continue;
|
||||
|
||||
if ((m_spells.find(prev_spell_id) == m_spells.end()))
|
||||
continue;
|
||||
|
||||
PlayerSpell &lowerRank = m_spells[tested_spell_id];
|
||||
if (lowerRank.state == PLAYERSPELL_REMOVED || !lowerRank.active)
|
||||
PlayerSpell* lowerRank = &m_spells[prev_spell_id];
|
||||
if (lowerRank->state == PLAYERSPELL_REMOVED || !lowerRank->active)
|
||||
continue;
|
||||
|
||||
SpellEntry const *spell_old = sSpellStore.LookupEntry(tested_spell_id); // was checked for NULL in SpellMgr::LoadSpellChains()
|
||||
SpellEntry const *spell_old = sSpellStore.LookupEntry(prev_spell_id);
|
||||
SpellEntry const *spell_new = spellInfo;
|
||||
if (sSpellMgr.IsHighRankOfSpell(tested_spell_id, spell_id) && sSpellMgr.IsRankedSpellNonStackableInSpellBook(spell_old))
|
||||
|
||||
if (sSpellMgr.IsRankedSpellNonStackableInSpellBook(spell_old))
|
||||
{
|
||||
spell_new = spell_old;
|
||||
spell_old = spellInfo;
|
||||
lowerRank = newspell;
|
||||
if (IsInWorld()) // not send spell (re-/over-)learn packets at loading
|
||||
{
|
||||
WorldPacket data(SMSG_SUPERCEDED_SPELL, (4));
|
||||
data << uint16(spell_old->Id);
|
||||
data << uint16(spell_new->Id);
|
||||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
// mark lower rank disabled (SMSG_SUPERCEDED_SPELL replaced it in client by new)
|
||||
lowerRank->active = false;
|
||||
if (lowerRank->state != PLAYERSPELL_NEW)
|
||||
lowerRank->state = PLAYERSPELL_CHANGED;
|
||||
|
||||
canAddToSpellBook = false;
|
||||
}
|
||||
else if (!(sSpellMgr.IsHighRankOfSpell(spell_id, tested_spell_id) && sSpellMgr.IsRankedSpellNonStackableInSpellBook(spell_new)))
|
||||
continue;
|
||||
|
||||
if (IsInWorld()) // not send spell (re-/over-)learn packets at loading
|
||||
{
|
||||
WorldPacket data(SMSG_SUPERCEDED_SPELL, (4));
|
||||
data << uint16(spell_old->Id);
|
||||
data << uint16(spell_new->Id);
|
||||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
// mark lower rank disabled (SMSG_SUPERCEDED_SPELL replaced it in client by new)
|
||||
lowerRank.active = false;
|
||||
if (lowerRank.state != PLAYERSPELL_NEW)
|
||||
lowerRank.state = PLAYERSPELL_CHANGED;
|
||||
|
||||
canAddToSpellBook = false;
|
||||
}
|
||||
} while(0);
|
||||
}
|
||||
|
||||
m_spells[spell_id] = newspell;
|
||||
|
@ -378,6 +378,28 @@ namespace MaNGOS
|
||||
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED>&) {}
|
||||
};
|
||||
|
||||
// unit worker
|
||||
template<class Do>
|
||||
struct UnitWorker
|
||||
{
|
||||
Do& i_do;
|
||||
|
||||
explicit UnitWorker(Do& _do) : i_do(_do) {}
|
||||
|
||||
void Visit(PlayerMapType& m)
|
||||
{
|
||||
for (PlayerMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
|
||||
{ i_do(itr->getSource()); }
|
||||
}
|
||||
void Visit(CreatureMapType& m)
|
||||
{
|
||||
for (CreatureMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
|
||||
{ i_do(itr->getSource()); }
|
||||
}
|
||||
|
||||
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED>&) {}
|
||||
};
|
||||
|
||||
// Creature searchers
|
||||
|
||||
template<class Check>
|
||||
@ -927,6 +949,60 @@ namespace MaNGOS
|
||||
bool i_targetForPlayer;
|
||||
};
|
||||
|
||||
class AnySpecificUnitInGameObjectRangeCheck
|
||||
{
|
||||
public:
|
||||
AnySpecificUnitInGameObjectRangeCheck(GameObject* go, float range, bool friendly = true)
|
||||
: i_obj(go), i_range(range), i_isFriendly(friendly)
|
||||
{
|
||||
}
|
||||
WorldObject const& GetFocusObject() const { return *i_obj; }
|
||||
bool operator()(Unit* u)
|
||||
{
|
||||
// Check contains checks for: live, non-selectable, non-attackable flags, flight check and GM check, ignore totems
|
||||
if (!u->IsTargetableForAttack())
|
||||
{ return false; }
|
||||
|
||||
if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->IsTotem())
|
||||
{ return false; }
|
||||
|
||||
if ((i_isFriendly ? i_obj->IsFriendlyTo(u) : i_obj->IsHostileTo(u)) && i_obj->IsWithinDistInMap(u, i_range))
|
||||
{ return true; }
|
||||
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
GameObject* i_obj;
|
||||
float i_range;
|
||||
bool i_isFriendly;
|
||||
};
|
||||
|
||||
class AllSpecificUnitsInGameObjectRangeDo
|
||||
{
|
||||
public:
|
||||
AllSpecificUnitsInGameObjectRangeDo(GameObject* go, float range, bool friendly = true)
|
||||
: i_obj(go), i_range(range), i_isFriendly(friendly)
|
||||
{
|
||||
}
|
||||
WorldObject const& GetFocusObject() const { return *i_obj; }
|
||||
void operator()(Unit* u)
|
||||
{
|
||||
// Check contains checks for: live, non-selectable, non-attackable flags, flight check and GM check, ignore totems
|
||||
if (!u->IsTargetableForAttack())
|
||||
{ return; }
|
||||
|
||||
if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->IsTotem())
|
||||
{ return; }
|
||||
|
||||
if ((i_isFriendly ? i_obj->IsFriendlyTo(u) : i_obj->IsHostileTo(u)) && i_obj->IsWithinDistInMap(u, i_range))
|
||||
{ i_obj->Use(u); }
|
||||
}
|
||||
private:
|
||||
GameObject* i_obj;
|
||||
float i_range;
|
||||
bool i_isFriendly;
|
||||
};
|
||||
|
||||
// do attack at call of help to friendly crearture
|
||||
class CallOfHelpCreatureInRangeDo
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user