⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skill.cpp.svn-base

📁 絲路server源碼 Silk Road server source
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
        }
};

// 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 + -