Esempio n. 1
0
bool CMobController::CanMoveForward(float currentDistance)
{
    if(PMob->m_Behaviour & BEHAVIOUR_STANDBACK && currentDistance < 20)
    {
        return false;
    }

    if(PMob->getMobMod(MOBMOD_HP_STANDBACK) > 0 && currentDistance < 20 && PMob->GetHPP() >= PMob->getMobMod(MOBMOD_HP_STANDBACK))
    {
        // Excluding Nins, mobs should not standback if can't cast magic
        if (PMob->GetMJob() != JOB_NIN && PMob->SpellContainer->HasSpells() && !CanCastSpells())
        {
            return true;
        }

        return false;
    }

    if(PMob->getMobMod(MOBMOD_SPAWN_LEASH) > 0 && distance(PMob->loc.p, PMob->m_SpawnPoint) > PMob->getMobMod(MOBMOD_SPAWN_LEASH))
    {
        return false;
    }

    return true;
}
Esempio n. 2
0
bool CMobController::TryCastSpell()
{
    if (!CanCastSpells())
    {
        return false;
    }

    int chosenSpellId = -1;
    m_LastMagicTime = m_Tick - std::chrono::milliseconds(dsprand::GetRandomNumber(PMob->getBigMobMod(MOBMOD_MAGIC_COOL) / 2));

    if (PMob->m_HasSpellScript)
    {
        // skip logic and follow script
        chosenSpellId = luautils::OnMonsterMagicPrepare(PMob, PTarget);
        if (chosenSpellId > -1)
        {
            CastSpell(chosenSpellId);
            return true;
        }
    }
    else
    {
        // find random spell

        if (m_firstSpell)
        {
            // mobs first spell, should be aggro spell
            chosenSpellId = PMob->SpellContainer->GetAggroSpell();
            m_firstSpell = false;
        }
        else
        {
            chosenSpellId = PMob->SpellContainer->GetSpell();
        }

        if (chosenSpellId > -1)
        {
            //#TODO: select target based on spell type
            CastSpell(chosenSpellId);
            return true;
        }
    }
    return false;
}
Esempio n. 3
0
bool CAIController::TryCastSpell()
{
    if (!CanCastSpells())
    {
        return false;
    }

    int chosenSpellId = -1;
    m_LastMagicTime = m_Tick;

    if (PMob->m_HasSpellScript)
    {
        // skip logic and follow script
        chosenSpellId = luautils::OnMonsterMagicPrepare(PMob, PTarget);
        if (chosenSpellId > -1)
        {
            CastSpell(chosenSpellId);
            return true;
        }
    }
    else
    {
        // find random spell

        if (m_firstSpell)
        {
            // mobs first spell, should be aggro spell
            chosenSpellId = PMob->SpellContainer->GetAggroSpell();
            m_firstSpell = false;
        }
        else
        {
            chosenSpellId = PMob->SpellContainer->GetSpell();
        }

        if (chosenSpellId > -1)
        {
            //#TODO: select target based on spell type
            CastSpell(chosenSpellId);
            return true;
        }
    }
    return false;
}
Esempio n. 4
0
void CMobController::DoRoamTick(time_point tick)
{
    // If there's someone on our enmity list, go from roaming -> engaging
    if (PMob->PEnmityContainer->GetHighestEnmity() != nullptr && !(PMob->m_roamFlags & ROAMFLAG_IGNORE))
    {
        Engage(PMob->PEnmityContainer->GetHighestEnmity()->targid);
        return;
    }
    else if (PMob->m_OwnerID.id != 0 && !(PMob->m_roamFlags & ROAMFLAG_IGNORE))
    {
        // i'm claimed by someone and need hate towards this person
        PTarget = (CBattleEntity*)PMob->GetEntity(PMob->m_OwnerID.targid, TYPE_PC | TYPE_MOB | TYPE_PET);

        battleutils::ClaimMob(PMob, PTarget);

        Engage(PTarget->targid);
        return;
    }
    //#TODO
    else if (PMob->GetDespawnTime() > time_point::min() && PMob->GetDespawnTime() < m_Tick)
    {
        Despawn();
        return;
    }

    if (PMob->m_roamFlags & ROAMFLAG_IGNORE)
    {
        // don't claim me if I ignore
        PMob->m_OwnerID.clean();
    }

    //skip roaming if waiting
    if (m_Tick >= m_WaitTime)
    {
        // don't aggro a little bit after I just disengaged
        PMob->m_neutral = PMob->CanBeNeutral() && m_Tick <= m_NeutralTime + 10s;

        if (PMob->PAI->PathFind->IsFollowingPath())
        {
            FollowRoamPath();
        }
        else if (m_Tick >= m_LastActionTime + std::chrono::milliseconds(PMob->getBigMobMod(MOBMOD_ROAM_COOL)))
        {
            // lets buff up or move around

            if (PMob->CalledForHelp())
            {
                PMob->CallForHelp(false);
            }

            // can't rest with poison or disease
            if (PMob->CanRest())
            {
                // recover 10% health
                if (PMob->Rest(0.1f))
                {
                    // health updated
                    PMob->updatemask |= UPDATE_HP;
                }

                if (PMob->GetHPP() == 100)
                {
                    // at max health undirty exp
                    PMob->m_giveExp = true;
                }
            }

            // if I just disengaged check if I should despawn
            if (PMob->IsFarFromHome())
            {
                if (PMob->CanRoamHome() && PMob->PAI->PathFind->PathTo(PMob->m_SpawnPoint))
                {
                    // walk back to spawn if too far away

                    // limit total path to just 10 or
                    // else we'll move straight back to spawn
                    PMob->PAI->PathFind->LimitDistance(10.0f);

                    FollowRoamPath();

                    // move back every 5 seconds
                    m_LastActionTime = m_Tick - (std::chrono::milliseconds(PMob->getBigMobMod(MOBMOD_ROAM_COOL)) + 10s);
                }
                else if (!PMob->getMobMod(MOBMOD_NO_DESPAWN) != 0 &&
                    !map_config.mob_no_despawn)
                {
                    PMob->PAI->Despawn();
                    return;
                }
            }
            else
            {
                if (PMob->getMobMod(MOBMOD_SPECIAL_SKILL) != 0 &&
                    m_Tick >= m_LastSpecialTime + std::chrono::milliseconds(PMob->getBigMobMod(MOBMOD_SPECIAL_COOL)) &&
                    TrySpecialSkill())
                {
                    // I spawned a pet
                }
                else if (PMob->GetMJob() == JOB_SMN && CanCastSpells() && PMob->SpellContainer->HasBuffSpells() &&
                    m_Tick >= m_LastMagicTime + std::chrono::milliseconds(PMob->getBigMobMod(MOBMOD_MAGIC_COOL)))
                {
                    // summon pet
                    CastSpell(PMob->SpellContainer->GetBuffSpell());
                }
                else if (CanCastSpells() && dsprand::GetRandomNumber(10) < 3 && PMob->SpellContainer->HasBuffSpells())
                {
                    // cast buff
                    CastSpell(PMob->SpellContainer->GetBuffSpell());
                }
                else if ((PMob->m_roamFlags & ROAMFLAG_AMBUSH))
                {
                    //#TODO: #AIToScript move to scripts
                    // stay underground
                    PMob->HideName(true);
                    PMob->HideModel(true);
                    PMob->animationsub = 0;

                    PMob->updatemask |= UPDATE_HP;
                }
                else if ((PMob->m_roamFlags & ROAMFLAG_STEALTH))
                {
                    // hidden name
                    PMob->HideName(true);
                    PMob->Untargetable(true);

                    PMob->updatemask |= UPDATE_HP;
                }
                else if (PMob->m_roamFlags & ROAMFLAG_EVENT)
                {
                    // allow custom event action
                    luautils::OnMobRoamAction(PMob);
                    m_LastActionTime = m_Tick;
                }
                else if (PMob->CanRoam() && PMob->PAI->PathFind->RoamAround(PMob->m_SpawnPoint, PMob->GetRoamDistance(), PMob->getMobMod(MOBMOD_ROAM_TURNS), PMob->m_roamFlags))
                {
                    //#TODO: #AIToScript (event probably)
                    if (PMob->m_roamFlags & ROAMFLAG_WORM)
                    {
                        // move down
                        PMob->animationsub = 1;
                        PMob->HideName(true);

                        // don't move around until i'm fully in the ground
                        Wait(2s);
                    }
                    else
                    {
                        FollowRoamPath();
                    }
                }
                else
                {
                    m_LastActionTime = m_Tick;
                }
            }
        }
    }
    if (m_Tick >= m_LastRoamScript + 3s)
    {
        luautils::OnMobRoam(PMob);
        m_LastRoamScript = m_Tick;
    }
}
bool CAutomatonController::TrySpellcast(const CurrentManeuvers& maneuvers)
{
    if (!PAutomaton->PMaster || m_magicCooldown == 0s ||
        m_Tick <= m_LastMagicTime + (m_magicCooldown - std::chrono::seconds(PAutomaton->getMod(Mod::AUTO_MAGIC_DELAY))) || !CanCastSpells())
        return false;

    switch (PAutomaton->getHead())
    {
    case HEAD_VALOREDGE:
    {
        if (TryHeal(maneuvers))
        {
            m_LastHealTime = m_Tick;
            return true;
        }
    }
    break;
    case HEAD_SHARPSHOT:
    {
        if (maneuvers.light && TryHeal(maneuvers)) // Light -> Heal
        {
            m_LastHealTime = m_Tick;
            return true;
        }

        if (TryEnfeeble(maneuvers))
        {
            m_LastEnfeebleTime = m_Tick;
            return true;
        }
        else if (!maneuvers.light && TryHeal(maneuvers))
        {
            m_LastHealTime = m_Tick;
            return true;
        }
    }
    break;
    case HEAD_HARLEQUIN:
    {
        if (maneuvers.light && TryHeal(maneuvers)) // Light -> Heal
        {
            m_LastHealTime = m_Tick;
            return true;
        }

        if (TryEnfeeble(maneuvers))
        {
            m_LastEnfeebleTime = m_Tick;
            return true;
        }
        else if (!maneuvers.light && TryHeal(maneuvers))
        {
            m_LastHealTime = m_Tick;
            return true;
        }
    }
    break;
    case HEAD_STORMWAKER:
    {
        bool lowHP = PTarget->GetHPP() <= 30 && PTarget->health.hp <= 300;
        if (lowHP && TryElemental(maneuvers))  // Mob low HP -> Nuke
        {
            m_LastElementalTime = m_Tick;
            return true;
        }

        if (maneuvers.light && TryHeal(maneuvers)) // Light -> Heal
        {
            m_LastHealTime = m_Tick;
            return true;
        }
        else if (!lowHP && maneuvers.ice && TryElemental(maneuvers))  // Ice -> Nuke
        {
            m_LastElementalTime = m_Tick;
            return true;
        }

        if (TryEnfeeble(maneuvers))
        {
            m_LastEnfeebleTime = m_Tick;
            return true;
        }
        else if (!maneuvers.light && TryHeal(maneuvers))
        {
            m_LastHealTime = m_Tick;
            return true;
        }
        else if (!lowHP && !maneuvers.ice && TryElemental(maneuvers))
        {
            m_LastElementalTime = m_Tick;
            return true;
        }
        else if (TryEnhance())
        {
            m_LastEnhanceTime = m_Tick;
            return true;
        }
    }
    break;
    case HEAD_SOULSOOTHER:
    {
        if (maneuvers.light && TryHeal(maneuvers)) // Light -> Heal
        {
            m_LastHealTime = m_Tick;
            return true;
        }

        if (TryStatusRemoval(maneuvers))
        {
            m_LastStatusTime = m_Tick;
            return true;
        }
        else if (!maneuvers.light && TryHeal(maneuvers))
        {
            m_LastHealTime = m_Tick;
            return true;
        }
        else if (TryEnhance())
        {
            m_LastEnhanceTime = m_Tick;
            return true;
        }
        else if (TryEnfeeble(maneuvers))
        {
            m_LastEnfeebleTime = m_Tick;
            return true;
        }
    }
    break;
    case HEAD_SPIRITREAVER:
    {
        if (maneuvers.ice && TryElemental(maneuvers))  // Ice -> Nuke
        {
            m_LastElementalTime = m_Tick;
            return true;
        }
        else if (maneuvers.dark && TryEnhance())
        {
            m_LastEnhanceTime = m_Tick;
            return true;
        }
        else if ((maneuvers.dark || PAutomaton->GetHPP() <= 75 || PAutomaton->GetMPP() <= 75) && TryEnfeeble(maneuvers)) // Dark or self HPP/MPP <= 75 -> Enfeeble
        {
            m_LastEnfeebleTime = m_Tick;
            return true;
        }

        if (!maneuvers.ice && TryElemental(maneuvers))
        {
            m_LastElementalTime = m_Tick;
            return true;
        }
    }
    }
    return false;
}