diff --git a/configure.ac b/configure.ac index 7a1b219ec..1f31c9429 100644 --- a/configure.ac +++ b/configure.ac @@ -138,6 +138,11 @@ AC_PATH_PROGS(MYSQL_CONFIG, mysql_config, mysql_config, $PATH) MYSQL_INCLUDES="`$MYSQL_CONFIG --cflags`" MYSQL_LIBS="`$MYSQL_CONFIG --libs_r`" CXXFLAGS="-DDO_MYSQL $CXXFLAGS" + # Workaround for --as-needed linker flag that comes sometimes from mysql + if echo $MYSQL_LIBS|grep "\-Wl,--as-needed" > /dev/null; then + MYSQL_LIBS=`echo $MYSQL_LIBS|sed -e "s/-Wl,--as-needed//"`; + AC_MSG_WARN([Your mysql libs contains -Wl,--as-needed, this is not good, problem fixed in more recent mysql versions]) + fi fi else AC_MSG_RESULT($DO_MYSQL) diff --git a/contrib/git_id/git_id.cpp b/contrib/git_id/git_id.cpp index 319abbd64..df81ac522 100644 --- a/contrib/git_id/git_id.cpp +++ b/contrib/git_id/git_id.cpp @@ -750,8 +750,10 @@ bool prepare_new_index() if(!use_new_index) return true; // only use a new index if there are staged changes that should be preserved - if( (cmd_pipe = popen( "git diff --cached", "r" )) == NULL ) + if( (cmd_pipe = popen( "git diff --cached", "r" )) == NULL ) { + use_new_index = false; return false; + } if(!fgets(buffer, MAX_BUF, cmd_pipe)) { diff --git a/sql/mangos.sql b/sql/mangos.sql index ca94c27ae..9f997595b 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -23,7 +23,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, - `required_8254_01_mangos_spell_proc_event` bit(1) default NULL + `required_8310_01_mangos_spell_proc_event` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -9791,7 +9791,7 @@ INSERT INTO `playercreateinfo_action` VALUES (2,3,0,6603,0), (2,3,1,2973,0), (2,3,2,75,0), -(2,3,4,20572,0), +(2,3,9,20572,0), (2,3,10,159,128), (2,3,11,117,128), (2,4,0,6603,0), @@ -9868,10 +9868,9 @@ INSERT INTO `playercreateinfo_action` VALUES (3,6,5,47541,0), (3,6,10,2481,0), (4,1,72,6603,0), -(4,1,73,6603,0), -(4,1,74,78,0), -(4,1,83,58984,0), -(4,1,84,117,128), +(4,1,73,78,0), +(4,1,82,58984,0), +(4,1,83,117,128), (4,1,85,6603,0), (4,1,97,6603,0), (4,1,109,6603,0), @@ -9885,8 +9884,9 @@ INSERT INTO `playercreateinfo_action` VALUES (4,4,1,1752,0), (4,4,2,2098,0), (4,4,3,2764,0), -(4,4,4,58984,0), +(4,4,10,58984,0), (4,4,11,4540,128), +(4,4,82,58984,0), (4,5,0,6603,0), (4,5,1,585,0), (4,5,2,2050,0), @@ -9904,7 +9904,7 @@ INSERT INTO `playercreateinfo_action` VALUES (4,11,0,6603,0), (4,11,1,5176,0), (4,11,2,5185,0), -(4,11,3,58984,0), +(4,11,9,58984,0), (4,11,10,159,128), (4,11,11,4536,128), (5,1,0,6603,0), @@ -10013,9 +10013,9 @@ INSERT INTO `playercreateinfo_action` VALUES (7,6,4,45902,0), (7,6,5,47541,0), (7,6,10,20589,0), -(7,6,11,117,128), +(7,6,11,41751,128), (7,6,72,6603,0), -(7,6,83,117,128), +(7,6,83,41751,128), (7,6,84,6603,0), (7,6,96,6603,0), (7,6,108,6603,0), @@ -10043,21 +10043,21 @@ INSERT INTO `playercreateinfo_action` VALUES (8,3,0,6603,0), (8,3,1,2973,0), (8,3,2,75,0), +(8,3,3,20554,0), (8,3,10,159,128), (8,3,11,4604,128), -(8,3,76,20554,0), (8,4,0,6603,0), (8,4,1,1752,0), (8,4,2,2098,0), (8,4,3,2764,0), +(8,4,4,26297,0), (8,4,11,117,128), -(8,4,76,20554,0), (8,5,0,6603,0), (8,5,1,585,0), (8,5,2,2050,0), +(8,5,3,20554,0), (8,5,10,159,128), (8,5,11,4540,128), -(8,5,76,20554,0), (8,6,0,6603,0), (8,6,1,49576,0), (8,6,2,45477,0), @@ -10068,15 +10068,15 @@ INSERT INTO `playercreateinfo_action` VALUES (8,7,0,6603,0), (8,7,1,403,0), (8,7,2,331,0), +(8,7,3,20554,0), (8,7,10,159,128), (8,7,11,117,128), -(8,7,76,20554,0), (8,8,0,6603,0), (8,8,1,133,0), (8,8,2,168,0), +(8,8,3,20554,0), (8,8,10,159,128), (8,8,11,117,128), -(8,8,76,20554,0), (10,2,0,6603,0), (10,2,1,21084,0), (10,2,2,635,0), @@ -10159,7 +10159,8 @@ INSERT INTO `playercreateinfo_action` VALUES (11,6,3,45462,0), (11,6,4,45902,0), (11,6,5,47541,0), -(11,6,6,59545,0), +(11,6,10,59545,0), +(11,6,11,41751,128), (11,7,0,6603,0), (11,7,1,403,0), (11,7,2,331,0), @@ -17952,7 +17953,8 @@ INSERT INTO `spell_proc_event` VALUES (63108, 0x00000000, 5, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (63156, 0x00000000, 0, 0x00000001, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (63245, 0x00000000, 5, 0x00000100, 0x00800000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), -(63730, 0x00000000, 6, 0x00000800, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0); +(63730, 0x00000000, 6, 0x00000800, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(64928, 0x00000000, 11, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0); /*!40000 ALTER TABLE `spell_proc_event` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/mangos_spell_check.sql b/sql/mangos_spell_check.sql index 21892c31c..a1a93cb43 100644 --- a/sql/mangos_spell_check.sql +++ b/sql/mangos_spell_check.sql @@ -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::EffectDummy */ +/* SpellEffect.cpp from start until end of Spell::EffectPowerBurn */ DROP TABLE IF EXISTS spell_check; CREATE TABLE `spell_check` ( @@ -58,6 +58,7 @@ 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'), @@ -98,6 +99,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas (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'), @@ -110,10 +112,13 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas (23133, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Gnomish Battle Chicken', 'Spell::EffectDummy'), (23170,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Brood Affliction: Bronze', 'Spell::EffectDummy'), (23441,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Gadgetzan Transporter', 'Spell::EffectDummy'), +(23442,-1, -1, -1, -1, -1, -1, 5, -1,-1,'Everlook Transporter', 'Spell::EffectTeleportUnits'), (23444,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Transporter Malfunction', 'Spell::EffectDummy'), (23445,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Evil Twin', 'Spell::EffectDummy'), +(23445,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Evil Twin', 'Spell::EffectTeleportUnits'), (23446,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Gadgetzan Transporter Failure', 'Spell::EffectDummy'), (23448, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Transporter Arrival', 'Spell::EffectDummy'), +(23449,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Transporter Malfunction', 'Spell::EffectTeleportUnits'), (23453, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Gnomish Transporter', 'Spell::EffectDummy'), (23645, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Hourglass Sand', 'Spell::EffectDummy'), (23725, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Gift of Life', 'Spell::EffectDummy'), @@ -123,6 +128,7 @@ 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'), +(24575,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Brittle Armor', 'Spell::EffectTriggerSpell'), (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'), @@ -134,6 +140,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas (25913,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Holy Shock', 'Spell::EffectDummy'), (25914,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Holy Shock', 'Spell::EffectDummy'), (26074, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Holiday Cheer', 'Spell::EffectDummy'), +(26464,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Mercurial Shield', 'Spell::EffectTriggerSpell'), (26467,-1, -1, -1, -1, -1, -1, 6, 42, 0,'Persistent Shield', 'Spell::EffectDummy'), (26558, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor', 'Spell::EffectSchoolDMG'), (26635,-1, -1, -1, -1, -1, -1, 6, -1, 0,'Berserking', 'Spell::EffectDummy'), @@ -145,6 +152,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas (27176,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Holy Shock', 'Spell::EffectDummy'), (27222, 5,0x0000000000040000,0x00000000, -1, -1, -1, 3, -1,-1,'Life Tap', 'Spell::EffectDummy'), (28006, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Arcane Cloaking', 'Spell::EffectDummy'), +(28305,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Mana Leech', 'Spell::EffectTriggerSpell'), (28884, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor', 'Spell::EffectSchoolDMG'), (29294,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Naxxramas Entry Flag Effect DND', 'Spell::EffectDummy'), (29200, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Purify Helboar Meat', 'Spell::EffectDummy'), @@ -163,6 +171,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas (31231, 8, -1, -1, -1, -1, -1, 3, -1,-1,'Cheat Death', 'Spell::EffectDummy'), (31436, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Malevolent Cleave', 'Spell::EffectSchoolDMG'), (31789,10, -1, -1, -1, -1, -1, 3, -1, 0,'Righteous Defense', 'Spell::EffectDummy'), +(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'), (32409,-1, -1, -1, -1, -1, -1, 6, 3,-1,'Shadow Word: Death', 'Spell::EffectSchoolDMG'), @@ -197,7 +206,16 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas (36755,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Rockbiter Weapon', 'Spell::EffectDummy'), (36759,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Rockbiter Weapon', 'Spell::EffectDummy'), (36837, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor', 'Spell::EffectSchoolDMG'), +(36890,-1, -1, -1, -1, -1, -1, 5, -1,-1,'Area52 Transporter', 'Spell::EffectTeleportUnits'), +(36893,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Transporter Malfunction', 'Spell::EffectTeleportUnits'), +(36895,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Transporter Malfunction', 'Spell::EffectTeleportUnits'), +(36897,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Transporter Malfunction', 'Spell::EffectTeleportUnits'), +(36899,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Transporter Malfunction', 'Spell::EffectTeleportUnits'), +(36900,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Soul Split: Evil!', 'Spell::EffectTeleportUnits'), +(36901,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Soul Split: Good', 'Spell::EffectTeleportUnits'), (36902,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Transporter Malfunction', 'Spell::EffectDummy'), +(36940,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Transporter Malfunction', 'Spell::EffectTeleportUnits'), +(36941,-1, -1, -1, -1, -1, -1, 5, -1,-1,'Toshley\'s Station Transporter', 'Spell::EffectTeleportUnits'), (37169,-1, -1, -1, -1, -1, -1, 6, 4,-1,'Eviscerate and Envenom Bonus Damage','Spell::EffectSchoolDMG'), (37506, 9, -1, -1, -1, -1, -1, 3, -1,-1,'Scatter Shot', 'Spell::EffectDummy'), (37674, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Chaos Blast', 'Spell::EffectDummy'), @@ -213,6 +231,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'), (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'), @@ -337,6 +356,7 @@ 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, 8,0x0000024000000860,0x00000000, -1, -1, -1, -1, -1,-1,'Preparation (affected spells)', 'Spell::EffectDummy'), ( 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 */ @@ -355,6 +375,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas (0, 7,0x0000000000000000,0x00000100, -1, -1, -1, 3, -1,-1,'Starfall', 'Spell::EffectDummy'), ( 0, 9,0x0000000100000000,0x00000000, -1, -1, -1, 2, -1,-1,'Steady Shot', 'Spell::EffectSchoolDMG'), ( 0, 9,0x0000000100000000,0x00000000, -1, -1, -1, 3, -1,-1,'Steady Shot', 'Spell::EffectDummy'), +( 0, 8,0x0000000000400000,0x00000000, -1, -1, -1, -1, -1,-1,'Stealth', 'Spell::EffectTriggerSpell'), ( 0, 7,0x0010000000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Swipe', 'Spell::EffectSchoolDMG'), ( 0, 4,0x0000000000000080,0x00000000, -1, -1, -1, 2, -1,-1,'Thunder Clap', 'Spell::EffectSchoolDMG'), ( 0, 4,0x0000010000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Victory Rush', 'Spell::EffectSchoolDMG'), diff --git a/sql/updates/8294_01_mangos_playercreateinfo_action.sql b/sql/updates/8294_01_mangos_playercreateinfo_action.sql new file mode 100644 index 000000000..802f3ab4f --- /dev/null +++ b/sql/updates/8294_01_mangos_playercreateinfo_action.sql @@ -0,0 +1,54 @@ +ALTER TABLE db_version CHANGE COLUMN required_8254_01_mangos_spell_proc_event required_8294_01_mangos_playercreateinfo_action bit; + +-- Remove Double attack icons for Night Elf Warrior +DELETE FROM playercreateinfo_action WHERE race=4 AND class=1 AND button=73; +-- Move Heroic Strike to correct location for Night Elf Warrior +DELETE FROM playercreateinfo_action WHERE race=4 AND class=1 AND button=74; +INSERT INTO playercreateinfo_action VALUES (4,1,73,78,0); +-- Moved Shadowmeld to correct location for Night Elf Warrior +DELETE FROM playercreateinfo_action WHERE race=4 AND class=1 AND button IN (82,83); +INSERT INTO playercreateinfo_action VALUES (4,1,82,58984,0); +-- Add correct Tough Jerky location for Night elf Warrior +DELETE FROM playercreateinfo_action WHERE race=4 AND class=1 AND button=84; +INSERT INTO playercreateinfo_action VALUES (4,1,83,117,128); + +-- Moved Shadowmeld to correct location for Night Elf Druid +DELETE FROM playercreateinfo_action WHERE race=4 AND class=11 AND button IN (3,9); +INSERT INTO playercreateinfo_action VALUES (4,11,9,58984,0); + +-- Moved Shadowmeld to correct location for Night Elf Rogue +DELETE FROM playercreateinfo_action WHERE race=4 AND class=4 AND button IN (4,10); +INSERT INTO playercreateinfo_action VALUES (4,4,10,58984,0); +-- Add Shadowmeld For Night Elf Rogue Shadow form bar +DELETE FROM playercreateinfo_action WHERE race=4 AND class=4 AND button = 82; +INSERT INTO playercreateinfo_action VALUES (4,4,82,58984,0); + +-- Replace Tough Jerky for Gnome Death Knight Action Bar +DELETE FROM playercreateinfo_action WHERE race=7 AND class=6 AND button IN (11,83); +INSERT INTO playercreateinfo_action VALUES +(7,6,11,41751,128), +(7,6,83,41751,128); + +-- Moved Gift of Naaru to correct location for Draenei Death Knight +DELETE FROM playercreateinfo_action WHERE race=11 AND class=6 AND button IN (6,10); +INSERT INTO playercreateinfo_action VALUES (11,6,10,59545,0); +-- Add Black Mushroom to Draenei Death Knight Action Bar +DELETE FROM playercreateinfo_action WHERE race=11 AND class=6 AND button IN (11); +INSERT INTO playercreateinfo_action VALUES +(11,6,11,41751,128); + +-- Moved Blood Fury to correct action bar location for Orc Hunter +DELETE FROM playercreateinfo_action WHERE race=2 AND class=3 AND button IN (4,9); +INSERT INTO playercreateinfo_action VALUES (2,3,9,20572,0); + +-- Moved Berserking to correct action bar location for Non-Heroic Troll classes +DELETE FROM playercreateinfo_action WHERE race=8 AND class IN (3,5,7,8) AND button IN (3,76); +INSERT INTO playercreateinfo_action VALUES +(8,3,3,20554,0), +(8,5,3,20554,0), +(8,7,3,20554,0), +(8,8,3,20554,0); + +-- Updated and moved Berserking skill for Troll Rogue +DELETE FROM playercreateinfo_action WHERE race=8 AND class=4 AND button IN (4,76); +INSERT INTO playercreateinfo_action VALUES (8,4,4,26297,0); diff --git a/sql/updates/8310_01_mangos_spell_proc_event.sql b/sql/updates/8310_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..932a1f9bd --- /dev/null +++ b/sql/updates/8310_01_mangos_spell_proc_event.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_8294_01_mangos_playercreateinfo_action required_8310_01_mangos_spell_proc_event bit; + +DELETE FROM `spell_proc_event` WHERE `entry` IN (64928); +INSERT INTO `spell_proc_event` VALUES +(64928, 0x00000000, 11, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 3a26346aa..fbe6d7a4d 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -261,6 +261,8 @@ pkgdata_DATA = \ 8253_01_mangos_spell_chain.sql \ 8253_02_mangos_spell_proc_event.sql \ 8254_01_mangos_spell_proc_event.sql \ + 8294_01_mangos_playercreateinfo_action.sql \ + 8310_01_mangos_spell_proc_event.sql \ README ## Additional files to include when running 'make dist' @@ -502,4 +504,6 @@ EXTRA_DIST = \ 8253_01_mangos_spell_chain.sql \ 8253_02_mangos_spell_proc_event.sql \ 8254_01_mangos_spell_proc_event.sql \ + 8294_01_mangos_playercreateinfo_action.sql \ + 8310_01_mangos_spell_proc_event.sql \ README diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index f2fc6b08e..c44df2751 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -81,13 +81,14 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) switch(criteria->requiredType) { - case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: - case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: // only hardcoded list + case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: // only hardcoded list case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA: case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: + case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL: case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE: case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: break; @@ -689,7 +690,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui // std. case: increment at 1 case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS: - case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL: case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL: case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED: case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED: @@ -1253,6 +1253,24 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui SetCriteriaProgress(achievementCriteria, spellCount); break; } + case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + + if(achievementCriteria->win_duel.duelCount) + { + // those requirements couldn't be found in the dbc + AchievementCriteriaDataSet const* data = achievementmgr.GetCriteriaDataSet(achievementCriteria); + if(!data) + continue; + + if(!data->Meets(GetPlayer(),unit)) + continue; + } + + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + break; case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION: SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetReveredFactionCount()); break; @@ -1942,6 +1960,10 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData() if(criteria->do_emote.count==0) continue; break; + case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL: // skip statistics + if(criteria->win_duel.duelCount==0) + continue; + break; case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: // any cases break; case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE: // need skip generic cases diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index d06e44253..9449e4f6e 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -201,16 +201,13 @@ BattleGround::~BattleGround() // (this is done automatically in mapmanager update, when the instance is reset after the reset time) int size = m_BgCreatures.size(); for(int i = 0; i < size; ++i) - { DelCreature(i); - } + size = m_BgObjects.size(); for(int i = 0; i < size; ++i) - { DelObject(i); - } - if(GetInstanceID()) // not spam by useless queries in case BG templates + if (GetInstanceID()) // not spam by useless queries in case BG templates { // delete creature and go respawn times WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE instance = '%u'",GetInstanceID()); @@ -227,6 +224,9 @@ BattleGround::~BattleGround() ((BattleGroundMap*)map)->SetUnload(); // remove from bg free slot queue this->RemoveFromBGFreeSlotQueue(); + + for(BattleGroundScoreMap::const_iterator itr = m_PlayerScores.begin(); itr != m_PlayerScores.end(); ++itr) + delete itr->second; } void BattleGround::Update(uint32 diff) @@ -939,7 +939,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac participant = true; } - std::map::iterator itr2 = m_PlayerScores.find(guid); + BattleGroundScoreMap::iterator itr2 = m_PlayerScores.find(guid); if (itr2 != m_PlayerScores.end()) { delete itr2->second; // delete player's score @@ -1081,6 +1081,9 @@ void BattleGround::Reset() m_InBGFreeSlotQueue = false; m_Players.clear(); + + for(BattleGroundScoreMap::const_iterator itr = m_PlayerScores.begin(); itr != m_PlayerScores.end(); ++itr) + delete itr->second; m_PlayerScores.clear(); } @@ -1271,7 +1274,7 @@ bool BattleGround::HasFreeSlots() const void BattleGround::UpdatePlayerScore(Player *Source, uint32 type, uint32 value) { //this procedure is called from virtual function implemented in bg subclass - std::map::const_iterator itr = m_PlayerScores.find(Source->GetGUID()); + BattleGroundScoreMap::const_iterator itr = m_PlayerScores.find(Source->GetGUID()); if(itr == m_PlayerScores.end()) // player not found... return; diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index e20556497..d5ba8e3a0 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -375,8 +375,9 @@ class BattleGround BattleGroundPlayerMap const& GetPlayers() const { return m_Players; } uint32 GetPlayersSize() const { return m_Players.size(); } - std::map::const_iterator GetPlayerScoresBegin() const { return m_PlayerScores.begin(); } - std::map::const_iterator GetPlayerScoresEnd() const { return m_PlayerScores.end(); } + typedef std::map BattleGroundScoreMap; + BattleGroundScoreMap::const_iterator GetPlayerScoresBegin() const { return m_PlayerScores.begin(); } + BattleGroundScoreMap::const_iterator GetPlayerScoresEnd() const { return m_PlayerScores.end(); } uint32 GetPlayerScoresSize() const { return m_PlayerScores.size(); } uint32 GetReviveQueueSize() const { return m_ReviveQueue.size(); } @@ -513,8 +514,8 @@ class BattleGround void PlayerAddedToBGCheckIfBGIsRunning(Player* plr); /* Scorekeeping */ - // Player scores - std::map m_PlayerScores; + + BattleGroundScoreMap m_PlayerScores; // Player scores // must be implemented in BG subclass virtual void RemovePlayer(Player * /*player*/, uint64 /*guid*/) {} diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index 1a5d4a283..7e27972ff 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -659,8 +659,7 @@ WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player) void BattleGroundAB::UpdatePlayerScore(Player *Source, uint32 type, uint32 value) { - std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); - + BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); if( itr == m_PlayerScores.end() ) // player not found... return; diff --git a/src/game/BattleGroundAV.cpp b/src/game/BattleGroundAV.cpp index 84789ce70..9a52e726f 100644 --- a/src/game/BattleGroundAV.cpp +++ b/src/game/BattleGroundAV.cpp @@ -96,8 +96,7 @@ void BattleGroundAV::HandleAreaTrigger(Player *Source, uint32 Trigger) void BattleGroundAV::UpdatePlayerScore(Player* Source, uint32 type, uint32 value) { - std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); - + BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); if(itr == m_PlayerScores.end()) // player not found... return; diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp index 111fff722..e15e360ba 100644 --- a/src/game/BattleGroundBE.cpp +++ b/src/game/BattleGroundBE.cpp @@ -180,8 +180,7 @@ bool BattleGroundBE::SetupBattleGround() void BattleGroundBE::UpdatePlayerScore(Player* Source, uint32 type, uint32 value) { - std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); - + BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); if(itr == m_PlayerScores.end()) // player not found... return; diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 60bfaa70e..824a8dd99 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -778,8 +778,7 @@ void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType void BattleGroundEY::UpdatePlayerScore(Player *Source, uint32 type, uint32 value) { - std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); - + BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); if(itr == m_PlayerScores.end()) // player not found return; diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 49f17630b..ab2a847b8 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -1333,7 +1333,7 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) *data << (int32)(bg->GetPlayerScoresSize()); - for(std::map::const_iterator itr = bg->GetPlayerScoresBegin(); itr != bg->GetPlayerScoresEnd(); ++itr) + for(BattleGround::BattleGroundScoreMap::const_iterator itr = bg->GetPlayerScoresBegin(); itr != bg->GetPlayerScoresEnd(); ++itr) { *data << (uint64)itr->first; *data << (int32)itr->second->KillingBlows; diff --git a/src/game/BattleGroundSA.cpp b/src/game/BattleGroundSA.cpp index c52635a04..20cadac93 100644 --- a/src/game/BattleGroundSA.cpp +++ b/src/game/BattleGroundSA.cpp @@ -72,8 +72,7 @@ void BattleGroundSA::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/) void BattleGroundSA::UpdatePlayerScore(Player* Source, uint32 type, uint32 value) { - std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); - + BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); if(itr == m_PlayerScores.end()) // player not found... return; diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index 5f6fb4b2c..312735654 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -631,8 +631,7 @@ void BattleGroundWS::HandleKillPlayer(Player *player, Player *killer) void BattleGroundWS::UpdatePlayerScore(Player *Source, uint32 type, uint32 value) { - std::map::iterator itr = m_PlayerScores.find(Source->GetGUID()); - + BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID()); if(itr == m_PlayerScores.end()) // player not found return; diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index d9eae3a94..26bf891f6 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -818,6 +818,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) { pCurrChar->resetTalents(true); + pCurrChar->SendTalentsInfoData(false); // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state SendNotification(LANG_RESET_TALENTS); } @@ -835,6 +836,9 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid:%u)", GetAccountId(),IP_str.c_str(),pCurrChar->GetName() ,pCurrChar->GetGUIDLow()); + if(!pCurrChar->IsStandState() && !pCurrChar->hasUnitState(UNIT_STAT_STUNNED)) + pCurrChar->SetStandState(UNIT_STAND_STATE_STAND); + m_playerLoading = false; delete holder; } diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp index 3ed40ad3d..ccfe5b9d1 100644 --- a/src/game/Guild.cpp +++ b/src/game/Guild.cpp @@ -808,17 +808,17 @@ void Guild::DisplayGuildEventlog(WorldSession *session) for (GuildEventlog::const_iterator itr = m_GuildEventlog.begin(); itr != m_GuildEventlog.end(); ++itr) { // Event type - data << uint8((*itr)->EventType); + data << uint8(itr->EventType); // Player 1 - data << uint64((*itr)->PlayerGuid1); + data << uint64(itr->PlayerGuid1); // Player 2 not for left/join guild events - if( (*itr)->EventType != GUILD_EVENT_LOG_JOIN_GUILD && (*itr)->EventType != GUILD_EVENT_LOG_LEAVE_GUILD ) - data << uint64((*itr)->PlayerGuid2); + if (itr->EventType != GUILD_EVENT_LOG_JOIN_GUILD && itr->EventType != GUILD_EVENT_LOG_LEAVE_GUILD) + data << uint64(itr->PlayerGuid2); // New Rank - only for promote/demote guild events - if( (*itr)->EventType == GUILD_EVENT_LOG_PROMOTE_PLAYER || (*itr)->EventType == GUILD_EVENT_LOG_DEMOTE_PLAYER ) - data << uint8((*itr)->NewRank); + if (itr->EventType == GUILD_EVENT_LOG_PROMOTE_PLAYER || itr->EventType == GUILD_EVENT_LOG_DEMOTE_PLAYER) + data << uint8(itr->NewRank); // Event timestamp - data << uint32(time(NULL)-(*itr)->TimeStamp); + data << uint32(time(NULL)-itr->TimeStamp); } session->SendPacket(&data); sLog.outDebug("WORLD: Sent (MSG_GUILD_EVENT_LOG_QUERY)"); @@ -837,14 +837,14 @@ void Guild::LoadGuildEventLogFromDB() do { Field *fields = result->Fetch(); - GuildEventlogEntry *NewEvent = new GuildEventlogEntry; + GuildEventlogEntry NewEvent; // Fill entry - NewEvent->LogGuid = fields[0].GetUInt32(); - NewEvent->EventType = fields[1].GetUInt8(); - NewEvent->PlayerGuid1 = fields[2].GetUInt32(); - NewEvent->PlayerGuid2 = fields[3].GetUInt32(); - NewEvent->NewRank = fields[4].GetUInt8(); - NewEvent->TimeStamp = fields[5].GetUInt64(); + NewEvent.LogGuid = fields[0].GetUInt32(); + NewEvent.EventType = fields[1].GetUInt8(); + NewEvent.PlayerGuid1 = fields[2].GetUInt32(); + NewEvent.PlayerGuid2 = fields[3].GetUInt32(); + NewEvent.NewRank = fields[4].GetUInt8(); + NewEvent.TimeStamp = fields[5].GetUInt64(); // Add entry to map m_GuildEventlog.push_front(NewEvent); @@ -854,9 +854,8 @@ void Guild::LoadGuildEventLogFromDB() // Check lists size in case to many event entries in db // This cases can happen only if a crash occured somewhere and table has too many log entries if (!m_GuildEventlog.empty()) - { - CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE guildid=%u AND LogGuid < %u", Id, m_GuildEventlog.front()->LogGuid); - } + CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE guildid=%u AND LogGuid < %u", Id, m_GuildEventlog.front().LogGuid); + m_eventlogloaded = true; } @@ -865,16 +864,8 @@ void Guild::UnloadGuildEventlog() { if (!m_eventlogloaded) return; - GuildEventlogEntry *EventLogEntry; - if( !m_GuildEventlog.empty() ) - { - do - { - EventLogEntry = *(m_GuildEventlog.begin()); - m_GuildEventlog.pop_front(); - delete EventLogEntry; - }while( !m_GuildEventlog.empty() ); - } + + m_GuildEventlog.clear(); m_eventlogloaded = false; } @@ -894,27 +885,25 @@ void Guild::RenumGuildEventlog() // Add entry to guild eventlog void Guild::LogGuildEvent(uint8 EventType, uint32 PlayerGuid1, uint32 PlayerGuid2, uint8 NewRank) { - GuildEventlogEntry *NewEvent = new GuildEventlogEntry; + GuildEventlogEntry NewEvent; // Fill entry - NewEvent->LogGuid = GuildEventlogMaxGuid++; - NewEvent->EventType = EventType; - NewEvent->PlayerGuid1 = PlayerGuid1; - NewEvent->PlayerGuid2 = PlayerGuid2; - NewEvent->NewRank = NewRank; - NewEvent->TimeStamp = uint32(time(NULL)); + NewEvent.LogGuid = GuildEventlogMaxGuid++; + NewEvent.EventType = EventType; + NewEvent.PlayerGuid1 = PlayerGuid1; + NewEvent.PlayerGuid2 = PlayerGuid2; + NewEvent.NewRank = NewRank; + NewEvent.TimeStamp = uint32(time(NULL)); // Check max entry limit and delete from db if needed if (m_GuildEventlog.size() > GUILD_EVENTLOG_MAX_ENTRIES) { - GuildEventlogEntry *OldEvent = *(m_GuildEventlog.begin()); + CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE guildid='%u' AND LogGuid='%u'", Id, m_GuildEventlog.front().LogGuid); m_GuildEventlog.pop_front(); - CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE guildid='%u' AND LogGuid='%u'", Id, OldEvent->LogGuid); - delete OldEvent; } // Add entry to map m_GuildEventlog.push_back(NewEvent); // Add new eventlog entry into DB CharacterDatabase.PExecute("INSERT INTO guild_eventlog (guildid, LogGuid, EventType, PlayerGuid1, PlayerGuid2, NewRank, TimeStamp) VALUES ('%u','%u','%u','%u','%u','%u','" UI64FMTD "')", - Id, NewEvent->LogGuid, uint32(NewEvent->EventType), NewEvent->PlayerGuid1, NewEvent->PlayerGuid2, uint32(NewEvent->NewRank), NewEvent->TimeStamp); + Id, NewEvent.LogGuid, uint32(NewEvent.EventType), NewEvent.PlayerGuid1, NewEvent.PlayerGuid2, uint32(NewEvent.NewRank), NewEvent.TimeStamp); } // ************************************************* @@ -1486,30 +1475,28 @@ void Guild::LoadGuildBankEventLogFromDB() do { Field *fields = result->Fetch(); - GuildBankEvent *NewEvent = new GuildBankEvent; + GuildBankEvent NewEvent; - NewEvent->LogGuid = fields[0].GetUInt32(); - NewEvent->LogEntry = fields[1].GetUInt8(); + NewEvent.LogGuid = fields[0].GetUInt32(); + NewEvent.LogEntry = fields[1].GetUInt8(); uint8 TabId = fields[2].GetUInt8(); - NewEvent->PlayerGuid = fields[3].GetUInt32(); - NewEvent->ItemOrMoney = fields[4].GetUInt32(); - NewEvent->ItemStackCount = fields[5].GetUInt8(); - NewEvent->DestTabId = fields[6].GetUInt8(); - NewEvent->TimeStamp = fields[7].GetUInt64(); + NewEvent.PlayerGuid = fields[3].GetUInt32(); + NewEvent.ItemOrMoney = fields[4].GetUInt32(); + NewEvent.ItemStackCount = fields[5].GetUInt8(); + NewEvent.DestTabId = fields[6].GetUInt8(); + NewEvent.TimeStamp = fields[7].GetUInt64(); if (TabId >= GUILD_BANK_MAX_TABS) { - sLog.outError( "Guild::LoadGuildBankEventLogFromDB: Invalid tabid '%u' for guild bank log entry (guild: '%s', LogGuid: %u), skipped.", TabId, GetName().c_str(), NewEvent->LogGuid); - delete NewEvent; + sLog.outError( "Guild::LoadGuildBankEventLogFromDB: Invalid tabid '%u' for guild bank log entry (guild: '%s', LogGuid: %u), skipped.", TabId, GetName().c_str(), NewEvent.LogGuid); continue; } - if (NewEvent->isMoneyEvent() && m_GuildBankEventLog_Money.size() >= GUILD_BANK_MAX_LOGS - || m_GuildBankEventLog_Item[TabId].size() >= GUILD_BANK_MAX_LOGS) - { - delete NewEvent; + + if (NewEvent.isMoneyEvent() && m_GuildBankEventLog_Money.size() >= GUILD_BANK_MAX_LOGS || + m_GuildBankEventLog_Item[TabId].size() >= GUILD_BANK_MAX_LOGS) continue; - } - if (NewEvent->isMoneyEvent()) + + if (NewEvent.isMoneyEvent()) m_GuildBankEventLog_Money.push_front(NewEvent); else m_GuildBankEventLog_Item[TabId].push_front(NewEvent); @@ -1522,43 +1509,24 @@ void Guild::LoadGuildBankEventLogFromDB() if (!m_GuildBankEventLog_Money.empty()) { CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid=%u AND LogGuid < %u", - Id, m_GuildBankEventLog_Money.front()->LogGuid); + Id, m_GuildBankEventLog_Money.front().LogGuid); } for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i) { if (!m_GuildBankEventLog_Item[i].empty()) { CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid=%u AND LogGuid < %u", - Id, m_GuildBankEventLog_Item[i].front()->LogGuid); + Id, m_GuildBankEventLog_Item[i].front().LogGuid); } } } void Guild::UnloadGuildBankEventLog() { - GuildBankEvent *EventLogEntry; - if( !m_GuildBankEventLog_Money.empty() ) - { - do - { - EventLogEntry = *(m_GuildBankEventLog_Money.begin()); - m_GuildBankEventLog_Money.pop_front(); - delete EventLogEntry; - }while( !m_GuildBankEventLog_Money.empty() ); - } + m_GuildBankEventLog_Money.clear(); for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i) - { - if( !m_GuildBankEventLog_Item[i].empty() ) - { - do - { - EventLogEntry = *(m_GuildBankEventLog_Item[i].begin()); - m_GuildBankEventLog_Item[i].pop_front(); - delete EventLogEntry; - }while( !m_GuildBankEventLog_Item[i].empty() ); - } - } + m_GuildBankEventLog_Item[i].clear(); } void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId) @@ -1574,24 +1542,24 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId) data << uint8(m_GuildBankEventLog_Money.size()); // number of log entries for (GuildBankEventLog::const_iterator itr = m_GuildBankEventLog_Money.begin(); itr != m_GuildBankEventLog_Money.end(); ++itr) { - data << uint8((*itr)->LogEntry); - data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER)); - if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY || - (*itr)->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY || - (*itr)->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY || - (*itr)->LogEntry == GUILD_BANK_LOG_UNK1 || - (*itr)->LogEntry == GUILD_BANK_LOG_UNK2) + data << uint8(itr->LogEntry); + data << uint64(MAKE_NEW_GUID(itr->PlayerGuid,0,HIGHGUID_PLAYER)); + if (itr->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY || + itr->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY || + itr->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY || + itr->LogEntry == GUILD_BANK_LOG_UNK1 || + itr->LogEntry == GUILD_BANK_LOG_UNK2) { - data << uint32((*itr)->ItemOrMoney); + data << uint32(itr->ItemOrMoney); } else { - data << uint32((*itr)->ItemOrMoney); - data << uint32((*itr)->ItemStackCount); - if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2) - data << uint8((*itr)->DestTabId); // moved tab + data << uint32(itr->ItemOrMoney); + data << uint32(itr->ItemStackCount); + if (itr->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || itr->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2) + data << uint8(itr->DestTabId); // moved tab } - data << uint32(time(NULL)-(*itr)->TimeStamp); + data << uint32(time(NULL) - itr->TimeStamp); } session->SendPacket(&data); } @@ -1604,24 +1572,24 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId) data << uint8(m_GuildBankEventLog_Item[TabId].size()); for (GuildBankEventLog::const_iterator itr = m_GuildBankEventLog_Item[TabId].begin(); itr != m_GuildBankEventLog_Item[TabId].end(); ++itr) { - data << uint8((*itr)->LogEntry); - data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER)); - if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY || - (*itr)->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY || - (*itr)->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY || - (*itr)->LogEntry == GUILD_BANK_LOG_UNK1 || - (*itr)->LogEntry == GUILD_BANK_LOG_UNK2) + data << uint8(itr->LogEntry); + data << uint64(MAKE_NEW_GUID(itr->PlayerGuid,0,HIGHGUID_PLAYER)); + if (itr->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY || + itr->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY || + itr->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY || + itr->LogEntry == GUILD_BANK_LOG_UNK1 || + itr->LogEntry == GUILD_BANK_LOG_UNK2) { - data << uint32((*itr)->ItemOrMoney); + data << uint32(itr->ItemOrMoney); } else { - data << uint32((*itr)->ItemOrMoney); - data << uint32((*itr)->ItemStackCount); - if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2) - data << uint8((*itr)->DestTabId); // moved tab + data << uint32(itr->ItemOrMoney); + data << uint32(itr->ItemStackCount); + if (itr->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || itr->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2) + data << uint8(itr->DestTabId); // moved tab } - data << uint32(time(NULL)-(*itr)->TimeStamp); + data << uint32(time(NULL) - itr->TimeStamp); } session->SendPacket(&data); } @@ -1630,24 +1598,23 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId) void Guild::LogBankEvent(uint8 LogEntry, uint8 TabId, uint32 PlayerGuidLow, uint32 ItemOrMoney, uint8 ItemStackCount, uint8 DestTabId) { - GuildBankEvent *NewEvent = new GuildBankEvent; + GuildBankEvent NewEvent; - NewEvent->LogGuid = LogMaxGuid++; - NewEvent->LogEntry = LogEntry; - NewEvent->PlayerGuid = PlayerGuidLow; - NewEvent->ItemOrMoney = ItemOrMoney; - NewEvent->ItemStackCount = ItemStackCount; - NewEvent->DestTabId = DestTabId; - NewEvent->TimeStamp = uint32(time(NULL)); + NewEvent.LogGuid = LogMaxGuid++; + NewEvent.LogEntry = LogEntry; + NewEvent.PlayerGuid = PlayerGuidLow; + NewEvent.ItemOrMoney = ItemOrMoney; + NewEvent.ItemStackCount = ItemStackCount; + NewEvent.DestTabId = DestTabId; + NewEvent.TimeStamp = uint32(time(NULL)); - if (NewEvent->isMoneyEvent()) + if (NewEvent.isMoneyEvent()) { if (m_GuildBankEventLog_Money.size() > GUILD_BANK_MAX_LOGS) { - GuildBankEvent *OldEvent = *(m_GuildBankEventLog_Money.begin()); + CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid='%u' AND LogGuid='%u'", + Id, m_GuildBankEventLog_Money.front().LogGuid); m_GuildBankEventLog_Money.pop_front(); - CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid='%u' AND LogGuid='%u'", Id, OldEvent->LogGuid); - delete OldEvent; } m_GuildBankEventLog_Money.push_back(NewEvent); } @@ -1655,15 +1622,14 @@ void Guild::LogBankEvent(uint8 LogEntry, uint8 TabId, uint32 PlayerGuidLow, uint { if (m_GuildBankEventLog_Item[TabId].size() > GUILD_BANK_MAX_LOGS) { - GuildBankEvent *OldEvent = *(m_GuildBankEventLog_Item[TabId].begin()); + CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid='%u' AND LogGuid='%u'", + Id, m_GuildBankEventLog_Item[TabId].front().LogGuid); m_GuildBankEventLog_Item[TabId].pop_front(); - CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid='%u' AND LogGuid='%u'", Id, OldEvent->LogGuid); - delete OldEvent; } m_GuildBankEventLog_Item[TabId].push_back(NewEvent); } CharacterDatabase.PExecute("INSERT INTO guild_bank_eventlog (guildid,LogGuid,LogEntry,TabId,PlayerGuid,ItemOrMoney,ItemStackCount,DestTabId,TimeStamp) VALUES ('%u','%u','%u','%u','%u','%u','%u','%u','" UI64FMTD "')", - Id, NewEvent->LogGuid, uint32(NewEvent->LogEntry), uint32(TabId), NewEvent->PlayerGuid, NewEvent->ItemOrMoney, uint32(NewEvent->ItemStackCount), uint32(NewEvent->DestTabId), NewEvent->TimeStamp); + Id, NewEvent.LogGuid, uint32(NewEvent.LogEntry), uint32(TabId), NewEvent.PlayerGuid, NewEvent.ItemOrMoney, uint32(NewEvent.ItemStackCount), uint32(NewEvent.DestTabId), NewEvent.TimeStamp); } // This will renum guids used at load to prevent always going up until infinit diff --git a/src/game/Guild.h b/src/game/Guild.h index d856ebea1..9794668ee 100644 --- a/src/game/Guild.h +++ b/src/game/Guild.h @@ -458,8 +458,8 @@ class Guild TabListMap m_TabListMap; /** These are actually ordered lists. The first element is the oldest entry.*/ - typedef std::list GuildEventlog; - typedef std::list GuildBankEventLog; + typedef std::list GuildEventlog; + typedef std::list GuildBankEventLog; GuildEventlog m_GuildEventlog; GuildBankEventLog m_GuildBankEventLog_Money; GuildBankEventLog m_GuildBankEventLog_Item[GUILD_BANK_MAX_TABS]; diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index 17e35f973..58c220f8e 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -44,7 +44,11 @@ INSTANTIATE_SINGLETON_2(ObjectAccessor, CLASS_LOCK); INSTANTIATE_CLASS_MUTEX(ObjectAccessor, ACE_Thread_Mutex); ObjectAccessor::ObjectAccessor() {} -ObjectAccessor::~ObjectAccessor() {} +ObjectAccessor::~ObjectAccessor() +{ + for(Player2CorpsesMapType::const_iterator itr = i_player2corpse.begin(); itr != i_player2corpse.end(); ++itr) + delete itr->second; +} Creature* ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const &u, uint64 guid) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 0a50c3581..693bac142 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -170,6 +170,9 @@ ObjectMgr::~ObjectMgr() for (GuildMap::iterator itr = mGuildMap.begin(); itr != mGuildMap.end(); ++itr) delete itr->second; + for (ArenaTeamMap::iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr) + delete itr->second; + for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr) itr->second.Clear(); diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index cd0e1db02..7bc2c7cef 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -194,9 +194,12 @@ void PetAI::UpdateAI(const uint32 diff) } } + // Autocast (casted only in combat or persistent spells in any state) if (m_creature->GetGlobalCooldown() == 0 && !m_creature->IsNonMeleeSpellCasted(false)) { - //Autocast + typedef std::vector > TargetSpellList; + TargetSpellList targetSpellStore; + for (uint8 i = 0; i < m_creature->GetPetAutoSpellSize(); ++i) { uint32 spellID = m_creature->GetPetAutoSpellOnPos(i); @@ -210,11 +213,29 @@ void PetAI::UpdateAI(const uint32 diff) // ignore some combinations of combat state and combat/noncombat spells if (!inCombat) { + // ignore attacking spells, and allow only self/around spells if (!IsPositiveSpell(spellInfo->Id)) continue; + + // non combat spells allowed + // only pet spells have IsNonCombatSpell and not fit this reqs: + // Consume Shadows, Lesser Invisibility, so ignore checks for its + if (!IsNonCombatSpell(spellInfo)) + { + // allow only spell without spell cost or with spell cost but not duration limit + int32 duration = GetSpellDuration(spellInfo); + if ((spellInfo->manaCost || spellInfo->ManaCostPercentage || spellInfo->manaPerSecond) && duration > 0) + continue; + + // allow only spell without cooldown > duration + int32 cooldown = GetSpellRecoveryTime(spellInfo); + if (cooldown >= 0 && duration >= 0 && cooldown > duration) + continue; + } } else { + // just ignore non-combat spells if (IsNonCombatSpell(spellInfo)) continue; } @@ -223,7 +244,7 @@ void PetAI::UpdateAI(const uint32 diff) if (inCombat && !m_creature->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(m_creature->getVictim())) { - m_targetSpellStore.push_back(std::make_pair(m_creature->getVictim(), spell)); + targetSpellStore.push_back(std::make_pair(m_creature->getVictim(), spell)); continue; } else @@ -239,7 +260,7 @@ void PetAI::UpdateAI(const uint32 diff) if(spell->CanAutoCast(Target)) { - m_targetSpellStore.push_back(std::make_pair(Target, spell)); + targetSpellStore.push_back(std::make_pair(Target, spell)); spellUsed = true; break; } @@ -250,14 +271,14 @@ void PetAI::UpdateAI(const uint32 diff) } //found units to cast on to - if (!m_targetSpellStore.empty()) + if (!targetSpellStore.empty()) { - uint32 index = urand(0, m_targetSpellStore.size() - 1); + uint32 index = urand(0, targetSpellStore.size() - 1); - Spell* spell = m_targetSpellStore[index].second; - Unit* target = m_targetSpellStore[index].first; + Spell* spell = targetSpellStore[index].second; + Unit* target = targetSpellStore[index].first; - m_targetSpellStore.erase(m_targetSpellStore.begin() + index); + targetSpellStore.erase(targetSpellStore.begin() + index); SpellCastTargets targets; targets.setUnitTarget( target ); @@ -276,11 +297,10 @@ void PetAI::UpdateAI(const uint32 diff) spell->prepare(&targets); } - while (!m_targetSpellStore.empty()) - { - delete m_targetSpellStore.begin()->second; - m_targetSpellStore.erase(m_targetSpellStore.begin()); - } + + // deleted cached Spell objects + for(TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr) + delete itr->second; } } diff --git a/src/game/PetAI.h b/src/game/PetAI.h index 797138539..90f0748df 100644 --- a/src/game/PetAI.h +++ b/src/game/PetAI.h @@ -52,8 +52,5 @@ class MANGOS_DLL_DECL PetAI : public CreatureAI bool inCombat; std::set m_AllySet; uint32 m_updateAlliesTimer; - - typedef std::pair TargetSpellPair; - std::vector m_targetSpellStore; }; #endif diff --git a/src/game/Player.cpp b/src/game/Player.cpp index a9f228f12..486900975 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -689,14 +689,14 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 switch(iProto->Spells[0].SpellCategory) { case 11: // food - if(iProto->Stackable > 4) - count = 4; + count = getClass()==CLASS_DEATH_KNIGHT ? 10 : 4; break; case 59: // drink - if(iProto->Stackable > 2) - count = 2; + count = 2; break; } + if(iProto->Stackable < count) + count = iProto->Stackable; } StoreNewItemInBestSlots(item_id, count); @@ -13853,61 +13853,6 @@ void Player::SendQuestUpdateAddCreatureOrGo( Quest const* pQuest, uint64 guid, u /*** LOAD SYSTEM ***/ /*********************************************************/ -bool Player::MinimalLoadFromDB( QueryResult *result, uint32 guid ) -{ - bool delete_result = true; - if (!result) - { - // 0 1 2 3 4 5 6 7 8 9 10 11 - result = CharacterDatabase.PQuery("SELECT guid, data, name, position_x, position_y, position_z, map, totaltime, leveltime, at_login, zone, level FROM characters WHERE guid = '%u'",guid); - if (!result) - return false; - } - else - delete_result = false; - - Field *fields = result->Fetch(); - - if (!LoadValues( fields[1].GetString())) - { - sLog.outError("Player #%d have broken data in `data` field. Can't be loaded for character list.",GUID_LOPART(guid)); - if (delete_result) - delete result; - return false; - } - - // overwrite possible wrong/corrupted guid - SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)); - - m_name = fields[2].GetCppString(); - - Relocate(fields[3].GetFloat(),fields[4].GetFloat(),fields[5].GetFloat()); - SetLocationMapId(fields[6].GetUInt32()); - - // the instance id is not needed at character enum - - m_Played_time[PLAYED_TIME_TOTAL] = fields[7].GetUInt32(); - m_Played_time[PLAYED_TIME_LEVEL] = fields[8].GetUInt32(); - - m_atLoginFlags = fields[9].GetUInt32(); - - // I don't see these used anywhere .. - /*_LoadGroup(); - - _LoadBoundInstances();*/ - - if (delete_result) - delete result; - - for (int i = 0; i < PLAYER_SLOTS_COUNT; ++i) - m_items[i] = NULL; - - if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) - m_deathState = DEAD; - - return true; -} - void Player::_LoadDeclinedNames(QueryResult* result) { if(!result) @@ -14762,7 +14707,7 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff) delete result; } - if(getClass() == CLASS_WARRIOR) + if(getClass() == CLASS_WARRIOR && !HasAuraType(SPELL_AURA_MOD_SHAPESHIFT)) CastSpell(this,SPELL_ID_PASSIVE_BATTLE_STANCE,true); } @@ -15564,26 +15509,9 @@ void Player::SaveToDB() // first save/honor gain after midnight will also update the player's honor fields UpdateHonorFields(); - int is_save_resting = HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0; - //save, far from tavern/city - //save, but in tavern/city sLog.outDebug("The value of player %s at save: ", m_name.c_str()); outDebugValues(); - // save state (after auras removing), if aura remove some flags then it must set it back by self) - uint32 tmp_bytes = GetUInt32Value(UNIT_FIELD_BYTES_1); - uint32 tmp_bytes2 = GetUInt32Value(UNIT_FIELD_BYTES_2); - uint32 tmp_flags = GetUInt32Value(UNIT_FIELD_FLAGS); - uint32 tmp_pflags = GetUInt32Value(PLAYER_FLAGS); - uint32 tmp_displayid = GetDisplayId(); - - // Set player sit state to standing on save, also stealth and shifted form - SetByteValue(UNIT_FIELD_BYTES_1, 0, UNIT_STAND_STATE_STAND); - SetByteValue(UNIT_FIELD_BYTES_2, 3, 0); // shapeshift - RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - - bool inworld = IsInWorld(); - CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("DELETE FROM characters WHERE guid = '%u'",GetGUIDLow()); @@ -15638,66 +15566,47 @@ void Player::SaveToDB() ss << "', "; - ss << m_taxi; // string with TaxiMaskSize numbers + ss << m_taxi << ", "; // string with TaxiMaskSize numbers - ss << ", "; - ss << (inworld ? 1 : 0); + ss << (IsInWorld() ? 1 : 0) << ", "; - ss << ", "; - ss << m_cinematic; + ss << m_cinematic << ", "; - ss << ", "; - ss << m_Played_time[PLAYED_TIME_TOTAL]; - ss << ", "; - ss << m_Played_time[PLAYED_TIME_LEVEL]; + ss << m_Played_time[PLAYED_TIME_TOTAL] << ", "; + ss << m_Played_time[PLAYED_TIME_LEVEL] << ", "; - ss << ", "; - ss << finiteAlways(m_rest_bonus); - ss << ", "; - ss << (uint64)time(NULL); - ss << ", "; - ss << is_save_resting; - ss << ", "; - ss << m_resetTalentsCost; - ss << ", "; - ss << (uint64)m_resetTalentsTime; + ss << finiteAlways(m_rest_bonus) << ", "; + ss << (uint64)time(NULL) << ", "; + ss << (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0) << ", "; + //save, far from tavern/city + //save, but in tavern/city + ss << m_resetTalentsCost << ", "; + ss << (uint64)m_resetTalentsTime << ", "; - ss << ", "; - ss << finiteAlways(m_movementInfo.t_x); - ss << ", "; - ss << finiteAlways(m_movementInfo.t_y); - ss << ", "; - ss << finiteAlways(m_movementInfo.t_z); - ss << ", "; - ss << finiteAlways(m_movementInfo.t_o); - ss << ", "; + ss << finiteAlways(m_movementInfo.t_x) << ", "; + ss << finiteAlways(m_movementInfo.t_y) << ", "; + ss << finiteAlways(m_movementInfo.t_z) << ", "; + ss << finiteAlways(m_movementInfo.t_o) << ", "; if (m_transport) ss << m_transport->GetGUIDLow(); else ss << "0"; + ss << ", "; - ss << ", "; - ss << m_ExtraFlags; + ss << m_ExtraFlags << ", "; - ss << ", "; - ss << uint32(m_stableSlots); // to prevent save uint8 as char + ss << uint32(m_stableSlots) << ", "; // to prevent save uint8 as char - ss << ", "; - ss << uint32(m_atLoginFlags); + ss << uint32(m_atLoginFlags) << ", "; - ss << ", "; - ss << GetZoneId(); + ss << GetZoneId() << ", "; - ss << ", "; - ss << (uint64)m_deathExpireTime; + ss << (uint64)m_deathExpireTime << ", '"; - ss << ", '"; - ss << m_taxi.SaveTaxiDestinationsToString(); - ss << "', '0', "; - ss << GetBattleGroundId(); - ss << ", "; - ss << GetBGTeam(); - ss << ", "; + ss << m_taxi.SaveTaxiDestinationsToString() << "', "; + ss << "'0', "; // arena_pending_points + ss << GetBattleGroundId() << ", "; + ss << GetBGTeam() << ", "; ss << m_bgEntryPoint.mapid << ", " << finiteAlways(m_bgEntryPoint.coord_x) << ", " << finiteAlways(m_bgEntryPoint.coord_y) << ", " @@ -15724,12 +15633,6 @@ void Player::SaveToDB() CharacterDatabase.CommitTransaction(); - // restore state (before aura apply, if aura remove flag then aura must set it ack by self) - SetUInt32Value(UNIT_FIELD_BYTES_1, tmp_bytes); - SetUInt32Value(UNIT_FIELD_BYTES_2, tmp_bytes2); - SetUInt32Value(UNIT_FIELD_FLAGS, tmp_flags); - SetUInt32Value(PLAYER_FLAGS, tmp_pflags); - // save pet (hunter pet level and experience and all type pets health/mana). if(Pet* pet = GetPet()) pet->SavePetToDB(PET_SAVE_AS_CURRENT); @@ -15798,26 +15701,13 @@ void Player::_SaveAuras() SpellEntry const *spellInfo = itr2->second->GetSpellProto(); - //skip all auras from spells that are passive or need a shapeshift - if (!(itr2->second->IsPassive() || itr2->second->IsRemovedOnShapeLost())) + //skip all auras from spells that are passive + //do not save single target auras (unless they were cast by the player) + if (!itr2->second->IsPassive() && (itr2->second->GetCasterGUID() == GetGUID() || !itr2->second->IsSingleTarget())) { - //do not save single target auras (unless they were cast by the player) - if (!(itr2->second->GetCasterGUID() != GetGUID() && itr2->second->IsSingleTarget())) - { - uint8 i; - // or apply at cast SPELL_AURA_MOD_SHAPESHIFT or SPELL_AURA_MOD_STEALTH auras - for (i = 0; i < 3; ++i) - if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT || - spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_STEALTH) - break; - - if (i == 3) - { - CharacterDatabase.PExecute("INSERT INTO character_aura (guid,caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges) " - "VALUES ('%u', '" UI64FMTD "' ,'%u', '%u', '%u', '%d', '%d', '%d', '%d')", - GetGUIDLow(), itr2->second->GetCasterGUID(), (uint32)itr2->second->GetId(), (uint32)itr2->second->GetEffIndex(), stackCounter, itr2->second->GetModifier()->m_amount,int(itr2->second->GetAuraMaxDuration()),int(itr2->second->GetAuraDuration()),int(itr2->second->GetAuraCharges())); - } - } + CharacterDatabase.PExecute("INSERT INTO character_aura (guid,caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges) " + "VALUES ('%u', '" UI64FMTD "' ,'%u', '%u', '%u', '%d', '%d', '%d', '%d')", + GetGUIDLow(), itr2->second->GetCasterGUID(), (uint32)itr2->second->GetId(), (uint32)itr2->second->GetEffIndex(), stackCounter, itr2->second->GetModifier()->m_amount,int(itr2->second->GetAuraMaxDuration()),int(itr2->second->GetAuraDuration()),int(itr2->second->GetAuraCharges())); } if(itr == auras.end()) @@ -18146,11 +18036,6 @@ void Player::SendInitialPacketsBeforeAddToMap() m_reputationMgr.SendInitialReputations(); m_achievementMgr.SendAllAchievementData(); - // update zone - uint32 newzone, newarea; - GetZoneAndAreaId(newzone,newarea); - UpdateZone(newzone,newarea); // also call SendInitWorldStates(); - SendEquipmentSetList(); data.Initialize(SMSG_LOGIN_SETTIMESPEED, 4 + 4 + 4); @@ -18160,7 +18045,7 @@ void Player::SendInitialPacketsBeforeAddToMap() GetSession()->SendPacket( &data ); // set fly flag if in fly form or taxi flight to prevent visually drop at ground in showup moment - if(HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) || isInFlight()) + if(HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) || HasAuraType(SPELL_AURA_FLY) || isInFlight()) m_movementInfo.AddMovementFlag(MOVEMENTFLAG_FLYING2); m_mover = this; @@ -18168,6 +18053,11 @@ void Player::SendInitialPacketsBeforeAddToMap() void Player::SendInitialPacketsAfterAddToMap() { + // update zone + uint32 newzone, newarea; + GetZoneAndAreaId(newzone,newarea); + UpdateZone(newzone,newarea); // also call SendInitWorldStates(); + WorldPacket data(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement data << uint32(0x00000000); // on blizz it increments periodically GetSession()->SendPacket(&data); @@ -19103,13 +18993,6 @@ void Player::SetClientControl(Unit* target, uint8 allowMove) void Player::UpdateZoneDependentAuras( uint32 newZone ) { - // remove new continent flight forms - if( !IsAllowUseFlyMountsHere() ) - { - RemoveSpellsCausingAura(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED); - RemoveSpellsCausingAura(SPELL_AURA_FLY); - } - // Some spells applied at enter into zone (with subzones), aura removed in UpdateAreaDependentAuras that called always at zone->area update SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAreaMapBounds(newZone); for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) @@ -19682,13 +19565,11 @@ uint32 Player::CalculateTalentsPoints() const return uint32(talentPointsForLevel * sWorld.getRate(RATE_TALENT)); } -bool Player::IsAllowUseFlyMountsHere() const +bool Player::IsKnowHowFlyIn(uint32 mapid, uint32 zone) const { - if (isGameMaster()) - return true; - - uint32 v_map = GetVirtualMapForMapAndZone(GetMapId(), GetZoneId()); - return v_map == 530 || v_map == 571 && HasSpell(54197); + // continent checked in SpellMgr::GetSpellAllowedInLocationError at cast and area update + uint32 v_map = GetVirtualMapForMapAndZone(mapid, zone); + return v_map != 571 || HasSpell(54197); // Cold Weather Flying } struct DoPlayerLearnSpell diff --git a/src/game/Player.h b/src/game/Player.h index 7d2490b05..1ac5ea4c3 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1351,7 +1351,6 @@ class MANGOS_DLL_SPEC Player : public Unit bool LoadFromDB(uint32 guid, SqlQueryHolder *holder); - bool MinimalLoadFromDB(QueryResult *result, uint32 guid); static bool LoadValuesArrayFromDB(Tokens& data,uint64 guid); static uint32 GetUInt32ValueFromArray(Tokens const& data, uint16 index); static float GetFloatValueFromArray(Tokens const& data, uint16 index); @@ -2065,7 +2064,7 @@ class MANGOS_DLL_SPEC Player : public Unit bool CanFly() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); } bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING); } - bool IsAllowUseFlyMountsHere() const; + bool IsKnowHowFlyIn(uint32 mapid, uint32 zone) const; void SetClientControl(Unit* target, uint8 allowMove); void SetMover(Unit* target) { m_mover = target ? target : this; } diff --git a/src/game/PlayerDump.cpp b/src/game/PlayerDump.cpp index 79201503b..27ff17502 100644 --- a/src/game/PlayerDump.cpp +++ b/src/game/PlayerDump.cpp @@ -581,7 +581,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s ROLLBACK(DUMP_FILE_BROKEN); if(!changetoknth(vals, ITEM_FIELD_OWNER+1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); - if(!changetokGuid(vals, ITEM_FIELD_ITEM_TEXT_ID+1, itemTexts, objmgr.m_ItemTextId)) + if(!changetokGuid(vals, ITEM_FIELD_ITEM_TEXT_ID+1, itemTexts, objmgr.m_ItemTextId,true)) ROLLBACK(DUMP_FILE_BROKEN); if(!changenth(line, 3, vals.c_str())) ROLLBACK(DUMP_FILE_BROKEN); diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index f6489e988..2e138e517 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -2389,6 +2389,7 @@ enum SummonType SUMMON_TYPE_UNKNOWN5 = 409, SUMMON_TYPE_UNKNOWN2 = 427, SUMMON_TYPE_POSESSED2 = 428, + SUMMON_TYPE_INFERNO = 711, SUMMON_TYPE_GUARDIAN2 = 1161, SUMMON_TYPE_ELEMENTAL = 1561, SUMMON_TYPE_FORCE_OF_NATURE = 1562 diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index eafee4451..5c660c1ca 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1679,12 +1679,19 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) case TARGET_ALL_ENEMY_IN_AREA_INSTANT: { // targets the ground, not the units in the area - if (m_spellInfo->Effect[i]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) + switch(m_spellInfo->Effect[i]) { - FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); + case SPELL_EFFECT_PERSISTENT_AREA_AURA: + break; + case SPELL_EFFECT_SUMMON: + TagUnitMap.push_back(m_caster); + break; + default: + FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); - // exclude caster (this can be important if this not original caster) - TagUnitMap.remove(m_caster); + // exclude caster (this can be important if this not original caster) + TagUnitMap.remove(m_caster); + break; } break; } @@ -1705,9 +1712,9 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) case TARGET_ALL_RAID_AROUND_CASTER: { if(m_spellInfo->Id == 57669) // Replenishment (special target selection) - FillRaidOrPartyManaPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 10, true, false, false); - else if (m_spellInfo->Id==52759) //Ancestral Awakening (special target selection) - FillRaidOrPartyHealthPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 1, true, false, false); + FillRaidOrPartyManaPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 10, true, false, true); + else if (m_spellInfo->Id==52759) // Ancestral Awakening (special target selection) + FillRaidOrPartyHealthPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 1, true, false, true); else FillRaidOrPartyTargets(TagUnitMap, m_caster, m_caster, radius, true, true, true); break; @@ -4324,6 +4331,7 @@ SpellCastResult Spell::CheckCast(bool strict) case SUMMON_TYPE_DEMON: case SUMMON_TYPE_SUMMON: case SUMMON_TYPE_ELEMENTAL: + case SUMMON_TYPE_INFERNO: { if(m_caster->GetPetGUID()) return SPELL_FAILED_ALREADY_HAVE_SUMMON; @@ -4547,16 +4555,16 @@ SpellCastResult Spell::CheckCast(bool strict) break; } - case SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED: case SPELL_AURA_FLY: + case SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED: { - // not allow cast fly spells at old maps by players (all spells is self target) - if(m_caster->GetTypeId() == TYPEID_PLAYER) + // not allow cast fly spells if not have req. skills (all spells is self target) + // allow always ghost flight spells + if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->isAlive()) { - if( !((Player*)m_caster)->IsAllowUseFlyMountsHere() ) - return SPELL_FAILED_NOT_HERE; + if (!((Player*)m_caster)->IsKnowHowFlyIn(m_caster->GetMapId(),zone)) + return m_IsTriggeredSpell ? SPELL_FAILED_DONT_REPORT : SPELL_FAILED_NOT_HERE; } - break; } case SPELL_AURA_PERIODIC_MANA_LEECH: diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 78fe38460..dbeb81a22 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -1027,7 +1027,7 @@ void Aura::_AddAura() } } -void Aura::_RemoveAura() +bool Aura::_RemoveAura() { // Remove all triggered by aura spells vs unlimited duration // except same aura replace case @@ -1051,10 +1051,10 @@ void Aura::_RemoveAura() uint8 slot = GetAuraSlot(); if(slot >= MAX_AURAS) // slot not set - return; + return false; if(m_target->GetVisibleAura(slot) == 0) - return; + return false; bool lastaura = true; @@ -1075,96 +1075,98 @@ void Aura::_RemoveAura() } // only remove icon when the last aura of the spell is removed (current aura already removed from list) - if (lastaura) + if (!lastaura) + return false; + + // unregister aura diminishing (and store last time) + if (getDiminishGroup() != DIMINISHING_NONE ) + m_target->ApplyDiminishingAura(getDiminishGroup(), false); + + SetAura(true); + SetAuraFlags(AFLAG_NONE); + SetAuraLevel(0); + SendAuraUpdate(true); + + // update for out of range group members + m_target->UpdateAuraForGroup(slot); + + //***************************************************** + // Update target aura state flag (at last aura remove) + //***************************************************** + // Enrage aura state + if(m_spellProto->Dispel == DISPEL_ENRAGE) + m_target->ModifyAuraState(AURA_STATE_ENRAGE, false); + + uint32 removeState = 0; + uint64 removeFamilyFlag = m_spellProto->SpellFamilyFlags; + uint32 removeFamilyFlag2 = m_spellProto->SpellFamilyFlags2; + switch(m_spellProto->SpellFamilyName) { - // unregister aura diminishing (and store last time) - if (getDiminishGroup() != DIMINISHING_NONE ) - m_target->ApplyDiminishingAura(getDiminishGroup(), false); - - SetAura(true); - SetAuraFlags(AFLAG_NONE); - SetAuraLevel(0); - SendAuraUpdate(true); - - // update for out of range group members - m_target->UpdateAuraForGroup(slot); - - //***************************************************** - // Update target aura state flag (at last aura remove) - //***************************************************** - // Enrage aura state - if(m_spellProto->Dispel == DISPEL_ENRAGE) - m_target->ModifyAuraState(AURA_STATE_ENRAGE, false); - - uint32 removeState = 0; - uint64 removeFamilyFlag = m_spellProto->SpellFamilyFlags; - uint32 removeFamilyFlag2 = m_spellProto->SpellFamilyFlags2; - switch(m_spellProto->SpellFamilyName) + case SPELLFAMILY_PALADIN: + if (IsSealSpell(m_spellProto)) + removeState = AURA_STATE_JUDGEMENT; // Update Seals information + break; + case SPELLFAMILY_WARLOCK: + // Conflagrate aura state on Immolate and Shadowflame, + if ((m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000004)) || + (m_spellProto->SpellFamilyFlags2 & 0x00000002)) { - case SPELLFAMILY_PALADIN: - if (IsSealSpell(m_spellProto)) - removeState = AURA_STATE_JUDGEMENT; // Update Seals information - break; - case SPELLFAMILY_WARLOCK: - // Conflagrate aura state on Immolate and Shadowflame, - if ((m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000004)) || - (m_spellProto->SpellFamilyFlags2 & 0x00000002)) - { - removeFamilyFlag = UI64LIT(0x0000000000000004); - removeFamilyFlag2 = 0x00000002; - removeState = AURA_STATE_CONFLAGRATE; - } - break; - case SPELLFAMILY_DRUID: - if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000400)) - removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions) - else if(m_spellProto->SpellFamilyFlags & UI64LIT(0x50)) - { - removeFamilyFlag = 0x50; - removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state - } - break; - case SPELLFAMILY_WARRIOR: - if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0004000000000000)) - removeState = AURA_STATE_WARRIOR_VICTORY_RUSH; // Victorious - break; - case SPELLFAMILY_ROGUE: - if(m_spellProto->SpellFamilyFlags & UI64LIT(0x10000)) - removeState = AURA_STATE_DEADLY_POISON; // Deadly poison aura state - break; - case SPELLFAMILY_HUNTER: - if(m_spellProto->SpellFamilyFlags & UI64LIT(0x1000000000000000)) - removeState = AURA_STATE_FAERIE_FIRE; // Sting (hunter versions) - + removeFamilyFlag = UI64LIT(0x0000000000000004); + removeFamilyFlag2 = 0x00000002; + removeState = AURA_STATE_CONFLAGRATE; } - // Remove state (but need check other auras for it) - if (removeState) + break; + case SPELLFAMILY_DRUID: + if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000400)) + removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions) + else if(m_spellProto->SpellFamilyFlags & UI64LIT(0x50)) { - bool found = false; - Unit::AuraMap& Auras = m_target->GetAuras(); - for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i) - { - SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto(); - if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName && - (auraSpellInfo->SpellFamilyFlags & removeFamilyFlag || auraSpellInfo->SpellFamilyFlags2 & removeFamilyFlag2)) - { - found = true; - break; - } - } - // this has been last aura - if(!found) - m_target->ModifyAuraState(AuraState(removeState), false); + removeFamilyFlag = 0x50; + removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state } + break; + case SPELLFAMILY_WARRIOR: + if(m_spellProto->SpellFamilyFlags & UI64LIT(0x0004000000000000)) + removeState = AURA_STATE_WARRIOR_VICTORY_RUSH; // Victorious + break; + case SPELLFAMILY_ROGUE: + if(m_spellProto->SpellFamilyFlags & UI64LIT(0x10000)) + removeState = AURA_STATE_DEADLY_POISON; // Deadly poison aura state + break; + case SPELLFAMILY_HUNTER: + if(m_spellProto->SpellFamilyFlags & UI64LIT(0x1000000000000000)) + removeState = AURA_STATE_FAERIE_FIRE; // Sting (hunter versions) - // reset cooldown state for spells - if(caster && caster->GetTypeId() == TYPEID_PLAYER) - { - if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE ) - // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases) - ((Player*)caster)->SendCooldownEvent(GetSpellProto()); - } } + // Remove state (but need check other auras for it) + if (removeState) + { + bool found = false; + Unit::AuraMap& Auras = m_target->GetAuras(); + for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i) + { + SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto(); + if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName && + (auraSpellInfo->SpellFamilyFlags & removeFamilyFlag || auraSpellInfo->SpellFamilyFlags2 & removeFamilyFlag2)) + { + found = true; + break; + } + } + // this has been last aura + if(!found) + m_target->ModifyAuraState(AuraState(removeState), false); + } + + // reset cooldown state for spells + if(caster && caster->GetTypeId() == TYPEID_PLAYER) + { + if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE ) + // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases) + ((Player*)caster)->SendCooldownEvent(GetSpellProto()); + } + + return true; } void Aura::SendAuraUpdate(bool remove) @@ -3314,9 +3316,17 @@ void Aura::HandleModCharm(bool apply, bool Real) CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); if(cinfo && cinfo->type == CREATURE_TYPE_DEMON) { - //does not appear to have relevance. Why code added initially? See note below at !apply - //to prevent client crash - //m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048); + // creature with pet number expected have class set + if(m_target->GetByteValue(UNIT_FIELD_BYTES_0, 1)==0) + { + if(cinfo->unit_class==0) + sLog.outErrorDb("Creature (Entry: %u) have unit_class = 0 but used in charmed spell, that will be result client crash.",cinfo->Entry); + else + sLog.outError("Creature (Entry: %u) have unit_class = %u but at charming have class 0!!! that will be result client crash.",cinfo->Entry,cinfo->unit_class); + + m_target->SetByteValue(UNIT_FIELD_BYTES_0, 1, CLASS_MAGE); + } + //just to enable stat window charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true); //if charmed two demons the same session, the 2nd gets the 1st one's name @@ -3352,13 +3362,8 @@ void Aura::HandleModCharm(bool apply, bool Real) // restore UNIT_FIELD_BYTES_0 if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON) { - //does not appear to have relevance. Why code added initially? Class, gender, powertype should be same. - //db field removed and replaced with better way to set class, restore using this if problems - /*CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon(); - if(cainfo && cainfo->bytes0 != 0) - m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0); - else - m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);*/ + // DB must have proper class set in field at loading, not req. restore, including workaround case at apply + // m_target->SetByteValue(UNIT_FIELD_BYTES_0, 1, cinfo->unit_class); if(m_target->GetCharmInfo()) m_target->GetCharmInfo()->SetPetNumber(0, true); @@ -5555,6 +5560,107 @@ void Aura::HandleShapeshiftBoosts(bool apply) m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/ } +void Aura::HandleSpellSpecificBoosts(bool apply) +{ + uint32 spellId1 = 0; + uint32 spellId2 = 0; + uint32 spellId3 = 0; + + switch(GetSpellProto()->SpellFamilyName) + { + case SPELLFAMILY_WARRIOR: + { + if(!apply) + { + // Remove Blood Frenzy only if target no longer has any Deep Wound or Rend (applying is handled by procs) + if (GetSpellProto()->Mechanic != MECHANIC_BLEED) + return; + + // If target still has one of Warrior's bleeds, do nothing + Unit::AuraList const& PeriodicDamage = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); + for(Unit::AuraList::const_iterator i = PeriodicDamage.begin(); i != PeriodicDamage.end(); ++i) + if( (*i)->GetCasterGUID() == GetCasterGUID() && + (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARRIOR && + (*i)->GetSpellProto()->Mechanic == MECHANIC_BLEED) + return; + + spellId1 = 30069; + spellId2 = 30070; + } + break; + } + case SPELLFAMILY_HUNTER: + { + if(GetSpellSpecific(m_spellProto->Id) != SPELL_ASPECT) + return; + + // Aspect of the Dragonhawk dodge + if (GetSpellProto()->SpellFamilyFlags2 & 0x00001000) + spellId1 = 61848; + else + return; + + break; + } + case SPELLFAMILY_PALADIN: + { + // Only process on player casting paladin aura + // all aura bonuses applied also in aura area effect way to caster + if (GetCasterGUID() != m_target->GetGUID() || !IS_PLAYER_GUID(GetCasterGUID())) + return; + + if (GetSpellSpecific(m_spellProto->Id) != SPELL_AURA) + return; + + // Sanctified Retribution and Swift Retribution (they share one aura), but not Retribution Aura (already gets modded) + if ((GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000008))==0) + spellId1 = 63531; // placeholder for talent spell mods + // Improved Concentration Aura (auras bonus) + spellId2 = 63510; // placeholder for talent spell mods + // Improved Devotion Aura (auras bonus) + spellId3 = 63514; // placeholder for talent spell mods + break; + } + case SPELLFAMILY_DEATHKNIGHT: + { + if (GetSpellSpecific(m_spellProto->Id) != SPELL_PRESENCE) + return; + + // Frost Presence health + if (GetId() == 48263) + spellId1 = 61261; + // Unholy Presence move speed + else if (GetId() == 48265) + spellId1 = 49772; + else + return; + + break; + } + default: + return; + } + + 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 (spellId3) + m_target->CastSpell(m_target, spellId3, true, NULL, this); + } + else + { + if (spellId1) + m_target->RemoveAurasByCasterSpell(spellId1, GetCasterGUID()); + if (spellId2) + m_target->RemoveAurasByCasterSpell(spellId2, GetCasterGUID()); + if (spellId3) + m_target->RemoveAurasByCasterSpell(spellId3, GetCasterGUID()); + } +} + void Aura::HandleAuraEmpathy(bool apply, bool /*Real*/) { if(m_target->GetTypeId() != TYPEID_UNIT) @@ -5751,14 +5857,6 @@ void Aura::HandleSpiritOfRedemption( bool apply, bool Real ) void Aura::CleanupTriggeredSpells() { - if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000001000000020))) - { - // Blood Frenzy remove - m_target->RemoveAurasDueToSpell(30069); - m_target->RemoveAurasDueToSpell(30070); - return; - } - uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()]; if(!tSpellId) return; diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 760145b8d..6fc9d83a9 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -297,7 +297,7 @@ class MANGOS_DLL_SPEC Aura void ApplyModifier(bool apply, bool Real = false); void _AddAura(); - void _RemoveAura(); + bool _RemoveAura(); bool IsUpdated() { return m_updated; } void SetUpdated(bool val) { m_updated = val; } @@ -311,6 +311,7 @@ class MANGOS_DLL_SPEC Aura // add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras void HandleShapeshiftBoosts(bool apply); + void HandleSpellSpecificBoosts(bool apply); // Allow Apply Aura Handler to modify and access m_AuraDRGroup void setDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 22642086a..6012c6a01 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1856,6 +1856,28 @@ void Spell::EffectDummy(uint32 i) m_caster->CastSpell(m_caster, 51209, true); return; } + // Death Strike + else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000010)) + { + uint32 count = 0; + Unit::AuraMap const& auras = unitTarget->GetAuras(); + for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) + { + if(itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE && + itr->second->GetCasterGUID() == m_caster->GetGUID() && + IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex())) + { + ++count; + // max. 15% + if(count == 3) + break; + } + } + + int32 bp = count * m_caster->GetMaxHealth() * m_spellInfo->DmgMultiplier[0] / 100; + m_caster->CastCustomSpell(m_caster, 45470, &bp, NULL, NULL, true); + return; + } break; } @@ -1942,7 +1964,7 @@ void Spell::EffectTriggerSpell(uint32 i) // special cases switch(triggered_spell_id) { - // Vanish + // Vanish (not exist) case 18461: { m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); @@ -1991,7 +2013,8 @@ void Spell::EffectTriggerSpell(uint32 i) // Brittle Armor - (need add max stack of 24575 Brittle Armor) case 29284: { - const SpellEntry *spell = sSpellStore.LookupEntry(24575); + // Brittle Armor + SpellEntry const* spell = sSpellStore.LookupEntry(24575); if (!spell) return; @@ -2002,7 +2025,8 @@ void Spell::EffectTriggerSpell(uint32 i) // Mercurial Shield - (need add max stack of 26464 Mercurial Shield) case 29286: { - const SpellEntry *spell = sSpellStore.LookupEntry(26464); + // Mercurial Shield + SpellEntry const* spell = sSpellStore.LookupEntry(26464); if (!spell) return; @@ -2017,7 +2041,7 @@ void Spell::EffectTriggerSpell(uint32 i) return; } // Cloak of Shadows - case 35729 : + case 35729: { Unit::AuraMap& Auras = m_caster->GetAuras(); for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter) @@ -2348,7 +2372,7 @@ void Spell::EffectApplyAura(uint32 i) return; // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) - if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 && + if( !unitTarget->isAlive() && !IsDeathPersistentSpell(m_spellInfo) && (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) ) return; @@ -2391,7 +2415,7 @@ void Spell::EffectApplyAura(uint32 i) return; // Prayer of Mending (jump animation), we need formal caster instead original for correct animation - if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00002000000000))) + if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000002000000000))) m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID); } @@ -3260,12 +3284,17 @@ void Spell::EffectSummonType(uint32 i) case SUMMON_TYPE_POSESSED2: case SUMMON_TYPE_FORCE_OF_NATURE: case SUMMON_TYPE_GUARDIAN2: - EffectSummonGuardian(i); + // Jewelery statue case (totem like) + if(m_spellInfo->SpellIconID == 2056) + EffectSummonTotem(i); + else + EffectSummonGuardian(i); break; case SUMMON_TYPE_WILD: EffectSummonWild(i); break; case SUMMON_TYPE_DEMON: + case SUMMON_TYPE_INFERNO: EffectSummonDemon(i); break; case SUMMON_TYPE_SUMMON: @@ -3311,6 +3340,16 @@ void Spell::EffectSummon(uint32 i) if(m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry)) { + // Summon in dest location + float x, y, z; + if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) + { + x = m_targets.m_destX; + y = m_targets.m_destY; + z = m_targets.m_destZ; + spawnCreature->Relocate(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, -m_caster->GetOrientation()); + } + // set timer for unsummon int32 duration = GetSpellDuration(m_spellInfo); if(duration > 0) @@ -3508,25 +3547,12 @@ void Spell::EffectDispel(uint32 i) } m_caster->SendMessageToSet(&data, true); - // On succes dispel + // On success dispel // Devour Magic if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC) { - uint32 heal_spell = 0; - switch (m_spellInfo->Id) - { - case 19505: heal_spell = 19658; break; - case 19731: heal_spell = 19732; break; - case 19734: heal_spell = 19733; break; - case 19736: heal_spell = 19735; break; - case 27276: heal_spell = 27278; break; - case 27277: heal_spell = 27279; break; - default: - sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id); - break; - } - if (heal_spell) - m_caster->CastSpell(m_caster, heal_spell, true); + int32 heal_amount = m_spellInfo->CalculateSimpleValue(1); + m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true); } } // Send fail log to client @@ -3699,13 +3725,6 @@ void Spell::EffectSummonGuardian(uint32 i) if(!pet_entry) return; - // Jewelery statue case (totem like) - if(m_spellInfo->SpellIconID == 2056) - { - EffectSummonTotem(i); - return; - } - // set timer for unsummon int32 duration = GetSpellDuration(m_spellInfo); @@ -4501,6 +4520,38 @@ void Spell::EffectWeaponDmg(uint32 i) } } } + break; + } + case SPELLFAMILY_DEATHKNIGHT: + { + // Blood Strike, Heart Strike, Obliterate + // Blood-Caked Strike, Scourge Strike + if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000001400000) || + m_spellInfo->SpellIconID == 1736 || m_spellInfo->SpellIconID == 3143) + { + uint32 count = 0; + Unit::AuraMap const& auras = unitTarget->GetAuras(); + for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) + { + if(itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE && + itr->second->GetCasterGUID() == m_caster->GetGUID() && + IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex())) + ++count; + } + + if (count) + { + // Effect 1(for Blood-Caked Strike)/3(other) damage is bonus + double bonus = count * CalculateDamage(m_spellInfo->SpellIconID == 1736 ? 0 : 2, unitTarget) / 100.0f; + // Blood Strike, Blood-Caked Strike and Obliterate store bonus*2 + if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0002000000400000) || + m_spellInfo->SpellIconID == 1736) + bonus /= 2.0f; + + totalDamagePercentMod += bonus; + } + } + break; } } @@ -5173,6 +5224,7 @@ void Spell::EffectScriptEffect(uint32 effIndex) { uint32 spellId = 0; int32 basePoint = 0; + Unit* target = unitTarget; Unit::AuraMap& Auras = unitTarget->GetAuras(); for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i) { @@ -5197,6 +5249,7 @@ void Spell::EffectScriptEffect(uint32 effIndex) { spellId = 53358; // 53358 Chimera Shot - Viper basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100; + target = m_caster; } // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute. if (familyFlag & UI64LIT(0x0000000000008000)) @@ -5209,7 +5262,7 @@ void Spell::EffectScriptEffect(uint32 effIndex) //} } if (spellId) - m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false); + m_caster->CastCustomSpell(target, spellId, &basePoint, 0, 0, false); return; } default: @@ -5219,8 +5272,8 @@ void Spell::EffectScriptEffect(uint32 effIndex) } case SPELLFAMILY_PALADIN: { - // Judgement - if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000800000)) + // Judgement (seal trigger) + if (m_spellInfo->Category == SPELLCATEGORY_JUDGEMENT) { if(!unitTarget || !unitTarget->isAlive()) return; @@ -5230,12 +5283,12 @@ void Spell::EffectScriptEffect(uint32 effIndex) // Judgement self add switch switch (m_spellInfo->Id) { - case 41467: break; // Judgement case 53407: spellId1 = 20184; break; // Judgement of Justice case 20271: // Judgement of Light case 57774: spellId1 = 20185; break; // Judgement of Light case 53408: spellId1 = 20186; break; // Judgement of Wisdom default: + sLog.outError("Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect",m_spellInfo->Id); return; } // all seals have aura dummy in 2 effect @@ -6219,7 +6272,7 @@ void Spell::EffectSummonDeadPet(uint32 /*i*/) pet->AIM_Initialize(); - _player->PetSpellInitialize(); + // _player->PetSpellInitialize(); -- action bar not removed at death and not required send at revive pet->SavePetToDB(PET_SAVE_AS_CURRENT); } @@ -6503,6 +6556,9 @@ void Spell::EffectSummonDemon(uint32 i) int32 amount = damage > 0 ? damage : 1; + if (m_spellInfo->EffectMiscValueB[i] == SUMMON_TYPE_INFERNO) + amount = 1; + for(int32 count = 0; count < amount; ++count) { float px, py, pz; @@ -6535,13 +6591,15 @@ void Spell::EffectSummonDemon(uint32 i) // TODO: Add damage/mana/hp according to level + // Enslave demon effect, without mana cost and cooldown if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon { // Enslave demon effect, without mana cost and cooldown m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved - // Inferno effect - Charmed->CastSpell(Charmed, 22703, true, 0); + // Inferno effect for non player calls + if (m_spellInfo->EffectMiscValueB[i]!=SUMMON_TYPE_INFERNO) + Charmed->CastSpell(Charmed, 22703, true, 0); } } } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 7e820e4bb..dbb15f434 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -188,6 +188,9 @@ SpellSpecific GetSpellSpecific(uint32 spellId) if (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000011010002)) return SPELL_BLESSING; + if (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002190)) + return SPELL_HAND; + if ((spellInfo->SpellFamilyFlags & UI64LIT(0x00000820180400)) && (spellInfo->AttributesEx3 & 0x200)) return SPELL_JUDGEMENT; @@ -238,6 +241,7 @@ bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1,SpellSpecific s case SPELL_POSITIVE_SHOUT: case SPELL_JUDGEMENT: case SPELL_PRESENCE: + case SPELL_HAND: return spellSpec1==spellSpec2; case SPELL_BATTLE_ELIXIR: return spellSpec2==SPELL_BATTLE_ELIXIR @@ -261,6 +265,7 @@ bool IsSingleFromSpellSpecificRanksPerTarget(SpellSpecific spellId_spec, SpellSp case SPELL_BLESSING: case SPELL_AURA: case SPELL_CURSE: + case SPELL_HAND: return spellId_spec==i_spellId_spec; default: return false; @@ -1463,9 +1468,15 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons if( spellInfo_2->SpellFamilyName == SPELLFAMILY_PALADIN ) { // Paladin Seals - if( IsSealSpell(spellInfo_1) && IsSealSpell(spellInfo_2) ) + if (IsSealSpell(spellInfo_1) && IsSealSpell(spellInfo_2)) return true; + + // Swift Retribution / Improved Devotion Aura (talents) and Paladin Auras + if ((spellInfo_1->SpellFamilyFlags2 & 0x00000020) && (spellInfo_2->SpellIconID == 291 || spellInfo_2->SpellIconID == 3028) || + (spellInfo_2->SpellFamilyFlags2 & 0x00000020) && (spellInfo_1->SpellIconID == 291 || spellInfo_1->SpellIconID == 3028)) + return false; } + // Combustion and Fire Protection Aura (multi-family check) if( spellInfo_2->Id == 11129 && spellInfo_1->SpellIconID == 33 && spellInfo_1->SpellVisual[0] == 321 ) return false; @@ -1494,6 +1505,18 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons if( spellInfo_1->Id == 2825 && spellInfo_2->SpellIconID == 38 && spellInfo_2->SpellVisual[0] == 0 ) return false; break; + case SPELLFAMILY_DEATHKNIGHT: + if (spellInfo_2->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT) + { + // Frost Presence and Frost Presence (triggered) + if( spellInfo_1->SpellIconID == 2632 && spellInfo_2->SpellIconID == 2632 ) + return false; + + // Unholy Presence and Unholy Presence (triggered) + if( spellInfo_1->SpellIconID == 2633 && spellInfo_2->SpellIconID == 2633 ) + return false; + } + break; default: break; } @@ -2529,10 +2552,15 @@ void SpellMgr::LoadSpellAreas() continue; } - if(spellInfo->EffectApplyAuraName[0]!=SPELL_AURA_DUMMY && spellInfo->EffectApplyAuraName[0]!=SPELL_AURA_PHASE) + switch(spellInfo->EffectApplyAuraName[0]) { - sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell requirement (%u) without dummy/phase aura in effect 0", spell,abs(spellArea.auraSpell)); - continue; + case SPELL_AURA_DUMMY: + case SPELL_AURA_PHASE: + case SPELL_AURA_GHOST: + break; + default: + sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell requirement (%u) without dummy/phase/ghost aura in effect 0", spell,abs(spellArea.auraSpell)); + continue; } if(abs(spellArea.auraSpell)==spellArea.spellId) @@ -2625,8 +2653,12 @@ void SpellMgr::LoadSpellAreas() SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player) { + // allow in GM-mode + if (player && player->isGameMaster()) + return SPELL_CAST_OK; + // normal case - if( spellInfo->AreaGroupId > 0) + if (spellInfo->AreaGroupId > 0) { bool found = false; AreaGroupEntry const* groupEntry = sAreaGroupStore.LookupEntry(spellInfo->AreaGroupId); @@ -2645,9 +2677,18 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell return SPELL_FAILED_INCORRECT_AREA; } + // continent limitation (virtual continent) + if (spellInfo->AttributesEx4 & SPELL_ATTR_EX4_CAST_ONLY_IN_OUTLAND) + { + uint32 v_map = GetVirtualMapForMapAndZone(map_id, zone_id); + MapEntry const* mapEntry = sMapStore.LookupEntry(v_map); + if(!mapEntry || mapEntry->addon < 1 || !mapEntry->IsContinent()) + return SPELL_FAILED_INCORRECT_AREA; + } + // DB base check (if non empty then must fit at least single for allow) SpellAreaMapBounds saBounds = spellmgr.GetSpellAreaMapBounds(spellInfo->Id); - if(saBounds.first != saBounds.second) + if (saBounds.first != saBounds.second) { for(SpellAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) { @@ -2674,21 +2715,21 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell case 44535: // Spirit Heal (mana) { MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); - if(!mapEntry) + if (!mapEntry) return SPELL_FAILED_INCORRECT_AREA; return mapEntry->IsBattleGround() && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA; } case 44521: // Preparation { - if(!player) + if (!player) return SPELL_FAILED_REQUIRES_AREA; MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); - if(!mapEntry) + if (!mapEntry) return SPELL_FAILED_INCORRECT_AREA; - if(!mapEntry->IsBattleGround()) + if (!mapEntry->IsBattleGround()) return SPELL_FAILED_REQUIRES_AREA; BattleGround* bg = player->GetBattleGround(); @@ -2700,21 +2741,21 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell case 35775: // Green Team (Horde) { MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); - if(!mapEntry) + if (!mapEntry) return SPELL_FAILED_INCORRECT_AREA; return mapEntry->IsBattleArena() && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA; } case 32727: // Arena Preparation { - if(!player) + if (!player) return SPELL_FAILED_REQUIRES_AREA; MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); - if(!mapEntry) + if (!mapEntry) return SPELL_FAILED_INCORRECT_AREA; - if(!mapEntry->IsBattleArena()) + if (!mapEntry->IsBattleArena()) return SPELL_FAILED_REQUIRES_AREA; BattleGround* bg = player->GetBattleGround(); diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 76c3da926..f1eb31ef3 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -40,7 +40,8 @@ struct SpellModifier; enum SpellCategories { SPELLCATEGORY_HEALTH_MANA_POTIONS = 4, - SPELLCATEGORY_DEVOUR_MAGIC = 12 + SPELLCATEGORY_DEVOUR_MAGIC = 12, + SPELLCATEGORY_JUDGEMENT = 1210, // Judgement (seal trigger) }; enum SpellFamilyNames @@ -96,7 +97,8 @@ enum SpellSpecific SPELL_BATTLE_ELIXIR = 14, SPELL_GUARDIAN_ELIXIR = 15, SPELL_FLASK_ELIXIR = 16, - SPELL_PRESENCE = 17 + SPELL_PRESENCE = 17, + SPELL_HAND = 18, }; SpellSpecific GetSpellSpecific(uint32 spellId); @@ -122,7 +124,7 @@ int32 GetSpellMaxDuration(SpellEntry const *spellInfo); inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect) { - for(int i= 0; i < 3; ++i) + for(int i = 0; i < 3; ++i) if(SpellEffects(spellInfo->Effect[i])==effect) return true; return false; @@ -130,12 +132,20 @@ inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect) inline bool IsSpellHaveAura(SpellEntry const *spellInfo, AuraType aura) { - for(int i= 0; i < 3; ++i) + for(int i = 0; i < 3; ++i) if(AuraType(spellInfo->EffectApplyAuraName[i])==aura) return true; return false; } +inline bool IsSpellLastAuraEffect(SpellEntry const *spellInfo, int effecIdx) +{ + for(int i = effecIdx+1; i < 3; ++i) + if(spellInfo->EffectApplyAuraName[i]) + return false; + return true; +} + bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2); inline bool IsSealSpell(SpellEntry const *spellInfo) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 83e1a4336..89401250b 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -647,7 +647,11 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa if(!cVictim->isPet()) { cVictim->DeleteThreatList(); - cVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + // only lootable if it has loot or can drop gold + if(cVictim->GetCreatureInfo()->lootid || cVictim->GetCreatureInfo()->maxgold > 0) + cVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + else + cVictim->lootForBody = true; // needed for skinning } // Call creature just died function if (cVictim->AI()) @@ -3402,8 +3406,10 @@ int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_ bool Unit::AddAura(Aura *Aur) { + SpellEntry const* aurSpellInfo = Aur->GetSpellProto(); + // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) - if( !isAlive() && Aur->GetId() != 20584 && Aur->GetId() != 8326 && Aur->GetId() != 2584 && + if( !isAlive() && !IsDeathPersistentSpell(aurSpellInfo) && (GetTypeId()!=TYPEID_PLAYER || !((Player*)this)->GetSession()->PlayerLoading()) ) { delete Aur; @@ -3419,7 +3425,6 @@ bool Unit::AddAura(Aura *Aur) return false; } - SpellEntry const* aurSpellInfo = Aur->GetSpellProto(); AuraType aurName = Aur->GetModifier()->m_auraname; spellEffectPair spair = spellEffectPair(Aur->GetId(), Aur->GetEffIndex()); @@ -3531,6 +3536,10 @@ bool Unit::AddAura(Aura *Aur) Aur->ApplyModifier(true,true); sLog.outDebug("Aura %u now is in use", aurName); + + if(IsSpellLastAuraEffect(aurSpellInfo,Aur->GetEffIndex())) + Aur->HandleSpellSpecificBoosts(true); + return true; } @@ -3876,13 +3885,24 @@ void Unit::RemoveAurasWithInterruptFlags(uint32 flags) } } -void Unit::RemoveNotOwnSingleTargetAuras() +void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase) { // single target auras from other casters for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); ) { if (iter->second->GetCasterGUID()!=GetGUID() && IsSingleTargetSpell(iter->second->GetSpellProto())) - RemoveAura(iter); + { + if(!newPhase) + RemoveAura(iter); + else + { + Unit* caster = iter->second->GetCaster(); + if(!caster || !caster->InSamePhase(newPhase)) + RemoveAura(iter); + else + ++iter; + } + } else ++iter; } @@ -3892,7 +3912,7 @@ void Unit::RemoveNotOwnSingleTargetAuras() for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end(); ) { Aura* aura = *iter; - if (aura->GetTarget() != this) + if (aura->GetTarget() != this && !aura->GetTarget()->InSamePhase(newPhase)) { scAuras.erase(iter); // explicitly remove, instead waiting remove in RemoveAura aura->GetTarget()->RemoveAura(aura); @@ -3957,7 +3977,14 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) sLog.outDebug("Aura %u now is remove mode %d",Aur->GetModifier()->m_auraname, mode); Aur->ApplyModifier(false,true); - Aur->_RemoveAura(); + + if(Aur->_RemoveAura()) + { + // last aura in stack removed + if(IsSpellLastAuraEffect(Aur->GetSpellProto(),Aur->GetEffIndex())) + Aur->HandleSpellSpecificBoosts(false); + } + delete Aur; if(caster_channeled) @@ -5676,8 +5703,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 40471; chance = 15.0f; } - // Judgement - else if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000800000)) + // Judgement (any) + else if (GetSpellSpecific(procSpell->Id)==SPELL_JUDGEMENT) { triggered_spell_id = 40472; chance = 50.0f; @@ -5883,6 +5910,13 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 58879; break; } + // Shaman T8 Elemental 4P Bonus + case 64928: + { + basepoints0 = int32( triggerAmount * damage / 100 ); + triggered_spell_id = 64930; // Electrified + break; + } } // Storm, Earth and Fire if (dummySpell->SpellIconID == 3063) @@ -6114,6 +6148,12 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 50526; break; } + // Blood-Caked Blade + if (dummySpell->SpellIconID == 138) + { + triggered_spell_id = dummySpell->EffectTriggerSpell[effIndex]; + break; + } break; } default: @@ -11821,6 +11861,12 @@ void Unit::RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo) void Unit::SetPhaseMask(uint32 newPhaseMask, bool update) { + if(newPhaseMask==GetPhaseMask()) + return; + + if(IsInWorld()) + RemoveNotOwnSingleTargetAuras(newPhaseMask); // we can lost access to caster or target + WorldObject::SetPhaseMask(newPhaseMask,update); if(IsInWorld()) diff --git a/src/game/Unit.h b/src/game/Unit.h index 386f5181f..d59551093 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1209,7 +1209,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer); void RemoveAurasDueToSpellByCancel(uint32 spellId); void RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo); - void RemoveNotOwnSingleTargetAuras(); + void RemoveNotOwnSingleTargetAuras(uint32 newPhase = 0x0); void RemoveSpellsCausingAura(AuraType auraType); void RemoveRankAurasDueToSpell(uint32 spellId); diff --git a/src/shared/Util.cpp b/src/shared/Util.cpp index fa18ad9bd..0b70aac87 100644 --- a/src/shared/Util.cpp +++ b/src/shared/Util.cpp @@ -73,7 +73,7 @@ Tokens StrSplit(const std::string &src, const std::string &sep) void stripLineInvisibleChars(std::string &str) { - static std::string invChars = " \t\7"; + static std::string invChars = " \t\7\n"; size_t wpos = 0; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index bcb5b939d..e592c6e2c 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8284" + #define REVISION_NR "8315" #endif // __REVISION_NR_H__