📄 skill.cpp.svn-base
字号:
}
};
// Helper for targets nearest to the SKILLS target
// The SKILLS target is always first unless there is a target at _completely_ the same position (unbelievable case)
struct TargetDistanceOrder : public std::binary_function<const Unit, const Unit, bool>
{
const Unit* MainTarget;
TargetDistanceOrder(const Unit* Target) : MainTarget(Target) {};
// functor for operator ">"
bool operator()(const Unit* _Left, const Unit* _Right) const
{
return (MainTarget->GetDistance(_Left) < MainTarget->GetDistance(_Right));
}
};
void SKILLS::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
{
float radius;
if (m_SKILLSInfo->EffectRadiusIndex[i])
radius = GetSKILLSRadius(sSKILLSRadiusStore.Lookupid(m_SKILLSInfo->EffectRadiusIndex[i]));
else
radius = GetSKILLSMaxRange(sSKILLSRangeStore.Lookupid(m_SKILLSInfo->rangeIndex));
if(m_originalCaster)
if(Player* modOwner = m_originalCaster->GetSKILLSModOwner())
modOwner->ApplySKILLSMod(m_SKILLSInfo->Id, SKILLSMOD_RADIUS, radius,this);
uint32 unMaxTargets = m_SKILLSInfo->MaxAffectedTargets;
switch(cur)
{
case TARGET_TOTEM_EARTH:
case TARGET_TOTEM_WATER:
case TARGET_TOTEM_AIR:
case TARGET_TOTEM_FIRE:
case TARGET_SELF:
case TARGET_DYNAMIC_OBJECT:
case TARGET_AREAEFFECT_CUSTOM:
case TARGET_AREAEFFECT_CUSTOM_2:
{
TagUnitMap.push_back(m_caster);
break;
}
case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA:
{
m_targets.m_targetMask = 0;
unMaxTargets = m_SKILLSInfo->EffectChainTarget[i];
float max_range = radius + unMaxTargets * CHAIN_SKILLS_JUMP_RADIUS;
CellPair p(VENICE::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
std::list<Unit *> tempUnitMap;
{
VENICE::AnyAoETargetUnitInObjectRangeCheck u_check(m_caster, m_caster, max_range);
VENICE::UnitListSearcher<VENICE::AnyAoETargetUnitInObjectRangeCheck> searcher(tempUnitMap, u_check);
TypeContainerVisitor<VENICE::UnitListSearcher<VENICE::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
TypeContainerVisitor<VENICE::UnitListSearcher<VENICE::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::AREA().GetMap(m_caster->GetMapId(), m_caster));
cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::AREA().GetMap(m_caster->GetMapId(), m_caster));
}
if(tempUnitMap.empty())
break;
tempUnitMap.sort(TargetDistanceOrder(m_caster));
//Now to get us a random target that's in the initial range of the SKILLS
uint32 t = 0;
std::list<Unit *>::iterator itr = tempUnitMap.begin();
while(itr!= tempUnitMap.end() && (*itr)->GetDistanceSq(m_caster) < radius * 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<Unit*>::iterator next = tempUnitMap.begin();
while(t && next != tempUnitMap.end() )
{
if(prev->GetDistanceSq(*next) > CHAIN_SKILLS_JUMP_RADIUS * CHAIN_SKILLS_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();
if (!tmpUnit) break;
TagUnitMap.push_back(tmpUnit);
break;
}
case TARGET_CHAIN_DAMAGE:
{
if (m_SKILLSInfo->EffectChainTarget[i] <= 1)
{
Unit* pUnitTarget = SelectMagnetTarget();
if(pUnitTarget)
TagUnitMap.push_back(pUnitTarget);
}
else
{
Unit* pUnitTarget = m_targets.getUnitTarget();
if(!pUnitTarget)
break;
unMaxTargets = m_SKILLSInfo->EffectChainTarget[i];
float max_range;
if(m_SKILLSInfo->DmgClass==SKILLS_DAMAGE_CLASS_MELEE)
max_range = radius; //
else
//FIXME: This very like horrible hack and wrong for most SKILLSs
max_range = radius + unMaxTargets * CHAIN_SKILLS_JUMP_RADIUS;
CellPair p(VENICE::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
Unit* originalCaster = GetOriginalCaster();
if(originalCaster)
{
std::list<Unit *> tempUnitMap;
{
VENICE::AnyAoETargetUnitInObjectRangeCheck u_check(pUnitTarget, originalCaster, max_range);
VENICE::UnitListSearcher<VENICE::AnyAoETargetUnitInObjectRangeCheck> searcher(tempUnitMap, u_check);
TypeContainerVisitor<VENICE::UnitListSearcher<VENICE::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
TypeContainerVisitor<VENICE::UnitListSearcher<VENICE::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::AREA().GetMap(m_caster->GetMapId(), m_caster));
cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::AREA().GetMap(m_caster->GetMapId(), m_caster));
}
tempUnitMap.sort(TargetDistanceOrder(pUnitTarget));
if(tempUnitMap.empty())
break;
if(*tempUnitMap.begin() == pUnitTarget)
tempUnitMap.erase(tempUnitMap.begin());
TagUnitMap.push_back(pUnitTarget);
uint32 t = unMaxTargets - 1;
Unit *prev = pUnitTarget;
std::list<Unit*>::iterator next = tempUnitMap.begin();
while(t && next != tempUnitMap.end() )
{
if(prev->GetDistanceSq(*next) > CHAIN_SKILLS_JUMP_RADIUS * CHAIN_SKILLS_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_ALL_ENEMY_IN_AREA:
{
}break;
case TARGET_ALL_ENEMY_IN_AREA_INSTANT:
{
// targets the AREA, not the units in the area
if (m_SKILLSInfo->Effect[i]!=SKILLS_EFFECT_PERSISTENT_AREA_AURA)
{
CellPair p(VENICE::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
VENICE::SKILLSNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_DEST_CENTER,SKILLS_TARGETS_AOE_DAMAGE);
TypeContainerVisitor<VENICE::SKILLSNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
TypeContainerVisitor<VENICE::SKILLSNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::AREA().GetMap(m_caster->GetMapId(), m_caster));
cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::AREA().GetMap(m_caster->GetMapId(), m_caster));
// exclude caster (this can be important if this not original caster)
TagUnitMap.remove(m_caster);
}
}break;
case TARGET_ALL_PARTY_AROUND_CASTER:
case TARGET_ALL_PARTY_AROUND_CASTER_2:
case TARGET_ALL_PARTY:
{
Unit* owner = m_caster->GetCharmerOrOwner();
Player *pTarget = NULL;
if(owner)
{
if(owner->GetTypeId() == TYPEID_PLAYER)
pTarget = (Player*)owner;
}
else if (m_caster->GetTypeId() == TYPEID_PLAYER)
pTarget = (Player*)m_caster;
Group *pGroup = pTarget ? pTarget->GetGroup() : NULL;
if(pGroup)
{
uint8 subgroup = pTarget->GetSubGroup();
for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
{
Player* Target = itr->getSource();
// IsHostileTo check duel and controlled by enemy
if( Target && Target->GetSubGroup()==subgroup && !m_caster->IsHostileTo(Target) )
{
if( m_caster->IsWithinDistInMap(Target, radius) )
TagUnitMap.push_back(Target);
if(Pet* pet = Target->GetPet())
if( m_caster->IsWithinDistInMap(pet, radius) )
TagUnitMap.push_back(pet);
}
}
}
else if (owner)
{
if(m_caster->IsWithinDistInMap(owner, radius))
TagUnitMap.push_back(owner);
}
else
TagUnitMap.push_back(m_caster);
}break;
case TARGET_RANDOM_RAID_MEMBER:
{
Player *pTarget = NULL;
if (m_caster->GetTypeId() == TYPEID_PLAYER)
pTarget = (Player*)m_caster;
Group *pGroup = pTarget ? pTarget->GetGroup() : NULL;
if(pGroup)
{
std::vector<Player*> nearMembers;
nearMembers.reserve(pGroup->GetMembersCount());
for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
{
Player* Target = itr->getSource();
// IsHostileTo check duel and controlled by enemy
if( Target && Target != pTarget && m_caster->IsWithinDistInMap(Target, radius) &&
!Target->HasStealthAura() && !Target->HasInvisibilityAura()
&& !m_caster->IsHostileTo(Target) )
nearMembers.push_back(Target);
}
if (!nearMembers.empty())
{
uint32 randTarget = urand(0,nearMembers.size()-1);
TagUnitMap.push_back(nearMembers[randTarget]);
}
}
}break;
case TARGET_SINGLE_FRIEND:
case TARGET_SINGLE_FRIEND_2:
{
if(m_targets.getUnitTarget())
TagUnitMap.push_back(m_targets.getUnitTarget());
}break;
case TARGET_ALL_AROUND_CASTER:
{
CellPair p(VENICE::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
VENICE::SKILLSNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_SELF_CENTER,SKILLS_TARGETS_AOE_DAMAGE);
TypeContainerVisitor<VENICE::SKILLSNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
TypeContainerVisitor<VENICE::SKILLSNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::AREA().GetMap(m_caster->GetMapId(), m_caster));
cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::AREA().GetMap(m_caster->GetMapId(), m_caster));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -