Index: /trunk/src/game/Creature.h
===================================================================
--- /trunk/src/game/Creature.h (revision 123)
+++ /trunk/src/game/Creature.h (revision 135)
@@ -572,4 +572,6 @@
         void GetCombatStartPosition(float &x, float &y, float &z) { x = CombatStartX; y = CombatStartY; z = CombatStartZ; }
 
+        uint32 GetGlobalCooldown() const { return m_GlobalCooldown; }
+
     protected:
         bool CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL);
Index: /trunk/src/game/PetHandler.cpp
===================================================================
--- /trunk/src/game/PetHandler.cpp (revision 102)
+++ /trunk/src/game/PetHandler.cpp (revision 135)
@@ -167,4 +167,7 @@
                 unit_target = NULL;
 
+            if (((Creature*)pet)->GetGlobalCooldown() > 0)
+                return;
+
             // do not cast unknown spells
             SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid );
@@ -602,4 +605,7 @@
     }
 
+    if (pet->GetGlobalCooldown() > 0)
+        return;
+
     SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid);
     if(!spellInfo)
Index: /trunk/src/game/PetAI.cpp
===================================================================
--- /trunk/src/game/PetAI.cpp (revision 102)
+++ /trunk/src/game/PetAI.cpp (revision 135)
@@ -39,5 +39,5 @@
 }
 
-PetAI::PetAI(Creature &c) : i_pet(c), i_victimGuid(0), i_tracker(TIME_INTERVAL_LOOK)
+PetAI::PetAI(Creature &c) : i_pet(c), i_tracker(TIME_INTERVAL_LOOK), inCombat(false)
 {
     m_AllySet.clear();
@@ -66,5 +66,5 @@
 void PetAI::AttackStart(Unit *u)
 {
-    if( i_pet.getVictim() || !u || i_pet.isPet() && ((Pet&)i_pet).getPetType()==MINI_PET )
+    if( inCombat || !u || (i_pet.isPet() && ((Pet&)i_pet).getPetType() == MINI_PET) )
         return;
 
@@ -76,6 +76,6 @@
         // hope it doesn't start to leak memory without this :-/
         //i_pet->Clear();
-        i_victimGuid = u->GetGUID();
         i_pet.GetMotionMaster()->MoveChase(u);
+        inCombat = true;
     }
 }
@@ -92,7 +92,4 @@
 bool PetAI::_needToStop() const
 {
-    if(!i_pet.getVictim() || !i_pet.isAlive())
-        return true;
-
     // This is needed for charmed creatures, as once their target was reset other effects can trigger threat
     if(i_pet.isCharmed() && i_pet.getVictim() == i_pet.GetCharmer())
@@ -104,14 +101,5 @@
 void PetAI::_stopAttack()
 {
-    if( !i_victimGuid )
-        return;
-
-    Unit* victim = ObjectAccessor::GetUnit(i_pet, i_victimGuid );
-
-    if ( !victim )
-        return;
-
-    assert(!i_pet.getVictim() || i_pet.getVictim() == victim);
-
+    inCombat = false;
     if( !i_pet.isAlive() )
     {
@@ -120,29 +108,8 @@
         i_pet.GetMotionMaster()->Clear();
         i_pet.GetMotionMaster()->MoveIdle();
-        i_victimGuid = 0;
         i_pet.CombatStop();
         i_pet.getHostilRefManager().deleteReferences();
 
         return;
-    }
-    else if( !victim  )
-    {
-        DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_pet.GetGUIDLow());
-    }
-    else if( !victim->isAlive() )
-    {
-        DEBUG_LOG("Creature stopped attacking cuz his victim is dead [guid=%u]", i_pet.GetGUIDLow());
-    }
-    else if( victim->HasStealthAura() )
-    {
-        DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", i_pet.GetGUIDLow());
-    }
-    else if( victim->isInFlight() )
-    {
-        DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", i_pet.GetGUIDLow());
-    }
-    else
-    {
-        DEBUG_LOG("Creature stopped attacking due to target out run him [guid=%u]", i_pet.GetGUIDLow());
     }
 
@@ -159,5 +126,4 @@
         i_pet.GetMotionMaster()->MoveIdle();
     }
-    i_victimGuid = 0;
     i_pet.AttackStop();
 }
@@ -165,7 +131,6 @@
 void PetAI::UpdateAI(const uint32 diff)
 {
-    // update i_victimGuid if i_pet.getVictim() !=0 and changed
-    if(i_pet.getVictim())
-        i_victimGuid = i_pet.getVictim()->GetGUID();
+    if (!i_pet.isAlive())
+        return;
 
     Unit* owner = i_pet.GetCharmerOrOwner();
@@ -177,11 +142,14 @@
         m_updateAlliesTimer -= diff;
 
+    if (inCombat && i_pet.getVictim() == NULL)
+        _stopAttack();
+
     // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.
-    if( i_victimGuid )
+    if( i_pet.getVictim() != NULL )
     {
         if( _needToStop() )
         {
             DEBUG_LOG("Pet AI stoped attacking [guid=%u]", i_pet.GetGUIDLow());
-            _stopAttack();                                  // i_victimGuid == 0 && i_pet.getVictim() == NULL now
+            _stopAttack();
             return;
         }
@@ -229,73 +197,94 @@
     }
 
-    //Autocast
-    HM_NAMESPACE::hash_map<uint32, Unit*> targetMap;
-    targetMap.clear();
-    SpellCastTargets NULLtargets;
-
-    for (uint8 i = 0; i < i_pet.GetPetAutoSpellSize(); i++)
-    {
-        uint32 spellID = i_pet.GetPetAutoSpellOnPos(i);
-        if (!spellID)
-            continue;
-
-        SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID);
-        if (!spellInfo)
-            continue;
-
-        Spell *spell = new Spell(&i_pet, spellInfo, false, 0);
-
-        if(!IsPositiveSpell(spellInfo->Id) && i_pet.getVictim() && !_needToStop() && !i_pet.hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(i_pet.getVictim()))
-            targetMap[spellID] = i_pet.getVictim();
-        else
-        {
-            spell->m_targets = NULLtargets;
-            for(std::set<uint64>::iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
-            {
-                Unit* Target = ObjectAccessor::GetUnit(i_pet,*tar);
-
-                //only buff targets that are in combat, unless the spell can only be cast while out of combat
-                if(!Target || (!Target->isInCombat() && !IsNonCombatSpell(spellInfo)))
+    if (i_pet.GetGlobalCooldown() == 0 && !i_pet.IsNonMeleeSpellCasted(false))
+    {
+        //Autocast
+        for (uint8 i = 0; i < i_pet.GetPetAutoSpellSize(); i++)
+        {
+            uint32 spellID = i_pet.GetPetAutoSpellOnPos(i);
+            if (!spellID)
+                continue;
+
+            SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID);
+            if (!spellInfo)
+                continue;
+
+            // ignore some combinations of combat state and combat/noncombat spells
+            if (!inCombat)
+            {
+                if (!IsPositiveSpell(spellInfo->Id))
                     continue;
-                if(spell->CanAutoCast(Target))
-                    targetMap[spellID] = Target;
-            }
-        }
-
-        delete spell;
-    }
-
-    //found units to cast on to
-    if(!targetMap.empty())
-    {
-        uint32 index = urand(1, targetMap.size());
-        HM_NAMESPACE::hash_map<uint32, Unit*>::iterator itr;
-        uint32 i;
-        for(itr = targetMap.begin(), i = 1; i < index; ++itr, ++i);
-
-        SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
-
-        Spell *spell = new Spell(&i_pet, spellInfo, false);
-
-        SpellCastTargets targets;
-        targets.setUnitTarget( itr->second );
-
-        if(!i_pet.HasInArc(M_PI, itr->second))
-        {
-            i_pet.SetInFront(itr->second);
-            if( itr->second->GetTypeId() == TYPEID_PLAYER )
-                i_pet.SendUpdateToPlayer( (Player*)itr->second );
-
-            if(owner && owner->GetTypeId() == TYPEID_PLAYER)
-                i_pet.SendUpdateToPlayer( (Player*)owner );
-        }
-
-        i_pet.AddCreatureSpellCooldown(itr->first);
-        if(i_pet.isPet())
-            ((Pet*)&i_pet)->CheckLearning(itr->first);
-
-        spell->prepare(&targets);
-    }
-    targetMap.clear();
+            }
+            else
+            {
+                if (IsNonCombatSpell(spellInfo))
+                    continue;
+            }
+
+            Spell *spell = new Spell(&i_pet, spellInfo, false, 0);
+
+            if(inCombat && !i_pet.hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(i_pet.getVictim()))
+            {
+                m_targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(i_pet.getVictim(), spell));
+                continue;
+            }
+            else
+            {
+                bool spellUsed = false;
+                for(std::set<uint64>::iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
+                {
+                    Unit* Target = ObjectAccessor::GetUnit(i_pet,*tar);
+
+                    //only buff targets that are in combat, unless the spell can only be cast while out of combat
+                    if(!Target)
+                        continue;
+
+                    if(spell->CanAutoCast(Target))
+                    {
+                        m_targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(Target, spell));
+                        spellUsed = true;
+                        break;
+                    }
+                }
+                if (!spellUsed)
+                    delete spell;
+            }
+        }
+
+        //found units to cast on to
+        if(!m_targetSpellStore.empty())
+        {
+            uint32 index = urand(0, m_targetSpellStore.size() - 1);
+
+            Spell* spell  = m_targetSpellStore[index].second;
+            Unit*  target = m_targetSpellStore[index].first;
+
+            m_targetSpellStore.erase(m_targetSpellStore.begin() + index);
+
+            SpellCastTargets targets;
+            targets.setUnitTarget( target );
+
+            if( !i_pet.HasInArc(M_PI, target) )
+            {
+                i_pet.SetInFront(target);
+                if( target->GetTypeId() == TYPEID_PLAYER )
+                    i_pet.SendUpdateToPlayer( (Player*)target );
+
+                if(owner && owner->GetTypeId() == TYPEID_PLAYER)
+                    i_pet.SendUpdateToPlayer( (Player*)owner );
+            }
+
+            i_pet.AddCreatureSpellCooldown(spell->m_spellInfo->Id);
+            if(i_pet.isPet())
+                ((Pet*)&i_pet)->CheckLearning(spell->m_spellInfo->Id);
+
+            spell->prepare(&targets);
+        }
+        while (!m_targetSpellStore.empty())
+        {
+            delete m_targetSpellStore.begin()->second;
+            m_targetSpellStore.erase(m_targetSpellStore.begin());
+        }
+    }
 }
 
Index: /trunk/src/game/PetAI.h
===================================================================
--- /trunk/src/game/PetAI.h (revision 102)
+++ /trunk/src/game/PetAI.h (revision 135)
@@ -26,4 +26,5 @@
 
 class Creature;
+class Spell;
 
 class TRINITY_DLL_DECL PetAI : public CreatureAI
@@ -39,7 +40,7 @@
         void AttackedBy(Unit*);
         bool IsVisible(Unit *) const;
+        void JustDied(Unit* who) { _stopAttack(); }
 
         void UpdateAI(const uint32);
-        void UpdateAllies();
         static int Permissible(const Creature *);
 
@@ -49,10 +50,14 @@
         void _stopAttack(void);
 
+        void UpdateAllies();
+
         Creature &i_pet;
-        uint64 i_victimGuid;
+        bool inCombat;
         TimeTracker i_tracker;
-        //uint32 i_RepeatAction;
         std::set<uint64> m_AllySet;
         uint32 m_updateAlliesTimer;
+
+        typedef std::pair<Unit*, Spell*> TargetSpellPair;
+        std::vector<TargetSpellPair> m_targetSpellStore;
 };
 #endif
Index: /trunk/src/game/ObjectMgr.cpp
===================================================================
--- /trunk/src/game/ObjectMgr.cpp (revision 126)
+++ /trunk/src/game/ObjectMgr.cpp (revision 135)
@@ -6785,9 +6785,15 @@
     wstrToLower( wname );
 
+    // Alternative first GameTele what contains wnameLow as substring in case no GameTele location found
+    const GameTele* alt = NULL;
     for(GameTeleMap::const_iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr)
+    {
         if(itr->second.wnameLow == wname)
             return &itr->second;
-
-    return NULL;
+        else if (alt == NULL && itr->second.wnameLow.find(wname) != std::wstring::npos)
+            alt = &itr->second;
+    }
+
+    return alt;
 }
 
