Merge commit 'origin/master' into 320

This commit is contained in:
tomrus88 2009-08-05 14:52:29 +04:00
commit f97da77cbd
38 changed files with 788 additions and 538 deletions

View file

@ -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)

View file

@ -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))
{

View file

@ -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;

View file

@ -16,7 +16,7 @@
/* re-adding before command use. So need just adding new line to file. */
/* Current table fill progress state: */
/* SpellEffect.cpp from start until end of Spell::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'),

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -201,14 +201,11 @@ 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
{
@ -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<uint64, BattleGroundScore*>::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<uint64, BattleGroundScore*>::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;

View file

@ -375,8 +375,9 @@ class BattleGround
BattleGroundPlayerMap const& GetPlayers() const { return m_Players; }
uint32 GetPlayersSize() const { return m_Players.size(); }
std::map<uint64, BattleGroundScore*>::const_iterator GetPlayerScoresBegin() const { return m_PlayerScores.begin(); }
std::map<uint64, BattleGroundScore*>::const_iterator GetPlayerScoresEnd() const { return m_PlayerScores.end(); }
typedef std::map<uint64, BattleGroundScore*> 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<uint64, BattleGroundScore*> m_PlayerScores;
BattleGroundScoreMap m_PlayerScores; // Player scores
// must be implemented in BG subclass
virtual void RemovePlayer(Player * /*player*/, uint64 /*guid*/) {}

View file

@ -659,8 +659,7 @@ WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player)
void BattleGroundAB::UpdatePlayerScore(Player *Source, uint32 type, uint32 value)
{
std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID());
if( itr == m_PlayerScores.end() ) // player not found...
return;

View file

@ -96,8 +96,7 @@ void BattleGroundAV::HandleAreaTrigger(Player *Source, uint32 Trigger)
void BattleGroundAV::UpdatePlayerScore(Player* Source, uint32 type, uint32 value)
{
std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID());
if(itr == m_PlayerScores.end()) // player not found...
return;

View file

@ -180,8 +180,7 @@ bool BattleGroundBE::SetupBattleGround()
void BattleGroundBE::UpdatePlayerScore(Player* Source, uint32 type, uint32 value)
{
std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID());
if(itr == m_PlayerScores.end()) // player not found...
return;

View file

@ -778,8 +778,7 @@ void BattleGroundEY::EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType
void BattleGroundEY::UpdatePlayerScore(Player *Source, uint32 type, uint32 value)
{
std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID());
if(itr == m_PlayerScores.end()) // player not found
return;

View file

@ -1333,7 +1333,7 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg)
*data << (int32)(bg->GetPlayerScoresSize());
for(std::map<uint64, BattleGroundScore*>::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;

View file

@ -72,8 +72,7 @@ void BattleGroundSA::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/)
void BattleGroundSA::UpdatePlayerScore(Player* Source, uint32 type, uint32 value)
{
std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID());
if(itr == m_PlayerScores.end()) // player not found...
return;

View file

@ -631,8 +631,7 @@ void BattleGroundWS::HandleKillPlayer(Player *player, Player *killer)
void BattleGroundWS::UpdatePlayerScore(Player *Source, uint32 type, uint32 value)
{
std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID());
BattleGroundScoreMap::iterator itr = m_PlayerScores.find(Source->GetGUID());
if(itr == m_PlayerScores.end()) // player not found
return;

View file

@ -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;
}

View file

@ -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

View file

@ -458,8 +458,8 @@ class Guild
TabListMap m_TabListMap;
/** These are actually ordered lists. The first element is the oldest entry.*/
typedef std::list<GuildEventlogEntry*> GuildEventlog;
typedef std::list<GuildBankEvent*> GuildBankEventLog;
typedef std::list<GuildEventlogEntry> GuildEventlog;
typedef std::list<GuildBankEvent> GuildBankEventLog;
GuildEventlog m_GuildEventlog;
GuildBankEventLog m_GuildBankEventLog_Money;
GuildBankEventLog m_GuildBankEventLog_Item[GUILD_BANK_MAX_TABS];

View file

@ -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)

View file

@ -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();

View file

@ -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<std::pair<Unit*, Spell*> > 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<Unit*, Spell*>(m_creature->getVictim(), spell));
targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(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<Unit*, Spell*>(Target, spell));
targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(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;
}
}

View file

@ -52,8 +52,5 @@ class MANGOS_DLL_DECL PetAI : public CreatureAI
bool inCombat;
std::set<uint64> m_AllySet;
uint32 m_updateAlliesTimer;
typedef std::pair<Unit*, Spell*> TargetSpellPair;
std::vector<TargetSpellPair> m_targetSpellStore;
};
#endif

View file

@ -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;
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,27 +15701,14 @@ 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->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)
if (!itr2->second->IsPassive() && (itr2->second->GetCasterGUID() == GetGUID() || !itr2->second->IsSingleTarget()))
{
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())
break;
@ -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

View file

@ -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; }

View file

@ -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);

View file

@ -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

View file

@ -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])
{
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);
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);
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, false);
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:

View file

@ -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,8 +1075,9 @@ 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);
@ -1164,7 +1165,8 @@ void Aura::_RemoveAura()
// 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;

View file

@ -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; }

View file

@ -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;
@ -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:
// 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,12 +6591,14 @@ 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
// Inferno effect for non player calls
if (m_spellInfo->EffectMiscValueB[i]!=SUMMON_TYPE_INFERNO)
Charmed->CastSpell(Charmed, 22703, true, 0);
}
}

View file

@ -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;
@ -1465,7 +1470,13 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
// Paladin Seals
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,9 +2552,14 @@ 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));
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;
}
@ -2625,6 +2653,10 @@ 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)
{
@ -2645,6 +2677,15 @@ 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)

View file

@ -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);
@ -136,6 +138,14 @@ inline bool IsSpellHaveAura(SpellEntry const *spellInfo, AuraType aura)
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)

View file

@ -647,7 +647,11 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
if(!cVictim->isPet())
{
cVictim->DeleteThreatList();
// 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()))
{
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())

View file

@ -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);

View file

@ -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;

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "8284"
#define REVISION_NR "8315"
#endif // __REVISION_NR_H__