Merge commit 'origin/master' into 320

This commit is contained in:
tomrus88 2009-09-22 18:14:06 +04:00
commit 258e19a4a3
48 changed files with 744 additions and 206 deletions

View file

@ -21,7 +21,7 @@
DROP TABLE IF EXISTS `character_db_version`;
CREATE TABLE `character_db_version` (
`required_8469_01_characters_character_spell` bit(1) default NULL
`required_8505_01_characters_character_spell` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB';
--

View file

@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
`version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL,
`cache_id` int(10) default '0',
`required_8499_01_mangos_spell_elixir` bit(1) default NULL
`required_8521_01_mangos_spell_proc_event` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
--
@ -9746,7 +9746,7 @@ INSERT INTO `playercreateinfo_action` VALUES
(1,1,96,6603,0),
(1,1,108,6603,0),
(1,2,0,6603,0),
(1,2,1,20154,0),
(1,2,1,21084,0),
(1,2,2,635,0),
(1,2,9,59752,0),
(1,2,10,159,128),
@ -9833,7 +9833,7 @@ INSERT INTO `playercreateinfo_action` VALUES
(3,1,96,6603,0),
(3,1,108,6603,0),
(3,2,0,6603,0),
(3,2,1,20154,0),
(3,2,1,21084,0),
(3,2,2,635,0),
(3,2,3,20594,0),
(3,2,4,2481,0),
@ -10295,7 +10295,7 @@ INSERT INTO `playercreateinfo_spell` VALUES
(1,2,9078,'Cloth'),
(1,2,9116,'Shield'),
(1,2,9125,'Generic'),
(1,2,20154,'Seal of Righteousness'),
(1,2,21084,'Seal of Righteousness'),
(1,2,20597,'Sword Specialization'),
(1,2,20598,'The Human Spirit'),
(1,2,20599,'Diplomacy'),
@ -10882,7 +10882,7 @@ INSERT INTO `playercreateinfo_spell` VALUES
(3,2,9078,'Cloth'),
(3,2,9116,'Shield'),
(3,2,9125,'Generic'),
(3,2,20154,'Seal of Righteousness'),
(3,2,21084,'Seal of Righteousness'),
(3,2,20594,'Stoneform'),
(3,2,20595,'Gun Specialization'),
(3,2,20596,'Frost Resistance'),
@ -13659,6 +13659,7 @@ INSERT INTO `spell_bonus_data` VALUES
(20925, 0.09, 0, 0.056, 'Paladin - Holy Shield'),
(31803, 0, 0.0156, 0.03, 'Paladin - Holy Vengeance'),
(2812, 0.07, 0, 0.07, 'Paladin - Holy Wrath'),
(54158, 0.25, 0, 0, 'Paladin - Judgement'),
(31898, 0.18, 0, 0.11, 'Paladin - Judgement of Blood Enemy'),
(32220, 0.0594, 0, 0.0363,'Paladin - Judgement of Blood Self'),
(20467, 0.25, 0, 0.16, 'Paladin - Judgement of Command'),
@ -17929,6 +17930,7 @@ INSERT INTO `spell_proc_event` VALUES
(56344, 0x00000000, 9, 0x00004000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(56355, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0.000000, 0.000000, 0),
(56364, 0x00000000, 3, 0x00000000, 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(56372, 0x00000000, 3, 0x00000000, 0x00000080, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0),
(56451, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 3),
(56611, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(56612, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
@ -17942,6 +17944,8 @@ INSERT INTO `spell_proc_event` VALUES
(56834, 0x00000000, 15, 0x00440000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(56835, 0x00000000, 15, 0x00440000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(57352, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00010154, 0x00000003, 0.000000, 0.000000, 45),
(57470, 0x00000000, 6, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(57472, 0x00000000, 6, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(57878, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000010, 0.000000, 0.000000, 0),
(57880, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000010, 0.000000, 0.000000, 0),
(57881, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000010, 0.000000, 0.000000, 0),

View file

@ -308,8 +308,11 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
(53196, 7,0x0000000000000000,0x00000100, -1, -1, -1, 3, -1,-1,'Starfall', 'Spell::EffectDummy'),
(53197, 7,0x0000000000000000,0x00000100, -1, -1, -1, 3, -1,-1,'Starfall', 'Spell::EffectDummy'),
(53198, 7,0x0000000000000000,0x00000100, -1, -1, -1, 3, -1,-1,'Starfall', 'Spell::EffectDummy'),
(53271,-1, -1, -1, -1, -1, -1, 3, -1,-1,'Master''s Call', 'Spell::EffectDummy'),
(53271,-1, -1, -1, -1, -1, -1, 77, -1,-1,'Master''s Call', 'Spell::EffectScriptEffect'),
(53341, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Rune of Cinderglacier', 'Spell::EffectDummy'),
(53343, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Rune of Razorice', 'Spell::EffectDummy'),
(54216,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Master''s Call', 'Spell::EffectDummy'),
(54586,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Runeforging Credit', 'Spell::EffectDummy'),
(54824,-1, -1, -1, -1, -1, -1, -1, 4,-1,'Glyph of Swiftmend', 'Spell::EffectHeal'),
(54861,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Nitro Boosts', 'Spell::EffectDummy'),
@ -335,6 +338,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
(61491, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Intercept', 'Spell::EffectSchoolDMG'),
(61507, 9, -1, -1, -1, -1, -1, 3, -1,-1,'Disengage', 'Spell::EffectDummy'),
(61508,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Disengage', 'Spell::EffectDummy'),
(62305,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Master''s Call', 'Spell::EffectScriptEffect'),
(63375,-1, -1, -1, -1, -1, -1, 30, -1,-1,'Improved Stormstrike', 'Spell::EffectEnergize'),
/* sorted by spell names */

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_8499_01_mangos_spell_elixir required_8504_01_mangos_playercreateinfo_spell bit;
UPDATE `playercreateinfo_spell`
SET `spell` = 21084
WHERE `spell` = 20154;

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_8504_01_mangos_playercreateinfo_spell required_8504_02_mangos_playercreateinfo_action bit;
UPDATE `playercreateinfo_action`
SET `action` = 21084
WHERE `action` = 20154 AND `type` = 0;

View file

@ -0,0 +1,3 @@
ALTER TABLE character_db_version CHANGE COLUMN required_8469_01_characters_character_spell required_8505_01_characters_character_spell bit;
UPDATE character_spell SET active=1 WHERE spell=16857;

View file

@ -0,0 +1,7 @@
ALTER TABLE db_version CHANGE COLUMN required_8504_02_mangos_playercreateinfo_action required_8511_01_mangos_spell_proc_event bit;
DELETE FROM `spell_proc_event` WHERE `entry` IN (57470, 57472);
INSERT INTO spell_proc_event VALUES
(57470, 0x00000000, 6, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(57472, 0x00000000, 6, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0);

View file

@ -0,0 +1,6 @@
ALTER TABLE db_version CHANGE COLUMN required_8511_01_mangos_spell_proc_event required_8514_01_mangos_spell_bonus_data bit;
DELETE FROM `spell_bonus_data` WHERE `entry` IN (54158);
INSERT INTO `spell_bonus_data` VALUES
(54158, 0.25, 0, 0, 'Paladin - Judgement');

View file

@ -0,0 +1,6 @@
ALTER TABLE db_version CHANGE COLUMN required_8514_01_mangos_spell_bonus_data required_8521_01_mangos_spell_proc_event bit;
DELETE FROM `spell_proc_event` WHERE `entry` = 56372;
INSERT INTO `spell_proc_event` VALUES
(56372, 0x00, 3, 0x00000000, 0x00000080, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0);

View file

@ -107,6 +107,12 @@ pkgdata_DATA = \
8488_02_mangos_spell_bonus_data.sql \
8498_01_mangos_spell_proc_event.sql \
8499_01_mangos_spell_elixir.sql \
8504_01_mangos_playercreateinfo_spell.sql \
8504_02_mangos_playercreateinfo_action.sql \
8505_01_characters_character_spell.sql \
8511_01_mangos_spell_proc_event.sql \
8514_01_mangos_spell_bonus_data.sql \
8521_01_mangos_spell_proc_event.sql \
README
## Additional files to include when running 'make dist'
@ -194,4 +200,10 @@ EXTRA_DIST = \
8488_02_mangos_spell_bonus_data.sql \
8498_01_mangos_spell_proc_event.sql \
8499_01_mangos_spell_elixir.sql \
8504_01_mangos_playercreateinfo_spell.sql \
8504_02_mangos_playercreateinfo_action.sql \
8505_01_characters_character_spell.sql \
8511_01_mangos_spell_proc_event.sql \
8514_01_mangos_spell_bonus_data.sql \
8521_01_mangos_spell_proc_event.sql \
README

View file

@ -79,8 +79,19 @@ class MANGOS_DLL_DECL NGrid
i_GridInfo = GridInfo(expiry, unload);
}
const GridType& operator()(unsigned short x, unsigned short y) const { return i_cells[x][y]; }
GridType& operator()(unsigned short x, unsigned short y) { return i_cells[x][y]; }
const GridType& operator()(unsigned short x, unsigned short y) const
{
ASSERT(x < N);
ASSERT(y < N);
return i_cells[x][y];
}
GridType& operator()(unsigned short x, unsigned short y)
{
ASSERT(x < N);
ASSERT(y < N);
return i_cells[x][y];
}
const uint32& GetGridId(void) const { return i_gridId; }
void SetGridId(const uint32 id) const { i_gridId = id; }
@ -108,12 +119,12 @@ class MANGOS_DLL_DECL NGrid
template<class SPECIFIC_OBJECT> void AddWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl)
{
i_cells[x][y].AddWorldObject(obj, hdl);
getGridType(x, y).AddWorldObject(obj, hdl);
}
template<class SPECIFIC_OBJECT> void RemoveWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl)
{
i_cells[x][y].RemoveWorldObject(obj, hdl);
getGridType(x, y).RemoveWorldObject(obj, hdl);
}
template<class T, class TT> void Visit(TypeContainerVisitor<T, TypeMapContainer<TT> > &visitor)
@ -125,7 +136,7 @@ class MANGOS_DLL_DECL NGrid
template<class T, class TT> void Visit(const uint32 &x, const uint32 &y, TypeContainerVisitor<T, TypeMapContainer<TT> > &visitor)
{
i_cells[x][y].Visit(visitor);
getGridType(x, y).Visit(visitor);
}
unsigned int ActiveObjectsInGrid(void) const
@ -139,26 +150,33 @@ class MANGOS_DLL_DECL NGrid
template<class SPECIFIC_OBJECT> const SPECIFIC_OBJECT* GetGridObject(const uint32 x, const uint32 y, OBJECT_HANDLE hdl) const
{
return i_cells[x][y].template GetGridObject<SPECIFIC_OBJECT>(hdl);
return getGridType(x, y).template GetGridObject<SPECIFIC_OBJECT>(hdl);
}
template<class SPECIFIC_OBJECT> SPECIFIC_OBJECT* GetGridObject(const uint32 x, const uint32 y, OBJECT_HANDLE hdl)
{
return i_cells[x][y].template GetGridObject<SPECIFIC_OBJECT>(hdl);
return getGridType(x, y).template GetGridObject<SPECIFIC_OBJECT>(hdl);
}
template<class SPECIFIC_OBJECT> bool AddGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl)
{
return i_cells[x][y].AddGridObject(hdl, obj);
return getGridType(x, y).AddGridObject(hdl, obj);
}
template<class SPECIFIC_OBJECT> bool RemoveGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl)
{
return i_cells[x][y].RemoveGridObject(obj, hdl);
return getGridType(x, y).RemoveGridObject(obj, hdl);
}
private:
GridType& getGridType(const uint32& x, const uint32& y)
{
ASSERT(x < N);
ASSERT(y < N);
return i_cells[x][y];
}
uint32 i_gridId;
GridInfo i_GridInfo;
GridReference<NGrid<N, ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES, ThreadModel> > i_Reference;

View file

@ -605,7 +605,7 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement)
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::AchievementChatBuilder> > say_worker(GetPlayer(),sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY),say_do);
TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::AchievementChatBuilder> >, WorldTypeMapContainer > message(say_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetPlayer()->GetMap());
cell_lock->Visit(cell_lock, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY));
}
WorldPacket data(SMSG_ACHIEVEMENT_EARNED, 8+4+8);

View file

@ -25,6 +25,7 @@
#include <cmath>
class Map;
class WorldObject;
enum District
{
@ -42,6 +43,26 @@ enum District
template<class T> struct CellLock;
struct MANGOS_DLL_DECL CellArea
{
CellArea() : right_offset(0), left_offset(0), upper_offset(0), lower_offset(0) {}
CellArea(int right, int left, int upper, int lower) : right_offset(right), left_offset(left), upper_offset(upper), lower_offset(lower) {}
bool operator!() const { return !right_offset && !left_offset && !upper_offset && !lower_offset; }
void ResizeBorders(CellPair& begin_cell, CellPair& end_cell) const
{
begin_cell << left_offset;
begin_cell -= lower_offset;
end_cell >> right_offset;
end_cell += upper_offset;
}
int right_offset;
int left_offset;
int upper_offset;
int lower_offset;
};
struct MANGOS_DLL_DECL Cell
{
Cell() { data.All = 0; }
@ -131,15 +152,21 @@ struct MANGOS_DLL_DECL Cell
{
unsigned grid_x : 6;
unsigned grid_y : 6;
unsigned cell_x : 4;
unsigned cell_y : 4;
unsigned cell_x : 6;
unsigned cell_y : 6;
unsigned nocreate : 1;
unsigned reserved : 11;
unsigned reserved : 7;
} Part;
uint32 All;
} data;
template<class LOCK_TYPE, class T, class CONTAINER> void Visit(const CellLock<LOCK_TYPE> &, TypeContainerVisitor<T, CONTAINER> &visitor, Map &) const;
template<class LOCK_TYPE, class T, class CONTAINER> void Visit(const CellLock<LOCK_TYPE> &, TypeContainerVisitor<T, CONTAINER> &visitor, Map &m, const WorldObject &obj, float radius) const;
static CellArea CalculateCellArea(const WorldObject &obj, float radius);
private:
template<class LOCK_TYPE, class T, class CONTAINER> void VisitCircle(const CellLock<LOCK_TYPE> &, TypeContainerVisitor<T, CONTAINER> &, Map &, const CellPair& , const CellPair& ) const;
};
template<class T>

View file

@ -127,4 +127,163 @@ Cell::Visit(const CellLock<LOCK_TYPE> &l, TypeContainerVisitor<T, CONTAINER> &vi
}
}
}
inline int CellHelper(const float radius)
{
if(radius < 1.0f)
return 0;
return (int)ceilf(radius/SIZE_OF_GRID_CELL);
}
inline CellArea Cell::CalculateCellArea(const WorldObject &obj, float radius)
{
if(radius <= 0.0f)
return CellArea();
//we should increase search radius by object's radius, otherwise
//we could have problems with huge creatures, which won't attack nearest players etc
radius += obj.GetObjectSize();
//lets calculate object coord offsets from cell borders.
//TODO: add more correct/generic method for this task
const float x_offset = (obj.GetPositionX() - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL;
const float y_offset = (obj.GetPositionY() - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL;
const float x_val = floor(x_offset + CENTER_GRID_CELL_ID + 0.5f);
const float y_val = floor(y_offset + CENTER_GRID_CELL_ID + 0.5f);
const float x_off = (x_offset - x_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL;
const float y_off = (y_offset - y_val + CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL;
const float tmp_diff = radius - CENTER_GRID_CELL_OFFSET;
//lets calculate upper/lower/right/left corners for cell search
int right = CellHelper(tmp_diff + x_off);
int left = CellHelper(tmp_diff - x_off);
int upper = CellHelper(tmp_diff + y_off);
int lower = CellHelper(tmp_diff - y_off);
return CellArea(right, left, upper, lower);
}
template<class LOCK_TYPE, class T, class CONTAINER>
inline void
Cell::Visit(const CellLock<LOCK_TYPE> &l, TypeContainerVisitor<T, CONTAINER> &visitor, Map &m, const WorldObject &obj, float radius) const
{
const CellPair &standing_cell = l.i_cellPair;
if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
return;
//no jokes here... Actually placing ASSERT() here was good idea, but
//we had some problems with DynamicObjects, which pass radius = 0.0f (DB issue?)
//maybe it is better to just return when radius <= 0.0f?
if(radius <= 0.0f)
{
m.Visit(l, visitor);
return;
}
//lets limit the upper value for search radius
if(radius > 333.0f)
radius = 333.0f;
//lets calculate object coord offsets from cell borders.
CellArea area = Cell::CalculateCellArea(obj, radius);
//if radius fits inside standing cell
if(!area)
{
m.Visit(l, visitor);
return;
}
CellPair begin_cell = standing_cell;
CellPair end_cell = standing_cell;
area.ResizeBorders(begin_cell, end_cell);
//visit all cells, found in CalculateCellArea()
//if radius is known to reach cell area more than 4x4 then we should call optimized VisitCircle
//currently this technique works with MAX_NUMBER_OF_CELLS 16 and higher, with lower values
//there are nothing to optimize because SIZE_OF_GRID_CELL is too big...
if(((end_cell.x_coord - begin_cell.x_coord) > 4) && ((end_cell.y_coord - begin_cell.y_coord) > 4))
{
VisitCircle(l, visitor, m, begin_cell, end_cell);
return;
}
//ALWAYS visit standing cell first!!! Since we deal with small radiuses
//it is very essential to call visitor for standing cell firstly...
m.Visit(l, visitor);
// loop the cell range
for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; x++)
{
for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; y++)
{
CellPair cell_pair(x,y);
//lets skip standing cell since we already visited it
if(cell_pair != standing_cell)
{
Cell r_zone(cell_pair);
r_zone.data.Part.nocreate = l->data.Part.nocreate;
CellLock<LOCK_TYPE> lock(r_zone, cell_pair);
m.Visit(lock, visitor);
}
}
}
}
template<class LOCK_TYPE, class T, class CONTAINER>
inline void
Cell::VisitCircle(const CellLock<LOCK_TYPE> &l, TypeContainerVisitor<T, CONTAINER> &visitor, Map &m, const CellPair& begin_cell, const CellPair& end_cell) const
{
//here is an algorithm for 'filling' circum-squared octagon
uint32 x_shift = (uint32)ceilf((end_cell.x_coord - begin_cell.x_coord) * 0.3f - 0.5f);
//lets calculate x_start/x_end coords for central strip...
const uint32 x_start = begin_cell.x_coord + x_shift;
const uint32 x_end = end_cell.x_coord - x_shift;
//visit central strip with constant width...
for(uint32 x = x_start; x <= x_end; ++x)
{
for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y)
{
CellPair cell_pair(x,y);
Cell r_zone(cell_pair);
r_zone.data.Part.nocreate = l->data.Part.nocreate;
CellLock<LOCK_TYPE> lock(r_zone, cell_pair);
m.Visit(lock, visitor);
}
}
//if x_shift == 0 then we have too small cell area, which were already
//visited at previous step, so just return from procedure...
if(x_shift == 0)
return;
uint32 y_start = end_cell.y_coord;
uint32 y_end = begin_cell.y_coord;
//now we are visiting borders of an octagon...
for (uint32 step = 1; step <= (x_start - begin_cell.x_coord); ++step)
{
//each step reduces strip height by 2 cells...
y_end += 1;
y_start -= 1;
for (uint32 y = y_start; y >= y_end; --y)
{
//we visit cells symmetrically from both sides, heading from center to sides and from up to bottom
//e.g. filling 2 trapezoids after filling central cell strip...
CellPair cell_pair_left(x_start - step, y);
Cell r_zone_left(cell_pair_left);
r_zone_left.data.Part.nocreate = l->data.Part.nocreate;
CellLock<LOCK_TYPE> lock_left(r_zone_left, cell_pair_left);
m.Visit(lock_left, visitor);
//right trapezoid cell visit
CellPair cell_pair_right(x_end + step, y);
Cell r_zone_right(cell_pair_right);
r_zone_right.data.Part.nocreate = l->data.Part.nocreate;
CellLock<LOCK_TYPE> lock_right(r_zone_right, cell_pair_right);
m.Visit(lock_right, visitor);
}
}
}
#endif

View file

@ -584,7 +584,7 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::EmoteChatBuilder > > emote_worker(GetPlayer(),sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),emote_do);
TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::EmoteChatBuilder > >, WorldTypeMapContainer > message(emote_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetPlayer()->GetMap());
cell_lock->Visit(cell_lock, message, *GetPlayer()->GetMap(), *GetPlayer(), sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE));
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit);

View file

@ -534,7 +534,7 @@ void Creature::DoFleeToGetAssistance()
TypeContainerVisitor<MaNGOS::CreatureLastSearcher<MaNGOS::NearestAssistCreatureInCreatureRangeCheck>, GridTypeMapContainer > grid_creature_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_creature_searcher, *GetMap());
cell_lock->Visit(cell_lock, grid_creature_searcher, *GetMap(), *this, radius);
SetNoSearchAssistance(true);
if(!pCreature)
@ -1776,7 +1776,7 @@ void Creature::CallAssistance()
TypeContainerVisitor<MaNGOS::CreatureListSearcher<MaNGOS::AnyAssistCreatureInRangeCheck>, GridTypeMapContainer > grid_creature_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_creature_searcher, *GetMap());
cell_lock->Visit(cell_lock, grid_creature_searcher, *GetMap(), *this, radius);
}
if (!assistList.empty())
@ -1810,7 +1810,7 @@ void Creature::CallForHelp(float fRadius)
TypeContainerVisitor<MaNGOS::CreatureWorker<MaNGOS::CallOfHelpCreatureInRangeDo>, GridTypeMapContainer > grid_creature_searcher(worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_creature_searcher, *GetMap());
cell_lock->Visit(cell_lock, grid_creature_searcher, *GetMap(), *this, fRadius);
}
bool Creature::CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction /*= true*/) const

View file

@ -1214,7 +1214,7 @@ Unit* CreatureEventAI::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff)
TypeContainerVisitor<MaNGOS::UnitLastSearcher<MaNGOS::MostHPMissingInRange>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_creature->GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_creature->GetMap(), *m_creature, range);
return pUnit;
}
@ -1231,7 +1231,7 @@ void CreatureEventAI::DoFindFriendlyCC(std::list<Creature*>& _list, float range)
TypeContainerVisitor<MaNGOS::CreatureListSearcher<MaNGOS::FriendlyCCedInRange>, GridTypeMapContainer > grid_creature_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature->GetMap());
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature->GetMap(), *m_creature, range);
}
void CreatureEventAI::DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid)
@ -1247,7 +1247,7 @@ void CreatureEventAI::DoFindFriendlyMissingBuff(std::list<Creature*>& _list, flo
TypeContainerVisitor<MaNGOS::CreatureListSearcher<MaNGOS::FriendlyMissingBuffInRange>, GridTypeMapContainer > grid_creature_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature->GetMap());
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature->GetMap(), *m_creature, range);
}
//*********************************

View file

@ -125,8 +125,8 @@ void DynamicObject::Update(uint32 p_time)
TypeContainerVisitor<MaNGOS::DynamicObjectUpdater, GridTypeMapContainer > grid_object_notifier(notifier);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_object_notifier, *GetMap());
cell_lock->Visit(cell_lock, grid_object_notifier, *GetMap());
cell_lock->Visit(cell_lock, world_object_notifier, *GetMap(), *this, m_radius);
cell_lock->Visit(cell_lock, grid_object_notifier, *GetMap(), *this, m_radius);
}
if(deleteThis)

View file

@ -319,13 +319,13 @@ void GameObject::Update(uint32 /*p_time*/)
CellLock<GridReadGuard> cell_lock(cell, p);
TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker);
cell_lock->Visit(cell_lock, grid_object_checker, *GetMap());
cell_lock->Visit(cell_lock, grid_object_checker, *GetMap(), *this, radius);
// or unfriendly player/pet
if(!ok)
{
TypeContainerVisitor<MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
cell_lock->Visit(cell_lock, world_object_checker, *GetMap());
cell_lock->Visit(cell_lock, world_object_checker, *GetMap(), *this, radius);
}
}
else // environmental trap
@ -340,7 +340,7 @@ void GameObject::Update(uint32 /*p_time*/)
CellLock<GridReadGuard> cell_lock(cell, p);
TypeContainerVisitor<MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
cell_lock->Visit(cell_lock, world_object_checker, *GetMap());
cell_lock->Visit(cell_lock, world_object_checker, *GetMap(), *this, radius);
ok = p_ok;
}
@ -784,7 +784,7 @@ void GameObject::TriggeringLinkedGameObject( uint32 trapEntry, Unit* target)
TypeContainerVisitor<MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck>, GridTypeMapContainer > object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, object_checker, *GetMap());
cell_lock->Visit(cell_lock, object_checker, *GetMap(), *target, range);
}
// found correct GO
@ -806,7 +806,7 @@ GameObject* GameObject::LookupFishingHoleAround(float range)
CellLock<GridReadGuard> cell_lock(cell, p);
TypeContainerVisitor<MaNGOS::GameObjectSearcher<MaNGOS::NearestGameObjectFishingHole>, GridTypeMapContainer > grid_object_checker(checker);
cell_lock->Visit(cell_lock, grid_object_checker, *GetMap());
cell_lock->Visit(cell_lock, grid_object_checker, *GetMap(), *this, range);
return ok;
}
@ -1031,7 +1031,8 @@ void GameObject::Use(Unit* user)
//fish catched
player->UpdateFishingSkill();
GameObject* ok = LookupFishingHoleAround(DEFAULT_VISIBILITY_DISTANCE);
//TODO: find reasonable value for fishing hole search
GameObject* ok = LookupFishingHoleAround(20.0f + CONTACT_DISTANCE);
if (ok)
{
player->SendLoot(ok->GetGUID(),LOOT_FISHINGHOLE);

View file

@ -41,7 +41,7 @@ class Player;
#define MIN_GRID_DELAY (MINUTE*IN_MILISECONDS)
#define MIN_MAP_UPDATE_DELAY 50
#define MAX_NUMBER_OF_CELLS 4
#define MAX_NUMBER_OF_CELLS 8
#define SIZE_OF_GRID_CELL (SIZE_OF_GRIDS/MAX_NUMBER_OF_CELLS)
#define CENTER_GRID_CELL_ID (MAX_NUMBER_OF_CELLS*MAX_NUMBER_OF_GRIDS/2)
@ -86,26 +86,34 @@ struct MANGOS_DLL_DECL CoordPair
void operator<<(const uint32 val)
{
if( x_coord >= val )
if( x_coord > val )
x_coord -= val;
else
x_coord = 0;
}
void operator>>(const uint32 val)
{
if( x_coord+val < LIMIT )
x_coord += val;
else
x_coord = LIMIT - 1;
}
void operator-=(const uint32 val)
{
if( y_coord >= val )
if( y_coord > val )
y_coord -= val;
else
y_coord = 0;
}
void operator+=(const uint32 val)
{
if( y_coord+val < LIMIT )
y_coord += val;
else
y_coord = LIMIT - 1;
}
uint32 x_coord;

View file

@ -190,6 +190,7 @@ bool ChatHandler::HandleReloadConfigCommand(const char* /*args*/)
{
sLog.outString( "Re-Loading config settings..." );
sWorld.LoadConfigSettings(true);
MapManager::Instance().InitializeVisibilityDistanceInfo();
SendGlobalSysMessage("World config settings reloaded.");
return true;
}

View file

@ -41,6 +41,7 @@
#define DEFAULT_GRID_EXPIRY 300
#define MAX_GRID_LOAD_TIME 50
#define MAX_CREATURE_ATTACK_RADIUS (45.0f * sWorld.getRate(RATE_CREATURE_AGGRO))
GridState* si_GridStates[MAX_GRID_STATE];
@ -198,7 +199,8 @@ Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _par
: i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode),
i_id(id), i_InstanceId(InstanceId), m_unloadTimer(0),
m_activeNonPlayersIter(m_activeNonPlayers.end()),
i_gridExpiry(expiry), m_parentMap(_parent ? _parent : this)
i_gridExpiry(expiry), m_parentMap(_parent ? _parent : this),
m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE)
{
for(unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
{
@ -209,6 +211,15 @@ Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _par
setNGrid(NULL, idx, j);
}
}
//lets initialize visibility distance for map
Map::InitVisibilityDistance();
}
void Map::InitVisibilityDistance()
{
//init visibility for continents
m_VisibleDistance = sWorld.GetMaxVisibleDistanceOnContinents();
}
// Template specialization of utility methods
@ -346,8 +357,8 @@ Map::EnsureGridCreated(const GridPair &p)
getNGrid(p.x_coord, p.y_coord)->SetGridState(GRID_STATE_IDLE);
//z coord
int gx=63-p.x_coord;
int gy=63-p.y_coord;
int gx = (MAX_NUMBER_OF_GRIDS - 1) - p.x_coord;
int gy = (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord;
if(!GridMaps[gx][gy])
LoadMapAndVMap(gx,gy);
@ -491,7 +502,7 @@ void Map::MessageBroadcast(Player *player, WorldPacket *msg, bool to_self)
MaNGOS::MessageDeliverer post_man(*player, msg, to_self);
TypeContainerVisitor<MaNGOS::MessageDeliverer, WorldTypeMapContainer > message(post_man);
CellLock<ReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *this);
cell_lock->Visit(cell_lock, message, *this, *player, GetVisibilityDistance());
}
void Map::MessageBroadcast(WorldObject *obj, WorldPacket *msg)
@ -511,10 +522,12 @@ void Map::MessageBroadcast(WorldObject *obj, WorldPacket *msg)
if( !loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y)) )
return;
//TODO: currently on continents when Visibility.Distance.InFlight > Visibility.Distance.Continents
//we have alot of blinking mobs because monster move packet send is broken...
MaNGOS::ObjectMessageDeliverer post_man(*obj,msg);
TypeContainerVisitor<MaNGOS::ObjectMessageDeliverer, WorldTypeMapContainer > message(post_man);
CellLock<ReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *this);
cell_lock->Visit(cell_lock, message, *this, *obj, GetVisibilityDistance());
}
void Map::MessageDistBroadcast(Player *player, WorldPacket *msg, float dist, bool to_self, bool own_team_only)
@ -537,7 +550,7 @@ void Map::MessageDistBroadcast(Player *player, WorldPacket *msg, float dist, boo
MaNGOS::MessageDistDeliverer post_man(*player, msg, dist, to_self, own_team_only);
TypeContainerVisitor<MaNGOS::MessageDistDeliverer , WorldTypeMapContainer > message(post_man);
CellLock<ReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *this);
cell_lock->Visit(cell_lock, message, *this, *player, dist);
}
void Map::MessageDistBroadcast(WorldObject *obj, WorldPacket *msg, float dist)
@ -560,7 +573,7 @@ void Map::MessageDistBroadcast(WorldObject *obj, WorldPacket *msg, float dist)
MaNGOS::ObjectMessageDistDeliverer post_man(*obj, msg, dist);
TypeContainerVisitor<MaNGOS::ObjectMessageDistDeliverer, WorldTypeMapContainer > message(post_man);
CellLock<ReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *this);
cell_lock->Visit(cell_lock, message, *this, *obj, dist);
}
bool Map::loaded(const GridPair &p) const
@ -605,8 +618,9 @@ void Map::Update(const uint32 &t_diff)
// the overloaded operators handle range checking
// so ther's no need for range checking inside the loop
CellPair begin_cell(standing_cell), end_cell(standing_cell);
begin_cell << 1; begin_cell -= 1; // upper left
end_cell >> 1; end_cell += 1; // lower right
//lets update mobs/objects in ALL visible cells around player!
CellArea area = Cell::CalculateCellArea(*plr, GetVisibilityDistance());
area.ResizeBorders(begin_cell, end_cell);
for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x)
{
@ -1044,8 +1058,9 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce)
delete getNGrid(x, y);
setNGrid(NULL, x, y);
}
int gx=63-x;
int gy=63-y;
int gx = (MAX_NUMBER_OF_GRIDS - 1) - x;
int gy = (MAX_NUMBER_OF_GRIDS - 1) - y;
// delete grid map, but don't delete if it is from parent map (and thus only reference)
//+++if (GridMaps[gx][gy]) don't check for GridMaps[gx][gy], we might have to unload vmaps
@ -1921,7 +1936,7 @@ void Map::UpdateObjectVisibility( WorldObject* obj, Cell cell, CellPair cellpair
MaNGOS::VisibleChangesNotifier notifier(*obj);
TypeContainerVisitor<MaNGOS::VisibleChangesNotifier, WorldTypeMapContainer > player_notifier(notifier);
CellLock<GridReadGuard> cell_lock(cell, cellpair);
cell_lock->Visit(cell_lock, player_notifier, *this);
cell_lock->Visit(cell_lock, player_notifier, *this, *obj, GetVisibilityDistance());
}
void Map::UpdatePlayerVisibility( Player* player, Cell cell, CellPair cellpair )
@ -1932,7 +1947,7 @@ void Map::UpdatePlayerVisibility( Player* player, Cell cell, CellPair cellpair )
TypeContainerVisitor<MaNGOS::PlayerNotifier, WorldTypeMapContainer > player_notifier(pl_notifier);
CellLock<ReadGuard> cell_lock(cell, cellpair);
cell_lock->Visit(cell_lock, player_notifier, *this);
cell_lock->Visit(cell_lock, player_notifier, *this, *player, GetVisibilityDistance());
}
void Map::UpdateObjectsVisibilityFor( Player* player, Cell cell, CellPair cellpair )
@ -1944,8 +1959,8 @@ void Map::UpdateObjectsVisibilityFor( Player* player, Cell cell, CellPair cellpa
TypeContainerVisitor<MaNGOS::VisibleNotifier, WorldTypeMapContainer > world_notifier(notifier);
TypeContainerVisitor<MaNGOS::VisibleNotifier, GridTypeMapContainer > grid_notifier(notifier);
CellLock<GridReadGuard> cell_lock(cell, cellpair);
cell_lock->Visit(cell_lock, world_notifier, *this);
cell_lock->Visit(cell_lock, grid_notifier, *this);
cell_lock->Visit(cell_lock, world_notifier, *this, *player, GetVisibilityDistance());
cell_lock->Visit(cell_lock, grid_notifier, *this, *player, GetVisibilityDistance());
// send data
notifier.Notify();
@ -1960,8 +1975,8 @@ void Map::PlayerRelocationNotify( Player* player, Cell cell, CellPair cellpair )
TypeContainerVisitor<MaNGOS::PlayerRelocationNotifier, GridTypeMapContainer > p2grid_relocation(relocationNotifier);
TypeContainerVisitor<MaNGOS::PlayerRelocationNotifier, WorldTypeMapContainer > p2world_relocation(relocationNotifier);
cell_lock->Visit(cell_lock, p2grid_relocation, *this);
cell_lock->Visit(cell_lock, p2world_relocation, *this);
cell_lock->Visit(cell_lock, p2grid_relocation, *this, *player, MAX_CREATURE_ATTACK_RADIUS);
cell_lock->Visit(cell_lock, p2world_relocation, *this, *player, MAX_CREATURE_ATTACK_RADIUS);
}
void Map::CreatureRelocationNotify(Creature *creature, Cell cell, CellPair cellpair)
@ -1974,8 +1989,8 @@ void Map::CreatureRelocationNotify(Creature *creature, Cell cell, CellPair cellp
TypeContainerVisitor<MaNGOS::CreatureRelocationNotifier, WorldTypeMapContainer > c2world_relocation(relocationNotifier);
TypeContainerVisitor<MaNGOS::CreatureRelocationNotifier, GridTypeMapContainer > c2grid_relocation(relocationNotifier);
cell_lock->Visit(cell_lock, c2world_relocation, *this);
cell_lock->Visit(cell_lock, c2grid_relocation, *this);
cell_lock->Visit(cell_lock, c2world_relocation, *this, *creature, MAX_CREATURE_ATTACK_RADIUS);
cell_lock->Visit(cell_lock, c2grid_relocation, *this, *creature, MAX_CREATURE_ATTACK_RADIUS);
}
void Map::SendInitSelf( Player * player )
@ -2145,12 +2160,20 @@ void Map::SendToPlayers(WorldPacket const* data) const
bool Map::ActiveObjectsNearGrid(uint32 x, uint32 y) const
{
ASSERT(x < MAX_NUMBER_OF_GRIDS);
ASSERT(y < MAX_NUMBER_OF_GRIDS);
CellPair cell_min(x*MAX_NUMBER_OF_CELLS, y*MAX_NUMBER_OF_CELLS);
CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS);
cell_min << 2;
cell_min -= 2;
cell_max >> 2;
cell_max += 2;
//we must find visible range in cells so we unload only non-visible cells...
float viewDist = GetVisibilityDistance();
int cell_range = (int)ceilf(viewDist / SIZE_OF_GRID_CELL) + 1;
cell_min << cell_range;
cell_min -= cell_range;
cell_max >> cell_range;
cell_max += cell_range;
for(MapRefManager::const_iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter)
{
@ -2234,6 +2257,9 @@ InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 Spaw
m_resetAfterUnload(false), m_unloadWhenEmpty(false),
i_data(NULL), i_script_id(0)
{
//lets initialize visibility distance for dungeons
InstanceMap::InitVisibilityDistance();
// the timer is started by default, and stopped when the first player joins
// this make sure it gets unloaded if for some reason no player joins
m_unloadTimer = std::max(sWorld.getConfig(CONFIG_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY);
@ -2248,6 +2274,12 @@ InstanceMap::~InstanceMap()
}
}
void InstanceMap::InitVisibilityDistance()
{
//init visibility distance for instances
m_VisibleDistance = sWorld.GetMaxVisibleDistanceInInstances();
}
/*
Do map specific checks to see if the player can enter
*/
@ -2570,12 +2602,20 @@ uint32 InstanceMap::GetMaxPlayers() const
BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId, Map* _parent)
: Map(id, expiry, InstanceId, DUNGEON_DIFFICULTY_NORMAL, _parent)
{
//lets initialize visibility distance for BG/Arenas
BattleGroundMap::InitVisibilityDistance();
}
BattleGroundMap::~BattleGroundMap()
{
}
void BattleGroundMap::InitVisibilityDistance()
{
//init visibility distance for BG/Arenas
m_VisibleDistance = sWorld.GetMaxVisibleDistanceInBGArenas();
}
bool BattleGroundMap::CanEnter(Player * player)
{
if(player->GetMapRef().getTarget() == this)

View file

@ -279,6 +279,10 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
void MessageDistBroadcast(Player *, WorldPacket *, float dist, bool to_self, bool own_team_only = false);
void MessageDistBroadcast(WorldObject *, WorldPacket *, float dist);
float GetVisibilityDistance() const { return m_VisibleDistance; }
//function for setting up visibility distance for maps on per-type/per-Id basis
virtual void InitVisibilityDistance();
void PlayerRelocation(Player *, float x, float y, float z, float angl);
void CreatureRelocation(Creature *creature, float x, float y, float, float);
@ -424,7 +428,6 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
GridMap *GetGrid(float x, float y);
void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; }
//uint64 CalculateGridMask(const uint32 &y) const;
void SendInitSelf( Player * player );
@ -451,6 +454,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
NGridType* getNGrid(uint32 x, uint32 y) const
{
ASSERT(x < MAX_NUMBER_OF_GRIDS);
ASSERT(y < MAX_NUMBER_OF_GRIDS);
return i_grids[x][y];
}
@ -470,6 +475,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
uint32 i_id;
uint32 i_InstanceId;
uint32 m_unloadTimer;
float m_VisibleDistance;
MapRefManager m_mapRefManager;
MapRefManager::iterator m_mapRefIter;
@ -557,6 +563,8 @@ class MANGOS_DLL_SPEC InstanceMap : public Map
void SendResetWarnings(uint32 timeLeft) const;
void SetResetSchedule(bool on);
uint32 GetMaxPlayers() const;
virtual void InitVisibilityDistance();
private:
bool m_resetAfterUnload;
bool m_unloadWhenEmpty;
@ -575,6 +583,8 @@ class MANGOS_DLL_SPEC BattleGroundMap : public Map
bool CanEnter(Player* player);
void SetUnload();
void UnloadAll(bool pForce);
virtual void InitVisibilityDistance();
};
/*inline

View file

@ -32,6 +32,17 @@ MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, 0)
memset(&GridMapReference, 0, MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_GRIDS*sizeof(uint16));
}
void MapInstanced::InitVisibilityDistance()
{
if(m_InstancedMaps.empty())
return;
//initialize visibility distances for all instance copies
for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
{
(*i).second->InitVisibilityDistance();
}
}
void MapInstanced::Update(const uint32& t)
{
// take care of loaded GridMaps (when unused, unload it!)

View file

@ -57,6 +57,7 @@ class MANGOS_DLL_DECL MapInstanced : public Map
}
InstancedMaps &GetInstancedMaps() { return m_InstancedMaps; }
virtual void InitVisibilityDistance();
private:

View file

@ -70,6 +70,12 @@ MapManager::Initialize()
InitMaxInstanceId();
}
void MapManager::InitializeVisibilityDistanceInfo()
{
for(MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter)
(*iter).second->InitVisibilityDistance();
}
// debugging code, should be deleted some day
void MapManager::checkAndCorrectGridStatesArray()
{

View file

@ -122,6 +122,7 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::
void RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y);
uint32 GenerateInstanceId() { return ++i_MaxInstanceId; }
void InitMaxInstanceId();
void InitializeVisibilityDistanceInfo();
/* statistics */
uint32 GetNumInstances();

View file

@ -1479,7 +1479,7 @@ void WorldObject::MonsterSay(int32 textId, uint32 language, uint64 TargetGuid)
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY),say_do);
TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> >, WorldTypeMapContainer > message(say_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetMap());
cell_lock->Visit(cell_lock, message, *GetMap(), *this, sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY));
}
void WorldObject::MonsterYell(int32 textId, uint32 language, uint64 TargetGuid)
@ -1495,7 +1495,7 @@ void WorldObject::MonsterYell(int32 textId, uint32 language, uint64 TargetGuid)
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL),say_do);
TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> >, WorldTypeMapContainer > message(say_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetMap());
cell_lock->Visit(cell_lock, message, *GetMap(), *this, sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL));
}
void WorldObject::MonsterYellToZone(int32 textId, uint32 language, uint64 TargetGuid)
@ -1524,7 +1524,7 @@ void WorldObject::MonsterTextEmote(int32 textId, uint64 TargetGuid, bool IsBossE
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),say_do);
TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> >, WorldTypeMapContainer > message(say_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetMap());
cell_lock->Visit(cell_lock, message, *GetMap(), *this, sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE));
}
void WorldObject::MonsterWhisper(int32 textId, uint64 receiver, bool IsBossWhisper)
@ -1755,8 +1755,8 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y,
TypeContainerVisitor<MaNGOS::WorldObjectWorker<MaNGOS::NearUsedPosDo>, WorldTypeMapContainer > world_obj_worker(worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_obj_worker, *GetMap());
cell_lock->Visit(cell_lock, world_obj_worker, *GetMap());
cell_lock->Visit(cell_lock, grid_obj_worker, *GetMap(), *this, distance2d);
cell_lock->Visit(cell_lock, world_obj_worker, *GetMap(), *this, distance2d);
}
// maybe can just place in primary position

View file

@ -32,10 +32,13 @@
#define CONTACT_DISTANCE 0.5f
#define INTERACTION_DISTANCE 5.0f
#define ATTACK_DISTANCE 5.0f
#define MAX_VISIBILITY_DISTANCE (5*SIZE_OF_GRID_CELL/2.0f) // max distance for visible object show, limited by active zone for player based at cell size (active zone = 5x5 cells)
#define DEFAULT_VISIBILITY_DISTANCE (SIZE_OF_GRID_CELL) // default visible distance
#define MAX_VISIBILITY_DISTANCE 333.0f // max distance for visible object show, limited in 333 yards
#define DEFAULT_VISIBILITY_DISTANCE 90.0f // default visible distance, 90 yards on continents
#define DEFAULT_VISIBILITY_INSTANCE 120.0f // default visible distance in instances, 120 yards
#define DEFAULT_VISIBILITY_BGARENAS 180.0f // default visible distance in BG/Arenas, 180 yards
#define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects
#define MAX_STEALTH_DETECT_RANGE 45.0f
enum TypeMask
{

View file

@ -254,7 +254,9 @@ ObjectAccessor::_buildChangeObjectForPlayer(WorldObject *obj, UpdateDataMapType
WorldObjectChangeAccumulator notifier(*obj, update_players);
TypeContainerVisitor<WorldObjectChangeAccumulator, WorldTypeMapContainer > player_notifier(notifier);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, player_notifier, *obj->GetMap());
Map& map = *obj->GetMap();
//we must build packets for all visible players
cell_lock->Visit(cell_lock, player_notifier, map, *obj, map.GetVisibilityDistance());
}
Pet*

View file

@ -12140,6 +12140,7 @@ void Player::PrepareQuestMenu( uint64 guid )
void Player::SendPreparedQuest(uint64 guid)
{
QuestMenu& questMenu = PlayerTalkClass->GetQuestMenu();
if (questMenu.Empty())
return;
@ -12160,8 +12161,9 @@ void Player::SendPreparedQuest( uint64 guid )
PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, CanRewardQuest(pQuest, false), true);
else if (status == DIALOG_STATUS_UNK2)
PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, CanRewardQuest(pQuest, false), true);
// Send completable on repeatable quest if player don't have quest
else if( pQuest->IsRepeatable() && !pQuest->IsDaily() )
// Send completable on repeatable and autoCompletable quest if player don't have quest
// TODO: verify if check for !pQuest->IsDaily() is really correct (possibly not)
else if (pQuest->IsAutoComplete() && pQuest->IsRepeatable() && !pQuest->IsDaily())
PlayerTalkClass->SendQuestGiverRequestItems(pQuest, guid, CanCompleteRepeatableQuest(pQuest), true);
else
PlayerTalkClass->SendQuestGiverQuestDetails(pQuest, guid, true);
@ -16819,8 +16821,8 @@ void Player::HandleStealthedUnitsDetection()
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyStealthedCheck >, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *GetMap());
cell_lock->Visit(cell_lock, world_unit_searcher, *GetMap(), *this, MAX_PLAYER_STEALTH_DETECT_RANGE);
cell_lock->Visit(cell_lock, grid_unit_searcher, *GetMap(), *this, MAX_PLAYER_STEALTH_DETECT_RANGE);
WorldObject const* viewPoint = GetViewPoint();
@ -19631,7 +19633,7 @@ void Player::SetTitle(CharTitlesEntry const* title, bool lost)
GetSession()->SendPacket(&data);
}
void Player::ConvertRune(uint8 index, uint8 newType)
void Player::ConvertRune(uint8 index, RuneType newType)
{
SetCurrentRune(index, newType);
@ -19659,6 +19661,15 @@ void Player::AddRunePower(uint8 index)
GetSession()->SendPacket(&data);
}
static RuneType runeSlotTypes[MAX_RUNES] = {
/*0*/ RUNE_BLOOD,
/*1*/ RUNE_BLOOD,
/*2*/ RUNE_UNHOLY,
/*3*/ RUNE_UNHOLY,
/*4*/ RUNE_FROST,
/*5*/ RUNE_FROST
};
void Player::InitRunes()
{
if(getClass() != CLASS_DEATH_KNIGHT)
@ -19670,8 +19681,8 @@ void Player::InitRunes()
for(uint32 i = 0; i < MAX_RUNES; ++i)
{
SetBaseRune(i, i / 2); // init base types
SetCurrentRune(i, i / 2); // init current types
SetBaseRune(i, runeSlotTypes[i]); // init base types
SetCurrentRune(i, runeSlotTypes[i]); // init current types
SetRuneCooldown(i, 0); // reset cooldowns
m_runes->SetRuneState(i);
}
@ -19680,6 +19691,16 @@ void Player::InitRunes()
SetFloatValue(PLAYER_RUNE_REGEN_1 + i, 0.1f);
}
bool Player::IsBaseRuneSlotsOnCooldown( RuneType runeType ) const
{
for(uint32 i = 0; i < MAX_RUNES; ++i)
if (GetBaseRune(i) == runeType && GetRuneCooldown(i) == 0)
return false;
return true;
}
void Player::AutoStoreLoot(uint8 bag, uint8 slot, uint32 loot_id, LootStore const& store, bool broadcast)
{
Loot loot;

View file

@ -2222,13 +2222,14 @@ class MANGOS_DLL_SPEC Player : public Unit
DeclinedName const* GetDeclinedNames() const { return m_declinedname; }
uint8 GetRunesState() const { return m_runes->runeState; }
uint8 GetBaseRune(uint8 index) const { return m_runes->runes[index].BaseRune; }
uint8 GetCurrentRune(uint8 index) const { return m_runes->runes[index].CurrentRune; }
RuneType GetBaseRune(uint8 index) const { return RuneType(m_runes->runes[index].BaseRune); }
RuneType GetCurrentRune(uint8 index) const { return RuneType(m_runes->runes[index].CurrentRune); }
uint16 GetRuneCooldown(uint8 index) const { return m_runes->runes[index].Cooldown; }
void SetBaseRune(uint8 index, uint8 baseRune) { m_runes->runes[index].BaseRune = baseRune; }
void SetCurrentRune(uint8 index, uint8 currentRune) { m_runes->runes[index].CurrentRune = currentRune; }
bool IsBaseRuneSlotsOnCooldown(RuneType runeType) const;
void SetBaseRune(uint8 index, RuneType baseRune) { m_runes->runes[index].BaseRune = baseRune; }
void SetCurrentRune(uint8 index, RuneType currentRune) { m_runes->runes[index].CurrentRune = currentRune; }
void SetRuneCooldown(uint8 index, uint16 cooldown) { m_runes->runes[index].Cooldown = cooldown; m_runes->SetRuneState(index, (cooldown == 0) ? true : false); }
void ConvertRune(uint8 index, uint8 newType);
void ConvertRune(uint8 index, RuneType newType);
void ResyncRunes(uint8 count);
void AddRunePower(uint8 index);
void InitRunes();

View file

@ -31,7 +31,8 @@ INSTANTIATE_SINGLETON_1(PoolHandler);
template <class T>
PoolGroup<T>::PoolGroup()
{
Spawned = 0;
m_SpawnedPoolAmount = 0;
m_LastDespawnedNode = 0;
}
// Method to add a gameobject/creature guid to the proper list depending on pool type and chance value
@ -107,12 +108,14 @@ void PoolGroup<T>::DespawnObject(uint32 guid)
if (!guid || EqualChanced[i].guid == guid)
{
if (guid)
CacheValue = EqualChanced[i].guid;
m_LastDespawnedNode = EqualChanced[i].guid;
else
Despawn1Object(EqualChanced[i].guid);
EqualChanced[i].spawned = false;
Spawned--;
if (m_SpawnedPoolAmount > 0)
--m_SpawnedPoolAmount;
}
}
}
@ -182,36 +185,40 @@ void PoolGroup<T>::SpawnObject(uint32 limit, bool cache)
if (limit == 1) // This is the only case where explicit chance is used
{
uint32 roll = RollOne();
if (cache && CacheValue != roll)
Despawn1Object(CacheValue);
CacheValue = Spawn1Object(roll);
if (cache && m_LastDespawnedNode != roll)
Despawn1Object(m_LastDespawnedNode);
m_LastDespawnedNode = 0;
Spawn1Object(roll);
}
else if (limit < EqualChanced.size() && Spawned < limit)
else if (limit < EqualChanced.size() && m_SpawnedPoolAmount < limit)
{
std::vector<uint32> IndexList;
for (size_t i = 0; i < EqualChanced.size(); ++i)
if (!EqualChanced[i].spawned)
IndexList.push_back(i);
while (Spawned < limit && IndexList.size() > 0)
while (m_SpawnedPoolAmount < limit && IndexList.size() > 0)
{
uint32 roll = urand(1, IndexList.size()) - 1;
uint32 index = IndexList[roll];
if (!cache || (cache && EqualChanced[index].guid != CacheValue))
if (!cache || (cache && EqualChanced[index].guid != m_LastDespawnedNode))
{
if (cache)
Despawn1Object(CacheValue);
Despawn1Object(m_LastDespawnedNode);
EqualChanced[index].spawned = Spawn1Object(EqualChanced[index].guid);
}
else
EqualChanced[index].spawned = ReSpawn1Object(EqualChanced[index].guid);
if (EqualChanced[index].spawned)
++Spawned; // limited group use the Spawned variable to store the number of actualy spawned creatures
++m_SpawnedPoolAmount; // limited group use the Spawned variable to store the number of actualy spawned creatures
std::vector<uint32>::iterator itr = IndexList.begin()+roll;
IndexList.erase(itr);
}
CacheValue = 0;
m_LastDespawnedNode = 0;
}
else // Not enough objects in pool, so spawn all
{
@ -330,7 +337,7 @@ bool PoolGroup<Pool>::ReSpawn1Object(uint32 /*guid*/)
PoolHandler::PoolHandler()
{
isSystemInit = false;
m_IsPoolSystemStarted = false;
}
void PoolHandler::LoadFromDB()
@ -624,7 +631,7 @@ void PoolHandler::Initialize()
}
sLog.outBasic("Pool handling system initialized, %u pools spawned.", count);
isSystemInit = true;
m_IsPoolSystemStarted = true;
}
// Call to spawn a pool, if cache if true the method will spawn only if cached entry is different

View file

@ -56,10 +56,10 @@ class PoolGroup
void RemoveOneRelation(uint16 child_pool_id);
private:
typedef std::vector<PoolObject> PoolObjectList;
uint32 CacheValue; // Store the guid of the removed creature/gameobject during a pool update
PoolObjectList ExplicitlyChanced;
PoolObjectList EqualChanced;
uint32 Spawned; // Used to know the number of spawned objects
uint32 m_LastDespawnedNode; // Store the guid of the removed creature/gameobject during a pool update
uint32 m_SpawnedPoolAmount; // Used to know the number of spawned objects
};
class Pool // for Pool of Pool case
@ -81,7 +81,7 @@ class PoolHandler
void Initialize();
protected:
bool isSystemInit;
bool m_IsPoolSystemStarted;
uint16 max_pool_id;
typedef std::vector<PoolTemplateData> PoolTemplateDataMap;
typedef std::vector<PoolGroup<Creature> > PoolGroupCreatureMap;

View file

@ -2433,9 +2433,12 @@ enum SummonType
SUMMON_TYPE_UNKNOWN5 = 409,
SUMMON_TYPE_UNKNOWN2 = 427,
SUMMON_TYPE_POSESSED2 = 428,
SUMMON_TYPE_QUEST_CRITTER = 487,
SUMMON_TYPE_QUEST_WILD = 587,
SUMMON_TYPE_INFERNO = 711,
SUMMON_TYPE_GUARDIAN2 = 713,
SUMMON_TYPE_GUARDIAN3 = 1161,
SUMMON_TYPE_CREATURE = 1302,
SUMMON_TYPE_ELEMENTAL = 1561,
SUMMON_TYPE_FORCE_OF_NATURE = 1562
};

View file

@ -476,12 +476,12 @@ WorldObject* Spell::FindCorpseUsing()
TypeContainerVisitor<MaNGOS::WorldObjectSearcher<T>, GridTypeMapContainer > grid_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, grid_searcher, *m_caster->GetMap(), *m_caster, max_range);
if (!result)
{
TypeContainerVisitor<MaNGOS::WorldObjectSearcher<T>, WorldTypeMapContainer > world_searcher(searcher);
cell_lock->Visit(cell_lock, world_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, world_searcher, *m_caster->GetMap(), *m_caster, max_range);
}
return result;
@ -970,7 +970,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
// Do healing and triggers
if (m_healing)
{
bool crit = caster->isSpellCrit(NULL, m_spellInfo, m_spellSchoolMask);
bool crit = caster->isSpellCrit(unitTarget, m_spellInfo, m_spellSchoolMask);
uint32 addhealth = m_healing;
if (crit)
{
@ -1356,8 +1356,8 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap)
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, world_unit_searcher, *m_caster->GetMap(), *m_caster, max_range);
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap(), *m_caster, max_range);
}
if(tempUnitMap.empty())
@ -1426,8 +1426,8 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap)
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, world_unit_searcher, *m_caster->GetMap(), *m_caster, max_range);
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap(), *m_caster, max_range);
}
if(tempUnitMap.empty())
@ -1522,8 +1522,8 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap)
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer> grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, world_unit_searcher, *m_caster->GetMap(), *pUnitTarget, max_range);
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap(), *pUnitTarget, max_range);
}
if (tempUnitMap.empty())
break;
@ -3556,7 +3556,7 @@ SpellCastResult Spell::CheckRuneCost(uint32 runeCostID)
for(uint32 i = 0; i < MAX_RUNES; ++i)
{
uint8 rune = plr->GetCurrentRune(i);
RuneType rune = plr->GetCurrentRune(i);
if((plr->GetRuneCooldown(i) == 0) && (runeCost[rune] > 0))
runeCost[rune]--;
}
@ -3599,7 +3599,7 @@ void Spell::TakeRunePower()
for(uint32 i = 0; i < MAX_RUNES; ++i)
{
uint8 rune = plr->GetCurrentRune(i);
RuneType rune = plr->GetCurrentRune(i);
if((plr->GetRuneCooldown(i) == 0) && (runeCost[rune] > 0))
{
plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec
@ -3613,7 +3613,7 @@ void Spell::TakeRunePower()
{
for(uint32 i = 0; i < MAX_RUNES; ++i)
{
uint8 rune = plr->GetCurrentRune(i);
RuneType rune = plr->GetCurrentRune(i);
if((plr->GetRuneCooldown(i) == 0) && (rune == RUNE_DEATH))
{
plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec
@ -4089,7 +4089,7 @@ SpellCastResult Spell::CheckCast(bool strict)
TypeContainerVisitor<MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck>, GridTypeMapContainer > object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, object_checker, *m_caster->GetMap());
cell_lock->Visit(cell_lock, object_checker, *m_caster->GetMap(), *m_caster, range);
if (p_GameObject)
{
@ -4128,7 +4128,7 @@ SpellCastResult Spell::CheckCast(bool strict)
TypeContainerVisitor<MaNGOS::CreatureLastSearcher<MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck>, GridTypeMapContainer > grid_creature_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_caster->GetMap());
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_caster->GetMap(), *m_caster, range);
if(p_Creature )
{
@ -5189,7 +5189,8 @@ SpellCastResult Spell::CheckItems()
TypeContainerVisitor<MaNGOS::GameObjectSearcher<MaNGOS::GameObjectFocusCheck>, GridTypeMapContainer > object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, object_checker, *m_caster->GetMap());
Map& map = *m_caster->GetMap();
cell_lock->Visit(cell_lock, object_checker, map, *m_caster, map.GetVisibilityDistance());
if(!ok)
return SPELL_FAILED_REQUIRES_SPELL_FOCUS;

View file

@ -460,6 +460,13 @@ m_isRemovedOnShapeLost(true), m_in_use(0), m_deleted(false)
m_spellProto->Stances &&
!(m_spellProto->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) &&
!(m_spellProto->Attributes & SPELL_ATTR_NOT_SHAPESHIFT));
if (caster && m_spellProto->Id == 22959) // Improved Scorch
{
// Glyph of Improved Scorch
if (Aura* glyph = caster->GetDummyAura(56371))
m_stackAmount = glyph->GetModifier()->m_amount;
}
}
Aura::~Aura()
@ -754,8 +761,8 @@ void AreaAura::Update(uint32 diff)
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap());
cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap(), *caster, m_radius);
cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap(), *caster, m_radius);
break;
}
case AREA_AURA_ENEMY:
@ -770,8 +777,8 @@ void AreaAura::Update(uint32 diff)
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap());
cell_lock->Visit(cell_lock, world_unit_searcher, *caster->GetMap(), *caster, m_radius);
cell_lock->Visit(cell_lock, grid_unit_searcher, *caster->GetMap(), *caster, m_radius);
break;
}
case AREA_AURA_OWNER:
@ -5001,7 +5008,8 @@ void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real)
case 12976: // Warrior Last Stand triggered spell
case 28726: // Nightmare Seed ( Nightmare Seed )
case 34511: // Valor (Bulwark of Kings, Bulwark of the Ancient Kings)
case 44055: // Tremendous Fortitude (Battlemaster's Alacrity)
// FIXME: add case 67596: in 3.2.x
case 44055: case 55915: case 55917: // Tremendous Fortitude (Battlemaster's Alacrity)
case 50322: // Survival Instincts
case 54443: // Demonic Empowerment (Voidwalker)
{
@ -6141,6 +6149,15 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real)
//+30% from +spell bonus
DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.30f;
break;
case SPELLFAMILY_PALADIN:
// Sacred Shield
// (check not strictly needed, only Sacred Shield has SPELL_AURA_SCHOOL_ABSORB in SPELLFAMILY_PALADIN at this time)
if (m_spellProto->SpellFamilyFlags & UI64LIT(0x0008000000000000))
{
// +75% from spell power
DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.75f;
}
break;
case SPELLFAMILY_DRUID:
// Savage Defense (amount store original percent of attack power applied)
if (m_spellProto->SpellIconID == 50) // only spell with this aura fit
@ -6153,6 +6170,26 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real)
DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
m_modifier.m_amount += (int32)DoneActualBenefit;
// now that the correct amount is computed, apply caster aura, if any
switch(m_spellProto->SpellFamilyName)
{
case SPELLFAMILY_PRIEST:
// Power Word: Shield
if (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000001))
{
// Glyph of Power Word: Shield
if(Aura* glyph = caster->GetAura(55672,0))
{
// instant heal glyph m_amount% of the absorbed amount
int32 heal = (glyph->GetModifier()->m_amount * m_modifier.m_amount)/100;
caster->CastCustomSpell(m_target, 56160, &heal, NULL, NULL, true, 0, this);
}
}
break;
default:
break;
}
}
}
else
@ -7025,8 +7062,8 @@ void Aura::PeriodicDummyTick()
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_object_checker, *caster->GetMap());
cell_lock->Visit(cell_lock, world_object_checker, *caster->GetMap());
cell_lock->Visit(cell_lock, grid_object_checker, *caster->GetMap(), *caster, radius);
cell_lock->Visit(cell_lock, world_object_checker, *caster->GetMap(), *caster, radius);
}
if(targets.empty())
@ -7175,7 +7212,7 @@ void Aura::HandleManaShield(bool apply, bool Real)
switch(m_spellProto->SpellFamilyName)
{
case SPELLFAMILY_MAGE:
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x8000))
if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000008000))
{
// Mana Shield
// +50% from +spd bonus
@ -7256,13 +7293,13 @@ void Aura::HandleAuraConvertRune(bool apply, bool Real)
{
if(!plr->GetRuneCooldown(i))
{
plr->ConvertRune(i, GetSpellProto()->EffectMiscValueB[m_effIndex]);
plr->ConvertRune(i, RuneType(GetSpellProto()->EffectMiscValueB[m_effIndex]));
break;
}
}
else
{
if(plr->GetCurrentRune(i) == GetSpellProto()->EffectMiscValueB[m_effIndex])
if(plr->GetCurrentRune(i) == RuneType(GetSpellProto()->EffectMiscValueB[m_effIndex]))
{
plr->ConvertRune(i, plr->GetBaseRune(i));
break;

View file

@ -669,6 +669,12 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
{
damage+=int32(m_caster->GetShieldBlockValue());
}
// Judgement
else if (m_spellInfo->Id == 54158)
{
// [1 + 0.25 * SPH + 0.16 * AP]
damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.16f);
}
break;
}
}
@ -1636,6 +1642,25 @@ void Spell::EffectDummy(uint32 i)
((Player*)m_caster)->SendAttackSwingCancelAttack();
return;
}
// Last Stand
case 53478:
{
if (!unitTarget)
return;
int32 healthModSpellBasePoints0 = int32(unitTarget->GetMaxHealth() * 0.3);
unitTarget->CastCustomSpell(unitTarget, 53479, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
return;
}
// Master's Call
case 53271:
{
Pet* pet = m_caster->GetPet();
if (!pet || !unitTarget)
return;
pet->CastSpell(unitTarget, m_spellInfo->CalculateSimpleValue(i), true);
return;
}
}
break;
case SPELLFAMILY_PALADIN:
@ -3297,6 +3322,8 @@ void Spell::EffectSummonType(uint32 i)
EffectSummonGuardian(i);
break;
case SUMMON_TYPE_WILD:
case SUMMON_TYPE_QUEST_WILD:
case SUMMON_TYPE_CREATURE:
EffectSummonWild(i);
break;
case SUMMON_TYPE_DEMON:
@ -3310,6 +3337,7 @@ void Spell::EffectSummonType(uint32 i)
case SUMMON_TYPE_CRITTER:
case SUMMON_TYPE_CRITTER2:
case SUMMON_TYPE_CRITTER3:
case SUMMON_TYPE_QUEST_CRITTER:
EffectSummonCritter(i);
break;
case SUMMON_TYPE_TOTEM_SLOT1:
@ -5374,6 +5402,16 @@ void Spell::EffectScriptEffect(uint32 effIndex)
}
return;
}
// Master's Call
case 53271:
{
if (!unitTarget)
return;
// script effect have in value, but this outdated removed part
unitTarget->CastSpell(unitTarget, 62305, true);
return;
}
default:
break;
}
@ -5400,13 +5438,12 @@ void Spell::EffectScriptEffect(uint32 effIndex)
sLog.outError("Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect",m_spellInfo->Id);
return;
}
// all seals have aura dummy in 2 effect
// offensive seals have aura dummy in 2 effect
Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
{
SpellEntry const *spellInfo = (*itr)->GetSpellProto();
// search seal (all seals have judgement's aura dummy spell id in 2 effect
if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo))
// search seal (offensive seals have judgement's aura dummy spell id in 2 effect
if ((*itr)->GetEffIndex() != 2 || !IsSealSpell((*itr)->GetSpellProto()))
continue;
spellId2 = (*itr)->GetModifier()->m_amount;
SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
@ -5414,6 +5451,18 @@ void Spell::EffectScriptEffect(uint32 effIndex)
continue;
break;
}
// if there were no offensive seals than there is seal with proc trigger aura
if (!spellId2)
{
Unit::AuraList const& procTriggerAuras = m_caster->GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
for(Unit::AuraList::const_iterator itr = procTriggerAuras.begin(); itr != procTriggerAuras.end(); ++itr)
{
if ((*itr)->GetEffIndex() != 0 || !IsSealSpell((*itr)->GetSpellProto()))
continue;
spellId2 = 54158;
break;
}
}
if (spellId1)
m_caster->CastSpell(unitTarget, spellId1, true);
if (spellId2)
@ -6830,7 +6879,7 @@ void Spell::EffectActivateRune(uint32 eff_idx)
for(uint32 j = 0; j < MAX_RUNES; ++j)
{
if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[eff_idx])
if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == RuneType(m_spellInfo->EffectMiscValue[eff_idx]))
{
plr->SetRuneCooldown(j, 0);
}

View file

@ -1501,6 +1501,10 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
// Savage Roar and Savage Roar (triggered)
if (spellInfo_1->SpellIconID == 2865 && spellInfo_2->SpellIconID == 2865)
return false;
// Frenzied Regeneration and Savage Defense
if( spellInfo_1->Id == 22842 && spellInfo_2->Id == 62606 || spellInfo_2->Id == 22842 && spellInfo_1->Id == 62606 )
return false;
}
// Leader of the Pack and Scroll of Stamina (multi-family check)

View file

@ -156,7 +156,9 @@ inline bool IsSealSpell(SpellEntry const *spellInfo)
{
//Collection of all the seal family flags. No other paladin spell has any of those.
return spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN &&
( spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_PALADIN_SEALS );
( spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_PALADIN_SEALS ) &&
// avoid counting target triggered effect as seal for avoid remove it or seal by it.
spellInfo->EffectImplicitTargetA[0] == TARGET_SELF;
}
inline bool IsElementalShield(SpellEntry const *spellInfo)

View file

@ -91,8 +91,8 @@ TotemAI::UpdateAI(const uint32 /*diff*/)
TypeContainerVisitor<MaNGOS::UnitLastSearcher<MaNGOS::NearestAttackableUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_object_checker, *m_creature->GetMap());
cell_lock->Visit(cell_lock, world_object_checker, *m_creature->GetMap());
cell_lock->Visit(cell_lock, grid_object_checker, *m_creature->GetMap(), *m_creature, max_range);
cell_lock->Visit(cell_lock, world_object_checker, *m_creature->GetMap(), *m_creature, max_range);
}
// If have target

View file

@ -1862,6 +1862,8 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe
// Reduce shield amount
mod->m_amount-=currentAbsorb;
if((*i)->DropAuraCharge())
mod->m_amount = 0;
// Need remove it later
if (mod->m_amount<=0)
existExpired = true;
@ -3436,7 +3438,8 @@ bool Unit::AddAura(Aura *Aur)
// Aura can stack on self -> Stack it;
if(aurSpellInfo->StackAmount)
{
i2->second->modStackAmount(1);
// can be created with >1 stack by some spell mods
i2->second->modStackAmount(Aur->GetStackAmount());
delete Aur;
return false;
}
@ -5134,6 +5137,16 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
CastSpell(this, 28682, true, castItem, triggeredByAura);
return (procEx & PROC_EX_CRITICAL_HIT); // charge update only at crit hits, no hidden cooldowns
}
// Glyph of Ice Block
case 56372:
{
if (GetTypeId() != TYPEID_PLAYER)
return false;
// not 100% safe with client version switches but for 3.1.3 no spells with cooldown that can have mage player except Frost Nova.
((Player*)this)->RemoveSpellCategoryCooldown(35, true);
return true;
}
}
break;
}
@ -6121,8 +6134,16 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
// Earth Shield
if (dummySpell->SpellFamilyFlags & UI64LIT(0x0000040000000000))
{
basepoints0 = triggerAmount;
target = this;
basepoints0 = triggerAmount;
// Glyph of Earth Shield
if (Aura* aur = GetDummyAura(63279))
{
int32 aur_mod = aur->GetModifier()->m_amount;
basepoints0 = int32(basepoints0 * (aur_mod + 100.0f) / 100.0f);
}
triggered_spell_id = 379;
break;
}
@ -6983,6 +7004,12 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
break;
}
}
// Blade Barrier
if (auraSpellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && auraSpellInfo->SpellIconID == 85)
{
if (this->GetTypeId() != TYPEID_PLAYER || !((Player*)this)->IsBaseRuneSlotsOnCooldown(RUNE_BLOOD))
return false;
}
// Custom basepoints/target for exist spell
// dummy basepoints or other customs
@ -8218,7 +8245,17 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
if (spellProto->SpellIconID == 186)
{
if (pVictim->isFrozen())
DoneTotalMod *= 3.0f;
{
float multiplier = 3.0f;
// if target have higher level
if (pVictim->getLevel() > getLevel())
// Glyph of Ice Lance
if (Aura* glyph = GetDummyAura(56377))
multiplier = glyph->GetModifier()->m_amount;
DoneTotalMod *= multiplier;
}
}
// Torment the weak affected (Arcane Barrage, Arcane Blast, Frostfire Bolt, Arcane Missiles, Fireball)
if ((spellProto->SpellFamilyFlags & UI64LIT(0x0000900020200021)) &&
@ -8475,7 +8512,8 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM
crit_chance -= ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL);
}
// scripted (increase crit chance ... against ... target by x%
// scripted (increase crit chance ... against ... target by x%)
// scripted (Increases the critical effect chance of your .... by x% on targets ...)
AuraList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
{
@ -8495,12 +8533,6 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM
if (pVictim->HasAura(6788))
crit_chance+=(*i)->GetModifier()->m_amount;
break;
case 21: // Test of Faith
case 6935:
case 6918:
if (pVictim->GetHealth() < pVictim->GetMaxHealth()/2)
crit_chance+=(*i)->GetModifier()->m_amount;
break;
default:
break;
}
@ -8508,6 +8540,25 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM
// Custom crit by class
switch(spellProto->SpellFamilyName)
{
case SPELLFAMILY_PRIEST:
// Flash Heal
if (spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000800))
{
if (pVictim->GetHealth() > pVictim->GetMaxHealth()/2)
break;
AuraList const& mDummyAuras = GetAurasByType(SPELL_AURA_DUMMY);
for(AuraList::const_iterator i = mDummyAuras.begin(); i!= mDummyAuras.end(); ++i)
{
// Improved Flash Heal
if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST &&
(*i)->GetSpellProto()->SpellIconID == 2542)
{
crit_chance+=(*i)->GetModifier()->m_amount;
break;
}
}
}
break;
case SPELLFAMILY_PALADIN:
// Sacred Shield
if (spellProto->SpellFamilyFlags & UI64LIT(0x0000000040000000))
@ -8515,14 +8566,12 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM
Aura *aura = pVictim->GetDummyAura(58597);
if (aura && aura->GetCasterGUID() == GetGUID())
crit_chance+=aura->GetModifier()->m_amount;
break;
}
// Exorcism
else if (spellProto->Category == 19)
{
if (pVictim->GetCreatureTypeMask() & CREATURE_TYPEMASK_DEMON_OR_UNDEAD)
return true;
break;
}
break;
case SPELLFAMILY_SHAMAN:
@ -8536,7 +8585,6 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM
pVictim->RemoveAurasByCasterSpell(flameShock->GetId(), GetGUID());
return true;
}
break;
}
break;
}
@ -9417,7 +9465,7 @@ int32 Unit::ModifyPower(Powers power, int32 dVal)
bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, bool detect, bool inVisibleList, bool is3dDistance) const
{
if(!u)
if(!u || !IsInMap(u))
return false;
// Always can see self
@ -9440,6 +9488,7 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo
if(m_Visibility==VISIBILITY_RESPAWN)
return false;
Map& _map = *u->GetMap();
// Grid dead/alive checks
if( u->GetTypeId()==TYPEID_PLAYER)
{
@ -9483,26 +9532,26 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo
if(u->GetTypeId()==TYPEID_PLAYER)
{
// Players far than max visible distance for player or not in our map are not visible too
if (!at_same_transport && !IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
if (!at_same_transport && !IsWithinDistInMap(viewPoint, _map.GetVisibilityDistance() + (inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
return false;
}
else
{
// Units far than max visible distance for creature or not in our map are not visible too
if (!IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
if (!IsWithinDistInMap(viewPoint, _map.GetVisibilityDistance() + (inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
return false;
}
}
else if(GetCharmerOrOwnerGUID()) // distance for show pet/charmed
{
// Pet/charmed far than max visible distance for player or not in our map are not visible too
if (!IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
if (!IsWithinDistInMap(viewPoint, _map.GetVisibilityDistance() + (inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
return false;
}
else // distance for show creature
{
// Units far than max visible distance for creature or not in our map are not visible too
if (!IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
if (!IsWithinDistInMap(viewPoint, _map.GetVisibilityDistance() + (inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
return false;
}
@ -11690,8 +11739,8 @@ Unit* Unit::SelectNearbyTarget(Unit* except /*= NULL*/) const
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *GetMap());
cell_lock->Visit(cell_lock, world_unit_searcher, *GetMap(), *this, ATTACK_DISTANCE);
cell_lock->Visit(cell_lock, grid_unit_searcher, *GetMap(), *this, ATTACK_DISTANCE);
}
// remove current target

View file

@ -69,9 +69,11 @@ volatile bool World::m_stopEvent = false;
uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE;
volatile uint32 World::m_worldLoopCounter = 0;
float World::m_MaxVisibleDistanceForCreature = DEFAULT_VISIBILITY_DISTANCE;
float World::m_MaxVisibleDistanceForPlayer = DEFAULT_VISIBILITY_DISTANCE;
float World::m_MaxVisibleDistanceOnContinents = DEFAULT_VISIBILITY_DISTANCE;
float World::m_MaxVisibleDistanceInInctances = DEFAULT_VISIBILITY_INSTANCE;
float World::m_MaxVisibleDistanceInBGArenas = DEFAULT_VISIBILITY_BGARENAS;
float World::m_MaxVisibleDistanceForObject = DEFAULT_VISIBILITY_DISTANCE;
float World::m_MaxVisibleDistanceInFlight = DEFAULT_VISIBILITY_DISTANCE;
float World::m_VisibleUnitGreyDistance = 0;
float World::m_VisibleObjectGreyDistance = 0;
@ -1007,28 +1009,45 @@ void World::LoadConfigSettings(bool reload)
m_VisibleObjectGreyDistance = MAX_VISIBILITY_DISTANCE;
}
m_MaxVisibleDistanceForCreature = sConfig.GetFloatDefault("Visibility.Distance.Creature", DEFAULT_VISIBILITY_DISTANCE);
if(m_MaxVisibleDistanceForCreature < 45*sWorld.getRate(RATE_CREATURE_AGGRO))
//visibility on continents
m_MaxVisibleDistanceOnContinents = sConfig.GetFloatDefault("Visibility.Distance.Continents", DEFAULT_VISIBILITY_DISTANCE);
if(m_MaxVisibleDistanceOnContinents < 45*sWorld.getRate(RATE_CREATURE_AGGRO))
{
sLog.outError("Visibility.Distance.Creature can't be less max aggro radius %f",45*sWorld.getRate(RATE_CREATURE_AGGRO));
m_MaxVisibleDistanceForCreature = 45*sWorld.getRate(RATE_CREATURE_AGGRO);
sLog.outError("Visibility.Distance.Continents can't be less max aggro radius %f", 45*sWorld.getRate(RATE_CREATURE_AGGRO));
m_MaxVisibleDistanceOnContinents = 45*sWorld.getRate(RATE_CREATURE_AGGRO);
}
else if(m_MaxVisibleDistanceForCreature + m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
else if(m_MaxVisibleDistanceOnContinents + m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
{
sLog.outError("Visibility. Distance .Creature can't be greater %f",MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance);
m_MaxVisibleDistanceForCreature = MAX_VISIBILITY_DISTANCE-m_VisibleUnitGreyDistance;
sLog.outError("Visibility.Distance.Continents can't be greater %f",MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance);
m_MaxVisibleDistanceOnContinents = MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance;
}
m_MaxVisibleDistanceForPlayer = sConfig.GetFloatDefault("Visibility.Distance.Player", DEFAULT_VISIBILITY_DISTANCE);
if(m_MaxVisibleDistanceForPlayer < 45*sWorld.getRate(RATE_CREATURE_AGGRO))
//visibility in instances
m_MaxVisibleDistanceInInctances = sConfig.GetFloatDefault("Visibility.Distance.Instances", DEFAULT_VISIBILITY_INSTANCE);
if(m_MaxVisibleDistanceInInctances < 45*sWorld.getRate(RATE_CREATURE_AGGRO))
{
sLog.outError("Visibility.Distance.Player can't be less max aggro radius %f",45*sWorld.getRate(RATE_CREATURE_AGGRO));
m_MaxVisibleDistanceForPlayer = 45*sWorld.getRate(RATE_CREATURE_AGGRO);
sLog.outError("Visibility.Distance.Instances can't be less max aggro radius %f",45*sWorld.getRate(RATE_CREATURE_AGGRO));
m_MaxVisibleDistanceInInctances = 45*sWorld.getRate(RATE_CREATURE_AGGRO);
}
else if(m_MaxVisibleDistanceForPlayer + m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
else if(m_MaxVisibleDistanceInInctances + m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
{
sLog.outError("Visibility.Distance.Player can't be greater %f",MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance);
m_MaxVisibleDistanceForPlayer = MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance;
sLog.outError("Visibility.Distance.Instances can't be greater %f",MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance);
m_MaxVisibleDistanceInInctances = MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance;
}
//visibility in BG/Arenas
m_MaxVisibleDistanceInBGArenas = sConfig.GetFloatDefault("Visibility.Distance.BGArenas", DEFAULT_VISIBILITY_BGARENAS);
if(m_MaxVisibleDistanceInBGArenas < 45*sWorld.getRate(RATE_CREATURE_AGGRO))
{
sLog.outError("Visibility.Distance.BGArenas can't be less max aggro radius %f",45*sWorld.getRate(RATE_CREATURE_AGGRO));
m_MaxVisibleDistanceInBGArenas = 45*sWorld.getRate(RATE_CREATURE_AGGRO);
}
else if(m_MaxVisibleDistanceInBGArenas + m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
{
sLog.outError("Visibility.Distance.BGArenas can't be greater %f",MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance);
m_MaxVisibleDistanceInBGArenas = MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance;
}
m_MaxVisibleDistanceForObject = sConfig.GetFloatDefault("Visibility.Distance.Object", DEFAULT_VISIBILITY_DISTANCE);
if(m_MaxVisibleDistanceForObject < INTERACTION_DISTANCE)
{

View file

@ -494,9 +494,11 @@ class World
bool IsScriptScheduled() const { return m_scheduledScripts > 0; }
// for max speed access
static float GetMaxVisibleDistanceForCreature() { return m_MaxVisibleDistanceForCreature; }
static float GetMaxVisibleDistanceForPlayer() { return m_MaxVisibleDistanceForPlayer; }
static float GetMaxVisibleDistanceOnContinents() { return m_MaxVisibleDistanceOnContinents; }
static float GetMaxVisibleDistanceInInstances() { return m_MaxVisibleDistanceInInctances; }
static float GetMaxVisibleDistanceInBGArenas() { return m_MaxVisibleDistanceInBGArenas; }
static float GetMaxVisibleDistanceForObject() { return m_MaxVisibleDistanceForObject; }
static float GetMaxVisibleDistanceInFlight() { return m_MaxVisibleDistanceInFlight; }
static float GetVisibleUnitGreyDistance() { return m_VisibleUnitGreyDistance; }
static float GetVisibleObjectGreyDistance() { return m_VisibleObjectGreyDistance; }
@ -560,9 +562,11 @@ class World
std::string m_dataPath;
// for max speed access
static float m_MaxVisibleDistanceForCreature;
static float m_MaxVisibleDistanceForPlayer;
static float m_MaxVisibleDistanceOnContinents;
static float m_MaxVisibleDistanceInInctances;
static float m_MaxVisibleDistanceInBGArenas;
static float m_MaxVisibleDistanceForObject;
static float m_MaxVisibleDistanceInFlight;
static float m_VisibleUnitGreyDistance;
static float m_VisibleObjectGreyDistance;

View file

@ -962,12 +962,12 @@ GM.AllowAchievementGain = 1
# 1 (raid members 100% auto detect invisible player from same raid)
# 2 (players from same team can 100% auto detect invisible player)
#
# Visibility.Distance.Creature
# Visibility.Distance.Player
# Visibility distance for different in game object
# Visibility.Distance.Continents
# Visibility.Distance.Instances
# Visibility.Distance.BGArenas
# Visibility distance for different ingame object in different maps.
# Visibility on continents on offy ~90 yards. In BG/Arenas ~180. For instances default ~120.
# Max limited by active player zone: ~ 333
# Min limit dependent from objects
# Default: 132 (cell size)
# Min limit is max aggro radius (45) * Rate.Creature.Aggro
#
# Visibility.Distance.Object
@ -993,8 +993,9 @@ GM.AllowAchievementGain = 1
###################################################################################################################
Visibility.GroupMode = 0
Visibility.Distance.Creature = 100
Visibility.Distance.Player = 100
Visibility.Distance.Continents = 90
Visibility.Distance.Instances = 120
Visibility.Distance.BGArenas = 180
Visibility.Distance.Object = 100
Visibility.Distance.InFlight = 100
Visibility.Distance.Grey.Unit = 1

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "8502"
#define REVISION_NR "8526"
#endif // __REVISION_NR_H__

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_8469_01_characters_character_spell"
#define REVISION_DB_MANGOS "required_8499_01_mangos_spell_elixir"
#define REVISION_DB_CHARACTERS "required_8505_01_characters_character_spell"
#define REVISION_DB_MANGOS "required_8521_01_mangos_spell_proc_event"
#define REVISION_DB_REALMD "required_8332_01_realmd_realmcharacters"
#endif // __REVISION_SQL_H__