diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bindings/scripts/include/sc_creature.cpp | 3 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/creature/mob_event_ai.cpp | 1 | ||||
-rw-r--r-- | src/game/Creature.cpp | 13 | ||||
-rw-r--r-- | src/game/CreatureGroups.h | 4 | ||||
-rw-r--r-- | src/game/Map.cpp | 39 | ||||
-rw-r--r-- | src/game/Map.h | 1 | ||||
-rw-r--r-- | src/game/MotionMaster.cpp | 71 | ||||
-rw-r--r-- | src/game/MotionMaster.h | 33 | ||||
-rw-r--r-- | src/game/PetAI.cpp | 1 | ||||
-rw-r--r-- | src/game/ThreatManager.cpp | 9 | ||||
-rw-r--r-- | src/game/ThreatManager.h | 2 | ||||
-rw-r--r-- | src/game/Unit.cpp | 36 |
12 files changed, 146 insertions, 67 deletions
diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp index 12992eedc52..0caa102d56d 100644 --- a/src/bindings/scripts/include/sc_creature.cpp +++ b/src/bindings/scripts/include/sc_creature.cpp @@ -86,7 +86,6 @@ void ScriptedAI::AttackStart(Unit* who, bool melee) { m_creature->AddThreat(who, 0.0f); m_creature->SetInCombatWith(who); - who->SetInCombatWith(m_creature); if (!InCombat) { @@ -110,7 +109,6 @@ void ScriptedAI::AttackStart(Unit* who) { m_creature->AddThreat(who, 0.0f); m_creature->SetInCombatWith(who); - who->SetInCombatWith(m_creature); if (!InCombat) { @@ -823,7 +821,6 @@ void Scripted_NoMovementAI::AttackStart(Unit* who) { m_creature->AddThreat(who, 0.0f); m_creature->SetInCombatWith(who); - who->SetInCombatWith(m_creature); if (!InCombat) { diff --git a/src/bindings/scripts/scripts/creature/mob_event_ai.cpp b/src/bindings/scripts/scripts/creature/mob_event_ai.cpp index 456a88ab3bb..eee4269e12c 100644 --- a/src/bindings/scripts/scripts/creature/mob_event_ai.cpp +++ b/src/bindings/scripts/scripts/creature/mob_event_ai.cpp @@ -1152,7 +1152,6 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI //Begin melee attack if we are within range m_creature->AddThreat(who, 0.0f); m_creature->SetInCombatWith(who); - who->SetInCombatWith(m_creature); if (!InCombat) { diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index ad8d01aeca0..8745d86caa9 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1671,16 +1671,15 @@ bool Creature::FallGround() if (getDeathState() == DEAD_FALLING) return false; - // Let's do with no vmap because no way to get far distance with vmap high call - float tz = GetMap()->GetHeight(GetPositionX(), GetPositionY(), GetPositionZ(), false); - - // Abort too if the ground is very near - if (fabs(GetPositionZ() - tz) < 0.1f) + float x, y, z; + GetPosition(x, y, z); + float ground_Z = GetMap()->GetVmapHeight(x, y, z, true); + if (fabs(ground_Z - z) < 0.1f) return false; Unit::setDeathState(DEAD_FALLING); - GetMotionMaster()->MovePoint(0, GetPositionX(), GetPositionY(), tz); - Relocate(GetPositionX(), GetPositionY(), tz); + GetMotionMaster()->MovePoint(0, x, y, ground_Z); + Relocate(x, y, ground_Z); return true; } diff --git a/src/game/CreatureGroups.h b/src/game/CreatureGroups.h index 0f4474106de..dd7da865955 100644 --- a/src/game/CreatureGroups.h +++ b/src/game/CreatureGroups.h @@ -58,7 +58,9 @@ class CreatureGroup bool isEmpty() {return CreatureGroupMembers.empty();} }; -extern UNORDERED_MAP<uint32, CreatureGroup*> CreatureGroupHolder; +typedef UNORDERED_MAP<uint32, CreatureGroup*> CreatureGroupHolderType; + +extern CreatureGroupHolderType CreatureGroupHolder; extern UNORDERED_MAP<uint32, FormationMember*> CreatureGroupMap; #define formation_mgr Trinity::Singleton<CreatureGroupManager>::Instance() diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 1af68fce07e..cdc78ca41a5 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -1265,8 +1265,47 @@ float Map::GetHeight(float x, float y, float z, bool pUseVmaps) const } } +float Map::GetVmapHeight(float x, float y, float z, bool useMaps) const +{ + float mapHeight; + float vmapHeight; + if (useMaps) + { + mapHeight = GetHeight(x, y, z, false); + if (fabs(mapHeight - z) < 0.1) + return mapHeight; + } + else + mapHeight = INVALID_HEIGHT; + VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); + if (vmgr->isLineOfSightCalcEnabled()) + bool result = vmgr->getObjectHitPos(GetId(), x, y, z + 2.0f, x, y, mapHeight, x, y, vmapHeight, 0); + else + return INVALID_HEIGHT; + return vmapHeight; +} + uint16 Map::GetAreaFlag(float x, float y, float z) const { + float mapHeight; + float vmapHeight; + if (useMaps) + { + mapHeight = GetHeight(x, y, z, false); + if (fabs(mapHeight - z) < 0.1) + return mapHeight; + } + else + mapHeight = INVALID_HEIGHT; + VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); + if (vmgr->isLineOfSightCalcEnabled()) + bool result = vmgr->getObjectHitPos(GetId(), x, y, z + 2.0f, x, y, mapHeight, x, y, vmapHeight, 0); + else + return INVALID_HEIGHT; + return vmapHeight; +} + +{ //local x,y coords float lx,ly; int gx,gy; diff --git a/src/game/Map.h b/src/game/Map.h index 7e885ebf61f..bae8889d3ee 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -183,6 +183,7 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O // some calls like isInWater should not use vmaps due to processor power // can return INVALID_HEIGHT if under z+2 z coord not found height float GetHeight(float x, float y, float z, bool pCheckVMap=true) const; + float GetVmapHeight(float x, float y, float z, bool useMaps) const; bool IsInWater(float x, float y, float z) const; // does not use z pos. This is for future use uint16 GetAreaFlag(float x, float y, float z) const; diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp index 36bdbbb3a01..39260362212 100644 --- a/src/game/MotionMaster.cpp +++ b/src/game/MotionMaster.cpp @@ -111,7 +111,7 @@ MotionMaster::MoveRandom(float spawndist) if(i_owner->GetTypeId()==TYPEID_UNIT) { DEBUG_LOG("Creature (GUID: %u) start moving random", i_owner->GetGUIDLow() ); - Mutate(new RandomMovementGenerator<Creature>(spawndist)); + Mutate(new RandomMovementGenerator<Creature>(spawndist), MOTION_SLOT_IDLE); } } @@ -129,23 +129,27 @@ MotionMaster::MovementExpired(bool reset) delete curr; assert( !empty() ); - while( !empty() && top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE ) + while(!top()) + --i_top; + /*while( !empty() && top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE ) { // Should check if target is still valid? If not valid it will crash. curr = top(); curr->Finalize(*i_owner); pop(); delete curr; - } + }*/ if( empty() ) Initialize(); if (reset) top()->Reset(*i_owner); } -void MotionMaster::MoveIdle() +void MotionMaster::MoveIdle(MovementSlot slot) { - if( empty() || !isStatic( top() ) ) - push( &si_idleMovement ); + //if( empty() || !isStatic( top() ) ) + // push( &si_idleMovement ); + if(!isStatic(Impl[slot])) + Mutate(&si_idleMovement, slot); } void @@ -159,7 +163,7 @@ MotionMaster::MoveTargetedHome() if(i_owner->GetTypeId()==TYPEID_UNIT && !((Creature*)i_owner)->GetCharmerOrOwnerGUID()) { DEBUG_LOG("Creature (Entry: %u GUID: %u) targeted home", i_owner->GetEntry(), i_owner->GetGUIDLow()); - Mutate(new HomeMovementGenerator<Creature>()); + Mutate(new HomeMovementGenerator<Creature>(), MOTION_SLOT_ACTIVE); } else if(i_owner->GetTypeId()==TYPEID_UNIT && ((Creature*)i_owner)->GetCharmerOrOwnerGUID()) { @@ -172,7 +176,7 @@ MotionMaster::MoveTargetedHome() DEBUG_LOG("Following %s (GUID: %u)", target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() ); - Mutate(new TargetedMovementGenerator<Creature>(*target,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE)); + Mutate(new TargetedMovementGenerator<Creature>(*target,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE), MOTION_SLOT_ACTIVE); } } else @@ -187,13 +191,13 @@ MotionMaster::MoveConfused() if(i_owner->GetTypeId()==TYPEID_PLAYER) { DEBUG_LOG("Player (GUID: %u) move confused", i_owner->GetGUIDLow() ); - Mutate(new ConfusedMovementGenerator<Player>()); + Mutate(new ConfusedMovementGenerator<Player>(), MOTION_SLOT_CONTROLLED); } else { DEBUG_LOG("Creature (Entry: %u GUID: %u) move confused", i_owner->GetEntry(), i_owner->GetGUIDLow() ); - Mutate(new ConfusedMovementGenerator<Creature>()); + Mutate(new ConfusedMovementGenerator<Creature>(), MOTION_SLOT_CONTROLLED); } } @@ -211,7 +215,7 @@ MotionMaster::MoveChase(Unit* target, float dist, float angle) i_owner->GetGUIDLow(), target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", target->GetTypeId()==TYPEID_PLAYER ? i_owner->GetGUIDLow() : ((Creature*)i_owner)->GetDBTableGUIDLow() ); - Mutate(new TargetedMovementGenerator<Player>(*target,dist,angle)); + Mutate(new TargetedMovementGenerator<Player>(*target,dist,angle), MOTION_SLOT_ACTIVE); } else { @@ -219,7 +223,7 @@ MotionMaster::MoveChase(Unit* target, float dist, float angle) i_owner->GetEntry(), i_owner->GetGUIDLow(), target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() ); - Mutate(new TargetedMovementGenerator<Creature>(*target,dist,angle)); + Mutate(new TargetedMovementGenerator<Creature>(*target,dist,angle), MOTION_SLOT_ACTIVE); } } @@ -238,7 +242,7 @@ MotionMaster::MoveFollow(Unit* target, float dist, float angle) DEBUG_LOG("Player (GUID: %u) follow to %s (GUID: %u)", i_owner->GetGUIDLow(), target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", target->GetTypeId()==TYPEID_PLAYER ? i_owner->GetGUIDLow() : ((Creature*)i_owner)->GetDBTableGUIDLow() ); - Mutate(new TargetedMovementGenerator<Player>(*target,dist,angle)); + Mutate(new TargetedMovementGenerator<Player>(*target,dist,angle), MOTION_SLOT_ACTIVE); } else { @@ -246,7 +250,7 @@ MotionMaster::MoveFollow(Unit* target, float dist, float angle) i_owner->GetEntry(), i_owner->GetGUIDLow(), target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() ); - Mutate(new TargetedMovementGenerator<Creature>(*target,dist,angle)); + Mutate(new TargetedMovementGenerator<Creature>(*target,dist,angle), MOTION_SLOT_ACTIVE); } } @@ -256,13 +260,13 @@ MotionMaster::MovePoint(uint32 id, float x, float y, float z) if(i_owner->GetTypeId()==TYPEID_PLAYER) { DEBUG_LOG("Player (GUID: %u) targeted point (Id: %u X: %f Y: %f Z: %f)", i_owner->GetGUIDLow(), id, x, y, z ); - Mutate(new PointMovementGenerator<Player>(id,x,y,z)); + Mutate(new PointMovementGenerator<Player>(id,x,y,z), MOTION_SLOT_ACTIVE); } else { DEBUG_LOG("Creature (Entry: %u GUID: %u) targeted point (ID: %u X: %f Y: %f Z: %f)", i_owner->GetEntry(), i_owner->GetGUIDLow(), id, x, y, z ); - Mutate(new PointMovementGenerator<Creature>(id,x,y,z)); + Mutate(new PointMovementGenerator<Creature>(id,x,y,z), MOTION_SLOT_ACTIVE); } } @@ -277,7 +281,7 @@ MotionMaster::MoveFleeing(Unit* enemy) DEBUG_LOG("Player (GUID: %u) flee from %s (GUID: %u)", i_owner->GetGUIDLow(), enemy->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", enemy->GetTypeId()==TYPEID_PLAYER ? enemy->GetGUIDLow() : ((Creature*)enemy)->GetDBTableGUIDLow() ); - Mutate(new FleeingMovementGenerator<Player>(enemy->GetGUID())); + Mutate(new FleeingMovementGenerator<Player>(enemy->GetGUID()), MOTION_SLOT_CONTROLLED); } else { @@ -285,7 +289,7 @@ MotionMaster::MoveFleeing(Unit* enemy) i_owner->GetEntry(), i_owner->GetGUIDLow(), enemy->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", enemy->GetTypeId()==TYPEID_PLAYER ? enemy->GetGUIDLow() : ((Creature*)enemy)->GetDBTableGUIDLow() ); - Mutate(new FleeingMovementGenerator<Creature>(enemy->GetGUID())); + Mutate(new FleeingMovementGenerator<Creature>(enemy->GetGUID()), MOTION_SLOT_CONTROLLED); } } @@ -296,7 +300,7 @@ MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode) { DEBUG_LOG("Player (GUID: %u) taxi to (Path %u node %u)", i_owner->GetGUIDLow(), path, pathnode); FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(path,pathnode); - Mutate(mgen); + Mutate(mgen, MOTION_SLOT_CONTROLLED); } else { @@ -319,12 +323,25 @@ MotionMaster::MoveDistract(uint32 timer) } DistractMovementGenerator* mgen = new DistractMovementGenerator(timer); - Mutate(mgen); + Mutate(mgen, MOTION_SLOT_CONTROLLED); } -void MotionMaster::Mutate(MovementGenerator *m) +void MotionMaster::Mutate(MovementGenerator *m, MovementSlot slot) { - if (!empty()) + if(MovementGenerator *curr = Impl[slot]) + { + curr->Finalize(*i_owner); + if( !isStatic( curr ) ) + delete curr; + } + else if(i_top < slot) + { + i_top = slot; + } + m->Initialize(*i_owner); + Impl[slot] = m; + + /*if (!empty()) { switch(top()->GetMovementGeneratorType()) { @@ -336,7 +353,7 @@ void MotionMaster::Mutate(MovementGenerator *m) } } m->Initialize(*i_owner); - push(m); + push(m);*/ } void MotionMaster::MovePath(uint32 path_id, bool repeatable) @@ -356,7 +373,7 @@ void MotionMaster::MovePath(uint32 path_id, bool repeatable) //i_owner->GetTypeId()==TYPEID_PLAYER ? //Mutate(new WaypointMovementGenerator<Player>(path_id, repeatable)): - Mutate(new WaypointMovementGenerator<Creature>(path_id, repeatable)); + Mutate(new WaypointMovementGenerator<Creature>(path_id, repeatable), MOTION_SLOT_IDLE); DEBUG_LOG("%s (GUID: %u) start moving over path(Id:%u, repeatable: %s)", i_owner->GetTypeId()==TYPEID_PLAYER ? "Player" : "Creature", @@ -365,11 +382,13 @@ void MotionMaster::MovePath(uint32 path_id, bool repeatable) void MotionMaster::propagateSpeedChange() { - Impl::container_type::iterator it = Impl::c.begin(); + /*Impl::container_type::iterator it = Impl::c.begin(); for ( ;it != end(); ++it) { (*it)->unitSpeedChanged(); - } + }*/ + for(int i = 0; i <= i_top; ++i) + Impl[i]->unitSpeedChanged(); } MovementGeneratorType MotionMaster::GetCurrentMovementGeneratorType() const diff --git a/src/game/MotionMaster.h b/src/game/MotionMaster.h index 209b2cf176e..d275bdd4b90 100644 --- a/src/game/MotionMaster.h +++ b/src/game/MotionMaster.h @@ -47,31 +47,48 @@ enum MovementGeneratorType DISTRACT_MOTION_TYPE = 10, // IdleMovementGenerator.h }; -class TRINITY_DLL_SPEC MotionMaster : private std::stack<MovementGenerator *> +enum MovementSlot +{ + MOTION_SLOT_IDLE, + MOTION_SLOT_ACTIVE, + MOTION_SLOT_CONTROLLED, + MAX_MOTION_SLOT, +}; + +class TRINITY_DLL_SPEC MotionMaster //: private std::stack<MovementGenerator *> { private: - typedef std::stack<MovementGenerator *> Impl; + //typedef std::stack<MovementGenerator *> Impl; + typedef MovementGenerator* _Ty; + _Ty Impl[MAX_MOTION_SLOT]; + int i_top; + + int size() const { return i_top + 1; } + bool empty() const { return i_top < 0; } + void pop() { Impl[i_top] = NULL; --i_top; } + void push(_Ty _Val) { ++i_top; Impl[i_top] = _Val; } public: - explicit MotionMaster(Unit *unit) : i_owner(unit) {} + explicit MotionMaster(Unit *unit) : i_owner(unit), i_top(-1) {} ~MotionMaster(); void Initialize(); - MovementGenerator* operator->(void) { return top(); } + //MovementGenerator* operator->(void) { return top(); } - using Impl::top; + _Ty top() const { return Impl[i_top]; } + /*using Impl::top; using Impl::empty; typedef Impl::container_type::const_iterator const_iterator; const_iterator begin() const { return Impl::c.begin(); } - const_iterator end() const { return Impl::c.end(); } + const_iterator end() const { return Impl::c.end(); }*/ void UpdateMotion(const uint32 &diff); void Clear(bool reset = true); void MovementExpired(bool reset = true); - void MoveIdle(); + void MoveIdle(MovementSlot slot = MOTION_SLOT_ACTIVE); void MoveTargetedHome(); void MoveRandom(float spawndist = 0.0f); void MoveFollow(Unit* target, float dist, float angle); @@ -89,7 +106,7 @@ class TRINITY_DLL_SPEC MotionMaster : private std::stack<MovementGenerator *> bool GetDestination(float &x, float &y, float &z); private: - void Mutate(MovementGenerator *m); // use Move* functions instead + void Mutate(MovementGenerator *m, MovementSlot slot); // use Move* functions instead Unit *i_owner; }; diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index 82259cbba4d..abb62ade7da 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -74,7 +74,6 @@ void PetAI::AttackStart(Unit *u) if(i_pet.Attack(u,true)) { i_pet.SetInCombatWith(u); - u->SetInCombatWith(&i_pet); i_pet.clearUnitState(UNIT_STAT_FOLLOW); // TMGs call CreatureRelocation which via MoveInLineOfSight can call this function diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp index 1af12bedc02..a78dfc09373 100644 --- a/src/game/ThreatManager.cpp +++ b/src/game/ThreatManager.cpp @@ -372,10 +372,15 @@ void ThreatManager::addThreat(Unit* pVictim, float pThreat, SpellSchoolMask scho { float reducedThreat = threat * pVictim->GetReducedThreatPercent() / 100; threat -= reducedThreat; - if(pVictim->GetMisdirectionTarget()) - iThreatContainer.addThreat(pVictim->GetMisdirectionTarget(), reducedThreat); + if(Unit *unit = pVictim->GetMisdirectionTarget()) + _addThreat(unit, reducedThreat); } + _addThreat(pVictim, threat); +} + +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) diff --git a/src/game/ThreatManager.h b/src/game/ThreatManager.h index 1cecee3a4be..d4a3910e91e 100644 --- a/src/game/ThreatManager.h +++ b/src/game/ThreatManager.h @@ -175,6 +175,8 @@ class TRINITY_DLL_SPEC ThreatManager Unit* iOwner; ThreatContainer iThreatContainer; ThreatContainer iThreatOfflineContainer; + + void _addThreat(Unit* target, float threat); public: explicit ThreatManager(Unit *pOwner); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index e497ab25d2b..23adc211ec3 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -8570,23 +8570,12 @@ void Unit::CombatStart(Unit* target) if(!target->IsStandState()/* && !target->hasUnitState(UNIT_STAT_STUNNED)*/) target->SetStandState(PLAYER_STATE_NONE); - //Call creature group update - if(GetTypeId()==TYPEID_UNIT && ((Creature *)this)->GetFormationID() && - CreatureGroupHolder.find(((Creature *)this)->GetFormationID()) != CreatureGroupHolder.end()) - CreatureGroupHolder[((Creature *)this)->GetFormationID()]->MemberHasAttacked(((Creature *)this)); - if(!target->isInCombat() && target->GetTypeId() != TYPEID_PLAYER && !((Creature*)target)->HasReactState(REACT_PASSIVE) && ((Creature*)target)->AI()) - { - SetInCombatWith(target); - target->SetInCombatWith(this); ((Creature*)target)->AI()->AttackStart(this); - } - else - { - SetInCombatWith(target); - target->SetInCombatWith(this); - } + + SetInCombatWith(target); + target->SetInCombatWith(this); Unit *who = target->GetCharmerOrOwnerOrSelf(); if(who->GetTypeId() == TYPEID_PLAYER) @@ -8600,6 +8589,14 @@ void Unit::CombatStart(Unit* target) me->UpdatePvP(true); me->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT); } + + //Call creature group update + if(GetTypeId()==TYPEID_UNIT && ((Creature*)this)->GetFormationID()) + { + CreatureGroupHolderType::iterator itr = CreatureGroupHolder.find(((Creature*)this)->GetFormationID()); + if(itr != CreatureGroupHolder.end()) + itr->second->MemberHasAttacked(((Creature*)this)); + } } void Unit::SetInCombatState(bool PvP) @@ -9297,12 +9294,15 @@ bool Unit::SelectHostilTarget() } // search nearby enemy before enter evade mode - if(Unit *target = ((Creature*)this)->SelectNearestTarget()) + if(((Creature*)this)->HasReactState(REACT_AGGRESSIVE)) { - if(!((Creature*)this)->IsOutOfThreatArea(target)) + if(Unit *target = ((Creature*)this)->SelectNearestTarget()) { - ((Creature*)this)->AI()->AttackStart(target); - return true; + if(!((Creature*)this)->IsOutOfThreatArea(target)) + { + ((Creature*)this)->AI()->AttackStart(target); + return true; + } } } |