Пример #1
0
void ThreatManager::addThreat(Unit* pVictim, float pThreat, SpellSchools pSchool, SpellEntry const *pThreatSpell)
{
    //function deals with adding threat and adding players and pets into ThreatList
    //mobs, NPCs, guards have ThreatList and HateOfflineList
    //players and pets have only InHateListOf
    //HateOfflineList is used co contain unattackable victims (in-flight, in-water, GM etc.)

    if (pVictim == getOwner())                              // only for same creatures :)
        return;

    if(!pVictim || (pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->isGameMaster()) )
        return;

    assert(getOwner()->GetTypeId()== TYPEID_UNIT);

    float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, pSchool, pThreatSpell);

    HostilReference* ref = iThreatContainer.addThreat(pVictim, threat);
    // Ref is not in the online refs, search the offline refs next
    if(!ref)
        ref = iThreatOfflineContainer.addThreat(pVictim, threat);

    if(!ref)                                                // there was no ref => create a new one
    {
                                                            // threat has to be 0 here
        HostilReference* hostilReference = new HostilReference(pVictim, this, 0);
        iThreatContainer.addReference(hostilReference);
        hostilReference->addThreat(threat);                 // now we add the real threat
        if(pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->isGameMaster())
            hostilReference->setOnlineOfflineState(false);  // GM is always offline
    }
}
Пример #2
0
HostilReference* ThreatContainer::modifyThreatPercent(Unit *pVictim, int32 pPercent)
{
    HostilReference* ref = getReferenceByTarget(pVictim);
    assert(ref);                                            // for a modification the reference must be there. (or not?)
    ref->addThreatPercent(pPercent);
    return ref;
}
Пример #3
0
void TeleportToInnerVeil(Player* plr)
{
    if (plr->HasAura(SPELL_SPECTRAL_EXHAUSTION, 0))
    {
        plr->GetSession()->SendNotification(NOTIFY_SPECTRALLY_EXHAUSTED);
        return;
    }

    ScriptedInstance* pInstance = ((ScriptedInstance*)plr->GetInstanceData());
    if (!pInstance)
    {
        error_log(ERROR_INST_DATA);
        plr->GetSession()->SendNotification(ERROR_INST_DATA_PLR);
        return;
    }

    pInstance->SetData64(DATA_PLAYER_SPECTRAL_REALM, plr->GetGUID());
    // Remove the player from Kalecgos' Threat List
    Creature* Kalecgos = ((Creature*)Unit::GetUnit(*plr, pInstance->GetData64(DATA_KALECGOS_DRAGON)));
    if (Kalecgos)
    {
        HostilReference* ref = Kalecgos->getThreatManager().getOnlineContainer().getReferenceByTarget(plr);
        if (ref)
            ref->removeReference();
    }

    // Add the player to Sathrovarr's Threat List
    Creature* Sathrovarr = ((Creature*)Unit::GetUnit(*plr, pInstance->GetData64(DATA_SATHROVARR)));
    if (Sathrovarr)
        Sathrovarr->AddThreat(plr, 1.0f);

    // Make them able to see Sathrovarr (he's invisible for some reason). Also, when this buff wears off, they get teleported back to Normal Realm (this is handled by Instance Script)
    plr->CastSpell(plr, SPELL_SPECTRAL_REALM, true);
    plr->CastSpell(plr, SPELL_TELEPORT_SPECTRAL_REALM, true);
}
Пример #4
0
HostilReference* ThreatContainer::addThreat(Unit* pVictim, float pThreat)
{
    HostilReference* ref = getReferenceByTarget(pVictim);
    if(ref)
        ref->addThreat(pThreat);
    return ref;
}
Пример #5
0
    void EjectPlayer(Player* plr)
    {
        debug_log("SD2: INST: Ejecting Player %s from Spectral Realm", plr->GetName());
        // Remove player from Sathrovarr's threat list
        Creature* Sath = ((Creature*)Unit::GetUnit(*plr, Sathrovarr));
        if (Sath && Sath->isAlive())
        {
            HostilReference* ref = Sath->getThreatManager().getOnlineContainer().getReferenceByTarget(plr);
            if (ref)
            {
                ref->removeReference();
                debug_log("SD2: INST: Deleting %s from Sathrovarr's threatlist", plr->GetName());
            }
        }

        // Put player back in Kalecgos(Dragon)'s threat list
        Creature* Kalecgos = ((Creature*)Unit::GetUnit(*plr, Kalecgos_Dragon));
        if (Kalecgos && Kalecgos->isAlive())
        {
            debug_log("SD2: INST: Putting %s in Kalecgos' threatlist", plr->GetName());
            Kalecgos->AddThreat(plr, 1.0f);
        }

        plr->CastSpell(plr, SPELL_TELEPORT_NORMAL_REALM, true);
        plr->CastSpell(plr, SPELL_SPECTRAL_EXHAUSTION, true);
    }
Пример #6
0
void ThreatManager::tauntApply(Unit* pTaunter)
{
    HostilReference* ref = iThreatContainer.getReferenceByTarget(pTaunter);
    if(getCurrentVictim() && ref && (ref->getThreat() < getCurrentVictim()->getThreat()))
    {
        if(ref->getTempThreatModifier() == 0.0f) // Ok, temp threat is unused
            ref->setTempThreat(getCurrentVictim()->getThreat());
    }
}
Пример #7
0
void HostilRefManager::updateThreatTables()
{
    HostilReference* ref = getFirst();
    while(ref)
    {
        ref->updateOnlineStatus();
        ref = ref->next();
    }
}
Пример #8
0
HostilReference* ThreatContainer::selectNextVictim(Creature* pAttacker, HostilReference* pCurrentVictim)
{
    HostilReference* currentRef = NULL;
    bool found = false;

    std::list<HostilReference*>::iterator lastRef = iThreatList.end();
    lastRef--;

    for(std::list<HostilReference*>::iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found; ++iter)
    {
        currentRef = (*iter);

        Unit* target = currentRef->getTarget();
        assert(target);                                     // if the ref has status online the target must be there !

        // some units are preferred in comparison to others
        if(iter != lastRef && (target->IsImmunedToDamage(pAttacker->GetMeleeDamageSchoolMask(), false) ||
                target->hasUnitState(UNIT_STAT_CONFUSED)
                ) )
        {
            // current victim is a second choice target, so don't compare threat with it below
            if(currentRef == pCurrentVictim)
                pCurrentVictim = NULL;
            continue;
        }

        if(!pAttacker->IsOutOfThreatArea(target))           // skip non attackable currently targets
        {
            if(pCurrentVictim)                              // select 1.3/1.1 better target in comparison current target
            {
                // list sorted and and we check current target, then this is best case
                if(pCurrentVictim == currentRef || currentRef->getThreat() <= 1.1f * pCurrentVictim->getThreat() )
                {
                    currentRef = pCurrentVictim;            // for second case
                    found = true;
                    break;
                }

                if( currentRef->getThreat() > 1.3f * pCurrentVictim->getThreat() ||
                    currentRef->getThreat() > 1.1f * pCurrentVictim->getThreat() && pAttacker->IsWithinMeleeRange(target) )
                {                                           //implement 110% threat rule for targets in melee range
                    found = true;                           //and 130% rule for targets in ranged distances
                    break;                                  //for selecting alive targets
                }
            }
            else                                            // select any
            {
                found = true;
                break;
            }
        }
    }
    if(!found)
        currentRef = NULL;

    return currentRef;
}
Пример #9
0
float ThreatManager::getThreat(Unit *pVictim, bool pAlsoSearchOfflineList)
{
    float threat = 0.0f;
    HostilReference* ref = iThreatContainer.getReferenceByTarget(pVictim);
    if(!ref && pAlsoSearchOfflineList)
        ref = iThreatOfflineContainer.getReferenceByTarget(pVictim);
    if(ref)
        threat = ref->getThreat();
    return threat;
}
Пример #10
0
void HostilRefManager::deleteReferences()
{
    HostilReference* ref = getFirst();
    while(ref)
    {
        HostilReference* nextRef = ref->next();
        ref->removeReference();
        delete ref;
        ref = nextRef;
    }
}
Пример #11
0
void HostilRefManager::addThreatPercent(int32 iPercent)
{
    HostilReference* ref;

    ref = getFirst();
    while (ref != NULL)
    {
        ref->addThreatPercent(iPercent);
        ref = ref->next();
    }
}
Пример #12
0
void HostilRefManager::setOnlineOfflineState(bool bIsOnline)
{
    HostilReference* ref;

    ref = getFirst();
    while(ref != NULL)
    {
        ref->setOnlineOfflineState(bIsOnline);
        ref = ref->next();
    }
}
Пример #13
0
bool ThreatManager::processThreatEvent(const UnitBaseEvent* pUnitBaseEvent)
{
    bool consumed = false;

    ThreatRefStatusChangeEvent* threatRefStatusChangeEvent;
    HostilReference* hostilReference;

    threatRefStatusChangeEvent = (ThreatRefStatusChangeEvent*) pUnitBaseEvent;
    threatRefStatusChangeEvent->setThreatManager(this);     // now we can set the threat manager
    hostilReference = threatRefStatusChangeEvent->getReference();

    switch(pUnitBaseEvent->getType())
    {
        case UEV_THREAT_REF_THREAT_CHANGE:
            if((getCurrentVictim() == hostilReference && threatRefStatusChangeEvent->getFValue()<0.0f) ||
                (getCurrentVictim() != hostilReference && threatRefStatusChangeEvent->getFValue()>0.0f))
                setDirty(true);                             // the order in the threat list might have changed
            break;
        case UEV_THREAT_REF_ONLINE_STATUS:
            if(!hostilReference->isOnline())
            {
                if (hostilReference == getCurrentVictim())
                {
                    setCurrentVictim(NULL);
                    setDirty(true);
                }
                iThreatContainer.remove(hostilReference);
                iThreatOfflineContainer.addReference(hostilReference);
            }
            else
            {
                if(getCurrentVictim() && hostilReference->getThreat() > (1.1f * getCurrentVictim()->getThreat()))
                    setDirty(true);
                iThreatContainer.addReference(hostilReference);
                iThreatOfflineContainer.remove(hostilReference);
            }
            break;
        case UEV_THREAT_REF_REMOVE_FROM_LIST:
            if (hostilReference == getCurrentVictim())
            {
                setCurrentVictim(NULL);
                setDirty(true);
            }
            if(hostilReference->isOnline())
                iThreatContainer.remove(hostilReference);
            else
                iThreatOfflineContainer.remove(hostilReference);
            break;
    }
    return consumed;
}
Пример #14
0
void HostilRefManager::setOnlineOfflineState(Unit *pCreature, bool bIsOnline)
{
    HostilReference* ref = getFirst();
    while(ref)
    {
        HostilReference* nextRef = ref->next();
        if(ref->getSource()->getOwner() == pCreature)
        {
            ref->setOnlineOfflineState(bIsOnline);
            break;
        }
        ref = nextRef;
    }
}
Пример #15
0
void HostilRefManager::deleteReference(Unit *pCreature)
{
    HostilReference* ref = getFirst();
    while(ref)
    {
        HostilReference* nextRef = ref->next();
        if(ref->getSource()->getOwner() == pCreature)
        {
            ref->removeReference();
            delete ref;
            break;
        }
        ref = nextRef;
    }
}
Пример #16
0
void HostilRefManager::threatAssist(Unit *pVictim, float fThreat, SpellEntry const *pThreatSpell, bool pSingleTarget)
{
    HostilReference* ref;

    float size = pSingleTarget ? 1.0f : getSize();            // if pSingleTarget do not divide threat
    ref = getFirst();
    while(ref != NULL)
    {
        float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, fThreat, (pThreatSpell ? GetSpellSchoolMask(pThreatSpell) : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell);
        if(pVictim == getOwner())
            ref->addThreat(threat / size);          // It is faster to modify the threat durectly if possible
        else
            ref->getSource()->addThreat(pVictim, threat / size);
        ref = ref->next();
    }
}
Пример #17
0
void ThreatManager::_addThreat(Unit *pVictim, float threat)
{
    HostilReference* ref = iThreatContainer.addThreat(pVictim, threat);
    // Ref is not in the online refs, search the offline refs next
    if(!ref)
        ref = iThreatOfflineContainer.addThreat(pVictim, threat);

    if(!ref)                                                // there was no ref => create a new one
    {
                                                            // threat has to be 0 here
        HostilReference* hostilReference = new HostilReference(pVictim, this, 0);
        iThreatContainer.addReference(hostilReference);
        hostilReference->addThreat(threat);                 // now we add the real threat
        if(pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->isGameMaster())
            hostilReference->setOnlineOfflineState(false);  // GM is always offline
    }
}
Пример #18
0
void ThreatManager::processThreatEvent(ThreatRefStatusChangeEvent* threatRefStatusChangeEvent)
{
    threatRefStatusChangeEvent->setThreatManager(this);     // now we can set the threat manager

    HostilReference* hostilReference = threatRefStatusChangeEvent->getReference();

    switch(threatRefStatusChangeEvent->getType())
    {
        case UEV_THREAT_REF_THREAT_CHANGE:
            if((getCurrentVictim() == hostilReference && threatRefStatusChangeEvent->getFValue()<0.0f) ||
                (getCurrentVictim() != hostilReference && threatRefStatusChangeEvent->getFValue()>0.0f))
                setDirty(true);                             // the order in the threat list might have changed
            break;
        case UEV_THREAT_REF_ONLINE_STATUS:
            if(!hostilReference->isOnline())
            {
                if (hostilReference == getCurrentVictim())
                {
                    setCurrentVictim(NULL);
                    setDirty(true);
                }
                iThreatContainer.remove(hostilReference);
                iThreatOfflineContainer.addReference(hostilReference);
            }
            else
            {
                if(getCurrentVictim() && hostilReference->getThreat() > (1.1f * getCurrentVictim()->getThreat()))
                    setDirty(true);
                iThreatContainer.addReference(hostilReference);
                iThreatOfflineContainer.remove(hostilReference);
            }
            break;
        case UEV_THREAT_REF_REMOVE_FROM_LIST:
            if (hostilReference == getCurrentVictim())
            {
                setCurrentVictim(NULL);
                setDirty(true);
            }
            iOwner->SendRemoveFromThreatListOpcode(hostilReference);
            if(hostilReference->isOnline())
                iThreatContainer.remove(hostilReference);
            else
                iThreatOfflineContainer.remove(hostilReference);
            break;
    }
}
Пример #19
0
void HostilRefManager::threatAssist(Unit *pVictim, float pThreat, SpellEntry const *pThreatSpell, bool pSingleTarget)
{
    if (iOwner->hasUnitState(UNIT_STAT_IGNORE_ATTACKERS))
        return;

    HostilReference* ref;

    uint32 size = pSingleTarget ? 1 : getSize();            // if pSingleTarget do not divide threat
    ref = getFirst();
    while (ref != NULL)
    {
        float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, (pThreatSpell ? SpellMgr::GetSpellSchoolMask(pThreatSpell) : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell);
        if (pVictim == getOwner())
            ref->addThreat(float (threat) / size);          // It is faster to modify the threat directly if possible
        else
            ref->getSource()->addThreat(pVictim, float (threat) / size);
        ref = ref->next();
    }
}
Пример #20
0
HostilReference* ThreatContainer::selectNextVictim(Creature* pAttacker, HostilReference* pCurrentVictim)
{
    HostilReference* currentRef = NULL;
    bool found = false;
    for(std::list<HostilReference*>::iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found; ++iter)
    {
        currentRef = (*iter);

        Unit* target = currentRef->getTarget();
        assert(target);                                     // if the ref has status online the target must be there !

        if(!pAttacker->IsOutOfThreatArea(target))           // skip non attackable currently targets
        {
            if(pCurrentVictim)                              // select 1.3/1.1 better target in comparison current target
            {
                // list sorted and and we check current target, then this is best case
                if(pCurrentVictim == currentRef || currentRef->getThreat() <= 1.1f * pCurrentVictim->getThreat() )
                {
                    currentRef = pCurrentVictim;            // for second case
                    found = true;
                    break;
                }

                if( currentRef->getThreat() > 1.3f * pCurrentVictim->getThreat() || 
                    currentRef->getThreat() > 1.1f * pCurrentVictim->getThreat() && pAttacker->IsWithinDistInMap(target, ATTACK_DISTANCE) )
                {                                           //implement 110% threat rule for targets in melee range
                    found = true;                           //and 130% rule for targets in ranged distances
                    break;                                  //for selecting alive targets
                }
            }
            else                                            // select any
            {
                found = true;
                break;
            }
        }
    }
    if(!found)
        currentRef = NULL;

    return currentRef;
}
Пример #21
0
bool ChatHandler::HandleDebugHostilRefList(const char * /*args*/)
{
    Unit* target = getSelectedUnit();
    if(!target)
        target = m_session->GetPlayer();
    HostilReference* ref = target->getHostilRefManager().getFirst();
    uint32 cnt = 0;
    PSendSysMessage("Hostil reference list of %s (guid %u)",target->GetName(), target->GetGUIDLow());
    while(ref)
    {
        if(Unit * unit = ref->getSource()->getOwner())
        {
            ++cnt;
            PSendSysMessage("   %u.   %s   (guid %u)  - threat %f",cnt,unit->GetName(), unit->GetGUIDLow(), ref->getThreat());
        }
        ref = ref->next();
    }
    SendSysMessage("End of hostil reference list.");
    return true;
}
Пример #22
0
void ThreatManager::tauntFadeOut(Unit *pTaunter)
{
    HostilReference* ref = iThreatContainer.getReferenceByTarget(pTaunter);
    if(ref)
        ref->resetTempThreat();
}
Пример #23
0
HostilReference* ThreatContainer::selectNextVictim(Creature* pAttacker, HostilReference* pCurrentVictim)
{
    HostilReference* currentRef = NULL;
    bool found = false;
    bool noPriorityTargetFound = false;

    std::list<HostilReference*>::iterator lastRef = iThreatList.end();
    lastRef--;

    for(std::list<HostilReference*>::iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found;)
    {
        currentRef = (*iter);

        Unit* target = currentRef->getTarget();
        assert(target);                                     // if the ref has status online the target must be there !

        // some units are prefered in comparison to others
        if(!noPriorityTargetFound && (target->IsImmunedToDamage(pAttacker->GetMeleeDamageSchoolMask()) || target->hasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_DAMAGE)) )
        {
            if(iter != lastRef)
            {
                // current victim is a second choice target, so don't compare threat with it below
                if(currentRef == pCurrentVictim)
                    pCurrentVictim = NULL;
                ++iter;
                continue;
            }
            else
            {
                // if we reached to this point, everyone in the threatlist is a second choice target. In such a situation the target with the highest threat should be attacked.
                noPriorityTargetFound = true;
                iter = iThreatList.begin();
                continue;
            }
        }

        if(!pAttacker->IsOutOfThreatArea(target))           // skip non attackable currently targets
        {
            if(pCurrentVictim)                              // select 1.3/1.1 better target in comparison current target
            {
                // list sorted and and we check current target, then this is best case
                if(pCurrentVictim == currentRef || currentRef->getThreat() <= 1.1f * pCurrentVictim->getThreat() )
                {
                    currentRef = pCurrentVictim;            // for second case
                    found = true;
                    break;
                }

                if( currentRef->getThreat() > 1.3f * pCurrentVictim->getThreat() ||
                    currentRef->getThreat() > 1.1f * pCurrentVictim->getThreat() && pAttacker->IsWithinDistInMap(target, ATTACK_DISTANCE) )
                {                                           //implement 110% threat rule for targets in melee range
                    found = true;                           //and 130% rule for targets in ranged distances
                    break;                                  //for selecting alive targets
                }
            }
            else                                            // select any
            {
                found = true;
                break;
            }
        }
        ++iter;
    }
    if(!found)
        currentRef = NULL;

    return currentRef;
}
Пример #24
0
void HostilRefManager::updateThreatTables()
{
    for (HostilReference* ref = getFirst(); ref != NULL; ref = ref->next())
        ref->updateOnlineStatus();
}
Пример #25
0
void HostilRefManager::addThreatPercent(int32 pValue)
{
    for (HostilReference* ref = getFirst(); ref != NULL; ref = ref->next())
        ref->addThreatPercent(pValue);
}
Пример #26
0
void HostilRefManager::setOnlineOfflineState(bool pIsOnline)
{
    for (HostilReference* ref = getFirst(); ref != NULL; ref = ref->next())
        ref->setOnlineOfflineState(pIsOnline);
}
Пример #27
0
    void UpdateAI(const uint32 uiDiff)
    {
        if (m_bIsActiveCheck)
        {
            if (!m_bIsActived && Active_Timer < uiDiff)
            {
                m_bIsActived = true;
                Active_Timer = 1000;
            }else Active_Timer -= uiDiff;
        }
        else
        {
            if (Active_Timer < uiDiff)
            {
                if(m_pInstance)
                {
                    bool m_bIsAlive = false;
                    Creature* pStalagg;
                    Creature* pFeugen;
                    if (pStalagg = ((Creature*)Unit::GetUnit((*m_creature), m_pInstance->GetData64(DATA_STALAGG))))
                        if (pStalagg->isAlive())
                            m_bIsAlive = true;
                    if (pFeugen = ((Creature*)Unit::GetUnit((*m_creature), m_pInstance->GetData64(DATA_FEUGEN))))
                        if (pFeugen->isAlive())
                            m_bIsAlive = true;

                    if (!m_bIsAlive)
                    {
                        m_bIsActiveCheck = true;
                        Active_Timer = 15000;
                    }
                    else
                    {
                        if (pStalagg->isInCombat() && pFeugen->isInCombat())
                        {
                            if (SwitchTarget_Timer < uiDiff)
                            {
                                Unit* pStalaggTarget;
                                Unit* pFeugenTarget;
                                float StalaggTargetThreat;
                                float FeugenTargetThreat;

                                // Get Stalagg's target threat
                                if (pStalagg && pStalagg->isAlive())
                                {
                                    if (pStalaggTarget = pStalagg->getVictim())
                                        StalaggTargetThreat = m_creature->getThreatManager().getThreat(pStalaggTarget);
                                }
                                // Get Feugen's target threat
                                if (pFeugen && pFeugen->isAlive())
                                {
                                    if (pFeugenTarget = pFeugen->getVictim())
                                        FeugenTargetThreat = m_creature->getThreatManager().getThreat(pFeugenTarget);
                                }

                                // Switch Feugen's target from Stalagg
                                if (pStalagg && pStalagg->isAlive())
                                {
                                    if (pFeugen && pFeugen->isAlive())
                                    {
                                        HostilReference* ref = pFeugen->getThreatManager().getOnlineContainer().getReferenceByTarget(pFeugenTarget);
                                        if (ref)
                                        {
                                            pStalagg->CastSpell(pFeugenTarget, 54517, true);
                                            ((Player*)pFeugenTarget)->TeleportTo(pFeugenTarget->GetMapId(), pStalagg->GetPositionX(), pStalagg->GetPositionY(), pStalagg->GetPositionZ(), 0, TELE_TO_NOT_LEAVE_COMBAT);
                                            ref->removeReference();
                                            pStalagg->AddThreat(pFeugenTarget, FeugenTargetThreat);
                                            pStalagg->AI()->AttackStart(pFeugenTarget);
                                        }
                                    }
                                }
                                // Switch Stalagg's target from Feugen
                                if (pFeugen && pFeugen->isAlive())
                                {
                                    if (pStalagg && pStalagg->isAlive())
                                    {
                                        HostilReference* ref = pStalagg->getThreatManager().getOnlineContainer().getReferenceByTarget(pStalaggTarget);
                                        if (ref)
                                        {
                                            pFeugen->CastSpell(pStalaggTarget, 54517, true);
                                            ((Player*)pStalaggTarget)->TeleportTo(pStalaggTarget->GetMapId(), pFeugen->GetPositionX(), pFeugen->GetPositionY(), pFeugen->GetPositionZ(), 0, TELE_TO_NOT_LEAVE_COMBAT);
                                            ref->removeReference();
                                            pFeugen->AddThreat(pStalaggTarget, StalaggTargetThreat);
                                            pFeugen->AI()->AttackStart(pStalaggTarget);
                                        }
                                    }
                                }

                                SwitchTarget_Timer = 20000;
                            }else SwitchTarget_Timer -= uiDiff;
                        }
                        else if (pStalagg->isInCombat() || pFeugen->isInCombat())
                        {
                            if (m_pInstance)
                                m_pInstance->SetData(TYPE_THADDIUS, IN_PROGRESS);
                        }
                        else if (!pStalagg->isInCombat() && !pFeugen->isInCombat())
                        {
                            if (m_pInstance)
                                m_pInstance->SetData(TYPE_THADDIUS, NOT_STARTED);
                        }

                        Active_Timer = 1000;
                    }
                }
            }else Active_Timer -= uiDiff;
        }

        if (!m_creature->SelectHostilTarget() || !m_creature->getVictim())
            return;

        if (ChainLightning_Timer < uiDiff)
        {
            DoCast(m_creature, m_bIsHeroicMode ? H_SPELL_CHAIN_LIGHTNING : SPELL_CHAIN_LIGHTNING);
            ChainLightning_Timer = 15000;
        }else ChainLightning_Timer -= uiDiff;

        if(m_bIsPolarityShift)
        {
            // workaround for POLARITY_SHIFT
            if (PolarityShift_Timer < uiDiff)
            {
                Map *map = m_creature->GetMap();
                if (map->IsDungeon())
                {
                    Map::PlayerList const &PlayerList = map->GetPlayers();

                    if (PlayerList.isEmpty())
                        return;

                    for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
                        if (i->getSource()->isAlive() && i->getSource()->isTargetableForAttack())
                        {
                            switch(rand()%2)
                            {
                                case 0:
                                    if (i->getSource()->HasAura(SPELL_CHARGE_NEGATIVE_NEARDMG))
                                        i->getSource()->RemoveAurasDueToSpell(SPELL_CHARGE_NEGATIVE_NEARDMG);
                                    i->getSource()->CastSpell(i->getSource(), SPELL_CHARGE_POSITIVE_NEARDMG, true);
                                    break;
                                case 1:
                                    if (i->getSource()->HasAura(SPELL_CHARGE_POSITIVE_NEARDMG))
                                        i->getSource()->RemoveAurasDueToSpell(SPELL_CHARGE_POSITIVE_NEARDMG);
                                    i->getSource()->CastSpell(i->getSource(), SPELL_CHARGE_NEGATIVE_NEARDMG, true);
                                    break;
                            }
                        }
                }
                m_bIsPolarityShift = false;
                PolarityShift_Timer = 27000;
            }else PolarityShift_Timer -= uiDiff;
        }
        else
        {
            if(PolarityShift_Timer < uiDiff)
            {
      	        DoCast(m_creature, SPELL_POLARITY_SHIFT); // need core support
                m_bIsPolarityShift = true;
                PolarityShift_Timer = 3000;
            }else PolarityShift_Timer -= uiDiff;
        }

        if (Enrage_Timer < uiDiff)
        {
            DoCast(m_creature, SPELL_BESERK);
            Enrage_Timer = 300000;
        }else Enrage_Timer -= uiDiff;

        if (Scream_Timer < uiDiff)
        {
            switch(rand()%4)
            {
                case 0: DoScriptText(SAY_SCREAM1, m_creature);break;
                case 1: DoScriptText(SAY_SCREAM2, m_creature);break;
                case 2: DoScriptText(SAY_SCREAM3, m_creature);break;
                case 3: DoScriptText(SAY_SCREAM4, m_creature);break;
            }
            Scream_Timer = 60000+rand()%30000;
        }else Scream_Timer -= uiDiff;

        if (RangeCheck_Timer < uiDiff)
        {
            m_bInMeleeRange = false;
            std::list<HostilReference *> t_list = m_creature->getThreatManager().getThreatList();
            for(std::list<HostilReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
            {
                Unit* pTarget = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());

                //if in melee range
                if (pTarget && pTarget->IsWithinDistInMap(m_creature, ATTACK_DISTANCE))
                {
                    m_bInMeleeRange = true;
                    break;
                }
            }

            if (!m_bInMeleeRange)
                DoCast(SelectUnit(SELECT_TARGET_TOPAGGRO,0), SPELL_BALL_LIGHTNING);

            RangeCheck_Timer = 2000;
        }else RangeCheck_Timer -= uiDiff;

        //if nobody is in melee range
        if (m_bInMeleeRange)
            DoMeleeAttackIfReady();
    }