void CreatureEventAI::DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid) { CellCoord p(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY())); Cell cell(p); cell.SetNoCreate(); Trinity::FriendlyMissingBuffInRange u_check(me, range, spellid); Trinity::CreatureListSearcher<Trinity::FriendlyMissingBuffInRange> searcher(me, _list, u_check); TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::FriendlyMissingBuffInRange>, GridTypeMapContainer > grid_creature_searcher(searcher); cell.Visit(p, grid_creature_searcher, *me->GetMap(), *me, range); }
void TotemAI::UpdateAI(const uint32 /*diff*/) { if (getTotem().GetTotemType() != TOTEM_ACTIVE) return; if (!m_creature->isAlive() || m_creature->IsNonMeleeSpellCasted(false)) return; // Search spell SpellEntry const *spellInfo = sSpellStore.LookupEntry(getTotem().GetSpell()); if (!spellInfo) return; SpellMiscEntry const* spellMisc = sSpellMiscStore.LookupEntry(spellInfo->Id); // Get spell rangy SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellMisc->rangeIndex); float max_range = GetSpellMaxRange(srange); // SPELLMOD_RANGE not applied in this place just because nonexistent range mods for attacking totems // pointer to appropriate target if found any Unit* victim = m_creature->GetMap()->GetUnit(i_victimGuid); // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if( !victim || !victim->isTargetableForAttack() || !m_creature->IsWithinDistInMap(victim, max_range) || m_creature->IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(m_creature,m_creature,false) ) { victim = NULL; Strawberry::NearestAttackableUnitInObjectRangeCheck u_check(m_creature, m_creature, max_range); Strawberry::UnitLastSearcher<Strawberry::NearestAttackableUnitInObjectRangeCheck> checker(victim, u_check); Cell::VisitAllObjects(m_creature, checker, max_range); } // If have target if (victim) { // remember i_victimGuid = victim->GetObjectGuid(); // attack m_creature->SetInFront(victim); // client change orientation by self m_creature->CastSpell(victim, getTotem().GetSpell(), false); } else i_victimGuid.Clear(); }
void CreatureEventAI::DoFindFriendlyCC(std::list<Creature*>& _list, float range) { CellPair p(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); Trinity::FriendlyCCedInRange u_check(me, range); Trinity::CreatureListSearcher<Trinity::FriendlyCCedInRange> searcher(me, _list, u_check); TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::FriendlyCCedInRange>, GridTypeMapContainer > grid_creature_searcher(searcher); cell.Visit(p, grid_creature_searcher, *me->GetMap()); }
void UpdateAI(uint32 diff) { if (_initialSelection) { _initialSelection = false; // Find victim of Summon Gargoyle spell std::list<Unit*> targets; Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 50); Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check); me->VisitNearbyObject(50, searcher); for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) if ((*iter)->GetAura(SPELL_DK_SUMMON_GARGOYLE_1, me->GetOwnerGUID())) { (*iter)->RemoveAura(SPELL_DK_SUMMON_GARGOYLE_1, me->GetOwnerGUID()); SetGazeOn(*iter); _targetGUID = (*iter)->GetGUID(); break; } } if (_despawnTimer > 4000) { _despawnTimer -= diff; if (!UpdateVictimWithGaze()) { MySelectNextTarget(); return; } _initialCastTimer += diff; _selectionTimer += diff; if (_selectionTimer >= 1000) { MySelectNextTarget(); _selectionTimer = 0; } if (_initialCastTimer >= 2000 && !me->HasUnitState(UNIT_STATE_CASTING|UNIT_STATE_LOST_CONTROL) && me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE) me->CastSpell(me->GetVictim(), 51963, false); } else { if (!_despawning) FlyAway(); if (_despawnTimer > diff) _despawnTimer -= diff; else me->DespawnOrUnsummon(); } }
void TotemAI::UpdateAI(const uint32 /*diff*/) { if (me->ToTotem()->GetTotemType() != TOTEM_ACTIVE) return; if (!me->isAlive() || me->IsNonMeleeSpellCasted(false)) return; // Search spell SpellEntry const *spellInfo = sSpellStore.LookupEntry( me->ToTotem()->GetSpell()); if (!spellInfo) return; // Get spell range SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry( spellInfo->rangeIndex); float max_range = GetSpellMaxRangeForHostile(srange); // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems // pointer to appropriate target if found any Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(*me, i_victimGuid) : NULL; // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if (!victim || !victim->isTargetableForAttack() || !me->IsWithinDistInMap(victim, max_range) || me->IsFriendlyTo(victim) || !me->canSeeOrDetect(victim)) { victim = NULL; Trinity::NearestAttackableUnitInObjectRangeCheck u_check(me, me, max_range); Trinity::UnitLastSearcher< Trinity::NearestAttackableUnitInObjectRangeCheck> checker(me, victim, u_check); me->VisitNearbyObject(max_range, checker); } // If have target if (victim) { // remember i_victimGuid = victim->GetGUID(); // attack me->SetInFront(victim); // client change orientation by self me->CastSpell(victim, me->ToTotem()->GetSpell(), false); } else i_victimGuid = 0; }
Creature* BossSpellWorker::SelectNearestCreature(uint32 guid, float range) { Creature* pTarget = NULL; MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*boss, guid, true, range*2); MaNGOS::CreatureLastSearcher<MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(boss, pTarget, u_check); Cell::VisitGridObjects(boss, searcher, range*2); if (pTarget && pTarget->IsInMap(boss) && pTarget != boss && pTarget->isAlive()) { debug_log("BSW: search creature %u in range %f - found it.",guid,range); return pTarget; } else return NULL; }
Creature* BSWScriptedAI::doSelectNearestCreature(uint32 guid, float range) { Creature* pTarget = NULL; Diamond::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_creature, guid, true, range*2); Diamond::CreatureLastSearcher<Diamond::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(m_creature, pTarget, u_check); Cell::VisitGridObjects(m_creature, searcher, range*2); if (pTarget && pTarget->IsInMap(m_creature) && pTarget != m_creature && pTarget->isAlive()) { debug_log("BSW: search creature %u in range %f - found it.",guid,range); return pTarget; } else return NULL; }
void UpdateAI(uint32 diff) { if (_initialSelection) { _initialSelection = false; // Find victim of Summon Gargoyle spell std::list<Unit*> targets; Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 50); Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check); me->VisitNearbyObject(50, searcher); for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) if ((*iter)->GetAura(SPELL_DK_SUMMON_GARGOYLE_1, me->GetOwnerGUID())) { SwitchTargetAndAttack((*iter)); break; } } if (_despawnTimer > 4000) { _despawnTimer -= diff; _initialCastTimer += diff; _selectionTimer += diff; if (_selectionTimer >= 1000) { MySelectNextTarget(); _selectionTimer = 0; } // check start timer and if not casting if(_initialCastTimer >= 2000 && !me->HasUnitState(UNIT_STATE_CASTING)) if (!(me->HasAuraType(SPELL_AURA_MOD_FEAR) || me->HasAuraType(SPELL_AURA_MOD_ROOT) || me->HasAuraType(SPELL_AURA_MOD_CONFUSE) || me->HasAuraType(SPELL_AURA_MOD_STUN))) if (_initialCastTimer >= 2000 && !me->HasUnitState(UNIT_STATE_LOST_CONTROL) && me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE) me->CastSpell(me->GetVictim(), 51963, false); } else { if (!_despawning) FlyAway(); if (_despawnTimer > diff) _despawnTimer -= diff; else me->DespawnOrUnsummon(); } }
GameObject* GameObject::LookupFishingHoleAround(float range) { GameObject* ok = NULL; CellPair p(MaNGOS::ComputeCellPair(GetPositionX(),GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; MaNGOS::NearestGameObjectFishingHole u_check(*this, range); MaNGOS::GameObjectSearcher<MaNGOS::NearestGameObjectFishingHole> checker(ok, u_check); CellLock<GridReadGuard> cell_lock(cell, p); TypeContainerVisitor<MaNGOS::GameObjectSearcher<MaNGOS::NearestGameObjectFishingHole>, GridTypeMapContainer > grid_object_checker(checker); cell_lock->Visit(cell_lock, grid_object_checker, *GetMap()); return ok; }
void TotemAI::UpdateAI(uint32 /*diff*/) { if (me->ToTotem()->GetTotemType() != TOTEM_ACTIVE) return; if (!me->IsAlive() || me->IsNonMeleeSpellCast(false)) return; // Search spell SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->ToTotem()->GetSpell()); if (!spellInfo) return; // Get spell range float max_range = spellInfo->GetMaxRange(false); // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems // pointer to appropriate target if found any Unit* victim = !i_victimGuid.IsEmpty() ? ObjectAccessor::GetUnit(*me, i_victimGuid) : NULL; // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if (!victim || !victim->isTargetableForAttack() || !me->IsWithinDistInMap(victim, max_range) || me->IsFriendlyTo(victim) || !me->CanSeeOrDetect(victim)) { victim = NULL; Trinity::NearestAttackableUnitInObjectRangeCheck u_check(me, me->GetCharmerOrOwnerOrSelf(), max_range); Trinity::UnitLastSearcher<Trinity::NearestAttackableUnitInObjectRangeCheck> checker(me, victim, u_check); Cell::VisitAllObjects(me, checker, max_range); } // If have target if (victim) { // remember i_victimGuid = victim->GetGUID(); // attack me->SetInFront(victim); // client change orientation by self me->CastSpell(victim, me->ToTotem()->GetSpell(), false); } else i_victimGuid.Clear(); }
Unit* BSWScriptedAI::doSelectLowHPFriendly(float fRange, uint32 uiMinHPDiff) { CellPair p(Diamond::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); Unit* pUnit = NULL; Diamond::MostHPMissingInRange u_check(m_creature, fRange, uiMinHPDiff); Diamond::UnitLastSearcher<Diamond::MostHPMissingInRange> searcher(m_creature, pUnit, u_check); TypeContainerVisitor<Diamond::UnitLastSearcher<Diamond::MostHPMissingInRange>, GridTypeMapContainer > grid_unit_searcher(searcher); cell.Visit(p, grid_unit_searcher, *(pMap), *m_creature, fRange); return pUnit; }
std::list<Creature*> ScriptedAI::DoFindFriendlyMissingBuff(float fRange, uint32 uiSpellId) { CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); std::list<Creature*> pList; MaNGOS::FriendlyMissingBuffInRange u_check(m_creature, fRange, uiSpellId); MaNGOS::CreatureListSearcher<MaNGOS::FriendlyMissingBuffInRange> searcher(m_creature, pList, u_check); TypeContainerVisitor<MaNGOS::CreatureListSearcher<MaNGOS::FriendlyMissingBuffInRange>, GridTypeMapContainer > grid_creature_searcher(searcher); cell.Visit(p, grid_creature_searcher, *(m_creature->GetMap()), *m_creature, fRange); return pList; }
Unit* BossSpellWorker::SelectLowHPFriendly(float fRange, uint32 uiMinHPDiff) { CellPair p(Trinity::ComputeCellPair(boss->GetPositionX(), boss->GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); Unit* pUnit = NULL; Trinity::MostHPMissingInRange u_check(boss, fRange, uiMinHPDiff); Trinity::UnitLastSearcher<Trinity::MostHPMissingInRange> searcher(boss, pUnit, u_check); TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::MostHPMissingInRange>, GridTypeMapContainer > grid_unit_searcher(searcher); cell.Visit(p, grid_unit_searcher, *(pMap), *boss, fRange); return pUnit; }
void CreatureAI::SendAIEventAround(AIEventType eventType, Unit* pInvoker, uint32 uiDelay, float fRadius, uint32 miscValue /*=0*/) const { if (fRadius > 0) { std::list<Creature*> receiverList; // Use this check here to collect only assitable creatures in case of CALL_ASSISTANCE, else be less strict MaNGOS::AnyAssistCreatureInRangeCheck u_check(m_creature, eventType == AI_EVENT_CALL_ASSISTANCE ? pInvoker : NULL, fRadius); MaNGOS::CreatureListSearcher<MaNGOS::AnyAssistCreatureInRangeCheck> searcher(receiverList, u_check); Cell::VisitGridObjects(m_creature, searcher, fRadius); if (!receiverList.empty()) { AiDelayEventAround* e = new AiDelayEventAround(eventType, pInvoker ? pInvoker->GetObjectGuid() : ObjectGuid(), *m_creature, receiverList, miscValue); m_creature->m_Events.AddEvent(e, m_creature->m_Events.CalculateTime(uiDelay)); } } }
std::list<Creature*> ScriptedAI::DoFindFriendlyCC(float fRange) { CellPair p(Diamond::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); std::list<Creature*> pList; Diamond::FriendlyCCedInRange u_check(m_creature, fRange); Diamond::CreatureListSearcher<Diamond::FriendlyCCedInRange> searcher(m_creature, pList, u_check); GridTypeVisitor<Diamond::CreatureListSearcher<Diamond::FriendlyCCedInRange> >::Grid grid_creature_searcher(searcher); cell.Visit(p, grid_creature_searcher, *(m_creature->GetMap()), *m_creature, fRange); return pList; }
Unit* GuardianAI::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff, bool onlyInCombat) const { Unit* owner = m_creature->GetOwner(); if (!owner) return nullptr; Unit* pUnit = nullptr; MaNGOS::MostHPMissingInRangeCheck u_check(m_creature, range, MinHPDiff, onlyInCombat); MaNGOS::UnitLastSearcher<MaNGOS::MostHPMissingInRangeCheck> searcher(pUnit, u_check); if (owner->GetTypeId() == TYPEID_PLAYER) Cell::VisitWorldObjects(m_creature, searcher, range); // search all friendly unit including players else Cell::VisitGridObjects(m_creature, searcher, range); // search only friendly creatures return pUnit; }
std::list<Creature*> ScriptedAI::DoFindFriendlyCC(float range) { CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); std::list<Creature*> pList; MaNGOS::FriendlyCCedInRange u_check(m_creature, range); MaNGOS::CreatureListSearcher<MaNGOS::FriendlyCCedInRange> searcher(m_creature, pList, u_check); TypeContainerVisitor<MaNGOS::CreatureListSearcher<MaNGOS::FriendlyCCedInRange>, GridTypeMapContainer > grid_creature_searcher(searcher); CellLock<GridReadGuard> cell_lock(cell, p); cell_lock->Visit(cell_lock, grid_creature_searcher, *(m_creature->GetMap())); return pList; }
Unit* CreatureEventAI::DoSelectLowestHpFriendly(float range, uint32 minHPDiff) { CellCoord p(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY())); Cell cell(p); cell.SetNoCreate(); Unit* unit = NULL; Trinity::MostHPMissingInRange u_check(me, range, minHPDiff); Trinity::UnitLastSearcher<Trinity::MostHPMissingInRange> searcher(me, unit, u_check); /* typedef TYPELIST_4(GameObject, Creature*except pets*, DynamicObject, Corpse*Bones*) AllGridObjectTypes; This means that if we only search grid then we cannot possibly return pets or players so this is safe */ TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::MostHPMissingInRange>, GridTypeMapContainer > grid_unit_searcher(searcher); cell.Visit(p, grid_unit_searcher, *me->GetMap(), *me, range); return unit; }
void InitializeAI() { CasterAI::InitializeAI(); uint64 ownerGuid = me->GetOwnerGUID(); if (!ownerGuid) return; // Not needed to be despawned now _despawnTimer = 0; // Find victim of Summon Gargoyle spell std::list<Unit*> targets; Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 30.0f); Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check); me->VisitNearbyObject(30.0f, searcher); for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) if ((*iter)->GetAura(SPELL_DK_SUMMON_GARGOYLE_1, ownerGuid)) { me->Attack((*iter), false); break; } }
Unit* ScriptedAI::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff) { CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); Unit* pUnit = NULL; MaNGOS::MostHPMissingInRange u_check(m_creature, range, MinHPDiff); MaNGOS::UnitLastSearcher<MaNGOS::MostHPMissingInRange> searcher(m_creature, pUnit, u_check); /* typedef TYPELIST_4(GameObject, Creature*except pets*, DynamicObject, Corpse*Bones*) AllGridObjectTypes; This means that if we only search grid then we cannot possibly return pets or players so this is safe */ TypeContainerVisitor<MaNGOS::UnitLastSearcher<MaNGOS::MostHPMissingInRange>, GridTypeMapContainer > grid_unit_searcher(searcher); CellLock<GridReadGuard> cell_lock(cell, p); cell_lock->Visit(cell_lock, grid_unit_searcher, *(m_creature->GetMap())); return pUnit; }
void SearchForTrigger(Unit* target, uint32 triggerEntry, uint32 SpellID, bool ArcRequirement) { Player* pPlayer = me->GetPlayer(*me, PlayerGuid); std::list<Unit*> SearchedTriggers; Trinity::AllCreaturesOfEntryInRange u_check(target, triggerEntry, 100.0f); Trinity::UnitListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(target, SearchedTriggers, u_check); target->VisitNearbyObject(100.0f, searcher); if(SearchedTriggers.empty()) return; for (std::list<Unit*>::const_iterator iter = SearchedTriggers.begin(); iter != SearchedTriggers.end(); ++iter) { if(ArcRequirement) { if((*iter)->HasInArc(M_PI/3, me)) (*iter)->CastSpell(target, SpellID, true); } else (*iter)->CastSpell(target, SpellID, true); } SearchedTriggers.clear(); }
Unit* ScriptedAI::DoSelectLowestHpFriendly(float fRange, uint32 uiMinHPDiff) { CellPair p(Diamond::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); Unit* pUnit = NULL; Diamond::MostHPMissingInRange u_check(m_creature, fRange, uiMinHPDiff); Diamond::UnitLastSearcher<Diamond::MostHPMissingInRange> searcher(m_creature, pUnit, u_check); /* typedef TYPELIST_4(GameObject, Creature*except pets*, DynamicObject, Corpse*Bones*) AllGridObjectTypes; This means that if we only search grid then we cannot possibly return pets or players so this is safe */ GridTypeVisitor<Diamond::UnitLastSearcher<Diamond::MostHPMissingInRange> >::Grid grid_unit_searcher(searcher); cell.Visit(p, grid_unit_searcher, *(m_creature->GetMap()), *m_creature, fRange); return pUnit; }
void HandleStormSequence(Unit* Cloud) // 1: begin, 2-9: tick, 10: end { if (StormCount < 10 && StormCount > 1) { // deal damage int32 bp0 = 800; for (uint8 i = 2; i < StormCount; ++i) bp0 *= 2; std::list<Unit*> tempUnitMap; Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(me, me, SIZE_OF_GRIDS); Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(me, tempUnitMap, u_check); Cell::VisitAllObjects(me, searcher, SIZE_OF_GRIDS); // deal damage for (std::list<Unit*>::const_iterator i = tempUnitMap.begin(); i != tempUnitMap.end(); ++i) { if (Unit* target = (*i)) { if (Cloud && !Cloud->IsWithinDist(target, 6, false)) { CastSpellExtraArgs args; args.TriggerFlags = TRIGGERED_FULL_MASK; args.OriginalCaster = me->GetGUID(); args.AddSpellMod(SPELLVALUE_BASE_POINT0, bp0); Cloud->CastSpell(target, SPELL_ZAP, args); } } } // visual float x, y, z; z = me->GetPositionZ(); uint8 maxCount = 5 + rand32() % 5; for (uint8 i = 0; i < maxCount; ++i) { x = 343.0f + rand32() % 60; y = 1380.0f + rand32() % 60; if (Unit* trigger = me->SummonTrigger(x, y, z, 0, 2000)) { trigger->SetFaction(FACTION_FRIENDLY); trigger->SetMaxHealth(100000); trigger->SetHealth(100000); trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); if (Cloud) { CastSpellExtraArgs args; args.TriggerFlags = TRIGGERED_FULL_MASK; args.OriginalCaster = Cloud->GetGUID(); args.AddSpellMod(SPELLVALUE_BASE_POINT0, bp0); Cloud->CastSpell(trigger, SPELL_ZAP, args); } } } } ++StormCount; if (StormCount > 10) { StormCount = 0; // finish events.ScheduleEvent(EVENT_SUMMON_EAGLES, 5s); me->InterruptNonMeleeSpells(false); CloudGUID.Clear(); if (Cloud) Cloud->KillSelf(); SetWeather(WEATHER_STATE_FINE, 0.0f); isRaining = false; } events.ScheduleEvent(EVENT_STORM_SEQUENCE, 1s); }
void HandleStormSequence(Unit *Cloud) // 1: begin, 2-9: tick, 10: end { if(StormCount < 10 && StormCount > 1) { // deal damage int32 bp0 = 800; for(uint8 i = 2; i < StormCount; ++i) bp0 *= 2; CellPair p(Ribon::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); std::list<Unit *> tempUnitMap; { Ribon::AnyAoETargetUnitInObjectRangeCheck u_check(m_creature, m_creature, 999); Ribon::UnitListSearcher<Ribon::AnyAoETargetUnitInObjectRangeCheck> searcher(m_creature, tempUnitMap, u_check); TypeContainerVisitor<Ribon::UnitListSearcher<Ribon::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher); TypeContainerVisitor<Ribon::UnitListSearcher<Ribon::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher); CellLock<GridReadGuard> cell_lock(cell, p); cell_lock->Visit(cell_lock, world_unit_searcher, *(m_creature->GetMap())); cell_lock->Visit(cell_lock, grid_unit_searcher, *(m_creature->GetMap())); } //dealdamege for(std::list<Unit*>::iterator i = tempUnitMap.begin(); i != tempUnitMap.end(); ++i) { if(!Cloud->IsWithinDist(*i, 6, false)) { Cloud->CastCustomSpell(*i, 43137, &bp0, NULL, NULL, true, 0, 0, m_creature->GetGUID()); } } // visual float x,y,z; z = m_creature->GetPositionZ(); for(uint8 i = 0; i < 5+rand()%5; ++i) { x = 343+rand()%60; y = 1380+rand()%60; if(Unit *trigger = m_creature->SummonTrigger(x, y, z, 0, 2000)) { trigger->setFaction(35); trigger->SetMaxHealth(100000); trigger->SetHealth(100000); trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); if (Cloud) Cloud->CastCustomSpell(trigger, /*43661*/43137, &bp0, NULL, NULL,true, 0, 0, Cloud->GetGUID()); } } } StormCount++; if(StormCount > 10) { StormCount = 0; // finish SummonEagles_Timer = 5000; m_creature->InterruptNonMeleeSpells(false); CloudGUID = 0; if (Cloud) Cloud->DealDamage(Cloud, Cloud->GetHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); SetWeather(WEATHER_STATE_FINE, 0.0f); isRaining = false; } StormSequenceTimer = 1000; }
void TotemAI::UpdateAI(uint32 const /*diff*/) { if (me->ToTotem()->GetTotemType() != TOTEM_ACTIVE) return; if (!me->IsAlive()) return; // pointer to appropriate target if found any Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(*me, i_victimGuid) : NULL; if (me->IsNonMeleeSpellCasted(false)) { if (victim && victim->HasCrowdControlAura()) victim = NULL; else return; } // Search spell SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->ToTotem()->GetSpell()); if (!spellInfo) return; // Get spell range float max_range = spellInfo->GetMaxRange(false); // Apply SPELLMOD_RANGE from owner (required by Elemental Reach talent at least) if (Player * const modOwner = me->GetSpellModOwner()) modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RANGE, max_range); // Searing Totem prioritize Flame Shock or Stormstrike targets if (spellInfo->Id == 3606) { if (Unit * caster = me->GetOwner()) { std::list<Unit*> targets; Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, max_range); Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check); Trinity::VisitNearbyObject(caster, max_range, searcher); // Find Stormstrike and Flame Shock -> Stormstrike -> Flame Shock const uint64 guid = caster->GetGUID(); auto itr = std::find_if(targets.begin(), targets.end(), [guid](Unit *u) { return u->HasAura(17364, guid) && u->HasAura(8050, guid); }); if (itr == targets.end()) itr = std::find_if(targets.begin(), targets.end(), [guid](Unit *u) { return u->HasAura(17364, guid); }); if (itr == targets.end()) itr = std::find_if(targets.begin(), targets.end(), [guid](Unit *u) { return u->HasAura(8050, guid); }); if (itr != targets.end()) victim = *itr; } if (!victim) { victim = me->GetOwner()->GetVictim(); if (!victim) return; } } // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if (!victim || !victim->isTargetableForAttack() || !me->IsWithinDistInMap(victim, max_range) || me->IsFriendlyTo(victim) || !me->canSeeOrDetect(victim) || victim->HasCrowdControlAura()) { victim = NULL; Trinity::NearestAttackableNoCCUnitInObjectRangeCheck u_check(me, me, max_range); Trinity::UnitLastSearcher<Trinity::NearestAttackableNoCCUnitInObjectRangeCheck> checker(me, victim, u_check); Trinity::VisitNearbyObject(me, max_range, checker); } // If have target if (victim) { // remember i_victimGuid = victim->GetGUID(); // attack me->SetInFront(victim); // client change orientation by self me->CastSpell(victim, me->ToTotem()->GetSpell(), false); } else i_victimGuid = 0; }
void GameObject::Update(uint32 /*p_time*/) { if (IS_MO_TRANSPORT(GetGUID())) { //((Transport*)this)->Update(p_time); return; } switch (m_lootState) { case GO_NOT_READY: { switch(GetGoType()) { case GAMEOBJECT_TYPE_TRAP: { // Arming Time for GAMEOBJECT_TYPE_TRAP (6) Unit* owner = GetOwner(); if (owner && ((Player*)owner)->isInCombat()) m_cooldownTime = time(NULL) + GetGOInfo()->trap.startDelay; m_lootState = GO_READY; break; } case GAMEOBJECT_TYPE_FISHINGNODE: { // fishing code (bobber ready) if( time(NULL) > m_respawnTime - FISHING_BOBBER_READY_TIME ) { // splash bobber (bobber ready now) Unit* caster = GetOwner(); if(caster && caster->GetTypeId()==TYPEID_PLAYER) { SetGoState(0); SetUInt32Value(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN); UpdateData udata; WorldPacket packet; BuildValuesUpdateBlockForPlayer(&udata,((Player*)caster)); udata.BuildPacket(&packet); ((Player*)caster)->GetSession()->SendPacket(&packet); WorldPacket data(SMSG_GAMEOBJECT_CUSTOM_ANIM,8+4); data << GetGUID(); data << (uint32)(0); ((Player*)caster)->SendMessageToSet(&data,true); } m_lootState = GO_READY; // can be successfully open with some chance } return; } default: m_lootState = GO_READY; // for other GOis same switched without delay to GO_READY break; } // NO BREAK for switch (m_lootState) } case GO_READY: { if (m_respawnTime > 0) // timer on { if (m_respawnTime <= time(NULL)) // timer expired { m_respawnTime = 0; m_SkillupList.clear(); m_usetimes = 0; switch (GetGoType()) { case GAMEOBJECT_TYPE_FISHINGNODE: // can't fish now { Unit* caster = GetOwner(); if(caster && caster->GetTypeId()==TYPEID_PLAYER) { if(caster->m_currentSpells[CURRENT_CHANNELED_SPELL]) { caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0); caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish(false); } WorldPacket data(SMSG_FISH_NOT_HOOKED,0); ((Player*)caster)->GetSession()->SendPacket(&data); } // can be delete m_lootState = GO_JUST_DEACTIVATED; return; } case GAMEOBJECT_TYPE_DOOR: case GAMEOBJECT_TYPE_BUTTON: //we need to open doors if they are closed (add there another condition if this code breaks some usage, but it need to be here for battlegrounds) if( !GetGoState() ) SwitchDoorOrButton(false); //flags in AB are type_button and we need to add them here so no break! default: if(!m_spawnedByDefault) // despawn timer { // can be despawned or destroyed SetLootState(GO_JUST_DEACTIVATED); return; } // respawn timer GetMap()->Add(this); break; } } } // traps can have time and can not have GameObjectInfo const* goInfo = GetGOInfo(); if(goInfo->type == GAMEOBJECT_TYPE_TRAP) { // traps Unit* owner = GetOwner(); Unit* ok = NULL; // pointer to appropriate target if found any if(m_cooldownTime >= time(NULL)) return; bool IsBattleGroundTrap = false; //FIXME: this is activation radius (in different casting radius that must be selected from spell data) //TODO: move activated state code (cast itself) to GO_ACTIVATED, in this place only check activating and set state float radius = goInfo->trap.radius; if(!radius) { if(goInfo->trap.cooldown != 3) // cast in other case (at some triggering/linked go/etc explicit call) return; else { if(m_respawnTime > 0) break; radius = goInfo->trap.cooldown; // battlegrounds gameobjects has data2 == 0 && data5 == 3 IsBattleGroundTrap = true; } } bool NeedDespawn = (goInfo->trap.charges != 0); CellPair p(MaNGOS::ComputeCellPair(GetPositionX(),GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; // Note: this hack with search required until GO casting not implemented // search unfriendly creature if(owner && NeedDespawn) // hunter trap { MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, owner, radius); MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck> checker(ok, u_check); CellLock<GridReadGuard> cell_lock(cell, p); TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker); cell_lock->Visit(cell_lock, grid_object_checker, *GetMap()); // or unfriendly player/pet if(!ok) { TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); cell_lock->Visit(cell_lock, world_object_checker, *GetMap()); } } else // environmental trap { // environmental damage spells already have around enemies targeting but this not help in case not existed GO casting support // affect only players Player* p_ok = NULL; MaNGOS::AnyPlayerInObjectRangeCheck p_check(this, radius); MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck> checker(p_ok, p_check); CellLock<GridReadGuard> cell_lock(cell, p); TypeContainerVisitor<MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); cell_lock->Visit(cell_lock, world_object_checker, *GetMap()); ok = p_ok; } if (ok) { Unit *caster = owner ? owner : ok; caster->CastSpell(ok, goInfo->trap.spellId, true); m_cooldownTime = time(NULL) + 4; // 4 seconds if(NeedDespawn) SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed if(IsBattleGroundTrap && ok->GetTypeId() == TYPEID_PLAYER) { //BattleGround gameobjects case if(((Player*)ok)->InBattleGround()) if(BattleGround *bg = ((Player*)ok)->GetBattleGround()) bg->HandleTriggerBuff(GetGUID()); } } } if (m_charges && m_usetimes >= m_charges) SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed break; } case GO_ACTIVATED: { switch(GetGoType()) { case GAMEOBJECT_TYPE_DOOR: case GAMEOBJECT_TYPE_BUTTON: if(GetAutoCloseTime() && (m_cooldownTime < time(NULL))) { SwitchDoorOrButton(false); SetLootState(GO_JUST_DEACTIVATED); } break; } break; } case GO_JUST_DEACTIVATED: { //if Gameobject should cast spell, then this, but some GOs (type = 10) should be destroyed if (GetGoType() == GAMEOBJECT_TYPE_GOOBER) { uint32 spellId = GetGOInfo()->goober.spellId; if(spellId) { std::set<uint32>::iterator it = m_unique_users.begin(); std::set<uint32>::iterator end = m_unique_users.end(); for (; it != end; it++) { Unit* owner = Unit::GetUnit(*this, uint64(*it)); if (owner) owner->CastSpell(owner, spellId, false); } m_unique_users.clear(); m_usetimes = 0; } //any return here in case battleground traps } if(GetOwnerGUID()) { m_respawnTime = 0; Delete(); return; } //burning flags in some battlegrounds, if you find better condition, just add it if (GetGoAnimProgress() > 0) { SendObjectDeSpawnAnim(GetGUID()); //reset flags SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags); } loot.clear(); SetLootState(GO_READY); if(!m_respawnDelayTime) return; if(!m_spawnedByDefault) { m_respawnTime = 0; return; } m_respawnTime = time(NULL) + m_respawnDelayTime; // if option not set then object will be saved at grid unload if(sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY)) SaveRespawnTime(); ObjectAccessor::UpdateObjectVisibility(this); break; } } }
void TotemAI::UpdateAI(uint32 const /*diff*/) { if (me->ToTotem()->GetTotemType() != TOTEM_ACTIVE) return; if (!me->isAlive()) return; // pointer to appropriate target if found any Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(*me, i_victimGuid) : NULL; if (me->IsNonMeleeSpellCasted(false)) { if (victim && victim->HasCrowdControlAura()) victim = NULL; else return; } // Search spell SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->ToTotem()->GetSpell()); if (!spellInfo) return; // Get spell range float max_range = spellInfo->GetMaxRange(false); // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if (!victim || !victim->isTargetableForAttack() || !me->IsWithinDistInMap(victim, max_range) || me->IsFriendlyTo(victim) || !me->canSeeOrDetect(victim) || victim->HasCrowdControlAura()) { victim = NULL; MoPCore::NearestAttackableNoCCUnitInObjectRangeCheck u_check(me, me, max_range); MoPCore::UnitLastSearcher<MoPCore::NearestAttackableNoCCUnitInObjectRangeCheck> checker(me, victim, u_check); me->VisitNearbyObject(max_range, checker); } if (me->GetUInt32Value(UNIT_CREATED_BY_SPELL) == 3599) // Searing Totem { if (me->GetOwner() && me->GetOwner()->getVictim()) { i_victimGuid = me->GetOwner()->getVictim()->GetGUID(); victim = i_victimGuid ? ObjectAccessor::GetUnit(*me, i_victimGuid) : NULL; if (victim) { me->SetTarget(i_victimGuid); me->SetInCombatWith(victim); } } } // If have target if (victim) { // remember i_victimGuid = victim->GetGUID(); // attack me->SetInFront(victim); // client change orientation by self me->CastSpell(victim, me->ToTotem()->GetSpell(), false); } else i_victimGuid = 0; }
void HandleStormSequence(Unit* Cloud) // 1: begin, 2-9: tick, 10: end { if (StormCount < 10 && StormCount > 1) { // deal damage int32 bp0 = 800; for (uint8 i = 2; i < StormCount; ++i) bp0 *= 2; CellCoord p(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY())); Cell cell(p); cell.SetNoCreate(); std::list<Unit*> tempUnitMap; { Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(me, me, SIZE_OF_GRIDS); Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(me, tempUnitMap, u_check); TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher); TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher); cell.Visit(p, world_unit_searcher, *me->GetMap(), *me, SIZE_OF_GRIDS); cell.Visit(p, grid_unit_searcher, *me->GetMap(), *me, SIZE_OF_GRIDS); } // deal damage for (std::list<Unit*>::const_iterator i = tempUnitMap.begin(); i != tempUnitMap.end(); ++i) { if (Unit* target = (*i)) { if (Cloud && !Cloud->IsWithinDist(target, 6, false)) Cloud->CastCustomSpell(target, SPELL_ZAP, &bp0, NULL, NULL, true, 0, 0, me->GetGUID()); } } // visual float x, y, z; z = me->GetPositionZ(); for (uint8 i = 0; i < 5+rand()%5; ++i) { x = 343.0f+rand()%60; y = 1380.0f+rand()%60; if (Unit* trigger = me->SummonTrigger(x, y, z, 0, 2000)) { trigger->setFaction(35); trigger->SetMaxHealth(100000); trigger->SetHealth(100000); trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); if (Cloud) Cloud->CastCustomSpell(trigger, /*43661*/SPELL_ZAP, &bp0, NULL, NULL, true, 0, 0, Cloud->GetGUID()); } } } ++StormCount; if (StormCount > 10) { StormCount = 0; // finish events.ScheduleEvent(EVENT_SUMMON_EAGLES, 5000); me->InterruptNonMeleeSpells(false); CloudGUID = 0; if (Cloud) Cloud->DealDamage(Cloud, Cloud->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); SetWeather(WEATHER_STATE_FINE, 0.0f); isRaining = false; } events.ScheduleEvent(EVENT_STORM_SEQUENCE, 1000); }
void TotemAI::UpdateAI(const uint32 /*diff*/) { if (me->ToTotem()->GetTotemType() != TOTEM_ACTIVE) return; if (!me->isAlive() || me->IsNonMeleeSpellCasted(false)) return; // Search spell SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->ToTotem()->GetSpell()); if (!spellInfo) return; // Get spell range float max_range = spellInfo->GetMaxRange(false); // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems // pointer to appropriate target if found any Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(*me, i_victimGuid) : NULL; Unit* tmpvictim = 0; // Search victim if no, not attackable, or out of range, or friendly (possible in case duel end) if (!victim || (!victim->isTargetableForAttack() || !me->IsWithinDistInMap(victim, max_range) || me->IsFriendlyTo(victim) || !me->canSeeOrDetect(victim))) { Trinity::NearestAttackableUnitInObjectRangeCheck u_check(me, me, max_range); Trinity::UnitLastSearcher<Trinity::NearestAttackableUnitInObjectRangeCheck> checker(me, victim, u_check); me->VisitNearbyObject(max_range, checker); tmpvictim = victim; } else if(!(victim->HasAura(FLAME_SHOCK, me->GetOwnerGUID()) || victim->HasAura(STORMSTRIKE, me->GetOwnerGUID()))) tmpvictim = victim; Unit* owner = me->GetOwner(); // looking for attacker with specific auras, do only if new victim found in radius or current victim has no aura if (owner && tmpvictim) { if (Unit* ownervictim = owner->getVictim()) { //Owner's target is priority if (me->IsWithinDistInMap(ownervictim, max_range) && (ownervictim->HasAura(FLAME_SHOCK, owner->GetGUID()) || ownervictim->HasAura(STORMSTRIKE, owner->GetGUID()))) victim = ownervictim; else { Unit::AttackerSet attackers = owner->getAttackers(); for (Unit::AttackerSet::iterator itr = attackers.begin(); itr != attackers.end(); ++itr) { tmpvictim = *itr; if (me->IsWithinDistInMap(tmpvictim, max_range) && (tmpvictim->HasAura(FLAME_SHOCK, owner->GetGUID()) || tmpvictim->HasAura(STORMSTRIKE, owner->GetGUID()))) victim = tmpvictim; } } } } // If have target if (victim) { // remember i_victimGuid = victim->GetGUID(); // attack me->SetInFront(victim); // client change orientation by self me->CastSpell(victim, me->ToTotem()->GetSpell(), false, NULL, NULL, me->GetOwnerGUID()); } else i_victimGuid = 0; }
bool OPvPCapturePoint::Update(uint32 diff) { if(!m_capturePoint) return false; float radius = m_capturePoint->GetGOInfo()->capturePoint.radius; for (uint32 team = 0; team < 2; ++team) { for (PlayerSet::iterator itr = m_activePlayers[team].begin(); itr != m_activePlayers[team].end();) { Player *player = *itr; ++itr; if(!m_capturePoint->IsWithinDistInMap(player, radius) || !player->IsOutdoorPvPActive()) HandlePlayerLeave(player); } } std::list<Player*> players; std::list<Unit *> targets; CellPair p(MaNGOS::ComputeCellPair(m_capturePoint->GetPositionX(), m_capturePoint->GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); { MaNGOS::AnyUnitInObjectRangeCheck u_check(m_capturePoint, radius); MaNGOS::UnitListSearcher<MaNGOS::AnyUnitInObjectRangeCheck> searcher(targets, u_check); TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher); TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher); cell.Visit(p, world_unit_searcher, *m_capturePoint->GetMap()); cell.Visit(p, grid_unit_searcher, *m_capturePoint->GetMap()); } for( std::list<Unit *>::iterator itr = targets.begin(); itr != targets.end(); ++itr ) if( (*itr)->GetTypeId() == TYPEID_PLAYER ) players.push_back((Player*)(*itr)); for (std::list<Player*>::iterator itr = players.begin(); itr != players.end(); ++itr) { if((*itr)->IsOutdoorPvPActive()) { if(m_activePlayers[(*itr)->GetTeamId()].insert(*itr).second) HandlePlayerEnter(*itr); } } // get the difference of numbers float fact_diff = ((float)m_activePlayers[0].size() - (float)m_activePlayers[1].size()) * diff / OUTDOORPVP_OBJECTIVE_UPDATE_INTERVAL; if(!fact_diff) return false; uint32 Challenger = 0; float maxDiff = m_maxSpeed * diff; if(fact_diff < 0) { // horde is in majority, but it's already horde-controlled -> no change if(m_State == OBJECTIVESTATE_HORDE && m_value <= -m_maxValue) return false; if(fact_diff < -maxDiff) fact_diff = -maxDiff; Challenger = HORDE; } else { // ally is in majority, but it's already ally-controlled -> no change if(m_State == OBJECTIVESTATE_ALLIANCE && m_value >= m_maxValue) return false; if(fact_diff > maxDiff) fact_diff = maxDiff; Challenger = ALLIANCE; } float oldValue = m_value; TeamId oldTeam = m_team; m_OldState = m_State; m_value += fact_diff; if(m_value < -m_minValue) // red { if(m_value < -m_maxValue) m_value = -m_maxValue; m_State = OBJECTIVESTATE_HORDE; m_team = TEAM_HORDE; } else if(m_value > m_minValue) // blue { if(m_value > m_maxValue) m_value = m_maxValue; m_State = OBJECTIVESTATE_ALLIANCE; m_team = TEAM_ALLIANCE; } else if(oldValue * m_value <= 0) // grey, go through mid point { // if challenger is ally, then n->a challenge if(Challenger == ALLIANCE) m_State = OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE; // if challenger is horde, then n->h challenge else if(Challenger == HORDE) m_State = OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE; m_team = TEAM_NEUTRAL; } else // grey, did not go through mid point { // old phase and current are on the same side, so one team challenges the other if(Challenger == ALLIANCE && (m_OldState == OBJECTIVESTATE_HORDE || m_OldState == OBJECTIVESTATE_NEUTRAL_HORDE_CHALLENGE)) m_State = OBJECTIVESTATE_HORDE_ALLIANCE_CHALLENGE; else if(Challenger == HORDE && (m_OldState == OBJECTIVESTATE_ALLIANCE || m_OldState == OBJECTIVESTATE_NEUTRAL_ALLIANCE_CHALLENGE)) m_State = OBJECTIVESTATE_ALLIANCE_HORDE_CHALLENGE; m_team = TEAM_NEUTRAL; } if(m_value != oldValue) SendChangePhase(); if(m_OldState != m_State) { //sLog.outError("%u->%u", m_OldState, m_State); if(oldTeam != m_team) ChangeTeam(oldTeam); ChangeState(); return true; } return false; }