Merge commit 'origin/master' into 320

Conflicts:
	src/game/Player.cpp
This commit is contained in:
tomrus88 2009-08-27 01:54:04 +04:00
commit 3882772658
42 changed files with 696 additions and 487 deletions

View file

@ -201,16 +201,34 @@ AC_TYPE_SIGNAL
AC_FUNC_VPRINTF
AC_CHECK_FUNCS([atexit ftime gethostbyaddr gethostbyname gethostname gettimeofday memmove memset pow realpath select socket sqrt strchr strdup strerror strstr])
PKG_CHECK_MODULES(ACE, [ACE >= 5.5.2], [need_to_build_ace=no], [need_to_build_ace=yes])
if test X$need_to_build_ace = Xyes ; then
# Check for use buildtin ACE sources
AC_ARG_ENABLE(builtin_ace, AC_HELP_STRING([--enable-builtin-ace], [turn on/off using builtin ACE sources]))
enable_builtin_ace_support=yes
if test "x$enable_builtin_ace" = "xno"; then
PKG_CHECK_MODULES(ACE, [ACE >= 5.5.2], [need_builtin_ace=no], [need_builtin_ace=yes])
if test X$need_builtin_ace = Xyes ; then
AC_MSG_ERROR([You need to install ACE package or use built-in ACE sources])
fi
enable_builtin_ace_support=no
fi
if test X$enable_builtin_ace_support = Xno; then
# old ace versions might not have ace/Stack_Trace.h...
AC_LANG_PUSH([C++])
AC_CHECK_HEADERS([ace/Stack_Trace.h])
AC_LANG_POP
else
# ...but we certainly have it in our included version
AC_DEFINE(HAVE_ACE_STACK_TRACE_H)
ACE_INCLUDES="-I\$(top_srcdir)/dep/ACE_wrappers -I\$(top_builddir)/dep/ACE_wrappers"
ACE_LIBS="\$(top_builddir)/dep/ACE_wrappers/ace/libACE.la"
fi
AM_CONDITIONAL([MANGOS_BUILD_ACE], [test X$need_to_build_ace = Xyes])
# old ace versions not have ace/Stack_Trace.h
AC_CHECK_HEADERS([ace/Stack_Trace.h])
AM_CONDITIONAL([MANGOS_BUILD_ACE], [test X$enable_builtin_ace_support = Xyes])
## Unify all additional includes/libs in one variable.
# TODO this looks kinda ugly, but when we add m4 folder I will make it look very pritey ( by Derex ).
@ -261,7 +279,7 @@ AC_CONFIG_FILES([
])
## Configure ACE, if needed
if test X$need_to_build_ace = Xyes; then
if test X$enable_builtin_ace_support = Xyes; then
AC_CONFIG_SUBDIRS([dep/ACE_wrappers])
fi

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_8399_01_mangos_spell_elixir` bit(1) default NULL
`required_8416_01_mangos_spell_learn_spell` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
--
@ -2831,8 +2831,8 @@ INSERT INTO `mangos_string` VALUES
(509,'%d - sender: %s (guid: %u account: %u ) receiver: %s (guid: %u account: %u ) %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(510,'%d - owner: %s (guid: %u account: %u ) %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(511,'Wrong link type!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(512,'%d - |cffffffff|Hitem:%d:0:0:0:0:0:0:0|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(513,'%d - |cffffffff|Hquest:%d|h[%s]|h|r %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(512,'%d - |cffffffff|Hitem:%d:0:0:0:0:0:0:0:0|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(513,'%d - |cffffffff|Hquest:%d:%d|h[%s]|h|r %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(514,'%d - |cffffffff|Hcreature_entry:%d|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(515,'%d - |cffffffff|Hcreature:%d|h[%s X:%f Y:%f Z:%f MapId:%d]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(516,'%d - |cffffffff|Hgameobject_entry:%d|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
@ -17045,39 +17045,20 @@ CREATE TABLE `spell_learn_spell` (
LOCK TABLES `spell_learn_spell` WRITE;
/*!40000 ALTER TABLE `spell_learn_spell` DISABLE KEYS */;
INSERT INTO `spell_learn_spell` VALUES
(71,7376,0),
(768,3025,0),
(783,5419,0),
(1066,5421,0),
(2457,21156,0),
(2458,7381,0),
(5487,1178,0),
(5487,21178,0),
(5784,33388,1),
(9634,9635,0),
(9634,21178,0),
(13819,33388,1),
(17002,24867,0),
(23161,33391,1),
(23214,33391,1),
(24858,24905,0),
(24866,24864,0),
(33872,47179,0),
(33873,47180,0),
(33891,5420,0),
(33891,34123,0),
(33943,33948,0),
(33943,34090,1),
(33943,34764,0),
(34767,33391,1),
(34769,33388,1),
(40123,40121,0),
(40123,40122,0),
(53428,53341,1),
(53428,53343,1),
(58984,21009,1);
/*!40000 ALTER TABLE `spell_learn_spell` ENABLE KEYS */;
UNLOCK TABLES;

View file

@ -16,7 +16,7 @@
/* re-adding before command use. So need just adding new line to file. */
/* Current table fill progress state: */
/* SpellEffect.cpp from start until end of Spell::EffectPowerBurn */
/* SpellEffect.cpp from start until end of Spell::EffectEnchantItemPrismatic */
DROP TABLE IF EXISTS spell_check;
CREATE TABLE `spell_check` (
@ -41,6 +41,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
(1454, 5,0x0000000000040000,0x00000000, -1, -1, -1, 3, -1,-1,'Life Tap', 'Spell::EffectDummy'),
(1455, 5,0x0000000000040000,0x00000000, -1, -1, -1, 3, -1,-1,'Life Tap', 'Spell::EffectDummy'),
(1456, 5,0x0000000000040000,0x00000000, -1, -1, -1, 3, -1,-1,'Life Tap', 'Spell::EffectDummy'),
(9512, -1, -1, -1, -1, -1, -1, 30, -1,-1,'Restore Energy', 'Spell::EffectEnergize'),
(4073, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Mechanical Dragonling', 'Spell::EffectDummy'),
(5938, 8, -1, -1, -1, -1, -1, 3, -1,-1,'Shiv', 'Spell::EffectDummy'),
(5940, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Shiv', 'Spell::EffectDummy'),
@ -58,7 +59,6 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
(8220, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Flip Out', 'Spell::EffectDummy'),
(8221, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Yaaarrrr', 'Spell::EffectDummy'),
(8222, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Yaaarrrr', 'Spell::EffectDummy'),
(8326, -1, -1, -1, -1, -1, -1, 6, -1,-1,'Ghost', 'Spell::EffectApplyAura'),
(8593, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Symbol of life', 'Spell::EffectDummy'),
(10399,11,0x0000000000400000,0x00000000, -1, -1, -1, 3, -1,-1,'Rockbiter Weapon', 'Spell::EffectDummy'),
(11687, 5,0x0000000000040000,0x00000000, -1, -1, -1, 3, -1,-1,'Life Tap', 'Spell::EffectDummy'),
@ -93,13 +93,13 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
(18790,-1, -1, -1, -1, -1, -1, -1, -1,-1,'', 'Spell::EffectInstaKill'),
(18791,-1, -1, -1, -1, -1, -1, -1, -1,-1,'', 'Spell::EffectInstaKill'),
(18792,-1, -1, -1, -1, -1, -1, -1, -1,-1,'', 'Spell::EffectInstaKill'),
(19658,-1, -1, -1, -1, -1, -1, 10, -1,-1,'Devour Magic Effect', 'Spell::EffectDispel'),
(19804,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Arcanite Dragonling', 'Spell::EffectDummy'),
(20187,10, -1, -1, -1, -1, -1, 3, -1,-1,'Judgement of Righteousness', 'Spell::EffectDummy'),
(20253, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Intercept', 'Spell::EffectSchoolDMG'),
(20473,10, -1, -1, 156, -1, -1, 3, -1,-1,'Holy Shock', 'Spell::EffectDummy'),
(20577, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Cannibalize', 'Spell::EffectDummy'),
(20578,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Cannibalize', 'Spell::EffectDummy'),
(20584,-1, -1, -1, -1, -1, -1, 6, -1,-1,'Ghost', 'Spell::EffectApplyAura'),
(20647,-1, -1, -1, -1, -1, -1, 2, -1, 0,'Execute', 'Spell::EffectDummy'),
(20929,10, -1, -1, 156, -1, -1, 3, -1,-1,'Holy Shock', 'Spell::EffectDummy'),
(20930,10, -1, -1, 156, -1, -1, 3, -1,-1,'Holy Shock', 'Spell::EffectDummy'),
@ -128,7 +128,15 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
(23885,-1, -1, -1, -1, -1, -1, 6, 42, 0,'Bloodthirst', 'Spell::EffectDummy'),
(23989, 9, -1, -1, -1, -1, -1, 3, -1,-1,'Readiness', 'Spell::EffectDummy'),
(24340, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor', 'Spell::EffectSchoolDMG'),
(24532,-1, -1, -1, -1, -1, -1, 30, -1,-1,'Burst of Energy', 'Spell::EffectEnergize'),
(24571,-1, -1, -1, -1, -1, -1, 30, -1,-1,'Blood Fury', 'Spell::EffectEnergize'),
(24575,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Brittle Armor', 'Spell::EffectTriggerSpell'),
(24950,-1, -1, -1, -1, -1, -1, 24, -1,-1,'Create Warsong Mark of Honor (Loser)','Spell::DoCreateItem'),
(24951,-1, -1, -1, -1, -1, -1, 24, -1,-1,'Create Warsong Mark of Honor (WInner)','Spell::DoCreateItem'),
(24952,-1, -1, -1, -1, -1, -1, 24, -1,-1,'Arathi Basin Mark of Honor (Loser)', 'Spell::DoCreateItem'),
(24953,-1, -1, -1, -1, -1, -1, 24, -1,-1,'Arathi Basin Mark of Honor (Winner)','Spell::DoCreateItem'),
(24954,-1, -1, -1, -1, -1, -1, 24, -1,-1,'Alterac Valley Mark of Honor (Loser)','Spell::DoCreateItem'),
(24955,-1, -1, -1, -1, -1, -1, 24, -1,-1,'Alterac Valley Mark of Honor (Winner)','Spell::DoCreateItem'),
(25599, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Thundercrash', 'Spell::EffectSchoolDMG'),
(25858,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Reindeer', 'Spell::EffectDummy'),
(25859,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Reindeer', 'Spell::EffectDummy'),
@ -174,6 +182,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
(31790,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Righteous Defense', 'Spell::EffectTriggerSpell'),
(31803,-1, -1, -1, -1, -1, -1, 6, 3,-1,'Holy Vengeance', 'Spell::EffectSchoolDMG'),
(31818,-1, -1, -1, -1, -1, -1, 30, -1, 0,'Life Tap', 'Spell::EffectDummy'),
(31930,-1, -1, -1, -1, -1, -1, 30, -1,-1,'Judgements of the Wise', 'Spell::EffectEnergize'),
(32409,-1, -1, -1, -1, -1, -1, 6, 3,-1,'Shadow Word: Death', 'Spell::EffectSchoolDMG'),
(32553,-1, -1, -1, -1, -1, -1, 30, -1, 0,'Life Tap', 'Spell::EffectDummy'),
(32813,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Squirrel Form', 'Spell::EffectDummy'),
@ -231,7 +240,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
(39610,11, -1, -1, -1, -1, -1, 3, -1,-1,'Mana Tide Totem effect', 'Spell::EffectDummy'),
(40810, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Saber Lash', 'Spell::EffectSchoolDMG'),
(41276, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor', 'Spell::EffectSchoolDMG'),
(41637,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Prayer of Mending', 'Spell::EffectApplyAura'),
(41637,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Prayer of Mending', 'Spell::cast'),
(42384, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Brutal Swipe', 'Spell::EffectSchoolDMG'),
(43267, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Saber Lash', 'Spell::EffectSchoolDMG'),
(43268, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Saber Lash', 'Spell::EffectSchoolDMG'),
@ -246,8 +255,11 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
(44997, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Converting Sentry', 'Spell::EffectDummy'),
(45009,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Converted Sentry Credit', 'Spell::EffectDummy'),
(45030, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Impale Emissary', 'Spell::EffectDummy'),
(45062,-1, -1, -1, -1, -1, -1, -1, 4,-1,'Holy Energy', 'Spell::EffectHeal'),
(45064,-1, -1, -1, -1, -1, -1, 10, -1,-1,'Vessel of the Naaru', 'Spell::EffectHeal'),
(45088,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Emissary of Hate Credit', 'Spell::EffectDummy'),
(45150, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor Slash', 'Spell::EffectSchoolDMG'),
(45470,-1, -1, -1, -1, -1, -1, 10, -1, 0,'Intercept', 'Spell::EffectDummy'),
(64422, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor Slash', 'Spell::EffectSchoolDMG'),
(64688, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor Slash', 'Spell::EffectSchoolDMG'),
(45182,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Cheat Death', 'Spell::EffectDummy'),
@ -298,6 +310,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
(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'),
(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'),
(55004, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Nitro Boosts', 'Spell::EffectDummy'),
(55441,11, -1, -1, -1, -1, -1, -1, 4,-1,'Glyph of Mana Tide', 'Spell::EffectDummy'),
@ -314,6 +327,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
(61290, 5,0x0001000000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Shadowflame', 'Spell::EffectSchoolDMG'),
(61291,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Shadowflame', 'Spell::EffectSchoolDMG'),
(61491, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Intercept', 'Spell::EffectSchoolDMG'),
(63375,-1, -1, -1, -1, -1, -1, 30, -1,-1,'Improved Stormstrike', 'Spell::EffectEnergize'),
/* sorted by spell names */
/*id fm familyMaskA fmMaskB icon vis cat eff aur ef name code */
@ -328,6 +342,8 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
( 0, 9,0x0008000000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Counterattack', 'Spell::EffectSchoolDMG'),
( 0, 8,0x0000000000010000,0x00000000, -1, -1, -1, -1, 3,-1,'Deadly poison', 'Spell::EffectSchoolDMG'),
( 0,15,0x0000000000002000,0x00000000, -1, -1, -1, 3, -1,-1,'Death Coil', 'Spell::EffectDummy'),
( 0,15,0x0000000000000010,0x00000000, -1, -1, -1, 3, -1,-1,'Death Strike', 'Spell::EffectDummy'),
( 0, 5, -1, -1, -1, -1, 12, 38, -1,-1,'Devour Magic', 'Spell::EffectDispel'),
( 0, 8,0x0000000800000000,0x00000000, -1, -1, -1, 2, -1,-1,'Envenom', 'Spell::EffectSchoolDMG'),
( 0, 8,0x0000000000020000,0x00000000, -1, -1, -1, 2, -1,-1,'Eviscerate', 'Spell::EffectSchoolDMG'),
(0, 4,0x0000000020000000,0x00000000, -1, -1, -1, 3, -1,-1,'Execute', 'Spell::EffectDummy'),
@ -356,8 +372,10 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas
( 0, 7,0x0000044000000000,0x00000000, -1, -1, -1, -1, -1,-1,'Mangle (Cat) and Mangle (Bear)', 'Unit::HandleDummyAuraProc'),
( 0, 9,0x0000000000000002,0x00000000, -1, 342, -1, 2, -1,-1,'Mongoose Bite', 'Spell::EffectSchoolDMG'),
(0, 6,0x0080000000000000,0x00000000, -1, -1, -1, 3, -1,-1,'Penance', 'Spell::EffectDummy'),
( 0, 6,0x0000002000000000,0x00000000, -1, -1, -1, 6, -1,-1,'Prayer of Mending', 'Spell::EffectApplyAura'),
( 0, 6,0x0000002000000000,0x00000000, -1, -1, -1, 6, -1,-1,'Prayer of Mending', 'Spell::cast'),
( 0, 8,0x0000024000000860,0x00000000, -1, -1, -1, -1, -1,-1,'Preparation (affected spells)', 'Spell::EffectDummy'),
( 0, 7,0x0000000000000040,0x00000000, -1, -1, -1, -1, 8,-1,'Regrowth', 'Spell::EffectHeal'),
( 0, 7,0x0000000000000010,0x00000000, -1, -1, -1, -1, 8,-1,'Rejuvenation', 'Spell::EffectHeal'),
( 0, 7,0x0000000000001000,0x00000000, -1, -1, -1, 2, -1,-1,'Rake', 'Spell::EffectSchoolDMG'), /* used in */
( 0, 7,0x0000000000001000,0x00000000, -1, -1, -1, 80, -1, 2,'Rake', 'Spell::EffectSchoolDMG'), /* exactly selected */
( 0, 7,0x0000000000001000,0x00000000, -1, -1, -1, -1, 3,-1,'Rake', 'Aura::HandlePeriodicDamage'), /* used in */

View file

@ -0,0 +1,6 @@
ALTER TABLE db_version CHANGE COLUMN required_8399_01_mangos_spell_elixir required_8412_01_mangos_mangos_string bit;
DELETE FROM mangos_string WHERE entry IN(512,513);
INSERT INTO mangos_string VALUES
(512,'%d - |cffffffff|Hitem:%d:0:0:0:0:0:0:0:0|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(513,'%d - |cffffffff|Hquest:%d:%d|h[%s]|h|r %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

View file

@ -0,0 +1,21 @@
ALTER TABLE db_version CHANGE COLUMN required_8412_01_mangos_mangos_string required_8416_01_mangos_spell_learn_spell bit;
/* All form passives */
DELETE FROM spell_learn_spell WHERE SpellID in (
1178, /* Bear Form (Passive) */
3025, /* Cat Form (Passive) */
5419, /* Travel Form (Passive) */
5420, /* Tree of Life _passive_ */
5421, /* Aquatic Form (Passive) */
7376, /* Defensive Stance Passive */
7381, /* Berserker Stance Passive */
9635, /* Dire Bear Form (Passive) */
21156, /* Battle Stance Passive */
21178, /* Bear Form (Passive2) */
24905, /* Moonkin Form (Passive) */
34123, /* Tree of Life _pasive_ */
33948, /* Flight Form (Passive) */
34764, /* Flight Form (Passive) */
40121, /* Swift Flight Form (Passive) */
40122 /* Swift Flight Form (Passive) */
);

View file

@ -93,6 +93,8 @@ pkgdata_DATA = \
8402_01_characters_guild_eventlog.sql \
8402_02_characters_guild_bank_eventlog.sql \
8409_01_characters_guild.sql \
8412_01_mangos_mangos_string.sql \
8416_01_mangos_spell_learn_spell.sql \
README
## Additional files to include when running 'make dist'
@ -166,4 +168,6 @@ EXTRA_DIST = \
8402_01_characters_guild_eventlog.sql \
8402_02_characters_guild_bank_eventlog.sql \
8409_01_characters_guild.sql \
8412_01_mangos_mangos_string.sql \
8416_01_mangos_spell_learn_spell.sql \
README

View file

@ -141,7 +141,7 @@ bool
AggressorAI::IsVisible(Unit *pl) const
{
return m_creature->IsWithinDist(pl,sWorld.getConfig(CONFIG_SIGHT_MONSTER))
&& pl->isVisibleForOrDetect(m_creature,true);
&& pl->isVisibleForOrDetect(m_creature,m_creature,true);
}
void

View file

@ -33,16 +33,21 @@
#include "AccountMgr.h"
// Supported shift-links (client generated and server side)
// |color|Hachievement:achievement_id:player_guid:0:0:0:0:0:0:0:0|h[name]|h|r
// - client, item icon shift click, not used in server currently
// |color|Harea:area_id|h[name]|h|r
// |color|Hcreature:creature_guid|h[name]|h|r
// |color|Hcreature_entry:creature_id|h[name]|h|r
// |color|Henchant:recipe_spell_id|h[prof_name: recipe_name]|h|r - client, at shift click in recipes list dialog
// |color|Hgameevent:id|h[name]|h|r
// |color|Hgameobject:go_guid|h[name]|h|r
// |color|Hgameobject_entry:go_id|h[name]|h|r
// |color|Hitem:item_id:perm_ench_id:0:0|h[name]|h|r
// |color|Hglyph:glyph_slot_id:glyph_prop_id|h[%s]|h|r - client, at shift click in glyphs dialog, GlyphSlot.dbc, GlyphProperties.dbc
// |color|Hitem:item_id:perm_ench_id:gem1:gem2:gem3:0:0:0:0:reporter_level|h[name]|h|r
// - client, item icon shift click
// |color|Hitemset:itemset_id|h[name]|h|r
// |color|Hplayer:name|h[name]|h|r - client, in some messages, at click copy only name instead link
// |color|Hquest:quest_id|h[name]|h|r
// |color|Hquest:quest_id:quest_level|h[name]|h|r - client, quest list name shift-click
// |color|Hskill:skill_id|h[name]|h|r
// |color|Hspell:spell_id|h[name]|h|r - client, spellbook spell icon shift-click
// |color|Htalent:talent_id,rank|h[name]|h|r - client, talent icon shift-click
@ -1357,21 +1362,27 @@ GameObject* ChatHandler::GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid
enum SpellLinkType
{
SPELL_LINK_SPELL = 0,
SPELL_LINK_TALENT = 1,
SPELL_LINK_TRADE = 2
SPELL_LINK_SPELL = 0,
SPELL_LINK_TALENT = 1,
SPELL_LINK_ENCHANT = 2,
SPELL_LINK_TRADE = 3,
SPELL_LINK_GLYPH = 4
};
static char const* const spellKeys[] =
{
"Hspell", // normal spell
"Htalent", // talent spell
"Henchant", // enchanting recipe spell
"Htrade", // profession/skill spell
"Hglyph", // glyph
0
};
uint32 ChatHandler::extractSpellIdFromLink(char* text)
{
// number or [name] Shift-click form |color|Henchant:recipe_spell_id|h[prof_name: recipe_name]|h|r
// number or [name] Shift-click form |color|Hglyph:glyph_slot_id:glyph_prop_id|h[%s]|h|r
// number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r
// number or [name] Shift-click form |color|Htalent:talent_id,rank|h[name]|h|r
// number or [name] Shift-click form |color|Htrade:spell_id,skill_id,max_value,cur_value|h[name]|h|r
@ -1403,8 +1414,19 @@ uint32 ChatHandler::extractSpellIdFromLink(char* text)
return talentEntry->RankID[rank];
}
case SPELL_LINK_ENCHANT:
case SPELL_LINK_TRADE:
return id;
case SPELL_LINK_GLYPH:
{
uint32 glyph_prop_id = param1_str ? (uint32)atol(param1_str) : 0;
GlyphPropertiesEntry const* glyphPropEntry = sGlyphPropertiesStore.LookupEntry(glyph_prop_id);
if(!glyphPropEntry)
return 0;
return glyphPropEntry->SpellId;
}
}
// unknown type?

View file

@ -227,7 +227,7 @@ bool Corpse::LoadFromDB(uint32 guid, Field *fields)
return true;
}
bool Corpse::isVisibleForInState(Player const* u, bool inVisibleList) const
bool Corpse::isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const
{
return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(u, World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false);
return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(viewPoint, World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false);
}

View file

@ -74,7 +74,7 @@ class Corpse : public WorldObject
GridPair const& GetGrid() const { return m_grid; }
void SetGrid(GridPair const& grid) { m_grid = grid; }
bool isVisibleForInState(Player const* u, bool inVisibleList) const;
bool isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const;
Loot loot; // remove insignia ONLY at BG
Player* lootRecipient;

View file

@ -681,7 +681,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
void SetDeadByDefault (bool death_state) { m_isDeadByDefault = death_state; }
bool isActiveObject() const { return m_isActiveObject; }
bool isActiveObject() const { return m_isActiveObject || HasAuraType(SPELL_AURA_BIND_SIGHT) || HasAuraType(SPELL_AURA_FAR_SIGHT); }
void SetActiveObjectState(bool on);
protected:

View file

@ -1116,7 +1116,7 @@ void CreatureEventAI::UpdateAI(const uint32 diff)
bool CreatureEventAI::IsVisible(Unit *pl) const
{
return m_creature->IsWithinDist(pl,sWorld.getConfig(CONFIG_SIGHT_MONSTER))
&& pl->isVisibleForOrDetect(m_creature,true);
&& pl->isVisibleForOrDetect(m_creature,m_creature,true);
}
inline Unit* CreatureEventAI::SelectUnit(AttackingTarget target, uint32 position)

View file

@ -25,8 +25,9 @@
#include "GridNotifiers.h"
#include "CellImpl.h"
#include "GridNotifiersImpl.h"
#include "SpellMgr.h"
DynamicObject::DynamicObject() : WorldObject()
DynamicObject::DynamicObject() : WorldObject(), m_isActiveObject(false)
{
m_objectType |= TYPEMASK_DYNAMICOBJECT;
m_objectTypeId = TYPEID_DYNAMICOBJECT;
@ -78,6 +79,11 @@ bool DynamicObject::Create( uint32 guidlow, Unit *caster, uint32 spellId, uint32
m_radius = radius;
m_effIndex = effIndex;
m_spellId = spellId;
// set to active for far sight case
if(SpellEntry const* spellEntry = sSpellStore.LookupEntry(spellId))
m_isActiveObject = IsSpellHaveEffect(spellEntry,SPELL_EFFECT_ADD_FARSIGHT);
return true;
}
@ -104,20 +110,24 @@ void DynamicObject::Update(uint32 p_time)
else
deleteThis = true;
// TODO: make a timer and update this in larger intervals
CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
// have radius and work as persistent effect
if(m_radius)
{
// TODO: make a timer and update this in larger intervals
CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
MaNGOS::DynamicObjectUpdater notifier(*this, caster);
MaNGOS::DynamicObjectUpdater notifier(*this, caster);
TypeContainerVisitor<MaNGOS::DynamicObjectUpdater, WorldTypeMapContainer > world_object_notifier(notifier);
TypeContainerVisitor<MaNGOS::DynamicObjectUpdater, GridTypeMapContainer > grid_object_notifier(notifier);
TypeContainerVisitor<MaNGOS::DynamicObjectUpdater, WorldTypeMapContainer > world_object_notifier(notifier);
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());
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_object_notifier, *GetMap());
cell_lock->Visit(cell_lock, grid_object_notifier, *GetMap());
}
if(deleteThis)
{
@ -140,7 +150,15 @@ void DynamicObject::Delay(int32 delaytime)
(*iunit)->DelayAura(m_spellId, m_effIndex, delaytime);
}
bool DynamicObject::isVisibleForInState(Player const* u, bool inVisibleList) const
bool DynamicObject::isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const
{
return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(u, World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false);
if(!IsInWorld() || !u->IsInWorld())
return false;
// always seen by owner
if(GetCasterGUID()==u->GetGUID())
return true;
// normal case
return IsWithinDistInMap(viewPoint, World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false);
}

View file

@ -46,7 +46,7 @@ class DynamicObject : public WorldObject
void AddAffected(Unit *unit) { m_affected.insert(unit); }
void RemoveAffected(Unit *unit) { m_affected.erase(unit); }
void Delay(int32 delaytime);
bool isVisibleForInState(Player const* u, bool inVisibleList) const;
bool isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const;
void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); }
void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); }
@ -56,15 +56,16 @@ class DynamicObject : public WorldObject
GridReference<DynamicObject> &GetGridRef() { return m_gridRef; }
bool isActiveObject() const { return false; }
bool isActiveObject() const { return m_isActiveObject; }
protected:
uint32 m_spellId;
uint32 m_effIndex;
int32 m_aliveDuration;
time_t m_nextThinkTime;
float m_radius;
float m_radius; // radius apply persistent effect, 0 = no persistent effect
AffectedSet m_affected;
private:
GridReference<DynamicObject> m_gridRef;
bool m_isActiveObject;
};
#endif

View file

@ -690,7 +690,7 @@ void GameObject::SaveRespawnTime()
objmgr.SaveGORespawnTime(m_DBTableGuid,GetInstanceId(),m_respawnTime);
}
bool GameObject::isVisibleForInState(Player const* u, bool inVisibleList) const
bool GameObject::isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const
{
// Not in world
if(!IsInWorld() || !u->IsInWorld())
@ -717,7 +717,7 @@ bool GameObject::isVisibleForInState(Player const* u, bool inVisibleList) const
}
// check distance
return IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject() +
return IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceForObject() +
(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false);
}

View file

@ -670,7 +670,7 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
void TriggeringLinkedGameObject( uint32 trapEntry, Unit* target);
bool isVisibleForInState(Player const* u, bool inVisibleList) const;
bool isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const;
GameObject* LookupFishingHoleAround(float range);

View file

@ -30,13 +30,16 @@ using namespace MaNGOS;
void
MaNGOS::PlayerNotifier::Visit(PlayerMapType &m)
{
WorldObject const* viewPoint = i_player.GetViewPoint();
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{
if( iter->getSource() == &i_player )
Player* player = iter->getSource();
if( player == &i_player )
continue;
iter->getSource()->UpdateVisibilityOf(&i_player);
i_player.UpdateVisibilityOf(iter->getSource());
player->UpdateVisibilityOf(player->GetViewPoint(),&i_player);
i_player.UpdateVisibilityOf(viewPoint,player);
}
}
@ -45,24 +48,28 @@ VisibleChangesNotifier::Visit(PlayerMapType &m)
{
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{
if(iter->getSource() == &i_object)
Player* player = iter->getSource();
if(player == &i_object)
continue;
iter->getSource()->UpdateVisibilityOf(&i_object);
player->UpdateVisibilityOf(player->GetViewPoint(),&i_object);
}
}
void
VisibleNotifier::Visit(PlayerMapType &m)
{
WorldObject const* viewPoint = i_player.GetViewPoint();
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{
if( iter->getSource() == &i_player )
Player* player = iter->getSource();
if( player == &i_player )
continue;
iter->getSource()->UpdateVisibilityOf(&i_player);
i_player.UpdateVisibilityOf(iter->getSource(),i_data,i_data_updates,i_visibleNow);
i_clientGUIDs.erase(iter->getSource()->GetGUID());
player->UpdateVisibilityOf(player->GetViewPoint(),&i_player);
i_player.UpdateVisibilityOf(viewPoint,player,i_data,i_data_updates,i_visibleNow);
i_clientGUIDs.erase(player->GetGUID());
}
}
@ -77,8 +84,9 @@ VisibleNotifier::Notify()
{
if(i_clientGUIDs.find((*itr)->GetGUID())!=i_clientGUIDs.end())
{
(*itr)->UpdateVisibilityOf(&i_player);
i_player.UpdateVisibilityOf((*itr),i_data,i_data_updates,i_visibleNow);
// ignore far sight case
(*itr)->UpdateVisibilityOf((*itr),&i_player);
i_player.UpdateVisibilityOf(&i_player,(*itr),i_data,i_data_updates,i_visibleNow);
i_clientGUIDs.erase((*itr)->GetGUID());
}
}
@ -121,9 +129,8 @@ VisibleNotifier::Notify()
if(!IS_PLAYER_GUID(*iter))
continue;
Player* plr = ObjectAccessor::GetPlayer(i_player,*iter);
if(plr)
plr->UpdateVisibilityOf(&i_player);
if (Player* plr = ObjectAccessor::GetPlayer(i_player,*iter))
plr->UpdateVisibilityOf(plr->GetViewPoint(),&i_player);
}
}

View file

@ -778,7 +778,7 @@ namespace MaNGOS
return u->isAlive()
&& i_obj->IsWithinDistInMap(u, i_range)
&& !i_funit->IsFriendlyTo(u)
&& u->isVisibleForOrDetect(i_funit, false);
&& u->isVisibleForOrDetect(i_funit,i_funit,false);
}
private:
WorldObject const* i_obj;
@ -827,7 +827,7 @@ namespace MaNGOS
bool operator()(Unit* u)
{
if( u->isTargetableForAttack() && i_obj->IsWithinDistInMap(u, i_range) &&
!i_funit->IsFriendlyTo(u) && u->isVisibleForOrDetect(i_funit,false) )
!i_funit->IsFriendlyTo(u) && u->isVisibleForOrDetect(i_funit,i_funit,false) )
{
i_range = i_obj->GetDistance(u); // use found unit range as new range limit for next check
return true;
@ -863,7 +863,7 @@ namespace MaNGOS
return false;
if(u->GetTypeId()==TYPEID_UNIT && ((Creature*)u)->isTotem())
return false;
if (!i_hitHidden && !u->isVisibleForOrDetect(i_funit, false))
if (!i_hitHidden && !u->isVisibleForOrDetect(i_funit, i_funit, false))
return false;
if(( i_targetForPlayer ? !i_funit->IsFriendlyTo(u) : i_funit->IsHostileTo(u) )&& i_obj->IsWithinDistInMap(u, i_range))

View file

@ -31,9 +31,11 @@ template<class T>
inline void
MaNGOS::VisibleNotifier::Visit(GridRefManager<T> &m)
{
WorldObject const* viewPoint = i_player.GetViewPoint();
for(typename GridRefManager<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
{
i_player.UpdateVisibilityOf(iter->getSource(),i_data,i_data_updates,i_visibleNow);
i_player.UpdateVisibilityOf(viewPoint,iter->getSource(),i_data,i_data_updates,i_visibleNow);
i_clientGUIDs.erase(iter->getSource()->GetGUID());
}
}
@ -64,10 +66,10 @@ MaNGOS::PlayerRelocationNotifier::Visit(PlayerMapType &m)
}
}
inline void PlayerCreatureRelocationWorker(Player* pl, Creature* c)
inline void PlayerCreatureRelocationWorker(Player* pl, WorldObject const* viewPoint, Creature* c)
{
// update creature visibility at player/creature move
pl->UpdateVisibilityOf(c);
pl->UpdateVisibilityOf(viewPoint,c);
// Creature AI reaction
if(!c->hasUnitState(UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))
@ -98,9 +100,11 @@ MaNGOS::PlayerRelocationNotifier::Visit(CreatureMapType &m)
if(!i_player.isAlive() || i_player.isInFlight())
return;
WorldObject const* viewPoint = i_player.GetViewPoint();
for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
if( iter->getSource()->isAlive())
PlayerCreatureRelocationWorker(&i_player,iter->getSource());
if (iter->getSource()->isAlive())
PlayerCreatureRelocationWorker(&i_player,viewPoint,iter->getSource());
}
template<>
@ -111,8 +115,9 @@ MaNGOS::CreatureRelocationNotifier::Visit(PlayerMapType &m)
return;
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
if( iter->getSource()->isAlive() && !iter->getSource()->isInFlight())
PlayerCreatureRelocationWorker(iter->getSource(), &i_creature);
if (Player* player = iter->getSource())
if (player->isAlive() && !player->isInFlight())
PlayerCreatureRelocationWorker(player, player->GetViewPoint(), &i_creature);
}
template<>

View file

@ -980,7 +980,7 @@ void Group::UpdatePlayerOutOfRange(Player* pPlayer)
for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
{
player = itr->getSource();
if (player && player != pPlayer && !pPlayer->isVisibleFor(player))
if (player && player != pPlayer && !pPlayer->isVisibleFor(player,player->GetViewPoint()))
player->GetSession()->SendPacket(&data);
}
}

View file

@ -126,7 +126,7 @@ void GuardAI::UpdateAI(const uint32 /*diff*/)
bool GuardAI::IsVisible(Unit *pl) const
{
return m_creature->IsWithinDist(pl,sWorld.getConfig(CONFIG_SIGHT_GUARDER))
&& pl->isVisibleForOrDetect(m_creature,true);
&& pl->isVisibleForOrDetect(m_creature,m_creature,true);
}
void GuardAI::AttackStart(Unit *u)

View file

@ -2935,7 +2935,7 @@ bool ChatHandler::HandleLookupQuestCommand(const char* args)
}
if (m_session)
PSendSysMessage(LANG_QUEST_LIST_CHAT,qinfo->GetQuestId(),qinfo->GetQuestId(),title.c_str(),statusStr);
PSendSysMessage(LANG_QUEST_LIST_CHAT,qinfo->GetQuestId(),qinfo->GetQuestId(),qinfo->GetQuestLevel(),title.c_str(),statusStr);
else
PSendSysMessage(LANG_QUEST_LIST_CONSOLE,qinfo->GetQuestId(),title.c_str(),statusStr);
++counter;
@ -2969,7 +2969,7 @@ bool ChatHandler::HandleLookupQuestCommand(const char* args)
}
if (m_session)
PSendSysMessage(LANG_QUEST_LIST_CHAT,qinfo->GetQuestId(),qinfo->GetQuestId(),title.c_str(),statusStr);
PSendSysMessage(LANG_QUEST_LIST_CHAT,qinfo->GetQuestId(),qinfo->GetQuestId(),qinfo->GetQuestLevel(),title.c_str(),statusStr);
else
PSendSysMessage(LANG_QUEST_LIST_CONSOLE,qinfo->GetQuestId(),title.c_str(),statusStr);
@ -4686,7 +4686,7 @@ bool ChatHandler::HandleQuestAdd(const char* args)
}
// .addquest #entry'
// number or [name] Shift-click form |color|Hquest:quest_id|h[name]|h|r
// number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r
char* cId = extractKeyFromLink((char*)args,"Hquest");
if(!cId)
return false;
@ -4740,7 +4740,7 @@ bool ChatHandler::HandleQuestRemove(const char* args)
}
// .removequest #entry'
// number or [name] Shift-click form |color|Hquest:quest_id|h[name]|h|r
// number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r
char* cId = extractKeyFromLink((char*)args,"Hquest");
if(!cId)
return false;
@ -4790,7 +4790,7 @@ bool ChatHandler::HandleQuestComplete(const char* args)
}
// .quest complete #entry
// number or [name] Shift-click form |color|Hquest:quest_id|h[name]|h|r
// number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r
char* cId = extractKeyFromLink((char*)args,"Hquest");
if(!cId)
return false;

View file

@ -256,8 +256,7 @@ void WorldSession::HandleLootReleaseOpcode( WorldPacket & recv_data )
// cheaters can modify lguid to prevent correct apply loot release code and re-loot
// use internal stored guid
//uint64 lguid;
//recv_data >> lguid;
recv_data.read_skip<uint64>(); // guid;
if(uint64 lguid = GetPlayer()->GetLootGUID())
DoLootRelease(lguid);

View file

@ -1502,13 +1502,15 @@ void WorldSession::HandleMoveSetCanFlyAckOpcode( WorldPacket & recv_data )
sLog.outDebug("WORLD: CMSG_MOVE_SET_CAN_FLY_ACK");
//recv_data.hexlike();
uint64 guid;
uint32 unk;
uint32 flags;
recv_data.read_skip<uint64>(); // guid
recv_data.read_skip<uint32>(); // unk
recv_data >> guid >> unk >> flags;
MovementInfo movementInfo;
ReadMovementInfo(recv_data, &movementInfo);
_player->m_movementInfo.SetMovementFlags(MovementFlags(flags));
recv_data.read_skip<uint32>(); // unk2
_player->m_movementInfo.SetMovementFlags(movementInfo.GetMovementFlags());
}
void WorldSession::HandleRequestPetInfoOpcode( WorldPacket & /*recv_data */)

View file

@ -1359,6 +1359,16 @@ bool WorldObject::HasInArc(const float arcangle, const WorldObject* obj) const
return (( angle >= lborder ) && ( angle <= rborder ));
}
bool WorldObject::isInFrontInMap(WorldObject const* target, float distance, float arc) const
{
return IsWithinDistInMap(target, distance) && HasInArc( arc, target );
}
bool WorldObject::isInBackInMap(WorldObject const* target, float distance, float arc) const
{
return IsWithinDistInMap(target, distance) && !HasInArc( 2 * M_PI - arc, target );
}
void WorldObject::GetRandomPoint( float x, float y, float z, float distance, float &rand_x, float &rand_y, float &rand_z) const
{
if(distance == 0)

View file

@ -445,6 +445,8 @@ class MANGOS_DLL_SPEC WorldObject : public Object
float GetAngle( const WorldObject* obj ) const;
float GetAngle( const float x, const float y ) const;
bool HasInArc( const float arcangle, const WorldObject* obj ) const;
bool isInFrontInMap(WorldObject const* target,float distance, float arc = M_PI) const;
bool isInBackInMap(WorldObject const* target, float distance, float arc = M_PI) const;
virtual void CleanupsBeforeDelete(); // used in destructor or explicitly before mass creature delete to remove cross-references to already deleted units
@ -471,10 +473,10 @@ class MANGOS_DLL_SPEC WorldObject : public Object
void AddObjectToRemoveList();
// main visibility check function in normal case (ignore grey zone distance check)
bool isVisibleFor(Player const* u) const { return isVisibleForInState(u,false); }
bool isVisibleFor(Player const* u, WorldObject const* viewPoint) const { return isVisibleForInState(u,viewPoint,false); }
// low level function for visibility change code, must be define in all main world object subclasses
virtual bool isVisibleForInState(Player const* u, bool inVisibleList) const = 0;
virtual bool isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const = 0;
void SetMap(Map * map);
Map * GetMap() const { ASSERT(m_currMap); return m_currMap; }

View file

@ -90,43 +90,61 @@ ObjectAccessor::GetCorpse(WorldObject const &u, uint64 guid)
return ret;
}
WorldObject* ObjectAccessor::GetWorldObject(WorldObject const &p, uint64 guid)
{
switch(GUID_HIPART(guid))
{
case HIGHGUID_PLAYER: return FindPlayer(guid);
case HIGHGUID_GAMEOBJECT: return p.GetMap()->GetGameObject(guid);
case HIGHGUID_UNIT: return p.GetMap()->GetCreature(guid);
case HIGHGUID_PET: return GetPet(guid);
case HIGHGUID_VEHICLE: return GetVehicle(guid);
case HIGHGUID_DYNAMICOBJECT:return p.GetMap()->GetDynamicObject(guid);
case HIGHGUID_TRANSPORT: return NULL;
case HIGHGUID_CORPSE: return GetCorpse(p,guid);
case HIGHGUID_MO_TRANSPORT: return NULL;
default: break;
}
return NULL;
}
Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const &p, uint64 guid, uint32 typemask)
{
Object *obj = NULL;
if(typemask & TYPEMASK_PLAYER)
switch(GUID_HIPART(guid))
{
obj = FindPlayer(guid);
if(obj)
return obj;
}
if(typemask & TYPEMASK_UNIT)
{
obj = GetCreatureOrPetOrVehicle(p,guid);
if(obj)
return obj;
}
if(typemask & TYPEMASK_GAMEOBJECT)
{
obj = p.GetMap()->GetGameObject(guid);
if(obj)
return obj;
}
if(typemask & TYPEMASK_DYNAMICOBJECT)
{
obj = p.GetMap()->GetDynamicObject(guid);
if(obj)
return obj;
}
if(typemask & TYPEMASK_ITEM && p.GetTypeId() == TYPEID_PLAYER)
{
obj = ((Player const &)p).GetItemByGuid( guid );
if(obj)
return obj;
case HIGHGUID_ITEM:
if(typemask & TYPEMASK_ITEM && p.GetTypeId() == TYPEID_PLAYER)
return ((Player const &)p).GetItemByGuid( guid );
break;
case HIGHGUID_PLAYER:
if(typemask & TYPEMASK_PLAYER)
return FindPlayer(guid);
break;
case HIGHGUID_GAMEOBJECT:
if(typemask & TYPEMASK_GAMEOBJECT)
return p.GetMap()->GetGameObject(guid);
break;
case HIGHGUID_UNIT:
if(typemask & TYPEMASK_UNIT)
return p.GetMap()->GetCreature(guid);
break;
case HIGHGUID_PET:
if(typemask & TYPEMASK_UNIT)
return GetPet(guid);
break;
case HIGHGUID_VEHICLE:
if(typemask & TYPEMASK_UNIT)
return GetVehicle(guid);
break;
case HIGHGUID_DYNAMICOBJECT:
if(typemask & TYPEMASK_DYNAMICOBJECT)
return p.GetMap()->GetDynamicObject(guid);
break;
case HIGHGUID_TRANSPORT:
case HIGHGUID_CORPSE:
case HIGHGUID_MO_TRANSPORT:
break;
}
return NULL;

View file

@ -142,6 +142,7 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor,
else return NULL;
}
static WorldObject* GetWorldObject(WorldObject const &, uint64);
static Object* GetObjectByTypeMask(WorldObject const &, uint64, uint32 typemask);
static Creature* GetCreatureOrPetOrVehicle(WorldObject const &, uint64);
static Unit* GetUnit(WorldObject const &, uint64);

View file

@ -224,6 +224,7 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
if(owner->IsPvP())
SetPvP(true);
SetCanModifyStats(true);
InitStatsForLevel(petlevel);
InitTalentForLevel(); // set original talents points before spell loading
@ -263,7 +264,6 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
delete result;
//load spells/cooldowns/auras
SetCanModifyStats(true);
_LoadAuras(timediff);
//init AB

View file

@ -307,7 +307,7 @@ void PetAI::UpdateAI(const uint32 diff)
bool PetAI::_isVisible(Unit *u) const
{
return m_creature->IsWithinDist(u,sWorld.getConfig(CONFIG_SIGHT_GUARDER))
&& u->isVisibleForOrDetect(m_creature,true);
&& u->isVisibleForOrDetect(m_creature,m_creature,true);
}
void PetAI::UpdateAllies()

View file

@ -3118,24 +3118,9 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
bool Player::IsNeedCastPassiveSpellAtLearn(SpellEntry const* spellInfo) const
{
bool need_cast = false;
switch(spellInfo->Id)
{
// some spells not have stance data expected cast at form change or present
case 5420: need_cast = (m_form == FORM_TREE); break;
case 5419: need_cast = (m_form == FORM_TRAVEL); break;
case 7376: need_cast = (m_form == FORM_DEFENSIVESTANCE); break;
case 7381: need_cast = (m_form == FORM_BERSERKERSTANCE); break;
case 21156: need_cast = (m_form == FORM_BATTLESTANCE); break;
case 21178: need_cast = (m_form == FORM_BEAR || m_form == FORM_DIREBEAR); break;
case 33948: need_cast = (m_form == FORM_FLIGHT); break;
case 34764: need_cast = (m_form == FORM_FLIGHT); break;
case 40121: need_cast = (m_form == FORM_FLIGHT_EPIC); break;
case 40122: need_cast = (m_form == FORM_FLIGHT_EPIC); break;
// another spells have proper stance data
default: need_cast = !spellInfo->Stances || m_form != 0 && (spellInfo->Stances & (1<<(m_form-1))); break;
}
// note: form passives activated with shapeshift spells be implemented by HandleShapeshiftBoosts instead of spell_learn_spell
// talent dependent passives activated at form apply have proper stance data
bool need_cast = !spellInfo->Stances || m_form != 0 && (spellInfo->Stances & (1<<(m_form-1)));
//Check CasterAuraStates
return need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraState(spellInfo->CasterAuraState)));
@ -16825,13 +16810,15 @@ void Player::HandleStealthedUnitsDetection()
cell_lock->Visit(cell_lock, world_unit_searcher, *GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *GetMap());
WorldObject const* viewPoint = GetViewPoint();
for (std::list<Unit*>::const_iterator i = stealthedUnits.begin(); i != stealthedUnits.end(); ++i)
{
if((*i)==this)
continue;
bool hasAtClient = HaveAtClient((*i));
bool hasDetected = (*i)->isVisibleForOrDetect(this, true);
bool hasDetected = (*i)->isVisibleForOrDetect(this, viewPoint, true);
if (hasDetected)
{
@ -17915,6 +17902,17 @@ void Player::ReportedAfkBy(Player* reporter)
}
}
WorldObject const* Player::GetViewPoint() const
{
if(uint64 far_sight = GetFarSight())
{
WorldObject const* viewPoint = ObjectAccessor::GetWorldObject(*this,far_sight);
return viewPoint ? viewPoint : this; // always expected not NULL
}
else
return this;
}
bool Player::IsVisibleInGridForPlayer( Player* pl ) const
{
// gamemaster in GM mode see all, including ghosts
@ -17980,11 +17978,11 @@ bool Player::IsVisibleGloballyFor( Player* u ) const
return true;
}
void Player::UpdateVisibilityOf(WorldObject* target)
void Player::UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* target)
{
if(HaveAtClient(target))
{
if(!target->isVisibleForInState(this, true))
if(!target->isVisibleForInState(this, viewPoint, true))
{
target->DestroyForPlayer(this);
m_clientGUIDs.erase(target->GetGUID());
@ -17997,7 +17995,7 @@ void Player::UpdateVisibilityOf(WorldObject* target)
}
else
{
if(target->isVisibleForInState(this,false))
if(target->isVisibleForInState(this, viewPoint, false))
{
target->SendUpdateToPlayer(this);
if(target->GetTypeId()!=TYPEID_GAMEOBJECT||!((GameObject*)target)->IsTransport())
@ -18033,11 +18031,11 @@ inline void UpdateVisibilityOf_helper(std::set<uint64>& s64, GameObject* target)
}
template<class T>
void Player::UpdateVisibilityOf(T* target, UpdateData& data, UpdateDataMapType& data_updates, std::set<WorldObject*>& visibleNow)
void Player::UpdateVisibilityOf(WorldObject const* viewPoint, T* target, UpdateData& data, UpdateDataMapType& data_updates, std::set<WorldObject*>& visibleNow)
{
if(HaveAtClient(target))
{
if(!target->isVisibleForInState(this,true))
if(!target->isVisibleForInState(this,viewPoint,true))
{
target->BuildOutOfRangeUpdateBlock(&data);
m_clientGUIDs.erase(target->GetGUID());
@ -18050,7 +18048,7 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, UpdateDataMapType&
}
else
{
if(target->isVisibleForInState(this,false))
if(target->isVisibleForInState(this,viewPoint,false))
{
visibleNow.insert(target);
target->BuildUpdate(data_updates);
@ -18065,11 +18063,11 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, UpdateDataMapType&
}
}
template void Player::UpdateVisibilityOf(Player* target, UpdateData& data, UpdateDataMapType& data_updates, std::set<WorldObject*>& visibleNow);
template void Player::UpdateVisibilityOf(Creature* target, UpdateData& data, UpdateDataMapType& data_updates, std::set<WorldObject*>& visibleNow);
template void Player::UpdateVisibilityOf(Corpse* target, UpdateData& data, UpdateDataMapType& data_updates, std::set<WorldObject*>& visibleNow);
template void Player::UpdateVisibilityOf(GameObject* target, UpdateData& data, UpdateDataMapType& data_updates, std::set<WorldObject*>& visibleNow);
template void Player::UpdateVisibilityOf(DynamicObject* target, UpdateData& data, UpdateDataMapType& data_updates, std::set<WorldObject*>& visibleNow);
template void Player::UpdateVisibilityOf(WorldObject const* viewPoint, Player* target, UpdateData& data, UpdateDataMapType& data_updates, std::set<WorldObject*>& visibleNow);
template void Player::UpdateVisibilityOf(WorldObject const* viewPoint, Creature* target, UpdateData& data, UpdateDataMapType& data_updates, std::set<WorldObject*>& visibleNow);
template void Player::UpdateVisibilityOf(WorldObject const* viewPoint, Corpse* target, UpdateData& data, UpdateDataMapType& data_updates, std::set<WorldObject*>& visibleNow);
template void Player::UpdateVisibilityOf(WorldObject const* viewPoint, GameObject* target, UpdateData& data, UpdateDataMapType& data_updates, std::set<WorldObject*>& visibleNow);
template void Player::UpdateVisibilityOf(WorldObject const* viewPoint, DynamicObject* target, UpdateData& data, UpdateDataMapType& data_updates, std::set<WorldObject*>& visibleNow);
void Player::InitPrimaryProfessions()
{
@ -20594,6 +20592,17 @@ bool Player::HasMovementFlag( MovementFlags f ) const
return m_movementInfo.HasMovementFlag(f);
}
void Player::SetFarSightGUID( uint64 guid )
{
if(GetFarSight() == guid)
return;
SetUInt64Value(PLAYER_FARSIGHT, guid);
// need triggering load grids around new view point
ObjectAccessor::UpdateVisibilityForPlayer(this);
}
void Player::SendDuelCountdown(uint32 counter)
{
WorldPacket data(SMSG_DUEL_COUNTDOWN, 4);

View file

@ -2099,7 +2099,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void ExitVehicle(Vehicle *vehicle);
uint64 GetFarSight() const { return GetUInt64Value(PLAYER_FARSIGHT); }
void SetFarSightGUID(uint64 guid) { SetUInt64Value(PLAYER_FARSIGHT, guid); }
void SetFarSightGUID(uint64 guid);
// Transports
Transport * GetTransport() const { return m_transport; }
@ -2137,13 +2137,14 @@ class MANGOS_DLL_SPEC Player : public Unit
bool HaveAtClient(WorldObject const* u) { return u==this || m_clientGUIDs.find(u->GetGUID())!=m_clientGUIDs.end(); }
WorldObject const* GetViewPoint() const;
bool IsVisibleInGridForPlayer(Player* pl) const;
bool IsVisibleGloballyFor(Player* pl) const;
void UpdateVisibilityOf(WorldObject* target);
void UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* target);
template<class T>
void UpdateVisibilityOf(T* target, UpdateData& data, UpdateDataMapType& data_updates, std::set<WorldObject*>& visibleNow);
void UpdateVisibilityOf(WorldObject const* viewPoint,T* target, UpdateData& data, UpdateDataMapType& data_updates, std::set<WorldObject*>& visibleNow);
// Stealth detection system
void HandleStealthedUnitsDetection();

View file

@ -2416,7 +2416,8 @@ enum SummonType
SUMMON_TYPE_UNKNOWN2 = 427,
SUMMON_TYPE_POSESSED2 = 428,
SUMMON_TYPE_INFERNO = 711,
SUMMON_TYPE_GUARDIAN2 = 1161,
SUMMON_TYPE_GUARDIAN2 = 713,
SUMMON_TYPE_GUARDIAN3 = 1161,
SUMMON_TYPE_ELEMENTAL = 1561,
SUMMON_TYPE_FORCE_OF_NATURE = 1562
};

View file

@ -1194,7 +1194,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
{
// for delayed spells ignore not visible explicit target
if (m_spellInfo->speed > 0.0f && unit == m_targets.getUnitTarget() &&
!unit->isVisibleForOrDetect(m_caster,false))
!unit->isVisibleForOrDetect(m_caster,m_caster,false))
{
realCaster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE);
return;
@ -1204,9 +1204,9 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
if (!(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_BREAK_STEALTH))
unit->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
// can cause back attack (if detected)
// can cause back attack (if detected), stealth removed at Spell::cast if spell break it
if (!(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO) && !IsPositiveSpell(m_spellInfo->Id) &&
m_caster->isVisibleForOrDetect(unit,false)) // stealth removed at Spell::cast if spell break it
m_caster->isVisibleForOrDetect(unit,unit,false))
{
// use speedup check to avoid re-remove after above lines
if (m_spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_BREAK_STEALTH)

View file

@ -4899,11 +4899,17 @@ void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real)
case 34511: // Valor (Bulwark of Kings, Bulwark of the Ancient Kings)
case 44055: // Tremendous Fortitude (Battlemaster's Alacrity)
case 50322: // Survival Instincts
case 54443: // Demonic Empowerment (Voidwalker)
{
if(Real)
{
if(apply)
{
// Demonic Empowerment (Voidwalker) - special case, store percent in data
// recalculate to full amount at apply for proper remove
if (GetId() == 54443)
m_modifier.m_amount = m_target->GetMaxHealth() * m_modifier.m_amount / 100;
m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
m_target->ModifyHealth(m_modifier.m_amount);
}
@ -5486,8 +5492,6 @@ void Aura::HandleShapeshiftBoosts(bool apply)
break;
case FORM_MOONKIN:
spellId1 = 24905;
// aura from effect trigger spell
spellId2 = 24907;
MasterShaperSpellId = 48421;
break;
case FORM_FLIGHT:
@ -5495,15 +5499,15 @@ void Aura::HandleShapeshiftBoosts(bool apply)
spellId2 = 34764;
break;
case FORM_FLIGHT_EPIC:
spellId1 = 40122;
spellId1 = 40122;
spellId2 = 40121;
break;
case FORM_METAMORPHOSIS:
spellId1 = 54817;
spellId1 = 54817;
spellId2 = 54879;
break;
case FORM_SPIRITOFREDEMPTION:
spellId1 = 27792;
spellId1 = 27792;
spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation.
break;
case FORM_SHADOW:
@ -5518,14 +5522,15 @@ void Aura::HandleShapeshiftBoosts(bool apply)
case FORM_STEALTH:
case FORM_CREATURECAT:
case FORM_CREATUREBEAR:
spellId1 = 0;
break;
}
if(apply)
{
if (spellId1) m_target->CastSpell(m_target, spellId1, true, NULL, this );
if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this);
if (spellId1)
m_target->CastSpell(m_target, spellId1, true, NULL, this );
if (spellId2)
m_target->CastSpell(m_target, spellId2, true, NULL, this);
if (m_target->GetTypeId() == TYPEID_PLAYER)
{
@ -5616,9 +5621,12 @@ void Aura::HandleShapeshiftBoosts(bool apply)
}
else
{
m_target->RemoveAurasDueToSpell(spellId1);
m_target->RemoveAurasDueToSpell(spellId2);
m_target->RemoveAurasDueToSpell(MasterShaperSpellId);
if(spellId1)
m_target->RemoveAurasDueToSpell(spellId1);
if(spellId2)
m_target->RemoveAurasDueToSpell(spellId2);
if(MasterShaperSpellId)
m_target->RemoveAurasDueToSpell(MasterShaperSpellId);
Unit::AuraMap& tAuras = m_target->GetAuras();
for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();)

File diff suppressed because it is too large Load diff

View file

@ -277,36 +277,53 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
// target not allow have more one spell specific from same caster
bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1,SpellSpecific spellSpec2)
bool IsSingleFromSpellSpecificPerTargetPerCaster(SpellSpecific spellSpec1,SpellSpecific spellSpec2)
{
switch(spellSpec1)
{
case SPELL_SEAL:
case SPELL_BLESSING:
case SPELL_AURA:
case SPELL_STING:
case SPELL_CURSE:
case SPELL_POSITIVE_SHOUT:
case SPELL_JUDGEMENT:
case SPELL_HAND:
return spellSpec1==spellSpec2;
default:
return false;
}
}
// target not allow have more one ranks from spell from spell specific per target
bool IsSingleFromSpellSpecificSpellRanksPerTarget(SpellSpecific spellSpec1,SpellSpecific spellSpec2)
{
switch(spellSpec1)
{
case SPELL_BLESSING:
case SPELL_AURA:
case SPELL_CURSE:
case SPELL_HAND:
return spellSpec1==spellSpec2;
default:
return false;
}
}
// target not allow have more one spell specific per target from any caster
bool IsSingleFromSpellSpecificPerTarget(SpellSpecific spellSpec1,SpellSpecific spellSpec2)
{
switch(spellSpec1)
{
case SPELL_SEAL:
case SPELL_ASPECT:
case SPELL_TRACKER:
case SPELL_WARLOCK_ARMOR:
case SPELL_MAGE_ARMOR:
case SPELL_ELEMENTAL_SHIELD:
case SPELL_MAGE_POLYMORPH:
case SPELL_POSITIVE_SHOUT:
case SPELL_JUDGEMENT:
case SPELL_PRESENCE:
case SPELL_HAND:
case SPELL_WELL_FED:
return spellSpec1==spellSpec2;
case SPELL_FOOD:
return spellSpec2==SPELL_FOOD
|| spellSpec2==SPELL_FOOD_AND_DRINK;
case SPELL_DRINK:
return spellSpec2==SPELL_DRINK
|| spellSpec2==SPELL_FOOD_AND_DRINK;
case SPELL_FOOD_AND_DRINK:
return spellSpec2==SPELL_FOOD
|| spellSpec2==SPELL_DRINK
|| spellSpec2==SPELL_FOOD_AND_DRINK;
case SPELL_BATTLE_ELIXIR:
return spellSpec2==SPELL_BATTLE_ELIXIR
|| spellSpec2==SPELL_FLASK_ELIXIR;
@ -317,22 +334,16 @@ bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1,SpellSpecific s
return spellSpec2==SPELL_BATTLE_ELIXIR
|| spellSpec2==SPELL_GUARDIAN_ELIXIR
|| spellSpec2==SPELL_FLASK_ELIXIR;
default:
return false;
}
}
// target not allow have more one ranks from spell from spell specific per target
bool IsSingleFromSpellSpecificRanksPerTarget(SpellSpecific spellId_spec, SpellSpecific i_spellId_spec)
{
switch(spellId_spec)
{
case SPELL_BLESSING:
case SPELL_AURA:
case SPELL_CURSE:
case SPELL_HAND:
case SPELL_ELEMENTAL_SHIELD:
return spellId_spec==i_spellId_spec;
case SPELL_FOOD:
return spellSpec2==SPELL_FOOD
|| spellSpec2==SPELL_FOOD_AND_DRINK;
case SPELL_DRINK:
return spellSpec2==SPELL_DRINK
|| spellSpec2==SPELL_FOOD_AND_DRINK;
case SPELL_FOOD_AND_DRINK:
return spellSpec2==SPELL_FOOD
|| spellSpec2==SPELL_DRINK
|| spellSpec2==SPELL_FOOD_AND_DRINK;
default:
return false;
}

View file

@ -180,8 +180,12 @@ inline bool IsLootCraftingSpell(SpellEntry const *spellInfo)
}
int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2);
bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1,SpellSpecific spellSpec2);
bool IsSingleFromSpellSpecificRanksPerTarget(SpellSpecific spellId_spec, SpellSpecific i_spellId_spec);
// order from less to more strict
bool IsSingleFromSpellSpecificPerTargetPerCaster(SpellSpecific spellSpec1,SpellSpecific spellSpec2);
bool IsSingleFromSpellSpecificSpellRanksPerTarget(SpellSpecific spellSpec1,SpellSpecific spellSpec2);
bool IsSingleFromSpellSpecificPerTarget(SpellSpecific spellSpec1,SpellSpecific spellSpec2);
bool IsPassiveSpell(uint32 spellId);
inline bool IsPassiveSpellStackableWithRanks(SpellEntry const* spellProto)

View file

@ -76,7 +76,7 @@ TotemAI::UpdateAI(const uint32 /*diff*/)
// Search victim if no, not attackable, or out of range, or friendly (possible in case duel end)
if( !victim ||
!victim->isTargetableForAttack() || !m_creature->IsWithinDistInMap(victim, max_range) ||
m_creature->IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(m_creature,false) )
m_creature->IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(m_creature,m_creature,false) )
{
CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(),m_creature->GetPositionY()));
Cell cell(p);

View file

@ -3193,21 +3193,11 @@ Spell* Unit::FindCurrentSpellBySpellId(uint32 spell_id) const
return NULL;
}
bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const
{
return IsWithinDistInMap(target, distance) && HasInArc( arc, target );
}
void Unit::SetInFront(Unit const* target)
{
SetOrientation(GetAngle(target));
}
bool Unit::isInBackInMap(Unit const* target, float distance, float arc) const
{
return IsWithinDistInMap(target, distance) && !HasInArc( 2 * M_PI - arc, target );
}
bool Unit::isInAccessablePlaceFor(Creature const* c) const
{
if(IsInWater())
@ -3631,9 +3621,10 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
SpellSpecific i_spellId_spec = GetSpellSpecific(i_spellId);
// single allowed spell specific from same caster
bool is_sspc = IsSingleFromSpellSpecificPerCaster(spellId_spec,i_spellId_spec);
if( is_sspc && Aur->GetCasterGUID() == (*i).second->GetCasterGUID() )
// single allowed spell specific from same caster or from any caster at target
bool is_spellSpecPerTargetPerCaster = IsSingleFromSpellSpecificPerTargetPerCaster(spellId_spec,i_spellId_spec);
bool is_spellSpecPerTarget = IsSingleFromSpellSpecificPerTarget(spellId_spec,i_spellId_spec);
if( is_spellSpecPerTarget || is_spellSpecPerTargetPerCaster && Aur->GetCasterGUID() == (*i).second->GetCasterGUID() )
{
// cannot remove higher rank
if (spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId))
@ -3658,9 +3649,8 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
// spell with spell specific that allow single ranks for spell from diff caster
// same caster case processed or early or later
bool is_sspt = IsSingleFromSpellSpecificRanksPerTarget(spellId_spec,i_spellId_spec);
if ( is_sspt && Aur->GetCasterGUID() != (*i).second->GetCasterGUID() &&
(spellProto->Id == i_spellId || spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId)))
bool is_spellPerTarget = IsSingleFromSpellSpecificSpellRanksPerTarget(spellId_spec,i_spellId_spec);
if ( is_spellPerTarget && Aur->GetCasterGUID() != (*i).second->GetCasterGUID() && spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId))
{
// cannot remove higher rank
if(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0)
@ -3682,8 +3672,8 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
continue;
}
// non single per caster spell specific (possible single per target spells at caster)
if( !is_sspc && spellmgr.IsNoStackSpellDueToSpell(spellId, i_spellId) )
// non single (per caster) per target spell specific (possible single spell per target at caster)
if( !is_spellSpecPerTargetPerCaster && !is_spellSpecPerTarget && spellmgr.IsNoStackSpellDueToSpell(spellId, i_spellId) )
{
// Its a parent aura (create this aura in ApplyModifier)
if ((*i).second->IsInUse())
@ -9272,7 +9262,7 @@ int32 Unit::ModifyPower(Powers power, int32 dVal)
return gain;
}
bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList, bool is3dDistance) const
bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, bool detect, bool inVisibleList, bool is3dDistance) const
{
if(!u)
return false;
@ -9319,16 +9309,20 @@ bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList,
if(GetCharmerOrOwnerGUID()==u->GetGUID())
return true;
// always seen by far sight caster
if( u->GetTypeId()==TYPEID_PLAYER && ((Player*)u)->GetFarSight()==GetGUID())
return true;
// different visible distance checks
if(u->isInFlight()) // what see player in flight
{
// use object grey distance for all (only see objects any way)
if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), is3dDistance))
if (!IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), is3dDistance))
return false;
}
else if(!isAlive()) // distance for show body
{
if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), is3dDistance))
if (!IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), is3dDistance))
return false;
}
else if(GetTypeId()==TYPEID_PLAYER) // distance for show player
@ -9336,26 +9330,26 @@ bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList,
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(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
if (!at_same_transport && !IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceForPlayer()+(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(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
if (!IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceForCreature()+(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(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
if (!IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceForPlayer()+(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(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
if (!IsWithinDistInMap(viewPoint,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
return false;
}
@ -9463,7 +9457,7 @@ bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList,
float visibleDistance = (u->GetTypeId() == TYPEID_PLAYER) ? MAX_PLAYER_STEALTH_DETECT_RANGE : ((Creature const*)u)->GetAttackDistance(this);
//Always invisible from back (when stealth detection is on), also filter max distance cases
bool isInFront = u->isInFrontInMap(this, visibleDistance);
bool isInFront = viewPoint->isInFrontInMap(this, visibleDistance);
if(!isInFront)
return false;
@ -9490,13 +9484,13 @@ bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList,
visibleDistance = visibleDistance > MAX_PLAYER_STEALTH_DETECT_RANGE ? MAX_PLAYER_STEALTH_DETECT_RANGE : visibleDistance;
// recheck new distance
if(visibleDistance <= 0 || !IsWithinDist(u,visibleDistance))
if(visibleDistance <= 0 || !IsWithinDist(viewPoint,visibleDistance))
return false;
}
// Now check is target visible with LoS
float ox,oy,oz;
u->GetPosition(ox,oy,oz);
viewPoint->GetPosition(ox,oy,oz);
return IsWithinLOS(ox,oy,oz);
}
@ -10203,9 +10197,9 @@ Unit* Unit::GetUnit(WorldObject& object, uint64 guid)
return ObjectAccessor::GetUnit(object,guid);
}
bool Unit::isVisibleForInState( Player const* u, bool inVisibleList ) const
bool Unit::isVisibleForInState( Player const* u, WorldObject const* viewPoint, bool inVisibleList ) const
{
return isVisibleForOrDetect(u, false, inVisibleList, false);
return isVisibleForOrDetect(u, viewPoint, false, inVisibleList, false);
}
uint32 Unit::GetCreatureType() const

View file

@ -1310,21 +1310,19 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
float GetWeaponDamageRange(WeaponAttackType attType ,WeaponDamageRange type) const;
void SetBaseWeaponDamage(WeaponAttackType attType ,WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; }
bool isInFrontInMap(Unit const* target,float distance, float arc = M_PI) const;
void SetInFront(Unit const* target);
bool isInBackInMap(Unit const* target, float distance, float arc = M_PI) const;
// Visibility system
UnitVisibility GetVisibility() const { return m_Visibility; }
void SetVisibility(UnitVisibility x);
// common function for visibility checks for player/creatures with detection code
bool isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList = false, bool is3dDistance = true) const;
bool isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, bool detect, bool inVisibleList = false, bool is3dDistance = true) const;
bool canDetectInvisibilityOf(Unit const* u) const;
void SetPhaseMask(uint32 newPhaseMask, bool update);// overwrite WorldObject::SetPhaseMask
// virtual functions for all world objects types
bool isVisibleForInState(Player const* u, bool inVisibleList) const;
bool isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const;
// function for low level grid visibility checks in player/creature cases
virtual bool IsVisibleInGridForPlayer(Player* pl) const = 0;

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "8411"
#define REVISION_NR "8423"
#endif // __REVISION_NR_H__