diff --git a/sql/characters.sql b/sql/characters.sql index 6d4debeef..bbc42f893 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -21,7 +21,7 @@ DROP TABLE IF EXISTS `character_db_version`; CREATE TABLE `character_db_version` ( - `required_8828_01_characters_instance_reset` bit(1) default NULL + `required_8874_01_characters_character_skills` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB'; -- @@ -690,6 +690,28 @@ LOCK TABLES `character_reputation` WRITE; /*!40000 ALTER TABLE `character_reputation` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `character_skills` +-- + +DROP TABLE IF EXISTS `character_skills`; +CREATE TABLE `character_skills` ( + `guid` int(11) unsigned NOT NULL COMMENT 'Global Unique Identifier', + `skill` mediumint(9) unsigned NOT NULL, + `value` mediumint(9) unsigned NOT NULL, + `max` mediumint(9) unsigned NOT NULL, + PRIMARY KEY (`guid`,`skill`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + +-- +-- Dumping data for table `character_skills` +-- + +LOCK TABLES `character_skills` WRITE; +/*!40000 ALTER TABLE `character_skills` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_skills` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `character_social` -- diff --git a/sql/mangos.sql b/sql/mangos.sql index 3d1b1a674..7300accb4 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -24,7 +24,7 @@ CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, `cache_id` int(10) default '0', - `required_8840_01_mangos_spell_proc_event` bit(1) default NULL + `required_8891_01_mangos_spell_proc_event` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -2849,6 +2849,9 @@ INSERT INTO `mangos_string` VALUES (57,'Using World DB: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (58,'Using script library: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (59,'Using creature EventAI: %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(60,'I\'m busy right now, come back later.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(61,'Username: ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(62,'Password: ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (100,'Global notify: ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (101,'Map: %u (%s) Zone: %u (%s) Area: %u (%s) Phase: %u\nX: %f Y: %f Z: %f Orientation: %f\ngrid[%u,%u]cell[%u,%u] InstanceID: %u\n ZoneX: %f ZoneY: %f\nGroundZ: %f FloorZ: %f Have height data (Map: %u VMap: %u)',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (102,'%s is already being teleported.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), @@ -14043,11 +14046,13 @@ INSERT INTO `spell_bonus_data` VALUES (34861, 0.402, 0, 0, 'Priest - Circle of Healing'), (19236, 0.8068, 0, 0, 'Priest - Desperate Prayer'), (2944, 0, 0.1849, 0, 'Priest - Devouring Plague'), +(63544, 0, 0, 0, 'Priest - Empowered Renew Triggered'), (14914, 0.5711, 0.024, 0, 'Priest - Holy Fire'), (15237, 0.1606, 0, 0, 'Priest - Holy Nova Damage'), (2061, 0.8068, 0, 0, 'Priest - Flash Heal'), (2060, 1.6135, 0, 0, 'Priest - Greater Heal'), (23455, 0.3035, 0, 0, 'Priest - Holy Nova Heal'), +(63675, 0, 0, 0, 'Priest - Improved Devouring Plague Triggered'), (8129, 0, 0, 0, 'Priest - Mana Burn'), (58381, 0.257143,0, 0, 'Priest - Mind Flay Triggered'), (49821, 0.14286,0, 0, 'Priest - Mind Sear Trigger'), @@ -14440,7 +14445,11 @@ INSERT INTO spell_chain VALUES (25208,11574,772,8,0), (46845,25208,772,9,0), (47465,46845,772,10,0), -/*ThunderClap*/ +/*Taste for Blood*/ +(56636,0,56636,1,0), +(56637,56636,56636,2,0), +(56638,56637,56636,3,0), +/*Thunder Clap*/ (6343,0,6343,1,0), (8198,6343,6343,2,0), (8204,8198,6343,3,0), @@ -15166,6 +15175,10 @@ INSERT INTO spell_chain VALUES (27180,24239,24275,4,0), (48805,27180,24275,5,0), (48806,48805,24275,6,0), +/*Heart of the Crusader*/ +(20335, 0, 20335, 1, 0), +(20336, 20335, 20335, 2, 0), +(20337, 20336, 20335, 3, 0), /*Retribution Aura*/ (7294,0,7294,1,0), (10298,7294,7294,2,0), @@ -17125,6 +17138,10 @@ INSERT INTO spell_chain VALUES (51423,49020,49020,2,0), (51424,51423,49020,3,0), (51425,51424,49020,4,0), +/*Threat of Thassarian*/ +(65661,0,65661,1,0), +(66191,65661,65661,2,0), +(66192,66191,65661,3,0), /*------------------ --(772)Unholy ------------------*/ @@ -17462,6 +17479,7 @@ INSERT INTO `spell_learn_spell` VALUES (34769,33388,1), (53428,53341,1), (53428,53343,1), +(56815,56816,0), (58984,21009,1); /*!40000 ALTER TABLE `spell_learn_spell` ENABLE KEYS */; UNLOCK TABLES; @@ -17556,7 +17574,8 @@ INSERT INTO `spell_pet_auras` VALUES (23822, 0, 17252, 35703), (23823, 0, 17252, 35704), (23824, 0, 17252, 35705), -(23825, 0, 17252, 35706); +(23825, 0, 17252, 35706), +(58228, 0, 19668, 57989); /*!40000 ALTER TABLE `spell_pet_auras` ENABLE KEYS */; UNLOCK TABLES; @@ -17567,7 +17586,7 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `spell_proc_event`; CREATE TABLE `spell_proc_event` ( - `entry` smallint(5) unsigned NOT NULL default '0', + `entry` mediumint(8) unsigned NOT NULL default '0', `SchoolMask` tinyint(4) NOT NULL default '0', `SpellFamilyName` smallint(5) unsigned NOT NULL default '0', `SpellFamilyMask0` int(10) unsigned NOT NULL default '0', @@ -17755,6 +17774,7 @@ INSERT INTO `spell_proc_event` VALUES (20215, 0x00000000, 10, 0xC0000000, 0x00010000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (20234, 0x00000000, 10, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (20235, 0x00000000, 10, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(20335, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00000100, 0x00000000, 0.000000, 100.000000, 0), (20375, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 7.000000, 0.000000, 0), (20500, 0x00000000, 4, 0x10000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (20501, 0x00000000, 4, 0x10000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), @@ -18293,9 +18313,8 @@ INSERT INTO `spell_proc_event` VALUES (56612, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (56613, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (56614, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), -(56636, 0x00000000, 4, 0x00000020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), -(56637, 0x00000000, 4, 0x00000020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), -(56638, 0x00000000, 4, 0x00000020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(56636, 0x00000000, 4, 0x00000020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 6), +(56816, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000030, 0.000000, 0.000000, 0), (56821, 0x00000000, 8, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (56822, 0x00000000, 15, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (56834, 0x00000000, 15, 0x00440000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), @@ -18310,7 +18329,7 @@ INSERT INTO `spell_proc_event` VALUES (58364, 0x00000000, 4, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (58372, 0x00000000, 4, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (58386, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000020, 0.000000, 0.000000, 0), -(58616, 0x00000000, 15, 0x00040000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(58616, 0x00000000, 15, 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (58620, 0x00000000, 15, 0x00000000, 0x00004000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (58626, 0x00000000, 15, 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (58631, 0x00000000, 15, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), @@ -18361,8 +18380,13 @@ INSERT INTO `spell_proc_event` VALUES (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), (63320, 0x00000000, 5, 0x00040000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(63534, 0x00000000, 6, 0x00000040, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0), +(63625, 0x00000000, 6, 0x02000000, 0x00000000, 0x00000000, 0x00010000, 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); +(64928, 0x00000000, 11, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), +(64976, 0x00000000, 4, 0x00000001, 0x00000000, 0x00000000, 0x00010000, 0x00000000, 0.000000, 0.000000, 0), +(65661, 0x00000000, 15, 0x00400010, 0x20020004, 0x00000000, 0x00000010, 0x00000000, 0.000000, 100.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 1dae67688..eeeceaeb6 100644 --- a/sql/mangos_spell_check.sql +++ b/sql/mangos_spell_check.sql @@ -41,6 +41,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas (1454, 5,0x0000000000040000,0x00000000, -1, -1, -1, 3, -1,-1,'Life Tap', 'Spell::EffectDummy'), (1455, 5,0x0000000000040000,0x00000000, -1, -1, -1, 3, -1,-1,'Life Tap', 'Spell::EffectDummy'), (1456, 5,0x0000000000040000,0x00000000, -1, -1, -1, 3, -1,-1,'Life Tap', 'Spell::EffectDummy'), +(2584, -1, -1, -1, -1, -1, -1, -1, 4,-1,'Waiting to Resurrect', 'Spell::EffectSpiritHeal'), (9512, -1, -1, -1, -1, -1, -1, 30, -1,-1,'Restore Energy', 'Spell::EffectEnergize'), (4073, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Mechanical Dragonling', 'Spell::EffectDummy'), (5938, 8, -1, -1, -1, -1, -1, 3, -1,-1,'Shiv', 'Spell::EffectDummy'), @@ -105,6 +106,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas (20930,10, -1, -1, 156, -1, -1, 3, -1,-1,'Holy Shock', 'Spell::EffectDummy'), (21887,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Warrior\'s Wrath', 'Spell::EffectDummy'), (21977, 4, -1, -1, -1, -1, -1, 3, -1,-1,'Warrior\'s Wrath', 'Spell::EffectDummy'), +(22012,-1, -1, -1, -1, -1, -1,117, -1,-1,'Spirit Heal', 'Spell::EffectSpiritHeal'), (23019, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Crystal Prison Dummy DND', 'Spell::EffectDummy'), (23074, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Arcanite Dragonling', 'Spell::EffectDummy'), (23075, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Mithril Mechanical Dragonling', 'Spell::EffectDummy'), @@ -239,16 +241,18 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas (38903, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor', 'Spell::EffectSchoolDMG'), (39609,-1, -1, -1, -1, -1, -1, 30, -1, 0,'Mana Tide Totem', 'Spell::EffectDummy'), (39610,11, -1, -1, -1, -1, -1, 3, -1,-1,'Mana Tide Totem effect', 'Spell::EffectDummy'), +(40802, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Mingo\'s Fortune Generator', '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::cast'), +(42337,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Raptor Capture Credit', 'Spell::EffectDummy'), (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'), (43723, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Demon Broiled Surprise', 'Spell::EffectDummy'), (43753,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Demon-Broiled Surprise', 'Spell::EffectDummy'), -(40802, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Mingo\'s Fortune Generator', 'Spell::EffectDummy'), -(42337,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Raptor Capture Credit', 'Spell::EffectDummy'), +(43899,-1, -1, -1, -1, -1, -1, -1, 78,-1,'Brewfest Ram', 'Spell::EffectDummy'), +(43900,-1, -1, -1, -1, -1, -1, -1, 78,-1,'Swift Brewfest Ram', 'Spell::EffectDummy'), (44824,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Flying Reindeer', 'Spell::EffectDummy'), (44825,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Flying Reindeer', 'Spell::EffectDummy'), (44827,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Flying Reindeer', 'Spell::EffectDummy'), @@ -272,17 +276,22 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas (47758,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Penance', 'Spell::EffectDummy'), (47897, 5,0x0001000000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Shadowflame', 'Spell::EffectSchoolDMG'), (47960,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Shadowflame', 'Spell::EffectSchoolDMG'), +(48301,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Mind Trauma', 'Spell::EffectSchoolDMG'), (48820,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Holy Shock', 'Spell::EffectDummy'), (48821,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Holy Shock', 'Spell::EffectDummy'), (48822,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Holy Shock', 'Spell::EffectDummy'), (48823,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Holy Shock', 'Spell::EffectDummy'), (48824,10, -1, -1, 156, -1, -1, 3, -1,-1,'Holy Shock', 'Spell::EffectDummy'), (48825,10, -1, -1, 156, -1, -1, 3, -1,-1,'Holy Shock', 'Spell::EffectDummy'), +(49357,-1, -1, -1, -1, -1, -1, 3, -1,-1,'Brewfest Mount Transformation', 'Spell::EffectDummy'), +(49378,-1, -1, -1, -1, -1, -1, -1, 78,-1,'Brewfest Riding Kodo', 'Spell::EffectDummy'), +(49379,-1, -1, -1, -1, -1, -1, -1, 78,-1,'Great Brewfest Kodo', 'Spell::EffectDummy'), (50242,-1, -1, -1, -1, -1, -1, -1, -1,-1,'1000001', 'Spell::EffectDummy'), (50243, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Teach Language', 'Spell::EffectDummy'), (50246,-1, -1, -1, -1, -1, -1, -1, -1,-1,'01001000', 'Spell::EffectDummy'), (50286, 7,0x0000000000000000,0x00000100, -1, -1, -1, 3, -1,-1,'Starfall', 'Spell::EffectDummy'), (50288,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Starfall', 'Spell::EffectDummy'), +(50842,15, -1, -1, -1, -1, -1, 77, -1,-1,'Pestilence', 'Spell::EffectScriptEffect'), (51209,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Hungering Cold', 'Spell::EffectDummy'), (51582, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Rocket Boots Engaged', 'Spell::EffectDummy'), (51592, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Pickup Primordial Hatchling', 'Spell::EffectDummy'), @@ -293,6 +302,7 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas (52308, 0, -1, -1, -1, -1, -1, 3, -1, 1,'Take Sputum Sample', 'Spell::EffectDummy'), (52752,-1, -1, -1, -1, -1, -1, 10, -1, 0,'Ancestral Awakening', 'Spell::EffectDummy'), (52759, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Ancestral Awakening', 'Spell::EffectDummy'), +(52845,-1, -1, -1, -1, -1, -1, 3, -1,-1,'Brewfest Mount Transformation (Faction Swap)','Spell::EffectDummy'), (52986,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Penance', 'Spell::EffectDummy'), (52987,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Penance', 'Spell::EffectDummy'), (52988,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Penance', 'Spell::EffectDummy'), @@ -312,11 +322,15 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas (53271,-1, -1, -1, -1, -1, -1, 77, -1,-1,'Master''s Call', 'Spell::EffectScriptEffect'), (53341, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Rune of Cinderglacier', 'Spell::EffectDummy'), (53343, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Rune of Razorice', 'Spell::EffectDummy'), +(53478, 9, -1, -1, -1, -1, -1, 3, -1,-1,'Last Stand', 'Spell::EffectDummy'), +(53479,-1, -1, -1, -1, -1, -1, -1, 34, 0,'Last Stand', 'Spell::EffectDummy'), (54216,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Master''s Call', 'Spell::EffectDummy'), (54586,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Runeforging Credit', 'Spell::EffectDummy'), (54824,-1, -1, -1, -1, -1, -1, -1, 4,-1,'Glyph of Swiftmend', 'Spell::EffectHeal'), (54861,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Nitro Boosts', 'Spell::EffectDummy'), (55004, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Nitro Boosts', 'Spell::EffectDummy'), +(55078,-1, -1, -1, -1, -1, -1, -1, 3,-1,'Blood Plague', 'Spell::EffectScriptEffect'), +(55095,-1, -1, -1, -1, -1, -1, -1, 3,-1,'Frost Fever', 'Spell::EffectScriptEffect'), (55441,11, -1, -1, -1, -1, -1, -1, 4,-1,'Glyph of Mana Tide', 'Spell::EffectDummy'), (56235,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Glyph of Conflagrate', 'Spell::EffectSchoolDMG'), (56446,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Disengage', 'Spell::EffectDummy'), @@ -327,6 +341,9 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas (58367,-1, -1, -1, -1, -1, -1, -1, 4,-1,'Glyph of Execution', 'Spell::EffectDummy'), (58418, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Portal to Orgrimmar', 'Spell::EffectDummy'), (58420, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Portal to Stormwind', 'Spell::EffectDummy'), +(58657,-1, -1, -1, -1, -1, -1, -1, 4,-1,'Glyph of Plague Strike', 'Spell::EffectWeaponDmg'), +(59336,-1, -1, -1, -1, -1, -1, -1, 4,-1,'Glyph of Death Strike', 'Spell::EffectWeaponDmg'), +(59332,-1, -1, -1, -1, -1, -1, -1, 4,-1,'Glyph of Blood Strike', 'Spell::EffectWeaponDmg'), (59640, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Underbelly Elixir', 'Spell::EffectDummy'), (59645,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Underbelly Elixir', 'Spell::EffectDummy'), (59831,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Underbelly Elixir', 'Spell::EffectDummy'), @@ -339,27 +356,38 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas (61507, 9, -1, -1, -1, -1, -1, 3, -1,-1,'Disengage', 'Spell::EffectDummy'), (61508,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Disengage', 'Spell::EffectDummy'), (62305,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Master''s Call', 'Spell::EffectScriptEffect'), +(62775, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Tympanic Tantrum', 'Spell::EffectSchoolDMG'), +(63334,-1, -1, -1, -1, -1, -1, -1, 4,-1,'Glyph of Disease', 'Spell::EffectScriptEffect'), (63375,-1, -1, -1, -1, -1, -1, 30, -1,-1,'Improved Stormstrike', 'Spell::EffectEnergize'), +(67016,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Flask of the North', 'Spell::EffectDummy'), +(67017,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Flask of the North', 'Spell::EffectDummy'), +(67018,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Flask of the North', 'Spell::EffectDummy'), +(67019,-1, -1, -1, -1, -1, -1, 3, -1,-1,'Flask of the North', 'Spell::EffectDummy'), + +/*id fm familyMaskA fmMaskB icon vis cat eff aur ef name code */ /* sorted by spell names */ /*id fm familyMaskA fmMaskB icon vis cat eff aur ef name code */ ( 0, 3,0x0000000020000000,0x00000000, -1, -1, -1, 2, -1,-1,'Arcane Blast', 'Spell::EffectSchoolDMG'), ( 0, 9,0x0000000000000800,0x00000000, -1, -1, -1, 2, -1,-1,'Arcane Shot', 'Spell::EffectSchoolDMG'), +( 0,15,0x0000000000400000,0x00000000, -1, -1, -1, 31, -1,-1,'Blood Strike', 'Spell::EffectWeaponDmg'), +( 0,15, -1, -1,1736, -1, -1, 31, -1,-1,'Blood-Caked Strike', 'Spell::EffectWeaponDmg'), ( 0, 5,0x0000000000004000,0x00000000, -1, -1, -1, -1, -1,-1,'Drain Soul', 'Unit::SpellDamageBonus'), ( 0,10,0x0000000000004000,0x00000000, -1, -1, -1, 2, -1,-1,'Avenger\'s Shield', 'Spell::EffectSchoolDMG'), ( 0, 4,0x0000040000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Bloodthirst', 'Spell::EffectSchoolDMG'), -(0, 4,0x0000000000000001,0x00000000, -1, 867, -1, 3, -1,-1,'Charge', 'Spell::EffectDummy'), +( 0, 4,0x0000000000000001,0x00000000, -1, 867, -1, 3, -1,-1,'Charge', 'Spell::EffectDummy'), ( 0,11,0x0000000004000000,0x00000000,1673, -1, -1, 3, -1,-1,'Cleansing Totem', 'Spell::EffectDummy'), -(0, 4,0x0000000004000000,0x00000000, -1, -1, -1, 3, -1,-1,'Concussion Blow', 'Spell::EffectDummy'), +( 0, 4,0x0000000004000000,0x00000000, -1, -1, -1, 3, -1,-1,'Concussion Blow', 'Spell::EffectDummy'), ( 0, 9,0x0008000000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Counterattack', 'Spell::EffectSchoolDMG'), ( 0, 8,0x0000000000010000,0x00000000, -1, -1, -1, -1, 3,-1,'Deadly poison', 'Spell::EffectSchoolDMG'), ( 0,15,0x0000000000002000,0x00000000, -1, -1, -1, 3, -1,-1,'Death Coil', 'Spell::EffectDummy'), +( 0,15,0x0000000000000010,0x00000000, -1, -1, -1, 31, -1,-1,'Death Strike', 'Spell::EffectWeaponDmg'), ( 0,15,0x0000000000000010,0x00000000, -1, -1, -1, 3, -1,-1,'Death Strike', 'Spell::EffectDummy'), ( 0, 5, -1, -1, -1, -1, 12, 38, -1,-1,'Devour Magic', 'Spell::EffectDispel'), ( 0, 9,0x0000400000000000,0x00000000, -1, -1, -1, 3, -1,-1,'Disengage', 'Spell::EffectDummy'), ( 0, 8,0x0000000800000000,0x00000000, -1, -1, -1, 2, -1,-1,'Envenom', 'Spell::EffectSchoolDMG'), ( 0, 8,0x0000000000020000,0x00000000, -1, -1, -1, 2, -1,-1,'Eviscerate', 'Spell::EffectSchoolDMG'), -(0, 4,0x0000000020000000,0x00000000, -1, -1, -1, 3, -1,-1,'Execute', 'Spell::EffectDummy'), +( 0, 4,0x0000000020000000,0x00000000, -1, -1, -1, 3, -1,-1,'Execute', 'Spell::EffectDummy'), ( 0, 9,0x0000000000000004,0x00000000, -1, -1, -1, 2, -1,-1,'Explosive Trap Effect', 'Spell::EffectSchoolDMG'), ( 0, 7,0x0000000000800000,0x00000000, -1,6587, -1, 2, -1,-1,'Ferocious Bite', 'Spell::EffectSchoolDMG'), ( 0,11,0x0000000000200000,0x00000000, -1, -1, -1, -1, -1,-1,'Flametongue', 'Spell::EffectDummy'), @@ -372,19 +400,22 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas ( 0,10, -1, -1, 156, -1, -1, 3, -1,-1,'Holy Shock', 'Spell::EffectDummy'), ( 0,15,0x0000100000000000,0x00000000, -1, -1, -1, 3, -1,-1,'Hungering Cold', 'Spell::EffectDummy'), ( 0, 5,0x0000000000000004,0x00000000, -1, -1, -1, -1, 3,-1,'Immolate', 'Spell::EffectSchoolDMG'), -(0, 5, -1, -1, 208, -1, -1, -1, 4,-1,'Improved Life Tap', 'Spell::EffectDummy'), +( 0, 5, -1, -1, 208, -1, -1, -1, 4,-1,'Improved Life Tap', 'Spell::EffectDummy'), +( 0, 6, -1, -1, 95, -1, -1, -1,107,-1,'Improved Mind Blast', 'Spell::EffectSchoolDMG'), ( 0, 5,0x0000004000000000,0x00000000,2128, -1, -1, 2, -1,-1,'Incinerate', 'Spell::EffectSchoolDMG'), ( 0, 8,0x0000000000002000,0x00000000, -1, -1, -1, 2, -1,-1,'Instant Poison', 'Spell::EffectSchoolDMG'), ( 0,10, -1, -1, 561, -1, -1, 3, -1,-1,'Judgement of command', 'Spell::EffectDummy'), ( 0,10,0x0000000800000000,0x00000000,2292, -1, -1, 2, -1,-1,'Judgement of Vengeance', 'Spell::EffectSchoolDMG'), ( 0, 7,0x0000010000000000,0x00000000,2246, -1, -1, 2, -1,-1,'Lacerate', 'Spell::EffectSchoolDMG'), ( 0,11,0x0000000000000000,0x00000004, -1, -1, -1, 3, -1,-1,'Lava Lash', 'Spell::EffectDummy'), -(0, 5,0x0000000000040000,0x00000000, -1, -1, -1, 3, -1,-1,'Life Tap', 'Spell::EffectDummy'), -(0, 5, -1, -1,1982, -1, -1, -1,107,-1,'Mana Feed', 'Spell::EffectDummy'), +( 0, 5,0x0000000000040000,0x00000000, -1, -1, -1, 3, -1,-1,'Life Tap', 'Spell::EffectDummy'), +( 0, 5, -1, -1,1982, -1, -1, -1,107,-1,'Mana Feed', 'Spell::EffectDummy'), ( 0,11,0x0000000000004000,0x00000000, -1, -1, -1, 3, -1,-1,'Mana Spring Totem', 'Spell::EffectDummy'), ( 0, 7,0x0000044000000000,0x00000000, -1, -1, -1, -1, -1,-1,'Mangle (Cat) and Mangle (Bear)', 'Unit::HandleDummyAuraProc'), +( 0, 6,0x0000000000002000,0x00000000, -1, -1, -1, 2, -1,-1,'Mind Blast', 'Spell::EffectSchoolDMG'), ( 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,0x0080000000000000,0x00000000, -1, -1, -1, 3, -1,-1,'Penance', 'Spell::EffectDummy'), +( 0,15,0x0000000000000001,0x00000000, -1, -1, -1, 31, -1,-1,'Plague Strike', 'Spell::EffectWeaponDmg'), ( 0, 6,0x0000002000000000,0x00000000, -1, -1, -1, 6, -1,-1,'Prayer of Mending', 'Spell::cast'), ( 0, 8,0x0000024000000860,0x00000000, -1, -1, -1, -1, -1,-1,'Preparation (affected spells)', 'Spell::EffectDummy'), ( 0, 7,0x0000000000000040,0x00000000, -1, -1, -1, -1, 8,-1,'Regrowth', 'Spell::EffectHeal'), @@ -402,8 +433,8 @@ INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMas ( 0, 4,0x0000020000000000,0x00000000, -1, -1,1209, 2, -1,-1,'Shield Slam', 'Spell::EffectSchoolDMG'), ( 0, 4,0x0000800000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Shockwave', 'Spell::EffectSchoolDMG'), ( 0, 7,0x0000000000008000,0x00000000, -1, -1, -1, -1, -1,-1,'Shred', 'Unit::MeleeDamageBonus'), -(0, 4,0x0000000000200000,0x00000000, -1, -1, -1, 3, -1,-1,'Slam', 'Spell::EffectDummy'), -(0, 7,0x0000000000000000,0x00000100, -1, -1, -1, 3, -1,-1,'Starfall', 'Spell::EffectDummy'), +( 0, 4,0x0000000000200000,0x00000000, -1, -1, -1, 3, -1,-1,'Slam', 'Spell::EffectDummy'), +( 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'), diff --git a/sql/updates/8841_01_mangos_spell_proc_event.sql b/sql/updates/8841_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..ccf9adfdb --- /dev/null +++ b/sql/updates/8841_01_mangos_spell_proc_event.sql @@ -0,0 +1,9 @@ +ALTER TABLE db_version CHANGE COLUMN required_8840_01_mangos_spell_proc_event required_8841_01_mangos_spell_proc_event bit; + +ALTER TABLE `spell_proc_event` + CHANGE `entry` `entry` mediumint(8) unsigned NOT NULL default '0'; + +DELETE FROM `spell_proc_event` WHERE `entry` IN (65661); + +INSERT INTO `spell_proc_event` VALUES + (65661, 0, 15, 0x00400010, 0x20020004, 0x00000000, 0x00000010, 0x00000000, 0.000000, 100.000000, 0); diff --git a/sql/updates/8841_02_mangos_spell_chain.sql b/sql/updates/8841_02_mangos_spell_chain.sql new file mode 100644 index 000000000..fa66000cf --- /dev/null +++ b/sql/updates/8841_02_mangos_spell_chain.sql @@ -0,0 +1,8 @@ +ALTER TABLE db_version CHANGE COLUMN required_8841_01_mangos_spell_proc_event required_8841_02_mangos_spell_chain bit; + +DELETE FROM spell_chain WHERE first_spell = 65661; + +INSERT INTO spell_chain VALUES +(65661,0,65661,1,0), +(66191,65661,65661,2,0), +(66192,66191,65661,3,0); diff --git a/sql/updates/8843_01_characters.sql b/sql/updates/8843_01_characters.sql new file mode 100644 index 000000000..9da8a8788 --- /dev/null +++ b/sql/updates/8843_01_characters.sql @@ -0,0 +1,6 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_8828_01_characters_instance_reset required_8843_01_characters bit; + +DELETE FROM `character_spell` WHERE `spell` IN (31892, 53720); +DELETE FROM `character_spell_cooldown` WHERE `spell` IN (31892, 53720); +DELETE FROM `character_aura` WHERE `spell` IN (31892, 53720); +DELETE FROM `character_action` WHERE `action` IN (31892, 53720) AND `type`=0; diff --git a/sql/updates/8847_01_mangos_spell_proc_event.sql b/sql/updates/8847_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..d80a8277c --- /dev/null +++ b/sql/updates/8847_01_mangos_spell_proc_event.sql @@ -0,0 +1,7 @@ +ALTER TABLE db_version CHANGE COLUMN required_8841_02_mangos_spell_chain required_8847_01_mangos_spell_proc_event bit; + +-- (20335) Heart of the Crusader (Rank 1) +DELETE FROM `spell_proc_event` WHERE `entry` IN (20335); +INSERT INTO `spell_proc_event` VALUES + (20335, 0x00, 10, 0x00800000, 0x00000000, 0x00000008, 0x00000100, 0x00000000, 0.000000, 100.000000, 0); + diff --git a/sql/updates/8847_02_mangos_spell_chain.sql b/sql/updates/8847_02_mangos_spell_chain.sql new file mode 100644 index 000000000..f2a6d2560 --- /dev/null +++ b/sql/updates/8847_02_mangos_spell_chain.sql @@ -0,0 +1,8 @@ +ALTER TABLE db_version CHANGE COLUMN required_8847_01_mangos_spell_proc_event required_8847_02_mangos_spell_chain bit; + +DELETE FROM spell_chain WHERE first_spell = 20335; + +INSERT INTO spell_chain VALUES + (20335, 0, 20335, 1, 0), + (20336, 20335, 20335, 2, 0), + (20337, 20336, 20335, 3, 0); diff --git a/sql/updates/8851_01_mangos_spell_proc_event.sql b/sql/updates/8851_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..274b8f759 --- /dev/null +++ b/sql/updates/8851_01_mangos_spell_proc_event.sql @@ -0,0 +1,8 @@ +ALTER TABLE db_version CHANGE COLUMN required_8847_02_mangos_spell_chain required_8851_01_mangos_spell_proc_event bit; + +-- Taste for Blood (1/2/3 ranks) +DELETE FROM spell_proc_event WHERE entry IN (56636, 56637, 56638); +INSERT INTO spell_proc_event VALUES +(56636, 0x00000000, 4, 0x00000020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 6), +(56637, 0x00000000, 4, 0x00000020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 6), +(56638, 0x00000000, 4, 0x00000020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 6); diff --git a/sql/updates/8856_01_mangos_spell_proc_event.sql b/sql/updates/8856_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..13cfd82a3 --- /dev/null +++ b/sql/updates/8856_01_mangos_spell_proc_event.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_8851_01_mangos_spell_proc_event required_8856_01_mangos_spell_proc_event bit; + +DELETE FROM `spell_proc_event` WHERE `entry` IN (58617); +INSERT INTO `spell_proc_event` VALUES +(58617, 0x00000000, 15, 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0); diff --git a/sql/updates/8863_01_mangos_spell_proc_event.sql b/sql/updates/8863_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..995a67c15 --- /dev/null +++ b/sql/updates/8863_01_mangos_spell_proc_event.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_8856_01_mangos_spell_proc_event required_8863_01_mangos_spell_proc_event bit; + +DELETE FROM `spell_proc_event` WHERE `entry` IN (58616,58617); +INSERT INTO `spell_proc_event` VALUES +(58616, 0x00000000, 15, 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0); diff --git a/sql/updates/8873_01_mangos_spell_proc_event.sql b/sql/updates/8873_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..498e2b99d --- /dev/null +++ b/sql/updates/8873_01_mangos_spell_proc_event.sql @@ -0,0 +1,6 @@ +ALTER TABLE db_version CHANGE COLUMN required_8863_01_mangos_spell_proc_event required_8873_01_mangos_spell_proc_event bit; + +-- (56816) Rune Strike () +DELETE FROM `spell_proc_event` WHERE `entry` IN (56816); +INSERT INTO `spell_proc_event` VALUES +(56816, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000030, 0.000000, 0.000000, 0); diff --git a/sql/updates/8873_02_mangos_spell_learn_spell.sql b/sql/updates/8873_02_mangos_spell_learn_spell.sql new file mode 100644 index 000000000..67f13225d --- /dev/null +++ b/sql/updates/8873_02_mangos_spell_learn_spell.sql @@ -0,0 +1,4 @@ +ALTER TABLE db_version CHANGE COLUMN required_8873_01_mangos_spell_proc_event required_8873_02_mangos_spell_learn_spell bit; + +DELETE FROM spell_learn_spell WHERE SpellID = 56816; +INSERT INTO spell_learn_spell VALUES (56815, 56816, 0); diff --git a/sql/updates/8874_01_characters_character_skills.sql b/sql/updates/8874_01_characters_character_skills.sql new file mode 100644 index 000000000..5e28b4837 --- /dev/null +++ b/sql/updates/8874_01_characters_character_skills.sql @@ -0,0 +1,50 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_8843_01_characters required_8874_01_characters_character_skills bit; + +DROP TABLE IF EXISTS `character_skills`; +CREATE TABLE `character_skills` ( + `guid` int(11) unsigned NOT NULL COMMENT 'Global Unique Identifier', + `skill` mediumint(9) unsigned NOT NULL, + `value` int(11) unsigned NOT NULL, + `max` mediumint(9) unsigned NOT NULL, + i mediumint(9), + PRIMARY KEY (`guid`,`skill`,`i`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System'; + + +DROP TABLE IF EXISTS temp_skills; +CREATE TABLE temp_skills ( + i int(11) unsigned NOT NULL, + PRIMARY KEY (i) +); + +INSERT INTO temp_skills VALUES +( 0),( 1),( 2),( 3),( 4),( 5),( 6),( 7),( 8),( 9),(10),(11),(12),(13),(14),(15),(16),(17),(18),(19), +(20),(21),(22),(23),(24),(25),(26),(27),(28),(29),(30),(31),(32),(33),(34),(35),(36),(37),(38),(39), +(40),(41),(42),(43),(44),(45),(46),(47),(48),(49),(50),(51),(52),(53),(54),(55),(56),(57),(58),(59), +(60),(61),(62),(63),(64),(65),(66),(67),(68),(69),(70),(71),(72),(73),(74),(75),(76),(77),(78),(79), +(80),(81),(82),(83),(84),(85),(86),(87),(88),(89),(90),(91),(92),(93),(94),(95),(96),(97),(98),(99), +(100),(101),(102),(103),(104),(105),(106),(107),(108),(109),(110),(111),(112),(113),(114),(115),(116),(117),(118),(119), +(120),(121),(122),(123),(124),(125),(126),(127); + +INSERT INTO character_skills SELECT +guid, +((SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 610+3*i))+2, length(SUBSTRING_INDEX(data, ' ', 610+3*i+1))- length(SUBSTRING_INDEX(data, ' ', 610+3*i)) - 1)) & 0xFFFF) as skill, +(SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 610+3*i+1))+2, length(SUBSTRING_INDEX(data, ' ', 610+3*i+2))- length(SUBSTRING_INDEX(data, ' ', 610+3*i+1)) - 1)) as value, +(0) as max, +i +FROM characters, temp_skills; + +DELETE FROM character_skills WHERE skill = 0; +DROP TABLE IF EXISTS temp_skills; + +UPDATE character_skills + SET max = ((value & 0xFFFF0000) >> 16); + +UPDATE character_skills + SET value = (value & 0xFFFF); + +ALTER IGNORE TABLE character_skills + CHANGE COLUMN value value mediumint(9) unsigned NOT NULL, + DROP PRIMARY KEY, + ADD PRIMARY KEY (guid,skill), + DROP COLUMN i; diff --git a/sql/updates/8882_01_mangos_spell_proc_event.sql b/sql/updates/8882_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..bc8c52539 --- /dev/null +++ b/sql/updates/8882_01_mangos_spell_proc_event.sql @@ -0,0 +1,7 @@ +ALTER TABLE db_version CHANGE COLUMN required_8873_02_mangos_spell_learn_spell required_8882_01_mangos_spell_proc_event bit; + +DELETE FROM `spell_proc_event` WHERE `entry` IN (63625); +INSERT INTO `spell_proc_event` VALUES +(63625, 0x00000000, 6, 0x02000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000, 0.000000, 0.000000, 0); + +DELETE FROM spell_proc_event WHERE entry IN (56637, 56638); diff --git a/sql/updates/8882_02_mangos_spell_chain.sql b/sql/updates/8882_02_mangos_spell_chain.sql new file mode 100644 index 000000000..4305211da --- /dev/null +++ b/sql/updates/8882_02_mangos_spell_chain.sql @@ -0,0 +1,9 @@ +ALTER TABLE db_version CHANGE COLUMN required_8882_01_mangos_spell_proc_event required_8882_02_mangos_spell_chain bit; + +DELETE FROM spell_chain WHERE first_spell = 56636; + +/*Taste for Blood*/ +INSERT INTO spell_chain VALUES + (56636, 0, 56636, 1, 0), + (56637, 56636, 56636, 2, 0), + (56638, 56637, 56636, 3, 0); diff --git a/sql/updates/8882_03_mangos_spell_bonus_data.sql b/sql/updates/8882_03_mangos_spell_bonus_data.sql new file mode 100644 index 000000000..e297e8656 --- /dev/null +++ b/sql/updates/8882_03_mangos_spell_bonus_data.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_8882_02_mangos_spell_chain required_8882_03_mangos_spell_bonus_data bit; + +DELETE FROM spell_bonus_data WHERE entry = 63675; +INSERT INTO spell_bonus_data VALUES +(63675, 0, 0, 0, 'Priest - Improved Devouring Plague Triggered'); diff --git a/sql/updates/8883_01_mangos_spell_proc_event.sql b/sql/updates/8883_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..97930df79 --- /dev/null +++ b/sql/updates/8883_01_mangos_spell_proc_event.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_8882_03_mangos_spell_bonus_data required_8883_01_mangos_spell_proc_event bit; + +DELETE FROM `spell_proc_event` WHERE `entry` IN (63534); +INSERT INTO `spell_proc_event` VALUES +(63534, 0x00000000, 6, 0x00000040, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0); diff --git a/sql/updates/8883_02_mangos_spell_bonus_data.sql b/sql/updates/8883_02_mangos_spell_bonus_data.sql new file mode 100644 index 000000000..e71cb7335 --- /dev/null +++ b/sql/updates/8883_02_mangos_spell_bonus_data.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_8883_01_mangos_spell_proc_event required_8883_02_mangos_spell_bonus_data bit; + +DELETE FROM spell_bonus_data WHERE entry = 63544; +INSERT INTO spell_bonus_data VALUES +(63544, 0, 0, 0, 'Priest - Empowered Renew Triggered'); diff --git a/sql/updates/8886_01_mangos_string.sql b/sql/updates/8886_01_mangos_string.sql new file mode 100644 index 000000000..92843ab60 --- /dev/null +++ b/sql/updates/8886_01_mangos_string.sql @@ -0,0 +1,7 @@ +ALTER TABLE db_version CHANGE COLUMN required_8883_02_mangos_spell_bonus_data required_8886_01_mangos_string bit; + +DELETE FROM mangos_string WHERE entry IN(60,61,62); +INSERT INTO mangos_string VALUES +(60,'I\'m busy right now, come back later.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(61,'Username: ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(62,'Password: ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/8889_01_mangos_spell_pet_auras.sql b/sql/updates/8889_01_mangos_spell_pet_auras.sql new file mode 100644 index 000000000..6c731b65a --- /dev/null +++ b/sql/updates/8889_01_mangos_spell_pet_auras.sql @@ -0,0 +1,6 @@ +ALTER TABLE db_version CHANGE COLUMN required_8886_01_mangos_string required_8889_01_mangos_spell_pet_auras bit; + +DELETE FROM spell_pet_auras WHERE aura = 57989; + +INSERT INTO `spell_pet_auras` VALUES +(58228, 0, 19668, 57989); \ No newline at end of file diff --git a/sql/updates/8891_01_mangos_spell_proc_event.sql b/sql/updates/8891_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..757060d80 --- /dev/null +++ b/sql/updates/8891_01_mangos_spell_proc_event.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_8889_01_mangos_spell_pet_auras required_8891_01_mangos_spell_proc_event bit; + +DELETE FROM `spell_proc_event` WHERE `entry` IN (64976); +INSERT INTO `spell_proc_event` VALUES +(64976, 0x00000000, 4, 0x00000001, 0x00000000, 0x00000000, 0x00010000, 0x00000000, 0.000000, 0.000000, 0); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 2cd538c3e..8d6da8074 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -164,6 +164,25 @@ pkgdata_DATA = \ 8833_02_mangos_command.sql \ 8835_01_mangos_command.sql \ 8840_01_mangos_spell_proc_event.sql \ + 8841_01_mangos_spell_proc_event.sql \ + 8841_02_mangos_spell_chain.sql \ + 8843_01_characters.sql \ + 8847_01_mangos_spell_proc_event.sql \ + 8847_02_mangos_spell_chain.sql \ + 8851_01_mangos_spell_proc_event.sql \ + 8856_01_mangos_spell_proc_event.sql \ + 8863_01_mangos_spell_proc_event.sql \ + 8873_01_mangos_spell_proc_event.sql \ + 8873_02_mangos_spell_learn_spell.sql \ + 8874_01_characters_character_skills.sql \ + 8882_01_mangos_spell_proc_event.sql \ + 8882_02_mangos_spell_chain.sql \ + 8882_03_mangos_spell_bonus_data.sql \ + 8883_01_mangos_spell_proc_event.sql \ + 8883_02_mangos_spell_bonus_data.sql \ + 8886_01_mangos_string.sql \ + 8889_01_mangos_spell_pet_auras.sql \ + 8891_01_mangos_spell_proc_event.sql \ README ## Additional files to include when running 'make dist' @@ -308,4 +327,23 @@ EXTRA_DIST = \ 8833_02_mangos_command.sql \ 8835_01_mangos_command.sql \ 8840_01_mangos_spell_proc_event.sql \ + 8841_01_mangos_spell_proc_event.sql \ + 8841_02_mangos_spell_chain.sql \ + 8843_01_characters.sql \ + 8847_01_mangos_spell_proc_event.sql \ + 8847_02_mangos_spell_chain.sql \ + 8851_01_mangos_spell_proc_event.sql \ + 8856_01_mangos_spell_proc_event.sql \ + 8863_01_mangos_spell_proc_event.sql \ + 8873_01_mangos_spell_proc_event.sql \ + 8873_02_mangos_spell_learn_spell.sql \ + 8874_01_characters_character_skills.sql \ + 8882_01_mangos_spell_proc_event.sql \ + 8882_02_mangos_spell_chain.sql \ + 8882_03_mangos_spell_bonus_data.sql \ + 8883_01_mangos_spell_proc_event.sql \ + 8883_02_mangos_spell_bonus_data.sql \ + 8886_01_mangos_string.sql \ + 8889_01_mangos_spell_pet_auras.sql \ + 8891_01_mangos_spell_proc_event.sql \ README diff --git a/src/framework/Platform/Define.h b/src/framework/Platform/Define.h index 831849369..769765bdb 100644 --- a/src/framework/Platform/Define.h +++ b/src/framework/Platform/Define.h @@ -22,6 +22,8 @@ #include #include +#include +#include #include #include "Platform/CompilerDefs.h" @@ -37,22 +39,21 @@ # endif //ACE_BYTE_ORDER #endif //MANGOS_ENDIAN +typedef ACE_SHLIB_HANDLE MANGOS_LIBRARY_HANDLE; + +#define MANGOS_SCRIPT_NAME "mangosscript" +#define MANGOS_SCRIPT_SUFFIX ACE_DLL_SUFFIX +#define MANGOS_SCRIPT_PREFIX ACE_DLL_PREFIX +#define MANGOS_LOAD_LIBRARY(libname) ACE_OS::dlopen(libname) +#define MANGOS_CLOSE_LIBRARY(hlib) ACE_OS::dlclose(hlib) +#define MANGOS_GET_PROC_ADDR(hlib,name) ACE_OS::dlsym(hlib,name) + #if PLATFORM == PLATFORM_WINDOWS # define MANGOS_EXPORT __declspec(dllexport) -# define MANGOS_LIBRARY_HANDLE HMODULE -# define MANGOS_LOAD_LIBRARY(a) LoadLibrary(a) -# define MANGOS_CLOSE_LIBRARY FreeLibrary -# define MANGOS_GET_PROC_ADDR GetProcAddress # define MANGOS_IMPORT __cdecl -# define MANGOS_SCRIPT_EXT ".dll" -# define MANGOS_SCRIPT_NAME "MaNGOSScript" # define MANGOS_PATH_MAX MAX_PATH #else //PLATFORM != PLATFORM_WINDOWS -# define MANGOS_LIBRARY_HANDLE void* # define MANGOS_EXPORT export -# define MANGOS_LOAD_LIBRARY(a) dlopen(a,RTLD_NOW) -# define MANGOS_CLOSE_LIBRARY dlclose -# define MANGOS_GET_PROC_ADDR dlsym # if defined(__APPLE_CC__) && defined(BIG_ENDIAN) # define MANGOS_IMPORT __attribute__ ((longcall)) # elif defined(__x86_64__) @@ -60,8 +61,6 @@ # else # define MANGOS_IMPORT __attribute__ ((cdecl)) # endif //__APPLE_CC__ && BIG_ENDIAN -# define MANGOS_SCRIPT_EXT ".so" -# define MANGOS_SCRIPT_NAME "libmangosscript" # define MANGOS_PATH_MAX PATH_MAX #endif //PLATFORM diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 8c51fc020..e4c0b590f 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -302,7 +302,7 @@ bool AchievementCriteriaRequirement::Meets(Player const* source, Unit const* tar return false; return ((Player*)target)->GetTeam() == team.team; case ACHIEVEMENT_CRITERIA_REQUIRE_S_DRUNK: - return Player::GetDrunkenstateByValue(source->GetDrunkValue()) >= drunk.state; + return (uint32)Player::GetDrunkenstateByValue(source->GetDrunkValue()) >= drunk.state; case ACHIEVEMENT_CRITERIA_REQUIRE_HOLIDAY: return IsHolidayActive(HolidayIds(holiday.id)); case ACHIEVEMENT_CRITERIA_REQUIRE_BG_LOSS_TEAM_SCORE: diff --git a/src/game/AuctionHouseHandler.cpp b/src/game/AuctionHouseHandler.cpp index 565ba130f..067d65a29 100644 --- a/src/game/AuctionHouseHandler.cpp +++ b/src/game/AuctionHouseHandler.cpp @@ -323,7 +323,7 @@ void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data ) } // cheating - if(price <= auction->bid) + if(price <= auction->bid || price < auction->startbid) return; // price too low for next bid if not buyout diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index f6d322989..cb38b33cd 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -32,30 +32,33 @@ #include "Language.h" #include "ScriptCalls.h" -void WorldSession::HandleBattlemasterHelloOpcode( WorldPacket & recv_data ) +void WorldSession::HandleBattlemasterHelloOpcode(WorldPacket & recv_data) { uint64 guid; recv_data >> guid; - sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_HELLO Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid),GuidHigh2TypeId(GUID_HIPART(guid))); - Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); - if (!unit) + sLog.outDebug("WORLD: Recvd CMSG_BATTLEMASTER_HELLO Message from (GUID: %u TypeId:%u)", GUID_LOPART(guid),GuidHigh2TypeId(GUID_HIPART(guid))); + + Creature *pCreature = GetPlayer()->GetMap()->GetCreature(guid); + + if (!pCreature) return; - if(!unit->isBattleMaster()) // it's not battlemaster + if (!pCreature->isBattleMaster()) // it's not battlemaster return; // Stop the npc if moving - unit->StopMoving(); + if (!pCreature->IsStopped()) + pCreature->StopMoving(); - BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(unit->GetEntry()); + BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(pCreature->GetEntry()); if (bgTypeId == BATTLEGROUND_TYPE_NONE) return; if (!_player->GetBGAccessByLevel(bgTypeId)) { - // temp, must be gossip message... + // temp, must be gossip message... SendNotification(LANG_YOUR_BG_LEVEL_REQ_ERROR); return; } diff --git a/src/game/Channel.cpp b/src/game/Channel.cpp index 026c2eae2..7da136276 100644 --- a/src/game/Channel.cpp +++ b/src/game/Channel.cpp @@ -446,7 +446,7 @@ void Channel::List(Player* player) size_t pos = data.wpos(); data << uint32(0); // size of list, placeholder - uint32 gmLevelInWhoList = sWorld.getConfig(CONFIG_GM_LEVEL_IN_WHO_LIST); + AccountTypes gmLevelInWhoList = (AccountTypes)sWorld.getConfig(CONFIG_GM_LEVEL_IN_WHO_LIST); uint32 count = 0; for(PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 69cd034c5..7e2417593 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -85,6 +85,7 @@ bool LoginQueryHolder::Initialize() res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS, "SELECT setguid, setindex, name, iconname, item0, item1, item2, item3, item4, item5, item6, item7, item8, item9, item10, item11, item12, item13, item14, item15, item16, item17, item18 FROM character_equipmentsets WHERE guid = '%u' ORDER BY setindex", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBGDATA, "SELECT instance_id, team, join_x, join_y, join_z, join_o, join_map, taxi_start, taxi_end, mount_spell FROM character_battleground_data WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA, "SELECT type, time, data FROM character_account_data WHERE guid='%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = '%u'", GUID_LOPART(m_guid)); return res; } diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 4c2654697..23457fdf7 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -700,7 +700,7 @@ const char *ChatHandler::GetMangosString(int32 entry) const bool ChatHandler::isAvailable(ChatCommand const& cmd) const { // check security level only for simple command (without child commands) - return m_session->GetSecurity() >= cmd.SecurityLevel; + return m_session->GetSecurity() >= (AccountTypes)cmd.SecurityLevel; } bool ChatHandler::HasLowerSecurity(Player* target, uint64 guid, bool strong) @@ -742,7 +742,7 @@ bool ChatHandler::HasLowerSecurityAccount(WorldSession* target, uint32 target_ac else return true; // caller must report error for (target==NULL && target_account==0) - if (m_session->GetSecurity() < target_sec || (strong && m_session->GetSecurity() <= target_sec)) + if (m_session->GetSecurity() < target_sec || (strong && (uint32)m_session->GetSecurity() <= target_sec)) { SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); SetSentErrorMessage(true); @@ -1521,7 +1521,7 @@ valid examples: for(uint8 i=LOCALE_koKR; i= il->Name.size()) + if (dbIndex == -1 || il == NULL || (size_t)dbIndex >= il->Name.size()) // using strange database/client combinations can lead to this case expectedName = linkedItem->Name1; else diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 416ef1912..679951a9f 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -838,9 +838,9 @@ void Creature::prepareGossipMenu( Player *pPlayer,uint32 gossipid ) NpcOptionLocale const *no = sObjectMgr.GetNpcOptionLocale(gso->Id); if (no) { - if (no->OptionText.size() > loc_idx && !no->OptionText[loc_idx].empty()) + if (no->OptionText.size() > (size_t)loc_idx && !no->OptionText[loc_idx].empty()) OptionText=no->OptionText[loc_idx]; - if (no->BoxText.size() > loc_idx && !no->BoxText[loc_idx].empty()) + if (no->BoxText.size() > (size_t)loc_idx && !no->BoxText[loc_idx].empty()) BoxText=no->BoxText[loc_idx]; } } @@ -2301,7 +2301,7 @@ const char* Creature::GetNameForLocaleIdx(int32 loc_idx) const CreatureLocale const *cl = sObjectMgr.GetCreatureLocale(GetEntry()); if (cl) { - if (cl->Name.size() > loc_idx && !cl->Name[loc_idx].empty()) + if (cl->Name.size() > (size_t)loc_idx && !cl->Name[loc_idx].empty()) return cl->Name[loc_idx].c_str(); } } diff --git a/src/game/CreatureAISelector.cpp b/src/game/CreatureAISelector.cpp index e446f72b7..d68ee8ac2 100644 --- a/src/game/CreatureAISelector.cpp +++ b/src/game/CreatureAISelector.cpp @@ -46,8 +46,8 @@ namespace FactorySelector // select by NPC flags _first_ - otherwise EventAI might be choosen for pets/totems // excplicit check for isControlled() and owner type to allow guardian, mini-pets and pets controlled by NPCs to be scripted by EventAI Unit *owner=NULL; - if (creature->isPet() && ((Pet*)creature)->isControlled() && - ((owner=creature->GetOwner()) && owner->GetTypeId()==TYPEID_PLAYER) || creature->isCharmed()) + if ((creature->isPet() && ((Pet*)creature)->isControlled() && + ((owner=creature->GetOwner()) && owner->GetTypeId()==TYPEID_PLAYER)) || creature->isCharmed()) ai_factory = ai_registry.GetRegistryItem("PetAI"); else if (creature->isTotem()) ai_factory = ai_registry.GetRegistryItem("TotemAI"); diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index 078e4335a..62b748323 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -292,7 +292,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction //Note: checked only aura for effect 0, if need check aura for effect 1/2 then // possible way: pack in event.buffed.amount 2 uint16 (ammount+effectIdx) Aura* aura = m_creature->GetAura(event.buffed.spellId,0); - if(!aura || aura->GetStackAmount() < event.buffed.amount) + if (!aura || aura->GetStackAmount() < event.buffed.amount) return false; //Repeat Timers @@ -523,8 +523,8 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 break; case ACTION_T_THREAT_ALL_PCT: { - std::list& threatList = m_creature->getThreatManager().getThreatList(); - for (std::list::iterator i = threatList.begin(); i != threatList.end(); ++i) + ThreatList const& threatList = m_creature->getThreatManager().getThreatList(); + for (ThreatList::const_iterator i = threatList.begin(); i != threatList.end(); ++i) if(Unit* Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid())) m_creature->getThreatManager().modifyThreatPercent(Temp, action.threat_all_pct.percent); break; @@ -634,8 +634,8 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 break; case ACTION_T_CAST_EVENT_ALL: { - std::list& threatList = m_creature->getThreatManager().getThreatList(); - for (std::list::iterator i = threatList.begin(); i != threatList.end(); ++i) + ThreatList const& threatList = m_creature->getThreatManager().getThreatList(); + for (ThreatList::const_iterator i = threatList.begin(); i != threatList.end(); ++i) if (Unit* Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid())) if (Temp->GetTypeId() == TYPEID_PLAYER) ((Player*)Temp)->CastedCreatureOrGO(action.cast_event_all.creatureId, m_creature->GetGUID(), action.cast_event_all.spellId); @@ -1111,21 +1111,21 @@ bool CreatureEventAI::IsVisible(Unit *pl) const && pl->isVisibleForOrDetect(m_creature,m_creature,true); } -inline Unit* CreatureEventAI::SelectUnit(AttackingTarget target, uint32 position) +inline Unit* CreatureEventAI::SelectUnit(AttackingTarget target, uint32 position) const { //ThreatList m_threatlist; - std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); - std::list::iterator i = m_threatlist.begin(); - std::list::reverse_iterator r = m_threatlist.rbegin(); + ThreatList const& threatlist = m_creature->getThreatManager().getThreatList(); + ThreatList::const_iterator i = threatlist.begin(); + ThreatList::const_reverse_iterator r = threatlist.rbegin(); - if (position >= m_threatlist.size() || !m_threatlist.size()) + if (position >= threatlist.size() || !threatlist.size()) return NULL; switch (target) { case ATTACKING_TARGET_RANDOM: { - advance ( i , position + (rand() % (m_threatlist.size() - position ) )); + advance ( i , position + (rand() % (threatlist.size() - position ) )); return Unit::GetUnit(*m_creature,(*i)->getUnitGuid()); } case ATTACKING_TARGET_TOPAGGRO: diff --git a/src/game/CreatureEventAI.h b/src/game/CreatureEventAI.h index 5d942b6e7..6124fb884 100644 --- a/src/game/CreatureEventAI.h +++ b/src/game/CreatureEventAI.h @@ -594,7 +594,7 @@ class MANGOS_DLL_SPEC CreatureEventAI : public CreatureAI inline uint32 GetRandActionParam(uint32 rnd, uint32 param1, uint32 param2, uint32 param3); inline int32 GetRandActionParam(uint32 rnd, int32 param1, int32 param2, int32 param3); inline Unit* GetTargetByType(uint32 Target, Unit* pActionInvoker); - inline Unit* SelectUnit(AttackingTarget target, uint32 position); + inline Unit* SelectUnit(AttackingTarget target, uint32 position) const; void DoScriptText(int32 textEntry, WorldObject* pSource, Unit* target); void DoMeleeAttackIfReady(); diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index f7efae548..6088ab008 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -1769,7 +1769,7 @@ struct MapDifficulty MapDifficulty(uint32 _resetTime, uint32 _maxPlayers) : resetTime(_resetTime), maxPlayers(_maxPlayers) {} uint32 resetTime; - uint32 maxPlayers; + uint32 maxPlayers; // some heroic dungeons have 0 when expect same value as in normal dificulty case }; struct TalentSpellPos diff --git a/src/game/GameEventMgr.cpp b/src/game/GameEventMgr.cpp index a29c48644..2249b9465 100644 --- a/src/game/GameEventMgr.cpp +++ b/src/game/GameEventMgr.cpp @@ -199,7 +199,7 @@ void GameEventMgr::LoadFromDB() int32 internal_event_id = mGameEvent.size() + event_id - 1; - if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size()) + if(internal_event_id < 0 || (size_t)internal_event_id >= mGameEventCreatureGuids.size()) { sLog.outErrorDb("`game_event_creature` game event id (%i) is out of range compared to max event id in `game_event`",event_id); continue; @@ -245,7 +245,7 @@ void GameEventMgr::LoadFromDB() int32 internal_event_id = mGameEvent.size() + event_id - 1; - if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size()) + if(internal_event_id < 0 || (size_t)internal_event_id >= mGameEventGameobjectGuids.size()) { sLog.outErrorDb("`game_event_gameobject` game event id (%i) is out of range compared to max event id in `game_event`",event_id); continue; @@ -394,7 +394,7 @@ void GameEventMgr::LoadFromDB() int32 internal_event_id = mGameEvent.size() + event_id - 1; - if(internal_event_id < 0 || internal_event_id >= mGameEventPoolIds.size()) + if (internal_event_id < 0 || (size_t)internal_event_id >= mGameEventPoolIds.size()) { sLog.outErrorDb("`game_event_pool` game event id (%i) is out of range compared to max event id in `game_event`",event_id); continue; @@ -506,7 +506,7 @@ void GameEventMgr::GameEventSpawn(int16 event_id) { int32 internal_event_id = mGameEvent.size() + event_id - 1; - if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size()) + if (internal_event_id < 0 || (size_t)internal_event_id >= mGameEventCreatureGuids.size()) { sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventCreatureGuids element %i (size: " SIZEFMTD ")",internal_event_id,mGameEventCreatureGuids.size()); return; @@ -539,7 +539,7 @@ void GameEventMgr::GameEventSpawn(int16 event_id) } } - if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size()) + if (internal_event_id < 0 || (size_t)internal_event_id >= mGameEventGameobjectGuids.size()) { sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventGameobjectGuids element %i (size: " SIZEFMTD ")",internal_event_id,mGameEventGameobjectGuids.size()); return; @@ -573,7 +573,7 @@ void GameEventMgr::GameEventSpawn(int16 event_id) } } - if(internal_event_id < 0 || internal_event_id >= mGameEventPoolIds.size()) + if (internal_event_id < 0 || (size_t)internal_event_id >= mGameEventPoolIds.size()) { sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventPoolIds element %i (size: " SIZEFMTD ")",internal_event_id,mGameEventPoolIds.size()); return; @@ -591,7 +591,7 @@ void GameEventMgr::GameEventUnspawn(int16 event_id) { int32 internal_event_id = mGameEvent.size() + event_id - 1; - if(internal_event_id < 0 || internal_event_id >= mGameEventCreatureGuids.size()) + if (internal_event_id < 0 || (size_t)internal_event_id >= mGameEventCreatureGuids.size()) { sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventCreatureGuids element %i (size: " SIZEFMTD ")",internal_event_id,mGameEventCreatureGuids.size()); return; @@ -609,7 +609,7 @@ void GameEventMgr::GameEventUnspawn(int16 event_id) } } - if(internal_event_id < 0 || internal_event_id >= mGameEventGameobjectGuids.size()) + if (internal_event_id < 0 || (size_t)internal_event_id >= mGameEventGameobjectGuids.size()) { sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventGameobjectGuids element %i (size: " SIZEFMTD ")",internal_event_id,mGameEventGameobjectGuids.size()); return; @@ -626,7 +626,7 @@ void GameEventMgr::GameEventUnspawn(int16 event_id) pGameobject->AddObjectToRemoveList(); } } - if(internal_event_id < 0 || internal_event_id >= mGameEventPoolIds.size()) + if (internal_event_id < 0 || (size_t)internal_event_id >= mGameEventPoolIds.size()) { sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventPoolIds element %i (size: " SIZEFMTD ")",internal_event_id,mGameEventPoolIds.size()); return; @@ -755,7 +755,7 @@ MANGOS_DLL_SPEC bool IsHolidayActive( HolidayIds id ) GameEventMgr::ActiveEvents const& ae = sGameEventMgr.GetActiveEventList(); for(GameEventMgr::ActiveEvents::const_iterator itr = ae.begin(); itr != ae.end(); ++itr) - if(events[*itr].holiday_id==id) + if (events[*itr].holiday_id == id) return true; return false; diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 5dbd927b1..0aa6f7f99 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -1296,7 +1296,7 @@ const char* GameObject::GetNameForLocaleIdx(int32 loc_idx) const GameObjectLocale const *cl = sObjectMgr.GetGameObjectLocale(GetEntry()); if (cl) { - if (cl->Name.size() > loc_idx && !cl->Name[loc_idx].empty()) + if (cl->Name.size() > (size_t)loc_idx && !cl->Name[loc_idx].empty()) return cl->Name[loc_idx].c_str(); } } diff --git a/src/game/GossipDef.cpp b/src/game/GossipDef.cpp index 9b4a78108..e64166d9d 100644 --- a/src/game/GossipDef.cpp +++ b/src/game/GossipDef.cpp @@ -160,7 +160,7 @@ void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID ) QuestLocale const *ql = sObjectMgr.GetQuestLocale(questID); if (ql) { - if (ql->Title.size() > loc_idx && !ql->Title[loc_idx].empty()) + if (ql->Title.size() > (size_t)loc_idx && !ql->Title[loc_idx].empty()) Title=ql->Title[loc_idx]; } } @@ -266,9 +266,9 @@ void PlayerMenu::SendTalking( uint32 textID ) { for (int i=0;i<8;++i) { - if (nl->Text_0[i].size() > loc_idx && !nl->Text_0[i][loc_idx].empty()) + if (nl->Text_0[i].size() > (size_t)loc_idx && !nl->Text_0[i][loc_idx].empty()) Text_0[i]=nl->Text_0[i][loc_idx]; - if (nl->Text_1[i].size() > loc_idx && !nl->Text_1[i][loc_idx].empty()) + if (nl->Text_1[i].size() > (size_t)loc_idx && !nl->Text_1[i][loc_idx].empty()) Text_1[i]=nl->Text_1[i][loc_idx]; } } @@ -393,7 +393,7 @@ void PlayerMenu::SendQuestGiverQuestList( QEmote eEmote, const std::string& Titl { if(QuestLocale const *ql = sObjectMgr.GetQuestLocale(questID)) { - if (ql->Title.size() > loc_idx && !ql->Title[loc_idx].empty()) + if (ql->Title.size() > (size_t)loc_idx && !ql->Title[loc_idx].empty()) title=ql->Title[loc_idx]; } } @@ -430,13 +430,13 @@ void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID QuestLocale const *ql = sObjectMgr.GetQuestLocale(pQuest->GetQuestId()); if (ql) { - if (ql->Title.size() > loc_idx && !ql->Title[loc_idx].empty()) + if (ql->Title.size() > (size_t)loc_idx && !ql->Title[loc_idx].empty()) Title=ql->Title[loc_idx]; - if (ql->Details.size() > loc_idx && !ql->Details[loc_idx].empty()) + if (ql->Details.size() > (size_t)loc_idx && !ql->Details[loc_idx].empty()) Details=ql->Details[loc_idx]; - if (ql->Objectives.size() > loc_idx && !ql->Objectives[loc_idx].empty()) + if (ql->Objectives.size() > (size_t)loc_idx && !ql->Objectives[loc_idx].empty()) Objectives=ql->Objectives[loc_idx]; - if (ql->EndText.size() > loc_idx && !ql->EndText[loc_idx].empty()) + if (ql->EndText.size() > (size_t)loc_idx && !ql->EndText[loc_idx].empty()) EndText=ql->EndText[loc_idx]; } } @@ -541,17 +541,17 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest ) QuestLocale const *ql = sObjectMgr.GetQuestLocale(pQuest->GetQuestId()); if (ql) { - if (ql->Title.size() > loc_idx && !ql->Title[loc_idx].empty()) + if (ql->Title.size() > (size_t)loc_idx && !ql->Title[loc_idx].empty()) Title=ql->Title[loc_idx]; - if (ql->Details.size() > loc_idx && !ql->Details[loc_idx].empty()) + if (ql->Details.size() > (size_t)loc_idx && !ql->Details[loc_idx].empty()) Details=ql->Details[loc_idx]; - if (ql->Objectives.size() > loc_idx && !ql->Objectives[loc_idx].empty()) + if (ql->Objectives.size() > (size_t)loc_idx && !ql->Objectives[loc_idx].empty()) Objectives=ql->Objectives[loc_idx]; - if (ql->EndText.size() > loc_idx && !ql->EndText[loc_idx].empty()) + if (ql->EndText.size() > (size_t)loc_idx && !ql->EndText[loc_idx].empty()) EndText=ql->EndText[loc_idx]; for (int i = 0;i < QUEST_OBJECTIVES_COUNT; ++i) - if (ql->ObjectiveText[i].size() > loc_idx && !ql->ObjectiveText[i][loc_idx].empty()) + if (ql->ObjectiveText[i].size() > (size_t)loc_idx && !ql->ObjectiveText[i][loc_idx].empty()) ObjectiveText[i] = ql->ObjectiveText[i][loc_idx]; } } @@ -679,9 +679,9 @@ void PlayerMenu::SendQuestGiverOfferReward( Quest const* pQuest, uint64 npcGUID, QuestLocale const *ql = sObjectMgr.GetQuestLocale(pQuest->GetQuestId()); if (ql) { - if (ql->Title.size() > loc_idx && !ql->Title[loc_idx].empty()) + if (ql->Title.size() > (size_t)loc_idx && !ql->Title[loc_idx].empty()) Title=ql->Title[loc_idx]; - if (ql->OfferRewardText.size() > loc_idx && !ql->OfferRewardText[loc_idx].empty()) + if (ql->OfferRewardText.size() > (size_t)loc_idx && !ql->OfferRewardText[loc_idx].empty()) OfferRewardText=ql->OfferRewardText[loc_idx]; } } @@ -781,9 +781,9 @@ void PlayerMenu::SendQuestGiverRequestItems( Quest const *pQuest, uint64 npcGUID QuestLocale const *ql = sObjectMgr.GetQuestLocale(pQuest->GetQuestId()); if (ql) { - if (ql->Title.size() > loc_idx && !ql->Title[loc_idx].empty()) + if (ql->Title.size() > (size_t)loc_idx && !ql->Title[loc_idx].empty()) Title=ql->Title[loc_idx]; - if (ql->RequestItemsText.size() > loc_idx && !ql->RequestItemsText[loc_idx].empty()) + if (ql->RequestItemsText.size() > (size_t)loc_idx && !ql->RequestItemsText[loc_idx].empty()) RequestItemsText=ql->RequestItemsText[loc_idx]; } } diff --git a/src/game/Group.cpp b/src/game/Group.cpp index 6ea74d414..ab76bae09 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -1577,7 +1577,7 @@ void Group::ResetInstances(uint8 method, bool isRaid, Player* SendMsgTo) { InstanceSave *p = itr->second.save; const MapEntry *entry = sMapStore.LookupEntry(itr->first); - if(!entry || entry->IsRaid() != isRaid || !p->CanReset() && method != INSTANCE_RESET_GROUP_DISBAND) + if (!entry || entry->IsRaid() != isRaid || (!p->CanReset() && method != INSTANCE_RESET_GROUP_DISBAND)) { ++itr; continue; diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp index 7c7677bd3..b113b0caf 100644 --- a/src/game/GuildHandler.cpp +++ b/src/game/GuildHandler.cpp @@ -1072,7 +1072,7 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data ) recv_data >> SplitedAmount; } - if (BankTabSlot >= GUILD_BANK_MAX_SLOTS && BankTabSlot != 0xFF || + if ((BankTabSlot >= GUILD_BANK_MAX_SLOTS && BankTabSlot != 0xFF) || BankTab >= pGuild->GetPurchasedTabs()) { recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet diff --git a/src/game/HostileRefManager.cpp b/src/game/HostileRefManager.cpp index 12accb7cf..b173f7706 100644 --- a/src/game/HostileRefManager.cpp +++ b/src/game/HostileRefManager.cpp @@ -107,6 +107,24 @@ void HostileRefManager::deleteReferences() } } +//================================================= +// delete one reference, defined by faction + +void HostileRefManager::deleteReferencesForFaction(uint32 faction) +{ + HostileReference* ref = getFirst(); + while(ref) + { + HostileReference* nextRef = ref->next(); + if(ref->getSource()->getOwner()->getFactionTemplateEntry()->faction == faction) + { + ref->removeReference(); + delete ref; + } + ref = nextRef; + } +} + //================================================= // delete one reference, defined by Unit diff --git a/src/game/HostileRefManager.h b/src/game/HostileRefManager.h index 93945e669..a2555858d 100644 --- a/src/game/HostileRefManager.h +++ b/src/game/HostileRefManager.h @@ -50,6 +50,9 @@ class HostileRefManager : public RefManager // tell the source to remove them from the list and free the mem void deleteReferences(); + // Remove specific faction references + void deleteReferencesForFaction(uint32 faction); + HostileReference* getFirst() { return ((HostileReference* ) RefManager::getFirst()); } void updateThreatTables(); diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp index ea713d95a..54f71b2ce 100644 --- a/src/game/InstanceSaveMgr.cpp +++ b/src/game/InstanceSaveMgr.cpp @@ -80,7 +80,7 @@ InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instance const MapEntry* entry = sMapStore.LookupEntry(mapId); if (!entry) { - sLog.outError("InstanceSaveManager::AddInstanceSave: wrong mapid = %d!", mapId, instanceId); + sLog.outError("InstanceSaveManager::AddInstanceSave: wrong mapid = %d, instanceid = %d!", mapId, instanceId); return NULL; } diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 23af0d5d6..6f235125e 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -700,29 +700,32 @@ void WorldSession::HandleListInventoryOpcode( WorldPacket & recv_data ) SendListInventory( guid ); } -void WorldSession::SendListInventory( uint64 vendorguid ) +void WorldSession::SendListInventory(uint64 vendorguid) { - sLog.outDebug( "WORLD: Sent SMSG_LIST_INVENTORY" ); + sLog.outDebug("WORLD: Sent SMSG_LIST_INVENTORY"); Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR); + if (!pCreature) { - sLog.outDebug( "WORLD: SendListInventory - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) ); - _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0); + sLog.outDebug("WORLD: SendListInventory - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid))); + _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0); return; } // remove fake death - if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); // Stop the npc if moving - pCreature->StopMoving(); + if (!pCreature->IsStopped()) + pCreature->StopMoving(); VendorItemData const* vItems = pCreature->GetVendorItems(); - if(!vItems) + + if (!vItems) { - _player->SendSellError( SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0); + _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0, 0); return; } diff --git a/src/game/LFGHandler.cpp b/src/game/LFGHandler.cpp index 7ab6fe4e0..46055f8dd 100644 --- a/src/game/LFGHandler.cpp +++ b/src/game/LFGHandler.cpp @@ -45,7 +45,7 @@ static void AttemptJoin(Player* _player) continue; // skip not auto add, not group leader cases - if(!plr->GetSession()->LookingForGroup_auto_add || plr->GetGroup() && plr->GetGroup()->GetLeaderGUID()!=plr->GetGUID()) + if (!plr->GetSession()->LookingForGroup_auto_add || (plr->GetGroup() && plr->GetGroup()->GetLeaderGUID()!=plr->GetGUID())) continue; // skip non auto-join or empty slots, or non compatible slots diff --git a/src/game/Language.h b/src/game/Language.h index bc8aa8668..9f9f7afad 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -83,7 +83,10 @@ enum MangosStrings LANG_USING_WORLD_DB = 57, LANG_USING_SCRIPT_LIB = 58, LANG_USING_EVENT_AI = 59, - // Room for more level 0 60-99 not used + LANG_RA_BUSY = 60, + LANG_RA_USER = 61, + LANG_RA_PASS = 62, + // Room for more level 0 63-99 not used // level 1 chat LANG_GLOBAL_NOTIFY = 100, diff --git a/src/game/LootHandler.cpp b/src/game/LootHandler.cpp index d96aef44e..a19e8d014 100644 --- a/src/game/LootHandler.cpp +++ b/src/game/LootHandler.cpp @@ -350,7 +350,7 @@ void WorldSession::DoLootRelease( uint64 lguid ) else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more go->AddUse(); // if the max usage is reached, will be despawned in next tick - if (go->GetUseCount()>=irand(go->GetGOInfo()->fishinghole.minSuccessOpens,go->GetGOInfo()->fishinghole.maxSuccessOpens)) + if (go->GetUseCount() >= irand(go->GetGOInfo()->fishinghole.minSuccessOpens,go->GetGOInfo()->fishinghole.maxSuccessOpens)) { go->SetLootState(GO_JUST_DEACTIVATED); } diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp index 5e561db59..0557b6a59 100644 --- a/src/game/Mail.cpp +++ b/src/game/Mail.cpp @@ -671,7 +671,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket & recv_data ) Player *pl = _player; Mail* m = pl->GetMail(mailId); - if(!m || !m->itemTextId && !m->mailTemplateId || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) + if (!m || (!m->itemTextId && !m->mailTemplateId) || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) { pl->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_ERR_INTERNAL_ERROR); return; diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 59ed9dd11..2d174e42d 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -200,9 +200,9 @@ void Map::DeleteStateMachine() Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent) : i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), i_id(id), i_InstanceId(InstanceId), m_unloadTimer(0), + m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE), m_activeNonPlayersIter(m_activeNonPlayers.end()), i_gridExpiry(expiry), m_parentMap(_parent ? _parent : this), - m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE), m_hiDynObjectGuid(1), m_hiPetGuid(1), m_hiVehicleGuid(1) { for(unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx) @@ -1134,8 +1134,18 @@ MapDifficulty const* Map::GetMapDifficulty() const uint32 Map::GetMaxPlayers() const { - MapDifficulty const* mapDiff = GetMapDifficulty(); - return mapDiff ? mapDiff->maxPlayers : 0; + if(MapDifficulty const* mapDiff = GetMapDifficulty()) + { + if(mapDiff->maxPlayers || IsRegularDifficulty()) // Normal case (expect that regular difficulty always have correct maxplayers) + return mapDiff->maxPlayers; + else // DBC have 0 maxplayers for heroic instances with expansion < 2 + { // The heroic entry exists, so we don't have to check anything, simply return normal max players + MapDifficulty const* normalDiff = GetMapDifficultyData(i_id, REGULAR_DIFFICULTY); + return normalDiff ? normalDiff->maxPlayers : 0; + } + } + else // I'd rather assert(false); + return 0; } uint32 Map::GetMaxResetDelay() const @@ -1747,6 +1757,7 @@ uint16 Map::GetAreaFlag(float x, float y, float z) const if(z > 350.0f) areaflag = 1950; break; // Dalaran case 2492: // Forlorn Woods (Crystalsong Forest) + case 2371: // Valley of Echoes (Icecrown Glacier) if (x > 5568.0f && x < 6116.0f && y > 282.0f && y < 982.0f && z > 563.0f) { // Krasus' Landing (Dalaran), fast check diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 18821b0a3..59a272a32 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -136,7 +136,7 @@ void WorldSession::HandleWhoOpcode( WorldPacket & recv_data ) uint32 team = _player->GetTeam(); uint32 security = GetSecurity(); bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST); - uint32 gmLevelInWhoList = sWorld.getConfig(CONFIG_GM_LEVEL_IN_WHO_LIST); + AccountTypes gmLevelInWhoList = (AccountTypes)sWorld.getConfig(CONFIG_GM_LEVEL_IN_WHO_LIST); WorldPacket data( SMSG_WHO, 50 ); // guess size data << clientcount; // clientcount place holder @@ -153,7 +153,7 @@ void WorldSession::HandleWhoOpcode( WorldPacket & recv_data ) continue; // player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if CONFIG_GM_IN_WHO_LIST - if ((itr->second->GetSession()->GetSecurity() > gmLevelInWhoList)) + if (itr->second->GetSession()->GetSecurity() > gmLevelInWhoList) continue; } diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 096783e00..8dd54a60a 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -249,37 +249,36 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) SendPacket(&data); } -void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data ) +void WorldSession::HandleGossipHelloOpcode(WorldPacket & recv_data) { - sLog.outDebug( "WORLD: Received CMSG_GOSSIP_HELLO" ); + sLog.outDebug("WORLD: Received CMSG_GOSSIP_HELLO"); uint64 guid; recv_data >> guid; - Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); - if (!unit) + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); + + if (!pCreature) { - sLog.outDebug( "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); + sLog.outDebug("WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); return; } // remove fake death - if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); - if( unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider()) - { - unit->StopMoving(); - } + if (!pCreature->IsStopped()) + pCreature->StopMoving(); - if (unit->isSpiritGuide()) - unit->SendAreaSpiritHealerQueryOpcode(_player); + if (pCreature->isSpiritGuide()) + pCreature->SendAreaSpiritHealerQueryOpcode(_player); - if(!Script->GossipHello( _player, unit )) + if (!Script->GossipHello(_player, pCreature)) { - _player->TalkedToCreature(unit->GetEntry(),unit->GetGUID()); - unit->prepareGossipMenu(_player); - unit->sendPreparedGossip(_player); + _player->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); + pCreature->prepareGossipMenu(_player); + pCreature->sendPreparedGossip(_player); } } diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 7b3900fad..8e608a954 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -181,8 +181,8 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) c if(isType(TYPEMASK_UNIT)) { - if(((Unit*)this)->GetTargetGUID()) - flags |= UPDATEFLAG_HAS_TARGET; + if(((Unit*)this)->getVictim()) + flags |= UPDATEFLAG_HAS_ATTACKING_TARGET; } } @@ -261,7 +261,27 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2) { case TYPEID_UNIT: { - flags2 = ((Creature*)this)->canFly() ? (MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_LEVITATING) : MOVEMENTFLAG_NONE; + flags2 = MOVEMENTFLAG_NONE; + + if (!((Creature*)this)->IsStopped()) + flags2 |= MOVEMENTFLAG_FORWARD; // not set if not really moving + + if (((Creature*)this)->canFly()) + { + flags2 |= MOVEMENTFLAG_LEVITATING; // (ok) most seem to have this + + if (((Creature*)this)->IsStopped()) + flags2 |= MOVEMENTFLAG_FLY_UNK1; // (ok) possibly some "hover" mode + else + { + if (((Creature*)this)->IsMounted()) + flags2 |= MOVEMENTFLAG_FLYING; // seems to be often when mounted + /* for further research + else + flags2 |= MOVEMENTFLAG_FLYING2; // not seen, but work on some, even if not "correct" + */ + } + } } break; case TYPEID_PLAYER: @@ -546,9 +566,12 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2) } // 0x4 - if(flags & UPDATEFLAG_HAS_TARGET) // packed guid (current target guid) + if(flags & UPDATEFLAG_HAS_ATTACKING_TARGET) // packed guid (current target guid) { - data->appendPackGUID(((Unit*)this)->GetTargetGUID()); + if (((Unit*)this)->getVictim()) + data->append(((Unit*)this)->getVictim()->GetPackGUID()); + else + data->appendPackGUID(0); } // 0x2 @@ -1115,8 +1138,8 @@ void Object::BuildUpdateData( UpdateDataMapType& update_players ) } WorldObject::WorldObject() - : m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL), - m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f), m_currMap(NULL) + : m_currMap(NULL), m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL), + m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f) { } diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index a905d7bca..50b072b95 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -310,7 +310,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*0x119*/ { "CMSG_IGNORE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleIgnoreTradeOpcode }, /*0x11A*/ { "CMSG_ACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleAcceptTradeOpcode }, /*0x11B*/ { "CMSG_UNACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleUnacceptTradeOpcode }, - /*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, &WorldSession::HandleCancelTradeOpcode}, + /*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_LOGGEDIN_OR_RECENTLY_LOGGEDOUT, &WorldSession::HandleCancelTradeOpcode}, /*0x11D*/ { "CMSG_SET_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeItemOpcode }, /*0x11E*/ { "CMSG_CLEAR_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleClearTradeItemOpcode }, /*0x11F*/ { "CMSG_SET_TRADE_GOLD", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeGoldOpcode }, diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index 290baf8dd..f766fe43f 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -1329,7 +1329,7 @@ enum SessionStatus STATUS_AUTHED = 0, ///< Player authenticated (_player==NULL, m_playerRecentlyLogout = false or will be reset before handler call, m_GUID have garbage) STATUS_LOGGEDIN, ///< Player in game (_player!=NULL, m_GUID == _player->GetGUID(), inWorld()) STATUS_TRANSFER, ///< Player transferring to another map (_player!=NULL, m_GUID == _player->GetGUID(), !inWorld()) - STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, ///< _player!= NULL or _player==NULL && m_playerRecentlyLogout, m_GUID store last _player guid) + STATUS_LOGGEDIN_OR_RECENTLY_LOGGEDOUT, ///< _player!= NULL or _player==NULL && m_playerRecentlyLogout, m_GUID store last _player guid) STATUS_NEVER, ///< Opcode not accepted from client (deprecated or server side only) STATUS_UNHANDLED ///< We don' handle this opcode yet }; diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index db5f6eb36..1a9af6755 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -499,7 +499,7 @@ void Pet::Update(uint32 diff) { // unsummon pet that lost owner Unit* owner = GetOwner(); - if(!owner || (!IsWithinDistInMap(owner, OWNER_MAX_DISTANCE) && (owner->GetCharmGUID() && (owner->GetCharmGUID() != GetGUID()))) || (isControlled() && !owner->GetPetGUID())) + if(!owner || (!IsWithinDistInMap(owner, GetMap()->GetVisibilityDistance()) && (owner->GetCharmGUID() && (owner->GetCharmGUID() != GetGUID()))) || (isControlled() && !owner->GetPetGUID())) { Remove(PET_SAVE_NOT_IN_SLOT, true); return; @@ -1882,9 +1882,6 @@ void Pet::CastPetAuras(bool current) if(!owner || owner->GetTypeId()!=TYPEID_PLAYER) return; - if(!IsPermanentPetFor((Player*)owner)) - return; - for(PetAuraSet::const_iterator itr = owner->m_petAuras.begin(); itr != owner->m_petAuras.end();) { PetAura const* pa = *itr; diff --git a/src/game/Pet.h b/src/game/Pet.h index 303d3ba50..600a1d535 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -116,8 +116,6 @@ typedef std::vector AutoSpellList; #define ACTIVE_SPELLS_MAX 4 -#define OWNER_MAX_DISTANCE 100.0f - #define PET_FOLLOW_DIST 1 #define PET_FOLLOW_ANGLE (M_PI/2) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 20541c96b..7a66874e2 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1335,7 +1335,7 @@ void Player::Update( uint32 p_time ) SendUpdateToOutOfRangeGroupMembers(); Pet* pet = GetPet(); - if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE) && (GetCharmGUID() && (pet->GetGUID() != GetCharmGUID()))) + if(pet && !pet->IsWithinDistInMap(this, GetMap()->GetVisibilityDistance()) && (GetCharmGUID() && (pet->GetGUID() != GetCharmGUID()))) { RemovePet(pet, PET_SAVE_NOT_IN_SLOT, true); } @@ -1651,7 +1651,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati if (!(options & TELE_TO_NOT_UNSUMMON_PET)) { //same map, only remove pet if out of range for new position - if(pet && !pet->IsWithinDist3d(x,y,z, OWNER_MAX_DISTANCE)) + if(pet && !pet->IsWithinDist3d(x,y,z,GetMap()->GetVisibilityDistance())) UnsummonPetTemporaryIfAny(); } @@ -5025,15 +5025,12 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) if(!skill_id) return false; - uint16 i=0; - for (; i < PLAYER_MAX_SKILLS; ++i) - if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill_id) - break; - - if(i>=PLAYER_MAX_SKILLS) + SkillStatusMap::iterator itr = mSkillStatus.find(skill_id); + if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return false; - uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)); + uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); + uint32 data = GetUInt32Value(valueIndex); uint32 value = SKILL_VALUE(data); uint32 max = SKILL_MAX(data); @@ -5046,7 +5043,9 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) if(new_value > max) new_value = max; - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(new_value,max)); + SetUInt32Value(valueIndex,MAKE_SKILL_VALUE(new_value,max)); + if(itr->second.uState != SKILL_NEW) + itr->second.uState = SKILL_CHANGED; GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL,skill_id); return true; } @@ -5155,13 +5154,13 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) return false; } - uint16 i=0; - for (; i < PLAYER_MAX_SKILLS; ++i) - if ( SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_INDEX(i))) == SkillId ) break; - if ( i >= PLAYER_MAX_SKILLS ) + SkillStatusMap::iterator itr = mSkillStatus.find(SkillId); + if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return false; - uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)); + uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); + + uint32 data = GetUInt32Value(valueIndex); uint16 SkillValue = SKILL_VALUE(data); uint16 MaxValue = SKILL_MAX(data); @@ -5176,7 +5175,9 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) if(new_value > MaxValue) new_value = MaxValue; - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(new_value,MaxValue)); + SetUInt32Value(valueIndex,MAKE_SKILL_VALUE(new_value,MaxValue)); + if(itr->second.uState != SKILL_NEW) + itr->second.uState = SKILL_CHANGED; for(uint32* bsl = &bonusSkillLevels[0]; *bsl; ++bsl) { if((SkillValue < *bsl && new_value >= *bsl)) @@ -5274,19 +5275,20 @@ void Player::UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, bool de void Player::ModifySkillBonus(uint32 skillid,int32 val, bool talent) { - for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i) - if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skillid) - { - uint32 bonus_val = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i)); - int16 temp_bonus = SKILL_TEMP_BONUS(bonus_val); - int16 perm_bonus = SKILL_PERM_BONUS(bonus_val); - - if(talent) // permanent bonus stored in high part - SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),MAKE_SKILL_BONUS(temp_bonus,perm_bonus+val)); - else // temporary/item bonus stored in low part - SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),MAKE_SKILL_BONUS(temp_bonus+val,perm_bonus)); + SkillStatusMap::const_iterator itr = mSkillStatus.find(skillid); + if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return; - } + + uint32 bonusIndex = PLAYER_SKILL_BONUS_INDEX(itr->second.pos); + + uint32 bonus_val = GetUInt32Value(bonusIndex); + int16 temp_bonus = SKILL_TEMP_BONUS(bonus_val); + int16 perm_bonus = SKILL_PERM_BONUS(bonus_val); + + if(talent) // permanent bonus stored in high part + SetUInt32Value(bonusIndex,MAKE_SKILL_BONUS(temp_bonus,perm_bonus+val)); + else // temporary/item bonus stored in low part + SetUInt32Value(bonusIndex,MAKE_SKILL_BONUS(temp_bonus+val,perm_bonus)); } void Player::UpdateSkillsForLevel() @@ -5296,10 +5298,12 @@ void Player::UpdateSkillsForLevel() bool alwaysMaxSkill = sWorld.getConfig(CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL); - for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i) - if (GetUInt32Value(PLAYER_SKILL_INDEX(i))) + for(SkillStatusMap::iterator itr = mSkillStatus.begin(); itr != mSkillStatus.end(); ++itr) { - uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF; + if(itr->second.uState == SKILL_DELETED) + continue; + + uint32 pskill = itr->first; SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(pskill); if(!pSkill) @@ -5308,37 +5312,52 @@ void Player::UpdateSkillsForLevel() if(GetSkillRangeType(pSkill,false) != SKILL_RANGE_LEVEL) continue; - uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)); + uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); + uint32 data = GetUInt32Value(valueIndex); uint32 max = SKILL_MAX(data); uint32 val = SKILL_VALUE(data); /// update only level dependent max skill values if(max!=1) { - /// miximize skill always + /// maximize skill always if(alwaysMaxSkill) - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(maxSkill,maxSkill)); - /// update max skill value if current max skill not maximized - else if(max != maxconfskill) - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(val,maxSkill)); + { + SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(maxSkill,maxSkill)); + if(itr->second.uState != SKILL_NEW) + itr->second.uState = SKILL_CHANGED; + } + else if(max != maxconfskill) /// update max skill value if current max skill not maximized + { + SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(val,maxSkill)); + if(itr->second.uState != SKILL_NEW) + itr->second.uState = SKILL_CHANGED; + } } } } void Player::UpdateSkillsToMaxSkillsForLevel() { - for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i) - if (GetUInt32Value(PLAYER_SKILL_INDEX(i))) + for(SkillStatusMap::iterator itr = mSkillStatus.begin(); itr != mSkillStatus.end(); ++itr) { - uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF; + if(itr->second.uState == SKILL_DELETED) + continue; + + uint32 pskill = itr->first; if( IsProfessionOrRidingSkill(pskill)) continue; - uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)); + uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); + uint32 data = GetUInt32Value(valueIndex); uint32 max = SKILL_MAX(data); if(max > 1) - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(max,max)); + { + SetUInt32Value(valueIndex,MAKE_SKILL_VALUE(max,max)); + if(itr->second.uState != SKILL_NEW) + itr->second.uState = SKILL_CHANGED; + } if(pskill == SKILL_DEFENSE) UpdateDefenseBonusesMod(); @@ -5352,15 +5371,16 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal) if(!id) return; - uint16 i=0; - for (; i < PLAYER_MAX_SKILLS; ++i) - if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == id) break; + SkillStatusMap::iterator itr = mSkillStatus.find(id); - if(isecond.uState != SKILL_DELETED) { if(currVal) { - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(currVal,maxVal)); + SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos),MAKE_SKILL_VALUE(currVal,maxVal)); + if(itr->second.uState != SKILL_NEW) + itr->second.uState = SKILL_CHANGED; learnSkillRewardedSpells(id, currVal); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL,id); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL,id); @@ -5368,9 +5388,15 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal) else //remove { // clear skill fields - SetUInt32Value(PLAYER_SKILL_INDEX(i),0); - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),0); - SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0); + SetUInt32Value(PLAYER_SKILL_INDEX(itr->second.pos),0); + SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos),0); + SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos),0); + + // mark as deleted or simply remove from map if not saved yet + if(itr->second.uState != SKILL_NEW) + itr->second.uState = SKILL_DELETED; + else + mSkillStatus.erase(itr); // remove all spells that related to this skill for (uint32 j=0; jsecond.pos = i; + itr->second.uState = SKILL_CHANGED; + } + else + mSkillStatus.insert(SkillStatusMap::value_type(id, SkillStatusData(i, SKILL_NEW))); + // apply skill bonuses SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0); @@ -5423,15 +5458,11 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal) bool Player::HasSkill(uint32 skill) const { - if(!skill)return false; - for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i) - { - if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) - { - return true; - } - } - return false; + if(!skill) + return false; + + SkillStatusMap::const_iterator itr = mSkillStatus.find(skill); + return (itr != mSkillStatus.end() && itr->second.uState != SKILL_DELETED); } uint16 Player::GetSkillValue(uint32 skill) const @@ -5439,78 +5470,71 @@ uint16 Player::GetSkillValue(uint32 skill) const if(!skill) return 0; - for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i) - { - if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) - { - uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i)); + SkillStatusMap::const_iterator itr = mSkillStatus.find(skill); + if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) + return 0; - int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)))); - result += SKILL_TEMP_BONUS(bonus); - result += SKILL_PERM_BONUS(bonus); - return result < 0 ? 0 : result; - } - } - return 0; + uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)); + + int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)))); + result += SKILL_TEMP_BONUS(bonus); + result += SKILL_PERM_BONUS(bonus); + return result < 0 ? 0 : result; } uint16 Player::GetMaxSkillValue(uint32 skill) const { - if(!skill)return 0; - for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i) - { - if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) - { - uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i)); + if(!skill) + return 0; - int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)))); - result += SKILL_TEMP_BONUS(bonus); - result += SKILL_PERM_BONUS(bonus); - return result < 0 ? 0 : result; - } - } - return 0; + SkillStatusMap::const_iterator itr = mSkillStatus.find(skill); + if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) + return 0; + + uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)); + + int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)))); + result += SKILL_TEMP_BONUS(bonus); + result += SKILL_PERM_BONUS(bonus); + return result < 0 ? 0 : result; } uint16 Player::GetPureMaxSkillValue(uint32 skill) const { - if(!skill)return 0; - for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i) - { - if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) - { - return SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i))); - } - } - return 0; + if(!skill) + return 0; + + SkillStatusMap::const_iterator itr = mSkillStatus.find(skill); + if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) + return 0; + + return SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))); } uint16 Player::GetBaseSkillValue(uint32 skill) const { - if(!skill)return 0; - for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i) - { - if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) - { - int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)))); - result += SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i))); - return result < 0 ? 0 : result; - } - } - return 0; + if(!skill) + return 0; + + SkillStatusMap::const_iterator itr = mSkillStatus.find(skill); + if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) + return 0; + + int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)))); + result += SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos))); + return result < 0 ? 0 : result; } uint16 Player::GetPureSkillValue(uint32 skill) const { - if(!skill)return 0; - for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i) - { - if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) - { - return SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i))); - } - } - return 0; + if(!skill) + return 0; + + SkillStatusMap::const_iterator itr = mSkillStatus.find(skill); + if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) + return 0; + + return SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))); } int16 Player::GetSkillPermBonusValue(uint32 skill) const @@ -5518,15 +5542,11 @@ int16 Player::GetSkillPermBonusValue(uint32 skill) const if(!skill) return 0; - for (int i = 0; i < PLAYER_MAX_SKILLS; ++i) - { - if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) - { - return SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i))); - } - } + SkillStatusMap::const_iterator itr = mSkillStatus.find(skill); + if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) + return 0; - return 0; + return SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos))); } int16 Player::GetSkillTempBonusValue(uint32 skill) const @@ -5534,15 +5554,11 @@ int16 Player::GetSkillTempBonusValue(uint32 skill) const if(!skill) return 0; - for (int i = 0; i < PLAYER_MAX_SKILLS; ++i) - { - if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) - { - return SKILL_TEMP_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i))); - } - } + SkillStatusMap::const_iterator itr = mSkillStatus.find(skill); + if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) + return 0; - return 0; + return SKILL_TEMP_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos))); } void Player::SendInitialActionButtons() const @@ -9005,11 +9021,11 @@ uint8 Player::_CanStoreItem_InBag( uint8 bag, ItemPosCountVec &dest, ItemPrototy Item* pItem2 = GetItemByPos( bag, j ); // ignore move item (this slot will be empty at move) - if (pItem2==pSrcItem) + if (pItem2 == pSrcItem) pItem2 = NULL; // if merge skip empty, if !merge skip non-empty - if ((pItem2!=NULL)!=merge) + if ((pItem2 != NULL) != merge) continue; if (pItem2) @@ -9066,7 +9082,7 @@ uint8 Player::_CanStoreItem_InInventorySlots( uint8 slot_begin, uint8 slot_end, pItem2 = NULL; // if merge skip empty, if !merge skip non-empty - if ((pItem2!=NULL)!=merge) + if ((pItem2 != NULL) != merge) continue; if (pItem2) @@ -9971,6 +9987,9 @@ uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *p if (!pItem) return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND; + if (pItem->m_lootGenerated) + return EQUIP_ERR_ITEM_LOCKED; + uint32 count = pItem->GetCount(); sLog.outDebug( "STORAGE: CanBankItem bag = %u, slot = %u, item = %u, count = %u", bag, slot, pItem->GetEntry(), pItem->GetCount()); @@ -14484,7 +14503,10 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) SetUInt32Value(PLAYER_TRACK_CREATURES, 0 ); SetUInt32Value(PLAYER_TRACK_RESOURCES, 0 ); - _LoadSkills(); + // cleanup aura list explicitly before skill load wher some spells can be applied + RemoveAllAuras(); + + _LoadSkills(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSKILLS)); // make sure the unit is considered out of combat for proper loading ClearInCombat(); @@ -14742,7 +14764,7 @@ void Player::_LoadActions(QueryResult *result) void Player::_LoadAuras(QueryResult *result, uint32 timediff) { - RemoveAllAuras(); + //RemoveAllAuras(); -- some spells casted before aura load, for example in LoadSkills, aura list explcitly cleaned early //QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'",GetGUIDLow()); @@ -15748,6 +15770,7 @@ void Player::SaveToDB() _SaveSpellCooldowns(); _SaveActions(); _SaveAuras(); + _SaveSkills(); m_achievementMgr.SaveToDB(); m_reputationMgr.SaveToDB(); _SaveEquipmentSets(); @@ -16028,6 +16051,46 @@ void Player::_SaveDailyQuestStatus() GetGUIDLow(), GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx),uint64(m_lastDailyQuestTime)); } + +void Player::_SaveSkills() +{ + // we don't need transactions here. + for( SkillStatusMap::iterator itr = mSkillStatus.begin(); itr != mSkillStatus.end(); ) + { + if(itr->second.uState == SKILL_UNCHANGED) + { + ++itr; + continue; + } + + if(itr->second.uState == SKILL_DELETED) + { + CharacterDatabase.PExecute("DELETE FROM character_skills WHERE guid = '%u' AND skill = '%u' ", GetGUIDLow(), itr->first ); + mSkillStatus.erase(itr++); + continue; + } + + uint32 valueData = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)); + uint16 value = SKILL_VALUE(valueData); + uint16 max = SKILL_MAX(valueData); + + switch (itr->second.uState) + { + case SKILL_NEW: + CharacterDatabase.PExecute("INSERT INTO character_skills (guid, skill, value, max) VALUES ('%u', '%u', '%u', '%u')", + GetGUIDLow(), itr->first, value, max); + break; + case SKILL_CHANGED: + CharacterDatabase.PExecute("UPDATE character_skills SET value = '%u',max = '%u'WHERE guid = '%u' AND skill = '%u' ", + value, max, GetGUIDLow(), itr->first ); + break; + }; + itr->second.uState = SKILL_UNCHANGED; + + ++itr; + } +} + void Player::_SaveSpells() { for (PlayerSpellMap::iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end();) @@ -18092,12 +18155,27 @@ bool Player::IsVisibleGloballyFor( Player* u ) const return true; } +template +inline void BeforeVisibilityDestroy(T* /*t*/, Player* /*p*/) +{ +} + +template<> +inline void BeforeVisibilityDestroy(Creature* t, Player* p) +{ + if (p->GetPetGUID()==t->GetGUID() && ((Creature*)t)->isPet()) + ((Pet*)t)->Remove(PET_SAVE_NOT_IN_SLOT, true); +} + void Player::UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* target) { if(HaveAtClient(target)) { if(!target->isVisibleForInState(this, viewPoint, true)) { + if (target->GetTypeId()==TYPEID_UNIT) + BeforeVisibilityDestroy((Creature*)target,this); + target->DestroyForPlayer(this); m_clientGUIDs.erase(target->GetGUID()); @@ -18151,6 +18229,8 @@ void Player::UpdateVisibilityOf(WorldObject const* viewPoint, T* target, UpdateD { if(!target->isVisibleForInState(this,viewPoint,true)) { + BeforeVisibilityDestroy(target,this); + target->BuildOutOfRangeUpdateBlock(&data); m_clientGUIDs.erase(target->GetGUID()); @@ -19862,43 +19942,78 @@ void Player::learnSpellHighRank(uint32 spellid) sSpellMgr.doForHighRanks(spellid,worker); } -void Player::_LoadSkills() +void Player::_LoadSkills(QueryResult *result) { - // Note: skill data itself loaded from `data` field. This is only cleanup part of load + // 0 1 2 + // SetPQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = '%u'", GUID_LOPART(m_guid)); - // reset skill modifiers and set correct unlearn flags - for (uint32 i = 0; i < PLAYER_MAX_SKILLS; ++i) + uint32 count = 0; + if (result) { - SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0); - - // set correct unlearn bit - uint32 id = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF; - if(!id) continue; - - SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(id); - if(!pSkill) continue; - - // enable unlearn button for primary professions only - if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION) - SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,1)); - else - SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,0)); - - // set fixed skill ranges - switch(GetSkillRangeType(pSkill,false)) + do { - case SKILL_RANGE_LANGUAGE: // 300..300 - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(300,300)); - break; - case SKILL_RANGE_MONO: // 1..1, grey monolite bar - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(1,1)); - break; - default: - break; - } + Field *fields = result->Fetch(); - uint32 vskill = SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i))); - learnSkillRewardedSpells(id, vskill); + uint16 skill = fields[0].GetUInt16(); + uint16 value = fields[1].GetUInt16(); + uint16 max = fields[2].GetUInt16(); + + SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(skill); + if(!pSkill) + { + sLog.outError("Character %u has skill %u that does not exist.", GetGUIDLow(), skill); + continue; + } + + // set fixed skill ranges + switch(GetSkillRangeType(pSkill,false)) + { + case SKILL_RANGE_LANGUAGE: // 300..300 + value = max = 300; + break; + case SKILL_RANGE_MONO: // 1..1, grey monolite bar + value = max = 1; + break; + default: + break; + } + + if(value == 0) + { + sLog.outError("Character %u has skill %u with value 0. Will be deleted.", GetGUIDLow(), skill); + CharacterDatabase.PExecute("DELETE FROM character_skills WHERE guid = '%u' AND skill = '%u' ", GetGUIDLow(), skill ); + continue; + } + + // enable unlearn button for primary professions only + if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION) + SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill,1)); + else + SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill,0)); + + SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count),MAKE_SKILL_VALUE(value, max)); + SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count),0); + + mSkillStatus.insert(SkillStatusMap::value_type(skill, SkillStatusData(count, SKILL_UNCHANGED))); + + learnSkillRewardedSpells(skill, value); + + ++count; + + if(count >= PLAYER_MAX_SKILLS) // client limit + { + sLog.outError("Character %u has more than %u skills.", PLAYER_MAX_SKILLS); + break; + } + } while (result->NextRow()); + delete result; + } + + for (; count < PLAYER_MAX_SKILLS; ++count) + { + SetUInt32Value(PLAYER_SKILL_INDEX(count), 0); + SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count),0); + SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count),0); } // special settings diff --git a/src/game/Player.h b/src/game/Player.h index f7949dc35..d58d5bb5a 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -564,6 +564,25 @@ enum QuestSlotStateMask QUEST_STATE_FAIL = 0x0002 }; +enum SkillUpdateState +{ + SKILL_UNCHANGED = 0, + SKILL_CHANGED = 1, + SKILL_NEW = 2, + SKILL_DELETED = 3 +}; + +struct SkillStatusData +{ + SkillStatusData(uint8 _pos, SkillUpdateState _uState) : pos(_pos), uState(_uState) + { + } + uint8 pos; + SkillUpdateState uState; +}; + +typedef UNORDERED_MAP SkillStatusMap; + class Quest; class Spell; class Item; @@ -885,7 +904,8 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS = 20, PLAYER_LOGIN_QUERY_LOADBGDATA = 21, PLAYER_LOGIN_QUERY_LOADACCOUNTDATA = 22, - MAX_PLAYER_LOGIN_QUERY = 23 + PLAYER_LOGIN_QUERY_LOADSKILLS = 23, + MAX_PLAYER_LOGIN_QUERY = 24 }; enum PlayerDelayedOperations @@ -2303,7 +2323,7 @@ class MANGOS_DLL_SPEC Player : public Unit void _LoadQuestStatus(QueryResult *result); void _LoadDailyQuestStatus(QueryResult *result); void _LoadGroup(QueryResult *result); - void _LoadSkills(); + void _LoadSkills(QueryResult *result); void _LoadSpells(QueryResult *result); void _LoadFriendList(QueryResult *result); bool _LoadHomeBind(QueryResult *result); @@ -2322,6 +2342,7 @@ class MANGOS_DLL_SPEC Player : public Unit void _SaveMail(); void _SaveQuestStatus(); void _SaveDailyQuestStatus(); + void _SaveSkills(); void _SaveSpells(); void _SaveEquipmentSets(); void _SaveBGData(); @@ -2369,6 +2390,8 @@ class MANGOS_DLL_SPEC Player : public Unit QuestStatusMap mQuestStatus; + SkillStatusMap mSkillStatus; + uint32 m_GuildIdInvited; uint32 m_ArenaTeamIdInvited; diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index 5409b65d2..72a4c3e50 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -76,28 +76,30 @@ void WorldSession::HandleQuestgiverStatusQueryOpcode( WorldPacket & recv_data ) _player->PlayerTalkClass->SendQuestGiverStatus(questStatus, guid); } -void WorldSession::HandleQuestgiverHelloOpcode( WorldPacket & recv_data ) +void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket & recv_data) { uint64 guid; recv_data >> guid; sLog.outDebug ("WORLD: Received CMSG_QUESTGIVER_HELLO npc = %u", GUID_LOPART(guid)); - Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_NONE); + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); + if (!pCreature) { - sLog.outDebug ("WORLD: HandleQuestgiverHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", - GUID_LOPART(guid)); + sLog.outDebug ("WORLD: HandleQuestgiverHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guid)); return; } // remove fake death - if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) + if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); - // Stop the npc if moving - pCreature->StopMoving(); - if(Script->GossipHello( _player, pCreature ) ) + // Stop the npc if moving + if (!pCreature->IsStopped()) + pCreature->StopMoving(); + + if (Script->GossipHello(_player, pCreature)) return; pCreature->prepareGossipMenu(_player); diff --git a/src/game/ScriptCalls.cpp b/src/game/ScriptCalls.cpp index 99435b34e..7998cf493 100644 --- a/src/game/ScriptCalls.cpp +++ b/src/game/ScriptCalls.cpp @@ -43,7 +43,7 @@ bool LoadScriptingModule(char const* libName) ScriptsSet testScript=new _ScriptSet; std::string name = strlen(libName) ? libName : MANGOS_SCRIPT_NAME; - name += MANGOS_SCRIPT_EXT; + name = MANGOS_SCRIPT_PREFIX + name + MANGOS_SCRIPT_SUFFIX; testScript->hScriptsLib=MANGOS_LOAD_LIBRARY(name.c_str()); diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 7f58b26c2..62fb2c029 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -2467,6 +2467,7 @@ enum SummonType SUMMON_TYPE_QUEST_WILD = 587, SUMMON_TYPE_INFERNO = 711, SUMMON_TYPE_GUARDIAN2 = 713, + SUMMON_TYPE_LIGHTWELL = 1141, SUMMON_TYPE_GUARDIAN3 = 1161, SUMMON_TYPE_CREATURE = 1302, SUMMON_TYPE_ELEMENTAL = 1561, diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index be4e65aab..a71d25924 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -992,6 +992,13 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) if (m_canTrigger && missInfo != SPELL_MISS_REFLECT) caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, damageInfo.damage, m_attackType, m_spellInfo); + // Haunt (NOTE: for avoid use additional field damage stored in dummy value (replace unused 100%) + // apply before deal damage because aura can be removed at target kill + if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->SpellIconID == 3172 && + (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000))) + if(Aura* dummy = unitTarget->GetDummyAura(m_spellInfo->Id)) + dummy->GetModifier()->m_amount = damageInfo.damage; + caster->DealSpellDamage(&damageInfo, true); } // Passive spell hits/misses or active spells only misses (only triggers) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 3065fcd18..1520731db 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2488,6 +2488,22 @@ void Aura::HandleAuraDummy(bool apply, bool Real) } case SPELLFAMILY_MAGE: break; + case SPELLFAMILY_WARLOCK: + { + // Haunt + if (GetSpellProto()->SpellIconID == 3172 && (GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0004000000000000))) + { + // NOTE: for avoid use additional field damage stored in dummy value (replace unused 100% + if (apply) + m_modifier.m_amount = 0; // use value as damage counter instead redundent 100% percent + else + { + int32 bp0 = m_modifier.m_amount; + m_target->CastCustomSpell(caster,48210,&bp0,NULL,NULL,true); + } + } + break; + } case SPELLFAMILY_PRIEST: { // Pain and Suffering @@ -2510,8 +2526,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real) } break; } - case SPELLFAMILY_PALADIN: - break; case SPELLFAMILY_DRUID: { switch(GetId()) @@ -2642,6 +2656,8 @@ void Aura::HandleAuraDummy(bool apply, bool Real) } case SPELLFAMILY_HUNTER: break; + case SPELLFAMILY_PALADIN: + break; case SPELLFAMILY_SHAMAN: { // Improved Weapon Totems @@ -3226,10 +3242,14 @@ void Aura::HandleForceReaction(bool apply, bool Real) Player* player = (Player*)m_target; uint32 faction_id = m_modifier.m_miscvalue; - uint32 faction_rank = m_modifier.m_amount; + ReputationRank faction_rank = ReputationRank(m_modifier.m_amount); - player->GetReputationMgr().ApplyForceReaction(faction_id, ReputationRank(faction_rank), apply); + player->GetReputationMgr().ApplyForceReaction(faction_id, faction_rank, apply); player->GetReputationMgr().SendForceReactions(); + + // stop fighting if at apply forced rank friendly or at remove real rank friendly + if (apply && faction_rank >= REP_FRIENDLY || !apply && player->GetReputationRank(faction_id) >= REP_FRIENDLY) + player->StopAttackFaction(faction_id); } void Aura::HandleAuraModSkill(bool apply, bool /*Real*/) @@ -4408,16 +4428,37 @@ void Aura::HandlePeriodicEnergize(bool apply, bool Real) if (!Real) return; - if (apply) + // For prevent double apply bonuses + bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading()); + + if (apply && !loading) { switch (GetId()) { + case 54833: // Glyph of Innervate (value%/2 of casters base mana) + { + Unit* caster = GetCaster(); + m_modifier.m_amount = int32(caster->GetCreateMana() * GetBasePoints() / (200 * m_maxduration / m_periodicTimer)); + break; + + } + case 29166: // Innervate (value% of casters base mana) + { + Unit* caster = GetCaster(); + + // Glyph of Innervate + if (caster && caster->HasAura(54832)) + caster->CastSpell(caster,54833,true,NULL,this); + + m_modifier.m_amount = int32(caster->GetCreateMana() * GetBasePoints() / (100 * m_maxduration / m_periodicTimer)); + break; + } case 48391: // Owlkin Frenzy 2% base mana m_modifier.m_amount = m_target->GetCreateMana() * 2 / 100; break; - case 57669: // Replenishment (0.25% from max) + case 57669: // Replenishment (0.2% from max) case 61782: // Infinite Replenishment - m_modifier.m_amount = m_target->GetMaxPower(POWER_MANA) * 25 / 10000; + m_modifier.m_amount = m_target->GetMaxPower(POWER_MANA) * 2 / 1000; break; default: break; @@ -4441,8 +4482,6 @@ void Aura::HandleAuraPeriodicDummy(bool apply, bool Real) // For prevent double apply bonuses bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading()); - Unit* caster = GetCaster(); - SpellEntry const*spell = GetSpellProto(); switch( spell->SpellFamilyName) { @@ -4462,6 +4501,8 @@ void Aura::HandleAuraPeriodicDummy(bool apply, bool Real) } case SPELLFAMILY_HUNTER: { + Unit* caster = GetCaster(); + // Explosive Shot if (apply && !loading && caster) m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 14 / 100); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 8a89bc197..614175bd5 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -487,6 +487,23 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) // Shadow Word: Death - deals damage equal to damage done to caster if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000200000000)) m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true); + // Improved Mind Blast (Mind Blast in shadow form bonus) + else if (m_caster->m_form == FORM_SHADOW && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00002000))) + { + Unit::AuraList const& ImprMindBlast = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER); + for(Unit::AuraList::const_iterator i = ImprMindBlast.begin(); i != ImprMindBlast.end(); ++i) + { + if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST && + ((*i)->GetSpellProto()->SpellIconID == 95)) + { + int chance = (*i)->GetSpellProto()->CalculateSimpleValue(1); + if (roll_chance_i(chance)) + // Mind Trauma + m_caster->CastSpell(unitTarget, 48301, true, 0); + break; + } + } + } break; } case SPELLFAMILY_DRUID: @@ -1267,19 +1284,19 @@ void Spell::EffectDummy(uint32 i) if (((Player *)m_caster)->GetTeam() == HORDE) { if (m_caster->GetSpeedRate(MOVE_RUN) >= 2.0f) - // 100% Ram + // Swift Brewfest Ram, 100% Ram m_caster->CastSpell(m_caster, 43900, true); else - // 60% Ram + // Brewfest Ram, 60% Ram m_caster->CastSpell(m_caster, 43899, true); } else { if (((Player *)m_caster)->GetSpeedRate(MOVE_RUN) >= 2.0f) - // 100% Kodo + // Great Brewfest Kodo, 100% Kodo m_caster->CastSpell(m_caster, 49379, true); else - // 60% Kodo + // Brewfest Riding Kodo, 60% Kodo m_caster->CastSpell(m_caster, 49378, true); } return; @@ -1326,15 +1343,34 @@ void Spell::EffectDummy(uint32 i) if (m_caster->GetTypeId() != TYPEID_PLAYER) return; - uint32 spell_id; - switch(urand(1, 3)) + uint32 spell_id = 0; + switch(m_caster->getClass()) { - case 1: spell_id = 67016; break; - case 2: spell_id = 67017; break; - default:spell_id = 67018; break; + case CLASS_WARRIOR: + case CLASS_DEATH_KNIGHT: + spell_id = 67018; // STR for Warriors, Death Knights + break; + case CLASS_ROGUE: + case CLASS_HUNTER: + spell_id = 67017; // AP for Rogues, Hunters + break; + case CLASS_PRIEST: + case CLASS_MAGE: + case CLASS_WARLOCK: + spell_id = 67016; // SPD for Priests, Mages, Warlocks + break; + case CLASS_SHAMAN: + // random (SPD, AP) + spell_id = roll_chance_i(50) ? 67016 : 67017; + break; + case CLASS_PALADIN: + case CLASS_DRUID: + default: + // random (SPD, STR) + spell_id = roll_chance_i(50) ? 67016 : 67018; + break; } - - m_caster->CastSpell(m_caster, spell_id, true, NULL); + m_caster->CastSpell(m_caster, spell_id, true); return; } } @@ -4714,15 +4750,6 @@ void Spell::EffectWeaponDmg(uint32 i) else m_caster->CastCustomSpell(m_caster, 53725, &damagePoint, NULL, NULL, true); } - // Seal of Blood/of the Martyr backlash damage (10%) - else if(m_spellInfo->SpellIconID==2293) - { - int32 damagePoint = m_damage * 10 / 100; - if(m_spellInfo->Id == 31893) - m_caster->CastCustomSpell(m_caster, 32221, &damagePoint, NULL, NULL, true); - else - m_caster->CastCustomSpell(m_caster, 53718, &damagePoint, NULL, NULL, true); - } } // take ammo diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 2d4d5590c..bdb1b663b 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -294,7 +294,8 @@ SpellSpecific GetSpellSpecific(uint32 spellId) if (spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000002190)) return SPELL_HAND; - if ((spellInfo->SpellFamilyFlags & UI64LIT(0x00000820180400)) && (spellInfo->AttributesEx3 & 0x200)) + // skip Heart of the Crusader that have also same spell family mask + if ((spellInfo->SpellFamilyFlags & UI64LIT(0x00000820180400)) && (spellInfo->AttributesEx3 & 0x200) && (spellInfo->SpellIconID != 237)) return SPELL_JUDGEMENT; // only paladin auras have this (for palaldin class family) @@ -1536,6 +1537,10 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons (spellId_2 == 33891 && spellId_1 == 34123)) return false; + // Innervate and Glyph of Innervate and some other spells + if (spellInfo_1->SpellIconID == 62 && spellInfo_2->SpellIconID == 62) + return false; + // Wrath of Elune and Nature's Grace if( spellInfo_1->Id == 16886 && spellInfo_2->Id == 46833 || spellInfo_2->Id == 16886 && spellInfo_1->Id == 46833 ) return false; diff --git a/src/game/TaxiHandler.cpp b/src/game/TaxiHandler.cpp index 754a441c0..f452ea61e 100644 --- a/src/game/TaxiHandler.cpp +++ b/src/game/TaxiHandler.cpp @@ -182,10 +182,20 @@ void WorldSession::HandleActivateTaxiExpressOpcode ( WorldPacket & recv_data ) GetPlayer()->ActivateTaxiPathTo(nodes, npc); } -void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& /*recv_data*/) +void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data) { sLog.outDebug( "WORLD: Received CMSG_MOVE_SPLINE_DONE" ); + uint64 guid; // used only for proper packet read + if(!recv_data.readPackGUID(guid)) + return; + + MovementInfo movementInfo; // used only for proper packet read + ReadMovementInfo(recv_data, &movementInfo); + + recv_data.read_skip(); // unk + + // in taxi flight packet received in 2 case: // 1) end taxi path in far (multi-node) flight // 2) switch from one map to other in case multim-map taxi path diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp index 11b560482..2d4669518 100644 --- a/src/game/ThreatManager.cpp +++ b/src/game/ThreatManager.cpp @@ -208,7 +208,7 @@ Unit* HostileReference::getSourceUnit() void ThreatContainer::clearReferences() { - for(std::list::const_iterator i = iThreatList.begin(); i != iThreatList.end(); ++i) + for(ThreatList::const_iterator i = iThreatList.begin(); i != iThreatList.end(); ++i) { (*i)->unlink(); delete (*i); @@ -222,7 +222,7 @@ HostileReference* ThreatContainer::getReferenceByTarget(Unit* pVictim) { HostileReference* result = NULL; uint64 guid = pVictim->GetGUID(); - for(std::list::const_iterator i = iThreatList.begin(); i != iThreatList.end(); ++i) + for(ThreatList::const_iterator i = iThreatList.begin(); i != iThreatList.end(); ++i) { if((*i)->getUnitGuid() == guid) { @@ -283,10 +283,10 @@ HostileReference* ThreatContainer::selectNextVictim(Creature* pAttacker, Hostile bool found = false; bool noPriorityTargetFound = false; - std::list::const_iterator lastRef = iThreatList.end(); + ThreatList::const_iterator lastRef = iThreatList.end(); lastRef--; - for(std::list::const_iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found;) + for(ThreatList::const_iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found;) { currentRef = (*iter); @@ -351,7 +351,8 @@ HostileReference* ThreatContainer::selectNextVictim(Creature* pAttacker, Hostile //=================== ThreatManager ========================== //============================================================ -ThreatManager::ThreatManager(Unit* owner) : iCurrentVictim(NULL), iOwner(owner) +ThreatManager::ThreatManager(Unit* owner) +: iCurrentVictim(NULL), iOwner(owner), iUpdateTimer(THREAT_UPDATE_INTERVAL), iUpdateNeed(false) { } @@ -362,6 +363,8 @@ void ThreatManager::clearReferences() iThreatContainer.clearReferences(); iThreatOfflineContainer.clearReferences(); iCurrentVictim = NULL; + iUpdateTimer.Reset(THREAT_UPDATE_INTERVAL); + iUpdateNeed = false; } //============================================================ @@ -378,7 +381,7 @@ void ThreatManager::addThreat(Unit* pVictim, float pThreat, bool crit, SpellScho return; // not to GM - if(!pVictim || (pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->isGameMaster()) ) + if (!pVictim || (pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->isGameMaster()) ) return; // not to dead and not for dead @@ -390,8 +393,11 @@ void ThreatManager::addThreat(Unit* pVictim, float pThreat, bool crit, SpellScho float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, crit, schoolMask, pThreatSpell); HostileReference* ref = iThreatContainer.addThreat(pVictim, threat); + // Ref is online + if (ref) + iUpdateNeed = true; // Ref is not in the online refs, search the offline refs next - if(!ref) + else ref = iThreatOfflineContainer.addThreat(pVictim, threat); if(!ref) // there was no ref => create a new one @@ -400,6 +406,7 @@ void ThreatManager::addThreat(Unit* pVictim, float pThreat, bool crit, SpellScho HostileReference* hostileReference = new HostileReference(pVictim, this, 0); iThreatContainer.addReference(hostileReference); hostileReference->addThreat(threat); // now we add the real threat + iUpdateNeed = true; if(pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->isGameMaster()) hostileReference->setOnlineOfflineState(false); // GM is always offline } @@ -410,6 +417,7 @@ void ThreatManager::addThreat(Unit* pVictim, float pThreat, bool crit, SpellScho void ThreatManager::modifyThreatPercent(Unit *pVictim, int32 pPercent) { iThreatContainer.modifyThreatPercent(pVictim, pPercent); + iUpdateNeed = true; } //============================================================ @@ -439,12 +447,17 @@ float ThreatManager::getThreat(Unit *pVictim, bool pAlsoSearchOfflineList) void ThreatManager::tauntApply(Unit* pTaunter) { - HostileReference* ref = iThreatContainer.getReferenceByTarget(pTaunter); - if(getCurrentVictim() && ref && (ref->getThreat() < getCurrentVictim()->getThreat())) + if(HostileReference* ref = iThreatContainer.getReferenceByTarget(pTaunter)) { - if(ref->getTempThreatModifyer() == 0.0f) - // Ok, temp threat is unused - ref->setTempThreat(getCurrentVictim()->getThreat()); + if(getCurrentVictim() && (ref->getThreat() < getCurrentVictim()->getThreat())) + { + // Ok, temp threat is unused + if(ref->getTempThreatModifyer() == 0.0f) + { + ref->setTempThreat(getCurrentVictim()->getThreat()); + iUpdateNeed = true; + } + } } } @@ -452,16 +465,26 @@ void ThreatManager::tauntApply(Unit* pTaunter) void ThreatManager::tauntFadeOut(Unit *pTaunter) { - HostileReference* ref = iThreatContainer.getReferenceByTarget(pTaunter); - if(ref) + if(HostileReference* ref = iThreatContainer.getReferenceByTarget(pTaunter)) + { ref->resetTempThreat(); + iUpdateNeed = true; + } } //============================================================ void ThreatManager::setCurrentVictim(HostileReference* pHostileReference) { + // including NULL==NULL case + if (pHostileReference == iCurrentVictim) + return; + + if (pHostileReference) + iOwner->SendHighestThreatUpdate(pHostileReference); + iCurrentVictim = pHostileReference; + iUpdateNeed = true; } //============================================================ @@ -490,6 +513,7 @@ void ThreatManager::processThreatEvent(ThreatRefStatusChangeEvent* threatRefStat setDirty(true); } iThreatContainer.remove(hostileReference); + iUpdateNeed = true; iThreatOfflineContainer.addReference(hostileReference); } else @@ -497,6 +521,7 @@ void ThreatManager::processThreatEvent(ThreatRefStatusChangeEvent* threatRefStat if(getCurrentVictim() && hostileReference->getThreat() > (1.1f * getCurrentVictim()->getThreat())) setDirty(true); iThreatContainer.addReference(hostileReference); + iUpdateNeed = true; iThreatOfflineContainer.remove(hostileReference); } break; @@ -506,10 +531,28 @@ void ThreatManager::processThreatEvent(ThreatRefStatusChangeEvent* threatRefStat setCurrentVictim(NULL); setDirty(true); } + iOwner->SendThreatRemove(hostileReference); if(hostileReference->isOnline()) + { iThreatContainer.remove(hostileReference); + iUpdateNeed = true; + } else iThreatOfflineContainer.remove(hostileReference); break; } } + +void ThreatManager::UpdateForClient(uint32 diff) +{ + if (!iUpdateNeed || isThreatListEmpty()) + return; + + iUpdateTimer.Update(diff); + if (iUpdateTimer.Passed()) + { + iOwner->SendThreatUpdate(); + iUpdateTimer.Reset(THREAT_UPDATE_INTERVAL); + iUpdateNeed = false; + } +} diff --git a/src/game/ThreatManager.h b/src/game/ThreatManager.h index 7c8cf23fb..1b870095c 100644 --- a/src/game/ThreatManager.h +++ b/src/game/ThreatManager.h @@ -23,7 +23,7 @@ #include "SharedDefines.h" #include "Utilities/LinkedReference/Reference.h" #include "UnitEvents.h" - +#include "Timer.h" #include //============================================================== @@ -33,6 +33,8 @@ class Creature; class ThreatManager; struct SpellEntry; +#define THREAT_UPDATE_INTERVAL 1 * IN_MILISECONDS // Server should send threat update to client periodically each second + //============================================================== // Class to calculate the real threat based @@ -127,10 +129,13 @@ class MANGOS_DLL_SPEC HostileReference : public Reference //============================================================== class ThreatManager; +typedef std::list ThreatList; + + class MANGOS_DLL_SPEC ThreatContainer { private: - std::list iThreatList; + ThreatList iThreatList; bool iDirty; protected: friend class ThreatManager; @@ -152,15 +157,15 @@ class MANGOS_DLL_SPEC ThreatContainer void setDirty(bool pDirty) { iDirty = pDirty; } - bool isDirty() { return iDirty; } + bool isDirty() const { return iDirty; } - bool empty() { return(iThreatList.empty()); } + bool empty() const { return(iThreatList.empty()); } HostileReference* getMostHated() { return iThreatList.empty() ? NULL : iThreatList.front(); } HostileReference* getReferenceByTarget(Unit* pVictim); - std::list& getThreatList() { return iThreatList; } + ThreatList const& getThreatList() const { return iThreatList; } }; //================================================= @@ -182,13 +187,15 @@ class MANGOS_DLL_SPEC ThreatManager float getThreat(Unit *pVictim, bool pAlsoSearchOfflineList = false); - bool isThreatListEmpty() { return iThreatContainer.empty();} + bool isThreatListEmpty() const { return iThreatContainer.empty(); } void processThreatEvent(ThreatRefStatusChangeEvent* threatRefStatusChangeEvent); + void UpdateForClient(uint32 time); + HostileReference* getCurrentVictim() { return iCurrentVictim; } - Unit* getOwner() { return iOwner; } + Unit* getOwner() const { return iOwner; } Unit* getHostileTarget(); @@ -199,15 +206,13 @@ class MANGOS_DLL_SPEC ThreatManager void setDirty(bool pDirty) { iThreatContainer.setDirty(pDirty); } - // methods to access the lists from the outside to do sume dirty manipulation (scriping and such) - // I hope they are used as little as possible. - std::list& getThreatList() { return iThreatContainer.getThreatList(); } - std::list& getOfflieThreatList() { return iThreatOfflineContainer.getThreatList(); } - ThreatContainer& getOnlineContainer() { return iThreatContainer; } - ThreatContainer& getOfflineContainer() { return iThreatOfflineContainer; } + // Don't must be used for explicit modify threat values in iterator return pointers + ThreatList const& getThreatList() const { return iThreatContainer.getThreatList(); } private: HostileReference* iCurrentVictim; Unit* iOwner; + TimeTrackerSmall iUpdateTimer; + bool iUpdateNeed; ThreatContainer iThreatContainer; ThreatContainer iThreatOfflineContainer; }; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index b5eab8dfe..68146479d 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -209,6 +209,9 @@ void Unit::Update( uint32 p_time ) delete *itr; m_deletedAuras.clear(); + if (CanHaveThreatList()) + getThreatManager().UpdateForClient(p_time); + // update combat timer only for players and pets if (isInCombat() && (GetTypeId() == TYPEID_PLAYER || ((Creature*)this)->isPet() || ((Creature*)this)->isCharmed())) { @@ -574,6 +577,14 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa { player->RewardPlayerAndGroupAtKill(pVictim); player->ProcDamageAndSpell(pVictim, PROC_FLAG_KILL, PROC_FLAG_KILLED, PROC_EX_NONE, 0); + + WorldPacket data(SMSG_PARTYKILLLOG, (8+8)); //send event PARTY_KILL + data << uint64(player->GetGUID()); //player with killing blow + data << uint64(pVictim->GetGUID()); //victim + if (Group *group = player->GetGroup()) + group->BroadcastPacket(&data, group->GetMemberGroup(player->GetGUID())); + else + player->SendDirectMessage(&data); } DEBUG_LOG("DealDamageAttackStop"); @@ -5415,22 +5426,55 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return true; // no hidden cooldown } - // Divine Aegis - if (dummySpell->SpellIconID == 2820) + switch(dummySpell->SpellIconID) { - basepoints0 = damage * triggerAmount/100; - triggered_spell_id = 47753; - break; - } - // Improved Shadowform - else if (dummySpell->SpellIconID == 217) - { - if(!roll_chance_i(triggerAmount)) - return false; + // Improved Shadowform + case 217: + { + if(!roll_chance_i(triggerAmount)) + return false; - RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); - RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED); - break; + RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); + RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED); + break; + } + // Divine Aegis + case 2820: + { + basepoints0 = damage * triggerAmount/100; + triggered_spell_id = 47753; + break; + } + // Empowered Renew + case 3021: + { + if (!procSpell) + return false; + + Aura* healingAura = pVictim->GetAura(procSpell->Id,0); + if (!healingAura) + return false; + + int32 healingfromticks = SpellHealingBonus(pVictim, procSpell, (healingAura->GetModifier()->m_amount* GetSpellAuraMaxTicks(procSpell)), DOT); + basepoints0 = healingfromticks * triggerAmount / 100; + triggered_spell_id = 63544; + break; + } + // Improved Devouring Plague + case 3790: + { + if (!procSpell) + return false; + + Aura* leachAura = pVictim->GetAura(procSpell->Id,0); + if (!leachAura) + return false; + + int32 damagefromticks = SpellDamageBonus(pVictim, procSpell, (leachAura->GetModifier()->m_amount* GetSpellAuraMaxTicks(procSpell)), DOT); + basepoints0 = damagefromticks * triggerAmount / 100; + triggered_spell_id = 63675; + break; + } } switch(dummySpell->Id) @@ -5785,20 +5829,32 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu } return true; } - // Judgements of the Wise - case 31876: - case 31877: - case 31878: - // triggered only at casted Judgement spells, not at additional Judgement effects - if(!procSpell || procSpell->Category != 1210) - return false; - - target = this; - triggered_spell_id = 31930; - - // Replenishment - CastSpell(this, 57669, true, NULL, triggeredByAura); + // Heart of the Crusader (Rank 1) + case 20335: + triggered_spell_id = 21183; break; + // Heart of the Crusader (Rank 2) + case 20336: + triggered_spell_id = 54498; + break; + // Heart of the Crusader (Rank 3) + case 20337: + triggered_spell_id = 54499; + break; + case 20911: // Blessing of Sanctuary + case 25899: // Greater Blessing of Sanctuary + { + target = this; + switch (target->getPowerType()) + { + case POWER_MANA: + triggered_spell_id = 57319; + break; + default: + return false; + } + break; + } // Holy Power (Redemption Armor set) case 28789: { @@ -5830,20 +5886,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu } break; } - case 25899: // Greater Blessing of Sanctuary - case 20911: // Blessing of Sanctuary - { - target = this; - switch (target->getPowerType()) - { - case POWER_MANA: - triggered_spell_id = 57319; - break; - default: - return false; - } - break; - } // Seal of Vengeance (damage calc on apply aura) case 31801: { @@ -5867,6 +5909,62 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu CastSpell(target,42463,true,NULL,triggeredByAura); break; } + // Judgements of the Wise + case 31876: + case 31877: + case 31878: + // triggered only at casted Judgement spells, not at additional Judgement effects + if(!procSpell || procSpell->Category != 1210) + return false; + + target = this; + triggered_spell_id = 31930; + + // Replenishment + CastSpell(this, 57669, true, NULL, triggeredByAura); + break; + // Spiritual Attunement + case 31785: + case 33776: + { + // if healed by another unit (pVictim) + if(this == pVictim) + return false; + + // heal amount + basepoints0 = triggerAmount*damage/100; + target = this; + triggered_spell_id = 31786; + break; + } + // Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal) + case 40470: + { + if (!procSpell) + return false; + + float chance; + + // Flash of light/Holy light + if (procSpell->SpellFamilyFlags & UI64LIT(0x00000000C0000000)) + { + triggered_spell_id = 40471; + chance = 15.0f; + } + // Judgement (any) + else if (GetSpellSpecific(procSpell->Id)==SPELL_JUDGEMENT) + { + triggered_spell_id = 40472; + chance = 50.0f; + } + else + return false; + + if (!roll_chance_f(chance)) + return false; + + break; + } // Seal of Corruption (damage calc on apply aura) case 53736: { @@ -5890,30 +5988,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu CastSpell(target,53739,true,NULL,triggeredByAura); break; } - // Spiritual Attunement - case 31785: - case 33776: - { - // if healed by another unit (pVictim) - if(this == pVictim) - return false; - - // heal amount - basepoints0 = triggerAmount*damage/100; - target = this; - triggered_spell_id = 31786; - break; - } - // Seal of Blood do damage trigger - case 31892: - { - // 0 effect - is proc on enemy - if (effIndex == 0 && (procFlag & PROC_FLAG_SUCCESSFUL_MELEE_HIT)) - triggered_spell_id = 31893; - else - return true; - break; - } // Light's Beacon (heal target area aura) case 53651: { @@ -5949,44 +6023,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu beacon->CastCustomSpell(beacon,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura,pVictim->GetGUID()); return true; } - // Seal of the Martyr do damage trigger - case 53720: - { - // 0 effect - is proc on enemy - if (effIndex == 0 && (procFlag & PROC_FLAG_SUCCESSFUL_MELEE_HIT)) - triggered_spell_id = 53719; - else - return true; - break; - } - // Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal) - case 40470: - { - if (!procSpell) - return false; - - float chance; - - // Flash of light/Holy light - if (procSpell->SpellFamilyFlags & UI64LIT(0x00000000C0000000)) - { - triggered_spell_id = 40471; - chance = 15.0f; - } - // Judgement (any) - else if (GetSpellSpecific(procSpell->Id)==SPELL_JUDGEMENT) - { - triggered_spell_id = 40472; - chance = 50.0f; - } - else - return false; - - if (!roll_chance_f(chance)) - return false; - - break; - } // Glyph of Divinity case 54939: { @@ -6404,6 +6440,85 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 51460; break; } + // Threat of Thassarian + if (dummySpell->SpellIconID == 2023) + { + // Must Dual Wield + if (!procSpell || !haveOffhandWeapon()) + return false; + // Chance as basepoints for dummy aura + if (!roll_chance_i(triggerAmount)) + return false; + + switch (procSpell->Id) + { + // Obliterate + case 49020: // Rank 1 + triggered_spell_id = 66198; break; + case 51423: // Rank 2 + triggered_spell_id = 66972; break; + case 51424: // Rank 3 + triggered_spell_id = 66973; break; + case 51425: // Rank 4 + triggered_spell_id = 66974; break; + // Frost Strike + case 49143: // Rank 1 + triggered_spell_id = 66196; break; + case 51416: // Rank 2 + triggered_spell_id = 66958; break; + case 51417: // Rank 3 + triggered_spell_id = 66959; break; + case 51418: // Rank 4 + triggered_spell_id = 66960; break; + case 51419: // Rank 5 + triggered_spell_id = 66961; break; + case 51420: // Rank 6 + triggered_spell_id = 66962; break; + // Plague Strike + case 45462: // Rank 1 + triggered_spell_id = 66216; break; + case 49917: // Rank 2 + triggered_spell_id = 66988; break; + case 49918: // Rank 3 + triggered_spell_id = 66989; break; + case 49919: // Rank 4 + triggered_spell_id = 66990; break; + case 49920: // Rank 5 + triggered_spell_id = 66991; break; + case 49921: // Rank 6 + triggered_spell_id = 66992; break; + // Death Strike + case 49998: // Rank 1 + triggered_spell_id = 66188; break; + case 49999: // Rank 2 + triggered_spell_id = 66950; break; + case 45463: // Rank 3 + triggered_spell_id = 66951; break; + case 49923: // Rank 4 + triggered_spell_id = 66952; break; + case 49924: // Rank 5 + triggered_spell_id = 66953; break; + // Rune Strike + case 56815: + triggered_spell_id = 66217; break; + // Blood Strike + case 45902: // Rank 1 + triggered_spell_id = 66215; break; + case 49926: // Rank 2 + triggered_spell_id = 66975; break; + case 49927: // Rank 3 + triggered_spell_id = 66976; break; + case 49928: // Rank 4 + triggered_spell_id = 66977; break; + case 49929: // Rank 5 + triggered_spell_id = 66978; break; + case 49930: // Rank 6 + triggered_spell_id = 66979; break; + default: + return false; + } + break; + } // Runic Power Back on Snare/Root if (dummySpell->Id == 61257) { @@ -6542,7 +6657,23 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB // intellect if (GetStat(STAT_INTELLECT)> stat) { trigger_spell_id = 60234;stat = GetStat(STAT_INTELLECT);} // spirit - if (GetStat(STAT_SPIRIT) > stat) { trigger_spell_id = 60235;stat = GetStat(STAT_SPIRIT); } + if (GetStat(STAT_SPIRIT) > stat) { trigger_spell_id = 60235; } + } + else if (auraSpellInfo->Id==67702) // Death's Choice, Item - Coliseum 25 Normal Melee Trinket + { + float stat = 0.0f; + // strength + if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 67708;stat = GetStat(STAT_STRENGTH); } + // agility + if (GetStat(STAT_AGILITY) > stat) { trigger_spell_id = 67703; } + } + else if (auraSpellInfo->Id==67771) // Death's Choice (heroic), Item - Coliseum 25 Heroic Melee Trinket + { + float stat = 0.0f; + // strength + if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 67773;stat = GetStat(STAT_STRENGTH); } + // agility + if (GetStat(STAT_AGILITY) > stat) { trigger_spell_id = 67772; } } //else if (auraSpellInfo->Id==31255) // Deadly Swiftness (Rank 1) //else if (auraSpellInfo->Id==5301) // Defensive State (DND) @@ -8701,13 +8832,9 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM // Lava Burst if (spellProto->SpellFamilyFlags & UI64LIT(0x0000100000000000)) { + // Flame Shock if (Aura *flameShock = pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, UI64LIT(0x0000000010000000), 0, GetGUID())) - { - // Consume shock aura if not have Glyph of Flame Shock - if (!GetAura(55447, 0)) - pVictim->RemoveAurasByCasterSpell(flameShock->GetId(), GetGUID()); return true; - } } break; } @@ -9261,7 +9388,16 @@ uint32 Unit::MeleeDamageBonus(Unit *pVictim, uint32 pdamage,WeaponAttackType att TakenPercent *= pVictim->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, schoolMask); // ..taken pct (by mechanic mask) - TakenPercent *= pVictim->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT, mechanicMask); + if (mechanicMask) + { + AuraList const& mTotalAuraList = GetAurasByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT); + for(AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + { + Modifier* mod = (*i)->GetModifier(); + if ((1<<(mod->m_miscvalue-1)) & mechanicMask) + TakenPercent *= (100.0f + mod->m_amount)/100.0f; + } + } // ..taken pct (melee/ranged) if(attType == RANGED_ATTACK) @@ -9750,10 +9886,6 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo return false; } - // always seen by owner - if (GetCharmerOrOwnerGUID()==u->GetGUID()) - return true; - // always seen by far sight caster if (u->GetTypeId()==TYPEID_PLAYER && ((Player*)u)->GetFarSight()==GetGUID()) return true; @@ -9798,6 +9930,10 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo return false; } + // always seen by owner + if (GetCharmerOrOwnerGUID()==u->GetGUID()) + return true; + // isInvisibleForAlive() those units can only be seen by dead or if other // unit is also invisible for alive.. if an isinvisibleforalive unit dies we // should be able to see it too @@ -10307,6 +10443,8 @@ void Unit::AddThreat(Unit* pVictim, float threat /*= 0.0f*/, bool crit /*= false void Unit::DeleteThreatList() { + if(CanHaveThreatList() && !m_ThreatManager.isThreatListEmpty()) + SendThreatClear(); m_ThreatManager.clearReferences(); } @@ -12668,3 +12806,97 @@ uint32 Unit::GetCombatRatingDamageReduction(CombatRating cr, float rate, float c percent = cap; return uint32 (percent * damage / 100.0f); } + +void Unit::SendThreatUpdate() +{ + ThreatList const& tlist = getThreatManager().getThreatList(); + if (uint32 count = tlist.size()) + { + sLog.outDebug( "WORLD: Send SMSG_THREAT_UPDATE Message" ); + WorldPacket data(SMSG_THREAT_UPDATE, 8 + count * 8); + data.append(GetPackGUID()); + data << uint32(count); + for (ThreatList::const_iterator itr = tlist.begin(); itr != tlist.end(); ++itr) + { + data.appendPackGUID((*itr)->getUnitGuid()); + data << uint32((*itr)->getThreat()); + } + SendMessageToSet(&data, false); + } +} + +void Unit::SendHighestThreatUpdate(HostileReference* pHostilReference) +{ + ThreatList const& tlist = getThreatManager().getThreatList(); + if (uint32 count = tlist.size()) + { + sLog.outDebug( "WORLD: Send SMSG_HIGHEST_THREAT_UPDATE Message" ); + WorldPacket data(SMSG_HIGHEST_THREAT_UPDATE, 8 + 8 + count * 8); + data.append(GetPackGUID()); + data.appendPackGUID(pHostilReference->getUnitGuid()); + data << uint32(count); + for (ThreatList::const_iterator itr = tlist.begin(); itr != tlist.end(); ++itr) + { + data.appendPackGUID((*itr)->getUnitGuid()); + data << uint32((*itr)->getThreat()); + } + SendMessageToSet(&data, false); + } +} + +void Unit::SendThreatClear() +{ + sLog.outDebug( "WORLD: Send SMSG_THREAT_CLEAR Message" ); + WorldPacket data(SMSG_THREAT_CLEAR, 8); + data.append(GetPackGUID()); + SendMessageToSet(&data, false); +} + +void Unit::SendThreatRemove(HostileReference* pHostileReference) +{ + sLog.outDebug( "WORLD: Send SMSG_THREAT_REMOVE Message" ); + WorldPacket data(SMSG_THREAT_REMOVE, 8 + 8); + data.append(GetPackGUID()); + data.appendPackGUID(pHostileReference->getUnitGuid()); + SendMessageToSet(&data, false); +} + +void Unit::StopAttackFaction(uint32 faction_id) +{ + if (Unit* victim = getVictim()) + { + if (victim->getFactionTemplateEntry()->faction==faction_id) + { + AttackStop(); + if (IsNonMeleeSpellCasted(false)) + InterruptNonMeleeSpells(false); + + // melee and ranged forced attack cancel + if (GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->SendAttackSwingCancelAttack(); + } + } + + AttackerSet const& attackers = getAttackers(); + for(AttackerSet::const_iterator itr = attackers.begin(); itr != attackers.end();) + { + if ((*itr)->getFactionTemplateEntry()->faction==faction_id) + { + (*itr)->AttackStop(); + itr = attackers.begin(); + } + else + ++itr; + } + + getHostileRefManager().deleteReferencesForFaction(faction_id); + + if(Pet* pet = GetPet()) + pet->StopAttackFaction(faction_id); + if(Unit* charm = GetCharm()) + charm->StopAttackFaction(faction_id); + + for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end(); ++itr) + if(Unit* guardian = Unit::GetUnit(*this,*itr)) + guardian->StopAttackFaction(faction_id); +} diff --git a/src/game/Unit.h b/src/game/Unit.h index aa1d5fce2..0d5fea3d5 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -929,6 +929,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject Unit* getVictim() const { return m_attacking; } void CombatStop(bool includingCast = false); void CombatStopWithPets(bool includingCast = false); + void StopAttackFaction(uint32 faction_id); Unit* SelectNearbyTarget(Unit* except = NULL) const; bool hasNegativeAuraWithInterruptFlag(uint32 flag); void SendMeleeAttackStop(Unit* victim); @@ -1161,6 +1162,11 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, MonsterMovementFlags flags, uint32 Time, Player* player = NULL); void SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end, MonsterMovementFlags flags); + void SendHighestThreatUpdate(HostileReference* pHostileReference); + void SendThreatClear(); + void SendThreatRemove(HostileReference* pHostileReference); + void SendThreatUpdate(); + void BuildHeartBeatMsg( WorldPacket *data ) const; virtual void MoveOutOfRange(Player &) { }; @@ -1373,6 +1379,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void TauntApply(Unit* pVictim); void TauntFadeOut(Unit *taunter); ThreatManager& getThreatManager() { return m_ThreatManager; } + ThreatManager const& getThreatManager() const { return m_ThreatManager; } void addHatedBy(HostileReference* pHostileReference) { m_HostileRefManager.insertFirst(pHostileReference); }; void removeHatedBy(HostileReference* /*pHostileReference*/ ) { /* nothing to do yet */ } HostileRefManager& getHostileRefManager() { return m_HostileRefManager; } diff --git a/src/game/UpdateData.h b/src/game/UpdateData.h index 211025ade..c96f50063 100644 --- a/src/game/UpdateData.h +++ b/src/game/UpdateData.h @@ -36,17 +36,17 @@ enum OBJECT_UPDATE_TYPE enum OBJECT_UPDATE_FLAGS { - UPDATEFLAG_NONE = 0x0000, - UPDATEFLAG_SELF = 0x0001, - UPDATEFLAG_TRANSPORT = 0x0002, - UPDATEFLAG_HAS_TARGET = 0x0004, - UPDATEFLAG_LOWGUID = 0x0008, - UPDATEFLAG_HIGHGUID = 0x0010, - UPDATEFLAG_LIVING = 0x0020, - UPDATEFLAG_HAS_POSITION = 0x0040, - UPDATEFLAG_VEHICLE = 0x0080, - UPDATEFLAG_POSITION = 0x0100, - UPDATEFLAG_ROTATION = 0x0200 + UPDATEFLAG_NONE = 0x0000, + UPDATEFLAG_SELF = 0x0001, + UPDATEFLAG_TRANSPORT = 0x0002, + UPDATEFLAG_HAS_ATTACKING_TARGET = 0x0004, + UPDATEFLAG_LOWGUID = 0x0008, + UPDATEFLAG_HIGHGUID = 0x0010, + UPDATEFLAG_LIVING = 0x0020, + UPDATEFLAG_HAS_POSITION = 0x0040, + UPDATEFLAG_VEHICLE = 0x0080, + UPDATEFLAG_POSITION = 0x0100, + UPDATEFLAG_ROTATION = 0x0200 }; class UpdateData diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 479d7b392..8917fa4ca 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -169,97 +169,93 @@ bool WorldSession::Update(uint32 /*diff*/) packet->GetOpcode()); #endif*/ - if(packet->GetOpcode() >= NUM_MSG_TYPES) + OpcodeHandler& opHandle = opcodeTable[packet->GetOpcode()]; + try { - sLog.outError( "SESSION: received non-existed opcode %s (0x%.4X)", - LookupOpcodeName(packet->GetOpcode()), - packet->GetOpcode()); - } - else - { - OpcodeHandler& opHandle = opcodeTable[packet->GetOpcode()]; - try + switch (opHandle.status) { - switch (opHandle.status) - { - case STATUS_LOGGEDIN: - if(!_player) - { - // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets - if(!m_playerRecentlyLogout) - LogUnexpectedOpcode(packet, "the player has not logged in yet"); - } - else if(_player->IsInWorld()) - { - (this->*opHandle.handler)(*packet); - if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) - LogUnprocessedTail(packet); - } - // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer - break; - case STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT: - if(!_player && !m_playerRecentlyLogout) - { - LogUnexpectedOpcode(packet, "the player has not logged in yet and not recently logout"); - } - else - { - // not expected _player or must checked in packet hanlder - (this->*opHandle.handler)(*packet); - if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) - LogUnprocessedTail(packet); - } - break; - case STATUS_TRANSFER: - if(!_player) + case STATUS_LOGGEDIN: + if(!_player) + { + // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets + if(!m_playerRecentlyLogout) LogUnexpectedOpcode(packet, "the player has not logged in yet"); - else if(_player->IsInWorld()) - LogUnexpectedOpcode(packet, "the player is still in world"); - else - { - (this->*opHandle.handler)(*packet); - if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) - LogUnprocessedTail(packet); - } - break; - case STATUS_AUTHED: - // prevent cheating with skip queue wait - if(m_inQueue) - { - LogUnexpectedOpcode(packet, "the player not pass queue yet"); - break; - } - - // single from authed time opcodes send in to after logout time - // and before other STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes. - if (packet->GetOpcode() != CMSG_SET_ACTIVE_VOICE_CHANNEL) - m_playerRecentlyLogout = false; - + } + else if(_player->IsInWorld()) + { (this->*opHandle.handler)(*packet); if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) LogUnprocessedTail(packet); + } + // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer + break; + case STATUS_LOGGEDIN_OR_RECENTLY_LOGGEDOUT: + if(!_player && !m_playerRecentlyLogout) + { + LogUnexpectedOpcode(packet, "the player has not logged in yet and not recently logout"); + } + else + { + // not expected _player or must checked in packet hanlder + (this->*opHandle.handler)(*packet); + if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) + LogUnprocessedTail(packet); + } + break; + case STATUS_TRANSFER: + if(!_player) + LogUnexpectedOpcode(packet, "the player has not logged in yet"); + else if(_player->IsInWorld()) + LogUnexpectedOpcode(packet, "the player is still in world"); + else + { + (this->*opHandle.handler)(*packet); + if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) + LogUnprocessedTail(packet); + } + break; + case STATUS_AUTHED: + // prevent cheating with skip queue wait + if(m_inQueue) + { + LogUnexpectedOpcode(packet, "the player not pass queue yet"); break; - case STATUS_NEVER: - sLog.outError( "SESSION: received not allowed opcode %s (0x%.4X)", - LookupOpcodeName(packet->GetOpcode()), - packet->GetOpcode()); - break; - case STATUS_UNHANDLED: - sLog.outDebug("SESSION: received not handled opcode %s (0x%.4X)", - LookupOpcodeName(packet->GetOpcode()), - packet->GetOpcode()); - break; - } + } + + // single from authed time opcodes send in to after logout time + // and before other STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes. + if (packet->GetOpcode() != CMSG_SET_ACTIVE_VOICE_CHANNEL) + m_playerRecentlyLogout = false; + + (this->*opHandle.handler)(*packet); + if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) + LogUnprocessedTail(packet); + break; + case STATUS_NEVER: + sLog.outError( "SESSION: received not allowed opcode %s (0x%.4X)", + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode()); + break; + case STATUS_UNHANDLED: + sLog.outDebug("SESSION: received not handled opcode %s (0x%.4X)", + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode()); + break; + default: + sLog.outError("SESSION: received wrong-status-req opcode %s (0x%.4X)", + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode()); + break; } - catch(ByteBufferException &) + } + catch(ByteBufferException &) + { + sLog.outError("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.", + packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId()); + if(sLog.IsOutDebug()) { - sLog.outError("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.", - packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId()); - if(sLog.IsOutDebug()) - { - sLog.outDebug("Dumping error causing packet:"); - packet->hexlike(); - } + sLog.outDebug("Dumping error causing packet:"); + packet->hexlike(); } } diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp index f7ad1469a..ba7fbbefc 100644 --- a/src/game/WorldSocket.cpp +++ b/src/game/WorldSocket.cpp @@ -659,6 +659,12 @@ int WorldSocket::ProcessIncoming (WorldPacket* new_pct) const ACE_UINT16 opcode = new_pct->GetOpcode (); + if (opcode >= NUM_MSG_TYPES) + { + sLog.outError( "SESSION: received non-existed opcode 0x%.4X", opcode); + return -1; + } + if (closing_) return -1; @@ -839,9 +845,9 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) // Re-check account ban (same check as in realmd) QueryResult *banresult = - loginDatabase.PQuery ("SELECT 1 FROM account_banned WHERE id = %u AND active = 1 " + loginDatabase.PQuery ("SELECT 1 FROM account_banned WHERE id = %u AND active = 1 AND (unbandate > UNIX_TIMESTAMP() OR unbandate = bandate)" "UNION " - "SELECT 1 FROM ip_banned WHERE ip = '%s'", + "SELECT 1 FROM ip_banned WHERE (unbandate = bandate OR unbandate > UNIX_TIMESTAMP()) AND ip = '%s'", id, GetRemoteAddress().c_str()); if (banresult) // if account banned diff --git a/src/mangosd/Main.cpp b/src/mangosd/Main.cpp index a662dd56d..3985ec76d 100644 --- a/src/mangosd/Main.cpp +++ b/src/mangosd/Main.cpp @@ -30,6 +30,7 @@ #include "revision_nr.h" #include #include +#include #ifdef WIN32 #include "ServiceWin32.h" @@ -166,6 +167,7 @@ extern int main(int argc, char **argv) sLog.outDetail("WARNING: Outdated version of OpenSSL lib. Logins to server may not work!"); sLog.outDetail("WARNING: Minimal required version [OpenSSL 0.9.8k]"); } + sLog.outDetail("Using ACE: %s", ACE_VERSION); ///- and run the 'Master' /// \todo Why do we need this 'Master'? Can't all of this be in the Main as for Realmd? diff --git a/src/mangosd/Master.cpp b/src/mangosd/Master.cpp index 8e4daa9b4..1117a1739 100644 --- a/src/mangosd/Master.cpp +++ b/src/mangosd/Master.cpp @@ -291,8 +291,6 @@ int Master::Run() uint32 realCurrTime, realPrevTime; realCurrTime = realPrevTime = getMSTime(); - uint32 socketSelecttime = sWorld.getConfig(CONFIG_SOCKET_SELECTTIME); - ///- Start up freeze catcher thread if(uint32 freeze_delay = sConfig.GetIntDefault("MaxCoreStuckTime", 0)) { diff --git a/src/mangosd/RASocket.cpp b/src/mangosd/RASocket.cpp index 91baac0a6..db03c6ae9 100644 --- a/src/mangosd/RASocket.cpp +++ b/src/mangosd/RASocket.cpp @@ -28,15 +28,12 @@ #include "Config/ConfigEnv.h" #include "Util.h" #include "AccountMgr.h" +#include "Language.h" +#include "ObjectMgr.h" /// \todo Make this thread safe if in the future 2 admins should be able to log at the same time. SOCKET r; -#define dropclient {Sendf("I'm busy right now, come back later."); \ - SetCloseAndDelete(); \ - return; \ - } - uint32 iSession=0; ///< Session number (incremented each time a new connection is made) unsigned int iUsers=0; ///< Number of active administrators @@ -80,10 +77,15 @@ void RASocket::OnAccept() sLog.outRALog("Incoming connection from %s.\n",ss.c_str()); ///- If there is already an active admin, drop the connection if(iUsers) - dropclient + { + Sendf(sObjectMgr.GetMangosStringForDBCLocale(LANG_RA_BUSY)); + SetCloseAndDelete(); + return; + } - ///- Else print Motd - Sendf("%s\r\n",sWorld.GetMotd()); + ///- Else print Motd + Sendf("%s\r\n",sWorld.GetMotd()); + Sendf("\r\n%s",sObjectMgr.GetMangosStringForDBCLocale(LANG_RA_USER)); } /// Read data from the network @@ -93,7 +95,7 @@ void RASocket::OnRead() TcpSocket::OnRead(); unsigned int sz=ibuf.GetLength(); - if(iInputLength+sz>=RA_BUFF_SIZE) + if (iInputLength+sz>=RA_BUFF_SIZE) { sLog.outRALog("Input buffer overflow, possible DOS attack.\n"); SetCloseAndDelete(); @@ -101,126 +103,126 @@ void RASocket::OnRead() } ///- If there is already an active admin (other than you), drop the connection - if(stage!=OK && iUsers) - dropclient + if (stage!=OK && iUsers) + { + Sendf(sObjectMgr.GetMangosStringForDBCLocale(LANG_RA_BUSY)); + SetCloseAndDelete(); + return; + } - char *inp = new char [sz+1]; + char *inp = new char [sz+1]; ibuf.Read(inp,sz); - /// \todo Can somebody explain this 'Linux bugfix'? - if(stage==NONE) - if(sz>4) //linux remote telnet - if(memcmp(inp ,"USER ",5)) - { - delete [] inp;return; - printf("lin bugfix"); - } //linux bugfix - ///- Discard data after line break or line feed bool gotenter=false; unsigned int y=0; for(;y
  • If the input is 'USER ' case NONE: - if(!memcmp(buff,"USER ",5)) //got "USER" cmd + { + ///- If we're interactive we don't expect "USER " to be there + szLogin=&buff[0]; + + ///- Get the gmlevel from the account table + std::string login = szLogin; + + ///- Convert Account name to Upper Format + AccountMgr::normalizeString(login); + + ///- Escape the Login to allow quotes in names + loginDatabase.escape_string(login); + + QueryResult* result = loginDatabase.PQuery("SELECT gmlevel FROM account WHERE username = '%s'",login.c_str()); + + ///- If the user is not found, deny access + if(!result) { - szLogin=&buff[5]; + Sendf("-No such user.\r\n"); + sLog.outRALog("User %s does not exist.\n",szLogin.c_str()); + if(bSecure)SetCloseAndDelete(); + Sendf("\r\n%s",sObjectMgr.GetMangosStringForDBCLocale(LANG_RA_USER)); + } + else + { + Field *fields = result->Fetch(); - ///- Get the gmlevel and password from the account table - std::string login = szLogin; - - ///- Convert Account name to Upper Format - AccountMgr::normalizeString(login); - - ///- Escape the Login to allow quotes in names - loginDatabase.escape_string(login); - - QueryResult* result = loginDatabase.PQuery("SELECT gmlevel FROM account WHERE username = '%s'",login.c_str()); - - ///- If the user is not found, deny access - if(!result) + ///- if gmlevel is too low, deny access + if (fields[0].GetUInt32()Fetch(); - - //szPass=fields[0].GetString(); - - ///- if gmlevel is too low, deny access - if(fields[0].GetUInt32() If the input is 'PASS ' (and the user already gave his username) + } + ///
  • If the input is 'PASS ' (and the user already gave his username) case LG: - if(!memcmp(buff,"PASS ",5)) //got "PASS" cmd - { //login+pass ok - ///- If password is correct, increment the number of active administrators - std::string login = szLogin; - std::string pw = &buff[5]; + { //login+pass ok + ///- If password is correct, increment the number of active administrators + std::string login = szLogin; - AccountMgr::normalizeString(login); - AccountMgr::normalizeString(pw); - loginDatabase.escape_string(login); - loginDatabase.escape_string(pw); + ///- If we're interactive we don't expect "PASS " to be there + std::string pw = &buff[0]; - QueryResult *check = loginDatabase.PQuery( - "SELECT 1 FROM account WHERE username = '%s' AND sha_pass_hash=SHA1(CONCAT(username,':','%s'))", - login.c_str(), pw.c_str()); + AccountMgr::normalizeString(login); + AccountMgr::normalizeString(pw); + loginDatabase.escape_string(login); + loginDatabase.escape_string(pw); - if(check) - { - delete check; - r=GetSocket(); - stage=OK; - ++iUsers; + QueryResult *check = loginDatabase.PQuery( + "SELECT 1 FROM account WHERE username = '%s' AND sha_pass_hash=SHA1(CONCAT(username,':','%s'))", + login.c_str(), pw.c_str()); - Sendf("+Logged in.\r\n"); - sLog.outRALog("User %s has logged in.\n",szLogin.c_str()); - Sendf("mangos>"); - } - else - { - ///- Else deny access - Sendf("-Wrong pass.\r\n"); - sLog.outRALog("User %s has failed to log in.\n",szLogin.c_str()); - if(bSecure)SetCloseAndDelete(); - } + if (check) + { + delete check; + r=GetSocket(); + stage=OK; + ++iUsers; + + Sendf("+Logged in.\r\n"); + sLog.outRALog("User %s has logged in.\n",szLogin.c_str()); + Sendf("mangos>"); + } + else + { + ///- Else deny access + Sendf("-Wrong pass.\r\n"); + sLog.outRALog("User %s has failed to log in.\n",szLogin.c_str()); + if(bSecure)SetCloseAndDelete(); + Sendf("\r\n%s",sObjectMgr.GetMangosStringForDBCLocale(LANG_RA_PASS)); } break; - ///
  • If user is logged, parse and execute the command + } + ///
  • If user is logged, parse and execute the command case OK: - if(strlen(buff)) + if (strlen(buff)) { sLog.outRALog("Got '%s' cmd.\n",buff); sWorld.QueueCliCommand(&RASocket::zprint , buff); @@ -228,7 +230,7 @@ void RASocket::OnRead() else Sendf("mangos>"); break; - /// + /// }; } diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index d925a1571..479a6ce5d 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -303,6 +303,7 @@ LogFilter_CreatureMoves = 1 LogFilter_TransportMoves = 1 LogFilter_VisibilityChanges = 1 WorldLogFile = "" +WorldLogTimestamp = 0 DBErrorLogFile = "DBErrors.log" CharLogFile = "Char.log" CharLogTimestamp = 0 diff --git a/src/shared/LockedQueue.h b/src/shared/LockedQueue.h index 72ec9e1b1..abb68dd80 100644 --- a/src/shared/LockedQueue.h +++ b/src/shared/LockedQueue.h @@ -42,20 +42,27 @@ namespace ACE_Based public: //! Create a LockedQueue. - LockedQueue() : _canceled(false) {} + LockedQueue() + : _canceled(false) + { + } //! Destroy a LockedQueue. - virtual ~LockedQueue() { } + virtual ~LockedQueue() + { + } //! Adds an item to the queue. void add(const T& item) { - ACE_Guard g(this->_lock); + lock(); //ASSERT(!this->_canceled); // throw Cancellation_Exception(); _queue.push_back(item); + + unlock(); } //! Gets the next result in the queue, if any. @@ -75,12 +82,24 @@ namespace ACE_Based return true; } + //! Peeks at the top of the queue. Remember to unlock after use. + T& peek() + { + lock(); + + T& result = _queue.front(); + + return result; + } + //! Cancels the queue. void cancel() { - ACE_Guard g(this->_lock); + lock(); _canceled = true; + + unlock(); } //! Checks if the queue is cancelled. @@ -90,6 +109,18 @@ namespace ACE_Based return _canceled; } + + //! Locks the queue for access. + void lock() + { + this->_lock.acquire(); + } + + //! Unlocks the queue. + void unlock() + { + this->_lock.release(); + } }; } #endif diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index ae0e67afb..28a3902eb 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 "8840" + #define REVISION_NR "8892" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index 122f4e8a5..7ea9ac652 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ - #define REVISION_DB_CHARACTERS "required_8828_01_characters_instance_reset" - #define REVISION_DB_MANGOS "required_8840_01_mangos_spell_proc_event" + #define REVISION_DB_CHARACTERS "required_8874_01_characters_character_skills" + #define REVISION_DB_MANGOS "required_8891_01_mangos_spell_proc_event" #define REVISION_DB_REALMD "required_8728_01_realmd_account" #endif // __REVISION_SQL_H__ diff --git a/win/VC100/script.vcxproj b/win/VC100/script.vcxproj index 13ff773cd..cd0a48fae 100644 --- a/win/VC100/script.vcxproj +++ b/win/VC100/script.vcxproj @@ -91,32 +91,32 @@ <_ProjectFileVersion>10.0.20506.1 ..\..\bin\$(Platform)_$(Configuration)\ .\script__$(Platform)_$(Configuration)\ - MaNGOSScript + mangosscript .dll true ..\..\bin\$(Platform)_$(Configuration)\ .\script__$(Platform)_$(Configuration)\ - MaNGOSScript + mangosscript .dll false ..\..\bin\$(Platform)_$(Configuration)\ .\script__$(Platform)_$(Configuration)\ - MaNGOSScript + mangosscript .dll false ..\..\bin\$(Platform)_$(Configuration)\ .\script__$(Platform)_$(Configuration)\ - MaNGOSScript + mangosscript .dll false ..\..\bin\$(Platform)_$(Configuration)\ .\script__$(Platform)_$(Configuration)\ - MaNGOSScript + mangosscript .dll false ..\..\bin\$(Platform)_$(Configuration)\ .\script__$(Platform)_$(Configuration)\ - MaNGOSScript + mangosscript .dll false AllRules.ruleset @@ -157,12 +157,12 @@ mangosd.lib;zlib.lib;libmySQL.lib;libeay32.lib;ws2_32.lib;winmm.lib;odbc32.lib;odbccp32.lib;aced.lib;%(AdditionalDependencies) .\mangosd__$(Platform)_$(Configuration);.\zlib__$(Platform)_$(Configuration);..\..\dep\lib\$(Platform)_$(Configuration);.\$(OutDir);%(AdditionalLibraryDirectories) true - $(OutDir)MaNGOSScript.pdb + $(OutDir)mangosscript.pdb Windows false - $(IntDir)MaNGOSScript.lib + $(IntDir)mangosscript.lib MachineX86 @@ -188,12 +188,12 @@ mangosd.lib;zlib.lib;libmySQL.lib;libeay32.lib;ws2_32.lib;winmm.lib;odbc32.lib;odbccp32.lib;aced.lib;%(AdditionalDependencies) .\mangosd__$(Platform)_$(Configuration);.\zlib__$(Platform)_$(Configuration);..\..\dep\lib\$(Platform)_$(Configuration);%(AdditionalLibraryDirectories) true - $(OutDir)MaNGOSScript.pdb + $(OutDir)mangosscript.pdb Windows false - $(IntDir)MaNGOSScript.lib + $(IntDir)mangosscript.lib MachineX64 @@ -220,7 +220,7 @@ false - $(IntDir)MaNGOSScript.lib + $(IntDir)mangosscript.lib MachineX86 @@ -250,7 +250,7 @@ false - $(IntDir)MaNGOSScript.lib + $(IntDir)mangosscript.lib MachineX64 @@ -273,12 +273,12 @@ mangosd.lib;zlib.lib;libmySQL.lib;libeay32.lib;ws2_32.lib;winmm.lib;odbc32.lib;odbccp32.lib;aced.lib;%(AdditionalDependencies) .\mangosd__$(Platform)_$(Configuration);.\zlib__$(Platform)_$(Configuration);..\..\dep\lib\$(Platform)_debug;%(AdditionalLibraryDirectories) true - $(OutDir)MaNGOSScript.pdb + $(OutDir)mangosscript.pdb Windows false - $(IntDir)MaNGOSScript.lib + $(IntDir)mangosscript.lib MachineX86 @@ -304,12 +304,12 @@ mangosd.lib;zlib.lib;libmySQL.lib;libeay32.lib;ws2_32.lib;winmm.lib;odbc32.lib;odbccp32.lib;aced.lib;%(AdditionalDependencies) .\mangosd__$(Platform)_$(Configuration);.\zlib__$(Platform)_$(Configuration);..\..\dep\lib\$(Platform)_debug;%(AdditionalLibraryDirectories) true - $(OutDir)MaNGOSScript.pdb + $(OutDir)mangosscript.pdb Windows false - $(IntDir)MaNGOSScript.lib + $(IntDir)mangosscript.lib MachineX64 diff --git a/win/VC80/script.vcproj b/win/VC80/script.vcproj index fe71c05fd..37ae2ce5a 100644 --- a/win/VC80/script.vcproj +++ b/win/VC80/script.vcproj @@ -65,13 +65,13 @@