diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index ae456ce79..711823895 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -797,6 +797,7 @@ enum Targets { TARGET_SELF = 1, TARGET_RANDOM_ENEMY_CHAIN_IN_AREA = 2, // only one spell has that, but regardless, it's a target type after all + TARGET_RANDOM_FRIEND_CHAIN_IN_AREA = 3, TARGET_PET = 5, TARGET_CHAIN_DAMAGE = 6, TARGET_AREAEFFECT_CUSTOM = 8, diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index dd176713a..2aa793449 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1378,6 +1378,73 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) --t; } }break; + case TARGET_RANDOM_FRIEND_CHAIN_IN_AREA: + { + m_targets.m_targetMask = 0; + unMaxTargets = EffectChainTarget; + float max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS; + CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + std::list tempUnitMap; + { + MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, max_range); + MaNGOS::UnitListSearcher searcher(tempUnitMap, u_check); + + TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); + TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); + + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_unit_searcher, *m_caster->GetMap()); + cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap()); + } + + if(tempUnitMap.empty()) + break; + + tempUnitMap.sort(TargetDistanceOrder(m_caster)); + + //Now to get us a random target that's in the initial range of the spell + uint32 t = 0; + std::list::iterator itr = tempUnitMap.begin(); + while(itr!= tempUnitMap.end() && (*itr)->GetDistance(m_caster) < radius) + ++t, ++itr; + + if(!t) + break; + + itr = tempUnitMap.begin(); + std::advance(itr, rand()%t); + Unit *pUnitTarget = *itr; + TagUnitMap.push_back(pUnitTarget); + + tempUnitMap.erase(itr); + + tempUnitMap.sort(TargetDistanceOrder(pUnitTarget)); + + t = unMaxTargets - 1; + Unit *prev = pUnitTarget; + std::list::iterator next = tempUnitMap.begin(); + + while(t && next != tempUnitMap.end() ) + { + if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) + break; + + if(!prev->IsWithinLOSInMap(*next)) + { + ++next; + continue; + } + prev = *next; + TagUnitMap.push_back(prev); + tempUnitMap.erase(next); + tempUnitMap.sort(TargetDistanceOrder(prev)); + next = tempUnitMap.begin(); + --t; + } + }break; case TARGET_PET: { Pet* tmpUnit = m_caster->GetPet();