Changeset 135
- Timestamp:
- 11/19/08 13:39:16 (17 years ago)
- Location:
- trunk/src/game
- Files:
-
- 5 modified
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/game/Creature.h
r123 r135 572 572 void GetCombatStartPosition(float &x, float &y, float &z) { x = CombatStartX; y = CombatStartY; z = CombatStartZ; } 573 573 574 uint32 GetGlobalCooldown() const { return m_GlobalCooldown; } 575 574 576 protected: 575 577 bool CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL); -
trunk/src/game/ObjectMgr.cpp
r126 r135 6785 6785 wstrToLower( wname ); 6786 6786 6787 // Alternative first GameTele what contains wnameLow as substring in case no GameTele location found 6788 const GameTele* alt = NULL; 6787 6789 for(GameTeleMap::const_iterator itr = m_GameTeleMap.begin(); itr != m_GameTeleMap.end(); ++itr) 6790 { 6788 6791 if(itr->second.wnameLow == wname) 6789 6792 return &itr->second; 6790 6791 return NULL; 6793 else if (alt == NULL && itr->second.wnameLow.find(wname) != std::wstring::npos) 6794 alt = &itr->second; 6795 } 6796 6797 return alt; 6792 6798 } 6793 6799 -
trunk/src/game/PetAI.cpp
r102 r135 39 39 } 40 40 41 PetAI::PetAI(Creature &c) : i_pet(c), i_ victimGuid(0), i_tracker(TIME_INTERVAL_LOOK)41 PetAI::PetAI(Creature &c) : i_pet(c), i_tracker(TIME_INTERVAL_LOOK), inCombat(false) 42 42 { 43 43 m_AllySet.clear(); … … 66 66 void PetAI::AttackStart(Unit *u) 67 67 { 68 if( i _pet.getVictim() || !u || i_pet.isPet() && ((Pet&)i_pet).getPetType()==MINI_PET)68 if( inCombat || !u || (i_pet.isPet() && ((Pet&)i_pet).getPetType() == MINI_PET) ) 69 69 return; 70 70 … … 76 76 // hope it doesn't start to leak memory without this :-/ 77 77 //i_pet->Clear(); 78 i_victimGuid = u->GetGUID();79 78 i_pet.GetMotionMaster()->MoveChase(u); 79 inCombat = true; 80 80 } 81 81 } … … 92 92 bool PetAI::_needToStop() const 93 93 { 94 if(!i_pet.getVictim() || !i_pet.isAlive())95 return true;96 97 94 // This is needed for charmed creatures, as once their target was reset other effects can trigger threat 98 95 if(i_pet.isCharmed() && i_pet.getVictim() == i_pet.GetCharmer()) … … 104 101 void PetAI::_stopAttack() 105 102 { 106 if( !i_victimGuid ) 107 return; 108 109 Unit* victim = ObjectAccessor::GetUnit(i_pet, i_victimGuid ); 110 111 if ( !victim ) 112 return; 113 114 assert(!i_pet.getVictim() || i_pet.getVictim() == victim); 115 103 inCombat = false; 116 104 if( !i_pet.isAlive() ) 117 105 { … … 120 108 i_pet.GetMotionMaster()->Clear(); 121 109 i_pet.GetMotionMaster()->MoveIdle(); 122 i_victimGuid = 0;123 110 i_pet.CombatStop(); 124 111 i_pet.getHostilRefManager().deleteReferences(); 125 112 126 113 return; 127 }128 else if( !victim )129 {130 DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_pet.GetGUIDLow());131 }132 else if( !victim->isAlive() )133 {134 DEBUG_LOG("Creature stopped attacking cuz his victim is dead [guid=%u]", i_pet.GetGUIDLow());135 }136 else if( victim->HasStealthAura() )137 {138 DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", i_pet.GetGUIDLow());139 }140 else if( victim->isInFlight() )141 {142 DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", i_pet.GetGUIDLow());143 }144 else145 {146 DEBUG_LOG("Creature stopped attacking due to target out run him [guid=%u]", i_pet.GetGUIDLow());147 114 } 148 115 … … 159 126 i_pet.GetMotionMaster()->MoveIdle(); 160 127 } 161 i_victimGuid = 0;162 128 i_pet.AttackStop(); 163 129 } … … 165 131 void PetAI::UpdateAI(const uint32 diff) 166 132 { 167 // update i_victimGuid if i_pet.getVictim() !=0 and changed 168 if(i_pet.getVictim()) 169 i_victimGuid = i_pet.getVictim()->GetGUID(); 133 if (!i_pet.isAlive()) 134 return; 170 135 171 136 Unit* owner = i_pet.GetCharmerOrOwner(); … … 177 142 m_updateAlliesTimer -= diff; 178 143 144 if (inCombat && i_pet.getVictim() == NULL) 145 _stopAttack(); 146 179 147 // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc. 180 if( i_ victimGuid)148 if( i_pet.getVictim() != NULL ) 181 149 { 182 150 if( _needToStop() ) 183 151 { 184 152 DEBUG_LOG("Pet AI stoped attacking [guid=%u]", i_pet.GetGUIDLow()); 185 _stopAttack(); // i_victimGuid == 0 && i_pet.getVictim() == NULL now153 _stopAttack(); 186 154 return; 187 155 } … … 229 197 } 230 198 231 //Autocast 232 HM_NAMESPACE::hash_map<uint32, Unit*> targetMap; 233 targetMap.clear(); 234 SpellCastTargets NULLtargets; 235 236 for (uint8 i = 0; i < i_pet.GetPetAutoSpellSize(); i++) 237 { 238 uint32 spellID = i_pet.GetPetAutoSpellOnPos(i); 239 if (!spellID) 240 continue; 241 242 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID); 243 if (!spellInfo) 244 continue; 245 246 Spell *spell = new Spell(&i_pet, spellInfo, false, 0); 247 248 if(!IsPositiveSpell(spellInfo->Id) && i_pet.getVictim() && !_needToStop() && !i_pet.hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(i_pet.getVictim())) 249 targetMap[spellID] = i_pet.getVictim(); 250 else 251 { 252 spell->m_targets = NULLtargets; 253 for(std::set<uint64>::iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar) 254 { 255 Unit* Target = ObjectAccessor::GetUnit(i_pet,*tar); 256 257 //only buff targets that are in combat, unless the spell can only be cast while out of combat 258 if(!Target || (!Target->isInCombat() && !IsNonCombatSpell(spellInfo))) 199 if (i_pet.GetGlobalCooldown() == 0 && !i_pet.IsNonMeleeSpellCasted(false)) 200 { 201 //Autocast 202 for (uint8 i = 0; i < i_pet.GetPetAutoSpellSize(); i++) 203 { 204 uint32 spellID = i_pet.GetPetAutoSpellOnPos(i); 205 if (!spellID) 206 continue; 207 208 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID); 209 if (!spellInfo) 210 continue; 211 212 // ignore some combinations of combat state and combat/noncombat spells 213 if (!inCombat) 214 { 215 if (!IsPositiveSpell(spellInfo->Id)) 259 216 continue; 260 if(spell->CanAutoCast(Target)) 261 targetMap[spellID] = Target; 262 } 263 } 264 265 delete spell; 266 } 267 268 //found units to cast on to 269 if(!targetMap.empty()) 270 { 271 uint32 index = urand(1, targetMap.size()); 272 HM_NAMESPACE::hash_map<uint32, Unit*>::iterator itr; 273 uint32 i; 274 for(itr = targetMap.begin(), i = 1; i < index; ++itr, ++i); 275 276 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); 277 278 Spell *spell = new Spell(&i_pet, spellInfo, false); 279 280 SpellCastTargets targets; 281 targets.setUnitTarget( itr->second ); 282 283 if(!i_pet.HasInArc(M_PI, itr->second)) 284 { 285 i_pet.SetInFront(itr->second); 286 if( itr->second->GetTypeId() == TYPEID_PLAYER ) 287 i_pet.SendUpdateToPlayer( (Player*)itr->second ); 288 289 if(owner && owner->GetTypeId() == TYPEID_PLAYER) 290 i_pet.SendUpdateToPlayer( (Player*)owner ); 291 } 292 293 i_pet.AddCreatureSpellCooldown(itr->first); 294 if(i_pet.isPet()) 295 ((Pet*)&i_pet)->CheckLearning(itr->first); 296 297 spell->prepare(&targets); 298 } 299 targetMap.clear(); 217 } 218 else 219 { 220 if (IsNonCombatSpell(spellInfo)) 221 continue; 222 } 223 224 Spell *spell = new Spell(&i_pet, spellInfo, false, 0); 225 226 if(inCombat && !i_pet.hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(i_pet.getVictim())) 227 { 228 m_targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(i_pet.getVictim(), spell)); 229 continue; 230 } 231 else 232 { 233 bool spellUsed = false; 234 for(std::set<uint64>::iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar) 235 { 236 Unit* Target = ObjectAccessor::GetUnit(i_pet,*tar); 237 238 //only buff targets that are in combat, unless the spell can only be cast while out of combat 239 if(!Target) 240 continue; 241 242 if(spell->CanAutoCast(Target)) 243 { 244 m_targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(Target, spell)); 245 spellUsed = true; 246 break; 247 } 248 } 249 if (!spellUsed) 250 delete spell; 251 } 252 } 253 254 //found units to cast on to 255 if(!m_targetSpellStore.empty()) 256 { 257 uint32 index = urand(0, m_targetSpellStore.size() - 1); 258 259 Spell* spell = m_targetSpellStore[index].second; 260 Unit* target = m_targetSpellStore[index].first; 261 262 m_targetSpellStore.erase(m_targetSpellStore.begin() + index); 263 264 SpellCastTargets targets; 265 targets.setUnitTarget( target ); 266 267 if( !i_pet.HasInArc(M_PI, target) ) 268 { 269 i_pet.SetInFront(target); 270 if( target->GetTypeId() == TYPEID_PLAYER ) 271 i_pet.SendUpdateToPlayer( (Player*)target ); 272 273 if(owner && owner->GetTypeId() == TYPEID_PLAYER) 274 i_pet.SendUpdateToPlayer( (Player*)owner ); 275 } 276 277 i_pet.AddCreatureSpellCooldown(spell->m_spellInfo->Id); 278 if(i_pet.isPet()) 279 ((Pet*)&i_pet)->CheckLearning(spell->m_spellInfo->Id); 280 281 spell->prepare(&targets); 282 } 283 while (!m_targetSpellStore.empty()) 284 { 285 delete m_targetSpellStore.begin()->second; 286 m_targetSpellStore.erase(m_targetSpellStore.begin()); 287 } 288 } 300 289 } 301 290 -
trunk/src/game/PetAI.h
r102 r135 26 26 27 27 class Creature; 28 class Spell; 28 29 29 30 class TRINITY_DLL_DECL PetAI : public CreatureAI … … 39 40 void AttackedBy(Unit*); 40 41 bool IsVisible(Unit *) const; 42 void JustDied(Unit* who) { _stopAttack(); } 41 43 42 44 void UpdateAI(const uint32); 43 void UpdateAllies();44 45 static int Permissible(const Creature *); 45 46 … … 49 50 void _stopAttack(void); 50 51 52 void UpdateAllies(); 53 51 54 Creature &i_pet; 52 uint64 i_victimGuid;55 bool inCombat; 53 56 TimeTracker i_tracker; 54 //uint32 i_RepeatAction;55 57 std::set<uint64> m_AllySet; 56 58 uint32 m_updateAlliesTimer; 59 60 typedef std::pair<Unit*, Spell*> TargetSpellPair; 61 std::vector<TargetSpellPair> m_targetSpellStore; 57 62 }; 58 63 #endif -
trunk/src/game/PetHandler.cpp
r102 r135 167 167 unit_target = NULL; 168 168 169 if (((Creature*)pet)->GetGlobalCooldown() > 0) 170 return; 171 169 172 // do not cast unknown spells 170 173 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid ); … … 602 605 } 603 606 607 if (pet->GetGlobalCooldown() > 0) 608 return; 609 604 610 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid); 605 611 if(!spellInfo)