コード例 #1
0
ファイル: targetfind.cpp プロジェクト: Apocalypse612/darkstar
void CTargetFind::addAllInEnmityList()
{
    if (m_PBattleEntity->objtype == TYPE_MOB)
    {
        CMobEntity* mob = (CMobEntity*)m_PBattleEntity;
        EnmityList_t* enmityList = mob->PEnmityContainer->GetEnmityList();

        for (EnmityList_t::iterator it = enmityList->begin(); it != enmityList->end(); ++it)
        {
            EnmityObject_t* PEnmityObject = it->second;
            addEntity(PEnmityObject->PEnmityOwner, false);
        }
    }
}
コード例 #2
0
bool CAutomatonController::TryEnhance()
{
    if (!PAutomaton->PMaster || m_enhanceCooldown == 0s || m_Tick <= m_LastEnhanceTime + m_enhanceCooldown)
        return false;

    if (PAutomaton->getHead() == HEAD_SPIRITREAVER)
        return Cast(PAutomaton->targid, SpellID::Dread_Spikes);

    EnmityList_t* enmityList;
    auto PMob = dynamic_cast<CMobEntity*>(PTarget);
    if (PMob)
        enmityList = PMob->PEnmityContainer->GetEnmityList();

    uint16 highestEnmity = 0;

    CBattleEntity* PRegenTarget = nullptr;
    CBattleEntity* PProtectTarget = nullptr;
    CBattleEntity* PShellTarget = nullptr;
    CBattleEntity* PHasteTarget = nullptr;
    CBattleEntity* PStoneSkinTarget = nullptr;
    CBattleEntity* PPhalanxTarget = nullptr;

    bool protect = false;
    uint8 protectcount = 0;
    bool shell = false;
    uint8 shellcount = 0;
    bool haste = false;
    bool stoneskin = false;
    bool phalanx = false;

    bool isEngaged = false;

    if (distance(PAutomaton->loc.p, PAutomaton->PMaster->loc.p) < 20)
    {
        if (PMob)
        {
            auto enmity_obj = enmityList->find(PAutomaton->PMaster->id);
            if (enmity_obj != enmityList->end())
            {
                isEngaged = true;
                if (highestEnmity < enmity_obj->second.CE + enmity_obj->second.VE)
                {
                    highestEnmity = enmity_obj->second.CE + enmity_obj->second.VE;
                    PRegenTarget = PAutomaton->PMaster;
                }
            }
        }
        else
        {
            isEngaged = true; // Assume everyone is engaged if the target isn't a mob
        }

        PAutomaton->PMaster->StatusEffectContainer->ForEachEffect([&protect, &protectcount, &shell, &shellcount, &haste, &stoneskin, &phalanx](CStatusEffect* PStatus)
        {
            if (PStatus->GetDuration() > 0)
            {
                if (PStatus->GetStatusID() == EFFECT_PROTECT)
                {
                    protect = true;
                    ++protectcount;
                }

                if (PStatus->GetStatusID() == EFFECT_SHELL)
                {
                    shell = true;
                    ++shellcount;
                }

                if (PStatus->GetStatusID() == EFFECT_HASTE || PStatus->GetStatusID() == EFFECT_HASTE_II)
                    haste = true;

                if (PStatus->GetStatusID() == EFFECT_STONESKIN)
                    stoneskin = true;

                if (PStatus->GetStatusID() == EFFECT_PHALANX)
                    phalanx = true;
            }
        });

        if (isEngaged) {
            if (!protect)
                PProtectTarget = PAutomaton->PMaster;

            if (!shell)
                PShellTarget = PAutomaton->PMaster;

            if (!haste)
                PHasteTarget = PAutomaton->PMaster;

            if (!stoneskin)
                PStoneSkinTarget = PAutomaton->PMaster;

            if (!phalanx)
                PPhalanxTarget = PAutomaton->PMaster;
        }
    }

    protect = false;
    shell = false;
    haste = false;
    stoneskin = false;
    phalanx = false;

    if (PMob)
    {
        auto enmity_obj = enmityList->find(PAutomaton->id);
        if (enmity_obj != enmityList->end() && highestEnmity < enmity_obj->second.CE + enmity_obj->second.VE)
        {
            highestEnmity = enmity_obj->second.CE + enmity_obj->second.VE;
            PRegenTarget = PAutomaton;
        }
    }

    PAutomaton->StatusEffectContainer->ForEachEffect([&protect, &shell, &haste, &stoneskin, &phalanx](CStatusEffect* PStatus)
    {
        if (PStatus->GetDuration() > 0)
        {
            if (PStatus->GetStatusID() == EFFECT_PROTECT)
                protect = true;

            if (PStatus->GetStatusID() == EFFECT_SHELL)
                shell = true;

            if (PStatus->GetStatusID() == EFFECT_HASTE || PStatus->GetStatusID() == EFFECT_HASTE_II)
                haste = true;
        }
    });

    if (!PProtectTarget && !protect)
        PProtectTarget = PAutomaton;

    if (!PShellTarget && !shell)
        PShellTarget = PAutomaton;

    if (!PHasteTarget && !haste)
        PHasteTarget = PAutomaton;

    uint8 members = 0;

    // Unknown whether it only applies buffs to other members if they have hate or if the Soulsoother head is needed
    if (PAutomaton->PMaster->PParty)
    {
        members = PAutomaton->PMaster->PParty->members.size();
        for (uint8 i = 0; i < members; ++i)
        {
            CBattleEntity* member = PAutomaton->PMaster->PParty->members.at(i);
            if (member->id != PAutomaton->PMaster->id && distance(PAutomaton->loc.p, member->loc.p) < 20)
            {
                protect = false;
                shell = false;
                haste = false;

                isEngaged = false;

                if (PMob)
                {
                    auto enmity_obj = enmityList->find(member->id);
                    if (enmity_obj != enmityList->end())
                    {
                        isEngaged = true;
                        if (highestEnmity < enmity_obj->second.CE + enmity_obj->second.VE)
                        {
                            highestEnmity = enmity_obj->second.CE + enmity_obj->second.VE;
                            PRegenTarget = member;
                        }
                    }
                }
                else
                {
                    isEngaged = true; // Assume everyone is engaged if the target isn't a mob
                }

                member->StatusEffectContainer->ForEachEffect([&protect, &protectcount, &shell, &shellcount, &haste](CStatusEffect* PStatus)
                {
                    if (PStatus->GetDuration() > 0)
                    {
                        if (PStatus->GetStatusID() == EFFECT_PROTECT)
                        {
                            protect = true;
                            ++protectcount;
                        }

                        if (PStatus->GetStatusID() == EFFECT_SHELL)
                        {
                            shell = true;
                            ++shellcount;
                        }

                        if (PStatus->GetStatusID() == EFFECT_HASTE || PStatus->GetStatusID() == EFFECT_HASTE_II)
                            haste = true;
                    }
                });

                if (isEngaged)
                {
                    if (!PProtectTarget && !protect)
                        PProtectTarget = member;

                    if (!PShellTarget && !shell)
                        PShellTarget = member;

                    if (!PHasteTarget && !haste)
                        PHasteTarget = member;
                }
            }
        }
    }

    // No info on how this spell worked
    if((members - protectcount) >= 4)
        Cast(PAutomaton->targid, SpellID::Protectra_V);

    // No info on how this spell worked
    if ((members - shellcount) >= 4)
        Cast(PAutomaton->targid, SpellID::Shellra_V);

    if (PRegenTarget && (PTarget->GetMLevel() + 5) >= PAutomaton->GetMLevel() && !(PRegenTarget->StatusEffectContainer->HasStatusEffect(EFFECT_REGEN) ||
        PRegenTarget->StatusEffectContainer->HasStatusEffect(EFFECT_REGEN_II)))
        if (Cast(PRegenTarget->targid, SpellID::Regen_III) ||
            Cast(PRegenTarget->targid, SpellID::Regen_II) ||
            Cast(PRegenTarget->targid, SpellID::Regen))
            return true;

    if (PProtectTarget)
        if (Cast(PProtectTarget->targid, SpellID::Protect_V) ||
            Cast(PProtectTarget->targid, SpellID::Protect_IV) ||
            Cast(PProtectTarget->targid, SpellID::Protect_III) ||
            Cast(PProtectTarget->targid, SpellID::Protect_II) ||
            Cast(PProtectTarget->targid, SpellID::Protect))
            return true;

    if (PShellTarget)
        if (Cast(PShellTarget->targid, SpellID::Shell_V) ||
            Cast(PShellTarget->targid, SpellID::Shell_IV) ||
            Cast(PShellTarget->targid, SpellID::Shell_III) ||
            Cast(PShellTarget->targid, SpellID::Shell_II) ||
            Cast(PShellTarget->targid, SpellID::Shell))
            return true;

    if (PHasteTarget)
        if (Cast(PHasteTarget->targid, SpellID::Haste_II) || Cast(PHasteTarget->targid, SpellID::Haste))
            return true;

    if (PStoneSkinTarget)
        if (Cast(PStoneSkinTarget->targid, SpellID::Stoneskin))
            return true;

    if (PPhalanxTarget)
        if (Cast(PPhalanxTarget->targid, SpellID::Phalanx))
            return true;

    return false;
}
コード例 #3
0
bool CAutomatonController::TryHeal(const CurrentManeuvers& maneuvers)
{
    if (!PAutomaton->PMaster || m_healCooldown == 0s || m_Tick <= m_LastHealTime + (m_healCooldown - std::chrono::seconds(PAutomaton->getMod(Mod::AUTO_HEALING_DELAY))))
        return false;

    float threshold = 0;
    switch (maneuvers.light) // Light -> Higher healing threshold
    {
    case 1:
        threshold = 40;
        break;
    case 2:
        threshold = 50;
        break;
    case 3:
        threshold = 75;
        break;
    default:
        threshold = 30;
        break;
    }

    threshold = dsp_cap(threshold + PAutomaton->getMod(Mod::AUTO_HEALING_THRESHOLD), 30, 90);
    CBattleEntity* PCastTarget = nullptr;

    bool haveHate = false;
    EnmityList_t* enmityList;

    auto PMob = dynamic_cast<CMobEntity*>(PTarget);
    if (PMob)
    {
        enmityList = PMob->PEnmityContainer->GetEnmityList();
        auto masterEnmity_obj = enmityList->find(PAutomaton->PMaster->id);
        auto selfEnmity_obj = enmityList->find(PAutomaton->id);

        if (masterEnmity_obj == enmityList->end())
            haveHate = true;
        else if (selfEnmity_obj == enmityList->end())
            haveHate = false;
        else
        {
            uint16 selfEnmity = selfEnmity_obj->second.CE + selfEnmity_obj->second.VE;
            uint16 masterEnmity = masterEnmity_obj->second.CE + masterEnmity_obj->second.VE;
            haveHate = selfEnmity > masterEnmity ? true : false;
        }
    }
    
    // Prioritize hate
    if (haveHate)
    {
        if (PAutomaton->GetHPP() <= 50) // Automaton only heals itself when <= 50%
            PCastTarget = PAutomaton;
        else if (PAutomaton->PMaster->GetHPP() <= threshold && distance(PAutomaton->loc.p, PAutomaton->PMaster->loc.p) < 20)
            PCastTarget = PAutomaton->PMaster;
    }
    else
    {
        if (PAutomaton->PMaster->GetHPP() <= threshold)
            PCastTarget = PAutomaton->PMaster;
        else if (PAutomaton->GetHPP() <= 50) // Automaton only heals itself when <= 50%
            PCastTarget = PAutomaton;
    }

    if (maneuvers.light && !PCastTarget && PAutomaton->getHead() == HEAD_SOULSOOTHER && PAutomaton->PMaster->PParty) // Light + Soulsoother head -> Heal party
    {
        if (PMob)
        {
            uint16 highestEnmity = 0;
            for (uint8 i = 0; i < PAutomaton->PMaster->PParty->members.size(); ++i)
            {
                CBattleEntity* member = PAutomaton->PMaster->PParty->members.at(i);
                if (member->id != PAutomaton->PMaster->id)
                {
                    auto enmity_obj = enmityList->find(member->id);
                    if (enmity_obj != enmityList->end() && highestEnmity < enmity_obj->second.CE + enmity_obj->second.VE &&
                        member->GetHPP() <= threshold && distance(PAutomaton->loc.p, PAutomaton->PMaster->loc.p) < 20)
                    {
                        highestEnmity = enmity_obj->second.CE + enmity_obj->second.VE;
                        PCastTarget = member;
                    }
                }
            }
        }
        else
        {
            for (uint8 i = 0; i < PAutomaton->PMaster->PParty->members.size(); ++i)
            {
                CBattleEntity* member = PAutomaton->PMaster->PParty->members.at(i);
                if (member->id != PAutomaton->PMaster->id && distance(PAutomaton->loc.p, PAutomaton->PMaster->loc.p) < 20)
                {
                    if (member->GetHPP() <= threshold)
                    {
                        PCastTarget = member;
                        break;
                    }
                }
            }
        }
    }

    // This might be wrong
    if (PCastTarget)
    {
        float missinghp = PCastTarget->GetMaxHP() - PCastTarget->health.hp;
        if (missinghp > 850 && Cast(PCastTarget->targid, SpellID::Cure_VI ))
            return true;
        else if (missinghp > 600 && Cast(PCastTarget->targid, SpellID::Cure_V))
            return true;
        else if (missinghp > 350 && Cast(PCastTarget->targid, SpellID::Cure_IV))
            return true;
        else if (missinghp > 190 && Cast(PCastTarget->targid, SpellID::Cure_III))
            return true;
        else if (missinghp > 120 && Cast(PCastTarget->targid, SpellID::Cure_II))
            return true;
        else if (Cast(PCastTarget->targid, SpellID::Cure))
            return true;
    }

    return false;
}