[8483] Implement glyph 43361.
[getmangos.git] / src / game / GridNotifiersImpl.h
blob8d2433ce30c9e992f7887c57934238fe0fbfd4d2
1 /*
2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #ifndef MANGOS_GRIDNOTIFIERSIMPL_H
20 #define MANGOS_GRIDNOTIFIERSIMPL_H
22 #include "GridNotifiers.h"
23 #include "WorldPacket.h"
24 #include "Corpse.h"
25 #include "Player.h"
26 #include "UpdateData.h"
27 #include "CreatureAI.h"
28 #include "SpellAuras.h"
30 template<class T>
31 inline void
32 MaNGOS::VisibleNotifier::Visit(GridRefManager<T> &m)
34 WorldObject const* viewPoint = i_player.GetViewPoint();
36 for(typename GridRefManager<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
38 i_player.UpdateVisibilityOf(viewPoint,iter->getSource(),i_data,i_data_updates,i_visibleNow);
39 i_clientGUIDs.erase(iter->getSource()->GetGUID());
43 inline void
44 MaNGOS::ObjectUpdater::Visit(CreatureMapType &m)
46 for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
47 if(!iter->getSource()->isSpiritService())
48 iter->getSource()->Update(i_timeDiff);
51 inline void
52 MaNGOS::PlayerRelocationNotifier::Visit(PlayerMapType &m)
54 for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
56 if(&i_player==iter->getSource())
57 continue;
59 // visibility for players updated by ObjectAccessor::UpdateVisibilityFor calls in appropriate places
61 // Cancel Trade
62 if(i_player.GetTrader()==iter->getSource())
63 // iteraction distance
64 if(!i_player.IsWithinDistInMap(iter->getSource(), 5))
65 i_player.GetSession()->SendCancelTrade(); // will clode both side trade windows
69 inline void PlayerCreatureRelocationWorker(Player* pl, WorldObject const* viewPoint, Creature* c)
71 // update creature visibility at player/creature move
72 pl->UpdateVisibilityOf(viewPoint,c);
74 // Creature AI reaction
75 if(!c->hasUnitState(UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))
77 if( c->AI() && c->AI()->IsVisible(pl) && !c->IsInEvadeMode() )
78 c->AI()->MoveInLineOfSight(pl);
82 inline void CreatureCreatureRelocationWorker(Creature* c1, Creature* c2)
84 if(!c1->hasUnitState(UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))
86 if( c1->AI() && c1->AI()->IsVisible(c2) && !c1->IsInEvadeMode() )
87 c1->AI()->MoveInLineOfSight(c2);
90 if(!c2->hasUnitState(UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))
92 if( c2->AI() && c2->AI()->IsVisible(c1) && !c2->IsInEvadeMode() )
93 c2->AI()->MoveInLineOfSight(c1);
97 inline void
98 MaNGOS::PlayerRelocationNotifier::Visit(CreatureMapType &m)
100 if(!i_player.isAlive() || i_player.isInFlight())
101 return;
103 WorldObject const* viewPoint = i_player.GetViewPoint();
105 for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
106 if (iter->getSource()->isAlive())
107 PlayerCreatureRelocationWorker(&i_player,viewPoint,iter->getSource());
110 template<>
111 inline void
112 MaNGOS::CreatureRelocationNotifier::Visit(PlayerMapType &m)
114 if(!i_creature.isAlive())
115 return;
117 for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
118 if (Player* player = iter->getSource())
119 if (player->isAlive() && !player->isInFlight())
120 PlayerCreatureRelocationWorker(player, player->GetViewPoint(), &i_creature);
123 template<>
124 inline void
125 MaNGOS::CreatureRelocationNotifier::Visit(CreatureMapType &m)
127 if(!i_creature.isAlive())
128 return;
130 for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
132 Creature* c = iter->getSource();
133 if( c != &i_creature && c->isAlive())
134 CreatureCreatureRelocationWorker(c, &i_creature);
138 inline void MaNGOS::DynamicObjectUpdater::VisitHelper(Unit* target)
140 if(!target->isAlive() || target->isInFlight() )
141 return;
143 if(target->GetTypeId()==TYPEID_UNIT && ((Creature*)target)->isTotem())
144 return;
146 if (!i_dynobject.IsWithinDistInMap(target, i_dynobject.GetRadius()))
147 return;
149 //Check targets for not_selectable unit flag and remove
150 if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE))
151 return;
153 // Evade target
154 if( target->GetTypeId()==TYPEID_UNIT && ((Creature*)target)->IsInEvadeMode() )
155 return;
157 //Check player targets and remove if in GM mode or GM invisibility (for not self casting case)
158 if( target->GetTypeId()==TYPEID_PLAYER && target != i_check && (((Player*)target)->isGameMaster() || ((Player*)target)->GetVisibility()==VISIBILITY_OFF) )
159 return;
161 if (i_check->GetTypeId()==TYPEID_PLAYER )
163 if (i_check->IsFriendlyTo( target ))
164 return;
166 else
168 if (!i_check->IsHostileTo( target ))
169 return;
172 if (i_dynobject.IsAffecting(target))
173 return;
175 SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_dynobject.GetSpellId());
176 uint32 eff_index = i_dynobject.GetEffIndex();
177 // Check target immune to spell or aura
178 if (target->IsImmunedToSpell(spellInfo) || target->IsImmunedToSpellEffect(spellInfo, eff_index))
179 return;
180 // Apply PersistentAreaAura on target
181 PersistentAreaAura* Aur = new PersistentAreaAura(spellInfo, eff_index, NULL, target, i_dynobject.GetCaster());
182 target->AddAura(Aur);
183 i_dynobject.AddAffected(target);
186 template<>
187 inline void
188 MaNGOS::DynamicObjectUpdater::Visit(CreatureMapType &m)
190 for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
191 VisitHelper(itr->getSource());
194 template<>
195 inline void
196 MaNGOS::DynamicObjectUpdater::Visit(PlayerMapType &m)
198 for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
199 VisitHelper(itr->getSource());
202 // SEARCHERS & LIST SEARCHERS & WORKERS
204 // WorldObject searchers & workers
206 template<class Check>
207 void MaNGOS::WorldObjectSearcher<Check>::Visit(GameObjectMapType &m)
209 // already found
210 if(i_object)
211 return;
213 for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
215 if(!itr->getSource()->InSamePhase(i_phaseMask))
216 continue;
218 if (i_check(itr->getSource()))
220 i_object = itr->getSource();
221 return;
226 template<class Check>
227 void MaNGOS::WorldObjectSearcher<Check>::Visit(PlayerMapType &m)
229 // already found
230 if(i_object)
231 return;
233 for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
235 if(!itr->getSource()->InSamePhase(i_phaseMask))
236 continue;
238 if(i_check(itr->getSource()))
240 i_object = itr->getSource();
241 return;
246 template<class Check>
247 void MaNGOS::WorldObjectSearcher<Check>::Visit(CreatureMapType &m)
249 // already found
250 if(i_object)
251 return;
253 for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
255 if(!itr->getSource()->InSamePhase(i_phaseMask))
256 continue;
258 if(i_check(itr->getSource()))
260 i_object = itr->getSource();
261 return;
266 template<class Check>
267 void MaNGOS::WorldObjectSearcher<Check>::Visit(CorpseMapType &m)
269 // already found
270 if(i_object)
271 return;
273 for(CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
275 if(!itr->getSource()->InSamePhase(i_phaseMask))
276 continue;
278 if(i_check(itr->getSource()))
280 i_object = itr->getSource();
281 return;
286 template<class Check>
287 void MaNGOS::WorldObjectSearcher<Check>::Visit(DynamicObjectMapType &m)
289 // already found
290 if(i_object)
291 return;
293 for(DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
295 if(!itr->getSource()->InSamePhase(i_phaseMask))
296 continue;
298 if(i_check(itr->getSource()))
300 i_object = itr->getSource();
301 return;
306 template<class Check>
307 void MaNGOS::WorldObjectListSearcher<Check>::Visit(PlayerMapType &m)
309 for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
310 if(itr->getSource()->InSamePhase(i_phaseMask))
311 if(i_check(itr->getSource()))
312 i_objects.push_back(itr->getSource());
315 template<class Check>
316 void MaNGOS::WorldObjectListSearcher<Check>::Visit(CreatureMapType &m)
318 for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
319 if(itr->getSource()->InSamePhase(i_phaseMask))
320 if(i_check(itr->getSource()))
321 i_objects.push_back(itr->getSource());
324 template<class Check>
325 void MaNGOS::WorldObjectListSearcher<Check>::Visit(CorpseMapType &m)
327 for(CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
328 if(itr->getSource()->InSamePhase(i_phaseMask))
329 if(i_check(itr->getSource()))
330 i_objects.push_back(itr->getSource());
333 template<class Check>
334 void MaNGOS::WorldObjectListSearcher<Check>::Visit(GameObjectMapType &m)
336 for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
337 if(itr->getSource()->InSamePhase(i_phaseMask))
338 if(i_check(itr->getSource()))
339 i_objects.push_back(itr->getSource());
342 template<class Check>
343 void MaNGOS::WorldObjectListSearcher<Check>::Visit(DynamicObjectMapType &m)
345 for(DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
346 if(itr->getSource()->InSamePhase(i_phaseMask))
347 if(i_check(itr->getSource()))
348 i_objects.push_back(itr->getSource());
351 // Gameobject searchers
353 template<class Check>
354 void MaNGOS::GameObjectSearcher<Check>::Visit(GameObjectMapType &m)
356 // already found
357 if(i_object)
358 return;
360 for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
362 if(!itr->getSource()->InSamePhase(i_phaseMask))
363 continue;
365 if(i_check(itr->getSource()))
367 i_object = itr->getSource();
368 return;
373 template<class Check>
374 void MaNGOS::GameObjectLastSearcher<Check>::Visit(GameObjectMapType &m)
376 for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
378 if(!itr->getSource()->InSamePhase(i_phaseMask))
379 continue;
381 if(i_check(itr->getSource()))
382 i_object = itr->getSource();
386 template<class Check>
387 void MaNGOS::GameObjectListSearcher<Check>::Visit(GameObjectMapType &m)
389 for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
390 if(itr->getSource()->InSamePhase(i_phaseMask))
391 if(i_check(itr->getSource()))
392 i_objects.push_back(itr->getSource());
395 // Unit searchers
397 template<class Check>
398 void MaNGOS::UnitSearcher<Check>::Visit(CreatureMapType &m)
400 // already found
401 if(i_object)
402 return;
404 for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
406 if(!itr->getSource()->InSamePhase(i_phaseMask))
407 continue;
409 if(i_check(itr->getSource()))
411 i_object = itr->getSource();
412 return;
417 template<class Check>
418 void MaNGOS::UnitSearcher<Check>::Visit(PlayerMapType &m)
420 // already found
421 if(i_object)
422 return;
424 for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
426 if(!itr->getSource()->InSamePhase(i_phaseMask))
427 continue;
429 if(i_check(itr->getSource()))
431 i_object = itr->getSource();
432 return;
437 template<class Check>
438 void MaNGOS::UnitLastSearcher<Check>::Visit(CreatureMapType &m)
440 for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
442 if(!itr->getSource()->InSamePhase(i_phaseMask))
443 continue;
445 if(i_check(itr->getSource()))
446 i_object = itr->getSource();
450 template<class Check>
451 void MaNGOS::UnitLastSearcher<Check>::Visit(PlayerMapType &m)
453 for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
455 if(!itr->getSource()->InSamePhase(i_phaseMask))
456 continue;
458 if(i_check(itr->getSource()))
459 i_object = itr->getSource();
463 template<class Check>
464 void MaNGOS::UnitListSearcher<Check>::Visit(PlayerMapType &m)
466 for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
467 if(itr->getSource()->InSamePhase(i_phaseMask))
468 if(i_check(itr->getSource()))
469 i_objects.push_back(itr->getSource());
472 template<class Check>
473 void MaNGOS::UnitListSearcher<Check>::Visit(CreatureMapType &m)
475 for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
476 if(itr->getSource()->InSamePhase(i_phaseMask))
477 if(i_check(itr->getSource()))
478 i_objects.push_back(itr->getSource());
481 // Creature searchers
483 template<class Check>
484 void MaNGOS::CreatureSearcher<Check>::Visit(CreatureMapType &m)
486 // already found
487 if(i_object)
488 return;
490 for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
492 if(!itr->getSource()->InSamePhase(i_phaseMask))
493 continue;
495 if(i_check(itr->getSource()))
497 i_object = itr->getSource();
498 return;
503 template<class Check>
504 void MaNGOS::CreatureLastSearcher<Check>::Visit(CreatureMapType &m)
506 for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
508 if(!itr->getSource()->InSamePhase(i_phaseMask))
509 continue;
511 if(i_check(itr->getSource()))
512 i_object = itr->getSource();
516 template<class Check>
517 void MaNGOS::CreatureListSearcher<Check>::Visit(CreatureMapType &m)
519 for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
520 if(itr->getSource()->InSamePhase(i_phaseMask))
521 if( i_check(itr->getSource()))
522 i_objects.push_back(itr->getSource());
525 template<class Check>
526 void MaNGOS::PlayerSearcher<Check>::Visit(PlayerMapType &m)
528 // already found
529 if(i_object)
530 return;
532 for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
534 if(!itr->getSource()->InSamePhase(i_phaseMask))
535 continue;
537 if(i_check(itr->getSource()))
539 i_object = itr->getSource();
540 return;
545 template<class Builder>
546 void MaNGOS::LocalizedPacketDo<Builder>::operator()( Player* p )
548 int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex();
549 uint32 cache_idx = loc_idx+1;
550 WorldPacket* data;
552 // create if not cached yet
553 if(i_data_cache.size() < cache_idx+1 || !i_data_cache[cache_idx])
555 if(i_data_cache.size() < cache_idx+1)
556 i_data_cache.resize(cache_idx+1);
558 data = new WorldPacket(SMSG_MESSAGECHAT, 200);
560 i_builder(*data,loc_idx);
562 i_data_cache[cache_idx] = data;
564 else
565 data = i_data_cache[cache_idx];
567 p->SendDirectMessage(data);
570 template<class Builder>
571 void MaNGOS::LocalizedPacketListDo<Builder>::operator()( Player* p )
573 int32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex();
574 uint32 cache_idx = loc_idx+1;
575 WorldPacketList* data_list;
577 // create if not cached yet
578 if(i_data_cache.size() < cache_idx+1 || i_data_cache[cache_idx].empty())
580 if(i_data_cache.size() < cache_idx+1)
581 i_data_cache.resize(cache_idx+1);
583 data_list = &i_data_cache[cache_idx];
585 i_builder(*data_list,loc_idx);
587 else
588 data_list = &i_data_cache[cache_idx];
590 for(size_t i = 0; i < data_list->size(); ++i)
591 p->SendDirectMessage((*data_list)[i]);
594 #endif // MANGOS_GRIDNOTIFIERSIMPL_H