diff --git a/sql/mangos_spell_check.sql b/sql/mangos_spell_check.sql new file mode 100644 index 000000000..23d0134d4 --- /dev/null +++ b/sql/mangos_spell_check.sql @@ -0,0 +1,225 @@ +/* This file contain expected by code spell properties from simple existance to spell family mask and icons. */ + +/* This data let easy detect spell properties change at client version */ +/* support switch and update or drop problematic code associated with checked*/ +/* spell data. */ + +/* sql file not required for server work but expected to be applied to */ +/* MaNGOS DB if you plan use .debug spellcheck command in console. */ + +/* To code commiters: */ +/* */ +/* If you commit code that include explicit used spell id or checks base at */ +/* spell family mask (and etc) please include same data in this table always.*/ +/* At least for parts already added in table. */ +/* File not required sql updates way to support, and always expected full */ +/* re-adding before command use. So need just adding new line to file. */ + +/* Current table fill progress state: */ +/* SpellEffect.cpp from start until end of SPELLFAMILY_GENERIC case of Spell::EffectDummy */ + +DROP TABLE IF EXISTS spell_check; +CREATE TABLE `spell_check` ( + spellid mediumint(7) unsigned NOT NULL default '0', + SpellFamilyName smallint(5) NOT NULL default '-1', + SpellFamilyMaskA bigint(30) NOT NULL default '-1', /* 0xFFFFFFFFFFFFFFFF */ + SpellFamilyMaskB int(10) NOT NULL default '-1', /* 0xFFFFFFFF */ + SpellIcon int(10) NOT NULL default '-1', + SpellVisual int(10) NOT NULL default '-1', + SpellCategory int(10) NOT NULL default '-1', + EffectType int(10) NOT NULL default '-1', + EffectAura int(10) NOT NULL default '-1', + EffectIdx tinyint(3) NOT NULL default '-1', + Name varchar(40) NOT NULL default '', + Code varchar(40) NOT NULL default '', + PRIMARY KEY (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMaskB,SpellIcon,SpellVisual,SpellCategory,EffectType,EffectAura,EffectIdx,Code) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO spell_check (spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMaskB,SpellIcon,SpellVisual,SpellCategory,EffectType,EffectAura,EffectIdx,Name,Code) VALUES +/* sorted by spell ids */ +/*id fm familyMaskA fmMaskB icon vis cat eff aur ef name code */ +(4073, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Mechanical Dragonling', 'Spell::EffectDummy'), +(8063, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Deviate Fish', 'Spell::EffectDummy'), +(8064, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Sleepy', 'Spell::EffectDummy'), +(8065, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Invigorate', 'Spell::EffectDummy'), +(8066, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Shrink', 'Spell::EffectDummy'), +(8067, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Party Time!', 'Spell::EffectDummy'), +(8068, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Healthy Spirit', 'Spell::EffectDummy'), +(8213, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Savory Deviate Delight', 'Spell::EffectDummy'), +(8219, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Flip Out', 'Spell::EffectDummy'), +(8220, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Flip Out', 'Spell::EffectDummy'), +(8221, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Yaaarrrr', 'Spell::EffectDummy'), +(8222, -1, -1, -1, -1, -1, -1, -1, -1,-1,'Yaaarrrr', 'Spell::EffectDummy'), +(8593, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Symbol of life', 'Spell::EffectDummy'), +(12162, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Deep wounds', 'Spell::EffectDummy'), +(12749,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Mithril Mechanical Dragonling', 'Spell::EffectDummy'), +(12850, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Deep wounds', 'Spell::EffectDummy'), +(12868, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Deep wounds', 'Spell::EffectDummy'), +(12721,-1, -1, -1, -1, -1, -1, 6, 3, 0,'Deep wounds', 'Spell::EffectDummy'), +(13099,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Net-o-Matic', 'Spell::EffectDummy'), +(13119,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Net-o-Matic', 'Spell::EffectDummy'), +(13120, 0, -1, -1, -1, -1, -1, 3, -1,-1,'net-o-matic', 'Spell::EffectDummy'), +(13166,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Gnomish Battle Chicken', 'Spell::EffectDummy'), +(13567, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Dummy Trigger', 'Spell::EffectDummy'), +(15998, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Capture Worg Pup', 'Spell::EffectDummy'), +(16566,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Net-o-Matic', 'Spell::EffectDummy'), +(16589, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Noggenfogger Elixir', 'Spell::EffectDummy'), +(16591,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Noggenfogger Elixir', 'Spell::EffectDummy'), +(16593,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Noggenfogger Elixir', 'Spell::EffectDummy'), +(16595,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Noggenfogger Elixir', 'Spell::EffectDummy'), +(17251, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Spirit Healer Res', 'Spell::EffectDummy'), +(17269,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Create Resonating Skull', 'Spell::EffectDummy'), +(17270,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Create Bone Dust', 'Spell::EffectDummy'), +(17271, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Test Fetid Skull', 'Spell::EffectDummy'), +(18788,-1, -1, -1, -1, -1, -1, 1, -1,-1,'Demonic Sacrifice', 'Spell::EffectInstaKill'), +(18789,-1, -1, -1, -1, -1, -1, -1, -1,-1,'', 'Spell::EffectInstaKill'), +(18790,-1, -1, -1, -1, -1, -1, -1, -1,-1,'', 'Spell::EffectInstaKill'), +(18791,-1, -1, -1, -1, -1, -1, -1, -1,-1,'', 'Spell::EffectInstaKill'), +(18792,-1, -1, -1, -1, -1, -1, -1, -1,-1,'', 'Spell::EffectInstaKill'), +(19804,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Arcanite Dragonling', 'Spell::EffectDummy'), +(20253, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Intercept', 'Spell::EffectSchoolDMG'), +(20577, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Cannibalize', 'Spell::EffectDummy'), +(20578,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Cannibalize', 'Spell::EffectDummy'), +(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'), +(23076, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Mechanical Dragonling', 'Spell::EffectDummy'), +(23133, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Gnomish Battle Chicken', 'Spell::EffectDummy'), +(23170,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Brood Affliction: Bronze', 'Spell::EffectDummy'), +(23441,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Gadgetzan Transporter', 'Spell::EffectDummy'), +(23444,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Transporter Malfunction', 'Spell::EffectDummy'), +(23445,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Evil Twin', 'Spell::EffectDummy'), +(23446,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Gadgetzan Transporter Failure', 'Spell::EffectDummy'), +(23448, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Transporter Arrival', 'Spell::EffectDummy'), +(23453, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Gnomish Transporter', 'Spell::EffectDummy'), +(23645, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Hourglass Sand', 'Spell::EffectDummy'), +(23725, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Gift of Life', 'Spell::EffectDummy'), +(23782,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Gift of Life', 'Spell::EffectDummy'), +(23783,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Gift of Life', 'Spell::EffectDummy'), +(24340, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor', 'Spell::EffectSchoolDMG'), +(25599, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Thundercrash', 'Spell::EffectSchoolDMG'), +(25858,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Reindeer', 'Spell::EffectDummy'), +(25859,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Reindeer', 'Spell::EffectDummy'), +(25860, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Reindeer Transformation', 'Spell::EffectDummy'), +(26074, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Holiday Cheer', 'Spell::EffectDummy'), +(26467,-1, -1, -1, -1, -1, -1, 6, 42, 0,'Persistent Shield', 'Spell::EffectDummy'), +(26558, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor', 'Spell::EffectSchoolDMG'), +(26635,-1, -1, -1, -1, -1, -1, 6, -1, 0,'Berserking', 'Spell::EffectDummy'), +(26635,-1, -1, -1, -1, -1, -1, 6, -1, 1,'Berserking', 'Spell::EffectDummy'), +(26635,-1, -1, -1, -1, -1, -1, 6, -1, 2,'Berserking', 'Spell::EffectDummy'), +(26789, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Shard of the Fallen Star', 'Spell::EffectSchoolDMG'), +(28006, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Arcane Cloaking', 'Spell::EffectDummy'), +(28884, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor', 'Spell::EffectSchoolDMG'), +(29294,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Naxxramas Entry Flag Effect DND', 'Spell::EffectDummy'), +(29200, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Purify Helboar Meat', 'Spell::EffectDummy'), +(29277,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Summon Purified Helboar Meat', 'Spell::EffectDummy'), +(29278,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Summon Toxic Helboar Meat', 'Spell::EffectDummy'), +(29435, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Capture Female Kaliri Hatchling', 'Spell::EffectDummy'), +(29858, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Soulshatter', 'Spell::EffectDummy'), +(30452,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Rocket Boots Engaged', 'Spell::EffectDummy'), +(30456,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Nigh-Invulnerability', 'Spell::EffectDummy'), +(30457,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Complete Vulnerability', 'Spell::EffectDummy'), +(30458, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Nigh Invulnerability', 'Spell::EffectDummy'), +(30501,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Poultryized!', 'Spell::EffectDummy'), +(30504,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Poultryized!', 'Spell::EffectDummy'), +(30507, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Poultryizer', 'Spell::EffectDummy'), +(31225, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Shimmering Vessel', 'Spell::EffectDummy'), +(31436, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Malevolent Cleave', 'Spell::EffectSchoolDMG'), +(31803,-1, -1, -1, -1, -1, -1, 6, 3,-1,'Holy Vengeance', 'Spell::EffectSchoolDMG'), +(32409,-1, -1, -1, -1, -1, -1, 6, 3,-1,'Shadow Word: Death', 'Spell::EffectSchoolDMG'), +(32835,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Soulshatter', 'Spell::EffectDummy'), +(33053,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Mr Pinchy\'s Blessing', 'Spell::EffectDummy'), +(33057,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Summon Mighty Mr. Pinchy', 'Spell::EffectDummy'), +(33059,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Summon Furious Mr. Pinchy', 'Spell::EffectDummy'), +(33060, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Make a Wish', 'Spell::EffectDummy'), +(33062,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Tiny Magical Crawdad', 'Spell::EffectDummy'), +(33064,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Mr. Pinchy\'s Gift', 'Spell::EffectDummy'), +(34665, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Administer Antidote', 'Spell::EffectDummy'), +(35181, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Dive Bomb', 'Spell::EffectSchoolDMG'), +(35701,-1, -1, -1, -1, -1, -1, -1, -1,-1,'', 'Spell::EffectInstaKill'), +(35743,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Socrethar Portal', 'Spell::EffectDummy'), +(35744,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Socrethar Portal', 'Spell::EffectDummy'), +(35745, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Socrethar\'s Stone', 'Spell::EffectDummy'), +(36032,-1, -1, -1, -1, -1, -1, -1, -1,-1,'', 'Spell::EffectSchoolDMG'), +(36837, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor', 'Spell::EffectSchoolDMG'), +(36902,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Transporter Malfunction', 'Spell::EffectDummy'), +(37169,-1, -1, -1, -1, -1, -1, 6, 4,-1,'Eviscerate and Envenom Bonus Damage','Spell::EffectSchoolDMG'), +(37674, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Chaos Blast', 'Spell::EffectDummy'), +(37675,-1, -1, -1, -1, -1, -1, 2, -1, 0,'Chaos Blast', 'Spell::EffectDummy'), +(38441, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Cataclysmic Bolt', 'Spell::EffectSchoolDMG'), +(38903, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor', 'Spell::EffectSchoolDMG'), +(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'), +(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'), +(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'), +(44875, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Complete Raptor Capture', 'Spell::EffectDummy'), +(44997, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Converting Sentry', 'Spell::EffectDummy'), +(45009,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Converted Sentry Credit', 'Spell::EffectDummy'), +(45030, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Impale Emissary', 'Spell::EffectDummy'), +(45088,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Emissary of Hate Credit', 'Spell::EffectDummy'), +(45150, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Meteor Slash', 'Spell::EffectSchoolDMG'), +(46014,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Knocked Up', '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'), +(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'), +(52308, 0, -1, -1, -1, -1, -1, 3, -1, 0,'Take Sputum Sample', 'Spell::EffectDummy'), +(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'), +(53341, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Rune of Cinderglacier', 'Spell::EffectDummy'), +(53343, 0, -1, -1, -1, -1, -1, 3, -1,-1,'Rune of Razorice', 'Spell::EffectDummy'), +(54586,-1, -1, -1, -1, -1, -1, -1, -1,-1,'Runeforging Credit', 'Spell::EffectDummy'), +(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'), +(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'), +(61491, 0, -1, -1, -1, -1, -1, 2, -1,-1,'Intercept', 'Spell::EffectSchoolDMG'), +/* 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,10,0x0000000000004000,0x00000000, -1, -1, -1, 2, -1,-1,'Avenger\'s Shield', 'Spell::EffectSchoolDMG'), +( 0, 0, -1, -1,1661, -1, -1, 3, -1,-1,'Berserking', 'Spell::EffectDummy'), +( 0, 4,0x0000040000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Bloodthirst', 'Spell::EffectSchoolDMG'), +( 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, 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, 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, 9, -1, -1,1578, -1, -1, 2, -1,-1,'Gore', 'Spell::EffectSchoolDMG'), +( 0, 8,0x0000000000000008,0x00000000, -1, -1, -1, 2, -1,-1,'Gouge', 'Spell::EffectSchoolDMG'), +( 0,10,0x0000008000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Hammer of Wrath', 'Spell::EffectSchoolDMG'), +( 0,10,0x0004000000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Hammer of the Righteous', 'Spell::EffectSchoolDMG'), +( 0, 4,0x0000000100000000,0x00000000, -1, -1, -1, 2, -1,-1,'Heroic Throw', '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,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, 7,0x0000044000000000,0x00000000, -1, -1, -1, -1, -1,-1,'Mangle (Cat) and Mangle (Bear)', 'Unit::HandleDummyAuraProc'), +( 0, 9,0x0000000000000002,0x00000000, -1, 342, -1, 2, -1,-1,'Mongoose Bite', 'Spell::EffectSchoolDMG'), +( 0, 7,0x0000000000001000,0x00000000, -1, -1, -1, 2, -1,-1,'Rake', 'Spell::EffectSchoolDMG'), /* used in */ +( 0, 7,0x0000000000001000,0x00000000, -1, -1, -1, 80, -1, 2,'Rake', 'Spell::EffectSchoolDMG'), /* exactly selected */ +( 0, 7,0x0000000000001000,0x00000000, -1, -1, -1, -1, 3,-1,'Rake', 'Aura::HandlePeriodicDamage'), /* used in */ +( 0, 7,0x0000000000001000,0x00000000, -1, -1, -1, 80, -1, 2,'Rake', 'Aura::HandlePeriodicDamage'), /* exactly selected */ +( 0, 4,0x0000000000000400,0x00000000, -1, -1, -1, 2, -1,-1,'Revenge', 'Spell::EffectSchoolDMG'), +( 0, 6,0x0000000200000000,0x00000000, -1, -1, -1, 2, -1,-1,'Shadow Word: Death', 'Spell::EffectSchoolDMG'), +( 0,10,0x0010000000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Shield of Righteousness', 'Spell::EffectSchoolDMG'), +( 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, 9,0x0000000100000000,0x00000000, -1, -1, -1, 2, -1,-1,'Steady Shot', 'Spell::EffectSchoolDMG'), +( 0, 7,0x0010000000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Swipe', 'Spell::EffectSchoolDMG'), +( 0, 4,0x0000000000000080,0x00000000, -1, -1, -1, 2, -1,-1,'Thunder Clap', 'Spell::EffectSchoolDMG'), +( 0, 4,0x0000010000000000,0x00000000, -1, -1, -1, 2, -1,-1,'Victory Rush', 'Spell::EffectSchoolDMG'), +( 0, 8,0x0000000010000000,0x00000000, -1, -1, -1, 2, -1,-1,'Wound Poison', 'Spell::EffectSchoolDMG'); diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index af7c914a9..122056050 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -148,18 +148,19 @@ ChatCommand * ChatHandler::getCommandTable() { "anim", SEC_GAMEMASTER, false, &ChatHandler::HandleDebugAnimCommand, "", NULL }, { "arena", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugArenaCommand, "", NULL }, { "bg", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugBattlegroundCommand, "", NULL }, - { "getitemstate", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugGetItemState, "", NULL }, - { "lootrecipient", SEC_GAMEMASTER, false, &ChatHandler::HandleDebugGetLootRecipient, "", NULL }, - { "getvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugGetValue, "", NULL }, - { "Mod32Value", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugMod32Value, "", NULL }, + { "getitemstate", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugGetItemStateCommand, "", NULL }, + { "lootrecipient", SEC_GAMEMASTER, false, &ChatHandler::HandleDebugGetLootRecipientCommand, "", NULL }, + { "getvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugGetValueCommand, "", NULL }, + { "Mod32Value", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugMod32ValueCommand, "", NULL }, { "play", SEC_MODERATOR, false, NULL, "", debugPlayCommandTable }, { "send", SEC_ADMINISTRATOR, false, NULL, "", debugSendCommandTable }, { "setaurastate", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetAuraStateCommand, "", NULL }, { "setitemflag", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetItemFlagCommand, "", NULL }, - { "setvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetValue, "", NULL }, + { "setvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetValueCommand, "", NULL }, + { "spellcheck", SEC_CONSOLE, true, &ChatHandler::HandleDebugSpellCheckCommand, "", NULL }, { "spawnvehicle", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSpawnVehicle, "", NULL }, { "uws", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugUpdateWorldStateCommand, "", NULL }, - { "update", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugUpdate, "", NULL }, + { "update", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugUpdateCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; @@ -566,7 +567,7 @@ ChatCommand * ChatHandler::getCommandTable() { "go", SEC_MODERATOR, false, NULL, "", goCommandTable }, { "learn", SEC_MODERATOR, false, NULL, "", learnCommandTable }, { "modify", SEC_MODERATOR, false, NULL, "", modifyCommandTable }, - { "debug", SEC_MODERATOR, false, NULL, "", debugCommandTable }, + { "debug", SEC_MODERATOR, true, NULL, "", debugCommandTable }, { "tele", SEC_MODERATOR, true, NULL, "", teleCommandTable }, { "character", SEC_GAMEMASTER, false, NULL, "", characterCommandTable}, { "event", SEC_GAMEMASTER, false, NULL, "", eventCommandTable }, @@ -1643,4 +1644,4 @@ LocaleConstant CliHandler::GetSessionDbcLocale() const int CliHandler::GetSessionDbLocaleIndex() const { return objmgr.GetDBCLocaleIndex(); -} +} \ No newline at end of file diff --git a/src/game/Chat.h b/src/game/Chat.h index cd235d4ee..fe6c8a8a4 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -128,15 +128,16 @@ class ChatHandler bool HandleDebugAnimCommand(const char* args); bool HandleDebugArenaCommand(const char * args); bool HandleDebugBattlegroundCommand(const char * args); - bool HandleDebugGetItemState(const char * args); - bool HandleDebugGetLootRecipient(const char * args); - bool HandleDebugGetValue(const char* args); - bool HandleDebugMod32Value(const char* args); + bool HandleDebugGetItemStateCommand(const char * args); + bool HandleDebugGetLootRecipientCommand(const char * args); + bool HandleDebugGetValueCommand(const char* args); + bool HandleDebugMod32ValueCommand(const char* args); bool HandleDebugSetAuraStateCommand(const char * args); bool HandleDebugSetItemFlagCommand(const char * args); - bool HandleDebugSetValue(const char* args); + bool HandleDebugSetValueCommand(const char* args); bool HandleDebugSpawnVehicle(const char * args); - bool HandleDebugUpdate(const char* args); + bool HandleDebugSpellCheckCommand(const char* args); + bool HandleDebugUpdateCommand(const char* args); bool HandleDebugUpdateWorldStateCommand(const char* args); bool HandleDebugPlayCinematicCommand(const char* args); diff --git a/src/game/Corpse.cpp b/src/game/Corpse.cpp index 4964d2ef2..3115a9473 100644 --- a/src/game/Corpse.cpp +++ b/src/game/Corpse.cpp @@ -72,12 +72,15 @@ bool Corpse::Create( uint32 guidlow ) bool Corpse::Create( uint32 guidlow, Player *owner) { - SetInstanceId(owner->GetInstanceId()); - - WorldObject::_Create(guidlow, HIGHGUID_CORPSE, owner->GetMapId(), owner->GetPhaseMask()); + ASSERT(owner); + WorldObject::_Create(guidlow, HIGHGUID_CORPSE, owner->GetPhaseMask()); Relocate(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), owner->GetOrientation()); + //we need to assign owner's map for corpse + //in other way we will get a crash in Corpse::SaveToDB() + SetMap(owner->GetMap()); + if(!IsPositionValid()) { sLog.outError("Corpse (guidlow %d, owner %s) not created. Suggested coordinates isn't valid (X: %f Y: %f)", @@ -207,8 +210,8 @@ bool Corpse::LoadFromDB(uint32 guid, Field *fields) SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_CORPSE)); // place - SetInstanceId(instanceid); - SetMapId(mapid); + SetLocationInstanceId(instanceid); + SetLocationMapId(mapid); SetPhaseMask(phaseMask, false); Relocate(positionX, positionY, positionZ, ort); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 98e500d8e..a49fe41ee 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -563,8 +563,8 @@ bool Creature::AIM_Initialize() bool Creature::Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 team, const CreatureData *data) { - SetMapId(map->GetId()); - SetInstanceId(map->GetInstanceId()); + ASSERT(map); + SetMap(map); SetPhaseMask(phaseMask,false); //oX = x; oY = y; dX = x; dY = y; m_moveTime = 0; m_startMove = 0; @@ -572,6 +572,12 @@ bool Creature::Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, if (bResult) { + //Notify the map's instance data. + //Only works if you create the object in it, not if it is moves to that map. + //Normally non-players do not teleport to other maps. + if(map->IsDungeon() && ((InstanceMap*)map)->GetInstanceData()) + ((InstanceMap*)map)->GetInstanceData()->OnCreatureCreate(this); + switch (GetCreatureInfo()->rank) { case CREATURE_ELITE_RARE: @@ -1312,15 +1318,6 @@ bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, uint32 team, const if(!UpdateEntry(Entry, team, data)) return false; - //Notify the map's instance data. - //Only works if you create the object in it, not if it is moves to that map. - //Normally non-players do not teleport to other maps. - Map *map = MapManager::Instance().FindMap(GetMapId(), GetInstanceId()); - if(map && map->IsDungeon() && ((InstanceMap*)map)->GetInstanceData()) - { - ((InstanceMap*)map)->GetInstanceData()->OnCreatureCreate(this); - } - return true; } diff --git a/src/game/DynamicObject.cpp b/src/game/DynamicObject.cpp index 38310b638..df5e6a7d3 100644 --- a/src/game/DynamicObject.cpp +++ b/src/game/DynamicObject.cpp @@ -56,9 +56,8 @@ void DynamicObject::RemoveFromWorld() bool DynamicObject::Create( uint32 guidlow, Unit *caster, uint32 spellId, uint32 effIndex, float x, float y, float z, int32 duration, float radius ) { - SetInstanceId(caster->GetInstanceId()); - - WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetMapId(), caster->GetPhaseMask()); + WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetPhaseMask()); + SetMap(caster->GetMap()); Relocate(x, y, z, 0); if(!IsPositionValid()) diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index d2d1478cc..37e5b55d3 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -87,7 +87,7 @@ void GameObject::CleanupsBeforeDelete() ownerType = "pet"; sLog.outError("Delete GameObject (GUID: %u Entry: %u SpellId %u LinkedGO %u) that lost references to owner (GUID %u Type '%s') GO list. Crash possible later.", - GetGUIDLow(), GetGOInfo()->id, m_spellId, GetLinkedGameObjectEntry(), GUID_LOPART(owner_guid), ownerType); + GetGUIDLow(), GetGOInfo()->id, m_spellId, GetGOInfo()->GetLinkedGameObjectEntry(), GUID_LOPART(owner_guid), ownerType); } } } @@ -109,9 +109,9 @@ void GameObject::RemoveFromWorld() bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state) { + ASSERT(map); Relocate(x,y,z,ang); - SetMapId(map->GetId()); - SetInstanceId(map->GetInstanceId()); + SetMap(map); SetPhaseMask(phaseMask,false); if(!IsPositionValid()) @@ -383,7 +383,7 @@ void GameObject::Update(uint32 /*p_time*/) { case GAMEOBJECT_TYPE_DOOR: case GAMEOBJECT_TYPE_BUTTON: - if (GetAutoCloseTime() && (m_cooldownTime < time(NULL))) + if (GetGOInfo()->GetAutoCloseTime() && (m_cooldownTime < time(NULL))) ResetDoorOrButton(); break; } @@ -423,7 +423,7 @@ void GameObject::Update(uint32 /*p_time*/) } //burning flags in some battlegrounds, if you find better condition, just add it - if (GetGoAnimProgress() > 0) + if (GetGOInfo()->IsDespawnAtAction() || GetGoAnimProgress() > 0) { SendObjectDeSpawnAnim(GetGUID()); //reset flags @@ -601,7 +601,7 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map) if (!Create(guid,entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state) ) return false; - if(!GetDespawnPossibility()) + if(!GetGOInfo()->GetDespawnPossibility() && !GetGOInfo()->IsDespawnAtAction()) { SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN); m_spawnedByDefault = true; @@ -647,22 +647,6 @@ GameObjectInfo const *GameObject::GetGOInfo() const return m_goInfo; } -uint32 GameObject::GetLootId(GameObjectInfo const* ginfo) -{ - if (!ginfo) - return 0; - - switch(ginfo->type) - { - case GAMEOBJECT_TYPE_CHEST: - return ginfo->chest.lootId; - case GAMEOBJECT_TYPE_FISHINGHOLE: - return ginfo->fishinghole.lootId; - default: - return 0; - } -} - /*********************************************************/ /*** QUEST SYSTEM ***/ /*********************************************************/ @@ -757,7 +741,7 @@ bool GameObject::ActivateToQuest( Player *pTarget)const // scan GO chest with loot including quest items case GAMEOBJECT_TYPE_CHEST: { - if(LootTemplates_Gameobject.HaveQuestLootForPlayer(GetLootId(), pTarget)) + if(LootTemplates_Gameobject.HaveQuestLootForPlayer(GetGOInfo()->GetLootId(), pTarget)) return true; break; } @@ -842,7 +826,7 @@ void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = f return; if(!time_to_restore) - time_to_restore = GetAutoCloseTime(); + time_to_restore = GetGOInfo()->GetAutoCloseTime(); SwitchDoorOrButton(true,alternative); SetLootState(GO_ACTIVATED); @@ -1294,7 +1278,7 @@ void GameObject::Use(Unit* user) return; } - Spell *spell = new Spell(spellCaster, spellInfo, triggered); + Spell *spell = new Spell(spellCaster, spellInfo, triggered,GetGUID()); // spell target is user of GO SpellCastTargets targets; diff --git a/src/game/GameObject.h b/src/game/GameObject.h index a15d4a848..911160017 100644 --- a/src/game/GameObject.h +++ b/src/game/GameObject.h @@ -397,6 +397,87 @@ struct GameObjectInfo } raw; }; uint32 ScriptId; + + // helpers + bool IsDespawnAtAction() const + { + switch(type) + { + case GAMEOBJECT_TYPE_CHEST: return chest.consumable; + case GAMEOBJECT_TYPE_GOOBER: return goober.consumable; + default: return false; + } + } + + uint32 GetLockId() const + { + switch(type) + { + case GAMEOBJECT_TYPE_DOOR: return door.lockId; + case GAMEOBJECT_TYPE_BUTTON: return button.lockId; + case GAMEOBJECT_TYPE_QUESTGIVER: return questgiver.lockId; + case GAMEOBJECT_TYPE_CHEST: return chest.lockId; + case GAMEOBJECT_TYPE_TRAP: return trap.lockId; + case GAMEOBJECT_TYPE_GOOBER: return goober.lockId; + case GAMEOBJECT_TYPE_AREADAMAGE: return areadamage.lockId; + case GAMEOBJECT_TYPE_CAMERA: return camera.lockId; + case GAMEOBJECT_TYPE_FLAGSTAND: return flagstand.lockId; + case GAMEOBJECT_TYPE_FISHINGHOLE:return fishinghole.lockId; + case GAMEOBJECT_TYPE_FLAGDROP: return flagdrop.lockId; + default: return 0; + } + } + + bool GetDespawnPossibility() const // despawn at targeting of cast? + { + switch(type) + { + case GAMEOBJECT_TYPE_DOOR: return door.noDamageImmune; + case GAMEOBJECT_TYPE_BUTTON: return button.noDamageImmune; + case GAMEOBJECT_TYPE_QUESTGIVER: return questgiver.noDamageImmune; + case GAMEOBJECT_TYPE_GOOBER: return goober.noDamageImmune; + case GAMEOBJECT_TYPE_FLAGSTAND: return flagstand.noDamageImmune; + case GAMEOBJECT_TYPE_FLAGDROP: return flagdrop.noDamageImmune; + default: return true; + } + } + + uint32 GetLinkedGameObjectEntry() const + { + switch(type) + { + case GAMEOBJECT_TYPE_CHEST: return chest.linkedTrapId; + case GAMEOBJECT_TYPE_SPELL_FOCUS: return spellFocus.linkedTrapId; + case GAMEOBJECT_TYPE_GOOBER: return goober.linkedTrapId; + default: return 0; + } + } + + uint32 GetAutoCloseTime() const + { + uint32 autoCloseTime = 0; + switch(type) + { + case GAMEOBJECT_TYPE_DOOR: autoCloseTime = door.autoCloseTime; break; + case GAMEOBJECT_TYPE_BUTTON: autoCloseTime = button.autoCloseTime; break; + case GAMEOBJECT_TYPE_TRAP: autoCloseTime = trap.autoCloseTime; break; + case GAMEOBJECT_TYPE_GOOBER: autoCloseTime = goober.autoCloseTime; break; + case GAMEOBJECT_TYPE_TRANSPORT: autoCloseTime = transport.autoCloseTime; break; + case GAMEOBJECT_TYPE_AREADAMAGE: autoCloseTime = areadamage.autoCloseTime; break; + default: break; + } + return autoCloseTime / 0x10000; + } + + uint32 GetLootId() const + { + switch(type) + { + case GAMEOBJECT_TYPE_CHEST: return chest.lootId; + case GAMEOBJECT_TYPE_FISHINGHOLE: return fishinghole.lootId; + default: return 0; + } + } }; // GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform @@ -500,40 +581,6 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask); bool LoadFromDB(uint32 guid, Map *map); void DeleteFromDB(); - static uint32 GetLootId(GameObjectInfo const* info); - uint32 GetLootId() const { return GetLootId(GetGOInfo()); } - uint32 GetLockId() const - { - switch(GetGoType()) - { - case GAMEOBJECT_TYPE_DOOR: return GetGOInfo()->door.lockId; - case GAMEOBJECT_TYPE_BUTTON: return GetGOInfo()->button.lockId; - case GAMEOBJECT_TYPE_QUESTGIVER: return GetGOInfo()->questgiver.lockId; - case GAMEOBJECT_TYPE_CHEST: return GetGOInfo()->chest.lockId; - case GAMEOBJECT_TYPE_TRAP: return GetGOInfo()->trap.lockId; - case GAMEOBJECT_TYPE_GOOBER: return GetGOInfo()->goober.lockId; - case GAMEOBJECT_TYPE_AREADAMAGE: return GetGOInfo()->areadamage.lockId; - case GAMEOBJECT_TYPE_CAMERA: return GetGOInfo()->camera.lockId; - case GAMEOBJECT_TYPE_FLAGSTAND: return GetGOInfo()->flagstand.lockId; - case GAMEOBJECT_TYPE_FISHINGHOLE:return GetGOInfo()->fishinghole.lockId; - case GAMEOBJECT_TYPE_FLAGDROP: return GetGOInfo()->flagdrop.lockId; - default: return 0; - } - } - - bool GetDespawnPossibility() const - { - switch(GetGoType()) - { - case GAMEOBJECT_TYPE_DOOR: return GetGOInfo()->door.noDamageImmune; - case GAMEOBJECT_TYPE_BUTTON: return GetGOInfo()->button.noDamageImmune; - case GAMEOBJECT_TYPE_QUESTGIVER: return GetGOInfo()->questgiver.noDamageImmune; - case GAMEOBJECT_TYPE_GOOBER: return GetGOInfo()->goober.noDamageImmune; - case GAMEOBJECT_TYPE_FLAGSTAND: return GetGOInfo()->flagstand.noDamageImmune; - case GAMEOBJECT_TYPE_FLAGDROP: return GetGOInfo()->flagdrop.noDamageImmune; - default: return true; - } - } time_t GetRespawnTime() const { return m_respawnTime; } time_t GetRespawnTimeEx() const @@ -603,34 +650,7 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject void UseDoorOrButton(uint32 time_to_restore = 0, bool alternative = false); // 0 = use `gameobject`.`spawntimesecs` void ResetDoorOrButton(); - // 0 = use `gameobject`.`spawntimesecs` - uint32 GetLinkedGameObjectEntry() const - { - switch(GetGoType()) - { - case GAMEOBJECT_TYPE_CHEST: return GetGOInfo()->chest.linkedTrapId; - case GAMEOBJECT_TYPE_SPELL_FOCUS: return GetGOInfo()->spellFocus.linkedTrapId; - case GAMEOBJECT_TYPE_GOOBER: return GetGOInfo()->goober.linkedTrapId; - default: return 0; - } - } - - uint32 GetAutoCloseTime() const - { - uint32 autoCloseTime = 0; - switch(GetGoType()) - { - case GAMEOBJECT_TYPE_DOOR: autoCloseTime = GetGOInfo()->door.autoCloseTime; break; - case GAMEOBJECT_TYPE_BUTTON: autoCloseTime = GetGOInfo()->button.autoCloseTime; break; - case GAMEOBJECT_TYPE_TRAP: autoCloseTime = GetGOInfo()->trap.autoCloseTime; break; - case GAMEOBJECT_TYPE_GOOBER: autoCloseTime = GetGOInfo()->goober.autoCloseTime; break; - case GAMEOBJECT_TYPE_TRANSPORT: autoCloseTime = GetGOInfo()->transport.autoCloseTime; break; - case GAMEOBJECT_TYPE_AREADAMAGE: autoCloseTime = GetGOInfo()->areadamage.autoCloseTime; break; - default: break; - } - return autoCloseTime / 0x10000; - } void TriggeringLinkedGameObject( uint32 trapEntry, Unit* target); diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 98cbe805f..0c0eca58f 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -3171,7 +3171,7 @@ bool ChatHandler::HandleLookupTaxiNodeCommand(const char * args) } } if (counter == 0) // if counter == 0 then we found nth - SendSysMessage(LANG_COMMAND_NOSPELLFOUND); + SendSysMessage(LANG_COMMAND_NOTAXINODEFOUND); return true; } @@ -4085,57 +4085,6 @@ bool ChatHandler::HandleHideAreaCommand(const char* args) return true; } -bool ChatHandler::HandleDebugUpdate(const char* args) -{ - if(!*args) - return false; - - uint32 updateIndex; - uint32 value; - - char* pUpdateIndex = strtok((char*)args, " "); - - Unit* chr = getSelectedUnit(); - if (chr == NULL) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if(!pUpdateIndex) - { - return true; - } - updateIndex = atoi(pUpdateIndex); - //check updateIndex - if(chr->GetTypeId() == TYPEID_PLAYER) - { - if (updateIndex>=PLAYER_END) return true; - } - else - { - if (updateIndex>=UNIT_END) return true; - } - - char* pvalue = strtok(NULL, " "); - if (!pvalue) - { - value=chr->GetUInt32Value(updateIndex); - - PSendSysMessage(LANG_UPDATE, chr->GetGUIDLow(),updateIndex,value); - return true; - } - - value=atoi(pvalue); - - PSendSysMessage(LANG_UPDATE_CHANGE, chr->GetGUIDLow(),updateIndex,value); - - chr->SetUInt32Value(updateIndex,value); - - return true; -} - bool ChatHandler::HandleBankCommand(const char* /*args*/) { m_session->SendShowBank( m_session->GetPlayer()->GetGUID() ); @@ -4185,106 +4134,6 @@ bool ChatHandler::HandleChangeWeather(const char* args) return true; } -bool ChatHandler::HandleDebugSetValue(const char* args) -{ - if(!*args) - return false; - - char* px = strtok((char*)args, " "); - char* py = strtok(NULL, " "); - char* pz = strtok(NULL, " "); - - if (!px || !py) - return false; - - Unit* target = getSelectedUnit(); - if(!target) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - uint64 guid = target->GetGUID(); - - uint32 Opcode = (uint32)atoi(px); - if(Opcode >= target->GetValuesCount()) - { - PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, GUID_LOPART(guid), target->GetValuesCount()); - return false; - } - uint32 iValue; - float fValue; - bool isint32 = true; - if(pz) - isint32 = (bool)atoi(pz); - if(isint32) - { - iValue = (uint32)atoi(py); - sLog.outDebug(GetMangosString(LANG_SET_UINT), GUID_LOPART(guid), Opcode, iValue); - target->SetUInt32Value( Opcode , iValue ); - PSendSysMessage(LANG_SET_UINT_FIELD, GUID_LOPART(guid), Opcode,iValue); - } - else - { - fValue = (float)atof(py); - sLog.outDebug(GetMangosString(LANG_SET_FLOAT), GUID_LOPART(guid), Opcode, fValue); - target->SetFloatValue( Opcode , fValue ); - PSendSysMessage(LANG_SET_FLOAT_FIELD, GUID_LOPART(guid), Opcode,fValue); - } - - return true; -} - -bool ChatHandler::HandleDebugGetValue(const char* args) -{ - if(!*args) - return false; - - char* px = strtok((char*)args, " "); - char* pz = strtok(NULL, " "); - - if (!px) - return false; - - Unit* target = getSelectedUnit(); - if(!target) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - uint64 guid = target->GetGUID(); - - uint32 Opcode = (uint32)atoi(px); - if(Opcode >= target->GetValuesCount()) - { - PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, GUID_LOPART(guid), target->GetValuesCount()); - return false; - } - uint32 iValue; - float fValue; - bool isint32 = true; - if(pz) - isint32 = (bool)atoi(pz); - - if(isint32) - { - iValue = target->GetUInt32Value( Opcode ); - sLog.outDebug(GetMangosString(LANG_GET_UINT), GUID_LOPART(guid), Opcode, iValue); - PSendSysMessage(LANG_GET_UINT_FIELD, GUID_LOPART(guid), Opcode, iValue); - } - else - { - fValue = target->GetFloatValue( Opcode ); - sLog.outDebug(GetMangosString(LANG_GET_FLOAT), GUID_LOPART(guid), Opcode, fValue); - PSendSysMessage(LANG_GET_FLOAT_FIELD, GUID_LOPART(guid), Opcode, fValue); - } - - return true; -} - bool ChatHandler::HandleSet32Bit(const char* args) { if(!*args) @@ -4309,38 +4158,6 @@ bool ChatHandler::HandleSet32Bit(const char* args) return true; } -bool ChatHandler::HandleDebugMod32Value(const char* args) -{ - if(!*args) - return false; - - char* px = strtok((char*)args, " "); - char* py = strtok(NULL, " "); - - if (!px || !py) - return false; - - uint32 Opcode = (uint32)atoi(px); - int Value = atoi(py); - - if(Opcode >= m_session->GetPlayer()->GetValuesCount()) - { - PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, m_session->GetPlayer()->GetGUIDLow(), m_session->GetPlayer( )->GetValuesCount()); - return false; - } - - sLog.outDebug(GetMangosString(LANG_CHANGE_32BIT), Opcode, Value); - - int CurrentValue = (int)m_session->GetPlayer( )->GetUInt32Value( Opcode ); - - CurrentValue += Value; - m_session->GetPlayer( )->SetUInt32Value( Opcode , (uint32)CurrentValue ); - - PSendSysMessage(LANG_CHANGE_32BIT_FIELD, Opcode,CurrentValue); - - return true; -} - bool ChatHandler::HandleTeleAddCommand(const char * args) { if(!*args) diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp index c70b4454e..0f4798471 100644 --- a/src/game/LootMgr.cpp +++ b/src/game/LootMgr.cpp @@ -1149,7 +1149,7 @@ void LoadLootTemplates_Gameobject() { if(GameObjectInfo const* gInfo = sGOStorage.LookupEntry(i)) { - if(uint32 lootid = GameObject::GetLootId(gInfo)) + if(uint32 lootid = gInfo->GetLootId()) { if(!ids_set.count(lootid)) LootTemplates_Gameobject.ReportNotExistedId(lootid); diff --git a/src/game/Map.cpp b/src/game/Map.cpp index b3c6b542b..acbbee140 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -124,14 +124,12 @@ void Map::LoadMap(int gx,int gy, bool reload) if(GridMaps[gx][gy]) return; - Map* baseMap = const_cast(MapManager::Instance().CreateBaseMap(i_id)); - // load grid map for base map - if (!baseMap->GridMaps[gx][gy]) - baseMap->EnsureGridCreated(GridPair(63-gx,63-gy)); + if (!m_parentMap->GridMaps[gx][gy]) + m_parentMap->EnsureGridCreated(GridPair(63-gx,63-gy)); - ((MapInstanced*)(baseMap))->AddGridMapReference(GridPair(gx,gy)); - GridMaps[gx][gy] = baseMap->GridMaps[gx][gy]; + ((MapInstanced*)(m_parentMap))->AddGridMapReference(GridPair(gx,gy)); + GridMaps[gx][gy] = m_parentMap->GridMaps[gx][gy]; return; } @@ -184,11 +182,11 @@ void Map::DeleteStateMachine() delete si_GridStates[GRID_STATE_REMOVAL]; } -Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode) +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_activeNonPlayersIter(m_activeNonPlayers.end()), - i_gridExpiry(expiry) + i_gridExpiry(expiry), m_parentMap(_parent ? _parent : this) { for(unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx) { @@ -295,6 +293,13 @@ void Map::DeleteFromWorld(T* obj) delete obj; } +template<> +void Map::DeleteFromWorld(Player* pl) +{ + ObjectAccessor::Instance().RemoveObject(pl); + delete pl; +} + template void Map::AddNotifier(T* , Cell const& , CellPair const& ) { @@ -399,8 +404,7 @@ void Map::LoadGrid(const Cell& cell, bool no_unload) bool Map::Add(Player *player) { player->GetMapRef().link(this, player); - - player->SetInstanceId(GetInstanceId()); + player->SetMap(this); // update player state for other player and visa-versa CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); @@ -431,6 +435,8 @@ Map::Add(T *obj) return; } + obj->SetMap(this); + Cell cell(p); if(obj->isActiveObject()) EnsureGridLoadedAtEnter(cell); @@ -688,8 +694,12 @@ void Map::Remove(Player *player, bool remove) CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) { + if(remove) + player->CleanupsBeforeDelete(); + // invalid coordinates player->RemoveFromWorld(); + player->ResetMap(); if( remove ) DeleteFromWorld(player); @@ -709,13 +719,16 @@ void Map::Remove(Player *player, bool remove) NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); assert(grid != NULL); + if(remove) + player->CleanupsBeforeDelete(); + player->RemoveFromWorld(); RemoveFromGrid(player,grid,cell); SendRemoveTransports(player); - UpdateObjectsVisibilityFor(player,cell,p); + player->ResetMap(); if( remove ) DeleteFromWorld(player); } @@ -760,6 +773,7 @@ Map::Remove(T *obj, bool remove) UpdateObjectVisibility(obj,cell,p); + obj->ResetMap(); if( remove ) { // if option set then object already saved at this moment @@ -1029,7 +1043,8 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce) VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gy, gx); } else - ((MapInstanced*)(MapManager::Instance().CreateBaseMap(i_id)))->RemoveGridMapReference(GridPair(gx, gy)); + ((MapInstanced*)m_parentMap)->RemoveGridMapReference(GridPair(gx, gy)); + GridMaps[gx][gy] = NULL; } DEBUG_LOG("Unloading grid[%u,%u] for map %u finished", x,y, i_id); @@ -2196,8 +2211,8 @@ template void Map::Remove(DynamicObject *, bool); /* ******* Dungeon Instance Maps ******* */ -InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode) - : Map(id, expiry, InstanceId, SpawnMode), +InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent) + : Map(id, expiry, InstanceId, SpawnMode, _parent), m_resetAfterUnload(false), m_unloadWhenEmpty(false), i_data(NULL), i_script_id(0) { @@ -2534,8 +2549,8 @@ uint32 InstanceMap::GetMaxPlayers() const /* ******* Battleground Instance Maps ******* */ -BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId) - : Map(id, expiry, InstanceId, DUNGEON_DIFFICULTY_NORMAL) +BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId, Map* _parent) + : Map(id, expiry, InstanceId, DUNGEON_DIFFICULTY_NORMAL, _parent) { } diff --git a/src/game/Map.h b/src/game/Map.h index faefcfa5b..4a6c9bde5 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -245,7 +245,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj { friend class MapReference; public: - Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode); + Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent = NULL); virtual ~Map(); // currently unused for normal maps @@ -300,6 +300,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj static void InitStateMachine(); static void DeleteStateMachine(); + Map const * GetParent() const { return m_parentMap; } + // some calls like isInWater should not use vmaps due to processor power // can return INVALID_HEIGHT if under z+2 z coord not found height float GetHeight(float x, float y, float z, bool pCheckVMap=true) const; @@ -461,6 +463,10 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj ActiveNonPlayers m_activeNonPlayers; ActiveNonPlayers::iterator m_activeNonPlayersIter; private: + //used for fast base_map (e.g. MapInstanced class object) search for + //InstanceMaps and BattleGroundMaps... + Map* m_parentMap; + typedef GridReadGuard ReadGuard; typedef GridWriteGuard WriteGuard; @@ -520,7 +526,7 @@ enum InstanceResetMethod class MANGOS_DLL_SPEC InstanceMap : public Map { public: - InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode); + InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent); ~InstanceMap(); bool Add(Player *); void Remove(Player *, bool); @@ -545,7 +551,7 @@ class MANGOS_DLL_SPEC InstanceMap : public Map class MANGOS_DLL_SPEC BattleGroundMap : public Map { public: - BattleGroundMap(uint32 id, time_t, uint32 InstanceId); + BattleGroundMap(uint32 id, time_t, uint32 InstanceId, Map* _parent); ~BattleGroundMap(); bool Add(Player *); diff --git a/src/game/MapInstanced.cpp b/src/game/MapInstanced.cpp index 43fc398f7..b9bd53114 100644 --- a/src/game/MapInstanced.cpp +++ b/src/game/MapInstanced.cpp @@ -108,84 +108,59 @@ void MapInstanced::UnloadAll(bool pForce) - create the instance if it's not created already - the player is not actually added to the instance (only in InstanceMap::Add) */ -Map* MapInstanced::GetInstance(const WorldObject* obj) +Map* MapInstanced::CreateInstance(const uint32 mapId, Player * player) { - uint32 CurInstanceId = obj->GetInstanceId(); - Map* map = NULL; + if(GetId() != mapId || !player) + return NULL; - if (obj->GetMapId() == GetId() && CurInstanceId != 0) + Map* map = NULL; + uint32 NewInstanceId = 0; // instanceId of the resulting map + + if(IsBattleGroundOrArena()) { - // the object wants to be put in a certain instance of this map - map = _FindMap(CurInstanceId); + // instantiate or find existing bg map for player + // the instance id is set in battlegroundid + NewInstanceId = player->GetBattleGroundId(); + ASSERT(NewInstanceId); + map = _FindMap(NewInstanceId); if(!map) - { - // For players if the instanceId is set, it's assumed they are already in a map, - // hence the map must be loaded. For Creatures, GameObjects etc the map must exist - // prior to calling GetMap, they are not allowed to create maps for themselves. - sLog.outError("GetInstance: object %s(%d), typeId %d, in world %d, should be in map %d,%d but that's not loaded yet.", obj->GetName(), obj->GetGUIDLow(), obj->GetTypeId(), obj->IsInWorld(), obj->GetMapId(), obj->GetInstanceId()); - assert(false); - } - return(map); + map = CreateBattleGround(NewInstanceId); } else { - // instance not specified, find an existing or create a new one - if(obj->GetTypeId() != TYPEID_PLAYER) + InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDungeonDifficulty()); + InstanceSave *pSave = pBind ? pBind->save : NULL; + + // the player's permanent player bind is taken into consideration first + // then the player's group bind and finally the solo bind. + if(!pBind || !pBind->perm) { - sLog.outError("MAPINSTANCED: WorldObject '%u' (Entry: %u TypeID: %u) is in map %d,%d and requested base map instance of map %d, this must not happen", obj->GetGUIDLow(), obj->GetEntry(), obj->GetTypeId(), obj->GetMapId(), obj->GetInstanceId(), GetId()); - assert(false); - return NULL; + InstanceGroupBind *groupBind = NULL; + Group *group = player->GetGroup(); + // use the player's difficulty setting (it may not be the same as the group's) + if(group && (groupBind = group->GetBoundInstance(GetId(), player->GetDungeonDifficulty()))) + pSave = groupBind->save; + } + + if(pSave) + { + // solo/perm/group + NewInstanceId = pSave->GetInstanceId(); + map = _FindMap(NewInstanceId); + // it is possible that the save exists but the map doesn't + if(!map) + map = CreateInstance(NewInstanceId, pSave, pSave->GetDifficulty()); } else { - uint32 NewInstanceId = 0; // instanceId of the resulting map - Player* player = (Player*)obj; - - if(IsBattleGroundOrArena()) - { - // instantiate or find existing bg map for player - // the instance id is set in battlegroundid - NewInstanceId = player->GetBattleGroundId(); - assert(NewInstanceId); - map = _FindMap(NewInstanceId); - if(!map) - map = CreateBattleGround(NewInstanceId); - return map; - } - - InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDungeonDifficulty()); - InstanceSave *pSave = pBind ? pBind->save : NULL; - - // the player's permanet player bind is taken into consideration first - // then the player's group bind and finally the solo bind. - if(!pBind || !pBind->perm) - { - InstanceGroupBind *groupBind = NULL; - Group *group = player->GetGroup(); - // use the player's difficulty setting (it may not be the same as the group's) - if(group && (groupBind = group->GetBoundInstance(GetId(), player->GetDungeonDifficulty()))) - pSave = groupBind->save; - } - - if(pSave) - { - // solo/perm/group - NewInstanceId = pSave->GetInstanceId(); - map = _FindMap(NewInstanceId); - // it is possible that the save exists but the map doesn't - if(!map) - map = CreateInstance(NewInstanceId, pSave, pSave->GetDifficulty()); - return map; - } - else - { - // if no instanceId via group members or instance saves is found - // the instance will be created for the first time - NewInstanceId = MapManager::Instance().GenerateInstanceId(); - return CreateInstance(NewInstanceId, NULL, player->GetDungeonDifficulty()); - } + // if no instanceId via group members or instance saves is found + // the instance will be created for the first time + NewInstanceId = MapManager::Instance().GenerateInstanceId(); + map = CreateInstance(NewInstanceId, NULL, player->GetDungeonDifficulty()); } } + + return map; } InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave *save, uint8 difficulty) @@ -210,10 +185,10 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave *save, // some instances only have one difficulty if (entry && !entry->SupportsHeroicMode()) difficulty = DUNGEON_DIFFICULTY_NORMAL; - sLog.outDebug("MapInstanced::CreateInstance: %smap instance %d for %d created with difficulty %s", save?"":"new ", InstanceId, GetId(), difficulty?"heroic":"normal"); + sLog.outDebug("MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %s", save?"":"new ", InstanceId, GetId(), difficulty?"heroic":"normal"); - InstanceMap *map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty); - assert(map->IsDungeon()); + InstanceMap *map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this); + ASSERT(map->IsDungeon()); bool load_data = save != NULL; map->CreateInstanceData(load_data); @@ -229,8 +204,8 @@ BattleGroundMap* MapInstanced::CreateBattleGround(uint32 InstanceId) sLog.outDebug("MapInstanced::CreateBattleGround: map bg %d for %d created.", InstanceId, GetId()); - BattleGroundMap *map = new BattleGroundMap(GetId(), GetGridExpiry(), InstanceId); - assert(map->IsBattleGroundOrArena()); + BattleGroundMap *map = new BattleGroundMap(GetId(), GetGridExpiry(), InstanceId, this); + ASSERT(map->IsBattleGroundOrArena()); m_InstancedMaps[InstanceId] = map; return map; diff --git a/src/game/MapInstanced.h b/src/game/MapInstanced.h index 8a6cfdb9f..67c57b98d 100644 --- a/src/game/MapInstanced.h +++ b/src/game/MapInstanced.h @@ -38,7 +38,7 @@ class MANGOS_DLL_DECL MapInstanced : public Map bool RemoveBones(uint64 guid, float x, float y); void UnloadAll(bool pForce); - Map* GetInstance(const WorldObject* obj); + Map* CreateInstance(const uint32 mapId, Player * player); Map* FindMap(uint32 InstanceId) const { return _FindMap(InstanceId); } void DestroyInstance(uint32 InstanceId); void DestroyInstance(InstancedMaps::iterator &itr); diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp index 314e44527..57b9dd1dc 100644 --- a/src/game/MapManager.cpp +++ b/src/game/MapManager.cpp @@ -122,13 +122,13 @@ MapManager::_createBaseMap(uint32 id) return m; } -Map* MapManager::GetMap(uint32 id, const WorldObject* obj) +Map* MapManager::CreateMap(uint32 id, const WorldObject* obj) { ASSERT(obj); //if(!obj->IsInWorld()) sLog.outError("GetMap: called for map %d with object (typeid %d, guid %d, mapid %d, instanceid %d) who is not in world!", id, obj->GetTypeId(), obj->GetGUIDLow(), obj->GetMapId(), obj->GetInstanceId()); Map *m = _createBaseMap(id); - if (m && obj && m->Instanceable()) m = ((MapInstanced*)m)->GetInstance(obj); + if (m && (obj->GetTypeId() == TYPEID_PLAYER) && m->Instanceable()) m = ((MapInstanced*)m)->CreateInstance(id, (Player*)obj); return m; } diff --git a/src/game/MapManager.h b/src/game/MapManager.h index 8755a3f45..f88e62a36 100644 --- a/src/game/MapManager.h +++ b/src/game/MapManager.h @@ -37,7 +37,7 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton(this)->_createBaseMap(id); } Map* FindMap(uint32 mapid, uint32 instanceId = 0) const; diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 7e80aa8e4..f71683e5b 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -65,18 +65,17 @@ void WorldSession::HandleMoveWorldportAckOpcode() GetPlayer()->SetSemaphoreTeleportFar(false); // relocate the player to the teleport destination - GetPlayer()->SetMapId(loc.mapid); + GetPlayer()->SetMap(MapManager::Instance().CreateMap(loc.mapid, GetPlayer())); GetPlayer()->Relocate(loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation); GetPlayer()->Relocate(loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation); - // since the MapId is set before the GetInstance call, the InstanceId must be set to 0 - // to let GetInstance() determine the proper InstanceId based on the player's binds - GetPlayer()->SetInstanceId(0); - GetPlayer()->SendInitialPacketsBeforeAddToMap(); // the CanEnter checks are done in TeleporTo but conditions may change // while the player is in transit, for example the map may get full if(!GetPlayer()->GetMap()->Add(GetPlayer())) { + //if player wasn't added to map, reset his map pointer! + GetPlayer()->ResetMap(); + sLog.outDebug("WORLD: teleport of player %s (%d) to location %d, %f, %f, %f, %f failed", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation); // teleport the player home if(!GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation())) diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 6ba4a8d36..d2ba5a8c0 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1056,7 +1056,7 @@ bool Object::PrintIndexError(uint32 index, bool set) const 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_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f), m_currMap(NULL) { } @@ -1064,11 +1064,9 @@ void WorldObject::CleanupsBeforeDelete() { } -void WorldObject::_Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid, uint32 phaseMask ) +void WorldObject::_Create( uint32 guidlow, HighGuid guidhigh, uint32 phaseMask ) { Object::_Create(guidlow, 0, guidhigh); - - m_mapId = mapid; m_phaseMask = phaseMask; } @@ -1545,14 +1543,19 @@ void WorldObject::SendObjectDeSpawnAnim(uint64 guid) SendMessageToSet(&data, true); } -Map* WorldObject::GetMap() const +void WorldObject::SetMap(Map * map) { - return MapManager::Instance().GetMap(GetMapId(), this); + ASSERT(map); + m_currMap = map; + //lets save current map's Id/instanceId + m_mapId = map->GetId(); + m_InstanceId = map->GetInstanceId(); } Map const* WorldObject::GetBaseMap() const { - return MapManager::Instance().CreateBaseMap(GetMapId()); + ASSERT(m_currMap); + return m_currMap->GetParent(); } void WorldObject::AddObjectToRemoveList() @@ -1564,7 +1567,6 @@ Creature* WorldObject::SummonCreature(uint32 id, float x, float y, float z, floa { TemporarySummon* pCreature = new TemporarySummon(GetGUID()); - pCreature->SetInstanceId(GetInstanceId()); uint32 team = 0; if (GetTypeId()==TYPEID_PLAYER) team = ((Player*)this)->GetTeam(); diff --git a/src/game/Object.h b/src/game/Object.h index d37451428..1a697fe1d 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -346,7 +346,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object virtual void Update ( uint32 /*time_diff*/ ) { } - void _Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid, uint32 phaseMask); + void _Create( uint32 guidlow, HighGuid guidhigh, uint32 phaseMask); void Relocate(float x, float y, float z, float orientation) { @@ -395,8 +395,8 @@ class MANGOS_DLL_SPEC WorldObject : public Object void GetRandomPoint( float x, float y, float z, float distance, float &rand_x, float &rand_y, float &rand_z ) const; - void SetMapId(uint32 newMap) { m_mapId = newMap; } uint32 GetMapId() const { return m_mapId; } + uint32 GetInstanceId() const { return m_InstanceId; } virtual void SetPhaseMask(uint32 newPhaseMask, bool update); uint32 GetPhaseMask() const { return m_phaseMask; } @@ -421,8 +421,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object float GetDistanceZ(const WorldObject* obj) const; bool IsInMap(const WorldObject* obj) const { - return IsInWorld() && obj->IsInWorld() && GetMapId()==obj->GetMapId() && - GetInstanceId()==obj->GetInstanceId() && InSamePhase(obj); + return IsInWorld() && obj->IsInWorld() && (GetMap() == obj->GetMap()) && InSamePhase(obj); } bool IsWithinDist3d(float x, float y, float z, float dist2compare) const; bool IsWithinDist2d(float x, float y, float dist2compare) const; @@ -469,10 +468,6 @@ class MANGOS_DLL_SPEC WorldObject : public Object void SendObjectDeSpawnAnim(uint64 guid); virtual void SaveRespawnTime() {} - - uint32 GetInstanceId() const { return m_InstanceId; } - void SetInstanceId(uint32 val) { m_InstanceId = val; } - void AddObjectToRemoveList(); // main visibility check function in normal case (ignore grey zone distance check) @@ -481,15 +476,29 @@ class MANGOS_DLL_SPEC WorldObject : public Object // low level function for visibility change code, must be define in all main world object subclasses virtual bool isVisibleForInState(Player const* u, bool inVisibleList) const = 0; - Map * GetMap() const; + void SetMap(Map * map); + Map * GetMap() const { ASSERT(m_currMap); return m_currMap; } + //used to check all object's GetMap() calls when object is not in world! + void ResetMap() { m_currMap = NULL; } + + //this function should be removed in nearest time... Map const* GetBaseMap() const; + Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime); protected: explicit WorldObject(); std::string m_name; + //these functions are used mostly for Relocate() and Corpse/Player specific stuff... + //use them ONLY in LoadFromDB()/Create() funcs and nowhere else! + //mapId/instanceId should be set in SetMap() function! + void SetLocationMapId(uint32 _mapId) { m_mapId = _mapId; } + void SetLocationInstanceId(uint32 _instanceId) { m_InstanceId = _instanceId; } + private: + Map * m_currMap; //current object's Map location + uint32 m_mapId; // object at map with map_id uint32 m_InstanceId; // in map copy with instance id uint32 m_phaseMask; // in area phase state diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index 43eb02a8a..17e35f973 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -363,8 +363,6 @@ ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool insignia) // bones->m_inWorld = m_inWorld; // don't overwrite world state // bones->m_type = m_type; // don't overwrite type bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation()); - bones->SetMapId(corpse->GetMapId()); - bones->SetInstanceId(corpse->GetInstanceId()); bones->SetPhaseMask(corpse->GetPhaseMask(), false); bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES); diff --git a/src/game/ObjectGridLoader.cpp b/src/game/ObjectGridLoader.cpp index 77695e758..896c0726d 100644 --- a/src/game/ObjectGridLoader.cpp +++ b/src/game/ObjectGridLoader.cpp @@ -123,6 +123,7 @@ void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager & obj->GetGridRef().link(&m, obj); addUnitState(obj,cell); + obj->SetMap(map); obj->AddToWorld(); if(obj->isActiveObject()) map->AddToActive(obj); @@ -151,6 +152,7 @@ void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType obj->GetGridRef().link(&m, obj); addUnitState(obj,cell); + obj->SetMap(map); obj->AddToWorld(); if(obj->isActiveObject()) map->AddToActive(obj); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 3c85796c3..d0a14fbff 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -800,67 +800,59 @@ void ObjectMgr::ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* endAura.effect_idx = 0; } +void ObjectMgr::LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment) +{ + creatureaddons.Load(); + + sLog.outString(">> Loaded %u %s", creatureaddons.RecordCount, comment); + sLog.outString(); + + // check data correctness and convert 'auras' + for(uint32 i = 1; i < creatureaddons.MaxEntry; ++i) + { + CreatureDataAddon const* addon = creatureaddons.LookupEntry(i); + if(!addon) + continue; + + if (addon->mount) + { + if (!sCreatureDisplayInfoStore.LookupEntry(addon->mount)) + { + sLog.outErrorDb("Creature (%s %u) have invalid displayInfoId for mount (%u) defined in `%s`.", entryName, addon->guidOrEntry, addon->mount, creatureaddons.GetTableName()); + const_cast(addon)->mount = 0; + } + } + + if (!sEmotesStore.LookupEntry(addon->emote)) + sLog.outErrorDb("Creature (%s %u) have invalid emote (%u) defined in `%s`.", entryName, addon->guidOrEntry, addon->emote, creatureaddons.GetTableName()); + + if (addon->move_flags & (MONSTER_MOVE_UNK1|MONSTER_MOVE_UNK4)) + { + sLog.outErrorDb("Creature (%s %u) movement flags mask defined in `%s` include forbidden flags (" I32FMT ") that can crash client, cleanup at load.", entryName, addon->guidOrEntry, creatureaddons.GetTableName(), (MONSTER_MOVE_UNK1|MONSTER_MOVE_UNK4)); + const_cast(addon)->move_flags &= ~(MONSTER_MOVE_UNK1|MONSTER_MOVE_UNK4); + } + + ConvertCreatureAddonAuras(const_cast(addon), creatureaddons.GetTableName(), entryName); + } +} + void ObjectMgr::LoadCreatureAddons() { - sCreatureInfoAddonStorage.Load(); + LoadCreatureAddons(sCreatureInfoAddonStorage,"Entry","creature template addons"); - sLog.outString( ">> Loaded %u creature template addons", sCreatureInfoAddonStorage.RecordCount ); - sLog.outString(); - - // check data correctness and convert 'auras' + // check entry ids for(uint32 i = 1; i < sCreatureInfoAddonStorage.MaxEntry; ++i) - { - CreatureDataAddon const* addon = sCreatureInfoAddonStorage.LookupEntry(i); - if(!addon) - continue; + if(CreatureDataAddon const* addon = sCreatureInfoAddonStorage.LookupEntry(i)) + if(!sCreatureStorage.LookupEntry(addon->guidOrEntry)) + sLog.outErrorDb("Creature (Entry: %u) does not exist but has a record in `%s`",addon->guidOrEntry, sCreatureInfoAddonStorage.GetTableName()); - if (addon->mount) - { - if (!sCreatureDisplayInfoStore.LookupEntry(addon->mount)) - { - sLog.outErrorDb("Creature (Entry %u) have invalid displayInfoId for mount (%u) defined in `creature_template_addon`.",addon->guidOrEntry, addon->mount); - const_cast(addon)->mount = 0; - } - } + LoadCreatureAddons(sCreatureDataAddonStorage,"GUID","creature addons"); - if (!sEmotesStore.LookupEntry(addon->emote)) - sLog.outErrorDb("Creature (Entry %u) have invalid emote (%u) defined in `creature_template_addon`.",addon->guidOrEntry, addon->emote); - - ConvertCreatureAddonAuras(const_cast(addon), "creature_template_addon", "Entry"); - - if(!sCreatureStorage.LookupEntry(addon->guidOrEntry)) - sLog.outErrorDb("Creature (Entry: %u) does not exist but has a record in `creature_template_addon`",addon->guidOrEntry); - } - - sCreatureDataAddonStorage.Load(); - - sLog.outString( ">> Loaded %u creature addons", sCreatureDataAddonStorage.RecordCount ); - sLog.outString(); - - // check data correctness and convert 'auras' + // check entry ids for(uint32 i = 1; i < sCreatureDataAddonStorage.MaxEntry; ++i) - { - CreatureDataAddon const* addon = sCreatureDataAddonStorage.LookupEntry(i); - if(!addon) - continue; - - if (addon->mount) - { - if (!sCreatureDisplayInfoStore.LookupEntry(addon->mount)) - { - sLog.outErrorDb("Creature (GUID %u) have invalid displayInfoId for mount (%u) defined in `creature_addon`.",addon->guidOrEntry, addon->mount); - const_cast(addon)->mount = 0; - } - } - - if (!sEmotesStore.LookupEntry(addon->emote)) - sLog.outErrorDb("Creature (GUID %u) have invalid emote (%u) defined in `creature_addon`.",addon->guidOrEntry, addon->emote); - - ConvertCreatureAddonAuras(const_cast(addon), "creature_addon", "GUIDLow"); - - if(mCreatureDataMap.find(addon->guidOrEntry)==mCreatureDataMap.end()) - sLog.outErrorDb("Creature (GUID: %u) does not exist but has a record in `creature_addon`",addon->guidOrEntry); - } + if(CreatureDataAddon const* addon = sCreatureDataAddonStorage.LookupEntry(i)) + if(mCreatureDataMap.find(addon->guidOrEntry)==mCreatureDataMap.end()) + sLog.outErrorDb("Creature (GUID: %u) does not exist but has a record in `creature_addon`",addon->guidOrEntry); } EquipmentInfo const* ObjectMgr::GetEquipmentInfo(uint32 entry) @@ -1238,6 +1230,12 @@ void ObjectMgr::LoadGameobjects() data.rotation2 = fields[ 9].GetFloat(); data.rotation3 = fields[10].GetFloat(); data.spawntimesecs = fields[11].GetInt32(); + + if (data.spawntimesecs==0 && gInfo->IsDespawnAtAction()) + { + sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with `spawntimesecs` (0) value, but gameobejct marked as despawnable at action.",guid,data.id); + } + data.animprogress = fields[12].GetUInt32(); uint32 go_state = fields[13].GetUInt32(); @@ -5725,6 +5723,16 @@ inline void CheckGONoDamageImmuneId(GameObjectInfo const* goInfo,uint32 dataN,ui goInfo->id,goInfo->type,N,dataN); } +inline void CheckGOConsumable(GameObjectInfo const* goInfo,uint32 dataN,uint32 N) +{ + // 0/1 correct values + if (dataN <= 1) + return; + + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but expected boolean (0/1) consumable field value.", + goInfo->id,goInfo->type,N,dataN); +} + void ObjectMgr::LoadGameobjectInfo() { SQLGameObjectLoader loader; @@ -5767,6 +5775,8 @@ void ObjectMgr::LoadGameobjectInfo() if (goInfo->chest.lockId) CheckGOLockId(goInfo,goInfo->chest.lockId,0); + CheckGOConsumable(goInfo,goInfo->chest.consumable,3); + if (goInfo->chest.linkedTrapId) // linked trap CheckGOLinkedTrapId(goInfo,goInfo->chest.linkedTrapId,7); break; @@ -5802,6 +5812,8 @@ void ObjectMgr::LoadGameobjectInfo() if (goInfo->goober.lockId) CheckGOLockId(goInfo,goInfo->goober.lockId,0); + CheckGOConsumable(goInfo,goInfo->goober.consumable,3); + if (goInfo->goober.pageId) // pageId { if (!sPageTextStore.LookupEntry(goInfo->goober.pageId)) @@ -6765,7 +6777,7 @@ void ObjectMgr::LoadGameObjectForQuests() // scan GO chest with loot including quest items case GAMEOBJECT_TYPE_CHEST: { - uint32 loot_id = GameObject::GetLootId(goInfo); + uint32 loot_id = goInfo->GetLootId(); // find quest loot for GO if(LootTemplates_Gameobject.HaveQuestLootFor(loot_id)) diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 0887f457f..b8995b89c 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -844,6 +844,7 @@ class ObjectMgr private: void LoadScripts(ScriptMapMap& scripts, char const* tablename); void CheckScripts(ScriptMapMap const& scripts,std::set& ids); + void LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment); void ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr); void LoadQuestRelationsHelper(QuestRelations& map,char const* table); diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 32964c818..6f6958d37 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -744,9 +744,6 @@ bool Pet::CreateBaseAtCreature(Creature* creature) } uint32 guid=objmgr.GenerateLowGuid(HIGHGUID_PET); - sLog.outBasic("SetInstanceID()"); - SetInstanceId(creature->GetInstanceId()); - sLog.outBasic("Create pet"); uint32 pet_number = objmgr.GeneratePetNumber(); if(!Create(guid, creature->GetMap(), creature->GetPhaseMask(), creature->GetEntry(), pet_number)) @@ -1841,8 +1838,7 @@ bool Pet::IsPermanentPetFor(Player* owner) bool Pet::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number) { - SetMapId(map->GetId()); - SetInstanceId(map->GetInstanceId()); + SetMap(map); SetPhaseMask(phaseMask,false); Object::_Create(guidlow, pet_number, HIGHGUID_PET); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index d5059f863..f2dec42ea 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -541,7 +541,7 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 for (int i = 0; i < PLAYER_SLOTS_COUNT; ++i) m_items[i] = NULL; - SetMapId(info->mapId); + SetLocationMapId(info->mapId); Relocate(info->positionX,info->positionY,info->positionZ); ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(class_); @@ -551,6 +551,8 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 return false; } + SetMap(MapManager::Instance().CreateMap(info->mapId, this)); + uint8 powertype = cEntry->powerType; SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); @@ -1496,7 +1498,12 @@ bool Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) uint32 enchants = GetUInt32ValueFromArray(data, visualbase + 1); for(uint8 enchantSlot = PERM_ENCHANTMENT_SLOT; enchantSlot <= TEMP_ENCHANTMENT_SLOT; ++enchantSlot) { - if(enchant = sSpellItemEnchantmentStore.LookupEntry(enchants >> enchantSlot*16)) + // values stored in 2 uint16 + uint32 enchantId = 0x0000FFFF & (enchants >> enchantSlot*16); + if(!enchantId) + continue; + + if(enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId)) break; } @@ -1639,7 +1646,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati m_teleport_dest = WorldLocation(mapid, x, y, z, orientation); SetFallInformation(0, z); - // code for finish transfer called in WorldSession::HandleMovementOpcodes() + // code for finish transfer called in WorldSession::HandleMovementOpcodes() // at client packet MSG_MOVE_TELEPORT_ACK SetSemaphoreTeleportNear(true); // near teleport, triggering send MSG_MOVE_TELEPORT_ACK from client at landing @@ -5566,7 +5573,7 @@ ActionButton* Player::addActionButton(uint8 button, uint32 action, uint8 type) } - // it create new button (NEW state) if need or return existed + // it create new button (NEW state) if need or return existed ActionButton& ab = m_actionButtons[button]; // set data and update to CHANGED if not NEW @@ -7334,7 +7341,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) if (go->getLootState() == GO_READY) { - uint32 lootid = go->GetLootId(); + uint32 lootid = go->GetGOInfo()->GetLootId(); if (lootid) { @@ -12027,7 +12034,11 @@ void Player::PrepareQuestMenu( uint64 guid ) } else { - GameObject *pGameObject = GetMap()->GetGameObject(guid); + //we should obtain map pointer from GetMap() in 99% of cases. Special case + //only for quests which cast teleport spells on player + Map * _map = IsInWorld() ? GetMap() : MapManager::Instance().FindMap(GetMapId(), GetInstanceId()); + ASSERT(_map); + GameObject *pGameObject = _map->GetGameObject(guid); if( pGameObject ) { pObject = (Object*)pGameObject; @@ -12536,12 +12547,12 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver if (pQuest->GetRewChoiceItemsCount() > 0) { - if (pQuest->RewChoiceItemId[reward]) + if (uint32 itemId = pQuest->RewChoiceItemId[reward]) { ItemPosCountVec dest; - if (CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewChoiceItemId[reward], pQuest->RewChoiceItemCount[reward] ) == EQUIP_ERR_OK) + if (CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, itemId, pQuest->RewChoiceItemCount[reward] ) == EQUIP_ERR_OK) { - Item* item = StoreNewItem( dest, pQuest->RewChoiceItemId[reward], true); + Item* item = StoreNewItem( dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId)); SendNewItem(item, pQuest->RewChoiceItemCount[reward], true, false); } } @@ -12551,12 +12562,12 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver { for (uint32 i=0; i < pQuest->GetRewItemsCount(); ++i) { - if (pQuest->RewItemId[i]) + if (uint32 itemId = pQuest->RewItemId[i]) { ItemPosCountVec dest; - if (CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pQuest->RewItemId[i], pQuest->RewItemCount[i] ) == EQUIP_ERR_OK) + if (CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, itemId, pQuest->RewItemCount[i] ) == EQUIP_ERR_OK) { - Item* item = StoreNewItem( dest, pQuest->RewItemId[i], true); + Item* item = StoreNewItem( dest, itemId, true, Item::GenerateItemRandomPropertyId(itemId)); SendNewItem(item, pQuest->RewItemCount[i], true, false); } } @@ -13825,7 +13836,8 @@ bool Player::MinimalLoadFromDB( QueryResult *result, uint32 guid ) m_name = fields[2].GetCppString(); Relocate(fields[3].GetFloat(),fields[4].GetFloat(),fields[5].GetFloat()); - SetMapId(fields[6].GetUInt32()); + SetLocationMapId(fields[6].GetUInt32()); + // the instance id is not needed at character enum m_Played_time[0] = fields[7].GetUInt32(); @@ -14106,7 +14118,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) // init saved position, and fix it later if problematic uint32 transGUID = fields[31].GetUInt32(); Relocate(fields[13].GetFloat(),fields[14].GetFloat(),fields[15].GetFloat(),fields[17].GetFloat()); - SetMapId(fields[16].GetUInt32()); + SetLocationMapId(fields[16].GetUInt32()); SetDungeonDifficulty(fields[39].GetUInt32()); // may be changed in _LoadGroup _LoadGroup(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGROUP)); @@ -14181,7 +14193,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) else { const WorldLocation& _loc = GetBattleGroundEntryPoint(); - SetMapId(_loc.mapid); + SetLocationMapId(_loc.mapid); Relocate(_loc.coord_x, _loc.coord_y, _loc.coord_z, _loc.orientation); //RemoveArenaAuras(true); } @@ -14194,7 +14206,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) if(!mapEntry || mapEntry->IsBattleGroundOrArena()) { // return to BG master - SetMapId(fields[43].GetUInt32()); + SetLocationMapId(fields[43].GetUInt32()); Relocate(fields[44].GetFloat(),fields[45].GetFloat(),fields[46].GetFloat(),fields[47].GetFloat()); // check entry point and fix to homebind if need @@ -14248,7 +14260,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) m_transport = *iter; m_transport->AddPassenger(this); - SetMapId(m_transport->GetMapId()); + SetLocationMapId(m_transport->GetMapId()); break; } } @@ -14281,11 +14293,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) // NOW player must have valid map // load the player's map here if it's not already loaded - Map *map = GetMap(); - - // since the player may not be bound to the map yet, make sure subsequent - // getmap calls won't create new maps - SetInstanceId(map->GetInstanceId()); + SetMap(MapManager::Instance().CreateMap(GetMapId(), this)); // if the player is in an instance and it has been reset in the meantime teleport him to the entrance if(GetInstanceId() && !sInstanceSaveManager.GetInstanceSave(GetInstanceId())) @@ -14463,15 +14471,19 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) { sLog.outError("Character %u have wrong data in taxi destination list, teleport to homebind.",GetGUIDLow()); RelocateToHomebind(); - SaveRecallPosition(); // save as recall also to prevent recall and fall from sky } else // have start node, to it { sLog.outError("Character %u have too short taxi destination list, teleport to original node.",GetGUIDLow()); - SetMapId(nodeEntry->map_id); + SetLocationMapId(nodeEntry->map_id); Relocate(nodeEntry->x, nodeEntry->y, nodeEntry->z,0.0f); - SaveRecallPosition(); // save as recall also to prevent recall and fall from sky } + + //we can be relocated from taxi and still have an outdated Map pointer! + //so we need to get a new Map pointer! + SetMap(MapManager::Instance().CreateMap(GetMapId(), this)); + SaveRecallPosition(); // save as recall also to prevent recall and fall from sky + m_taxi.ClearTaxiDestinations(); } else if(uint32 node_id = m_taxi.GetTaxiSource()) @@ -19600,7 +19612,8 @@ uint32 Player::CalculateTalentsPoints() const if(getClass() != CLASS_DEATH_KNIGHT) return uint32(base_talent * sWorld.getRate(RATE_TALENT)); - uint32 talentPointsForLevel = getLevel() < 56 ? 0 : getLevel() - 55 + m_questRewardTalentCount; + uint32 talentPointsForLevel = getLevel() < 56 ? 0 : getLevel() - 55; + talentPointsForLevel += m_questRewardTalentCount; if(talentPointsForLevel > base_talent) talentPointsForLevel = base_talent; diff --git a/src/game/Player.h b/src/game/Player.h index b3ec48982..8f151bf4e 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2091,7 +2091,7 @@ class MANGOS_DLL_SPEC Player : public Unit float m_homebindX; float m_homebindY; float m_homebindZ; - void RelocateToHomebind() { SetMapId(m_homebindMapId); Relocate(m_homebindX,m_homebindY,m_homebindZ); } + void RelocateToHomebind() { SetLocationMapId(m_homebindMapId); Relocate(m_homebindX,m_homebindY,m_homebindZ); } // currently visible objects at player client typedef std::set ClientGUIDs; diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 4cd2aaf68..17e1f6e55 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1431,10 +1431,8 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) case TARGET_AREAEFFECT_CUSTOM: case TARGET_AREAEFFECT_CUSTOM_2: case TARGET_SUMMON: - { TagUnitMap.push_back(m_caster); break; - } case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA: { m_targets.m_targetMask = 0; @@ -1506,7 +1504,8 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) --t; } - }break; + break; + } case TARGET_RANDOM_FRIEND_CHAIN_IN_AREA: { m_targets.m_targetMask = 0; @@ -1573,7 +1572,8 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) next = tempUnitMap.begin(); --t; } - }break; + break; + } case TARGET_PET: { Pet* tmpUnit = m_caster->GetPet(); @@ -1653,12 +1653,11 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) --t; } } - }break; - case TARGET_ALL_ENEMY_IN_AREA: - { - FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); break; } + case TARGET_ALL_ENEMY_IN_AREA: + FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); + break; case TARGET_AREAEFFECT_INSTANT: { SpellTargets targetB = SPELL_TARGETS_AOE_DAMAGE; @@ -1670,6 +1669,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) // exclude caster TagUnitMap.remove(m_caster); + break; } case TARGET_ALL_ENEMY_IN_AREA_INSTANT: { @@ -1681,7 +1681,8 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) // exclude caster (this can be important if this not original caster) TagUnitMap.remove(m_caster); } - }break; + break; + } case TARGET_DUELVSPLAYER_COORDINATES: { if(Unit* currentTarget = m_targets.getUnitTarget()) @@ -1689,7 +1690,8 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) m_targets.setDestination(currentTarget->GetPositionX(), currentTarget->GetPositionY(), currentTarget->GetPositionZ()); TagUnitMap.push_back(currentTarget); } - }break; + break; + } case TARGET_ALL_PARTY_AROUND_CASTER: case TARGET_ALL_PARTY_AROUND_CASTER_2: case TARGET_ALL_PARTY: @@ -1707,16 +1709,14 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) } case TARGET_SINGLE_FRIEND: case TARGET_SINGLE_FRIEND_2: - { if(m_targets.getUnitTarget()) TagUnitMap.push_back(m_targets.getUnitTarget()); - }break; + break; case TARGET_NONCOMBAT_PET: - { if(Unit* target = m_targets.getUnitTarget()) if( target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isPet() && ((Pet*)target)->getPetType() == MINI_PET) TagUnitMap.push_back(target); - }break; + break; case TARGET_CASTER_COORDINATES: { // Check original caster is GO - set its coordinates as dst cast @@ -1727,7 +1727,8 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) caster = m_caster; // Set dest for targets m_targets.setDestination(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ()); - }break; + break; + } case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER: // special target order if (m_spellInfo->Id==64904) // Hymn of Hope @@ -1793,12 +1794,12 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) } } } - }break; + break; + } case TARGET_GAMEOBJECT: - { if(m_targets.getGOTarget()) AddGOTarget(m_targets.getGOTarget(), i); - }break; + break; case TARGET_IN_FRONT_OF_CASTER: { bool inFront = m_spellInfo->SpellVisual[0] != 3879; @@ -1823,33 +1824,27 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) } } } - }break; + break; + } case TARGET_GAMEOBJECT_ITEM: - { if(m_targets.getGOTargetGUID()) AddGOTarget(m_targets.getGOTarget(), i); else if(m_targets.getItemTarget()) AddItemTarget(m_targets.getItemTarget(), i); break; - } case TARGET_MASTER: - { if(Unit* owner = m_caster->GetCharmerOrOwner()) TagUnitMap.push_back(owner); break; - } case TARGET_ALL_ENEMY_IN_AREA_CHANNELED: - { // targets the ground, not the units in the area if (m_spellInfo->Effect[i]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) FillAreaTargets(TagUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_DEST_CENTER, SPELL_TARGETS_AOE_DAMAGE); break; - } case TARGET_MINION: - { if(m_spellInfo->Effect[i] != SPELL_EFFECT_DUEL) TagUnitMap.push_back(m_caster); - }break; + break; case TARGET_SINGLE_ENEMY: { if(Unit* pUnitTarget = m_caster->SelectMagnetTarget(m_targets.getUnitTarget(), m_spellInfo)) @@ -1857,7 +1852,8 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) m_targets.setUnitTarget(pUnitTarget); TagUnitMap.push_back(pUnitTarget); } - }break; + break; + } case TARGET_AREAEFFECT_PARTY: { Unit* owner = m_caster->GetCharmerOrOwner(); @@ -1922,19 +1918,19 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) if( m_caster->IsWithinDistInMap(pet, radius) ) TagUnitMap.push_back(pet); } - - }break; + break; + } case TARGET_SCRIPT: { if(m_targets.getUnitTarget()) TagUnitMap.push_back(m_targets.getUnitTarget()); if(m_targets.getItemTarget()) AddItemTarget(m_targets.getItemTarget(), i); - }break; + break; + } case TARGET_SELF_FISHING: - { TagUnitMap.push_back(m_caster); - }break; + break; case TARGET_CHAIN_HEAL: { Unit* pUnitTarget = m_targets.getUnitTarget(); @@ -1994,7 +1990,8 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) --t; } } - }break; + break; + } case TARGET_CURRENT_ENEMY_COORDINATES: { Unit* currentTarget = m_targets.getUnitTarget(); @@ -2044,7 +2041,8 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) } else sLog.outError( "SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id ); - }break; + break; + } case TARGET_BEHIND_VICTIM: { Unit *pTarget = NULL; @@ -2071,12 +2069,10 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) break; } case TARGET_DYNAMIC_OBJECT_COORDINATES: - { // if parent spell create dynamic object extract area from it if(DynamicObject* dynObj = m_caster->GetDynObject(m_triggeredByAuraSpell ? m_triggeredByAuraSpell->Id : m_spellInfo->Id)) m_targets.setDestination(dynObj->GetPositionX(), dynObj->GetPositionY(), dynObj->GetPositionZ()); break; - } case TARGET_DIRECTLY_FORWARD: { if (!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) @@ -4215,7 +4211,7 @@ SpellCastResult Spell::CheckCast(bool strict) uint32 lockId = 0; if (GameObject* go = m_targets.getGOTarget()) { - lockId = go->GetLockId(); + lockId = go->GetGOInfo()->GetLockId(); if (!lockId) return SPELL_FAILED_BAD_TARGETS; } diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 0c9e16931..74f32c8dd 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -1190,24 +1190,23 @@ void Aura::SendAuraUpdate(bool remove) void Aura::SetStackAmount(uint8 stackAmount) { - if (stackAmount == m_stackAmount) - // Nothing changed - return; - Unit *target = GetTarget(); Unit *caster = GetCaster(); if (!target || !caster) return; - bool refresh = stackAmount > m_stackAmount; - m_stackAmount = stackAmount; - int32 amount = m_stackAmount * caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, target); - // Reapply if amount change - if (amount!=m_modifier.m_amount) + bool refresh = stackAmount >= m_stackAmount; + if (stackAmount != m_stackAmount) { - ApplyModifier(false, true); - m_modifier.m_amount = amount; - ApplyModifier(true, true); + m_stackAmount = stackAmount; + int32 amount = m_stackAmount * caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, target); + // Reapply if amount change + if (amount!=m_modifier.m_amount) + { + ApplyModifier(false, true); + m_modifier.m_amount = amount; + ApplyModifier(true, true); + } } if (refresh) @@ -3802,15 +3801,15 @@ void Aura::HandleAuraModSilence(bool apply, bool Real) void Aura::HandleModThreat(bool apply, bool Real) { // only at real add/remove aura - if(!Real) + if (!Real) return; - if(!m_target->isAlive()) + if (!m_target->isAlive()) return; Unit* caster = GetCaster(); - if(!caster || !caster->isAlive()) + if (!caster || !caster->isAlive()) return; int level_diff = 0; @@ -3828,38 +3827,31 @@ void Aura::HandleModThreat(bool apply, bool Real) multiplier = 1; break; } + if (level_diff > 0) m_modifier.m_amount += multiplier * level_diff; - for(int8 x=0;x < MAX_SPELL_SCHOOL;x++) - { - if(m_modifier.m_miscvalue & int32(1<GetTypeId() == TYPEID_PLAYER) - ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? m_modifier.m_amount : -m_modifier.m_amount, apply); - } - } + if (m_target->GetTypeId() == TYPEID_PLAYER) + for(int8 x=0;x < MAX_SPELL_SCHOOL;x++) + if (m_modifier.m_miscvalue & int32(1<m_threatModifier[x], m_modifier.m_amount, apply); } void Aura::HandleAuraModTotalThreat(bool apply, bool Real) { // only at real add/remove aura - if(!Real) + if (!Real) return; - if(!m_target->isAlive() || m_target->GetTypeId()!= TYPEID_PLAYER) + if (!m_target->isAlive() || m_target->GetTypeId() != TYPEID_PLAYER) return; Unit* caster = GetCaster(); - if(!caster || !caster->isAlive()) + if (!caster || !caster->isAlive()) return; - float threatMod = 0.0f; - if(apply) - threatMod = float(m_modifier.m_amount); - else - threatMod = float(-m_modifier.m_amount); + float threatMod = apply ? float(m_modifier.m_amount) : float(-m_modifier.m_amount); m_target->getHostilRefManager().threatAssist(caster, threatMod); } @@ -3867,18 +3859,18 @@ void Aura::HandleAuraModTotalThreat(bool apply, bool Real) void Aura::HandleModTaunt(bool apply, bool Real) { // only at real add/remove aura - if(!Real) + if (!Real) return; - if(!m_target->isAlive() || !m_target->CanHaveThreatList()) + if (!m_target->isAlive() || !m_target->CanHaveThreatList()) return; Unit* caster = GetCaster(); - if(!caster || !caster->isAlive()) + if (!caster || !caster->isAlive()) return; - if(apply) + if (apply) m_target->TauntApply(caster); else { @@ -4326,10 +4318,10 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) case SPELLFAMILY_DRUID: { // Rake - if (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000001000)) + if (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000000000001000) && m_spellProto->Effect[2]==SPELL_EFFECT_ADD_COMBO_POINTS) { - // $AP*0.06 bonus per tick - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 6 / 100); + // $AP*0.18 bonus per tick + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 18 / 100); return; } // Lacerate diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 5c1703814..e088017f7 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -310,12 +310,6 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) { case SPELLFAMILY_GENERIC: { - //Gore - if (m_spellInfo->SpellIconID == 2269 ) - { - damage+= rand()%2 ? damage : 0; - } - switch(m_spellInfo->Id) // better way to check unknown { // Meteor like spells (divided damage to targets) @@ -436,8 +430,9 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) m_caster->SetPower(POWER_ENERGY,0); } // Rake - else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000001000)) + else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000001000) && m_spellInfo->Effect[2]==SPELL_EFFECT_ADD_COMBO_POINTS) { + // $AP*0.01 bonus damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); } // Swipe @@ -445,18 +440,6 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) { damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f); } - //Mangle Bonus for the initial damage of Lacerate and Rake - if ((m_spellInfo->SpellFamilyFlags==UI64LIT(0x0000000000001000) && m_spellInfo->SpellIconID==494) || - (m_spellInfo->SpellFamilyFlags==UI64LIT(0x0000010000000000) && m_spellInfo->SpellIconID==2246)) - { - Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i) - if(((*i)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000044000000000)) && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID) - { - damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f); - break; - } - } break; } case SPELLFAMILY_ROGUE: @@ -527,8 +510,13 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) } case SPELLFAMILY_HUNTER: { + //Gore + if (m_spellInfo->SpellIconID == 1578) + { + damage+= rand()%2 ? damage : 0; + } // Mongoose Bite - if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x000000002)) && m_spellInfo->SpellVisual[0]==342) + else if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x000000002)) && m_spellInfo->SpellVisual[0]==342) { damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); } @@ -787,7 +775,9 @@ void Spell::EffectDummy(uint32 i) if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER) return; - uint32 spell_id = roll_chance_i(50) ? 17269 : 17270; + uint32 spell_id = roll_chance_i(50) + ? 17269 // Create Resonating Skull + : 17270; // Create Bone Dust m_caster->CastSpell(m_caster, spell_id, true, NULL); return; @@ -846,25 +836,25 @@ void Spell::EffectDummy(uint32 i) if (!m_CastItem) return; m_caster->CastSpell(m_caster, 13166, true, m_CastItem); return; - case 23448: // Ultrasafe Transporter: Gadgetzan - backfires + case 23448: // Transporter Arrival - Ultrasafe Transporter: Gadgetzan - backfires { int32 r = irand(0, 119); - if ( r < 20 ) // 1/6 polymorph + if ( r < 20 ) // Transporter Malfunction - 1/6 polymorph m_caster->CastSpell(m_caster, 23444, true); - else if ( r < 100 ) // 4/6 evil twin + else if ( r < 100 ) // Evil Twin - 4/6 evil twin m_caster->CastSpell(m_caster, 23445, true); - else // 1/6 miss the target + else // Transporter Malfunction - 1/6 miss the target m_caster->CastSpell(m_caster, 36902, true); return; } - case 23453: // Ultrasafe Transporter: Gadgetzan - if ( roll_chance_i(50) ) // success + case 23453: // Gnomish Transporter - Ultrasafe Transporter: Gadgetzan + if ( roll_chance_i(50) ) // Gadgetzan Transporter - success m_caster->CastSpell(m_caster, 23441, true); - else // failure + else // Gadgetzan Transporter Failure - failure m_caster->CastSpell(m_caster, 23446, true); return; case 23645: // Hourglass Sand - m_caster->RemoveAurasDueToSpell(23170); + m_caster->RemoveAurasDueToSpell(23170); // Brood Affliction: Bronze return; case 23725: // Gift of Life (warrior bwl trinket) m_caster->CastSpell(m_caster, 23782, true); @@ -882,43 +872,41 @@ void Spell::EffectDummy(uint32 i) //5 different spells used depending on mounted speed and if mount can fly or not if (flyspeed >= 4.1f) + // Flying Reindeer m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer else if (flyspeed >= 3.8f) + // Flying Reindeer m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer else if (flyspeed >= 1.6f) + // Flying Reindeer m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer else if (speed >= 2.0f) + // Reindeer m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer else + // Reindeer m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer return; } - //case 26074: // Holiday Cheer - // return; -- implemented at client side + case 26074: // Holiday Cheer + // implemented at client side + return; case 28006: // Arcane Cloaking { if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER ) + // Naxxramas Entry Flag Effect DND m_caster->CastSpell(unitTarget, 29294, true); return; } - case 28730: // Arcane Torrent (Mana) - { - Aura * dummy = m_caster->GetDummyAura(28734); - if (dummy) - { - int32 bp = damage * dummy->GetStackAmount(); - m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true); - m_caster->RemoveAurasDueToSpell(28734); - } - return; - } case 29200: // Purify Helboar Meat { if( m_caster->GetTypeId() != TYPEID_PLAYER ) return; - uint32 spell_id = roll_chance_i(50) ? 29277 : 29278; + uint32 spell_id = roll_chance_i(50) + ? 29277 // Summon Purified Helboar Meat + : 29278; // Summon Toxic Helboar Meat m_caster->CastSpell(m_caster,spell_id,true,NULL); return; @@ -929,19 +917,19 @@ void Spell::EffectDummy(uint32 i) return; case 30458: // Nigh Invulnerability if (!m_CastItem) return; - if(roll_chance_i(86)) // success + if(roll_chance_i(86)) // Nigh-Invulnerability - success m_caster->CastSpell(m_caster, 30456, true, m_CastItem); - else // backfire in 14% casts + else // Complete Vulnerability - backfire in 14% casts m_caster->CastSpell(m_caster, 30457, true, m_CastItem); return; case 30507: // Poultryizer if (!m_CastItem) return; - if(roll_chance_i(80)) // success + if(roll_chance_i(80)) // Poultryized! - success m_caster->CastSpell(unitTarget, 30501, true, m_CastItem); - else // backfire 20% + else // Poultryized! - backfire 20% m_caster->CastSpell(unitTarget, 30504, true, m_CastItem); return; - case 33060: // Make a Wish + case 33060: // Make a Wish { if(m_caster->GetTypeId()!=TYPEID_PLAYER) return; @@ -950,23 +938,23 @@ void Spell::EffectDummy(uint32 i) switch(urand(1,5)) { - case 1: spell_id = 33053; break; - case 2: spell_id = 33057; break; - case 3: spell_id = 33059; break; - case 4: spell_id = 33062; break; - case 5: spell_id = 33064; break; + case 1: spell_id = 33053; break; // Mr Pinchy's Blessing + case 2: spell_id = 33057; break; // Summon Mighty Mr. Pinchy + case 3: spell_id = 33059; break; // Summon Furious Mr. Pinchy + case 4: spell_id = 33062; break; // Tiny Magical Crawdad + case 5: spell_id = 33064; break; // Mr. Pinchy's Gift } m_caster->CastSpell(m_caster, spell_id, true, NULL); return; } - case 35745: + case 35745: // Socrethar's Stone { uint32 spell_id; switch(m_caster->GetAreaId()) { - case 3900: spell_id = 35743; break; - case 3742: spell_id = 35744; break; + case 3900: spell_id = 35743; break; // Socrethar Portal + case 3742: spell_id = 35744; break; // Socrethar Portal default: return; } @@ -1076,6 +1064,13 @@ void Spell::EffectDummy(uint32 i) m_caster->CastSpell(m_caster, 45088, true); return; } + case 55004: // Nitro Boosts + if(!m_CastItem) return; + if(roll_chance_i(95)) // Nitro Boosts - success + m_caster->CastSpell(m_caster, 54861, true, m_CastItem); + else // Knocked Up - backfire 5% + m_caster->CastSpell(m_caster, 46014, true, m_CastItem); + return; case 50243: // Teach Language { if(m_caster->GetTypeId() != TYPEID_PLAYER) @@ -1119,7 +1114,7 @@ void Spell::EffectDummy(uint32 i) return; } - case 52308: + case 52308: // Take Sputum Sample { switch(i) { @@ -1142,9 +1137,10 @@ void Spell::EffectDummy(uint32 i) return; m_caster->CastCustomSpell(unitTarget, 52752, &damage, NULL, NULL, true); return; - case 53341: - case 53343: + case 53341: // Rune of Cinderglacier + case 53343: // Rune of Razorice { + // Runeforging Credit m_caster->CastSpell(m_caster, 54586, true); return; } @@ -2983,7 +2979,7 @@ void Spell::EffectOpenLock(uint32 effIndex) return; } } - lockId = gameObjTarget->GetLockId(); + lockId = goInfo->GetLockId(); guid = gameObjTarget->GetGUID(); } else if(itemTarget) @@ -4080,7 +4076,6 @@ void Spell::EffectSummonPet(uint32 i) return; OldSummon->GetMap()->Remove((Creature*)OldSummon,false); - OldSummon->SetMapId(m_caster->GetMapId()); float px, py, pz; m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize()); @@ -4628,7 +4623,7 @@ void Spell::EffectSummonObjectWild(uint32 i) } } - if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry()) + if(uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry()) { GameObject* linkedGO = new GameObject; if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map, @@ -6333,7 +6328,7 @@ void Spell::EffectTransmitted(uint32 effIndex) cMap->Add(pGameObj); - if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry()) + if(uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry()) { GameObject* linkedGO = new GameObject; if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap, diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 1dd4544d6..fa5efea0e 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -551,17 +551,6 @@ bool IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellI return false; } -bool IsAuraAddedBySpell(uint32 auraType, uint32 spellId) -{ - SpellEntry const *spellproto = sSpellStore.LookupEntry(spellId); - if (!spellproto) return false; - - for (int i = 0; i < 3; ++i) - if (spellproto->EffectApplyAuraName[i] == auraType) - return true; - return false; -} - SpellCastResult GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form) { // talents that learn spells can have stance requirements that need ignore @@ -2726,6 +2715,260 @@ void SpellMgr::LoadSkillLineAbilityMap() sLog.outString(">> Loaded %u SkillLineAbility MultiMap Data", count); } +void SpellMgr::CheckUsedSpells(char const* table) +{ + uint32 countSpells = 0; + uint32 countMasks = 0; + + // 0 1 2 3 4 5 6 7 8 9 10 11 + QueryResult *result = WorldDatabase.PQuery("SELECT spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMaskB,SpellIcon,SpellVisual,SpellCategory,EffectType,EffectAura,EffectIdx,Name,Code FROM %s",table); + + if( !result ) + { + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb("`%s` table is empty!",table); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field *fields = result->Fetch(); + + bar.step(); + + uint32 spell = fields[0].GetUInt32(); + int32 family = fields[1].GetInt32(); + uint64 familyMaskA = fields[2].GetUInt64(); + uint32 familyMaskB = fields[3].GetUInt32(); + int32 spellIcon = fields[4].GetInt32(); + int32 spellVisual = fields[5].GetInt32(); + int32 category = fields[6].GetInt32(); + int32 effectType = fields[7].GetInt32(); + int32 auraType = fields[8].GetInt32(); + int32 effectIdx = fields[9].GetInt32(); + std::string name = fields[10].GetCppString(); + std::string code = fields[11].GetCppString(); + + // checks of correctness requirements itself + + if (family < -1 || family > SPELLFAMILY_PET) + { + sLog.outError("Table '%s' for spell %u have wrong SpellFamily value(%u), skipped.",table,spell,family); + continue; + } + + // TODO: spellIcon check need dbc loading + if (spellIcon < -1) + { + sLog.outError("Table '%s' for spell %u have wrong SpellIcon value(%u), skipped.",table,spell,spellIcon); + continue; + } + + // TODO: spellVisual check need dbc loading + if (spellVisual < -1) + { + sLog.outError("Table '%s' for spell %u have wrong SpellVisual value(%u), skipped.",table,spell,spellVisual); + continue; + } + + // TODO: for spellCategory better check need dbc loading + if (category < -1 || category >=0 && sSpellCategoryStore.find(category) == sSpellCategoryStore.end()) + { + sLog.outError("Table '%s' for spell %u have wrong SpellCategory value(%u), skipped.",table,spell,category); + continue; + } + + if (effectType < -1 || effectType >= TOTAL_SPELL_EFFECTS) + { + sLog.outError("Table '%s' for spell %u have wrong SpellEffect type value(%u), skipped.",table,spell,effectType); + continue; + } + + if (auraType < -1 || auraType >= TOTAL_AURAS) + { + sLog.outError("Table '%s' for spell %u have wrong SpellAura type value(%u), skipped.",table,spell,auraType); + continue; + } + + if (effectIdx < -1 || effectIdx >= 3) + { + sLog.outError("Table '%s' for spell %u have wrong EffectIdx value(%u), skipped.",table,spell,effectIdx); + continue; + } + + // now checks of requirements + + if(spell) + { + ++countSpells; + + SpellEntry const* spellEntry = sSpellStore.LookupEntry(spell); + if(!spellEntry) + { + sLog.outError("Spell %u '%s' not exist but used in %s.",spell,name.c_str(),code.c_str()); + continue; + } + + if(family >= 0 && spellEntry->SpellFamilyName != family) + { + sLog.outError("Spell %u '%s' family(%u) <> %u but used in %s.",spell,name.c_str(),spellEntry->SpellFamilyName,family,code.c_str()); + continue; + } + + if(familyMaskA != UI64LIT(0xFFFFFFFFFFFFFFFF) || familyMaskB != 0xFFFFFFFF) + { + if(familyMaskA == UI64LIT(0x0000000000000000) && familyMaskB == 0x00000000) + { + if(spellEntry->SpellFamilyFlags != 0 || spellEntry->SpellFamilyFlags2 != 0) + { + sLog.outError("Spell %u '%s' not fit to (" I64FMT "," I32FMT ") but used in %s.",spell,name.c_str(),familyMaskA,familyMaskB,code.c_str()); + continue; + } + + } + else + { + if((spellEntry->SpellFamilyFlags & familyMaskA)==0 && (spellEntry->SpellFamilyFlags2 & familyMaskB)==0) + { + sLog.outError("Spell %u '%s' not fit to (" I64FMT "," I32FMT ") but used in %s.",spell,name.c_str(),familyMaskA,familyMaskB,code.c_str()); + continue; + } + + } + } + + if(spellIcon >= 0 && spellEntry->SpellIconID != spellIcon) + { + sLog.outError("Spell %u '%s' icon(%u) <> %u but used in %s.",spell,name.c_str(),spellEntry->SpellIconID,spellIcon,code.c_str()); + continue; + } + + if(spellVisual >= 0 && spellEntry->SpellVisual[0] != spellVisual) + { + sLog.outError("Spell %u '%s' visual(%u) <> %u but used in %s.",spell,name.c_str(),spellEntry->SpellVisual[0],spellVisual,code.c_str()); + continue; + } + + if(category >= 0 && spellEntry->Category != category) + { + sLog.outError("Spell %u '%s' category(%u) <> %u but used in %s.",spell,name.c_str(),spellEntry->Category,category,code.c_str()); + continue; + } + + if(effectIdx >= 0) + { + if(effectType >= 0 && spellEntry->Effect[effectIdx] != effectType) + { + sLog.outError("Spell %u '%s' effect%d <> %u but used in %s.",spell,name.c_str(),effectIdx+1,effectType,code.c_str()); + continue; + } + + if(auraType >= 0 && spellEntry->EffectApplyAuraName[effectIdx] != auraType) + { + sLog.outError("Spell %u '%s' aura%d <> %u but used in %s.",spell,name.c_str(),effectIdx+1,auraType,code.c_str()); + continue; + } + + } + else + { + if(effectType >= 0 && !IsSpellHaveEffect(spellEntry,SpellEffects(effectType))) + { + sLog.outError("Spell %u '%s' not have effect %u but used in %s.",spell,name.c_str(),effectType,code.c_str()); + continue; + } + + if(auraType >= 0 && !IsSpellHaveAura(spellEntry,AuraType(auraType))) + { + sLog.outError("Spell %u '%s' not have aura %u but used in %s.",spell,name.c_str(),auraType,code.c_str()); + continue; + } + } + } + else + { + ++countMasks; + + bool found = false; + for(uint32 spellId = 1; spellId < sSpellStore.GetNumRows(); ++spellId) + { + SpellEntry const* spellEntry = sSpellStore.LookupEntry(spellId); + if(!spellEntry) + continue; + + if(family >=0 && spellEntry->SpellFamilyName != family) + continue; + + if(familyMaskA != UI64LIT(0xFFFFFFFFFFFFFFFF) || familyMaskB != 0xFFFFFFFF) + { + if(familyMaskA == UI64LIT(0x0000000000000000) && familyMaskB == 0x00000000) + { + if(spellEntry->SpellFamilyFlags != 0 || spellEntry->SpellFamilyFlags2 != 0) + continue; + } + else + { + if((spellEntry->SpellFamilyFlags & familyMaskA)==0 && (spellEntry->SpellFamilyFlags2 & familyMaskB)==0) + continue; + } + } + + if(spellIcon >= 0 && spellEntry->SpellIconID != spellIcon) + continue; + + if(spellVisual >= 0 && spellEntry->SpellVisual[0] != spellVisual) + continue; + + if(category >= 0 && spellEntry->Category != category) + continue; + + if(effectIdx >= 0) + { + if(effectType >=0 && spellEntry->Effect[effectIdx] != effectType) + continue; + + if(auraType >=0 && spellEntry->EffectApplyAuraName[effectIdx] != auraType) + continue; + } + else + { + if(effectType >=0 && !IsSpellHaveEffect(spellEntry,SpellEffects(effectType))) + continue; + + if(auraType >=0 && !IsSpellHaveAura(spellEntry,AuraType(auraType))) + continue; + } + + found = true; + break; + } + + if(!found) + { + if(effectIdx >= 0) + sLog.outError("Spells '%s' not found for family %i (" I64FMT "," I32FMT ") icon(%i) visual(%i) category(%i) effect%d(%i) aura%d(%i) but used in %s", + name.c_str(),family,familyMaskA,familyMaskB,spellIcon,spellVisual,category,effectIdx+1,effectType,effectIdx+1,auraType,code.c_str()); + else + sLog.outError("Spells '%s' not found for family %i (" I64FMT "," I32FMT ") icon(%i) visual(%i) category(%i) effect(%i) aura(%i) but used in %s", + name.c_str(),family,familyMaskA,familyMaskB,spellIcon,spellVisual,category,effectType,auraType,code.c_str()); + continue; + } + } + + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Checked %u spells and %u spell masks", countSpells, countMasks ); +} + DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto, bool triggered) { // Explicit Diminishing Groups diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index f6b71aeb6..a97515f85 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -128,6 +128,14 @@ inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect) return false; } +inline bool IsSpellHaveAura(SpellEntry const *spellInfo, AuraType aura) +{ + for(int i= 0; i < 3; ++i) + if(AuraType(spellInfo->EffectApplyAuraName[i])==aura) + return true; + return false; +} + bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2); inline bool IsSealSpell(SpellEntry const *spellInfo) @@ -186,8 +194,6 @@ bool IsPositiveTarget(uint32 targetA, uint32 targetB); bool IsSingleTargetSpell(SpellEntry const *spellInfo); bool IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellInfo2); -bool IsAuraAddedBySpell(uint32 auraType, uint32 spellId); - inline bool IsPointEffectTarget( Targets target ) { switch (target ) @@ -894,6 +900,8 @@ class SpellMgr public: static SpellMgr& Instance(); + void CheckUsedSpells(char const* table); + // Loading data at server startup void LoadSpellChains(); void LoadSpellLearnSkills(); diff --git a/src/game/TemporarySummon.cpp b/src/game/TemporarySummon.cpp index 1ba714d63..a93bdd925 100644 --- a/src/game/TemporarySummon.cpp +++ b/src/game/TemporarySummon.cpp @@ -165,13 +165,13 @@ void TemporarySummon::UnSummon() { CombatStop(); - AddObjectToRemoveList(); - Unit* sum = m_summoner ? ObjectAccessor::GetUnit(*this, m_summoner) : NULL; if (sum && sum->GetTypeId() == TYPEID_UNIT && ((Creature*)sum)->AI()) { ((Creature*)sum)->AI()->SummonedCreatureDespawn(this); } + + AddObjectToRemoveList(); } void TemporarySummon::SaveToDB() diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp index 9a1ad7e8f..a058a8fc7 100644 --- a/src/game/ThreatManager.cpp +++ b/src/game/ThreatManager.cpp @@ -32,11 +32,9 @@ // The pHatingUnit is not used yet float ThreatCalcHelper::calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float pThreat, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell) { - if(pThreatSpell) - { - if( Player* modOwner = pHatingUnit->GetSpellModOwner() ) + if (pThreatSpell) + if (Player* modOwner = pHatedUnit->GetSpellModOwner()) modOwner->ApplySpellMod(pThreatSpell->Id, SPELLMOD_THREAT, pThreat); - } float threat = pHatedUnit->ApplyTotalThreatModifier(pThreat, schoolMask); return threat; diff --git a/src/game/Totem.cpp b/src/game/Totem.cpp index d9f422e2e..1bfcc7e22 100644 --- a/src/game/Totem.cpp +++ b/src/game/Totem.cpp @@ -53,7 +53,6 @@ void Totem::Update( uint32 time ) void Totem::Summon(Unit* owner) { - SetInstanceId(owner->GetInstanceId()); owner->GetMap()->Add((Creature*)this); // select totem model in dependent from owner team diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp index a338c7b0b..43e854fd0 100644 --- a/src/game/Transports.cpp +++ b/src/game/Transports.cpp @@ -102,7 +102,8 @@ void MapManager::LoadTransports() m_TransportsByMap[*i].insert(t); //If we someday decide to use the grid to track transports, here: - //MapManager::Instance().LoadGrid(mapid,x,y,true); + t->SetMap(MapManager::Instance().CreateMap(mapid, t)); + //t->GetMap()->Add((GameObject *)t); ++count; } while(result->NextRow()); @@ -138,8 +139,6 @@ Transport::Transport() : GameObject() bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags) { Relocate(x,y,z,ang); - - SetMapId(mapid); // instance id and phaseMask isn't set to values different from std. if(!IsPositionValid()) @@ -432,7 +431,6 @@ Transport::WayPointMap::const_iterator Transport::GetNextWayPoint() void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) { Map const* oldMap = GetMap(); - SetMapId(newMapid); Relocate(x, y, z); for(PlayerSet::iterator itr = m_passengers.begin(); itr != m_passengers.end();) @@ -458,7 +456,11 @@ void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) //plr->GetSession()->SendPacket(&data); } - Map const* newMap = GetMap(); + //we need to create and save new Map object with 'newMapid' because if not done -> lead to invalid Map object reference... + //player far teleport would try to create same instance, but we need it NOW for transport... + //correct me if I'm wrong O.o + Map * newMap = MapManager::Instance().CreateMap(newMapid, this); + SetMap(newMap); if(oldMap != newMap) { diff --git a/src/game/Transports.h b/src/game/Transports.h index 1ade79499..1ae05a753 100644 --- a/src/game/Transports.h +++ b/src/game/Transports.h @@ -54,24 +54,11 @@ class TransportPath std::vector i_nodes; }; -class Transport : protected GameObject +class Transport : public GameObject { public: explicit Transport(); - // prevent using Transports as normal GO, but allow call some inherited functions - using GameObject::IsTransport; - using GameObject::GetEntry; - using GameObject::GetGUID; - using GameObject::GetGUIDLow; - using GameObject::GetMapId; - using GameObject::GetPositionX; - using GameObject::GetPositionY; - using GameObject::GetPositionZ; - using GameObject::BuildCreateUpdateBlockForPlayer; - using GameObject::BuildOutOfRangeUpdateBlock; - using GameObject::GetPackGUID; - bool Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags); bool GenerateWaypoints(uint32 pathid, std::set &mapids); void Update(uint32 p_time); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 06ac3d8fb..9af540c2e 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -431,10 +431,10 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa return 0; } - if (!spellProto || !IsAuraAddedBySpell(SPELL_AURA_MOD_FEAR, spellProto->Id)) + if (!spellProto || !IsSpellHaveAura(spellProto,SPELL_AURA_MOD_FEAR)) pVictim->RemoveSpellbyDamageTaken(SPELL_AURA_MOD_FEAR, damage); // root type spells do not dispel the root effect - if (!spellProto || !(spellProto->Mechanic == MECHANIC_ROOT || IsAuraAddedBySpell(SPELL_AURA_MOD_ROOT, spellProto->Id))) + if (!spellProto || !(spellProto->Mechanic == MECHANIC_ROOT || IsSpellHaveAura(spellProto,SPELL_AURA_MOD_ROOT))) pVictim->RemoveSpellbyDamageTaken(SPELL_AURA_MOD_ROOT, damage); // no xp,health if type 8 /critters/ @@ -5287,7 +5287,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 40446; chance = 25.0f; } - // Mangle (cat/bear) + // Mangle (Bear) and Mangle (Cat) else if (procSpell->SpellFamilyFlags & UI64LIT(0x0000044000000000)) { triggered_spell_id = 40452; @@ -7916,8 +7916,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; // Mod damage from spell mechanic - uint32 mechanicMask = GetAllSpellMechanicMask(spellProto); - if (mechanicMask) + if (uint32 mechanicMask = GetAllSpellMechanicMask(spellProto)) { AuraList const& mDamageDoneMechanic = pVictim->GetAurasByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT); for(AuraList::const_iterator i = mDamageDoneMechanic.begin();i != mDamageDoneMechanic.end(); ++i) @@ -8711,6 +8710,25 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT if((*i)->GetModifier()->m_miscvalue & GetMeleeDamageSchoolMask()) TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + // .. taken pct (special attacks) + if (spellProto) + { + uint32 mechanicMask = GetAllSpellMechanicMask(spellProto); + + // Shred also have bonus as MECHANIC_BLEED damages + if(spellProto->SpellFamilyName==SPELLFAMILY_DRUID && (spellProto->SpellFamilyFlags & UI64LIT(0x00008000))) + mechanicMask |= (1 << MECHANIC_BLEED); + + // Mod damage from spell mechanic + if (mechanicMask) + { + AuraList const& mDamageDoneMechanic = pVictim->GetAurasByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT); + for(AuraList::const_iterator i = mDamageDoneMechanic.begin();i != mDamageDoneMechanic.end(); ++i) + if(mechanicMask & uint32(1<<((*i)->GetModifier()->m_miscvalue))) + TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + } + } + // .. taken pct: dummy auras AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY); for(AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i) @@ -8729,14 +8747,6 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT TakenTotalMod *= (mod+100.0f)/100.0f; } break; - //Mangle - case 2312: - if(spellProto==NULL) - break; - // Should increase Shred (initial Damage of Lacerate and Rake handled in Spell::EffectSchoolDMG) - if(spellProto->SpellFamilyName==SPELLFAMILY_DRUID && (spellProto->SpellFamilyFlags == UI64LIT(0x00008000))) - TakenTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f; - break; } } @@ -9249,7 +9259,7 @@ bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList, //based on wowwiki every 5 mod we have 1 more level diff in calculation visibleDistance += (int32(u->GetTotalAuraModifier(SPELL_AURA_MOD_DETECT)) - stealthMod)/5.0f; - if(!IsWithinDist(u,visibleDistance)) + if(visibleDistance <= 0 || !IsWithinDist(u,visibleDistance)) return false; } diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp index c6c6f9279..5c5fad437 100644 --- a/src/game/Vehicle.cpp +++ b/src/game/Vehicle.cpp @@ -62,8 +62,7 @@ void Vehicle::Update(uint32 diff) bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team) { - SetMapId(map->GetId()); - SetInstanceId(map->GetInstanceId()); + SetMap(map); Object::_Create(guidlow, Entry, HIGHGUID_VEHICLE); diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 2a5d35b2b..798147fe8 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -385,15 +385,9 @@ void WorldSession::LogoutPlayer(bool Save) // the player may not be in the world when logging out // e.g if he got disconnected during a transfer to another map // calls to GetMap in this case may cause crashes - if(_player->IsInWorld()) _player->GetMap()->Remove(_player, false); - // RemoveFromWorld does cleanup that requires the player to be in the accessor - ObjectAccessor::Instance().RemoveObject(_player); - - ///- Delete the player object - _player->CleanupsBeforeDelete(); // do some cleanup before deleting to prevent crash at crossreferences to already deleted data - - delete _player; - _player = NULL; + Map* _map = _player->GetMap(); + _map->Remove(_player, true); + _player = NULL; // deleted in Remove call ///- Send the 'logout complete' packet to the client WorldPacket data( SMSG_LOGOUT_COMPLETE, 0 ); diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp index 3d12375d1..684c2e0b4 100644 --- a/src/game/debugcmds.cpp +++ b/src/game/debugcmds.cpp @@ -30,6 +30,7 @@ #include "BattleGroundMgr.h" #include #include "ObjectMgr.h" +#include "SpellMgr.h" bool ChatHandler::HandleDebugSendSpellFailCommand(const char* args) { @@ -336,7 +337,7 @@ bool ChatHandler::HandleDebugSendQuestPartyMsgCommand(const char* args) return true; } -bool ChatHandler::HandleDebugGetLootRecipient(const char* /*args*/) +bool ChatHandler::HandleDebugGetLootRecipientCommand(const char* /*args*/) { Creature* target = getSelectedCreature(); if (!target) @@ -353,7 +354,7 @@ bool ChatHandler::HandleDebugSendQuestInvalidMsgCommand(const char* args) return true; } -bool ChatHandler::HandleDebugGetItemState(const char* args) +bool ChatHandler::HandleDebugGetItemStateCommand(const char* args) { if (!*args) return false; @@ -649,6 +650,14 @@ bool ChatHandler::HandleDebugSpawnVehicle(const char* args) return true; } +bool ChatHandler::HandleDebugSpellCheckCommand(const char* /*args*/) +{ + sLog.outString( "Check expected in code spell properties base at table 'spell_check' content..."); + spellmgr.CheckUsedSpells("spell_check"); + return true; +} + + bool ChatHandler::HandleDebugSendLargePacketCommand(const char* /*args*/) { const char* stuffingString = "This is a dummy string to push the packet's size beyond 128000 bytes. "; @@ -733,3 +742,186 @@ bool ChatHandler::HandleDebugSetAuraStateCommand(const char* args) unit->ModifyAuraState(AuraState(abs(state)),state > 0); return true; } + +bool ChatHandler::HandleDebugSetValueCommand(const char* args) +{ + if(!*args) + return false; + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* pz = strtok(NULL, " "); + + if (!px || !py) + return false; + + Unit* target = getSelectedUnit(); + if(!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = target->GetGUID(); + + uint32 Opcode = (uint32)atoi(px); + if(Opcode >= target->GetValuesCount()) + { + PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, GUID_LOPART(guid), target->GetValuesCount()); + return false; + } + uint32 iValue; + float fValue; + bool isint32 = true; + if(pz) + isint32 = (bool)atoi(pz); + if(isint32) + { + iValue = (uint32)atoi(py); + sLog.outDebug(GetMangosString(LANG_SET_UINT), GUID_LOPART(guid), Opcode, iValue); + target->SetUInt32Value( Opcode , iValue ); + PSendSysMessage(LANG_SET_UINT_FIELD, GUID_LOPART(guid), Opcode,iValue); + } + else + { + fValue = (float)atof(py); + sLog.outDebug(GetMangosString(LANG_SET_FLOAT), GUID_LOPART(guid), Opcode, fValue); + target->SetFloatValue( Opcode , fValue ); + PSendSysMessage(LANG_SET_FLOAT_FIELD, GUID_LOPART(guid), Opcode,fValue); + } + + return true; +} + +bool ChatHandler::HandleDebugGetValueCommand(const char* args) +{ + if(!*args) + return false; + + char* px = strtok((char*)args, " "); + char* pz = strtok(NULL, " "); + + if (!px) + return false; + + Unit* target = getSelectedUnit(); + if(!target) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = target->GetGUID(); + + uint32 Opcode = (uint32)atoi(px); + if(Opcode >= target->GetValuesCount()) + { + PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, GUID_LOPART(guid), target->GetValuesCount()); + return false; + } + uint32 iValue; + float fValue; + bool isint32 = true; + if(pz) + isint32 = (bool)atoi(pz); + + if(isint32) + { + iValue = target->GetUInt32Value( Opcode ); + sLog.outDebug(GetMangosString(LANG_GET_UINT), GUID_LOPART(guid), Opcode, iValue); + PSendSysMessage(LANG_GET_UINT_FIELD, GUID_LOPART(guid), Opcode, iValue); + } + else + { + fValue = target->GetFloatValue( Opcode ); + sLog.outDebug(GetMangosString(LANG_GET_FLOAT), GUID_LOPART(guid), Opcode, fValue); + PSendSysMessage(LANG_GET_FLOAT_FIELD, GUID_LOPART(guid), Opcode, fValue); + } + + return true; +} + +bool ChatHandler::HandleDebugMod32ValueCommand(const char* args) +{ + if(!*args) + return false; + + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + + if (!px || !py) + return false; + + uint32 Opcode = (uint32)atoi(px); + int Value = atoi(py); + + if(Opcode >= m_session->GetPlayer()->GetValuesCount()) + { + PSendSysMessage(LANG_TOO_BIG_INDEX, Opcode, m_session->GetPlayer()->GetGUIDLow(), m_session->GetPlayer( )->GetValuesCount()); + return false; + } + + sLog.outDebug(GetMangosString(LANG_CHANGE_32BIT), Opcode, Value); + + int CurrentValue = (int)m_session->GetPlayer( )->GetUInt32Value( Opcode ); + + CurrentValue += Value; + m_session->GetPlayer( )->SetUInt32Value( Opcode , (uint32)CurrentValue ); + + PSendSysMessage(LANG_CHANGE_32BIT_FIELD, Opcode,CurrentValue); + + return true; +} + +bool ChatHandler::HandleDebugUpdateCommand(const char* args) +{ + if(!*args) + return false; + + uint32 updateIndex; + uint32 value; + + char* pUpdateIndex = strtok((char*)args, " "); + + Unit* chr = getSelectedUnit(); + if (chr == NULL) + { + SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + SetSentErrorMessage(true); + return false; + } + + if(!pUpdateIndex) + { + return true; + } + updateIndex = atoi(pUpdateIndex); + //check updateIndex + if(chr->GetTypeId() == TYPEID_PLAYER) + { + if (updateIndex>=PLAYER_END) return true; + } + else + { + if (updateIndex>=UNIT_END) return true; + } + + char* pvalue = strtok(NULL, " "); + if (!pvalue) + { + value=chr->GetUInt32Value(updateIndex); + + PSendSysMessage(LANG_UPDATE, chr->GetGUIDLow(),updateIndex,value); + return true; + } + + value=atoi(pvalue); + + PSendSysMessage(LANG_UPDATE_CHANGE, chr->GetGUIDLow(),updateIndex,value); + + chr->SetUInt32Value(updateIndex,value); + + return true; +} diff --git a/src/shared/Common.h b/src/shared/Common.h index 2296b3864..b6b795e16 100644 --- a/src/shared/Common.h +++ b/src/shared/Common.h @@ -125,6 +125,7 @@ #include +#define I32FMT "%08I32X" #define I64FMT "%016I64X" #define snprintf _snprintf #define atoll __atoi64 @@ -136,6 +137,7 @@ #define stricmp strcasecmp #define strnicmp strncasecmp +#define I32FMT "%08X" #define I64FMT "%016llX" #endif diff --git a/src/shared/Database/SQLStorage.h b/src/shared/Database/SQLStorage.h index e6ba01ee0..139d808e2 100644 --- a/src/shared/Database/SQLStorage.h +++ b/src/shared/Database/SQLStorage.h @@ -63,6 +63,8 @@ class SQLStorage uint32 MaxEntry; uint32 iNumFields; + char const* GetTableName() const { return table; } + void Load(); void Free(); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 138a0b067..e203338a2 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 "8159" + #define REVISION_NR "8183" #endif // __REVISION_NR_H__