/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
#ifndef ACORE_GRIDNOTIFIERS_H
#define ACORE_GRIDNOTIFIERS_H
#include "Corpse.h"
#include "CreatureAI.h"
#include "DynamicObject.h"
#include "GameObject.h"
#include "Group.h"
#include "Object.h"
#include "GridObjectLoader.h"
#include "Optional.h"
#include "Player.h"
#include "Spell.h"
#include "Unit.h"
#include "UpdateData.h"
#include "WorldSession.h"
#include
#include "SpellMgr.h"
class Player;
//class Map;
namespace Acore
{
struct VisibleNotifier
{
Player& i_player;
std::vector& i_visibleNow;
bool i_gobjOnly;
UpdateData i_data;
VisibleNotifier(Player& player, bool gobjOnly) :
i_player(player), i_visibleNow(player.m_newVisible), i_gobjOnly(gobjOnly)
{
i_visibleNow.clear();
}
void Visit(GameObjectMapType&);
template void Visit(std::vector& m);
template void Visit(GridRefMgr& m);
void SendToSelf(void);
};
struct VisibleChangesNotifier
{
WorldObject& i_object;
explicit VisibleChangesNotifier(WorldObject& object) : i_object(object) {}
template void Visit(GridRefMgr&) {}
void Visit(PlayerMapType&);
void Visit(CreatureMapType&);
void Visit(DynamicObjectMapType&);
};
struct PlayerRelocationNotifier : public VisibleNotifier
{
PlayerRelocationNotifier(Player& player): VisibleNotifier(player, false) { }
template void Visit(std::vector& m) { VisibleNotifier::Visit(m); }
template void Visit(GridRefMgr& m) { VisibleNotifier::Visit(m); }
void Visit(PlayerMapType&);
};
struct CreatureRelocationNotifier
{
Creature& i_creature;
CreatureRelocationNotifier(Creature& c) : i_creature(c) {}
template void Visit(GridRefMgr&) {}
void Visit(PlayerMapType&);
};
struct AIRelocationNotifier
{
Unit& i_unit;
bool isCreature;
explicit AIRelocationNotifier(Unit& unit) : i_unit(unit), isCreature(unit.IsCreature()) {}
template void Visit(GridRefMgr&) {}
void Visit(CreatureMapType&);
};
struct MessageDistDeliverer
{
WorldObject const* i_source;
WorldPacket const* i_message;
uint32 i_phaseMask;
float i_distSq;
TeamId teamId;
Player const* skipped_receiver;
bool required3dDist;
MessageDistDeliverer(WorldObject const* src, WorldPacket const* msg, float dist, bool own_team_only = false, Player const* skipped = nullptr, bool req3dDist = false)
: i_source(src), i_message(msg), i_phaseMask(src->GetPhaseMask()), i_distSq(dist * dist)
, teamId((own_team_only && src->IsPlayer()) ? src->ToPlayer()->GetTeamId() : TEAM_NEUTRAL)
, skipped_receiver(skipped), required3dDist(req3dDist)
{
}
void Visit(VisiblePlayersMap const& m);
void Visit(PlayerMapType& m);
void Visit(CreatureMapType& m);
void Visit(DynamicObjectMapType& m);
template void Visit(GridRefMgr&) {}
void SendPacket(Player* player)
{
// never send packet to self
if (player == i_source || (teamId != TEAM_NEUTRAL && player->GetTeamId() != teamId) || skipped_receiver == player)
return;
if (!player->HaveAtClient(i_source))
return;
player->SendDirectMessage(i_message);
}
};
struct MessageDistDelivererToHostile
{
Unit* i_source;
WorldPacket* i_message;
uint32 i_phaseMask;
float i_distSq;
MessageDistDelivererToHostile(Unit* src, WorldPacket* msg, float dist)
: i_source(src), i_message(msg), i_phaseMask(src->GetPhaseMask()), i_distSq(dist * dist)
{
}
void Visit(PlayerMapType& m);
void Visit(CreatureMapType& m);
void Visit(DynamicObjectMapType& m);
template void Visit(GridRefMgr&) {}
void SendPacket(Player* player)
{
// never send packet to self
if (player == i_source || !player->HaveAtClient(i_source) || player->IsFriendlyTo(i_source))
return;
player->SendDirectMessage(i_message);
}
};
// SEARCHERS & LIST SEARCHERS & WORKERS
// WorldObject searchers & workers
// Generic base class to insert elements into arbitrary containers using push_back
template
class ContainerInserter
{
using InserterType = void(*)(void*, Type&&);
void* ref;
InserterType inserter;
// MSVC workaround
template
static void InserterOf(void* ref, Type&& type)
{
static_cast(ref)->push_back(std::move(type));
}
protected:
template
ContainerInserter(T& ref_) : ref(&ref_), inserter(&InserterOf) { }
void Insert(Type type)
{
inserter(ref, std::move(type));
}
};
template
struct WorldObjectSearcher
{
uint32 i_mapTypeMask;
uint32 i_phaseMask;
WorldObject*& i_object;
Check& i_check;
WorldObjectSearcher(WorldObject const* searcher, WorldObject*& result, Check& check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
: i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {}
void Visit(GameObjectMapType& m);
void Visit(PlayerMapType& m);
void Visit(CreatureMapType& m);
void Visit(CorpseMapType& m);
void Visit(DynamicObjectMapType& m);
template void Visit(GridRefMgr&) {}
};
template
struct WorldObjectLastSearcher
{
uint32 i_mapTypeMask;
uint32 i_phaseMask;
WorldObject*& i_object;
Check& i_check;
WorldObjectLastSearcher(WorldObject const* searcher, WorldObject*& result, Check& check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
: i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {}
void Visit(GameObjectMapType& m);
void Visit(PlayerMapType& m);
void Visit(CreatureMapType& m);
void Visit(CorpseMapType& m);
void Visit(DynamicObjectMapType& m);
template void Visit(GridRefMgr&) {}
};
template
struct WorldObjectListSearcher : ContainerInserter
{
uint32 i_mapTypeMask;
uint32 i_phaseMask;
Check& i_check;
template
WorldObjectListSearcher(WorldObject const* searcher, Container& container, Check & check, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
: ContainerInserter(container),
i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_check(check) { }
void Visit(PlayerMapType& m);
void Visit(CreatureMapType& m);
void Visit(CorpseMapType& m);
void Visit(GameObjectMapType& m);
void Visit(DynamicObjectMapType& m);
template void Visit(GridRefMgr&) {}
};
template
struct WorldObjectWorker
{
uint32 i_mapTypeMask;
uint32 i_phaseMask;
Do const& i_do;
WorldObjectWorker(WorldObject const* searcher, Do const& _do, uint32 mapTypeMask = GRID_MAP_TYPE_MASK_ALL)
: i_mapTypeMask(mapTypeMask), i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {}
void Visit(GameObjectMapType& m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_GAMEOBJECT))
return;
for (GameObjectMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
if (itr->GetSource()->InSamePhase(i_phaseMask))
i_do(itr->GetSource());
}
void Visit(PlayerMapType& m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_PLAYER))
return;
for (PlayerMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
if (itr->GetSource()->InSamePhase(i_phaseMask))
i_do(itr->GetSource());
}
void Visit(CreatureMapType& m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CREATURE))
return;
for (CreatureMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
if (itr->GetSource()->InSamePhase(i_phaseMask))
i_do(itr->GetSource());
}
void Visit(CorpseMapType& m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CORPSE))
return;
for (CorpseMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
if (itr->GetSource()->InSamePhase(i_phaseMask))
i_do(itr->GetSource());
}
void Visit(DynamicObjectMapType& m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_DYNAMICOBJECT))
return;
for (DynamicObjectMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
if (itr->GetSource()->InSamePhase(i_phaseMask))
i_do(itr->GetSource());
}
template void Visit(GridRefMgr&) {}
};
// Gameobject searchers
template
struct GameObjectSearcher
{
uint32 i_phaseMask;
GameObject*& i_object;
Check& i_check;
GameObjectSearcher(WorldObject const* searcher, GameObject*& result, Check& check)
: i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {}
void Visit(GameObjectMapType& m);
template void Visit(GridRefMgr&) {}
};
// Last accepted by Check GO if any (Check can change requirements at each call)
template
struct GameObjectLastSearcher
{
uint32 i_phaseMask;
GameObject*& i_object;
Check& i_check;
GameObjectLastSearcher(WorldObject const* searcher, GameObject*& result, Check& check)
: i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {}
void Visit(GameObjectMapType& m);
template void Visit(GridRefMgr&) {}
};
template
struct GameObjectListSearcher : ContainerInserter
{
uint32 i_phaseMask;
Check& i_check;
template
GameObjectListSearcher(WorldObject const* searcher, Container& container, Check & check)
: ContainerInserter(container),
i_phaseMask(searcher->GetPhaseMask()), i_check(check) { }
void Visit(GameObjectMapType& m);
template void Visit(GridRefMgr&) {}
};
template
struct GameObjectWorker
{
GameObjectWorker(WorldObject const* searcher, Functor& func)
: _func(func), _phaseMask(searcher->GetPhaseMask()) {}
void Visit(GameObjectMapType& m)
{
for (GameObjectMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
if (itr->GetSource()->InSamePhase(_phaseMask))
_func(itr->GetSource());
}
template void Visit(GridRefMgr&) {}
private:
Functor& _func;
uint32 _phaseMask;
};
// Unit searchers
// First accepted by Check Unit if any
template
struct UnitSearcher
{
uint32 i_phaseMask;
Unit*& i_object;
Check& i_check;
UnitSearcher(WorldObject const* searcher, Unit*& result, Check& check)
: i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {}
void Visit(CreatureMapType& m);
void Visit(PlayerMapType& m);
template void Visit(GridRefMgr&) {}
};
// Last accepted by Check Unit if any (Check can change requirements at each call)
template
struct UnitLastSearcher
{
uint32 i_phaseMask;
Unit*& i_object;
Check& i_check;
UnitLastSearcher(WorldObject const* searcher, Unit*& result, Check& check)
: i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {}
void Visit(CreatureMapType& m);
void Visit(PlayerMapType& m);
template void Visit(GridRefMgr&) {}
};
// All accepted by Check units if any
template
struct UnitListSearcher : ContainerInserter
{
uint32 i_phaseMask;
Check& i_check;
template
UnitListSearcher(WorldObject const* searcher, Container& container, Check& check)
: ContainerInserter(container),
i_phaseMask(searcher->GetPhaseMask()), i_check(check) { }
void Visit(PlayerMapType& m);
void Visit(CreatureMapType& m);
template void Visit(GridRefMgr&) {}
};
// Creature searchers
template
struct CreatureSearcher
{
uint32 i_phaseMask;
Creature*& i_object;
Check& i_check;
CreatureSearcher(WorldObject const* searcher, Creature*& result, Check& check)
: i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {}
void Visit(CreatureMapType& m);
template void Visit(GridRefMgr&) {}
};
// Last accepted by Check Creature if any (Check can change requirements at each call)
template
struct CreatureLastSearcher
{
uint32 i_phaseMask;
Creature*& i_object;
Check& i_check;
CreatureLastSearcher(WorldObject const* searcher, Creature*& result, Check& check)
: i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {}
void Visit(CreatureMapType& m);
template void Visit(GridRefMgr&) {}
};
template
struct CreatureListSearcher : ContainerInserter
{
uint32 i_phaseMask;
Check& i_check;
template
CreatureListSearcher(WorldObject const* searcher, Container& container, Check & check)
: ContainerInserter(container),
i_phaseMask(searcher->GetPhaseMask()), i_check(check) { }
void Visit(CreatureMapType& m);
template void Visit(GridRefMgr&) {}
};
template
struct CreatureWorker
{
uint32 i_phaseMask;
Do& i_do;
CreatureWorker(WorldObject const* searcher, Do& _do)
: i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {}
void Visit(CreatureMapType& m)
{
for (CreatureMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
if (itr->GetSource()->InSamePhase(i_phaseMask))
i_do(itr->GetSource());
}
template void Visit(GridRefMgr&) {}
};
// Player searchers
template
struct PlayerSearcher
{
uint32 i_phaseMask;
Player*& i_object;
Check& i_check;
PlayerSearcher(WorldObject const* searcher, Player*& result, Check& check)
: i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {}
void Visit(PlayerMapType& m);
template void Visit(GridRefMgr&) {}
};
template
struct PlayerListSearcher : ContainerInserter
{
uint32 i_phaseMask;
Check& i_check;
template
PlayerListSearcher(WorldObject const* searcher, Container& container, Check & check)
: ContainerInserter(container),
i_phaseMask(searcher->GetPhaseMask()), i_check(check) { }
void Visit(PlayerMapType& m);
template void Visit(GridRefMgr&) {}
};
template
struct PlayerListSearcherWithSharedVision
{
uint32 i_phaseMask;
std::list& i_objects;
Check& i_check;
PlayerListSearcherWithSharedVision(WorldObject const* searcher, std::list& objects, Check& check)
: i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) {}
void Visit(PlayerMapType& m);
void Visit(CreatureMapType& m);
template void Visit(GridRefMgr&) {}
};
template
struct PlayerLastSearcher
{
uint32 i_phaseMask;
Player*& i_object;
Check& i_check;
PlayerLastSearcher(WorldObject const* searcher, Player*& result, Check& check) : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check)
{
}
void Visit(PlayerMapType& m);
template void Visit(GridRefMgr&) {}
};
template
struct PlayerWorker
{
uint32 i_phaseMask;
Do& i_do;
PlayerWorker(WorldObject const* searcher, Do& _do)
: i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {}
void Visit(PlayerMapType& m)
{
for (PlayerMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
if (itr->GetSource()->InSamePhase(i_phaseMask))
i_do(itr->GetSource());
}
template void Visit(GridRefMgr&) {}
};
template
struct PlayerDistWorker
{
WorldObject const* i_searcher;
float i_dist;
Do& i_do;
PlayerDistWorker(WorldObject const* searcher, float _dist, Do& _do)
: i_searcher(searcher), i_dist(_dist), i_do(_do) {}
void Visit(PlayerMapType& m)
{
for (PlayerMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
if (itr->GetSource()->HaveAtClient(i_searcher) && itr->GetSource()->IsWithinDist(i_searcher, i_dist))
i_do(itr->GetSource());
}
template void Visit(GridRefMgr&) {}
};
// CHECKS && DO classes
// WorldObject check classes
class AnyDeadUnitObjectInRangeCheck
{
public:
AnyDeadUnitObjectInRangeCheck(Unit* searchObj, float range) : i_searchObj(searchObj), i_range(range) {}
bool operator()(Player* u);
bool operator()(Corpse* u);
bool operator()(Creature* u);
template bool operator()(NOT_INTERESTED*) { return false; }
protected:
Unit const* const i_searchObj;
float i_range;
};
class AnyDeadUnitSpellTargetInRangeCheck : public AnyDeadUnitObjectInRangeCheck
{
public:
AnyDeadUnitSpellTargetInRangeCheck(Unit* searchObj, float range, SpellInfo const* spellInfo, SpellTargetCheckTypes check)
: AnyDeadUnitObjectInRangeCheck(searchObj, range), i_spellInfo(spellInfo), i_check(searchObj, searchObj, spellInfo, check, nullptr)
{}
bool operator()(Player* u);
bool operator()(Corpse* u);
bool operator()(Creature* u);
template bool operator()(NOT_INTERESTED*) { return false; }
protected:
SpellInfo const* i_spellInfo;
WorldObjectSpellTargetCheck i_check;
};
// WorldObject do classes
class RespawnDo
{
public:
RespawnDo() {}
void operator()(Creature* u) const { u->Respawn(); }
void operator()(GameObject* u) const { u->Respawn(); }
void operator()(WorldObject*) const {}
void operator()(Corpse*) const {}
};
// GameObject checks
class GameObjectFocusCheck
{
public:
GameObjectFocusCheck(Unit const* unit, uint32 focusId) : i_unit(unit), i_focusId(focusId) {}
bool operator()(GameObject* go) const
{
if (go->GetGOInfo()->type != GAMEOBJECT_TYPE_SPELL_FOCUS)
return false;
if (!go->isSpawned()) // xinef: dont allow to count deactivated objects
return false;
if (go->GetGOInfo()->spellFocus.focusId != i_focusId)
return false;
float dist = (float)((go->GetGOInfo()->spellFocus.dist) / 2);
return go->IsWithinDistInMap(i_unit, dist);
}
private:
Unit const* i_unit;
uint32 i_focusId;
};
// Find the nearest Fishing hole and return true only if source object is in range of hole
class NearestGameObjectFishingHole
{
public:
NearestGameObjectFishingHole(WorldObject const& obj, float range) : i_obj(obj), i_range(range) {}
bool operator()(GameObject* go)
{
if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_FISHINGHOLE && go->isSpawned() && i_obj.IsWithinDistInMap(go, i_range) && i_obj.IsWithinDistInMap(go, (float)go->GetGOInfo()->fishinghole.radius))
{
i_range = i_obj.GetDistance(go);
return true;
}
return false;
}
private:
WorldObject const& i_obj;
float i_range;
// prevent clone
NearestGameObjectFishingHole(NearestGameObjectFishingHole const&);
};
class NearestGameObjectCheck
{
public:
NearestGameObjectCheck(WorldObject const& obj) : i_obj(obj), i_range(999) {}
bool operator()(GameObject* go)
{
if (i_obj.IsWithinDistInMap(go, i_range))
{
i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check
return true;
}
return false;
}
private:
WorldObject const& i_obj;
float i_range;
// prevent clone this object
NearestGameObjectCheck(NearestGameObjectCheck const&);
};
// Success at unit in range, range update for next check (this can be use with GameobjectLastSearcher to find nearest GO)
class NearestGameObjectEntryInObjectRangeCheck
{
public:
NearestGameObjectEntryInObjectRangeCheck(WorldObject const& obj, uint32 entry, float range, bool onlySpawned = false) :
i_obj(obj), i_entry(entry), i_range(range), i_onlySpawned(onlySpawned) { }
bool operator()(GameObject* go)
{
if (go->GetEntry() == i_entry && i_obj.IsWithinDistInMap(go, i_range) && (!i_onlySpawned || go->isSpawned()))
{
i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check
return true;
}
return false;
}
private:
WorldObject const& i_obj;
uint32 i_entry;
float i_range;
bool i_onlySpawned;
// prevent clone this object
NearestGameObjectEntryInObjectRangeCheck(NearestGameObjectEntryInObjectRangeCheck const&);
};
// Success at unit in range, range update for next check (this can be use with GameobjectLastSearcher to find nearest GO with a certain type)
class NearestGameObjectTypeInObjectRangeCheck
{
public:
NearestGameObjectTypeInObjectRangeCheck(WorldObject const& obj, GameobjectTypes type, float range) : i_obj(obj), i_type(type), i_range(range) {}
bool operator()(GameObject* go)
{
if (go->GetGoType() == i_type && i_obj.IsWithinDistInMap(go, i_range))
{
i_range = i_obj.GetDistance(go); // use found GO range as new range limit for next check
return true;
}
return false;
}
private:
WorldObject const& i_obj;
GameobjectTypes i_type;
float i_range;
// prevent clone this object
NearestGameObjectTypeInObjectRangeCheck(NearestGameObjectTypeInObjectRangeCheck const&);
};
// Unit checks
class MostHPMissingInRange
{
public:
MostHPMissingInRange(Unit const* obj, float range, uint32 hp) : i_obj(obj), i_range(range), i_hp(hp) {}
bool operator()(Unit* u)
{
if (u->IsAlive() && u->IsInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && u->GetMaxHealth() - u->GetHealth() > i_hp)
{
i_hp = u->GetMaxHealth() - u->GetHealth();
return true;
}
return false;
}
private:
Unit const* i_obj;
float i_range;
uint32 i_hp;
};
class MostHPPercentMissingInRange
{
public:
MostHPPercentMissingInRange(Unit const* obj, float range, uint32 minHpPct, uint32 maxHpPct) :
i_obj(obj), i_range(range), i_minHpPct(minHpPct), i_maxHpPct(maxHpPct), i_hpPct(101.f) { }
bool operator()(Unit* u)
{
if (u->IsAlive() && u->IsInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) &&
i_minHpPct <= u->GetHealthPct() && u->GetHealthPct() <= i_maxHpPct && u->GetHealthPct() < i_hpPct)
{
i_hpPct = u->GetHealthPct();
return true;
}
return false;
}
private:
Unit const* i_obj;
float i_range;
float i_minHpPct, i_maxHpPct, i_hpPct;
};
class FriendlyCCedInRange
{
public:
FriendlyCCedInRange(Unit const* obj, float range) : i_obj(obj), i_range(range) {}
bool operator()(Unit* u)
{
if (u->IsAlive() && u->IsInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) &&
(u->HasFearAura() || u->IsCharmed() || u->isFrozen() || u->HasUnitState(UNIT_STATE_STUNNED) || u->HasUnitState(UNIT_STATE_CONFUSED)))
{
return true;
}
return false;
}
private:
Unit const* i_obj;
float i_range;
};
class FriendlyMissingBuffInRange
{
public:
FriendlyMissingBuffInRange(Unit const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range)
{
i_spell = spellid;
if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(spellid))
if (SpellInfo const* newSpell = sSpellMgr->GetSpellForDifficultyFromSpell(spell, const_cast(obj)))
i_spell = newSpell->Id;
}
bool operator()(Unit* u)
{
if (u->IsAlive() && u->IsInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) &&
!(u->HasAura(i_spell)))
{
return true;
}
return false;
}
private:
Unit const* i_obj;
float i_range;
uint32 i_spell;
};
class AnyUnfriendlyUnitInObjectRangeCheck
{
public:
AnyUnfriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {}
bool operator()(Unit* u)
{
if (u->IsAlive() && !u->IsCritter() && i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u) &&
(!i_funit->IsCreature() || !i_funit->ToCreature()->IsAvoidingAOE())) // pussywizard
return true;
else
return false;
}
private:
WorldObject const* i_obj;
Unit const* i_funit;
float i_range;
};
class AnyUnfriendlyNoTotemUnitInObjectRangeCheck
{
public:
AnyUnfriendlyNoTotemUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {}
bool operator()(Unit* u)
{
if (!u->IsAlive())
return false;
if (u->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET)
return false;
if (u->IsCreature() && (u->ToCreature()->IsTotem() || u->ToCreature()->IsTrigger() || u->ToCreature()->IsAvoidingAOE())) // pussywizard: added IsAvoidingAOE()
return false;
if (!u->isTargetableForAttack(false, i_funit))
return false;
return i_obj->IsWithinDistInMap(u, i_range) && !i_funit->IsFriendlyTo(u);
}
private:
WorldObject const* i_obj;
Unit const* i_funit;
float i_range;
};
class NearestAttackableNoTotemUnitInObjectRangeCheck
{
public:
NearestAttackableNoTotemUnitInObjectRangeCheck(WorldObject const* obj, Unit const* owner, float range) : i_obj(obj), i_owner(owner), i_range(range) {}
bool operator()(Unit* u)
{
if (!u->IsAlive())
{
return false;
}
if (u->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET)
{
return false;
}
if (u->IsCreature() && u->ToCreature()->IsTotem())
{
return false;
}
if (!u->isTargetableForAttack(false, i_owner))
{
return false;
}
uint32 losChecks = LINEOFSIGHT_ALL_CHECKS;
Optional collisionHeight = { };
if (i_obj->IsGameObject())
{
losChecks &= ~LINEOFSIGHT_CHECK_GOBJECT_M2;
collisionHeight = i_owner->GetCollisionHeight();
}
if (!i_obj->IsWithinDistInMap(u, i_range) || !i_owner->IsValidAttackTarget(u) ||
!i_obj->IsWithinLOSInMap(u, VMAP::ModelIgnoreFlags::Nothing, LineOfSightChecks(losChecks), collisionHeight))
{
return false;
}
return true;
}
private:
WorldObject const* i_obj;
Unit const* i_owner;
float i_range;
};
class AnyUnfriendlyAttackableVisibleUnitInObjectRangeCheck
{
public:
AnyUnfriendlyAttackableVisibleUnitInObjectRangeCheck(Unit const* funit, float range)
: i_funit(funit), i_range(range) {}
bool operator()(Unit const* u)
{
return u->IsAlive()
&& i_funit->IsWithinDistInMap(u, i_range)
&& !i_funit->IsFriendlyTo(u)
&& i_funit->IsValidAttackTarget(u)
&& !u->IsCritter()
&& !u->IsTotem() //xinef: dont attack totems
/*&& i_funit->CanSeeOrDetect(u)*/; // pussywizard: already checked in IsValidAttackTarget(u)
}
private:
Unit const* i_funit;
float i_range;
};
class AnyFriendlyUnitInObjectRangeCheck
{
public:
AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool playerOnly = false) : i_obj(obj), i_funit(funit), i_range(range), i_playerOnly(playerOnly) {}
bool operator()(Unit* u)
{
if (u->IsAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u) && (!i_playerOnly || u->IsPlayer()))
return true;
else
return false;
}
private:
WorldObject const* i_obj;
Unit const* i_funit;
float i_range;
bool i_playerOnly;
};
class AnyFriendlyNotSelfUnitInObjectRangeCheck
{
public:
AnyFriendlyNotSelfUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool playerOnly = false) : i_obj(obj), i_funit(funit), i_range(range), i_playerOnly(playerOnly) {}
bool operator()(Unit* u)
{
if (u != i_obj && u->IsAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u) && (!i_playerOnly || u->IsPlayer()))
return true;
else
return false;
}
private:
WorldObject const* i_obj;
Unit const* i_funit;
float i_range;
bool i_playerOnly;
};
class AnyGroupedUnitInObjectRangeCheck
{
public:
AnyGroupedUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool raid) : _source(obj), _refUnit(funit), _range(range), _raid(raid) {}
bool operator()(Unit* u)
{
if (_raid)
{
if (!_refUnit->IsInRaidWith(u))
return false;
}
else if (!_refUnit->IsInPartyWith(u))
return false;
return !_refUnit->IsHostileTo(u) && u->IsAlive() && _source->IsWithinDistInMap(u, _range);
}
private:
WorldObject const* _source;
Unit const* _refUnit;
float _range;
bool _raid;
};
class AnyUnitInObjectRangeCheck
{
public:
AnyUnitInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {}
bool operator()(Unit* u)
{
if (u->IsAlive() && i_obj->IsWithinDistInMap(u, i_range))
return true;
return false;
}
private:
WorldObject const* i_obj;
float i_range;
};
// Success at unit in range, range update for next check (this can be use with UnitLastSearcher to find nearest unit)
class NearestAttackableUnitInObjectRangeCheck
{
public:
NearestAttackableUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {}
bool operator()(Unit* u)
{
if (u->isTargetableForAttack(true, i_funit) && i_obj->IsWithinDistInMap(u, i_range) &&
(i_funit->IsInCombatWith(u) || u->IsHostileTo(i_funit)) && i_obj->CanSeeOrDetect(u))
{
i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check
return true;
}
return false;
}
private:
WorldObject const* i_obj;
Unit const* i_funit;
float i_range;
// prevent clone this object
NearestAttackableUnitInObjectRangeCheck(NearestAttackableUnitInObjectRangeCheck const&);
};
class AnyAoETargetUnitInObjectRangeCheck
{
public:
AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range)
: i_obj(obj), i_funit(funit), _spellInfo(nullptr), i_range(range)
{
Unit const* check = i_funit;
Unit const* owner = i_funit->GetOwner();
if (owner)
check = owner;
i_targetForPlayer = (check->IsPlayer());
if (i_obj->IsDynamicObject())
_spellInfo = sSpellMgr->GetSpellInfo(((DynamicObject*)i_obj)->GetSpellId());
}
bool operator()(Unit* u)
{
// Check contains checks for: live, non-selectable, non-attackable flags, flight check and GM check, ignore totems
if (Creature* creature = u->ToCreature())
{
if (creature->IsTotem())
{
return false;
}
if (creature->IsAvoidingAOE())
{
return false;
}
}
if (i_funit->_IsValidAttackTarget(u, _spellInfo, i_obj->IsDynamicObject() ? i_obj : nullptr) && i_obj->IsWithinDistInMap(u, i_range,true,false, true))
return true;
return false;
}
private:
bool i_targetForPlayer;
WorldObject const* i_obj;
Unit const* i_funit;
SpellInfo const* _spellInfo;
float i_range;
};
class AnyAttackableUnitExceptForOriginalCasterInObjectRangeCheck
{
public:
AnyAttackableUnitExceptForOriginalCasterInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range)
: i_obj(obj), i_funit(funit), i_range(range)
{}
bool operator()(Unit* u)
{
if (!u->IsAlive() || u->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE) || (u->IsImmuneToPC() && !u->IsInCombat()))
return false;
if (u->GetGUID() == i_funit->GetGUID())
return false;
if (i_obj->IsWithinDistInMap(u, i_range))
return true;
return false;
}
private:
WorldObject const* i_obj;
Unit const* i_funit;
float i_range;
};
// do attack at call of help to friendly crearture
class CallOfHelpCreatureInRangeDo
{
public:
CallOfHelpCreatureInRangeDo(Unit* funit, Unit* enemy, float range)
: i_funit(funit), i_enemy(enemy), i_range(range)
{}
void operator()(Creature* u)
{
if (u == i_funit)
return;
if (!u->CanAssistTo(i_funit, i_enemy, false))
return;
// too far
if (!u->IsWithinDistInMap(i_funit, i_range))
return;
// only if see assisted creature's enemy
if (!u->IsWithinLOSInMap(i_enemy))
return;
if (u->AI())
{
u->SetNoCallForHelp(true); // avoid recursive call for help causing stack overflow
u->AI()->AttackStart(i_enemy);
u->SetNoCallForHelp(false);
}
}
private:
Unit* const i_funit;
Unit* const i_enemy;
float i_range;
};
struct AnyDeadUnitCheck
{
bool operator()(Unit* u) { return !u->IsAlive(); }
};
/*
struct AnyStealthedCheck
{
bool operator()(Unit* u) { return u->GetVisibility() == VISIBILITY_GROUP_STEALTH; }
};
*/
// Creature checks
class NearestHostileUnitCheck
{
public:
explicit NearestHostileUnitCheck(Creature const* creature, float dist = 0, bool playerOnly = false) : me(creature), i_playerOnly(playerOnly)
{
m_range = (dist == 0 ? 9999 : dist);
}
bool operator()(Unit* u)
{
if (!me->IsWithinDistInMap(u, m_range, true, false, false))
return false;
if (!me->IsValidAttackTarget(u))
return false;
if (i_playerOnly && !u->IsPlayer())
return false;
m_range = me->GetDistance(u); // use found unit range as new range limit for next check
return true;
}
private:
Creature const* me;
float m_range;
bool i_playerOnly;
NearestHostileUnitCheck(NearestHostileUnitCheck const&);
};
class NearestHostileUnitInAttackDistanceCheck
{
public:
explicit NearestHostileUnitInAttackDistanceCheck(Creature const* creature, float dist) : me(creature), m_range(dist) {}
bool operator()(Unit* u)
{
if (!me->IsWithinDistInMap(u, m_range, true, false, false))
return false;
if (!me->CanStartAttack(u))
return false;
m_range = me->GetDistance(u); // use found unit range as new range limit for next check
return true;
}
private:
Creature const* me;
float m_range;
NearestHostileUnitInAttackDistanceCheck(NearestHostileUnitInAttackDistanceCheck const&);
};
class NearestVisibleDetectableContestedGuardUnitCheck
{
public:
explicit NearestVisibleDetectableContestedGuardUnitCheck(Unit const* unit) : me(unit) {}
bool operator()(Unit* u)
{
if (!u->CanSeeOrDetect(me, true, true, false))
{
return false;
}
if (!u->IsContestedGuard())
{
return false;
}
return true;
}
private:
Unit const* me;
NearestVisibleDetectableContestedGuardUnitCheck(NearestVisibleDetectableContestedGuardUnitCheck const&);
};
class AnyAssistCreatureInRangeCheck
{
public:
AnyAssistCreatureInRangeCheck(Unit* funit, Unit* enemy, float range)
: i_funit(funit), i_enemy(enemy), i_range(range)
{
}
bool operator()(Creature* u)
{
if (u == i_funit)
return false;
if (!u->CanAssistTo(i_funit, i_enemy))
return false;
// too far
if (!i_funit->IsWithinDistInMap(u, i_range))
return false;
// only if see assisted creature
if (!i_funit->IsWithinLOSInMap(u))
return false;
return true;
}
private:
Unit* const i_funit;
Unit* const i_enemy;
float i_range;
};
class NearestAssistCreatureInCreatureRangeCheck
{
public:
NearestAssistCreatureInCreatureRangeCheck(Creature* obj, Unit* enemy, float range)
: i_obj(obj), i_enemy(enemy), i_range(range) {}
bool operator()(Creature* u)
{
if (u == i_obj)
return false;
if (!u->CanAssistTo(i_obj, i_enemy))
return false;
if (!i_obj->IsWithinDistInMap(u, i_range))
return false;
if (!i_obj->IsWithinLOSInMap(u))
return false;
i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check
return true;
}
private:
Creature* const i_obj;
Unit* const i_enemy;
float i_range;
// prevent clone this object
NearestAssistCreatureInCreatureRangeCheck(NearestAssistCreatureInCreatureRangeCheck const&);
};
// Success at unit in range, range update for next check (this can be use with CreatureLastSearcher to find nearest creature)
class NearestCreatureEntryWithLiveStateInObjectRangeCheck
{
public:
NearestCreatureEntryWithLiveStateInObjectRangeCheck(WorldObject const& obj, uint32 entry, bool alive, float range)
: i_obj(obj), i_entry(entry), i_alive(alive), i_range(range) {}
bool operator()(Creature* u)
{
if (u->GetEntry() == i_entry && u->IsAlive() == i_alive && i_obj.IsWithinDist(u, i_range) && i_obj.InSamePhase(u))
{
i_range = i_obj.GetDistance(u); // use found unit range as new range limit for next check
return true;
}
return false;
}
private:
WorldObject const& i_obj;
uint32 i_entry;
bool i_alive;
float i_range;
// prevent clone this object
NearestCreatureEntryWithLiveStateInObjectRangeCheck(NearestCreatureEntryWithLiveStateInObjectRangeCheck const&);
};
class AnyPlayerInObjectRangeCheck
{
public:
AnyPlayerInObjectRangeCheck(WorldObject const* obj, float range, bool reqAlive = true, bool disallowGM = false) : _obj(obj), _range(range), _reqAlive(reqAlive), _disallowGM(disallowGM) {}
bool operator()(Player* u)
{
if (_reqAlive && !u->IsAlive())
return false;
if (_disallowGM && (u->IsGameMaster() || u->IsSpectator()))
return false;
if (!_obj->IsWithinDistInMap(u, _range))
return false;
return true;
}
// pussywizard: needed for DestroyForNearbyPlayers
bool operator()(Player* u, bool checkRange)
{
if (checkRange && !_obj->IsWithinDistInMap(u, _range))
return false;
return true;
}
private:
WorldObject const* _obj;
float _range;
bool _reqAlive;
bool _disallowGM;
};
class AnyPlayerExactPositionInGameObjectRangeCheck
{
public:
AnyPlayerExactPositionInGameObjectRangeCheck(GameObject const* go, float range) : _go(go), _range(range) {}
bool operator()(Player* u)
{
if (!_go->IsInRange(u->GetPositionX(), u->GetPositionY(), u->GetPositionZ(), _range))
return false;
return true;
}
private:
GameObject const* _go;
float _range;
};
class NearestPlayerInObjectRangeCheck
{
public:
NearestPlayerInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range)
{
}
bool operator()(Player* u)
{
if (u->IsAlive() && i_obj->IsWithinDistInMap(u, i_range))
{
i_range = i_obj->GetDistance(u);
return true;
}
return false;
}
private:
WorldObject const* i_obj;
float i_range;
NearestPlayerInObjectRangeCheck(NearestPlayerInObjectRangeCheck const&);
};
class AllFriendlyCreaturesInGrid
{
public:
AllFriendlyCreaturesInGrid(Unit const* obj) : unit(obj) {}
bool operator() (Unit* u)
{
if (u->IsAlive() && u->IsVisible() && u->IsFriendlyTo(unit))
return true;
return false;
}
private:
Unit const* unit;
};
class AllGameObjectsWithEntryInRange
{
public:
AllGameObjectsWithEntryInRange(WorldObject const* object, uint32 entry, float maxRange) : m_pObject(object), m_uiEntry(entry), m_fRange(maxRange) {}
bool operator() (GameObject* go)
{
if (go->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(go, m_fRange, false))
return true;
return false;
}
private:
WorldObject const* m_pObject;
uint32 m_uiEntry;
float m_fRange;
};
class AllGameObjectsMatchingOneEntryInRange
{
public:
AllGameObjectsMatchingOneEntryInRange(WorldObject const* object, std::vector entries, float maxRange) : m_pObject(object), m_uiEntries(entries), m_fRange(maxRange) {}
bool operator()(GameObject *go)
{
if (std::ranges::any_of( m_uiEntries, [go](uint32 entry) { return go->GetEntry() == entry; }) && m_pObject->IsWithinDist(go, m_fRange, false))
return true;
return false;
}
private:
WorldObject const* m_pObject;
std::vector m_uiEntries;
float m_fRange;
};
class AllCreaturesOfEntryInRange
{
public:
AllCreaturesOfEntryInRange(WorldObject const* object, uint32 entry, float maxRange) : m_pObject(object), m_uiEntry(entry), m_fRange(maxRange) {}
bool operator() (Unit* unit)
{
if (unit->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(unit, m_fRange, false))
return true;
return false;
}
private:
WorldObject const* m_pObject;
uint32 m_uiEntry;
float m_fRange;
};
class AllCreaturesMatchingOneEntryInRange
{
public:
AllCreaturesMatchingOneEntryInRange(WorldObject const* object, std::vector entries, float maxRange) : m_pObject(object), m_uiEntries(entries), m_fRange(maxRange) {}
bool operator()(Unit* unit)
{
if (std::ranges::any_of(m_uiEntries, [unit](uint32 entry) { return unit->GetEntry() == entry; }) && m_pObject->IsWithinDist(unit, m_fRange, false))
return true;
return false;
}
private:
WorldObject const* m_pObject;
std::vector m_uiEntries;
float m_fRange;
};
class MostHPMissingGroupInRange
{
public:
MostHPMissingGroupInRange(Unit const* obj, float range, uint32 hp) : i_obj(obj), i_range(range), i_hp(hp) {}
bool operator()(Unit* u)
{
if (i_obj == u)
{
return false;
}
Player* player = nullptr;
if (u->IsPlayer())
{
player = u->ToPlayer();
}
else if (u->IsPet() && u->GetOwner())
{
player = u->GetOwner()->ToPlayer();
}
if (!player)
{
return false;
}
Group* group = player->GetGroup();
if (!group || !group->IsMember(i_obj->IsPet() ? i_obj->GetOwnerGUID() : i_obj->GetGUID()))
{
return false;
}
if (u->IsAlive() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && u->GetMaxHealth() - u->GetHealth() > i_hp)
{
i_hp = u->GetMaxHealth() - u->GetHealth();
return true;
}
return false;
}
private:
Unit const* i_obj;
float i_range;
uint32 i_hp;
};
class AllDeadCreaturesInRange
{
public:
AllDeadCreaturesInRange(WorldObject const* obj, float range, bool reqAlive = true) : _obj(obj), _range(range), _reqAlive(reqAlive) {}
bool operator()(Unit* unit) const
{
if (_reqAlive && unit->IsAlive())
{
return false;
}
if (!_obj->IsWithinDistInMap(unit, _range))
{
return false;
}
return true;
}
private:
WorldObject const* _obj;
float _range;
bool _reqAlive;
};
class PlayerAtMinimumRangeAway
{
public:
PlayerAtMinimumRangeAway(Unit const* unit, float fMinRange) : unit(unit), fRange(fMinRange) {}
bool operator() (Player* player)
{
//No threat list check, must be done explicit if expected to be in combat with creature
if (!player->IsGameMaster() && player->IsAlive() && !unit->IsWithinDist(player, fRange, false))
return true;
return false;
}
private:
Unit const* unit;
float fRange;
};
class GameObjectInRangeCheck
{
public:
GameObjectInRangeCheck(float _x, float _y, float _z, float _range, uint32 _entry = 0) :
x(_x), y(_y), z(_z), range(_range), entry(_entry) {}
bool operator() (GameObject* go)
{
if (!entry || (go->GetGOInfo() && go->GetGOInfo()->entry == entry))
return go->IsInRange(x, y, z, range);
else return false;
}
private:
float x, y, z, range;
uint32 entry;
};
class AllWorldObjectsInRange
{
public:
AllWorldObjectsInRange(WorldObject const* object, float maxRange) : m_pObject(object), m_fRange(maxRange) {}
bool operator() (WorldObject* go)
{
return m_pObject->IsWithinDist(go, m_fRange, false) && m_pObject->InSamePhase(go);
}
private:
WorldObject const* m_pObject;
float m_fRange;
};
class ObjectTypeIdCheck
{
public:
ObjectTypeIdCheck(TypeID typeId, bool equals) : _typeId(typeId), _equals(equals) {}
bool operator()(WorldObject const* object)
{
return (object->GetTypeId() == _typeId) == _equals;
}
private:
TypeID _typeId;
bool _equals;
};
class ObjectGUIDCheck
{
public:
ObjectGUIDCheck(ObjectGuid GUID, bool equals) : _GUID(GUID), _equals(equals) {}
bool operator()(WorldObject const* object)
{
return (object->GetGUID() == _GUID) == _equals;
}
private:
ObjectGuid _GUID;
bool _equals;
};
class UnitAuraCheck
{
public:
UnitAuraCheck(bool present, uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty) : _present(present), _spellId(spellId), _casterGUID(casterGUID) {}
bool operator()(Unit const* unit) const
{
return unit->HasAura(_spellId, _casterGUID) == _present;
}
bool operator()(WorldObject const* object) const
{
return object->ToUnit() && object->ToUnit()->HasAura(_spellId, _casterGUID) == _present;
}
private:
bool _present;
uint32 _spellId;
ObjectGuid _casterGUID;
};
class AllWorldObjectsInExactRange
{
public:
AllWorldObjectsInExactRange(WorldObject const* object, float range, bool equals) : _object(object), _range(range), _equals(equals) { }
bool operator() (WorldObject const* object)
{
return (_object->GetExactDist2d(object) > _range) == _equals;
}
private:
WorldObject const* _object;
float _range;
bool _equals;
};
class RandomCheck
{
public:
explicit RandomCheck(uint8 chance) : _chance(chance) { }
bool operator()(WorldObject const* /*object*/) const
{
return roll_chance_i(_chance);
}
private:
uint8 const _chance;
};
class PowerCheck
{
public:
explicit PowerCheck(Powers const power, bool equals) : _power(power), _equals(equals) { }
bool operator()(WorldObject const* object) const
{
return object->ToUnit() && (object->ToUnit()->getPowerType() == _power) == _equals;
}
private:
Powers const _power;
bool const _equals;
};
class RaidCheck
{
public:
explicit RaidCheck(Unit const* compare, bool equals) : _compare(compare), _equals(equals) { }
bool operator()(WorldObject const* object) const
{
return object->ToUnit() && object->ToUnit()->IsInRaidWith(_compare) == _equals;
}
private:
Unit const* _compare;
bool const _equals;
};
// Player checks and do
// Prepare using Builder localized packets with caching and send to player
template
class LocalizedPacketDo
{
public:
explicit LocalizedPacketDo(Builder& builder) : i_builder(builder) {}
~LocalizedPacketDo()
{
for (std::size_t i = 0; i < i_data_cache.size(); ++i)
delete i_data_cache[i];
}
void operator()(Player* p);
private:
Builder& i_builder;
std::vector i_data_cache; // 0 = default, i => i-1 locale index
};
// Prepare using Builder localized packets with caching and send to player
template
class LocalizedPacketListDo
{
public:
typedef std::vector WorldPacketList;
explicit LocalizedPacketListDo(Builder& builder) : i_builder(builder) {}
~LocalizedPacketListDo()
{
for (std::size_t i = 0; i < i_data_cache.size(); ++i)
for (std::size_t j = 0; j < i_data_cache[i].size(); ++j)
delete i_data_cache[i][j];
}
void operator()(Player* p);
private:
Builder& i_builder;
std::vector i_data_cache;
// 0 = default, i => i-1 locale index
};
}
#endif