Пример #1
0
void PetAI::_AttackStart(Unit* target)
{
    // Check all pet states to decide if we can attack this target
    if (!CanAttack(target))
        return;

    // Only chase if not commanded to stay or if stay but commanded to attack
    DoAttack(target, (!me->GetCharmInfo()->HasCommandState(COMMAND_STAY) || me->GetCharmInfo()->IsCommandAttack()));
}
Пример #2
0
        void UpdateAI(uint32 diff) override
        {
            DoAttack();

            if (!UpdateVictim())
               return;

            DoMeleeAttackIfReady();
        }
Пример #3
0
void CStateMachinen::Update(CMonster& monster, eStateEvent evt)
{
	switch(monster.mStateParamter.stateCur)
	{
	case eMA_STAND:
		{
			DoStand(
				monster,
				evt);
			break;
		}
	case eMA_WALKAROUND:
		{
			DoWalkAround(
				monster,
				evt);
			break;
		}
	case eMA_PERSUIT:
		{
			DoPursuit(
				monster,
				evt);
			break;
		}
	case eMA_WALKAWAY:
	case eMA_RUNAWAY:
		{
			DoRunAway(
				monster,
				evt);
			break;
		}
	case eMA_ATTACK:
		{
			DoAttack(
				monster,
				evt);
			break;
		}
	case eMA_SCRIPT_RUN:
	case eMA_SCRIPT_WALK:
		{
			DoScriptMove(
				monster,
				evt);
			break;
		}
	case eMA_PAUSE:
		{
			DoPause(
				monster,
				evt);
			break;
		}
	}
}
Пример #4
0
void PetAI::AttackStart(Unit *target)
{
    // Overrides Unit::AttackStart to correctly evaluate Pet states

    // Check all pet states to decide if we can attack this target
    if (!_CanAttack(target))
        return;

    // We can attack, should we chase or not?
    if (me->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
        DoAttack(target,true); // FOLLOW, attack with chase
    else
    {
        if (me->GetCharmInfo()->IsCommandAttack())
            DoAttack(target,true); // STAY or FOLLOW, player clicked "attack" so attack with chase
        else
            DoAttack(target,false); // STAY, target in range, attack not clicked so attack without chase
    }
}
Пример #5
0
void PetAI::AttackStart(Unit* target)
{
    // Overrides Unit::AttackStart to correctly evaluate Pet states

    // Check all pet states to decide if we can attack this target
    if (!CanAttack(target))
        return;

    // Only chase if not commanded to stay or if stay but commanded to attack
    DoAttack(target, ((!me->GetCharmInfo()->HasCommandState(COMMAND_STAY) && !me->GetCharmInfo()->HasCommandState(COMMAND_MOVE_TO)) || me->GetCharmInfo()->IsCommandAttack()));
}
Пример #6
0
void PetAI::AttackStart(Unit *target) {
	// Overrides Unit::AttackStart to correctly evaluate Pet states

	// Check all pet states to decide if we can attack this target
	if (!_CanAttack(target))
		return;

	targetHasCC = _CheckTargetCC(target);

	DoAttack(target, true);
}
Пример #7
0
void PetAI::AttackStart(Unit* target)
{
    // Overrides Unit::AttackStart to correctly evaluate Pet states

    // Check all pet states to decide if we can attack this target
    if (!CanAttack(target))
        return;

    if (Unit* owner = me->GetOwner())
        owner->SetInCombatWith(target);

    DoAttack(target, true);
}
Пример #8
0
void PetAI::AttackStart(Unit* target)
{
    // Overrides Unit::AttackStart to correctly evaluate Pet states

    // Check all pet states to decide if we can attack this target
    if (!CanAttack(target))
        return;

    if (Unit* owner = me->GetCharmerOrOwner())
        owner->RemoveAurasByType(SPELL_AURA_MOD_CAMOUFLAGE);

    // Only chase if not commanded to stay or if stay but commanded to attack
    DoAttack(target, (!me->GetCharmInfo()->HasCommandState(COMMAND_STAY) || me->GetCharmInfo()->IsCommandAttack()));
}
Пример #9
0
void CAICharCharm::ActionAttack()
{
    SetBattleTarget(m_PChar->PMaster->PBattleAI->GetBattleTarget());

    if (m_PBattleTarget == nullptr)
    {
        m_ActionType = ACTION_DISENGAGE;
        ActionDisengage();
        return;
    }

    m_PPathFind->LookAt(m_PBattleTarget->loc.p);

    float currentDistance = distance(m_PChar->loc.p, m_PBattleTarget->loc.p);

    if (currentDistance > m_PBattleTarget->m_ModelSize)
    {
        if (m_PChar->speed != 0)
        {
            m_PPathFind->PathAround(m_PBattleTarget->loc.p, 2.0f, PATHFLAG_WALLHACK | PATHFLAG_RUN);
            // m_PPathFind->CurvePath(0.5f);
            m_PPathFind->FollowPath();

            // recalculate
            currentDistance = distance(m_PChar->loc.p, m_PBattleTarget->loc.p);
        }
    }

    uint16 WeaponDelay = m_PChar->GetWeaponDelay(false);

    if (m_Tick > m_LastMeleeTime + WeaponDelay)
    {
        if (currentDistance < m_PBattleTarget->m_ModelSize)
        {
            m_LastMeleeTime = m_Tick;
            if (battleutils::IsParalyzed(m_PChar))
            {
                m_PChar->loc.zone->PushPacket(m_PChar, CHAR_INRANGE_SELF, new CMessageBasicPacket(m_PChar, m_PBattleTarget, 0, 0, MSGBASIC_IS_PARALYZED));
            }
            else if (battleutils::IsIntimidated(m_PChar, m_PBattleTarget))
            {
                m_PChar->loc.zone->PushPacket(m_PChar, CHAR_INRANGE_SELF, new CMessageBasicPacket(m_PChar, m_PBattleTarget, 0, 0, MSGBASIC_IS_INTIMIDATED));
            }
            else
            {
                DoAttack();
            }
        }
    }
}
Пример #10
0
void PetAI::AttackStart(Unit* target)
{
    if (me->GetCharmInfo() == NULL) return;
    // Overrides Unit::AttackStart to correctly evaluate Pet states

    // Check all pet states to decide if we can attack this target
    if (!_CanAttack(target))
        return;

    targetHasCC = _CheckTargetCC(target);

    if (Unit* owner = me->GetOwner())
        owner->SetInCombatWith(target);

    DoAttack(target, true);
}
Пример #11
0
    void UpdateAI(const uint32 diff)
    {
        if (!m_pInstance)
            return;
        //Bomb_Timer
        if (Bomb_Timer < diff)
            Bomb_Timer = 0;
        else
            Bomb_Timer -= diff;

        switch (m_pInstance->GetData(TYPE_JEKLIK))
        {
            case IN_PROGRESS:
                DoAttack();
                break;
            default:
                m_creature->AddObjectToRemoveList();
                break;
        }
    }
Пример #12
0
void PetAI::UpdateAI(const uint32 diff)
{
    if (!m_creature->isAlive() || !m_creature->GetCharmInfo())
        return;

    Unit* owner = m_creature->GetCharmerOrOwner();

    if (m_updateAlliesTimer <= diff)
        // UpdateAllies self set update timer
        UpdateAllies();
    else
        m_updateAlliesTimer -= diff;

    // First checking if we have some taunt on us
    Unit* tauntTarget = NULL;
    const Unit::AuraList& tauntAuras = m_creature->GetAurasByType(SPELL_AURA_MOD_TAUNT);
    if (!tauntAuras.empty())
    {
        Unit* caster = NULL;

        // Auras are pushed_back, last caster will be on the end
        Unit::AuraList::const_iterator aura = tauntAuras.end();
        while (aura != tauntAuras.begin())
        {
            --aura;
            caster = (*aura)->GetCaster();
            if (caster && caster->isTargetableForAttack())
            {
                tauntTarget = caster;
                break;
            }
        }

        if (tauntTarget)
            DoAttack(tauntTarget, true);
    }

    if (m_creature->getVictim() && m_creature->getVictim()->isAlive())
    {
        
        if (_needToStop())
        {
            _stopAttack();
            return;
        }

        if (hasMelee)
        {
            // Check before attacking to prevent pets from leaving stay position
            bool attacked = false;
            if (m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY))
            {
                if (m_creature->GetCharmInfo()->IsCommandAttack() || (m_creature->GetCharmInfo()->IsAtStay() && m_creature->CanReachWithMeleeAttack(m_creature->getVictim())))
                    attacked = DoMeleeAttackIfReady();
            }
            else
                attacked = DoMeleeAttackIfReady();

            if (attacked && owner)
                if (Unit* v = m_creature->getVictim()) // Victim may have died between
                    owner->SetInCombatWith(v);
        }
    }
    else
    {
        if (m_creature->HasReactState(REACT_AGGRESSIVE) || m_creature->GetCharmInfo()->IsAtStay())
        {
            // Every update we need to check targets only in certain cases
            // Aggressive - Allow auto select if owner or pet don't have a target
            // Stay - Only pick from pet or owner targets / attackers so targets won't run by
            //   while chasing our owner. Don't do auto select.
            // All other cases (ie: defensive) - Targets are assigned by AttackedBy(), OwnerAttackedBy(), OwnerAttacked(), etc.
            Unit* nextTarget = SelectNextTarget(m_creature->HasReactState(REACT_AGGRESSIVE));

            if (nextTarget)
                AttackStart(nextTarget);
            else
                HandleReturnMovement();
        }
        else
            HandleReturnMovement();
    }

    // Autocast (casted only in combat or persistent spells in any state)
    if (!m_creature->IsNonMeleeSpellCasted(false))
    {
        typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
        TargetSpellList targetSpellStore;

        for (uint8 i = 0; i < m_creature->GetPetAutoSpellSize(); ++i)
        {
            uint32 spellID = m_creature->GetPetAutoSpellOnPos(i);
            if (!spellID)
                continue;

            SpellEntry const *spellInfo = sSpellMgr.GetSpellEntry(spellID);
            if (!spellInfo)
                continue;

            if (m_creature->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
                continue;

            // check spell cooldown
            if (m_creature->HasSpellCooldown(spellInfo->Id))
                continue;

            if (IsPositiveSpell(spellInfo->Id))
            {
                if (!IsNonCombatSpell(spellInfo)) // Can be used in combat.
                {
                    /*
                    Spells handled here:
                        Dash (1850), Dive (23145), Furious Howl (24604), Tainted Blood (19478)
                        Blood Pact (6307), Fire Shield (11771), Sacrifice ...
                        Consume Shadows (17767)
                    */

                    // Warlock Sacrifice: do not auto cast if not in combat
                    bool castOnlyInCombat = IsSpellHaveEffect(spellInfo, SPELL_EFFECT_INSTAKILL);

                    if (!castOnlyInCombat)
                    {
                        int32 duration = GetSpellDuration(spellInfo);
                        int32 cooldown = GetSpellRecoveryTime(spellInfo);
                        // Keep this spell for when we will be in combat.
                        if (cooldown >= 0 && duration >= 0 && cooldown > duration)
                            castOnlyInCombat = true;
                    }
                    // 19478 - Tainted Blood, rank 1 enUS
                    if (spellInfo->SpellIconID == 153)
                        castOnlyInCombat = true;
                    // 2947 - Fire Shield, rank 1 enUS
                    // When set to auto-cast, the Imp will cast this on any party members within 30 yds if they receive a melee attack.
                    if (spellInfo->IsFitToFamily<SPELLFAMILY_WARLOCK, CF_WARLOCK_IMP_BUFFS>() && spellInfo->SpellVisual == 289)
                        castOnlyInCombat = false;
                    // Furious Howl: in combat only
                    if (IsSpellHaveAura(spellInfo, SPELL_AURA_MOD_DAMAGE_DONE))
                        castOnlyInCombat = true;
                    if (castOnlyInCombat && !m_creature->getVictim())
                        continue;
                }

                Spell *spell = new Spell(m_creature, spellInfo, false);
                bool spellUsed = false;

                // Some spells can target enemy or friendly (DK Ghoul's Leap)
                // Check for enemy first (pet then owner)
                Unit* target = m_creature->getAttackerForHelper();
                if (!target && owner)
                    target = owner->getAttackerForHelper();

                if (target)
                {
                    if (CanAttack(target) && spell->CanAutoCast(target))
                    {
                        targetSpellStore.push_back(std::make_pair(target, spell));
                        spellUsed = true;
                    }
                }

                // No enemy, check friendly
                if (!spellUsed)
                {
                    for (std::set<uint64>::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
                    {
                        Unit* ally = m_creature->GetMap()->GetUnit(*tar);

                        //only buff targets that are in combat, unless the spell can only be cast while out of combat
                        if (!ally)
                            continue;

                        if (spell->CanAutoCast(ally))
                        {
                            targetSpellStore.push_back(std::make_pair(ally, spell));
                            spellUsed = true;
                            break;
                        }
                    }
                }

                // No valid targets at all
                if (!spellUsed)
                    spell->Delete();
            }
            else if (m_creature->getVictim() && CanAttack(m_creature->getVictim()) && !IsNonCombatSpell(spellInfo))
            {
                Spell *spell = new Spell(m_creature, spellInfo, false);
                if (spell->CanAutoCast(m_creature->getVictim()))
                    targetSpellStore.push_back(std::make_pair(m_creature->getVictim(), spell));
                else
                    spell->Delete();
            }
        }

        //found units to cast on to
        if (!targetSpellStore.empty())
        {
            uint32 index = urand(0, targetSpellStore.size() - 1);

            Spell* spell  = targetSpellStore[index].second;
            Unit*  target = targetSpellStore[index].first;

            targetSpellStore.erase(targetSpellStore.begin() + index);

            SpellCastTargets targets;
            targets.setUnitTarget(target);

            if (!m_creature->HasInArc(M_PI_F, target))
            {
                m_creature->SetInFront(target);
                if (target->GetTypeId() == TYPEID_PLAYER)
                    m_creature->SendCreateUpdateToPlayer((Player*)target);

                if (owner && owner->GetTypeId() == TYPEID_PLAYER)
                    m_creature->SendCreateUpdateToPlayer((Player*)owner);
            }

            if (((Creature*)m_creature)->IsPet())
                ((Pet*)m_creature)->CheckLearning(spell->m_spellInfo->Id);

            // 10% chance to play special pet attack talk, else growl
            // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell
            if (((Creature*)m_creature)->IsPet() && (((Pet*)m_creature)->getPetType() == SUMMON_PET) && (m_creature != target) && (urand(0, 100) < 10))
                m_creature->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL);
            else
                m_creature->SendPetAIReaction();

            spell->prepare(&targets);
        }

        // deleted cached Spell objects
        for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr)
            itr->second->Delete();
    }

    // Update speed as needed to prevent dropping too far behind and despawning
    m_creature->UpdateSpeed(MOVE_RUN, true);
    m_creature->UpdateSpeed(MOVE_WALK, true);
}